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;
 
 
  155int 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();
 
 
  243int 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  const 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 )
 
 
  420void 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  const 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    const 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;
 
 
  522int 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    const 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    const double X = ( x[i] * H[0] + y[i] * H[1] + H[2] ) / Z;
 
  559    const 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.