1 /***************************************************************************
2     qgsgeoreftransform.h - Encapsulates GCP-based parameter estimation and
3     reprojection for different transformation models.
4      --------------------------------------
5     Date                 : 18-Feb-2009
6     Copyright            : (c) 2009 by Manuel Massing
7     Email                : m.massing at warped-space.de
8  ***************************************************************************
9  *                                                                         *
10  *   This program is free software; you can redistribute it and/or modify  *
11  *   it under the terms of the GNU General Public License as published by  *
12  *   the Free Software Foundation; either version 2 of the License, or     *
13  *   (at your option) any later version.                                   *
14  *                                                                         *
15  ***************************************************************************/
16 
17 #ifndef QGSGEOREFTRANSFORM_H
18 #define QGSGEOREFTRANSFORM_H
19 
20 #include <gdal_alg.h>
21 #include "qgspoint.h"
22 #include "qgsgcptransformer.h"
23 #include "qgsrasterchangecoords.h"
24 
25 /**
26  * \brief Transform class for different gcp-based transform methods.
27  *
28  * Select transform type via \ref selectTransformParametrisation.
29  * Initialize and update parameters via \ref updateParametersFromGCPs.
30  * An initialized instance then provides transform functions and GDALTransformer entry points
31  * for warping and coordinate remapping.
32  *
33  * Delegates to concrete implementations of \ref QgsGeorefInterface. For exception safety,
34  * this is preferred over using the subclasses directly.
35  */
36 class QgsGeorefTransform : public QgsGcpTransformerInterface
37 {
38   public:
39 
40     explicit QgsGeorefTransform( TransformMethod parametrisation );
41     QgsGeorefTransform();
42     ~QgsGeorefTransform() override;
43 
44     /**
45      * Switches the used transform type to the given parametrisation.
46      */
47     void selectTransformParametrisation( TransformMethod parametrisation );
48 
49     /**
50      * Setting the mRasterChangeCoords for change type coordinate(map for pixel).
51      */
52     void setRasterChangeCoords( const QString &fileRaster );
53 
54     //! \returns Whether has Coordinate Reference Systems in image
hasCrs()55     bool hasCrs() const { return mRasterChangeCoords.hasCrs(); }
56 
57     //! \returns Coordinates of image
toColumnLine(const QgsPointXY & pntMap)58     QgsPointXY toColumnLine( const QgsPointXY &pntMap ) { return mRasterChangeCoords.toColumnLine( pntMap ); }
59 
60     //! \returns Bounding box of image(transform to coordinate of Map or Image )
getBoundingBox(const QgsRectangle & rect,bool toPixel)61     QgsRectangle getBoundingBox( const QgsRectangle &rect, bool toPixel ) { return mRasterChangeCoords.getBoundingBox( rect, toPixel ); }
62 
63     //! \brief The transform parametrisation currently in use.
64     TransformMethod transformParametrisation() const;
65 
66     //! True for linear, Helmert, first order polynomial
67     bool providesAccurateInverseTransformation() const;
68 
69     //! \returns whether the parameters of this transform have been initialized by \ref updateParametersFromGCPs
70     bool parametersInitialized() const;
71 
72     QgsGcpTransformerInterface *clone() const override;
73     bool updateParametersFromGcps( const QVector<QgsPointXY> &sourceCoordinates, const QVector<QgsPointXY> &destinationCoordinates, bool invertYAxis = false ) override;
74     int minimumGcpCount() const override;
75     TransformMethod method() const override;
76     GDALTransformerFunc GDALTransformer() const override;
77     void *GDALTransformerArgs() const override;
78 
79     /**
80      * \brief Transform from pixel coordinates to georeferenced coordinates.
81      *
82      * \note Negative y-axis points down in raster CS.
83      */
84     bool transformRasterToWorld( const QgsPointXY &raster, QgsPointXY &world );
85 
86     /**
87      * \brief Transform from referenced coordinates to raster coordinates.
88      *
89      * \note Negative y-axis points down in raster CS.
90      */
91     bool transformWorldToRaster( const QgsPointXY &world, QgsPointXY &raster );
92 
93     /**
94      * \brief Transforms from raster to world if rasterToWorld is TRUE,
95      * \brief or from world to raster when rasterToWorld is FALSE.
96      *
97      * \note Negative y-axis points down in raster CS.
98      */
99     bool transform( const QgsPointXY &src, QgsPointXY &dst, bool rasterToWorld );
100 
101     //! \brief Returns origin and scale if this is a linear transform, fails otherwise.
102     bool getLinearOriginScale( QgsPointXY &origin, double &scaleX, double &scaleY ) const;
103 
104     //! \brief Returns origin, scale and rotation for linear and helmert transform, fails otherwise.
105     bool getOriginScaleRotation( QgsPointXY &origin, double &scaleX, double &scaleY, double &rotation ) const;
106 
107   private:
108     // shallow copy constructor
109     QgsGeorefTransform( const QgsGeorefTransform &other );
110     QgsGeorefTransform &operator= ( const QgsGeorefTransform & ) = delete;
111 
112     // convenience wrapper around GDALTransformerFunc
113     bool gdal_transform( const QgsPointXY &src, QgsPointXY &dst, int dstToSrc ) const;
114 
115     QVector<QgsPointXY> mSourceCoordinates;
116     QVector<QgsPointXY> mDestinationCoordinates;
117     bool mInvertYAxis = false;
118 
119     std::unique_ptr< QgsGcpTransformerInterface > mGeorefTransformImplementation;
120 
121     TransformMethod mTransformParametrisation = TransformMethod::InvalidTransform;
122     bool mParametersInitialized = false;
123     QgsRasterChangeCoords mRasterChangeCoords;
124 };
125 
126 #endif //QGSGEOREFTRANSFORM_H
127