17#include "moc_qgsgcptransformer.cpp"
53 return QObject::tr(
"Linear" );
55 return QObject::tr(
"Helmert" );
57 return QObject::tr(
"Polynomial 1" );
59 return QObject::tr(
"Polynomial 2" );
61 return QObject::tr(
"Polynomial 3" );
63 return QObject::tr(
"Thin Plate Spline (TPS)" );
65 return QObject::tr(
"Projective" );
67 return QObject::tr(
"Not set" );
96 std::unique_ptr<QgsGcpTransformerInterface> transformer(
create(
method ) );
100 if ( !transformer->updateParametersFromGcps( sourceCoordinates, destinationCoordinates ) )
103 return transformer.release();
113 origin = mParameters.origin;
114 scaleX = mParameters.scaleX;
115 scaleY = mParameters.scaleY;
121 std::unique_ptr<QgsLinearGeorefTransform> res = std::make_unique<QgsLinearGeorefTransform>();
122 res->mParameters = mParameters;
123 return res.release();
131 mParameters.invertYAxis = invertYAxis;
132 QgsLeastSquares::linear( sourceCoordinates, destinationCoordinates, mParameters.origin, mParameters.scaleX, mParameters.scaleY );
143 return QgsLinearGeorefTransform::linearTransform;
148 return (
void * ) &mParameters;
156int QgsLinearGeorefTransform::linearTransform(
void *pTransformerArg,
int bDstToSrc,
int nPointCount,
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() || std::fabs( t->scaleY ) < std::numeric_limits<double>::epsilon() )
177 for (
int i = 0; i < nPointCount; ++i )
179 panSuccess[i] =
false;
183 for (
int i = 0; i < nPointCount; ++i )
185 x[i] = ( x[i] - t->origin.x() ) / t->scaleX;
186 y[i] = ( y[i] - t->origin.y() ) / ( ( t->invertYAxis ? -1 : 1 ) * t->scaleY );
187 panSuccess[i] =
true;
202 mHelmertParameters.invertYAxis = invertYAxis;
203 QgsLeastSquares::helmert( sourceCoordinates, destinationCoordinates, mHelmertParameters.origin, mHelmertParameters.scale, mHelmertParameters.angle );
214 return QgsHelmertGeorefTransform::helmertTransform;
219 return (
void * ) &mHelmertParameters;
229 origin = mHelmertParameters.origin;
230 scale = mHelmertParameters.scale;
231 rotation = mHelmertParameters.angle;
237 std::unique_ptr<QgsHelmertGeorefTransform> res = std::make_unique<QgsHelmertGeorefTransform>();
238 res->mHelmertParameters = mHelmertParameters;
239 return res.release();
242int QgsHelmertGeorefTransform::helmertTransform(
void *pTransformerArg,
int bDstToSrc,
int nPointCount,
double *x,
double *y,
double *z,
int *panSuccess )
245 const HelmertParameters *t =
static_cast<const HelmertParameters *
>( pTransformerArg );
249 double a = std::cos( t->angle );
250 double b = std::sin( t->angle );
251 const double x0 = t->origin.x();
252 const double y0 = t->origin.y();
253 const double s = t->scale;
258 for (
int i = 0; i < nPointCount; ++i )
260 const double xT = x[i];
261 const double yT = y[i];
263 if ( t->invertYAxis )
269 x[i] = x0 + ( a * xT + b * yT );
270 y[i] = y0 + ( b * xT - a * yT );
274 x[i] = x0 + ( a * xT - b * yT );
275 y[i] = y0 + ( b * xT + a * yT );
277 panSuccess[i] =
true;
283 if ( std::fabs( s ) < std::numeric_limits<double>::epsilon() )
285 for (
int i = 0; i < nPointCount; ++i )
287 panSuccess[i] =
false;
293 for (
int i = 0; i < nPointCount; ++i )
295 const double xT = x[i] - x0;
296 const double yT = y[i] - y0;
297 if ( t->invertYAxis )
301 x[i] = a * xT + b * yT;
302 y[i] = b * xT - a * yT;
306 x[i] = a * xT + b * yT;
307 y[i] = -b * xT + a * yT;
309 panSuccess[i] =
true;
320 : mPolynomialOrder( std::min( 3u, polynomialOrder ) )
321 , mIsTPSTransform( useTPS )
332 std::unique_ptr<QgsGDALGeorefTransform> res = std::make_unique<QgsGDALGeorefTransform>( mIsTPSTransform, mPolynomialOrder );
333 res->updateParametersFromGcps( mSourceCoords, mDestCoordinates, mInvertYAxis );
334 return res.release();
339 mSourceCoords = sourceCoordinates;
340 mDestCoordinates = destinationCoordinates;
341 mInvertYAxis = invertYAxis;
343 assert( sourceCoordinates.size() == destinationCoordinates.size() );
344 if ( sourceCoordinates.size() != destinationCoordinates.size() )
346 const int n = sourceCoordinates.size();
348 GDAL_GCP *GCPList =
new GDAL_GCP[n];
349 for (
int i = 0; i < n; i++ )
351 GCPList[i].pszId =
new char[20];
352 snprintf( GCPList[i].pszId, 19,
"gcp%i", i );
353 GCPList[i].pszInfo =
nullptr;
354 GCPList[i].dfGCPPixel = sourceCoordinates[i].x();
355 GCPList[i].dfGCPLine = ( mInvertYAxis ? -1 : 1 ) * sourceCoordinates[i].y();
356 GCPList[i].dfGCPX = destinationCoordinates[i].x();
357 GCPList[i].dfGCPY = destinationCoordinates[i].y();
358 GCPList[i].dfGCPZ = 0;
362 if ( mIsTPSTransform )
363 mGDALTransformerArgs = GDALCreateTPSTransformer( n, GCPList,
false );
365 mGDALTransformerArgs = GDALCreateGCPTransformer( n, GCPList, mPolynomialOrder,
false );
367 for (
int i = 0; i < n; i++ )
369 delete[] GCPList[i].pszId;
373 return nullptr != mGDALTransformerArgs;
378 if ( mIsTPSTransform )
381 return ( ( mPolynomialOrder + 2 ) * ( mPolynomialOrder + 1 ) ) / 2;
387 if ( !mGDALTransformerArgs )
390 if ( mIsTPSTransform )
391 return GDALTPSTransform;
393 return GDALGCPTransform;
398 return mGDALTransformerArgs;
403 if ( mIsTPSTransform )
406 switch ( mPolynomialOrder )
418void QgsGDALGeorefTransform::destroyGdalArgs()
420 if ( mGDALTransformerArgs )
422 if ( mIsTPSTransform )
423 GDALDestroyTPSTransformer( mGDALTransformerArgs );
425 GDALDestroyGCPTransformer( mGDALTransformerArgs );
439 std::unique_ptr<QgsProjectiveGeorefTransform> res = std::make_unique<QgsProjectiveGeorefTransform>();
440 res->mParameters = mParameters;
441 return res.release();
452 QVector<QgsPointXY> flippedPixelCoords;
453 flippedPixelCoords.reserve( sourceCoordinates.size() );
454 for (
const QgsPointXY &coord : sourceCoordinates )
456 flippedPixelCoords <<
QgsPointXY( coord.x(), -coord.y() );
467 double *H = mParameters.H;
470 adjoint[0] = H[4] * H[8] - H[5] * H[7];
471 adjoint[1] = -H[1] * H[8] + H[2] * H[7];
472 adjoint[2] = H[1] * H[5] - H[2] * H[4];
474 adjoint[3] = -H[3] * H[8] + H[5] * H[6];
475 adjoint[4] = H[0] * H[8] - H[2] * H[6];
476 adjoint[5] = -H[0] * H[5] + H[2] * H[3];
478 adjoint[6] = H[3] * H[7] - H[4] * H[6];
479 adjoint[7] = -H[0] * H[7] + H[1] * H[6];
480 adjoint[8] = H[0] * H[4] - H[1] * H[3];
482 const double det = H[0] * adjoint[0] + H[3] * adjoint[1] + H[6] * adjoint[2];
484 if ( std::fabs( det ) < 1024.0 * std::numeric_limits<double>::epsilon() )
486 mParameters.hasInverse =
false;
490 mParameters.hasInverse =
true;
491 const double oo_det = 1.0 / det;
492 for (
int i = 0; i < 9; i++ )
494 mParameters.Hinv[i] = adjoint[i] * oo_det;
507 return QgsProjectiveGeorefTransform::projectiveTransform;
512 return (
void * ) &mParameters;
520int QgsProjectiveGeorefTransform::projectiveTransform(
void *pTransformerArg,
int bDstToSrc,
int nPointCount,
double *x,
double *y,
double *z,
int *panSuccess )
523 ProjectiveParameters *t =
static_cast<ProjectiveParameters *
>( pTransformerArg );
534 if ( !t->hasInverse )
536 for (
int i = 0; i < nPointCount; ++i )
538 panSuccess[i] =
false;
546 for (
int i = 0; i < nPointCount; ++i )
548 const double Z = x[i] * H[6] + y[i] * H[7] + H[8];
550 if ( std::fabs( Z ) < 1024.0 * std::numeric_limits<double>::epsilon() )
552 panSuccess[i] =
false;
555 const double X = ( x[i] * H[0] + y[i] * H[1] + H[2] ) / Z;
556 const double Y = ( x[i] * H[3] + y[i] * H[4] + H[5] ) / Z;
561 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.