Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsgcptransformer.h
3 : : --------------------------------------
4 : : Date : 18-Feb-2009
5 : : Copyright : (c) 2009 by Manuel Massing
6 : : Email : m.massing at warped-space.de
7 : : ***************************************************************************
8 : : * *
9 : : * This program is free software; you can redistribute it and/or modify *
10 : : * it under the terms of the GNU General Public License as published by *
11 : : * the Free Software Foundation; either version 2 of the License, or *
12 : : * (at your option) any later version. *
13 : : * *
14 : : ***************************************************************************/
15 : :
16 : : #ifndef QGSGCPTRANSFORMER_H
17 : : #define QGSGCPTRANSFORMER_H
18 : :
19 : : #include <gdal_alg.h>
20 : : #include "qgspoint.h"
21 : : #include "qgis_analysis.h"
22 : : #include "qgis_sip.h"
23 : :
24 : : /**
25 : : * \ingroup analysis
26 : : * \brief An interface for Ground Control Points (GCP) based transformations.
27 : : *
28 : : * QgsGcpTransformerInterface implementations are able to transform point locations
29 : : * based on a transformation method and a list of GCPs.
30 : : *
31 : : * \since QGIS 3.20
32 : : */
33 : : class ANALYSIS_EXPORT QgsGcpTransformerInterface SIP_ABSTRACT
34 : : {
35 : : public:
36 : :
37 : : /**
38 : : * Available transformation methods.
39 : : */
40 : : enum class TransformMethod : int
41 : : {
42 : : Linear, //!< Linear transform
43 : : Helmert, //!< Helmert transform
44 : : PolynomialOrder1, //!< Polynomial order 1
45 : : PolynomialOrder2, //!< Polyonmial order 2
46 : : PolynomialOrder3, //!< Polynomial order
47 : : ThinPlateSpline, //!< Thin plate splines
48 : : Projective, //!< Projective
49 : : InvalidTransform = 65535 //!< Invalid transform
50 : : };
51 : :
52 : : //! Constructor for QgsGcpTransformerInterface
53 : 0 : QgsGcpTransformerInterface() = default;
54 : :
55 : 0 : virtual ~QgsGcpTransformerInterface() = default;
56 : :
57 : : //! QgsGcpTransformerInterface cannot be copied - use clone() instead.
58 : : QgsGcpTransformerInterface( const QgsGcpTransformerInterface &other ) = delete;
59 : :
60 : : //! QgsGcpTransformerInterface cannot be copied - use clone() instead.
61 : : QgsGcpTransformerInterface &operator=( const QgsGcpTransformerInterface &other ) = delete;
62 : :
63 : : /**
64 : : * Clones the transformer, returning a new copy of the transformer with the same
65 : : * parameters as this one.
66 : : *
67 : : * Caller takes ownership of the returned object.
68 : : */
69 : : virtual QgsGcpTransformerInterface *clone() const = 0 SIP_FACTORY;
70 : :
71 : : /**
72 : : * Fits transformation parameters using the specified Ground Control Points (GCPs) lists of source and destination coordinates.
73 : : *
74 : : * If \a invertYAxis is set to TRUE then the y-axis of source coordinates will be inverted, e.g. to allow for transformation of raster layers
75 : : * with ascending top-to-bottom vertical axis coordinates.
76 : : *
77 : : * \returns TRUE on success, FALSE on failure
78 : : */
79 : : virtual bool updateParametersFromGcps( const QVector<QgsPointXY> &sourceCoordinates, const QVector<QgsPointXY> &destinationCoordinates, bool invertYAxis = false ) = 0;
80 : :
81 : : /**
82 : : * Returns the minimum number of Ground Control Points (GCPs) required for parameter fitting.
83 : : */
84 : : virtual int minimumGcpCount() const = 0;
85 : :
86 : : /**
87 : : * Returns the transformation method.
88 : : */
89 : : virtual TransformMethod method() const = 0;
90 : :
91 : : /**
92 : : * Transforms the point (\a x, \a y) from source to destination coordinates.
93 : : *
94 : : * If \a inverseTransform is set to TRUE, the point will be transformed from the destination to the source.
95 : : *
96 : : * \returns TRUE if transformation was successful.
97 : : */
98 : : bool transform( double &x SIP_INOUT, double &y SIP_INOUT, bool inverseTransform = false ) const;
99 : :
100 : : /**
101 : : * Returns a translated string representing the specified transform \a method.
102 : : */
103 : : static QString methodToString( TransformMethod method );
104 : :
105 : : /**
106 : : * Creates a new QgsGcpTransformerInterface subclass representing the specified transform \a method.
107 : : *
108 : : * Caller takes ownership of the returned object.
109 : : */
110 : : static QgsGcpTransformerInterface *create( TransformMethod method ) SIP_FACTORY;
111 : :
112 : : /**
113 : : * Creates a new QgsGcpTransformerInterface subclass representing the specified transform \a method, initialized
114 : : * using the given lists of source and destination coordinates.
115 : : *
116 : : * If the parameters cannot be fit to a transform NULLPTR will be returned.
117 : : *
118 : : * Caller takes ownership of the returned object.
119 : : */
120 : : static QgsGcpTransformerInterface *createFromParameters( TransformMethod method, const QVector<QgsPointXY> &sourceCoordinates, const QVector<QgsPointXY> &destinationCoordinates ) SIP_FACTORY;
121 : :
122 : : #ifndef SIP_RUN
123 : :
124 : : /**
125 : : * Returns function pointer to the GDALTransformer function.
126 : : */
127 : : virtual GDALTransformerFunc GDALTransformer() const = 0;
128 : :
129 : : /**
130 : : * Returns pointer to the GDALTransformer arguments.
131 : : */
132 : : virtual void *GDALTransformerArgs() const = 0;
133 : : #endif
134 : :
135 : : private:
136 : :
137 : : #ifdef SIP_RUN
138 : : QgsGcpTransformerInterface( const QgsGcpTransformerInterface &other )
139 : : #endif
140 : : };
141 : :
142 : : /**
143 : : * \brief A simple transform which is parametrized by a translation and anistotropic scale.
144 : : * \ingroup analysis
145 : : * \note Not available in Python bindings
146 : : * \since QGIS 3.20
147 : : */
148 : 0 : class ANALYSIS_EXPORT QgsLinearGeorefTransform : public QgsGcpTransformerInterface SIP_SKIP
149 : : {
150 : : public:
151 : :
152 : : //! Constructor for QgsLinearGeorefTransform
153 : 0 : QgsLinearGeorefTransform() = default;
154 : :
155 : : /**
156 : : * Returns the origin and scale for the transform.
157 : : */
158 : : bool getOriginScale( QgsPointXY &origin, double &scaleX, double &scaleY ) const;
159 : :
160 : : QgsGcpTransformerInterface *clone() const override;
161 : : bool updateParametersFromGcps( const QVector<QgsPointXY> &sourceCoordinates, const QVector<QgsPointXY> &destinationCoordinates, bool invertYAxis = false ) override;
162 : : int minimumGcpCount() const override;
163 : : GDALTransformerFunc GDALTransformer() const override;
164 : : void *GDALTransformerArgs() const override;
165 : : TransformMethod method() const override;
166 : :
167 : : private:
168 : 0 : struct LinearParameters
169 : : {
170 : : QgsPointXY origin;
171 : 0 : double scaleX = 1;
172 : 0 : double scaleY = 1;
173 : 0 : bool invertYAxis = false;
174 : : } mParameters;
175 : :
176 : : static int linearTransform( void *pTransformerArg, int bDstToSrc, int nPointCount,
177 : : double *x, double *y, double *z, int *panSuccess );
178 : :
179 : : };
180 : :
181 : : /**
182 : : * \brief 2-dimensional helmert transform, parametrised by isotropic scale, rotation angle and translation.
183 : : * \ingroup analysis
184 : : * \note Not available in Python bindings
185 : : * \since QGIS 3.20
186 : : */
187 : 0 : class ANALYSIS_EXPORT QgsHelmertGeorefTransform : public QgsGcpTransformerInterface SIP_SKIP
188 : : {
189 : : public:
190 : :
191 : : //! Constructor for QgsHelmertGeorefTransform
192 : 0 : QgsHelmertGeorefTransform() = default;
193 : :
194 : : /**
195 : : * Returns the origin, scale and rotation for the transform.
196 : : */
197 : : bool getOriginScaleRotation( QgsPointXY &origin, double &scale, double &rotation ) const;
198 : :
199 : : QgsGcpTransformerInterface *clone() const override;
200 : : bool updateParametersFromGcps( const QVector<QgsPointXY> &sourceCoordinates, const QVector<QgsPointXY> &destinationCoordinates, bool invertYAxis = false ) override;
201 : : int minimumGcpCount() const override;
202 : : GDALTransformerFunc GDALTransformer() const override;
203 : : void *GDALTransformerArgs() const override;
204 : : TransformMethod method() const override;
205 : :
206 : : private:
207 : :
208 : 0 : struct HelmertParameters
209 : : {
210 : : QgsPointXY origin;
211 : : double scale;
212 : : double angle;
213 : 0 : bool invertYAxis = false;
214 : : };
215 : : HelmertParameters mHelmertParameters;
216 : :
217 : : static int helmertTransform( void *pTransformerArg, int bDstToSrc, int nPointCount,
218 : : double *x, double *y, double *z, int *panSuccess );
219 : :
220 : : };
221 : :
222 : : /**
223 : : * \brief Interface to gdal thin plate splines and 1st/2nd/3rd order polynomials.
224 : : * \ingroup analysis
225 : : * \note Not available in Python bindings
226 : : * \since QGIS 3.20
227 : : */
228 : : class ANALYSIS_EXPORT QgsGDALGeorefTransform : public QgsGcpTransformerInterface SIP_SKIP
229 : : {
230 : : public:
231 : :
232 : : //! Constructor for QgsGDALGeorefTransform
233 : : QgsGDALGeorefTransform( bool useTPS, unsigned int polynomialOrder );
234 : : ~QgsGDALGeorefTransform() override;
235 : :
236 : : QgsGcpTransformerInterface *clone() const override;
237 : : bool updateParametersFromGcps( const QVector<QgsPointXY> &sourceCoordinates, const QVector<QgsPointXY> &destinationCoordinates, bool invertYAxis = false ) override;
238 : : int minimumGcpCount() const override;
239 : : GDALTransformerFunc GDALTransformer() const override;
240 : : void *GDALTransformerArgs() const override;
241 : : TransformMethod method() const override;
242 : :
243 : : private:
244 : : void destroyGdalArgs();
245 : :
246 : : QVector<QgsPointXY> mSourceCoords;
247 : : QVector<QgsPointXY> mDestCoordinates;
248 : : bool mInvertYAxis = false;
249 : :
250 : : const int mPolynomialOrder;
251 : : const bool mIsTPSTransform;
252 : :
253 : : void *mGDALTransformerArgs = nullptr;
254 : :
255 : : };
256 : :
257 : : /**
258 : : * \brief A planar projective transform, expressed by a homography.
259 : : *
260 : : * Implements model fitting which minimizes algebraic error using total least squares.
261 : : *
262 : : * \ingroup analysis
263 : : * \note Not available in Python bindings
264 : : * \since QGIS 3.20
265 : : */
266 : 0 : class ANALYSIS_EXPORT QgsProjectiveGeorefTransform : public QgsGcpTransformerInterface SIP_SKIP
267 : : {
268 : : public:
269 : :
270 : : //! Constructor for QgsProjectiveGeorefTransform
271 : : QgsProjectiveGeorefTransform();
272 : :
273 : : QgsGcpTransformerInterface *clone() const override;
274 : : bool updateParametersFromGcps( const QVector<QgsPointXY> &sourceCoordinates, const QVector<QgsPointXY> &destinationCoordinates, bool invertYAxis = false ) override;
275 : : int minimumGcpCount() const override;
276 : : GDALTransformerFunc GDALTransformer() const override;
277 : : void *GDALTransformerArgs() const override;
278 : : TransformMethod method() const override;
279 : :
280 : : private:
281 : : struct ProjectiveParameters
282 : : {
283 : : double H[9]; // Homography
284 : : double Hinv[9]; // Inverted homography
285 : : bool hasInverse; // Could the inverted homography be calculated?
286 : : } mParameters;
287 : :
288 : : static int projectiveTransform( void *pTransformerArg, int bDstToSrc, int nPointCount,
289 : : double *x, double *y, double *z, int *panSuccess );
290 : :
291 : : };
292 : :
293 : : #endif //QGSGCPTRANSFORMER_H
|