52       return QObject::tr( 
"Linear" );
 
   54       return QObject::tr( 
"Helmert" );
 
   56       return QObject::tr( 
"Polynomial 1" );
 
   58       return QObject::tr( 
"Polynomial 2" );
 
   60       return QObject::tr( 
"Polynomial 3" );
 
   62       return QObject::tr( 
"Thin Plate Spline (TPS)" );
 
   64       return QObject::tr( 
"Projective" );
 
   66       return QObject::tr( 
"Not set" );
 
   95   std::unique_ptr< QgsGcpTransformerInterface > transformer( 
create( 
method ) );
 
   99   if ( !transformer->updateParametersFromGcps( sourceCoordinates, destinationCoordinates ) )
 
  102   return transformer.release();
 
  112   origin = mParameters.origin;
 
  113   scaleX = mParameters.scaleX;
 
  114   scaleY = mParameters.scaleY;
 
  120   std::unique_ptr< QgsLinearGeorefTransform > res = std::make_unique< QgsLinearGeorefTransform >();
 
  121   res->mParameters = mParameters;
 
  122   return res.release();
 
  130   mParameters.invertYAxis = invertYAxis;
 
  131   QgsLeastSquares::linear( sourceCoordinates, destinationCoordinates, mParameters.origin, mParameters.scaleX, mParameters.scaleY );
 
  142   return QgsLinearGeorefTransform::linearTransform;
 
  147   return ( 
void * )&mParameters;
 
  155 int QgsLinearGeorefTransform::linearTransform( 
void *pTransformerArg, 
int bDstToSrc, 
int nPointCount,
 
  156     double *x, 
double *y, 
double *z, 
int *panSuccess )
 
  159   LinearParameters *t = 
static_cast<LinearParameters *
>( pTransformerArg );
 
  165     for ( 
int i = 0; i < nPointCount; ++i )
 
  167       x[i] = x[i] * t->scaleX + t->origin.x();
 
  168       y[i] = ( t->invertYAxis ? -1 : 1 ) * y[i] * t->scaleY + t->origin.y();
 
  169       panSuccess[i] = 
true;
 
  175     if ( std::fabs( t->scaleX ) < std::numeric_limits<double>::epsilon() ||
 
  176          std::fabs( t->scaleY ) < std::numeric_limits<double>::epsilon() )
 
  178       for ( 
int i = 0; i < nPointCount; ++i )
 
  180         panSuccess[i] = 
false;
 
  184     for ( 
int i = 0; i < nPointCount; ++i )
 
  186       x[i] = ( x[i] - t->origin.x() ) / t->scaleX;
 
  187       y[i] = ( y[i] - t->origin.y() ) / ( ( t->invertYAxis ? -1 : 1 ) * t->scaleY );
 
  188       panSuccess[i] = 
true;
 
  203   mHelmertParameters.invertYAxis = invertYAxis;
 
  204   QgsLeastSquares::helmert( sourceCoordinates, destinationCoordinates, mHelmertParameters.origin, mHelmertParameters.scale, mHelmertParameters.angle );
 
  215   return QgsHelmertGeorefTransform::helmertTransform;
 
  220   return ( 
void * )&mHelmertParameters;
 
  230   origin = mHelmertParameters.origin;
 
  231   scale = mHelmertParameters.scale;
 
  232   rotation = mHelmertParameters.angle;
 
  238   std::unique_ptr< QgsHelmertGeorefTransform > res = std::make_unique< QgsHelmertGeorefTransform >();
 
  239   res->mHelmertParameters = mHelmertParameters;
 
  240   return res.release();
 
  243 int QgsHelmertGeorefTransform::helmertTransform( 
void *pTransformerArg, 
int bDstToSrc, 
int nPointCount,
 
  244     double *x, 
double *y, 
double *z, 
int *panSuccess )
 
  247   const HelmertParameters *t = 
static_cast< const HelmertParameters *
>( pTransformerArg );
 
  251   double a = std::cos( t->angle );
 
  252   double b = std::sin( t->angle );
 
  253   const double x0 = t->origin.x();
 
  254   const double y0 = t->origin.y();
 
  255   const double s = t->scale;
 
  260     for ( 
int i = 0; i < nPointCount; ++i )
 
  262       const double xT = x[i];
 
  263       const double yT = y[i];
 
  265       if ( t->invertYAxis )
 
  271         x[i] = x0 + ( a * xT + b * yT );
 
  272         y[i] = y0 + ( b * xT - a * yT );
 
  276         x[i] = x0 + ( a * xT - b * yT );
 
  277         y[i] = y0 + ( b * xT + a * yT );
 
  279       panSuccess[i] = 
true;
 
  285     if ( std::fabs( s ) < std::numeric_limits<double>::epsilon() )
 
  287       for ( 
int i = 0; i < nPointCount; ++i )
 
  289         panSuccess[i] = 
false;
 
  295     for ( 
int i = 0; i < nPointCount; ++i )
 
  297       const double xT = x[i] - x0;
 
  298       const double yT = y[i] - y0;
 
  299       if ( t->invertYAxis )
 
  303         x[i] = a * xT + b * yT;
 
  304         y[i] = b * xT - a * yT;
 
  308         x[i] = a * xT + b * yT;
 
  309         y[i] = -b * xT + a * yT;
 
  311       panSuccess[i] = 
true;
 
  322   : mPolynomialOrder( std::min( 3u, polynomialOrder ) )
 
  323   , mIsTPSTransform( useTPS )
 
  334   std::unique_ptr< QgsGDALGeorefTransform > res = std::make_unique< QgsGDALGeorefTransform >( mIsTPSTransform, mPolynomialOrder );
 
  335   res->updateParametersFromGcps( mSourceCoords, mDestCoordinates, mInvertYAxis );
 
  336   return res.release();
 
  341   mSourceCoords = sourceCoordinates;
 
  342   mDestCoordinates = destinationCoordinates;
 
  343   mInvertYAxis = invertYAxis;
 
  345   assert( sourceCoordinates.size() == destinationCoordinates.size() );
 
  346   if ( sourceCoordinates.size() != destinationCoordinates.size() )
 
  348   int n = sourceCoordinates.size();
 
  350   GDAL_GCP *GCPList = 
new GDAL_GCP[n];
 
  351   for ( 
int i = 0; i < n; i++ )
 
  353     GCPList[i].pszId = 
new char[20];
 
  354     snprintf( GCPList[i].pszId, 19, 
"gcp%i", i );
 
  355     GCPList[i].pszInfo = 
nullptr;
 
  356     GCPList[i].dfGCPPixel = sourceCoordinates[i].x();
 
  357     GCPList[i].dfGCPLine  = ( mInvertYAxis ? -1 : 1 ) * sourceCoordinates[i].y();
 
  358     GCPList[i].dfGCPX = destinationCoordinates[i].x();
 
  359     GCPList[i].dfGCPY = destinationCoordinates[i].y();
 
  360     GCPList[i].dfGCPZ = 0;
 
  364   if ( mIsTPSTransform )
 
  365     mGDALTransformerArgs = GDALCreateTPSTransformer( n, GCPList, 
false );
 
  367     mGDALTransformerArgs = GDALCreateGCPTransformer( n, GCPList, mPolynomialOrder, 
false );
 
  369   for ( 
int i = 0; i < n; i++ )
 
  371     delete [] GCPList[i].pszId;
 
  375   return nullptr != mGDALTransformerArgs;
 
  380   if ( mIsTPSTransform )
 
  383     return ( ( mPolynomialOrder + 2 ) * ( mPolynomialOrder + 1 ) ) / 2;
 
  389   if ( !mGDALTransformerArgs )
 
  392   if ( mIsTPSTransform )
 
  393     return GDALTPSTransform;
 
  395     return GDALGCPTransform;
 
  400   return mGDALTransformerArgs;
 
  405   if ( mIsTPSTransform )
 
  408   switch ( mPolynomialOrder )
 
  420 void QgsGDALGeorefTransform::destroyGdalArgs()
 
  422   if ( mGDALTransformerArgs )
 
  424     if ( mIsTPSTransform )
 
  425       GDALDestroyTPSTransformer( mGDALTransformerArgs );
 
  427       GDALDestroyGCPTransformer( mGDALTransformerArgs );
 
  441   std::unique_ptr< QgsProjectiveGeorefTransform > res = std::make_unique< QgsProjectiveGeorefTransform >();
 
  442   res->mParameters = mParameters;
 
  443   return res.release();
 
  454     QVector<QgsPointXY> flippedPixelCoords;
 
  455     flippedPixelCoords.reserve( sourceCoordinates.size() );
 
  456     for ( 
const QgsPointXY &coord : sourceCoordinates )
 
  458       flippedPixelCoords << 
QgsPointXY( coord.x(), -coord.y() );
 
  469   double *H = mParameters.H;
 
  472   adjoint[0] = H[4] * H[8] - H[5] * H[7];
 
  473   adjoint[1] = -H[1] * H[8] + H[2] * H[7];
 
  474   adjoint[2] = H[1] * H[5] - H[2] * H[4];
 
  476   adjoint[3] = -H[3] * H[8] + H[5] * H[6];
 
  477   adjoint[4] = H[0] * H[8] - H[2] * H[6];
 
  478   adjoint[5] = -H[0] * H[5] + H[2] * H[3];
 
  480   adjoint[6] = H[3] * H[7] - H[4] * H[6];
 
  481   adjoint[7] = -H[0] * H[7] + H[1] * H[6];
 
  482   adjoint[8] = H[0] * H[4] - H[1] * H[3];
 
  484   double det = H[0] * adjoint[0] + H[3] * adjoint[1] + H[6] * adjoint[2];
 
  486   if ( std::fabs( det ) < 1024.0 * std::numeric_limits<double>::epsilon() )
 
  488     mParameters.hasInverse = 
false;
 
  492     mParameters.hasInverse = 
true;
 
  493     double oo_det = 1.0 / det;
 
  494     for ( 
int i = 0; i < 9; i++ )
 
  496       mParameters.Hinv[i] = adjoint[i] * oo_det;
 
  509   return QgsProjectiveGeorefTransform::projectiveTransform;
 
  514   return ( 
void * )&mParameters;
 
  522 int QgsProjectiveGeorefTransform::projectiveTransform( 
void *pTransformerArg, 
int bDstToSrc, 
int nPointCount,
 
  523     double *x, 
double *y, 
double *z, 
int *panSuccess )
 
  526   ProjectiveParameters *t = 
static_cast<ProjectiveParameters *
>( pTransformerArg );
 
  537     if ( !t->hasInverse )
 
  539       for ( 
int i = 0; i < nPointCount; ++i )
 
  541         panSuccess[i] = 
false;
 
  549   for ( 
int i = 0; i < nPointCount; ++i )
 
  551     double Z = x[i] * H[6] + y[i] * H[7] + H[8];
 
  553     if ( std::fabs( Z ) < 1024.0 * std::numeric_limits<double>::epsilon() )
 
  555       panSuccess[i] = 
false;
 
  558     double X = ( x[i] * H[0] + y[i] * H[1] + H[2] ) / Z;
 
  559     double Y = ( x[i] * H[3] + y[i] * H[4] + H[5] ) / Z;
 
  564     panSuccess[i] = 
true;
 
static void helmert(const QVector< QgsPointXY > &sourceCoordinates, const QVector< QgsPointXY > &destinationCoordinates, QgsPointXY &origin, double &pixelSize, double &rotation)
Transforms the point at origin in-place, using a helmert transformation calculated from the list of s...
static void projective(const QVector< QgsPointXY > &sourceCoordinates, const QVector< QgsPointXY > &destinationCoordinates, double H[9])
Calculates projective parameters from the list of source and destination Ground Control Points (GCPs)...
static void linear(const QVector< QgsPointXY > &sourceCoordinates, const QVector< QgsPointXY > &destinationCoordinates, QgsPointXY &origin, double &pixelXSize, double &pixelYSize)
Transforms the point at origin in-place, using a linear transformation calculated from the list of so...
A class to represent a 2D point.