28#include "moc_qgsrasterprojector.cpp"
30using namespace Qt::StringLiterals;
45 projector->mSrcCRS = mSrcCRS;
46 projector->mDestCRS = mDestCRS;
47 projector->mTransformContext = mTransformContext;
50 projector->mSrcDatumTransform = mSrcDatumTransform;
51 projector->mDestDatumTransform = mDestDatumTransform;
54 projector->mPrecision = mPrecision;
61 return mInput->bandCount();
69 return mInput->dataType( bandNo );
82 mSrcDatumTransform = srcDatumTransform;
83 mDestDatumTransform = destDatumTransform;
91 mTransformContext = transformContext;
93 mSrcDatumTransform = -1;
94 mDestDatumTransform = -1;
99ProjectorData::ProjectorData(
102 : mInverseCt( inverseCt )
103 , mDestExtent( extent )
104 , mDestRows( height )
112 QgsRasterDataProvider *provider =
dynamic_cast<QgsRasterDataProvider *
>(
input->sourceInput() );
125 if ( mExtent.isEmpty() )
127 mExtent = provider->
extent();
132 mDestXRes = mDestExtent.width() / ( mDestCols );
133 mDestYRes = mDestExtent.height() / ( mDestRows );
139 const double myDestRes = mDestXRes < mDestYRes ? mDestXRes : mDestYRes;
140 mSqrTolerance = myDestRes * myDestRes;
148 mApproximate =
false;
153 mCPCols = mCPRows = 3;
161 if ( std::fabs( -mDestExtent.yMinimum() - mDestExtent.yMaximum() ) / height < 0.5 * mDestYRes )
164 for (
int i = 0; i < mCPRows; i++ )
166 QList<QgsPointXY> myRow;
167 myRow.append( QgsPointXY() );
168 myRow.append( QgsPointXY() );
169 myRow.append( QgsPointXY() );
170 mCPMatrix.insert( i, myRow );
172 QList<bool> myLegalRow;
173 myLegalRow.append(
bool(
false ) );
174 myLegalRow.append(
bool(
false ) );
175 myLegalRow.append(
bool(
false ) );
176 mCPLegalMatrix.insert( i, myLegalRow );
178 for (
int i = 0; i < mCPRows; i++ )
180 calcRow( i, inverseCt );
185 const bool myColsOK = checkCols( inverseCt );
188 insertRows( inverseCt );
190 const bool myRowsOK = checkRows( inverseCt );
193 insertCols( inverseCt );
195 if ( myColsOK && myRowsOK )
202 if ( mCPRows * mCPCols > 0.25 * mDestRows * mDestCols )
206 mApproximate =
false;
214 QgsDebugMsgLevel( u
"CPMatrix size: mCPRows = %1 mCPCols = %2"_s.arg( mCPRows ).arg( mCPCols ), 4 );
215 mDestRowsPerMatrixRow =
static_cast< double >( mDestRows ) / ( mCPRows - 1 );
216 mDestColsPerMatrixCol =
static_cast< double >( mDestCols ) / ( mCPCols - 1 );
224 pHelperTop.resize( mDestCols );
225 pHelperBottom.resize( mDestCols );
226 calcHelper( 0, pHelperTop );
227 calcHelper( 1, pHelperBottom );
233 mSrcYRes = mSrcExtent.height() / mSrcRows;
234 mSrcXRes = mSrcExtent.width() / mSrcCols;
237ProjectorData::~ProjectorData()
241void ProjectorData::calcSrcExtent()
252 mSrcExtent =
QgsRectangle( myPoint.
x(), myPoint.
y(), myPoint.
x(), myPoint.
y() );
253 for (
int i = 0; i < mCPRows; i++ )
255 for (
int j = 0; j < mCPCols; j++ )
257 myPoint = mCPMatrix[i][j];
258 if ( mCPLegalMatrix[i][j] )
260 mSrcExtent.combineExtentWith( myPoint.
x(), myPoint.
y() );
267 mSrcExtent = mSrcExtent.intersect( mExtent );
278 if ( !mExtent.isEmpty() )
280 if ( mMaxSrcXRes > 0 )
283 double col = std::floor( ( mSrcExtent.xMinimum() - mExtent.xMinimum() ) / mMaxSrcXRes );
284 double x = mExtent.xMinimum() + col * mMaxSrcXRes;
285 mSrcExtent.setXMinimum( x );
287 col = std::ceil( ( mSrcExtent.xMaximum() - mExtent.xMinimum() ) / mMaxSrcXRes );
288 x = mExtent.xMinimum() + col * mMaxSrcXRes;
289 mSrcExtent.setXMaximum( x );
291 if ( mMaxSrcYRes > 0 )
293 double row = std::floor( ( mExtent.yMaximum() - mSrcExtent.yMaximum() ) / mMaxSrcYRes );
294 double y = mExtent.yMaximum() - row * mMaxSrcYRes;
295 mSrcExtent.setYMaximum( y );
297 row = std::ceil( ( mExtent.yMaximum() - mSrcExtent.yMinimum() ) / mMaxSrcYRes );
298 y = mExtent.yMaximum() - row * mMaxSrcYRes;
299 mSrcExtent.setYMinimum( y );
305QString ProjectorData::cpToString()
const
308 for (
int i = 0; i < mCPRows; i++ )
312 for (
int j = 0; j < mCPCols; j++ )
317 if ( mCPLegalMatrix[i][j] )
323 myString +=
"(-,-)"_L1;
330void ProjectorData::calcSrcRowsCols()
338 double myMinSize = std::numeric_limits<double>::max();
342 double myMaxSize = 0;
345 const double myDestColsPerMatrixCell =
static_cast< double >( mDestCols ) / mCPCols;
346 const double myDestRowsPerMatrixCell =
static_cast< double >( mDestRows ) / mCPRows;
347 QgsDebugMsgLevel( u
"myDestColsPerMatrixCell = %1 myDestRowsPerMatrixCell = %2"_s.arg( myDestColsPerMatrixCell ).arg( myDestRowsPerMatrixCell ), 4 );
348 for (
int i = 0; i < mCPRows - 1; i++ )
350 for (
int j = 0; j < mCPCols - 1; j++ )
353 const QgsPointXY myPointB = mCPMatrix[i][j + 1];
354 const QgsPointXY myPointC = mCPMatrix[i + 1][j];
355 if ( mCPLegalMatrix[i][j] && mCPLegalMatrix[i][j + 1] && mCPLegalMatrix[i + 1][j] )
357 double mySize = std::sqrt( myPointA.
sqrDist( myPointB ) ) / myDestColsPerMatrixCell;
358 if ( mySize < myMinSize )
360 if ( mySize > myMaxSize )
363 mySize = std::sqrt( myPointA.
sqrDist( myPointC ) ) / myDestRowsPerMatrixCell;
364 if ( mySize < myMinSize )
366 if ( mySize > myMaxSize )
374 if ( myMinSize < 0.1 * myMaxSize )
375 myMinSize = 0.1 * myMaxSize;
382 int srcXSize, srcYSize;
385 const double srcXRes = srcExtent.
width() / srcXSize;
386 const double srcYRes = srcExtent.
height() / srcYSize;
387 myMinSize = std::min( srcXRes, srcYRes );
400 QgsDebugMsgLevel( u
"mMaxSrcXRes = %1 mMaxSrcYRes = %2"_s.arg( mMaxSrcXRes ).arg( mMaxSrcYRes ), 4 );
402 const double myMinXSize = mMaxSrcXRes > myMinSize ? mMaxSrcXRes : myMinSize;
403 const double myMinYSize = mMaxSrcYRes > myMinSize ? mMaxSrcYRes : myMinSize;
404 QgsDebugMsgLevel( u
"myMinXSize = %1 myMinYSize = %2"_s.arg( myMinXSize ).arg( myMinYSize ), 4 );
405 QgsDebugMsgLevel( u
"mSrcExtent.width = %1 mSrcExtent.height = %2"_s.arg( mSrcExtent.width() ).arg( mSrcExtent.height() ), 4 );
410 double dblSrcRows = mSrcExtent.height() / myMinYSize;
411 if ( dblSrcRows > mDestRows * 10 )
412 mSrcRows = mDestRows * 10;
414 mSrcRows =
static_cast< int >( std::round( dblSrcRows ) );
416 double dblSrcCols = mSrcExtent.width() / myMinXSize;
417 if ( dblSrcCols > mDestCols * 10 )
418 mSrcCols = mDestCols * 10;
420 mSrcCols =
static_cast< int >( std::round( dblSrcCols ) );
422 QgsDebugMsgLevel( u
"mSrcRows = %1 mSrcCols = %2"_s.arg( mSrcRows ).arg( mSrcCols ), 4 );
426inline void ProjectorData::destPointOnCPMatrix(
int row,
int col,
double *theX,
double *theY )
const
428 *theX = mDestExtent.xMinimum() + col * mDestExtent.width() / ( mCPCols - 1 );
429 *theY = mDestExtent.yMaximum() - row * mDestExtent.height() / ( mCPRows - 1 );
432inline int ProjectorData::matrixRow(
int destRow )
const
434 return static_cast< int >( std::floor( ( destRow + 0.5 ) / mDestRowsPerMatrixRow ) );
436inline int ProjectorData::matrixCol(
int destCol )
const
438 return static_cast< int >( std::floor( ( destCol + 0.5 ) / mDestColsPerMatrixCol ) );
441void ProjectorData::calcHelper(
int matrixRow, std::vector<QgsPointXY> &points )
444 for (
int myDestCol = 0; myDestCol < mDestCols; myDestCol++ )
446 const double myDestX = mDestExtent.xMinimum() + ( myDestCol + 0.5 ) * mDestXRes;
448 const int myMatrixCol = matrixCol( myDestCol );
450 double myDestXMin, myDestYMin, myDestXMax, myDestYMax;
452 destPointOnCPMatrix( matrixRow, myMatrixCol, &myDestXMin, &myDestYMin );
453 destPointOnCPMatrix( matrixRow, myMatrixCol + 1, &myDestXMax, &myDestYMax );
455 const double xfrac = ( myDestX - myDestXMin ) / ( myDestXMax - myDestXMin );
457 const QgsPointXY &mySrcPoint0 = mCPMatrix[matrixRow][myMatrixCol];
458 const QgsPointXY &mySrcPoint1 = mCPMatrix[matrixRow][myMatrixCol + 1];
459 const double s = mySrcPoint0.
x() + ( mySrcPoint1.
x() - mySrcPoint0.
x() ) * xfrac;
460 const double t = mySrcPoint0.
y() + ( mySrcPoint1.
y() - mySrcPoint0.
y() ) * xfrac;
462 points[myDestCol].setX( s );
463 points[myDestCol].setY( t );
467void ProjectorData::nextHelper()
470 swap( pHelperTop, pHelperBottom );
471 calcHelper( mHelperTopRow + 2, pHelperBottom );
475bool ProjectorData::srcRowCol(
int destRow,
int destCol,
int *srcRow,
int *srcCol )
479 return approximateSrcRowCol( destRow, destCol, srcRow, srcCol );
483 return preciseSrcRowCol( destRow, destCol, srcRow, srcCol );
487bool ProjectorData::preciseSrcRowCol(
int destRow,
int destCol,
int *srcRow,
int *srcCol )
491 QgsDebugMsgLevel( u
"theDestRow = %1 mDestExtent.yMaximum() = %2 mDestYRes = %3"_s.arg( destRow ).arg( mDestExtent.yMaximum() ).arg( mDestYRes ), 5 );
495 double x = mDestExtent.xMinimum() + ( destCol + 0.5 ) * mDestXRes;
496 double y = mDestExtent.yMaximum() - ( destRow + 0.5 ) * mDestYRes;
503 if ( mInverseCt.isValid() )
507 mInverseCt.transformInPlace( x, y, z );
519 if ( !mExtent.contains( x, y ) )
524 *srcRow =
static_cast< int >( std::floor( ( mSrcExtent.yMaximum() - y ) / mSrcYRes ) );
525 *srcCol =
static_cast< int >( std::floor( ( x - mSrcExtent.xMinimum() ) / mSrcXRes ) );
527 QgsDebugMsgLevel( u
"mSrcExtent.yMinimum() = %1 mSrcExtent.yMaximum() = %2 mSrcYRes = %3"_s.arg( mSrcExtent.yMinimum() ).arg( mSrcExtent.yMaximum() ).arg( mSrcYRes ), 5 );
528 QgsDebugMsgLevel( u
"theSrcRow = %1 srcCol = %2"_s.arg( *srcRow ).arg( *srcCol ), 5 );
535 if ( *srcRow >= mSrcRows )
539 if ( *srcCol >= mSrcCols )
547bool ProjectorData::approximateSrcRowCol(
int destRow,
int destCol,
int *srcRow,
int *srcCol )
549 const int myMatrixRow = matrixRow( destRow );
550 const int myMatrixCol = matrixCol( destCol );
552 if ( myMatrixRow > mHelperTopRow )
558 const double myDestY = mDestExtent.yMaximum() - ( destRow + 0.5 ) * mDestYRes;
562 double myDestXMin, myDestYMin, myDestXMax, myDestYMax;
564 destPointOnCPMatrix( myMatrixRow + 1, myMatrixCol, &myDestXMin, &myDestYMin );
565 destPointOnCPMatrix( myMatrixRow, myMatrixCol + 1, &myDestXMax, &myDestYMax );
567 const double yfrac = ( myDestY - myDestYMin ) / ( myDestYMax - myDestYMin );
569 const QgsPointXY &myTop = pHelperTop[destCol];
570 const QgsPointXY &myBot = pHelperBottom[destCol];
576 const double tx = myTop.
x();
577 const double ty = myTop.
y();
578 const double bx = myBot.
x();
579 const double by = myBot.
y();
580 const double mySrcX = bx + ( tx - bx ) * yfrac;
581 const double mySrcY = by + ( ty - by ) * yfrac;
583 if ( !mExtent.contains( mySrcX, mySrcY ) )
590 *srcRow =
static_cast< int >( std::floor( ( mSrcExtent.yMaximum() - mySrcY ) / mSrcYRes ) );
591 *srcCol =
static_cast< int >( std::floor( ( mySrcX - mSrcExtent.xMinimum() ) / mSrcXRes ) );
596 if ( *srcRow >= mSrcRows )
600 if ( *srcCol >= mSrcCols )
610 for (
int r = 0; r < mCPRows - 1; r++ )
612 QList<QgsPointXY> myRow;
613 QList<bool> myLegalRow;
614 myRow.reserve( mCPCols );
615 myLegalRow.reserve( mCPCols );
616 for (
int c = 0;
c < mCPCols; ++
c )
619 myLegalRow.append(
false );
622 mCPMatrix.insert( 1 + r * 2, myRow );
623 mCPLegalMatrix.insert( 1 + r * 2, myLegalRow );
625 mCPRows += mCPRows - 1;
626 for (
int r = 1; r < mCPRows - 1; r += 2 )
634 for (
int r = 0; r < mCPRows; r++ )
636 for (
int c = 0;
c < mCPCols - 1;
c++ )
639 mCPLegalMatrix[r].insert( 1 +
c * 2,
false );
642 mCPCols += mCPCols - 1;
643 for (
int c = 1;
c < mCPCols - 1;
c += 2 )
651 double myDestX, myDestY;
652 destPointOnCPMatrix( row, col, &myDestX, &myDestY );
653 const QgsPointXY myDestPoint( myDestX, myDestY );
658 mCPMatrix[row][col] = ct.
transform( myDestPoint );
659 mCPLegalMatrix[row][col] =
true;
663 mCPLegalMatrix[row][col] =
false;
670 mCPLegalMatrix[row][col] =
false;
677 for (
int i = 0; i < mCPCols; i++ )
679 calcCP( row, i, ct );
688 for (
int i = 0; i < mCPRows; i++ )
690 calcCP( i, col, ct );
703 for (
int c = 0;
c < mCPCols;
c++ )
705 for (
int r = 1; r < mCPRows - 1; r += 2 )
707 double myDestX, myDestY;
708 destPointOnCPMatrix( r,
c, &myDestX, &myDestY );
709 const QgsPointXY myDestPoint( myDestX, myDestY );
711 const QgsPointXY mySrcPoint1 = mCPMatrix[r - 1][
c];
713 const QgsPointXY mySrcPoint3 = mCPMatrix[r + 1][
c];
715 const QgsPointXY mySrcApprox( ( mySrcPoint1.
x() + mySrcPoint3.
x() ) / 2, ( mySrcPoint1.
y() + mySrcPoint3.
y() ) / 2 );
716 if ( !mCPLegalMatrix[r - 1][
c] || !mCPLegalMatrix[r][
c] || !mCPLegalMatrix[r + 1][
c] )
724 const double mySqrDist = myDestApprox.
sqrDist( myDestPoint );
725 if ( mySqrDist > mSqrTolerance )
748 for (
int r = 0; r < mCPRows; r++ )
750 for (
int c = 1;
c < mCPCols - 1;
c += 2 )
752 double myDestX, myDestY;
753 destPointOnCPMatrix( r,
c, &myDestX, &myDestY );
755 const QgsPointXY myDestPoint( myDestX, myDestY );
756 const QgsPointXY mySrcPoint1 = mCPMatrix[r][
c - 1];
758 const QgsPointXY mySrcPoint3 = mCPMatrix[r][
c + 1];
760 const QgsPointXY mySrcApprox( ( mySrcPoint1.
x() + mySrcPoint3.
x() ) / 2, ( mySrcPoint1.
y() + mySrcPoint3.
y() ) / 2 );
761 if ( !mCPLegalMatrix[r][
c - 1] || !mCPLegalMatrix[r][
c] || !mCPLegalMatrix[r][
c + 1] )
769 const double mySqrDist = myDestApprox.
sqrDist( myDestPoint );
770 if ( mySqrDist > mSqrTolerance )
794 return tr(
"Approximate" );
796 return tr(
"Exact" );
804 QgsDebugMsgLevel( u
"width = %1 height = %2"_s.arg( width ).arg( height ), 4 );
814 if ( !mSrcCRS.isValid() || !mDestCRS.isValid() || mSrcCRS == mDestCRS )
817 return mInput->block( bandNo,
extent, width, height, feedback );
825 ProjectorData pd(
extent, width, height,
mInput, inverseCt, mPrecision, feedback );
830 QgsDebugMsgLevel( u
"srcExtent:\n%1"_s.arg( pd.srcExtent().toString() ), 4 );
831 QgsDebugMsgLevel( u
"srcCols = %1 srcRows = %2"_s.arg( pd.srcCols() ).arg( pd.srcRows() ), 4 );
834 if ( pd.srcRows() <= 0 || pd.srcCols() <= 0 )
840 std::unique_ptr< QgsRasterBlock > inputBlock(
mInput->block( bandNo, pd.srcExtent(), pd.srcCols(), pd.srcRows(), feedback ) );
850 auto outputBlock = std::make_unique< QgsRasterBlock >(
input->dataType(), width, height );
853 if (
input->hasNoDataValue() )
860 return outputBlock.release();
879 for (
int i = 0; i < height; ++i )
883 for (
int j = 0; j < width; ++j )
885 const bool inside = pd.srcRowCol( i, j, &srcRow, &srcCol );
889 const qgssize srcIndex =
static_cast< qgssize >( srcRow ) * pd.srcCols() + srcCol;
892 if ( doNoData &&
input->isNoData( srcRow, srcCol ) )
897 const qgssize destIndex =
static_cast< qgssize >( i ) * width + j;
898 const char *srcBits =
input->constBits( srcIndex );
899 char *destBits = output->
bits( destIndex );
910 memcpy( destBits, srcBits, pixelSize );
915 return outputBlock.release();
920 if ( srcExtent.
isEmpty() || srcXSize <= 0 || srcYSize <= 0 )
930 return extentSize( ct, srcExtent, srcXSize, srcYSize, destExtent, destXSize, destYSize );
935 if ( srcExtent.
isEmpty() || srcXSize <= 0 || srcYSize <= 0 )
947 constexpr int steps = 3;
948 const double srcXStep = srcExtent.
width() / steps;
949 const double srcYStep = srcExtent.
height() / steps;
950 const double srcXRes = srcExtent.
width() / srcXSize;
951 const double srcYRes = srcExtent.
height() / srcYSize;
952 double destXRes = std::numeric_limits<double>::max();
953 double destYRes = std::numeric_limits<double>::max();
957 for (
int i = 0; i < steps; i++ )
959 const double x = srcExtent.
xMinimum() + i * srcXStep;
960 for (
int j = 0; j < steps; j++ )
962 const double y = srcExtent.
yMinimum() + j * srcYStep;
963 const QgsRectangle srcRectangle( x - srcXRes / 2, y - srcYRes / 2, x + srcXRes / 2, y + srcYRes / 2 );
967 if ( destRectangle.
width() > 0 )
969 destXRes = std::min( destXRes, destRectangle.
width() );
970 if ( destRectangle.
width() > maxXRes )
971 maxXRes = destRectangle.
width();
973 if ( destRectangle.
height() > 0 )
975 destYRes = std::min( destYRes, destRectangle.
height() );
976 if ( destRectangle.
height() > maxYRes )
977 maxYRes = destRectangle.
height();
988 if ( destXRes < 0.1 * maxXRes )
990 destXRes = 0.1 * maxXRes;
992 if ( destYRes < 0.1 * maxYRes )
994 destYRes = 0.1 * maxYRes;
996 if ( destXRes == 0 || destExtent.
width() / destXRes > std::numeric_limits<int>::max() )
998 if ( destYRes == 0 || destExtent.
height() / destYRes > std::numeric_limits<int>::max() )
1001 destXSize = std::max( 1,
static_cast< int >( destExtent.
width() / destXRes ) );
1002 destYSize = std::max( 1,
static_cast< int >( destExtent.
height() / destYRes ) );
@ ProviderHintCanPerformProviderResampling
Provider can perform resampling (to be opposed to post rendering resampling).
@ Size
Original data source size (and thus resolution) is known, it is not always available,...
DataType
Raster data types.
@ UnknownDataType
Unknown or unspecified type.
@ Reverse
Reverse/inverse transform (from destination to source).
Represents a coordinate reference system (CRS).
Contains information about the context in which a coordinate transform is executed.
Custom exception class for Coordinate Reference System related exceptions.
bool isCanceled() const
Tells whether the operation has been canceled already.
QString toString(int precision=-1) const
Returns a string representation of the point (x, y) with a preset precision.
double sqrDist(double x, double y) const
Returns the squared distance between this point a specified x, y coordinate.
Feedback object tailored for raster block reading.
bool isValid() const
Returns true if the block is valid (correctly filled with data).
static bool typeIsNumeric(Qgis::DataType type)
Returns true if a data type is numeric.
char * bits(int row, int column)
Returns a pointer to block data.
static int typeSize(Qgis::DataType dataType)
Returns the size in bytes for the specified dataType.
void setIsData(int row, int column)
Remove no data flag on pixel.
void setNoDataValue(double noDataValue)
Sets cell value that will be considered as "no data".
bool setIsNoData(int row, int column)
Set no data on pixel.
QgsRectangle extent() const override=0
Returns the extent of the layer.
virtual Qgis::RasterProviderCapabilities providerCapabilities() const
Returns flags containing the supported capabilities of the data provider.
Base class for processing filters like renderers, reprojector, resampler etc.
virtual Qgis::RasterInterfaceCapabilities capabilities() const
Returns the capabilities supported by the interface.
virtual int xSize() const
Gets raster size.
QgsRasterInterface(QgsRasterInterface *input=nullptr)
QgsRasterInterface * mInput
virtual int ySize() const
virtual QgsRectangle extent() const
Gets the extent of the interface.
virtual QgsRasterInterface * input() const
Current input.
QgsRasterProjector * clone() const override
Clone itself, create deep copy.
bool destExtentSize(const QgsRectangle &srcExtent, int srcXSize, int srcYSize, QgsRectangle &destExtent, int &destXSize, int &destYSize)
Calculate destination extent and size from source extent and size.
static QString precisionLabel(Precision precision)
Qgis::DataType dataType(int bandNo) const override
Returns data type for the band specified by number.
QgsRasterBlock * block(int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback=nullptr) override
Read block of data using given extent and size.
static bool extentSize(const QgsCoordinateTransform &ct, const QgsRectangle &srcExtent, int srcXSize, int srcYSize, QgsRectangle &destExtent, int &destXSize, int &destYSize)
Calculate destination extent and size from source extent and size.
Precision
Precision defines if each pixel is reprojected or approximate reprojection based on an approximation ...
@ Exact
Exact, precise but slow.
@ Approximate
Approximate (default), fast but possibly inaccurate.
Precision precision() const
int bandCount() const override
Gets number of bands.
Q_DECL_DEPRECATED void setCrs(const QgsCoordinateReferenceSystem &srcCRS, const QgsCoordinateReferenceSystem &destCRS, int srcDatumTransform=-1, int destDatumTransform=-1)
Sets the source and destination CRS.
A rectangle specified with double values.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
#define Q_NOWARN_DEPRECATED_POP
unsigned long long qgssize
Qgssize is used instead of size_t, because size_t is stdlib type, unknown by SIP, and it would be har...
#define Q_NOWARN_DEPRECATED_PUSH
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)