27 int theSrcDatumTransform,
28 int theDestDatumTransform,
30 int theDestRows,
int theDestCols,
31 double theMaxSrcXRes,
double theMaxSrcYRes,
34 , mSrcCRS( theSrcCRS )
35 , mDestCRS( theDestCRS )
36 , mSrcDatumTransform( theSrcDatumTransform )
37 , mDestDatumTransform( theDestDatumTransform )
38 , mDestExtent( theDestExtent )
39 , mExtent( theExtent )
40 , mDestRows( theDestRows ), mDestCols( theDestCols )
41 , pHelperTop( 0 ), pHelperBottom( 0 )
42 , mMaxSrcXRes( theMaxSrcXRes ), mMaxSrcYRes( theMaxSrcYRes )
54 int theDestRows,
int theDestCols,
55 double theMaxSrcXRes,
double theMaxSrcYRes,
58 , mSrcCRS( theSrcCRS )
59 , mDestCRS( theDestCRS )
60 , mSrcDatumTransform( -1 )
61 , mDestDatumTransform( -1 )
62 , mDestExtent( theDestExtent )
63 , mExtent( theExtent )
64 , mDestRows( theDestRows ), mDestCols( theDestCols )
65 , pHelperTop( 0 ), pHelperBottom( 0 )
66 , mMaxSrcXRes( theMaxSrcXRes ), mMaxSrcYRes( theMaxSrcYRes )
77 double theMaxSrcXRes,
double theMaxSrcYRes,
80 , mSrcCRS( theSrcCRS )
81 , mDestCRS( theDestCRS )
82 , mSrcDatumTransform( -1 )
83 , mDestDatumTransform( -1 )
84 , mExtent( theExtent )
93 , mDestRowsPerMatrixRow( 0.0 )
94 , mDestColsPerMatrixCol( 0.0 )
95 , pHelperTop( 0 ), pHelperBottom( 0 )
99 , mSqrTolerance( 0.0 )
100 , mMaxSrcXRes( theMaxSrcXRes )
101 , mMaxSrcYRes( theMaxSrcYRes )
102 , mApproximate( false )
109 , mSrcDatumTransform( -1 )
110 , mDestDatumTransform( -1 )
119 , mDestRowsPerMatrixRow( 0.0 )
120 , mDestColsPerMatrixCol( 0.0 )
126 , mSqrTolerance( 0.0 )
129 , mApproximate( false )
137 , pHelperBottom( NULL )
142 , mApproximate( false )
144 mSrcCRS = projector.mSrcCRS;
145 mDestCRS = projector.mDestCRS;
146 mSrcDatumTransform = projector.mSrcDatumTransform;
147 mDestDatumTransform = projector.mDestDatumTransform;
148 mMaxSrcXRes = projector.mMaxSrcXRes;
149 mMaxSrcYRes = projector.mMaxSrcYRes;
150 mExtent = projector.mExtent;
151 mDestRows = projector.mDestRows;
152 mDestCols = projector.mDestCols;
153 mDestXRes = projector.mDestXRes;
154 mDestYRes = projector.mDestYRes;
155 mSrcRows = projector.mSrcRows;
156 mSrcCols = projector.mSrcCols;
157 mSrcXRes = projector.mSrcXRes;
158 mSrcYRes = projector.mSrcYRes;
159 mDestRowsPerMatrixRow = projector.mDestRowsPerMatrixRow;
160 mDestColsPerMatrixCol = projector.mDestColsPerMatrixCol;
166 if ( &projector !=
this )
168 mSrcCRS = projector.mSrcCRS;
169 mDestCRS = projector.mDestCRS;
170 mSrcDatumTransform = projector.mSrcDatumTransform;
171 mDestDatumTransform = projector.mDestDatumTransform;
172 mMaxSrcXRes = projector.mMaxSrcXRes;
173 mMaxSrcYRes = projector.mMaxSrcYRes;
174 mExtent = projector.mExtent;
183 projector->mSrcDatumTransform = mSrcDatumTransform;
184 projector->mDestDatumTransform = mDestDatumTransform;
191 delete[] pHelperBottom;
211 mDestCRS = theDestCRS;
212 mSrcDatumTransform = srcDatumTransform;
213 mDestDatumTransform = destDatumTransform;
216 void QgsRasterProjector::calc()
220 mCPLegalMatrix.clear();
223 delete[] pHelperBottom;
242 mExtent = provider->
extent();
247 mDestXRes = mDestExtent.
width() / ( mDestCols );
248 mDestYRes = mDestExtent.
height() / ( mDestRows );
254 double myDestRes = mDestXRes < mDestYRes ? mDestXRes : mDestYRes;
255 mSqrTolerance = myDestRes * myDestRes;
260 mCPCols = mCPRows = 3;
261 for (
int i = 0; i < mCPRows; i++ )
263 QList<QgsPoint> myRow;
267 mCPMatrix.insert( i, myRow );
269 QList<bool> myLegalRow;
270 myLegalRow.append(
bool(
false ) );
271 myLegalRow.append(
bool(
false ) );
272 myLegalRow.append(
bool(
false ) );
273 mCPLegalMatrix.insert( i, myLegalRow );
275 for (
int i = 0; i < mCPRows; i++ )
277 calcRow( i, inverseCt );
282 bool myColsOK = checkCols( inverseCt );
285 insertRows( inverseCt );
287 bool myRowsOK = checkRows( inverseCt );
290 insertCols( inverseCt );
292 if ( myColsOK && myRowsOK )
300 if ( mCPRows * mCPCols > 0.25 * mDestRows * mDestCols )
303 mApproximate =
false;
307 QgsDebugMsg( QString(
"CPMatrix size: mCPRows = %1 mCPCols = %2" ).arg( mCPRows ).arg( mCPCols ) );
308 mDestRowsPerMatrixRow = ( float )mDestRows / ( mCPRows - 1 );
309 mDestColsPerMatrixCol = ( float )mDestCols / ( mCPCols - 1 );
317 mSrcYRes = mSrcExtent.
height() / mSrcRows;
318 mSrcXRes = mSrcExtent.
width() / mSrcCols;
321 pHelperTop =
new QgsPoint[mDestCols];
322 pHelperBottom =
new QgsPoint[mDestCols];
323 calcHelper( 0, pHelperTop );
324 calcHelper( 1, pHelperBottom );
328 void QgsRasterProjector::calcSrcExtent()
337 mSrcExtent =
QgsRectangle( myPoint.
x(), myPoint.
y(), myPoint.
x(), myPoint.
y() );
338 for (
int i = 0; i < mCPRows; i++ )
340 for (
int j = 0; j < mCPCols ; j++ )
342 myPoint = mCPMatrix[i][j];
343 if ( mCPLegalMatrix[i][j] )
352 mSrcExtent = mSrcExtent.
intersect( &mExtent );
365 if ( mMaxSrcXRes > 0 )
368 double col = floor(( mSrcExtent.
xMinimum() - mExtent.
xMinimum() ) / mMaxSrcXRes );
369 double x = mExtent.
xMinimum() + col * mMaxSrcXRes;
373 x = mExtent.
xMinimum() + col * mMaxSrcXRes;
376 if ( mMaxSrcYRes > 0 )
378 double row = floor(( mExtent.
yMaximum() - mSrcExtent.
yMaximum() ) / mMaxSrcYRes );
379 double y = mExtent.
yMaximum() - row * mMaxSrcYRes;
383 y = mExtent.
yMaximum() - row * mMaxSrcYRes;
390 QString QgsRasterProjector::cpToString()
393 for (
int i = 0; i < mCPRows; i++ )
397 for (
int j = 0; j < mCPCols; j++ )
402 if ( mCPLegalMatrix[i][j] )
415 void QgsRasterProjector::calcSrcRowsCols()
424 double myDestColsPerMatrixCell = ( double )mDestCols / mCPCols;
425 double myDestRowsPerMatrixCell = ( double )mDestRows / mCPRows;
426 QgsDebugMsg( QString(
"myDestColsPerMatrixCell = %1 myDestRowsPerMatrixCell = %2" ).arg( myDestColsPerMatrixCell ).arg( myDestRowsPerMatrixCell ) );
428 double myMinSize = DBL_MAX;
430 for (
int i = 0; i < mCPRows - 1; i++ )
432 for (
int j = 0; j < mCPCols - 1; j++ )
434 QgsPoint myPointA = mCPMatrix[i][j];
435 QgsPoint myPointB = mCPMatrix[i][j+1];
436 QgsPoint myPointC = mCPMatrix[i+1][j];
437 if ( mCPLegalMatrix[i][j] && mCPLegalMatrix[i][j+1] && mCPLegalMatrix[i+1][j] )
439 double mySize = sqrt( myPointA.
sqrDist( myPointB ) ) / myDestColsPerMatrixCell;
440 if ( mySize < myMinSize )
443 mySize = sqrt( myPointA.
sqrDist( myPointC ) ) / myDestRowsPerMatrixCell;
444 if ( mySize < myMinSize )
455 QgsDebugMsg( QString(
"mMaxSrcXRes = %1 mMaxSrcYRes = %2" ).arg( mMaxSrcXRes ).arg( mMaxSrcYRes ) );
457 double myMinXSize = mMaxSrcXRes > myMinSize ? mMaxSrcXRes : myMinSize;
458 double myMinYSize = mMaxSrcYRes > myMinSize ? mMaxSrcYRes : myMinSize;
459 QgsDebugMsg( QString(
"myMinXSize = %1 myMinYSize = %2" ).arg( myMinXSize ).arg( myMinYSize ) );
460 QgsDebugMsg( QString(
"mSrcExtent.width = %1 mSrcExtent.height = %2" ).arg( mSrcExtent.
width() ).arg( mSrcExtent.
height() ) );
463 mSrcRows = ( int ) qRound( mSrcExtent.
height() / myMinYSize );
464 mSrcCols = ( int ) qRound( mSrcExtent.
width() / myMinXSize );
466 QgsDebugMsg( QString(
"mSrcRows = %1 mSrcCols = %2" ).arg( mSrcRows ).arg( mSrcCols ) );
470 inline void QgsRasterProjector::destPointOnCPMatrix(
int theRow,
int theCol,
double *theX,
double *theY )
472 *theX = mDestExtent.
xMinimum() + theCol * mDestExtent.
width() / ( mCPCols - 1 );
473 *theY = mDestExtent.
yMaximum() - theRow * mDestExtent.
height() / ( mCPRows - 1 );
476 inline int QgsRasterProjector::matrixRow(
int theDestRow )
478 return (
int )( floor(( theDestRow + 0.5 ) / mDestRowsPerMatrixRow ) );
480 inline int QgsRasterProjector::matrixCol(
int theDestCol )
482 return (
int )( floor(( theDestCol + 0.5 ) / mDestColsPerMatrixCol ) );
485 QgsPoint QgsRasterProjector::srcPoint(
int theDestRow,
int theCol )
487 Q_UNUSED( theDestRow );
492 void QgsRasterProjector::calcHelper(
int theMatrixRow,
QgsPoint *thePoints )
495 for (
int myDestCol = 0; myDestCol < mDestCols; myDestCol++ )
497 double myDestX = mDestExtent.
xMinimum() + ( myDestCol + 0.5 ) * mDestXRes;
499 int myMatrixCol = matrixCol( myDestCol );
501 double myDestXMin, myDestYMin, myDestXMax, myDestYMax;
503 destPointOnCPMatrix( theMatrixRow, myMatrixCol, &myDestXMin, &myDestYMin );
504 destPointOnCPMatrix( theMatrixRow, myMatrixCol + 1, &myDestXMax, &myDestYMax );
506 double xfrac = ( myDestX - myDestXMin ) / ( myDestXMax - myDestXMin );
508 QgsPoint &mySrcPoint0 = mCPMatrix[theMatrixRow][myMatrixCol];
509 QgsPoint &mySrcPoint1 = mCPMatrix[theMatrixRow][myMatrixCol+1];
510 double s = mySrcPoint0.
x() + ( mySrcPoint1.
x() - mySrcPoint0.
x() ) * xfrac;
511 double t = mySrcPoint0.
y() + ( mySrcPoint1.
y() - mySrcPoint0.
y() ) * xfrac;
513 thePoints[myDestCol].
setX( s );
514 thePoints[myDestCol].
setY( t );
517 void QgsRasterProjector::nextHelper()
522 pHelperTop = pHelperBottom;
524 calcHelper( mHelperTopRow + 2, pHelperBottom );
528 bool QgsRasterProjector::srcRowCol(
int theDestRow,
int theDestCol,
int *theSrcRow,
int *theSrcCol,
const QgsCoordinateTransform* ct )
532 return approximateSrcRowCol( theDestRow, theDestCol, theSrcRow, theSrcCol );
536 return preciseSrcRowCol( theDestRow, theDestCol, theSrcRow, theSrcCol, ct );
540 bool QgsRasterProjector::preciseSrcRowCol(
int theDestRow,
int theDestCol,
int *theSrcRow,
int *theSrcCol,
const QgsCoordinateTransform* ct )
544 QgsDebugMsgLevel( QString(
"theDestRow = %1 mDestExtent.yMaximum() = %2 mDestYRes = %3" ).arg( theDestRow ).arg( mDestExtent.
yMaximum() ).arg( mDestYRes ), 5 );
548 double x = mDestExtent.
xMinimum() + ( theDestCol + 0.5 ) * mDestXRes;
549 double y = mDestExtent.
yMaximum() - ( theDestRow + 0.5 ) * mDestYRes;
570 *theSrcRow = ( int ) floor(( mSrcExtent.
yMaximum() - y ) / mSrcYRes );
571 *theSrcCol = ( int ) floor(( x - mSrcExtent.
xMinimum() ) / mSrcXRes );
573 QgsDebugMsgLevel( QString(
"mSrcExtent.yMinimum() = %1 mSrcExtent.yMaximum() = %2 mSrcYRes = %3" ).arg( mSrcExtent.
yMinimum() ).arg( mSrcExtent.
yMaximum() ).arg( mSrcYRes ), 5 );
574 QgsDebugMsgLevel( QString(
"theSrcRow = %1 theSrcCol = %2" ).arg( *theSrcRow ).arg( *theSrcCol ), 5 );
581 if ( *theSrcRow >= mSrcRows )
return false;
582 if ( *theSrcRow < 0 )
return false;
583 if ( *theSrcCol >= mSrcCols )
return false;
584 if ( *theSrcCol < 0 )
return false;
589 bool QgsRasterProjector::approximateSrcRowCol(
int theDestRow,
int theDestCol,
int *theSrcRow,
int *theSrcCol )
591 int myMatrixRow = matrixRow( theDestRow );
592 int myMatrixCol = matrixCol( theDestCol );
594 if ( myMatrixRow > mHelperTopRow )
600 double myDestY = mDestExtent.
yMaximum() - ( theDestRow + 0.5 ) * mDestYRes;
604 double myDestXMin, myDestYMin, myDestXMax, myDestYMax;
606 destPointOnCPMatrix( myMatrixRow + 1, myMatrixCol, &myDestXMin, &myDestYMin );
607 destPointOnCPMatrix( myMatrixRow, myMatrixCol + 1, &myDestXMax, &myDestYMax );
609 double yfrac = ( myDestY - myDestYMin ) / ( myDestYMax - myDestYMin );
611 QgsPoint &myTop = pHelperTop[theDestCol];
612 QgsPoint &myBot = pHelperBottom[theDestCol];
618 double tx = myTop.
x();
619 double ty = myTop.
y();
620 double bx = myBot.
x();
621 double by = myBot.
y();
622 double mySrcX = bx + ( tx - bx ) * yfrac;
623 double mySrcY = by + ( ty - by ) * yfrac;
632 *theSrcRow = ( int ) floor(( mSrcExtent.
yMaximum() - mySrcY ) / mSrcYRes );
633 *theSrcCol = ( int ) floor(( mySrcX - mSrcExtent.
xMinimum() ) / mSrcXRes );
638 if ( *theSrcRow >= mSrcRows )
return false;
639 if ( *theSrcRow < 0 )
return false;
640 if ( *theSrcCol >= mSrcCols )
return false;
641 if ( *theSrcCol < 0 )
return false;
648 for (
int r = 0; r < mCPRows - 1; r++ )
650 QList<QgsPoint> myRow;
651 QList<bool> myLegalRow;
652 for (
int c = 0; c < mCPCols; c++ )
655 myLegalRow.append(
false );
658 mCPMatrix.insert( 1 + r*2, myRow );
659 mCPLegalMatrix.insert( 1 + r*2, myLegalRow );
661 mCPRows += mCPRows - 1;
662 for (
int r = 1; r < mCPRows - 1; r += 2 )
670 for (
int r = 0; r < mCPRows; r++ )
672 QList<QgsPoint> myRow;
673 QList<bool> myLegalRow;
674 for (
int c = 0; c < mCPCols - 1; c++ )
676 mCPMatrix[r].insert( 1 + c*2,
QgsPoint() );
677 mCPLegalMatrix[r].insert( 1 + c*2,
false );
680 mCPCols += mCPCols - 1;
681 for (
int c = 1; c < mCPCols - 1; c += 2 )
690 double myDestX, myDestY;
691 destPointOnCPMatrix( theRow, theCol, &myDestX, &myDestY );
692 QgsPoint myDestPoint( myDestX, myDestY );
697 mCPMatrix[theRow][theCol] = ct->
transform( myDestPoint );
698 mCPLegalMatrix[theRow][theCol] =
true;
702 mCPLegalMatrix[theRow][theCol] =
false;
709 mCPLegalMatrix[theRow][theCol] =
false;
716 for (
int i = 0; i < mCPCols; i++ )
718 calcCP( theRow, i, ct );
727 for (
int i = 0; i < mCPRows; i++ )
729 calcCP( i, theCol, ct );
742 for (
int c = 0; c < mCPCols; c++ )
744 for (
int r = 1; r < mCPRows - 1; r += 2 )
746 double myDestX, myDestY;
747 destPointOnCPMatrix( r, c, &myDestX, &myDestY );
748 QgsPoint myDestPoint( myDestX, myDestY );
750 QgsPoint mySrcPoint1 = mCPMatrix[r-1][c];
751 QgsPoint mySrcPoint2 = mCPMatrix[r][c];
752 QgsPoint mySrcPoint3 = mCPMatrix[r+1][c];
754 QgsPoint mySrcApprox(( mySrcPoint1.
x() + mySrcPoint3.
x() ) / 2, ( mySrcPoint1.
y() + mySrcPoint3.
y() ) / 2 );
755 if ( !mCPLegalMatrix[r-1][c] || !mCPLegalMatrix[r][c] || !mCPLegalMatrix[r+1][c] )
763 double mySqrDist = myDestApprox.
sqrDist( myDestPoint );
764 if ( mySqrDist > mSqrTolerance )
787 for (
int r = 0; r < mCPRows; r++ )
789 for (
int c = 1; c < mCPCols - 1; c += 2 )
791 double myDestX, myDestY;
792 destPointOnCPMatrix( r, c, &myDestX, &myDestY );
794 QgsPoint myDestPoint( myDestX, myDestY );
795 QgsPoint mySrcPoint1 = mCPMatrix[r][c-1];
796 QgsPoint mySrcPoint2 = mCPMatrix[r][c];
797 QgsPoint mySrcPoint3 = mCPMatrix[r][c+1];
799 QgsPoint mySrcApprox(( mySrcPoint1.
x() + mySrcPoint3.
x() ) / 2, ( mySrcPoint1.
y() + mySrcPoint3.
y() ) / 2 );
800 if ( !mCPLegalMatrix[r][c-1] || !mCPLegalMatrix[r][c] || !mCPLegalMatrix[r][c+1] )
808 double mySqrDist = myDestApprox.
sqrDist( myDestPoint );
809 if ( mySqrDist > mSqrTolerance )
828 QgsDebugMsg( QString(
"width = %1 height = %2" ).arg( width ).arg( height ) );
835 if ( ! mSrcCRS.
isValid() || ! mDestCRS.
isValid() || mSrcCRS == mDestCRS )
838 return mInput->
block( bandNo, extent, width, height );
846 QgsDebugMsg( QString(
"srcExtent:\n%1" ).arg( srcExtent().toString() ) );
847 QgsDebugMsg( QString(
"srcCols = %1 srcRows = %2" ).arg( srcCols() ).arg( srcRows() ) );
850 if ( srcRows() <= 0 || srcCols() <= 0 )
857 if ( !inputBlock || inputBlock->
isEmpty() )
875 if ( !outputBlock->isValid() )
903 outputBlock->setIsNoData();
906 for (
int i = 0; i < height; ++i )
908 for (
int j = 0; j < width; ++j )
910 bool inside = srcRowCol( i, j, &srcRow, &srcCol, inverseCt );
911 if ( !inside )
continue;
914 QgsDebugMsgLevel( QString(
"row = %1 col = %2 srcRow = %3 srcCol = %4" ).arg( i ).arg( j ).arg( srcRow ).arg( srcCol ), 5 );
917 if ( doNoData && inputBlock->
isNoData( srcRow, srcCol ) )
919 outputBlock->setIsNoData( i, j );
924 char *srcBits = inputBlock->
bits( srcIndex );
925 char *destBits = outputBlock->bits( destIndex );
928 QgsDebugMsg( QString(
"Cannot get input block data: row = %1 col = %2" ).arg( i ).arg( j ) );
933 QgsDebugMsg( QString(
"Cannot set output block data: srcRow = %1 srcCol = %2" ).arg( srcRow ).arg( srcCol ) );
936 memcpy( destBits, srcBits, pixelSize );