@@ -290,6 +290,9 @@ void QgsRasterProjector::calcSrcExtent()
290
290
}
291
291
// Expand a bit to avoid possible approx coords falling out because of representation error?
292
292
293
+ // Combine with maximum source extent
294
+ mSrcExtent = mSrcExtent .intersect ( &mExtent );
295
+
293
296
// If mMaxSrcXRes, mMaxSrcYRes are defined (fixed src resolution)
294
297
// align extent to src resolution to avoid jumping of reprojected pixels
295
298
// when shifting resampled grid.
@@ -464,19 +467,19 @@ void QgsRasterProjector::nextHelper()
464
467
mHelperTopRow ++;
465
468
}
466
469
467
- void QgsRasterProjector::srcRowCol ( int theDestRow, int theDestCol, int *theSrcRow, int *theSrcCol, const QgsCoordinateTransform* ct )
470
+ bool QgsRasterProjector::srcRowCol ( int theDestRow, int theDestCol, int *theSrcRow, int *theSrcCol, const QgsCoordinateTransform* ct )
468
471
{
469
472
if ( mApproximate )
470
473
{
471
- approximateSrcRowCol ( theDestRow, theDestCol, theSrcRow, theSrcCol );
474
+ return approximateSrcRowCol ( theDestRow, theDestCol, theSrcRow, theSrcCol );
472
475
}
473
476
else
474
477
{
475
- preciseSrcRowCol ( theDestRow, theDestCol, theSrcRow, theSrcCol, ct );
478
+ return preciseSrcRowCol ( theDestRow, theDestCol, theSrcRow, theSrcCol, ct );
476
479
}
477
480
}
478
481
479
- void QgsRasterProjector::preciseSrcRowCol ( int theDestRow, int theDestCol, int *theSrcRow, int *theSrcCol, const QgsCoordinateTransform* ct )
482
+ bool QgsRasterProjector::preciseSrcRowCol ( int theDestRow, int theDestCol, int *theSrcRow, int *theSrcCol, const QgsCoordinateTransform* ct )
480
483
{
481
484
#ifdef QGISDEBUG
482
485
QgsDebugMsgLevel ( QString ( " theDestRow = %1" ).arg ( theDestRow ), 5 );
@@ -501,31 +504,31 @@ void QgsRasterProjector::preciseSrcRowCol( int theDestRow, int theDestCol, int *
501
504
QgsDebugMsgLevel ( QString ( " x = %1 y = %2" ).arg ( x ).arg ( y ), 5 );
502
505
#endif
503
506
507
+ if ( !mExtent .contains ( QgsPoint ( x, y ) ) )
508
+ {
509
+ return false ;
510
+ }
504
511
// Get source row col
505
512
*theSrcRow = ( int ) floor (( mSrcExtent .yMaximum () - y ) / mSrcYRes );
506
513
*theSrcCol = ( int ) floor (( x - mSrcExtent .xMinimum () ) / mSrcXRes );
507
514
#ifdef QGISDEBUG
508
- QgsDebugMsgLevel ( QString ( " mSrcExtent.yMaximum () = %1 mSrcYRes = %2" ).arg ( mSrcExtent .yMaximum () ).arg ( mSrcYRes ), 5 );
515
+ QgsDebugMsgLevel ( QString ( " mSrcExtent.yMinimum () = %1 mSrcExtent.yMaximum() = %2 mSrcYRes = %3 " ). arg ( mSrcExtent . yMinimum () ).arg ( mSrcExtent .yMaximum () ).arg ( mSrcYRes ), 5 );
509
516
QgsDebugMsgLevel ( QString ( " theSrcRow = %1 theSrcCol = %2" ).arg ( *theSrcRow ).arg ( *theSrcCol ), 5 );
510
517
#endif
511
518
512
519
// With epsg 32661 (Polar Stereographic) it was happening that *theSrcCol == mSrcCols
513
520
// For now silently correct limits to avoid crashes
514
521
// TODO: review
515
- if ( *theSrcRow >= mSrcRows )
516
- *theSrcRow = mSrcRows - 1 ;
517
- if ( *theSrcRow < 0 )
518
- *theSrcRow = 0 ;
519
- if ( *theSrcCol >= mSrcCols )
520
- *theSrcCol = mSrcCols - 1 ;
521
- if ( *theSrcCol < 0 )
522
- *theSrcCol = 0 ;
522
+ // should not happen
523
+ if ( *theSrcRow >= mSrcRows ) return false ;
524
+ if ( *theSrcRow < 0 ) return false ;
525
+ if ( *theSrcCol >= mSrcCols ) return false ;
526
+ if ( *theSrcCol < 0 ) return false ;
523
527
524
- Q_ASSERT ( *theSrcRow < mSrcRows );
525
- Q_ASSERT ( *theSrcCol < mSrcCols );
528
+ return true ;
526
529
}
527
530
528
- void QgsRasterProjector::approximateSrcRowCol ( int theDestRow, int theDestCol, int *theSrcRow, int *theSrcCol )
531
+ bool QgsRasterProjector::approximateSrcRowCol ( int theDestRow, int theDestCol, int *theSrcRow, int *theSrcCol )
529
532
{
530
533
int myMatrixRow = matrixRow ( theDestRow );
531
534
int myMatrixCol = matrixCol ( theDestCol );
@@ -561,23 +564,25 @@ void QgsRasterProjector::approximateSrcRowCol( int theDestRow, int theDestCol, i
561
564
double mySrcX = bx + ( tx - bx ) * yfrac;
562
565
double mySrcY = by + ( ty - by ) * yfrac;
563
566
567
+ if ( !mExtent .contains ( QgsPoint ( mySrcX, mySrcY ) ) )
568
+ {
569
+ return false ;
570
+ }
571
+
564
572
// TODO: check again cell selection (coor is in the middle)
565
573
566
574
*theSrcRow = ( int ) floor (( mSrcExtent .yMaximum () - mySrcY ) / mSrcYRes );
567
575
*theSrcCol = ( int ) floor (( mySrcX - mSrcExtent .xMinimum () ) / mSrcXRes );
568
576
569
577
// For now silently correct limits to avoid crashes
570
578
// TODO: review
571
- if ( *theSrcRow >= mSrcRows )
572
- *theSrcRow = mSrcRows - 1 ;
573
- if ( *theSrcRow < 0 )
574
- *theSrcRow = 0 ;
575
- if ( *theSrcCol >= mSrcCols )
576
- *theSrcCol = mSrcCols - 1 ;
577
- if ( *theSrcCol < 0 )
578
- *theSrcCol = 0 ;
579
- Q_ASSERT ( *theSrcRow < mSrcRows );
580
- Q_ASSERT ( *theSrcCol < mSrcCols );
579
+ // should not happen
580
+ if ( *theSrcRow >= mSrcRows ) return false ;
581
+ if ( *theSrcRow < 0 ) return false ;
582
+ if ( *theSrcCol >= mSrcCols ) return false ;
583
+ if ( *theSrcCol < 0 ) return false ;
584
+
585
+ return true ;
581
586
}
582
587
583
588
void QgsRasterProjector::insertRows ( const QgsCoordinateTransform* ct )
@@ -816,7 +821,11 @@ QgsRasterBlock * QgsRasterProjector::block( int bandNo, QgsRectangle const & ex
816
821
return outputBlock;
817
822
}
818
823
819
- // No data:
824
+ // set output to no data, it should be fast
825
+ outputBlock->setIsNoData ();
826
+
827
+ // No data: because isNoData()/setIsNoData() is slow with respect to simple memcpy,
828
+ // we use if only if necessary:
820
829
// 1) no data value exists (numerical) -> memcpy, not necessary isNoData()/setIsNoData()
821
830
// 2) no data value does not exist but it may contain no data (numerical no data bitmap)
822
831
// -> must use isNoData()/setIsNoData()
@@ -825,27 +834,31 @@ QgsRasterBlock * QgsRasterProjector::block( int bandNo, QgsRectangle const & ex
825
834
826
835
// To copy no data values stored in bitmaps we have to use isNoData()/setIsNoData(),
827
836
// we cannot fill output block with no data because we use memcpy for data, not setValue().
828
- bool doNoData = inputBlock->hasNoData () && !inputBlock->hasNoDataValue ();
837
+ bool doNoData = ! QgsRasterBlock::typeIsNumeric ( inputBlock-> dataType () ) && inputBlock->hasNoData () && !inputBlock->hasNoDataValue ();
829
838
830
839
const QgsCoordinateTransform* ct = 0 ;
831
840
if ( !mApproximate )
832
841
{
833
842
ct = QgsCoordinateTransformCache::instance ()->transform ( mDestCRS .authid (), mSrcCRS .authid (), mDestDatumTransform , mSrcDatumTransform );
834
843
}
835
844
845
+ outputBlock->setIsNoData ();
846
+
836
847
int srcRow, srcCol;
837
848
for ( int i = 0 ; i < height; ++i )
838
849
{
839
850
for ( int j = 0 ; j < width; ++j )
840
851
{
841
- srcRowCol ( i, j, &srcRow, &srcCol, ct );
852
+ bool inside = srcRowCol ( i, j, &srcRow, &srcCol, ct );
853
+ if ( !inside ) continue ; // we have everything set to no data
854
+
842
855
qgssize srcIndex = ( qgssize )srcRow * mSrcCols + srcCol;
843
856
QgsDebugMsgLevel ( QString ( " row = %1 col = %2 srcRow = %3 srcCol = %4" ).arg ( i ).arg ( j ).arg ( srcRow ).arg ( srcCol ), 5 );
844
857
845
858
// isNoData() may be slow so we check doNoData first
846
859
if ( doNoData && inputBlock->isNoData ( srcRow, srcCol ) )
847
860
{
848
- outputBlock->setIsNoData ( srcRow, srcCol );
861
+ outputBlock->setIsNoData ( i, j );
849
862
continue ;
850
863
}
851
864
0 commit comments