Line data Source code
1 : /******************************************************************************
2 : *
3 : * Name: gdal_geotransform.h
4 : * Project: GDAL Core
5 : * Purpose: Declaration of GDALGeoTransform class
6 : * Author: Even Rouault, <even.rouault@spatialys.com>
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2025, Even Rouault, <even.rouault@spatialys.com>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #ifndef GDALGEOTRANSFORM_H_INCLUDED
15 : #define GDALGEOTRANSFORM_H_INCLUDED
16 :
17 : #include "gdal.h"
18 :
19 : #include <utility>
20 :
21 : class GDALRasterWindow;
22 :
23 : /* ******************************************************************** */
24 : /* GDALGeoTransform */
25 : /* ******************************************************************** */
26 :
27 : /** Class that encapsulates a geotransform matrix.
28 : *
29 : * It contains 6 coefficients expressing an affine transformation from
30 : * (column, line) raster space to (X, Y) georeferenced space, such that
31 : *
32 : * \code{.c}
33 : * X = xorig + column * xscale + line * xrot;
34 : * Y = yorig + column * yrot + line * yscale;
35 : * \endcode
36 : *
37 : * The default value is the identity transformation.
38 : *
39 : * @since 3.12
40 : */
41 : class CPL_DLL GDALGeoTransform
42 : {
43 : public:
44 : // NOTE to GDAL developers: do not reorder those coefficients!
45 :
46 : /** X value of the origin of the raster */
47 : double xorig = 0;
48 :
49 : /** X scale factor */
50 : double xscale = 1;
51 :
52 : /** X rotation factor */
53 : double xrot = 0;
54 :
55 : /** Y value of the origin of the raster */
56 : double yorig = 0;
57 :
58 : /** Y rotation factor */
59 : double yrot = 0;
60 :
61 : /** Y scale factor */
62 : double yscale = 1;
63 :
64 : /** Default constructor for an identity geotransformation matrix. */
65 206258 : inline GDALGeoTransform() = default;
66 :
67 : /** Constructor from an array of 6 doubles */
68 49 : inline explicit GDALGeoTransform(const double coeffs[6])
69 49 : {
70 : static_assert(sizeof(GDALGeoTransform) == 6 * sizeof(double),
71 : "Wrong size for GDALGeoTransform");
72 49 : xorig = coeffs[0];
73 49 : xscale = coeffs[1];
74 49 : xrot = coeffs[2];
75 49 : yorig = coeffs[3];
76 49 : yrot = coeffs[4];
77 49 : yscale = coeffs[5];
78 49 : }
79 :
80 : /** Constructor from 6 double values */
81 7155 : inline GDALGeoTransform(double xorigIn, double xscaleIn, double xrotIn,
82 : double yorigIn, double yrotIn, double yscaleIn)
83 7155 : {
84 7155 : xorig = xorigIn;
85 7155 : xscale = xscaleIn;
86 7155 : xrot = xrotIn;
87 7155 : yorig = yorigIn;
88 7155 : yrot = yrotIn;
89 7155 : yscale = yscaleIn;
90 7155 : }
91 :
92 : /** Element accessor. idx must be in [0,5] range */
93 8356 : template <typename T> inline double operator[](T idx) const
94 : {
95 8356 : return *(&xorig + idx);
96 : }
97 :
98 : /** Element accessor. idx must be in [0,5] range */
99 6142589 : template <typename T> inline double &operator[](T idx)
100 : {
101 6142589 : return *(&xorig + idx);
102 : }
103 :
104 : /** Equality test operator */
105 5268 : inline bool operator==(const GDALGeoTransform &other) const
106 : {
107 3551 : return xorig == other.xorig && xscale == other.xscale &&
108 3523 : xrot == other.xrot && yorig == other.yorig &&
109 8819 : yrot == other.yrot && yscale == other.yscale;
110 : }
111 :
112 : /** Inequality test operator */
113 5205 : inline bool operator!=(const GDALGeoTransform &other) const
114 : {
115 5205 : return !(operator==(other));
116 : }
117 :
118 : /** Cast to const double* */
119 104240 : inline const double *data() const
120 : {
121 104240 : return &xorig;
122 : }
123 :
124 : /** Cast to double* */
125 25296 : inline double *data()
126 : {
127 25296 : return &xorig;
128 : }
129 :
130 : /**
131 : * Apply GeoTransform to x/y coordinate.
132 : *
133 : * Applies the following computation, converting a (pixel, line) coordinate
134 : * into a georeferenced (geo_x, geo_y) location.
135 : * \code{.c}
136 : * *pdfGeoX = padfGeoTransform[0] + dfPixel * padfGeoTransform[1]
137 : * + dfLine * padfGeoTransform[2];
138 : * *pdfGeoY = padfGeoTransform[3] + dfPixel * padfGeoTransform[4]
139 : * + dfLine * padfGeoTransform[5];
140 : * \endcode
141 : *
142 : * @param dfPixel Input pixel position.
143 : * @param dfLine Input line position.
144 : * @param pdfGeoX output location where geo_x (easting/longitude)
145 : * location is placed.
146 : * @param pdfGeoY output location where geo_y (northing/latitude)
147 : * location is placed.
148 : */
149 :
150 11806 : inline void Apply(double dfPixel, double dfLine, double *pdfGeoX,
151 : double *pdfGeoY) const
152 : {
153 11806 : GDALApplyGeoTransform(data(), dfPixel, dfLine, pdfGeoX, pdfGeoY);
154 11806 : }
155 :
156 : /** Apply a (inverse) geotransform to an OGREnvelope in georeferenced coordinates.
157 : *
158 : * @param env An envelope in georeferenced coordinates
159 : * @param[out] window A window in pixel/line coordinates
160 : * @return true if the geotransform was successfully applied
161 : */
162 : bool Apply(const OGREnvelope &env, GDALRasterWindow &window) const;
163 :
164 : /** Apply a geotransform to a GDALRasterWindow in pixel/line coordinates.
165 : *
166 : * @param window A window in pixel/line coordinates
167 : * @param[out] env An envelope in georeferenced coordinates
168 : * @return true if the geotransform was successfully applied
169 : */
170 : bool Apply(const GDALRasterWindow &window, OGREnvelope &env) const;
171 :
172 : /**
173 : * Apply GeoTransform to x/y coordinate.
174 : *
175 : * Applies the following computation, converting a (pixel, line) coordinate
176 : * into a georeferenced (geo_x, geo_y) location.
177 : * \code{.c}
178 : * out.first = padfGeoTransform[0] + dfPixel * padfGeoTransform[1]
179 : * + dfLine * padfGeoTransform[2];
180 : * out.second = padfGeoTransform[3] + dfPixel * padfGeoTransform[4]
181 : * + dfLine * padfGeoTransform[5];
182 : * \endcode
183 : *
184 : * @param dfPixel Input pixel position.
185 : * @param dfLine Input line position.
186 : * @return output location as a (geo_x, geo_y) pair
187 : */
188 :
189 92132 : inline std::pair<double, double> Apply(double dfPixel, double dfLine) const
190 : {
191 : double dfOutX, dfOutY;
192 92132 : GDALApplyGeoTransform(data(), dfPixel, dfLine, &dfOutX, &dfOutY);
193 92132 : return {dfOutX, dfOutY};
194 : }
195 :
196 : /**
197 : * Invert Geotransform.
198 : *
199 : * This function will invert a standard 3x2 set of GeoTransform coefficients.
200 : * This converts the equation from being pixel to geo to being geo to pixel.
201 : *
202 : * @param[out] inverse Output geotransform
203 : *
204 : * @return true on success or false if the equation is uninvertable.
205 : */
206 302 : inline bool GetInverse(GDALGeoTransform &inverse) const
207 : {
208 302 : return GDALInvGeoTransform(data(), inverse.data()) == TRUE;
209 : }
210 :
211 : /** Rescale a geotransform by multiplying its scale and rotation terms by
212 : * the provided ratios.
213 : *
214 : * This is typically used to compute the geotransform matrix of an overview
215 : * dataset from the full resolution dataset, where the ratios are the size
216 : * of the full resolution dataset divided by the size of the overview.
217 : */
218 2015 : inline void Rescale(double dfXRatio, double dfYRatio)
219 : {
220 2015 : xscale *= dfXRatio;
221 2015 : xrot *= dfYRatio;
222 2015 : yrot *= dfXRatio;
223 2015 : yscale *= dfYRatio;
224 2015 : }
225 :
226 : /** Check whether the geotransform has a rotation component.
227 : */
228 1309 : inline bool IsAxisAligned() const
229 : {
230 1309 : return xrot == 0 && yrot == 0;
231 : }
232 :
233 : /** Initialize a geotransform from a string.
234 : *
235 : * @param pszGT the string to parse
236 : * @param pszSep string separating the elements of the geotransform
237 : * @return true if the initialization was successful
238 : * @since 3.13
239 : */
240 : bool Init(const char *pszGT, const char *pszSep = ",");
241 :
242 : /** Return a string containing the six geotransform values
243 : * separated by commas.
244 : *
245 : * @param pszSep characters to place between elements of the geotransform
246 : * @since 3.13
247 : */
248 : std::string ToString(const char *pszSep = ", ") const;
249 : };
250 :
251 : #endif
|