Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsrasterprojector.h - Raster projector
3 : : --------------------------------------
4 : : Date : Jan 16, 2011
5 : : Copyright : (C) 2005 by Radim Blazek
6 : : email : radim dot blazek at gmail dot com
7 : : ***************************************************************************/
8 : :
9 : : /***************************************************************************
10 : : * *
11 : : * This program is free software; you can redistribute it and/or modify *
12 : : * it under the terms of the GNU General Public License as published by *
13 : : * the Free Software Foundation; either version 2 of the License, or *
14 : : * (at your option) any later version. *
15 : : * *
16 : : ***************************************************************************/
17 : :
18 : : /* This code takes ideas from WarpBuilder in Geotools.
19 : : * Thank to Ing. Andrea Aime, Ing. Simone Giannecchini and GeoSolutions S.A.S.
20 : : * See : http://geo-solutions.blogspot.com/2011/01/developers-corner-improving.html
21 : : */
22 : :
23 : : #ifndef QGSRASTERPROJECTOR_H
24 : : #define QGSRASTERPROJECTOR_H
25 : :
26 : : #include "qgis_core.h"
27 : : #include "qgis_sip.h"
28 : : #include <QVector>
29 : : #include <QList>
30 : :
31 : : #include "qgsrectangle.h"
32 : : #include "qgscoordinatereferencesystem.h"
33 : : #include "qgscoordinatetransform.h"
34 : : #include "qgsrasterinterface.h"
35 : :
36 : : #include <cmath>
37 : :
38 : : class QgsPointXY;
39 : :
40 : : /**
41 : : * \ingroup core
42 : : * \brief QgsRasterProjector implements approximate projection support for
43 : : * it calculates grid of points in source CRS for target CRS + extent
44 : : * which are used to calculate affine transformation matrices.
45 : : * \class QgsRasterProjector
46 : : */
47 : 0 : class CORE_EXPORT QgsRasterProjector : public QgsRasterInterface
48 : : {
49 : : Q_GADGET
50 : :
51 : : public:
52 : :
53 : : /**
54 : : * Precision defines if each pixel is reprojected or approximate reprojection based
55 : : * on an approximation matrix of reprojected points is used.
56 : : */
57 : : enum Precision
58 : : {
59 : : Approximate = 0, //!< Approximate (default), fast but possibly inaccurate
60 : : Exact = 1, //!< Exact, precise but slow
61 : : };
62 : : Q_ENUM( Precision )
63 : :
64 : : QgsRasterProjector();
65 : :
66 : : QgsRasterProjector *clone() const override SIP_FACTORY;
67 : :
68 : : int bandCount() const override;
69 : :
70 : : Qgis::DataType dataType( int bandNo ) const override;
71 : :
72 : : /**
73 : : * Sets the source and destination CRS
74 : : * \deprecated since QGIS 3.8, use transformContext version instead
75 : : */
76 : : Q_DECL_DEPRECATED void setCrs( const QgsCoordinateReferenceSystem &srcCRS, const QgsCoordinateReferenceSystem &destCRS,
77 : : int srcDatumTransform = -1, int destDatumTransform = -1 ) SIP_DEPRECATED;
78 : :
79 : : /**
80 : : * Sets source CRS to \a srcCRS and destination CRS to \a destCRS and the transformation context to \a transformContext
81 : : * \since QGIS 3.8
82 : : */
83 : : void setCrs( const QgsCoordinateReferenceSystem &srcCRS, const QgsCoordinateReferenceSystem &destCRS,
84 : : QgsCoordinateTransformContext transformContext );
85 : :
86 : : //! Returns the source CRS
87 : 0 : QgsCoordinateReferenceSystem sourceCrs() const { return mSrcCRS; }
88 : :
89 : : //! Returns the destination CRS
90 : 0 : QgsCoordinateReferenceSystem destinationCrs() const { return mDestCRS; }
91 : :
92 : : Precision precision() const { return mPrecision; }
93 : 0 : void setPrecision( Precision precision ) { mPrecision = precision; }
94 : : // Translated precision mode, for use in ComboBox etc.
95 : : static QString precisionLabel( Precision precision );
96 : :
97 : : QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback = nullptr ) override SIP_FACTORY;
98 : :
99 : : //! Calculate destination extent and size from source extent and size
100 : : bool destExtentSize( const QgsRectangle &srcExtent, int srcXSize, int srcYSize,
101 : : QgsRectangle &destExtent SIP_OUT, int &destXSize SIP_OUT, int &destYSize SIP_OUT );
102 : :
103 : : //! Calculate destination extent and size from source extent and size
104 : : static bool extentSize( const QgsCoordinateTransform &ct,
105 : : const QgsRectangle &srcExtent, int srcXSize, int srcYSize,
106 : : QgsRectangle &destExtent SIP_OUT, int &destXSize SIP_OUT, int &destYSize SIP_OUT );
107 : :
108 : : private:
109 : :
110 : : //! Source CRS
111 : : QgsCoordinateReferenceSystem mSrcCRS;
112 : :
113 : : //! Destination CRS
114 : : QgsCoordinateReferenceSystem mDestCRS;
115 : :
116 : : //! Source datum transformation id (or -1 if none)
117 : : Q_DECL_DEPRECATED int mSrcDatumTransform = -1;
118 : :
119 : : //! Destination datum transformation id (or -1 if none)
120 : : Q_DECL_DEPRECATED int mDestDatumTransform = -1;
121 : :
122 : : //! Requested precision
123 : : Precision mPrecision = Approximate;
124 : :
125 : : QgsCoordinateTransformContext mTransformContext;
126 : :
127 : : };
128 : :
129 : :
130 : : #ifndef SIP_RUN
131 : : /// @cond PRIVATE
132 : :
133 : : /**
134 : : * Internal class for reprojection of rasters - either exact or approximate.
135 : : * QgsRasterProjector creates it and then keeps calling srcRowCol() to get source pixel position
136 : : * for every destination pixel position.
137 : : */
138 : : class ProjectorData
139 : : {
140 : : public:
141 : : //! Initialize reprojector and calculate matrix
142 : : ProjectorData( const QgsRectangle &extent, int width, int height, QgsRasterInterface *input, const QgsCoordinateTransform &inverseCt, QgsRasterProjector::Precision precision, QgsRasterBlockFeedback *feedback = nullptr );
143 : : ~ProjectorData();
144 : :
145 : : ProjectorData( const ProjectorData &other ) = delete;
146 : : ProjectorData &operator=( const ProjectorData &other ) = delete;
147 : :
148 : : /**
149 : : * Returns the source row and column indexes for current source extent and resolution.
150 : : * If the source pixel is outside source extent srcRow and srcCol are left unchanged.
151 : : * \returns TRUE if inside source
152 : : */
153 : : bool srcRowCol( int destRow, int destCol, int *srcRow, int *srcCol );
154 : :
155 : 0 : QgsRectangle srcExtent() const { return mSrcExtent; }
156 : 0 : int srcRows() const { return mSrcRows; }
157 : 0 : int srcCols() const { return mSrcCols; }
158 : :
159 : : private:
160 : :
161 : : //! Returns the destination point for _current_ destination position.
162 : : void destPointOnCPMatrix( int row, int col, double *theX, double *theY );
163 : :
164 : : //! Returns the matrix upper left row index for destination row.
165 : : int matrixRow( int destRow );
166 : :
167 : : //! Returns the matrix upper left col index for destination col.
168 : : int matrixCol( int destCol );
169 : :
170 : : //! Returns precise source row and column indexes for current source extent and resolution.
171 : : inline bool preciseSrcRowCol( int destRow, int destCol, int *srcRow, int *srcCol );
172 : :
173 : : //! Returns approximate source row and column indexes for current source extent and resolution.
174 : : inline bool approximateSrcRowCol( int destRow, int destCol, int *srcRow, int *srcCol );
175 : :
176 : : //! \brief insert rows to matrix
177 : : void insertRows( const QgsCoordinateTransform &ct );
178 : :
179 : : //! \brief insert columns to matrix
180 : : void insertCols( const QgsCoordinateTransform &ct );
181 : :
182 : : //! Calculate single control point in current matrix
183 : : void calcCP( int row, int col, const QgsCoordinateTransform &ct );
184 : :
185 : : //! \brief calculate matrix row
186 : : bool calcRow( int row, const QgsCoordinateTransform &ct );
187 : :
188 : : //! \brief calculate matrix column
189 : : bool calcCol( int col, const QgsCoordinateTransform &ct );
190 : :
191 : : //! \brief calculate source extent
192 : : void calcSrcExtent();
193 : :
194 : : //! \brief calculate minimum source width and height
195 : : void calcSrcRowsCols();
196 : :
197 : : /**
198 : : * \brief check error along columns
199 : : * returns TRUE if within threshold
200 : : */
201 : : bool checkCols( const QgsCoordinateTransform &ct );
202 : :
203 : : /**
204 : : * \brief check error along rows
205 : : * returns TRUE if within threshold
206 : : */
207 : : bool checkRows( const QgsCoordinateTransform &ct );
208 : :
209 : : //! Calculate array of src helper points
210 : : void calcHelper( int matrixRow, QgsPointXY *points );
211 : :
212 : : //! Calc / switch helper
213 : : void nextHelper();
214 : :
215 : : //! Gets mCPMatrix as string
216 : : QString cpToString();
217 : :
218 : : /**
219 : : * Use approximation (requested precision is Approximate and it is possible to calculate
220 : : * an approximation matrix with a sufficient precision).
221 : : */
222 : : bool mApproximate;
223 : :
224 : : //! Transformation from destination CRS to source CRS
225 : : QgsCoordinateTransform mInverseCt;
226 : :
227 : : //! Destination extent
228 : : QgsRectangle mDestExtent;
229 : :
230 : : //! Source extent
231 : : QgsRectangle mSrcExtent;
232 : :
233 : : //! Source raster extent
234 : : QgsRectangle mExtent;
235 : :
236 : : //! Number of destination rows
237 : : int mDestRows;
238 : :
239 : : //! Number of destination columns
240 : : int mDestCols;
241 : :
242 : : //! Destination x resolution
243 : : double mDestXRes;
244 : :
245 : : //! Destination y resolution
246 : : double mDestYRes;
247 : :
248 : : //! Number of source rows
249 : : int mSrcRows;
250 : :
251 : : //! Number of source columns
252 : : int mSrcCols;
253 : :
254 : : //! Source x resolution
255 : : double mSrcXRes;
256 : :
257 : : //! Source y resolution
258 : : double mSrcYRes;
259 : :
260 : : //! Number of destination rows per matrix row
261 : : double mDestRowsPerMatrixRow;
262 : :
263 : : //! Number of destination cols per matrix col
264 : : double mDestColsPerMatrixCol;
265 : :
266 : : //! Grid of source control points
267 : : QList< QList<QgsPointXY> > mCPMatrix;
268 : :
269 : : //! Grid of source control points transformation possible indicator
270 : : /* Same size as mCPMatrix */
271 : : QList< QList<bool> > mCPLegalMatrix;
272 : :
273 : : //! Array of source points for each destination column on top of current CPMatrix grid row
274 : : /* Warning: using QList is slow on access */
275 : : QgsPointXY *pHelperTop = nullptr;
276 : :
277 : : //! Array of source points for each destination column on bottom of current CPMatrix grid row
278 : : /* Warning: using QList is slow on access */
279 : : QgsPointXY *pHelperBottom = nullptr;
280 : :
281 : : //! Current mHelperTop matrix row
282 : : int mHelperTopRow;
283 : :
284 : : //! Number of mCPMatrix columns
285 : : int mCPCols;
286 : : //! Number of mCPMatrix rows
287 : : int mCPRows;
288 : :
289 : : //! Maximum tolerance in destination units
290 : : double mSqrTolerance;
291 : :
292 : : //! Maximum source resolution
293 : : double mMaxSrcXRes;
294 : : double mMaxSrcYRes;
295 : :
296 : : };
297 : :
298 : : /// @endcond
299 : : #endif
300 : :
301 : : #endif
302 : :
|