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 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 )
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 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;
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 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;