All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Blender.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2001-2009 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/rp/Blender.cpp
22  \brief Blended pixel value calculation for two overlaped rasters.
23 */
24 
25 #include "Blender.h"
26 
27 #include "Macros.h"
28 #include "../geometry/LinearRing.h"
29 #include "../geometry/MultiPoint.h"
30 #include "../geometry/MultiLineString.h"
31 #include "../geometry/Point.h"
32 #include "../geometry/Envelope.h"
33 #include "../geometry/Enums.h"
34 #include "../raster/Raster.h"
35 #include "../raster/Grid.h"
36 #include "../raster/Band.h"
37 #include "../raster/BandProperty.h"
38 #include "../raster/Utils.h"
39 #include "../raster/SynchronizedRaster.h"
40 #include "../common/PlatformUtils.h"
41 #include "../common/progress/TaskProgress.h"
42 
43 #include <boost/thread.hpp>
44 #include <boost/graph/graph_concepts.hpp>
45 #include <boost/scoped_ptr.hpp>
46 
47 #include <complex>
48 #include <limits>
49 #include <algorithm>
50 #include <memory>
51 
52 // Get the perpendicular distance from a point P(pX,pY) from a line defined
53 // by the points A(lineAX,lineAY) and B(lineBX,lineBY)
54 // Requires two previously declared variables aux1 and aux2
55 #define getPerpendicularDistance( pX, pY, lineAX, lineAY, lineBX, lineBY, aux1, aux2, perpDist ) \
56  aux1 = lineAX - lineBX; \
57  aux2 = lineAY - lineBY; \
58  if( aux1 == 0.0 ) \
59  { \
60  perpDist = std::abs( pX - lineAX ); \
61  } \
62  else if( aux2 == 0.0 ) \
63  { \
64  perpDist = std::abs( pY - lineAY ); \
65  } \
66  else \
67  { \
68  perpDist = \
69  std::abs( \
70  ( aux2 * pX ) - ( aux1 * pY ) + ( lineAX * lineBY ) - ( lineBX * lineAY ) \
71  ) \
72  / \
73  std::sqrt( ( aux1 * aux1 ) + ( aux2 * aux2 ) ); \
74  }
75 
76 namespace te
77 {
78  namespace rp
79  {
81  : m_returnValuePtr( 0 ), m_abortValuePtr( 0 ), m_sync1Ptr( 0 ), m_sync2Ptr( 0 ),
82  m_raster1BlocksInfosPtr( 0 ), m_mutexPtr( 0 ), m_blockProcessedSignalMutexPtr( 0 ),
83  m_blockProcessedSignalPtr( 0 ), m_runningThreadsCounterPtr( 0 ),
84  m_blendMethod( te::rp::Blender::InvalidBlendMethod ),
85  m_interpMethod1( te::rst::Interpolator::NearestNeighbor ),
86  m_interpMethod2( te::rst::Interpolator::NearestNeighbor ),
87  m_noDataValue( 0.0 ), m_forceInputNoDataValue( false ),
88  m_maxRasterCachedBlocks( 0 ), m_useProgress( false )
89  {
90  }
91 
93  const BlendIntoRaster1ThreadParams& rhs )
94  {
95  operator=( rhs );
96  }
97 
99  {
100  }
101 
103  const BlendIntoRaster1ThreadParams& rhs )
104  {
105  m_returnValuePtr = rhs.m_returnValuePtr;
106  m_abortValuePtr = rhs.m_abortValuePtr;
107  m_sync1Ptr = rhs.m_sync1Ptr;
108  m_sync2Ptr = rhs.m_sync2Ptr;
109  m_raster1BlocksInfosPtr = rhs.m_raster1BlocksInfosPtr;
110  m_mutexPtr = rhs.m_mutexPtr;
111  m_blockProcessedSignalMutexPtr = rhs.m_blockProcessedSignalMutexPtr;
112  m_blockProcessedSignalPtr = rhs.m_blockProcessedSignalPtr;
113  m_runningThreadsCounterPtr = rhs.m_runningThreadsCounterPtr;
119  m_noDataValue = rhs.m_noDataValue;
121  m_maxRasterCachedBlocks = rhs.m_maxRasterCachedBlocks;
126  m_useProgress = rhs.m_useProgress;
127 
128  if( rhs.m_r1ValidDataDelimiterPtr.get() )
129  {
131  }
132  else
133  {
135  }
136 
137  if( rhs.m_r2ValidDataDelimiterPtr.get() )
138  {
140  }
141  else
142  {
144  }
145 
146  if( rhs.m_geomTransformationPtr.get() )
147  {
148  m_geomTransformationPtr.reset( rhs.m_geomTransformationPtr->clone() );
149  }
150  else
151  {
152  m_geomTransformationPtr.reset();
153  }
154 
155  return *this;
156  }
157 
158  // ----------------------------------------------------------------------
160  {
161  initState();
162  }
163 
165  {
166  clear();
167  }
168 
170  const std::vector< unsigned int >& raster1Bands,
171  const te::rst::Raster& raster2,
172  const std::vector< unsigned int >& raster2Bands,
173  const BlendMethod& blendMethod,
174  const te::rst::Interpolator::Method& interpMethod1,
175  const te::rst::Interpolator::Method& interpMethod2,
176  const double& noDataValue,
177  const bool forceInputNoDataValue,
178  const std::vector< double >& pixelOffsets1,
179  const std::vector< double >& pixelScales1,
180  const std::vector< double >& pixelOffsets2,
181  const std::vector< double >& pixelScales2,
182  te::gm::MultiPolygon const * const r1ValidDataDelimiterPtr,
183  te::gm::MultiPolygon const * const r2ValidDataDelimiterPtr,
184  const te::gm::GeometricTransformation& geomTransformation,
185  const unsigned int threadsNumber,
186  const bool enableProgressInterface )
187  {
190  "Invalid raster 1" );
193  "Invalid raster 2" );
194  TERP_TRUE_OR_RETURN_FALSE( raster1Bands.size() > 0,
195  "Invalid raster bands vector" );
196  TERP_TRUE_OR_RETURN_FALSE( raster1Bands.size() ==
197  raster2Bands.size(), "Invalid raster bands vector" );
198  TERP_TRUE_OR_RETURN_FALSE( pixelOffsets1.size() ==
199  raster1Bands.size(), "Invalid pixel offsets" );
200  TERP_TRUE_OR_RETURN_FALSE( pixelScales1.size() ==
201  raster1Bands.size(), "Invalid pixel scales" );
202  TERP_TRUE_OR_RETURN_FALSE( pixelOffsets2.size() ==
203  raster2Bands.size(), "Invalid pixel offsets" );
204  TERP_TRUE_OR_RETURN_FALSE( pixelScales2.size() ==
205  raster2Bands.size(), "Invalid pixel scales" );
206  TERP_TRUE_OR_RETURN_FALSE( ( r1ValidDataDelimiterPtr ?
207  ( r1ValidDataDelimiterPtr->getNumGeometries() > 0 ) : true ),
208  "Invalid polygon 1" )
209  TERP_TRUE_OR_RETURN_FALSE( ( r2ValidDataDelimiterPtr ?
210  ( r2ValidDataDelimiterPtr->getNumGeometries() > 0 ) : true ),
211  "Invalid polygon 2" )
212  TERP_TRUE_OR_RETURN_FALSE( geomTransformation.isValid(),
213  "Invalid transformation" );
214 
215  clear();
216 
217  // defining the input rasters
218 
219  m_raster1Ptr = &raster1;
220  m_raster2Ptr = &raster2;
221 
222  // Generating the valid data area points
223 
224  if( r1ValidDataDelimiterPtr )
225  {
226  m_r1ValidDataDelimiterPtr.reset( (te::gm::MultiPolygon*)r1ValidDataDelimiterPtr->clone() );
227  }
228  if( r2ValidDataDelimiterPtr )
229  {
230  m_r2ValidDataDelimiterPtr.reset( (te::gm::MultiPolygon*)r2ValidDataDelimiterPtr->clone() );
231  }
232 
233  // indexed under raster 1 lines/cols
234  std::auto_ptr< te::gm::MultiPolygon > indexedDelimiter1Ptr(
236 
237  if( r1ValidDataDelimiterPtr )
238  {
239  const te::rst::Grid& grid = (*raster1.getGrid());
240 
241  const std::size_t nGeoms = r1ValidDataDelimiterPtr->getNumGeometries();
242 
243  for( std::size_t geomIdx = 0 ; geomIdx < nGeoms ; ++geomIdx )
244  {
245  te::gm::Polygon const* geomPtr = dynamic_cast< te::gm::Polygon* >(
246  r1ValidDataDelimiterPtr->getGeometryN( geomIdx ) );
247  TERP_DEBUG_TRUE_OR_THROW( geomPtr, "Invalid geometry pointer" );
248 
249  const std::size_t nRings = geomPtr->getNumRings();
250 
251  te::gm::Polygon* outPolPtr = new te::gm::Polygon( 0, te::gm::PolygonType, 0, 0 );
252 
253  for( std::size_t ringIdx = 0 ; ringIdx < nRings ; ++ringIdx )
254  {
255  te::gm::LinearRing const* inRingPtr = dynamic_cast< te::gm::LinearRing const* >(
256  geomPtr->getRingN( ringIdx ) );
257  assert( inRingPtr );
258 
259  const std::size_t nPoints = inRingPtr->getNPoints();
260  te::gm::Coord2D const * inCoordsPtr = inRingPtr->getCoordinates();
261  te::gm::Coord2D auxCoord;
262 
263  te::gm::LinearRing* outRingPtr = new te::gm::LinearRing( nPoints,
264  te::gm::LineStringType, 0, 0 );
265 
266  for( std::size_t pIdx = 0 ; pIdx < nPoints ; ++pIdx )
267  {
268  grid.geoToGrid( inCoordsPtr[ pIdx ].x, inCoordsPtr[ pIdx ].y,
269  auxCoord.x, auxCoord.y );
270  outRingPtr->setPoint( pIdx, auxCoord.x, auxCoord.y );
271  }
272 
273  outPolPtr->add( outRingPtr );
274 
275  }
276 
277  indexedDelimiter1Ptr->add( outPolPtr );
278  }
279  }
280  else
281  {
282  te::gm::LinearRing* outRingPtr = new te::gm::LinearRing( 5,
283  te::gm::LineStringType, 0, 0 );
284 
285  outRingPtr->setPoint( 0,
286  -0.5,
287  -0.5 );
288  outRingPtr->setPoint( 1,
289  ((double)raster1.getNumberOfColumns()) - 0.5,
290  -0.5 );
291  outRingPtr->setPoint( 2,
292  ((double)raster1.getNumberOfColumns()) - 0.5,
293  ((double)raster1.getNumberOfRows()) - 0.5 );
294  outRingPtr->setPoint( 3,
295  -0.5,
296  ((double)raster1.getNumberOfRows()) - 0.5 );
297  outRingPtr->setPoint( 4,
298  -0.5,
299  -0.5 );
300 
301  te::gm::Polygon* outPolPtr = new te::gm::Polygon( 0, te::gm::PolygonType, 0, 0 );
302 
303  outPolPtr->add( outRingPtr );
304 
305  indexedDelimiter1Ptr->add( outPolPtr );
306  }
307 
308  // indexed under raster 1 lines/cols
309  std::auto_ptr< te::gm::MultiPolygon > indexedDelimiter2Ptr(
311 
312  if( r2ValidDataDelimiterPtr )
313  {
314  const te::rst::Grid& grid = (*raster2.getGrid());
315 
316  const std::size_t nGeoms = r2ValidDataDelimiterPtr->getNumGeometries();
317 
318  for( std::size_t geomIdx = 0 ; geomIdx < nGeoms ; ++geomIdx )
319  {
320  te::gm::Polygon const* geomPtr = dynamic_cast< te::gm::Polygon* >(
321  r2ValidDataDelimiterPtr->getGeometryN( geomIdx ) );
322  TERP_DEBUG_TRUE_OR_THROW( geomPtr, "Invalid geometry pointer" );
323 
324  const std::size_t nRings = geomPtr->getNumRings();
325 
326  te::gm::Polygon* outPolPtr = new te::gm::Polygon( 0, te::gm::PolygonType, 0, 0 );
327 
328  for( std::size_t ringIdx = 0 ; ringIdx < nRings ; ++ringIdx )
329  {
330  te::gm::LinearRing const* inRingPtr = dynamic_cast< te::gm::LinearRing const* >(
331  geomPtr->getRingN( ringIdx ) );
332  assert( inRingPtr );
333 
334  const std::size_t nPoints = inRingPtr->getNPoints();
335  te::gm::Coord2D const * inCoordsPtr = inRingPtr->getCoordinates();
336  te::gm::Coord2D auxCoord;
337  te::gm::Coord2D auxCoord2;
338 
339  te::gm::LinearRing* outRingPtr = new te::gm::LinearRing( nPoints,
340  te::gm::LineStringType, 0, 0 );
341 
342  for( std::size_t pIdx = 0 ; pIdx < nPoints ; ++pIdx )
343  {
344  grid.geoToGrid( inCoordsPtr[ pIdx ].x, inCoordsPtr[ pIdx ].y,
345  auxCoord.x, auxCoord.y );
346  geomTransformation.inverseMap( auxCoord.x, auxCoord.y, auxCoord2.x, auxCoord2.y );
347  outRingPtr->setPoint( pIdx, auxCoord2.x, auxCoord2.y );
348  }
349 
350  outPolPtr->add( outRingPtr );
351  }
352 
353  indexedDelimiter2Ptr->add( outPolPtr );
354  }
355  }
356  else
357  {
358  te::gm::LinearRing* outRingPtr = new te::gm::LinearRing( 5,
359  te::gm::LineStringType, 0, 0 );
360 
361  te::gm::Coord2D auxCoord;
362 
363  geomTransformation.inverseMap(
364  -0.5,
365  -0.5,
366  auxCoord.x, auxCoord.y );
367  outRingPtr->setPoint( 0, auxCoord.x, auxCoord.y );
368  outRingPtr->setPoint( 4, auxCoord.x, auxCoord.y );
369 
370  geomTransformation.inverseMap(
371  ((double)raster2.getNumberOfColumns()) - 0.5,
372  -0.5,
373  auxCoord.x, auxCoord.y );
374  outRingPtr->setPoint( 1, auxCoord.x, auxCoord.y );
375 
376  geomTransformation.inverseMap(
377  ((double)raster2.getNumberOfColumns()) - 0.5,
378  ((double)raster2.getNumberOfRows()) - 0.5,
379  auxCoord.x, auxCoord.y );
380  outRingPtr->setPoint( 2, auxCoord.x, auxCoord.y );
381 
382  geomTransformation.inverseMap(
383  -0.5,
384  ((double)raster2.getNumberOfRows()) - 0.5,
385  auxCoord.x, auxCoord.y );
386  outRingPtr->setPoint( 3, auxCoord.x, auxCoord.y );
387 
388  te::gm::Polygon* outPolPtr = new te::gm::Polygon( 0, te::gm::PolygonType, 0, 0 );
389 
390  outPolPtr->add( outRingPtr );
391 
392  indexedDelimiter2Ptr->add( outPolPtr );
393  }
394 
395  // Calculating the intersection (raster 1 lines/cols)
396 
397  {
398  std::auto_ptr< te::gm::Geometry > geomIntersectionPtr(
399  indexedDelimiter2Ptr->intersection( indexedDelimiter1Ptr.get() ) );
400 
401  if( geomIntersectionPtr.get() )
402  {
403  if( geomIntersectionPtr->getGeomTypeId() == te::gm::PolygonType )
404  {
405  std::auto_ptr< te::gm::MultiPolygon > multiPolIntersectionPtr(
407  multiPolIntersectionPtr->add( geomIntersectionPtr.release() );
408 
409  m_intersectionPtr.reset( multiPolIntersectionPtr.release() );
410  }
411  else if( geomIntersectionPtr->getGeomTypeId() == te::gm::MultiPolygonType )
412  {
413  m_intersectionPtr.reset( (te::gm::MultiPolygon*)geomIntersectionPtr.release() );
414  }
415  }
416  }
417 
418  // Extracting the intersection segments points
419 
420  if( m_intersectionPtr.get() )
421  {
422  std::size_t ringIdx = 0;
423  std::auto_ptr< te::gm::Geometry > ringIntersectionPtr;
424  std::size_t nPols = indexedDelimiter2Ptr->getNumGeometries();
425 
426  for( std::size_t polIdx = 0 ; polIdx < nPols ; ++polIdx )
427  {
428  te::gm::Polygon const* polPtr = dynamic_cast< te::gm::Polygon* >(
429  indexedDelimiter2Ptr->getGeometryN( polIdx ) );
430  TERP_DEBUG_TRUE_OR_THROW( polPtr, "Invalid geometry pointer" );
431 
432  for( ringIdx = 0 ; ringIdx < polPtr->getNumRings() ;
433  ++ringIdx )
434  {
435  ringIntersectionPtr.reset( indexedDelimiter1Ptr->intersection(
436  polPtr->getRingN( ringIdx ) ) );
437 
438  if( ringIntersectionPtr.get() != 0 )
439  {
440  if( ringIntersectionPtr->getGeomTypeId() == te::gm::MultiLineStringType )
441  {
442  te::gm::MultiLineString const* ringIntersectionNPtr = dynamic_cast< te::gm::MultiLineString const * >(
443  ringIntersectionPtr.get() );
444  assert( ringIntersectionNPtr );
445 
446  std::size_t numGeoms = ringIntersectionNPtr->getNumGeometries();
447 
448  for( std::size_t gIdx = 0 ; gIdx < numGeoms ; ++gIdx )
449  {
450  te::gm::LineString const* segIndexedNPtr = dynamic_cast< te::gm::LineString const * >(
451  ringIntersectionNPtr->getGeometryN( gIdx ) );
452  assert( segIndexedNPtr );
453 
454  std::size_t nPoints = segIndexedNPtr->size();
455  te::gm::Coord2D const* coodsPtr = segIndexedNPtr->getCoordinates();
456 
457  for( std::size_t pIdx = 1 ; pIdx < nPoints ; ++pIdx )
458  {
459  m_r2IntersectionSegmentsPoints.push_back( std::pair< te::gm::Coord2D, te::gm::Coord2D >(
460  coodsPtr[ pIdx - 1 ], coodsPtr[ pIdx ] ) );
461  }
462  }
463  }
464  else if( ringIntersectionPtr->getGeomTypeId() == te::gm::LineStringType )
465  {
466  te::gm::LineString const* segIndexedNPtr = dynamic_cast< te::gm::LineString const * >(
467  ringIntersectionPtr.get() );
468  assert( segIndexedNPtr );
469 
470  std::size_t nPoints = segIndexedNPtr->size();
471  te::gm::Coord2D const* coodsPtr = segIndexedNPtr->getCoordinates();
472 
473  for( std::size_t pIdx = 1 ; pIdx < nPoints ; ++pIdx )
474  {
475  m_r2IntersectionSegmentsPoints.push_back( std::pair< te::gm::Coord2D, te::gm::Coord2D >(
476  coodsPtr[ pIdx - 1 ], coodsPtr[ pIdx ] ) );
477  }
478  }
479  }
480  }
481  }
482 
483  nPols = indexedDelimiter1Ptr->getNumGeometries();
484 
485  for( std::size_t polIdx = 0 ; polIdx < nPols ; ++polIdx )
486  {
487  te::gm::Polygon const* polPtr = dynamic_cast< te::gm::Polygon* >(
488  indexedDelimiter1Ptr->getGeometryN( polIdx ) );
489  TERP_DEBUG_TRUE_OR_THROW( polPtr, "Invalid geometry pointer" );
490 
491  for( ringIdx = 0 ; ringIdx < polPtr->getNumRings() ;
492  ++ringIdx )
493  {
494  ringIntersectionPtr.reset( indexedDelimiter2Ptr->intersection(
495  polPtr->getRingN( ringIdx ) ) );
496 
497  if( ringIntersectionPtr.get() != 0 )
498  {
499  if( ringIntersectionPtr->getGeomTypeId() == te::gm::MultiLineStringType )
500  {
501  te::gm::MultiLineString const* ringIntersectionNPtr = dynamic_cast< te::gm::MultiLineString const * >(
502  ringIntersectionPtr.get() );
503  assert( ringIntersectionNPtr );
504 
505  std::size_t numGeoms = ringIntersectionNPtr->getNumGeometries();
506 
507  for( std::size_t gIdx = 0 ; gIdx < numGeoms ; ++gIdx )
508  {
509  te::gm::LineString const* segIndexedNPtr = dynamic_cast< te::gm::LineString const * >(
510  ringIntersectionNPtr->getGeometryN( gIdx ) );
511  assert( segIndexedNPtr );
512 
513  std::size_t nPoints = segIndexedNPtr->size();
514  te::gm::Coord2D const* coodsPtr = segIndexedNPtr->getCoordinates();
515 
516  for( std::size_t pIdx = 1 ; pIdx < nPoints ; ++pIdx )
517  {
518  m_r1IntersectionSegmentsPoints.push_back( std::pair< te::gm::Coord2D, te::gm::Coord2D >(
519  coodsPtr[ pIdx - 1 ], coodsPtr[ pIdx ] ) );
520  }
521  }
522  }
523  else if( ringIntersectionPtr->getGeomTypeId() == te::gm::LineStringType )
524  {
525  te::gm::LineString const* segIndexedNPtr = dynamic_cast< te::gm::LineString const * >(
526  ringIntersectionPtr.get() );
527  assert( segIndexedNPtr );
528 
529  std::size_t nPoints = segIndexedNPtr->size();
530  te::gm::Coord2D const* coodsPtr = segIndexedNPtr->getCoordinates();
531 
532  for( std::size_t pIdx = 1 ; pIdx < nPoints ; ++pIdx )
533  {
534  m_r1IntersectionSegmentsPoints.push_back( std::pair< te::gm::Coord2D, te::gm::Coord2D >(
535  coodsPtr[ pIdx - 1 ], coodsPtr[ pIdx ] ) );
536  }
537  }
538  }
539  }
540  }
541 
542 /* std::cout << std::endl;
543  for( unsigned int idx = 0 ; idx < m_r1IntersectionSegmentsPoints.size() ; ++idx )
544  {
545  std::cout << std::endl << "m_r1IntersectionSegmentsPoints[" << idx << "]="
546  << m_r1IntersectionSegmentsPoints[ idx ].first.x
547  << " " << m_r1IntersectionSegmentsPoints[ idx ].first.y
548  << " " << m_r1IntersectionSegmentsPoints[ idx ].second.x
549  << " " << m_r1IntersectionSegmentsPoints[ idx ].second.y;
550  }
551  for( unsigned int idx = 0 ; idx < m_r2IntersectionSegmentsPoints.size() ; ++idx )
552  {
553  std::cout << std::endl << "m_r2IntersectionSegmentsPoints[" << idx << "]="
554  << m_r2IntersectionSegmentsPoints[ idx ].first.x
555  << " " << m_r2IntersectionSegmentsPoints[ idx ].first.y
556  << " " << m_r2IntersectionSegmentsPoints[ idx ].second.x
557  << " " << m_r2IntersectionSegmentsPoints[ idx ].second.y;
558  }
559  std::cout << std::endl; */
560 
563  }
564 
565  // defining the blending method
566 
567  switch( blendMethod )
568  {
569  case NoBlendMethod :
570  {
572  break;
573  }
575  {
576  if( ( m_intersectionPtr.get() != 0 ) &&
579  {
581  }
582  else
583  {
585  }
586  break;
587  }
588  default :
589  {
590  TERP_LOG_AND_THROW( "Invalid blend method" );
591  break;
592  }
593  }
594 
595  // Defining the blending function pointers
596 
598 
599  // defining the geometric transformation
600 
601  m_geomTransformationPtr = geomTransformation.clone();
602 
603  // defining the interpolators
604 
605  m_interp1 = new te::rst::Interpolator( &raster1, interpMethod1 );
606  m_interp2 = new te::rst::Interpolator( &raster2, interpMethod2 );
607 
608  m_interpMethod1 = interpMethod1;
609  m_interpMethod2 = interpMethod2;
610 
611  // defining dummy values
612 
613  for( std::vector< unsigned int >::size_type rasterBandsIdx = 0 ;
614  rasterBandsIdx < raster1Bands.size() ; ++rasterBandsIdx )
615  {
616  TERP_TRUE_OR_RETURN_FALSE( raster1Bands[ rasterBandsIdx ] <
617  raster1.getNumberOfBands(), "Invalid band" );
618  TERP_TRUE_OR_RETURN_FALSE( raster2Bands[ rasterBandsIdx ] <
619  raster2.getNumberOfBands(), "Invalid band" );
620 
621  m_forceInputNoDataValue = forceInputNoDataValue;
622  if( forceInputNoDataValue )
623  {
624  m_raster1NoDataValues.push_back( noDataValue );
625  m_raster2NoDataValues.push_back( noDataValue );
626  }
627  else
628  {
629  m_raster1NoDataValues.push_back( raster1.getBand( raster1Bands[
630  rasterBandsIdx ] )->getProperty()->m_noDataValue );
631  m_raster2NoDataValues.push_back( raster2.getBand( raster2Bands[
632  rasterBandsIdx ] )->getProperty()->m_noDataValue );
633  }
634  }
635 
636  m_outputNoDataValue = noDataValue;
637 
638  // defining raster bands
639 
640  m_raster1Bands = raster1Bands;
641  m_raster2Bands = raster2Bands;
642 
643  // defining pixel offsets
644 
645  m_pixelOffsets1 = pixelOffsets1;
646  m_pixelScales1 = pixelScales1;
647 
648  m_pixelOffsets2 = pixelOffsets2;
649  m_pixelScales2 = pixelScales2;
650 
651  // threads
652 
653  if( threadsNumber == 0 )
654  {
656  }
657  else
658  {
659  m_threadsNumber = threadsNumber;
660  }
661 
662  // progress interface
663 
664  m_enableProgressInterface = enableProgressInterface;
665 
666  return true;
667  }
668 
670  {
672  m_forceInputNoDataValue = false;
673  m_threadsNumber = 0;
675  m_blendFuncPtr = 0;
676  m_raster1Ptr = 0;
677  m_raster2Ptr = 0;
684  m_interp1 = 0;
685  m_interp2 = 0;
686  }
687 
689  {
692  m_intersectionPtr.reset();
696  if( m_interp1 ) delete m_interp1;
697  if( m_interp2 ) delete m_interp2;
698  m_raster1Bands.clear();
699  m_raster2Bands.clear();
700  m_pixelOffsets1.clear();
701  m_pixelScales1.clear();
702  m_pixelOffsets2.clear();
703  m_pixelScales2.clear();
704  m_raster1NoDataValues.clear();
705  m_raster2NoDataValues.clear();
706 
707  initState();
708  }
709 
711  {
712  switch( blendMethod )
713  {
714  case NoBlendMethod :
715  {
717  break;
718  }
720  {
722  break;
723  }
724  default :
725  {
726  TERP_LOG_AND_THROW( "Invalid blend method" );
727  break;
728  }
729  }
730  }
731 
732  void Blender::noBlendMethodImp( const double& line, const double& col,
733  double* const values )
734  {
735  // Finding the point over the second raster
736 
739 
740  // Blending values
741 
744  {
748 
749  if( m_noBlendMethodImp_Value == m_raster1NoDataValues[ m_noBlendMethodImp_BandIdx ] )
750  {
753  m_raster2Bands[ m_noBlendMethodImp_BandIdx ] );
755 
756  if( m_noBlendMethodImp_Value == m_raster2NoDataValues[ m_noBlendMethodImp_BandIdx ] )
757  {
759  }
760  else
761  {
765  }
766  }
767  else
768  {
772  }
773  }
774  }
775 
776  void Blender::euclideanDistanceMethodImp( const double& line, const double& col,
777  double* const values )
778  {
779  TERP_DEBUG_TRUE_OR_THROW( m_intersectionPtr.get(), "Invalid intersection pointer" );
780  TERP_DEBUG_TRUE_OR_THROW( m_r1IntersectionSegmentsPointsSize > 1, "Invalid intersection points" );
781  TERP_DEBUG_TRUE_OR_THROW( m_r2IntersectionSegmentsPointsSize > 1, "Invalid intersection points" );
782 
783  // Checking if it is inside the intersection
784 
787 
789  {
790  // Finding distances to both rasters valid area delimiters
791 
792  m_euclideanDistanceMethodImp_dist1 = std::numeric_limits<double>::max();
796  {
797 
799  col,
800  line,
802  m_r1IntersectionSegmentsPoints[ m_euclideanDistanceMethodImp_vecIdx ].first.y,
803  m_r1IntersectionSegmentsPoints[ m_euclideanDistanceMethodImp_vecIdx ].second.x,
804  m_r1IntersectionSegmentsPoints[ m_euclideanDistanceMethodImp_vecIdx ].second.y,
808 
810  {
812  }
813  }
814 
815  m_euclideanDistanceMethodImp_dist2 = std::numeric_limits<double>::max();
819  {
820 
822  col,
823  line,
825  m_r2IntersectionSegmentsPoints[ m_euclideanDistanceMethodImp_vecIdx ].first.y,
826  m_r2IntersectionSegmentsPoints[ m_euclideanDistanceMethodImp_vecIdx ].second.x,
827  m_r2IntersectionSegmentsPoints[ m_euclideanDistanceMethodImp_vecIdx ].second.y,
831 
833  {
835  }
836  }
837 
838  // Finding the point over the second raster
839 
842 
843  // Blending values
844 
847  {
852  m_raster2Bands[ m_euclideanDistanceMethodImp_BandIdx ] );
853 
855  {
857  {
859  }
860  else
861  {
865  m_pixelOffsets2[ m_euclideanDistanceMethodImp_BandIdx ];
866  }
867  }
868  else
869  {
871  {
875  m_pixelOffsets1[ m_euclideanDistanceMethodImp_BandIdx ];
876  }
877  else
878  {
880  {
884  m_pixelOffsets1[ m_euclideanDistanceMethodImp_BandIdx ];
885  }
886  else if( m_euclideanDistanceMethodImp_dist1 == 0.0 )
887  {
891  m_pixelOffsets2[ m_euclideanDistanceMethodImp_BandIdx ];
892  }
893  else
894  {
896  (
897  (
898  (
899  (
901  *
903  )
904  +
905  m_pixelOffsets1[ m_euclideanDistanceMethodImp_BandIdx ]
906  )
907  *
909  )
910  +
911  (
912  (
913  (
915  *
917  )
918  +
919  m_pixelOffsets2[ m_euclideanDistanceMethodImp_BandIdx ]
920  )
921  *
923  )
924  )
925  /
926  (
928  +
930  );
931  }
932  }
933  }
934  }
935  }
936  else
937  {
938  noBlendMethodImp( line, col, values );
939  }
940  }
941 
943  {
945  te::common::WAccess, "Invalid output raster access policy" );
946 
947  // Locating raster2 over the raster1
948 
949  unsigned int firstOutputRasterCol = 0;
950  unsigned int lastOutputRasterRow = 0;
951  unsigned int lastOutputRasterCol = 0;
952  unsigned int firstOutputRasterRow = 0;
953 
954  {
955  const double raster2LastRowIdx =
956  (double)( m_raster2Ptr->getNumberOfRows() - 1 );
957  const double raster2LastColIdx =
958  (double)( m_raster2Ptr->getNumberOfColumns() - 1 );
959  double raster2LLColOverRaster1 = 0;
960  double raster2LLRowOverRaster1 = 0;
961  double raster2LRColOverRaster1 = 0;
962  double raster2LRRowOverRaster1 = 0;
963  double raster2URColOverRaster1 = 0;
964  double raster2URRowOverRaster1 = 0;
965  double raster2ULColOverRaster1 = 0;
966  double raster2ULRowOverRaster1 = 0;
967 
969  0.0,
970  raster2LastRowIdx,
971  raster2LLColOverRaster1,
972  raster2LLRowOverRaster1);
974  raster2LastColIdx,
975  raster2LastRowIdx,
976  raster2LRColOverRaster1,
977  raster2LRRowOverRaster1);
979  raster2LastColIdx,
980  0.0,
981  raster2URColOverRaster1,
982  raster2URRowOverRaster1);
984  0.0,
985  0.0,
986  raster2ULColOverRaster1,
987  raster2ULRowOverRaster1);
988 
989  firstOutputRasterCol = (unsigned int)
990  std::max( 0.0,
991  std::min( (double)( m_raster1Ptr->getNumberOfColumns() - 1 ),
992  std::floor(
993  std::min( raster2LLColOverRaster1,
994  std::min( raster2LRColOverRaster1,
995  std::min( raster2URColOverRaster1,
996  raster2ULColOverRaster1
997  )
998  )
999  )
1000  )
1001  )
1002  );
1003 
1004  lastOutputRasterRow = (unsigned int)
1005  std::max( 0.0,
1006  std::min( (double)( m_raster1Ptr->getNumberOfRows() - 1 ),
1007  std::ceil(
1008  std::max( raster2LLRowOverRaster1,
1009  std::max( raster2LRRowOverRaster1,
1010  std::max( raster2URRowOverRaster1,
1011  raster2ULRowOverRaster1
1012  )
1013  )
1014  )
1015  )
1016  )
1017  );
1018 
1019  lastOutputRasterCol = (unsigned int)
1020  std::max( 0.0,
1021  std::min( (double)( m_raster1Ptr->getNumberOfColumns() - 1 ),
1022  std::ceil(
1023  std::max( raster2LLColOverRaster1,
1024  std::max( raster2LRColOverRaster1,
1025  std::max( raster2URColOverRaster1,
1026  raster2ULColOverRaster1
1027  )
1028  )
1029  )
1030  )
1031  )
1032  );
1033 
1034  firstOutputRasterRow = (unsigned int)
1035  std::max( 0.0,
1036  std::min( (double)( m_raster1Ptr->getNumberOfRows() - 1 ),
1037  std::floor(
1038  std::min( raster2LLRowOverRaster1,
1039  std::min( raster2LRRowOverRaster1,
1040  std::min( raster2URRowOverRaster1,
1041  raster2ULRowOverRaster1
1042  )
1043  )
1044  )
1045  )
1046  )
1047  );
1048 
1049  assert( firstOutputRasterCol >= 0 );
1050  assert( firstOutputRasterCol <=
1051  ( m_raster1Ptr->getNumberOfColumns() - 1 ) );
1052  assert( lastOutputRasterRow >= 0 );
1053  assert( lastOutputRasterRow <=
1054  ( m_raster1Ptr->getNumberOfRows() - 1 ) );
1055  assert( lastOutputRasterCol >= 0 );
1056  assert( lastOutputRasterCol <=
1057  ( m_raster1Ptr->getNumberOfColumns() - 1 ) );
1058  assert( firstOutputRasterRow >= 0 );
1059  assert( firstOutputRasterRow <=
1060  ( m_raster1Ptr->getNumberOfRows() - 1 ) );
1061  }
1062 
1063  // Discovering the raster 1 blocks we need to process
1064 
1065  std::vector< RasterBlockInfo > raster1BlocksInfos;
1066  bool allRaster1BandsWithSameBlocking = true;
1067 
1068  {
1069  const te::rst::Band& firstBand = *( m_raster1Ptr->getBand(
1070  m_raster1Bands[ 0 ] ) );
1071 
1072  for( unsigned int raster1BandsIdx = 0 ; raster1BandsIdx <
1073  m_raster1Bands.size() ; ++raster1BandsIdx )
1074  {
1075  const te::rst::Band& band = *( m_raster1Ptr->getBand(
1076  m_raster1Bands[ raster1BandsIdx ] ) );
1077 
1078  if(
1079  ( band.getProperty()->m_blkh != firstBand.getProperty()->m_blkh )
1080  ||
1081  ( band.getProperty()->m_blkw != firstBand.getProperty()->m_blkw )
1082  ||
1083  ( band.getProperty()->m_nblocksx != firstBand.getProperty()->m_nblocksx )
1084  ||
1085  ( band.getProperty()->m_nblocksy != firstBand.getProperty()->m_nblocksy )
1086  )
1087  {
1088  allRaster1BandsWithSameBlocking = false;
1089  break;
1090  }
1091  }
1092 
1093  unsigned int firstBlockX = firstOutputRasterCol /
1094  firstBand.getProperty()->m_blkw;
1095  unsigned int lastBlockX = lastOutputRasterCol /
1096  firstBand.getProperty()->m_blkw;
1097  unsigned int firstBlockY = firstOutputRasterRow /
1098  firstBand.getProperty()->m_blkh;
1099  unsigned int lastBlockY = lastOutputRasterRow /
1100  firstBand.getProperty()->m_blkh;
1101 
1102  for( unsigned int blkY = firstBlockY ; blkY <= lastBlockY ; ++blkY )
1103  {
1104  for( unsigned int blkX = firstBlockX ; blkX <= lastBlockX ; ++blkX )
1105  {
1106  raster1BlocksInfos.push_back( RasterBlockInfo() );
1107 
1108  RasterBlockInfo& rBInfo = raster1BlocksInfos.back();
1109 
1110  rBInfo.m_wasProcessed = false;
1111  rBInfo.m_blkX = blkX;
1112  rBInfo.m_blkY = blkY;
1113  rBInfo.m_blkTotalPixelsNumber = firstBand.getProperty()->m_blkh *
1114  firstBand.getProperty()->m_blkw;
1115 
1116  rBInfo.m_firstRasterRow2Process = blkY * firstBand.getProperty()->m_blkh;
1117  rBInfo.m_firstRasterRow2Process = std::max( firstOutputRasterRow,
1118  rBInfo.m_firstRasterRow2Process );
1119  rBInfo.m_firstRasterRow2Process = std::min( lastOutputRasterRow,
1120  rBInfo.m_firstRasterRow2Process );
1121 
1122  rBInfo.m_rasterRows2ProcessBound = ( blkY + 1 ) * firstBand.getProperty()->m_blkh;
1123  rBInfo.m_rasterRows2ProcessBound = std::max( firstOutputRasterRow,
1124  rBInfo.m_rasterRows2ProcessBound );
1125  rBInfo.m_rasterRows2ProcessBound = std::min( lastOutputRasterRow,
1126  rBInfo.m_rasterRows2ProcessBound );
1127 
1128  rBInfo.m_firstRasterCol2Process = blkX * firstBand.getProperty()->m_blkw;
1129  rBInfo.m_firstRasterCol2Process = std::max( firstOutputRasterCol,
1130  rBInfo.m_firstRasterCol2Process );
1131  rBInfo.m_firstRasterCol2Process = std::min( lastOutputRasterCol,
1132  rBInfo.m_firstRasterCol2Process );
1133 
1134  rBInfo.m_rasterCols2ProcessBound = ( blkX + 1 ) * firstBand.getProperty()->m_blkw;
1135  rBInfo.m_rasterCols2ProcessBound = std::max( firstOutputRasterCol,
1136  rBInfo.m_rasterCols2ProcessBound );
1137  rBInfo.m_rasterCols2ProcessBound = std::min( lastOutputRasterCol,
1138  rBInfo.m_rasterCols2ProcessBound );
1139  }
1140  }
1141  }
1142 
1143  // blending
1144 
1145  bool returnValue = true;
1146 
1147  {
1148  // Guessing memory resources
1149 
1150  const double totalPhysMem = (double)te::common::GetTotalPhysicalMemory();
1151  const double usedVMem = (double)te::common::GetUsedVirtualMemory();
1152  const double totalVMem = ( (double)te::common::GetTotalVirtualMemory() );
1153  const double maxVMem2Use = 0.75 * MIN( totalPhysMem, ( totalVMem - usedVMem ) );
1154 
1155  // Creating thread exec params
1156 
1157  bool abortValue = false;
1158  boost::mutex mutex;
1161  boost::mutex blockProcessedSignalMutex;
1162  boost::condition_variable blockProcessedSignal;
1163  unsigned int runningThreadsCounter = 0;
1164 
1165  BlendIntoRaster1ThreadParams auxThreadParams;
1166  auxThreadParams.m_returnValuePtr = &returnValue;
1167  auxThreadParams.m_abortValuePtr = &abortValue;
1168  auxThreadParams.m_sync1Ptr = &sync1;
1169  auxThreadParams.m_sync2Ptr = &sync2;
1170  auxThreadParams.m_raster1BlocksInfosPtr = &raster1BlocksInfos;
1171  auxThreadParams.m_mutexPtr = &mutex;
1172  auxThreadParams.m_blockProcessedSignalMutexPtr = &blockProcessedSignalMutex;
1173  auxThreadParams.m_blockProcessedSignalPtr = &blockProcessedSignal;
1174  auxThreadParams.m_runningThreadsCounterPtr = &runningThreadsCounter;
1175  auxThreadParams.m_raster1Bands = m_raster1Bands;
1176  auxThreadParams.m_raster2Bands = m_raster2Bands;
1177  auxThreadParams.m_blendMethod = m_blendMethod;
1178  auxThreadParams.m_interpMethod1 = m_interpMethod1;
1179  auxThreadParams.m_interpMethod2 = m_interpMethod2;
1180  auxThreadParams.m_noDataValue = m_outputNoDataValue;
1182  auxThreadParams.m_pixelOffsets1 = m_pixelOffsets1;
1183  auxThreadParams.m_pixelScales1 = m_pixelScales1;
1184  auxThreadParams.m_pixelOffsets2 = m_pixelOffsets2;
1185  auxThreadParams.m_pixelScales2 = m_pixelScales2;
1186 
1187  std::vector< BlendIntoRaster1ThreadParams > allThreadsParams( m_threadsNumber,
1188  auxThreadParams );
1189 
1190  // creating threads
1191 
1192  if( ( m_threadsNumber == 1 ) || (!allRaster1BandsWithSameBlocking) )
1193  {
1194  runningThreadsCounter = 1;
1195  if( m_r1ValidDataDelimiterPtr.get() )
1196  {
1197  allThreadsParams[ 0 ].m_r1ValidDataDelimiterPtr.reset(
1199  }
1200  if( m_r2ValidDataDelimiterPtr.get() )
1201  {
1202  allThreadsParams[ 0 ].m_r2ValidDataDelimiterPtr.reset(
1204  }
1205  allThreadsParams[ 0 ].m_geomTransformationPtr.reset(
1207  allThreadsParams[ 0 ].m_maxRasterCachedBlocks = ((unsigned int)maxVMem2Use)
1208  / ((unsigned int)m_raster2Ptr->getBand( m_raster1Bands[ 0 ] )->getBlockSize() );
1209  allThreadsParams[ 0 ].m_useProgress = m_enableProgressInterface;
1210 
1211  blendIntoRaster1Thread( &( allThreadsParams[ 0 ] ) );
1212  }
1213  else
1214  {
1215  boost::thread_group threads;
1216  runningThreadsCounter = m_threadsNumber;
1217 
1218  for( unsigned int threadIdx = 0 ; threadIdx < m_threadsNumber ;
1219  ++threadIdx )
1220  {
1221  if( m_r1ValidDataDelimiterPtr.get() )
1222  {
1223  allThreadsParams[ threadIdx ].m_r1ValidDataDelimiterPtr.reset(
1225  }
1226  if( m_r2ValidDataDelimiterPtr.get() )
1227  {
1228  allThreadsParams[ threadIdx ].m_r2ValidDataDelimiterPtr.reset(
1230  }
1231  allThreadsParams[ threadIdx ].m_geomTransformationPtr.reset(
1233 
1234  allThreadsParams[ 0 ].m_maxRasterCachedBlocks =
1235  ((unsigned int)maxVMem2Use)
1236  /
1237  (
1238  ((unsigned int)m_raster2Ptr->getBand( m_raster1Bands[ 0 ] )->getBlockSize() )
1239  *
1240  m_threadsNumber
1241  );
1242 
1243  allThreadsParams[ threadIdx ].m_useProgress = false;
1244 
1245  threads.add_thread( new boost::thread( blendIntoRaster1Thread,
1246  &( allThreadsParams[ threadIdx ] ) ) );
1247  };
1248 
1249  // progress stuff
1250 
1251  std::auto_ptr< te::common::TaskProgress > progressPtr;
1253  {
1254  progressPtr.reset( new te::common::TaskProgress );
1255  progressPtr->setTotalSteps( raster1BlocksInfos.size() );
1256  progressPtr->setMessage( "Blending" );
1257 
1258  while( (!abortValue) && (runningThreadsCounter > 0 ) )
1259  {
1260  if( progressPtr->isActive() )
1261  {
1262  boost::unique_lock<boost::mutex> lock( blockProcessedSignalMutex );
1263  blockProcessedSignal.timed_wait( lock,
1264  boost::posix_time::seconds( 1 ) );
1265 
1266  int processedBlocksNmb = 0;
1267  for( unsigned int raster1BlocksInfosIdx = 0 ; raster1BlocksInfosIdx <
1268  raster1BlocksInfos.size() ; ++raster1BlocksInfosIdx )
1269  {
1270  if( raster1BlocksInfos[ raster1BlocksInfosIdx ].m_wasProcessed )
1271  {
1272  ++processedBlocksNmb;
1273  }
1274  }
1275 
1276  if( processedBlocksNmb != progressPtr->getCurrentStep() )
1277  {
1278  progressPtr->pulse();
1279  }
1280  }
1281  else
1282  {
1283  mutex.lock();
1284  abortValue = true;
1285  mutex.unlock();
1286  }
1287  }
1288  }
1289 
1290  // Joining threads
1291 
1292  threads.join_all();
1293  }
1294  }
1295 
1296  return returnValue;
1297  }
1298 
1300  {
1301  // Instantiating the local rasters instance
1302 
1303  te::rst::SynchronizedRaster raster1( 1, *( paramsPtr->m_sync1Ptr ) );
1305  *( paramsPtr->m_sync2Ptr ) );
1306 
1307  // Guessing the output raster channels ranges
1308 
1309  const std::vector< unsigned int >& raster1Bands =
1310  paramsPtr->m_raster1Bands;
1311  const unsigned int raster1BandsSize = raster1Bands.size();
1312 
1313  std::vector< double > raster1BandsRangeMin( raster1BandsSize, 0 );
1314  std::vector< double > raster1BandsRangeMax( raster1BandsSize, 0 );
1315 
1316  {
1317  for( unsigned int raster1BandsIdx = 0 ; raster1BandsIdx <
1318  raster1BandsSize ; ++raster1BandsIdx )
1319  {
1320  unsigned int bandIdx = raster1Bands[ raster1BandsIdx ];
1321 
1322  te::rst::GetDataTypeRanges( raster1.getBand( bandIdx )->getProperty()->m_type,
1323  raster1BandsRangeMin[ raster1BandsIdx ],
1324  raster1BandsRangeMax[ raster1BandsIdx ]);
1325  }
1326  }
1327 
1328  // instantiating the thread local blender instance
1329 
1330  paramsPtr->m_mutexPtr->lock();
1331  const unsigned int raster1BlocksInfosSize = paramsPtr->m_raster1BlocksInfosPtr->size();
1332  paramsPtr->m_mutexPtr->unlock();
1333 
1334  Blender blender;
1335 
1336  if( ! blender.initialize(
1337  raster1,
1338  paramsPtr->m_raster1Bands,
1339  raster2,
1340  paramsPtr->m_raster2Bands,
1341  paramsPtr->m_blendMethod,
1342  paramsPtr->m_interpMethod1,
1343  paramsPtr->m_interpMethod2,
1344  paramsPtr->m_noDataValue,
1345  paramsPtr->m_forceInputNoDataValue,
1346  paramsPtr->m_pixelOffsets1,
1347  paramsPtr->m_pixelScales1,
1348  paramsPtr->m_pixelOffsets2,
1349  paramsPtr->m_pixelScales2,
1350  paramsPtr->m_r1ValidDataDelimiterPtr.get(),
1351  paramsPtr->m_r2ValidDataDelimiterPtr.get(),
1352  *( paramsPtr->m_geomTransformationPtr ),
1353  1,
1354  false ) )
1355  {
1356  paramsPtr->m_mutexPtr->lock();
1357  *(paramsPtr->m_abortValuePtr) = true;
1358  *(paramsPtr->m_returnValuePtr) = false;
1359  --( *(paramsPtr->m_runningThreadsCounterPtr) );
1360  paramsPtr->m_mutexPtr->unlock();
1361  return;
1362  }
1363 
1364  // progress stuff
1365 
1366  std::auto_ptr< te::common::TaskProgress > progressPtr;
1367 
1368  if( paramsPtr->m_useProgress )
1369  {
1370  progressPtr.reset( new te::common::TaskProgress );
1371  progressPtr->setTotalSteps( raster1BlocksInfosSize );
1372  progressPtr->setMessage( "Blending" );
1373  }
1374 
1375  // loocking for the next raster block to blend
1376 
1377  boost::scoped_array< double > blendedValuesHandler( new double[ raster1BandsSize ] );
1378 
1379  const double noDataValue = paramsPtr->m_noDataValue;
1380 
1381  boost::scoped_array< double > blendedBandsBlockHandler;
1382  unsigned int blendedBandsBlockPixelsNumber = 0;
1383 
1384  for( unsigned int raster1BlocksInfosIdx = 0 ; raster1BlocksInfosIdx <
1385  raster1BlocksInfosSize ; ++raster1BlocksInfosIdx )
1386  {
1387  paramsPtr->m_mutexPtr->lock();
1388 
1389  if( paramsPtr->m_raster1BlocksInfosPtr->operator[]( raster1BlocksInfosIdx ).m_wasProcessed )
1390  {
1391  paramsPtr->m_mutexPtr->unlock();
1392  }
1393  else
1394  {
1395  RasterBlockInfo& rBInfo = paramsPtr->m_raster1BlocksInfosPtr->operator[](
1396  raster1BlocksInfosIdx );
1397  rBInfo.m_wasProcessed = true;
1398  paramsPtr->m_mutexPtr->unlock();
1399 
1400  // Allocating the blended block memory
1401 
1402  if( blendedBandsBlockPixelsNumber < rBInfo.m_blkTotalPixelsNumber )
1403  {
1404  blendedBandsBlockHandler.reset( new double[ rBInfo.m_blkTotalPixelsNumber *
1405  raster1BandsSize ] );
1406  blendedBandsBlockPixelsNumber = rBInfo.m_blkTotalPixelsNumber;
1407  }
1408 
1409  //blending block data
1410 
1411  unsigned int raster1Row = 0;
1412  unsigned int raster1Col = 0;
1413  unsigned int raster1BandsIdx = 0;
1414  double* blendedBandsBlockHandlerPointer = blendedBandsBlockHandler.get();
1415 
1416  for( raster1Row = rBInfo.m_firstRasterRow2Process ; raster1Row < rBInfo.m_rasterRows2ProcessBound ;
1417  ++raster1Row )
1418  {
1419  for( raster1Col = rBInfo.m_firstRasterCol2Process ; raster1Col < rBInfo.m_rasterCols2ProcessBound ;
1420  ++raster1Col )
1421  {
1422  blender.getBlendedValues( (double)raster1Row, (double)raster1Col,
1423  blendedBandsBlockHandlerPointer );
1424 
1425  blendedBandsBlockHandlerPointer = blendedBandsBlockHandlerPointer + raster1BandsSize;
1426  }
1427  }
1428 
1429  blendedBandsBlockHandlerPointer = blendedBandsBlockHandler.get();
1430 
1431  for( raster1BandsIdx = 0 ; raster1BandsIdx < raster1BandsSize ; ++raster1BandsIdx )
1432  {
1433  blendedBandsBlockHandlerPointer = blendedBandsBlockHandler.get() + raster1BandsIdx;
1434 
1435  for( raster1Row = rBInfo.m_firstRasterRow2Process ; raster1Row < rBInfo.m_rasterRows2ProcessBound ;
1436  ++raster1Row )
1437  {
1438  for( raster1Col = rBInfo.m_firstRasterCol2Process ; raster1Col < rBInfo.m_rasterCols2ProcessBound ;
1439  ++raster1Col )
1440  {
1441  double& blendedValue = *( blendedBandsBlockHandlerPointer );
1442 
1443  if( blendedValue != noDataValue )
1444  {
1445  blendedValue = std::max( blendedValue ,
1446  raster1BandsRangeMin[ raster1BandsIdx ] );
1447  blendedValue = std::min( blendedValue ,
1448  raster1BandsRangeMax[ raster1BandsIdx ] );
1449 
1450  raster1.setValue( raster1Col, raster1Row, blendedValue,
1451  raster1Bands[ raster1BandsIdx ] );
1452  }
1453 
1454  blendedBandsBlockHandlerPointer = blendedBandsBlockHandlerPointer + raster1BandsSize;
1455  }
1456  }
1457  }
1458 
1459  // progress stuff
1460 
1461  if( paramsPtr->m_useProgress )
1462  {
1463  if( progressPtr->isActive() )
1464  {
1465  progressPtr->pulse();
1466  }
1467  else
1468  {
1469  paramsPtr->m_mutexPtr->lock();
1470  *(paramsPtr->m_abortValuePtr) = true;
1471  *(paramsPtr->m_returnValuePtr) = false;
1472  --( *(paramsPtr->m_runningThreadsCounterPtr) );
1473  paramsPtr->m_mutexPtr->unlock();
1474  return;
1475  }
1476  }
1477  else
1478  {
1479  // notifying the main thread with the block processed signal
1480 
1481  boost::lock_guard<boost::mutex> blockProcessedSignalLockGuard(
1482  *( paramsPtr->m_blockProcessedSignalMutexPtr) );
1483 
1484  paramsPtr->m_blockProcessedSignalPtr->notify_one();
1485  }
1486  }
1487 
1488  // do we must continue processing ?
1489 
1490  if( *(paramsPtr->m_abortValuePtr) )
1491  {
1492  break;
1493  }
1494  }
1495 
1496  paramsPtr->m_mutexPtr->lock();
1497  --( *(paramsPtr->m_runningThreadsCounterPtr) );
1498  paramsPtr->m_mutexPtr->unlock();
1499  }
1500  } // end namespace rp
1501 } // end namespace te
1502 
double m_euclideanDistanceMethodImp_aux1
Definition: Blender.h:259
te::rst::Interpolator::Method m_interpMethod1
The interpolation method to use when reading raster 1 data.
Definition: Blender.h:223
std::vector< std::pair< te::gm::Coord2D, te::gm::Coord2D > > m_r2IntersectionSegmentsPoints
A sub-set of the intersection polygon wich is part of raster 2 valid data polygon ( raster 1 indexed ...
Definition: Blender.h:220
std::size_t getNumRings() const
It returns the number of rings in this CurvePolygon.
Definition: CurvePolygon.h:153
void initState()
Reset the instance to its initial default state.
Definition: Blender.cpp:669
std::size_t getNumGeometries() const
It returns the number of geometries in this GeometryCollection.
virtual void setValue(unsigned int c, unsigned int r, const double value, std::size_t b=0)
Sets the attribute value in a band of a cell.
Definition: Raster.cpp:233
void add(Curve *ring)
It adds the ring to the curve polygon.
Definition: CurvePolygon.h:267
MultiPolygon is a MultiSurface whose elements are Polygons.
Definition: MultiPolygon.h:50
static void blendIntoRaster1Thread(BlendIntoRaster1ThreadParams *paramsPtr)
Thread entry for the method blendIntoRaster1.
Definition: Blender.cpp:1299
An adapter class to allow concurrent access to raster data by multiple threads.
double y
y-coordinate.
Definition: Coord2D.h:87
std::auto_ptr< te::gm::MultiPolygon > m_intersectionPtr
The Intersection geometry ( raster 1 indexed coods).
Definition: Blender.h:217
unsigned long int m_maxRasterCachedBlocks
The maximum number of raster cache blocks.
Definition: Blender.h:196
TERASTEREXPORT void GetDataTypeRanges(const int &dataType, double &min, double &max)
Return the values range of a given data type.
Definition: Utils.cpp:331
bool * m_abortValuePtr
A pointer to the abort execution value.
Definition: Blender.h:174
std::vector< unsigned int > m_raster2Bands
Input raster 2 band indexes to use.
Definition: Blender.h:229
double m_euclideanDistanceMethodImp_Point2Col
Definition: Blender.h:251
std::vector< RasterBlockInfo > * m_raster1BlocksInfosPtr
blocks to process.
Definition: Blender.h:177
The parameters passed to blendIntoRaster1Thread method.
Definition: Blender.h:169
bool m_forceInputNoDataValue
Use noDataValue as the input rasters no-data value (The original rasters no-data values will be ignor...
Definition: Blender.h:188
bool m_useProgress
If enabled each thread will use its own progress interface, if false only a signal will be emitted on...
Definition: Blender.h:197
boost::condition_variable * m_blockProcessedSignalPtr
Signal used to update the main process progress update.
Definition: Blender.h:180
Coord2D * getCoordinates() const
It returns a pointer to the internal array of coordinates.
Definition: LineString.h:456
double m_euclideanDistanceMethodImp_currDist
Definition: Blender.h:255
double x
x-coordinate.
Definition: Coord2D.h:86
std::vector< double > m_pixelScales1
The values scale to be applied to raster 1 pixel values before the blended value calcule (one element...
Definition: Blender.h:190
Blended pixel value calculation for two overlaped rasters.
Definition: Blender.h:56
std::auto_ptr< te::gm::MultiPolygon > m_r2ValidDataDelimiterPtr
A pointer to a geometry (raster 2 world/projected coords) delimiting the raster region with valid dat...
Definition: Blender.h:194
std::vector< double > m_pixelOffsets1
The values offset to be applied to raster 1 pixel values before the blended value calcule (one elemen...
Definition: Blender.h:189
std::vector< double > m_pixelScales2
The values scale to be applied to raster 2 pixel values before the blended value calcule (one element...
Definition: Blender.h:233
unsigned int getNumberOfColumns() const
Returns the raster number of columns.
Definition: Raster.cpp:213
int m_nblocksx
The number of blocks in x.
Definition: BandProperty.h:145
virtual const Band * getBand(std::size_t i) const =0
Returns the raster i-th band.
te::rst::Raster const * m_raster2Ptr
Input raster 2.
Definition: Blender.h:214
double m_outputNoDataValue
The output raster no-data value.
Definition: Blender.h:225
It interpolates one pixel based on a selected algorithm. Methods currently available are Nearest Neig...
Definition: Interpolator.h:54
int m_nblocksy
The number of blocks in y.
Definition: BandProperty.h:146
Blended pixel value calculation for two overlaped rasters.
boost::mutex * m_mutexPtr
mutex pointer.
Definition: Blender.h:178
std::vector< double > m_raster2NoDataValues
Raster 1 no-data values (on value per band).
Definition: Blender.h:235
This class can be used to inform the progress of a task.
Definition: TaskProgress.h:53
#define MIN(a, b)
Macro that returns min between two values.
te::rst::Interpolator::Method m_interpMethod1
The interpolation method to use when reading raster 1 data.
Definition: Blender.h:185
std::vector< unsigned int > m_raster2Bands
Input raster 2 band indexes to use (this vector has the same size as raster1Bands).
Definition: Blender.h:183
bool * m_returnValuePtr
A pointer to the threadreturn value.
Definition: Blender.h:173
void clear()
Clear all internal allocated resources.
Definition: Blender.cpp:688
unsigned int * m_runningThreadsCounterPtr
a pointer to the running threads counter.
Definition: Blender.h:181
An utility struct for representing 2D coordinates.
Definition: Coord2D.h:40
An access synchronizer to be used in SynchronizedRaster raster instances.
void getValue(const double &c, const double &r, std::complex< double > &v, const std::size_t &b)
Get the interpolated value at specific band.
Definition: Interpolator.h:96
2D Geometric transformation base class.
te::rst::RasterSynchronizer * m_sync2Ptr
Raster 1 syncronizer pointer.
Definition: Blender.h:176
int m_type
The data type of the elements in the band.
Definition: BandProperty.h:133
double m_noDataValue
Value to indicate elements where there is no data, default is std::numeric_limits::max().
Definition: BandProperty.h:136
std::size_t m_r1IntersectionSegmentsPointsSize
Size of m_r1IntersectionSegmentsPoints;.
Definition: Blender.h:219
double m_euclideanDistanceMethodImp_dist2
Definition: Blender.h:257
No blending performed.
Definition: Blender.h:64
std::complex< double > m_noBlendMethodImp_cValue
Definition: Blender.h:244
double m_euclideanDistanceMethodImp_dist1
Definition: Blender.h:256
const te::rst::Band * getBand(std::size_t i) const
Returns the raster i-th band.
Raster block info.
Definition: Blender.h:154
void geoToGrid(const double &x, const double &y, double &col, double &row) const
Get the grid point associated to a spatial location.
Definition: Grid.cpp:307
bool m_enableProgressInterface
Enable progress interface.
Definition: Blender.h:208
bool blendIntoRaster1()
Execute blending of the given input rasters and write the result into raster1.
Definition: Blender.cpp:942
bool m_forceInputNoDataValue
Use noDataValue as the input rasters no-data value (The original rasters no-data values will be ignor...
Definition: Blender.h:209
BlendIntoRaster1ThreadParams & operator=(const BlendIntoRaster1ThreadParams &rhs)
Definition: Blender.cpp:102
void setBlendFunctionPonter(const BlendMethod blendMethod)
Set the value of m_blendFuncPtr following the given blend method.
Definition: Blender.cpp:710
#define TERP_TRUE_OR_RETURN_FALSE(value, message)
Checks if value is true. For false values a warning message will be logged and a return of context wi...
Definition: Macros.h:183
te::common::AccessPolicy getAccessPolicy() const
Returns the raster access policy.
Definition: Raster.cpp:89
A LinearRing is a LineString that is both closed and simple.
Definition: LinearRing.h:53
TECOMMONEXPORT unsigned int GetPhysProcNumber()
Returns the number of physical processors.
double m_euclideanDistanceMethodImp_aux2
Definition: Blender.h:260
std::auto_ptr< te::gm::MultiPolygon > m_r1ValidDataDelimiterPtr
A pointer to a geometry (raster 1 world/projected coords) delimiting the raster region with valid dat...
Definition: Blender.h:215
std::vector< double > m_pixelOffsets1
The values offset to be applied to raster 1 pixel values before the blended value calcule (one elemen...
Definition: Blender.h:230
LineString is a curve with linear interpolation between points.
Definition: LineString.h:62
void setPoint(std::size_t i, const double &x, const double &y)
It sets the value of the specified point.
Definition: LineString.cpp:352
TECOMMONEXPORT unsigned long int GetUsedVirtualMemory()
Returns the amount of used virtual memory (bytes) for the current process (physical + swapped)...
An abstract class for raster data strucutures.
Definition: Raster.h:71
std::size_t m_r2IntersectionSegmentsPointsSize
Size of m_r2IntersectionSegmentsPoints;.
Definition: Blender.h:221
te::rst::Raster * m_raster1Ptr
Input raster 1.
Definition: Blender.h:213
unsigned int getNumberOfRows() const
Returns the raster number of rows.
Definition: Raster.cpp:208
#define TERP_LOG_AND_THROW(message)
Logs a error message and throws.
Definition: Macros.h:138
void euclideanDistanceMethodImp(const double &line1, const double &col1, double *const values)
Implementation for EuclideanDistanceMethod.
Definition: Blender.cpp:776
BandProperty * getProperty()
Returns the band property.
Definition: Band.cpp:370
Invalid blending method.
Definition: Blender.h:63
std::vector< double > m_pixelOffsets2
The values offset to be applied to raster 2 pixel values before the blended value calcule (one elemen...
Definition: Blender.h:232
int m_blkw
Block width (pixels).
Definition: BandProperty.h:143
virtual std::size_t getNumberOfBands() const =0
Returns the number of bands (dimension of cells attribute values) in the raster.
std::vector< double > m_raster1NoDataValues
Definition: Blender.h:234
unsigned int m_rasterCols2ProcessBound
Definition: Blender.h:163
virtual GeometricTransformation * clone() const =0
Creat a clone copy of this instance.
te::rst::RasterSynchronizer * m_sync1Ptr
Raster 1 syncronizer pointer.
Definition: Blender.h:175
virtual void directMap(const GTParameters &params, const double &pt1X, const double &pt1Y, double &pt2X, double &pt2Y) const =0
Direct mapping (from pt1 space into pt2 space).
std::vector< double > m_pixelScales1
The values scale to be applied to raster 1 pixel values before the blended value calcule (one element...
Definition: Blender.h:231
std::size_t getNPoints() const
It returns the number of points (vertexes) in the linestring.
Definition: LineString.h:193
void getBlendedValues(const double &line, const double &col, double *const values)
Blend a pixel value using the current parameters.
Definition: Blender.h:125
A raster band description.
Definition: Band.h:63
double m_noBlendMethodImp_Point2Col
Definition: Blender.h:243
BlendFunctPtr m_blendFuncPtr
The current blend function.
Definition: Blender.h:212
Grid * getGrid()
It returns the raster grid.
Definition: Raster.cpp:94
std::vector< unsigned int > m_raster1Bands
Input raster 1 band indexes to use.
Definition: Blender.h:228
std::size_t m_euclideanDistanceMethodImp_vecIdx
Definition: Blender.h:258
unsigned int m_blkTotalPixelsNumber
Definition: Blender.h:159
Geometry * getGeometryN(std::size_t i) const
It returns the n-th geometry in this GeometryCollection.
std::auto_ptr< te::gm::MultiPolygon > m_r1ValidDataDelimiterPtr
A pointer to a geometry (raster 1 world/projected coords) delimiting the raster region with valid dat...
Definition: Blender.h:193
MultiLineString is a MultiCurve whose elements are LineStrings.
Method
Allowed interpolation methods.
Definition: Interpolator.h:61
unsigned int m_euclideanDistanceMethodImp_BandIdx
Definition: Blender.h:254
te::dt::AbstractData * clone() const
It clones the multi polygon.
Polygon is a subclass of CurvePolygon whose rings are defined by linear rings.
Definition: Polygon.h:50
#define getPerpendicularDistance(pX, pY, lineAX, lineAY, lineBX, lineBY, aux1, aux2, perpDist)
Definition: Blender.cpp:55
void setX(const double &x)
It sets the Point x-coordinate value.
Definition: Point.h:143
double m_noDataValue
The value returned where there is no pixel data bo blend.
Definition: Blender.h:187
unsigned int m_noBlendMethodImp_BandIdx
Definition: Blender.h:246
te::gm::GeometricTransformation * m_geomTransformationPtr
A transformation mapping raster 1 pixels ( te::gm::GTParameters::TiePoint::first ) to raster 2 ( te::...
Definition: Blender.h:222
unsigned int m_rasterRows2ProcessBound
Definition: Blender.h:161
Euclidean distance method.
Definition: Blender.h:65
te::rst::Interpolator::Method m_interpMethod2
The interpolation method to use when reading raster 2 data.
Definition: Blender.h:224
virtual bool isValid(const GTParameters &params) const =0
Verifies if the supplied parameters already has a valid transformation.
double m_noBlendMethodImp_Point2Line
Definition: Blender.h:242
boost::mutex * m_blockProcessedSignalMutexPtr
Mutex used to update the main process progress update.
Definition: Blender.h:179
double m_noBlendMethodImp_Value
Definition: Blender.h:245
BlendMethod m_blendMethod
The blend method to apply.
Definition: Blender.h:184
std::vector< double > m_pixelOffsets2
The values offset to be applied to raster 2 pixel values before the blended value calcule (one elemen...
Definition: Blender.h:191
TECOMMONEXPORT unsigned long int GetTotalPhysicalMemory()
Returns the amount of total physical memory (bytes).
std::auto_ptr< te::gm::MultiPolygon > m_r2ValidDataDelimiterPtr
A pointer to a geometry (raster 2 world/projected coords) delimiting the raster region with valid dat...
Definition: Blender.h:216
unsigned int m_threadsNumber
The number of threads to use (0:automatic , 1:disabled, any other integer dictates the number of thre...
Definition: Blender.h:210
void setY(const double &y)
It sets the Point y-coordinate value.
Definition: Point.h:157
int m_blkh
Block height (pixels).
Definition: BandProperty.h:144
unsigned int m_firstRasterRow2Process
Definition: Blender.h:160
Near neighborhood interpolation method.
Definition: Interpolator.h:63
std::complex< double > m_euclideanDistanceMethodImp_cValue1
Definition: Blender.h:252
double m_euclideanDistanceMethodImp_Point2Line
Definition: Blender.h:250
#define TERP_DEBUG_TRUE_OR_THROW(value, message)
Checks if value is true and throws an exception if not.
Definition: Macros.h:356
A rectified grid is the spatial support for raster data.
Definition: Grid.h:68
BlendMethod m_blendMethod
The blend method to apply.
Definition: Blender.h:211
std::vector< unsigned int > m_raster1Bands
Input raster 1 band indexes to use.
Definition: Blender.h:182
void noBlendMethodImp(const double &line1, const double &col1, double *const values)
Implementation for NoBlendMethod.
Definition: Blender.cpp:732
std::auto_ptr< te::gm::GeometricTransformation > m_geomTransformationPtr
A transformation mapping raster 1 pixels ( te::gm::GTParameters::TiePoint::first ) to raster 2 pixels...
Definition: Blender.h:195
virtual int getBlockSize() const
It returns the number of bytes ocuppied by a data block.
Definition: Band.cpp:572
te::gm::Point m_euclideanDistanceMethodImp_auxPoint
Definition: Blender.h:249
virtual void inverseMap(const GTParameters &params, const double &pt2X, const double &pt2Y, double &pt1X, double &pt1Y) const =0
Inverse mapping (from pt2 space into pt1 space).
te::rst::Interpolator * m_interp2
Raster 2 interpolator instance pointer.
Definition: Blender.h:227
bool initialize(te::rst::Raster &raster1, const std::vector< unsigned int > &raster1Bands, const te::rst::Raster &raster2, const std::vector< unsigned int > &raster2Bands, const BlendMethod &blendMethod, const te::rst::Interpolator::Method &interpMethod1, const te::rst::Interpolator::Method &interpMethod2, const double &noDataValue, const bool forceInputNoDataValue, const std::vector< double > &pixelOffsets1, const std::vector< double > &pixelScales1, const std::vector< double > &pixelOffsets2, const std::vector< double > &pixelScales2, te::gm::MultiPolygon const *const r1ValidDataDelimiterPtr, te::gm::MultiPolygon const *const r2ValidDataDelimiterPtr, const te::gm::GeometricTransformation &geomTransformation, const unsigned int threadsNumber, const bool enableProgressInterface)
Inititate the blender instance.
Definition: Blender.cpp:169
std::complex< double > m_euclideanDistanceMethodImp_cValue2
Definition: Blender.h:253
std::vector< double > m_pixelScales2
The values scale to be applied to raster 2 pixel values before the blended value calcule (one element...
Definition: Blender.h:192
Curve * getRingN(std::size_t i) const
It returns the n-th ring for this curve polygon as a curve.
Definition: CurvePolygon.h:193
te::rst::Interpolator::Method m_interpMethod2
The interpolation method to use when reading raster 2 data.
Definition: Blender.h:186
std::size_t size() const
It returns the number of points (vertexes) in the geometry.
Definition: LineString.h:262
std::vector< std::pair< te::gm::Coord2D, te::gm::Coord2D > > m_r1IntersectionSegmentsPoints
A sub-set of the intersection polygon wich is part of raster 1 valid data polygon ( raster 1 indexed ...
Definition: Blender.h:218
TECOMMONEXPORT unsigned long int GetTotalVirtualMemory()
Returns the amount of total virtual memory (bytes) that can be claimed by the current process (physic...
te::rst::Interpolator * m_interp1
Raster 1 interpolator instance pointer.
Definition: Blender.h:226
unsigned int m_firstRasterCol2Process
Definition: Blender.h:162
virtual bool within(const Geometry *const rhs) const
It returns true if the geometry object is spatially within rhs geometry.
Definition: Geometry.cpp:285