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 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 194785 : inline GDALGeoTransform() = default; 66 : 67 : /** Constructor from a array of 6 double */ 68 93 : inline explicit GDALGeoTransform(const double coeffs[6]) 69 93 : { 70 : static_assert(sizeof(GDALGeoTransform) == 6 * sizeof(double), 71 : "Wrong size for GDALGeoTransform"); 72 93 : xorig = coeffs[0]; 73 93 : xscale = coeffs[1]; 74 93 : xrot = coeffs[2]; 75 93 : yorig = coeffs[3]; 76 93 : yrot = coeffs[4]; 77 93 : yscale = coeffs[5]; 78 93 : } 79 : 80 : /** Constructor from 6 double values */ 81 6504 : inline GDALGeoTransform(double xorigIn, double xscaleIn, double xrotIn, 82 : double yorigIn, double yrotIn, double yscaleIn) 83 6504 : { 84 6504 : xorig = xorigIn; 85 6504 : xscale = xscaleIn; 86 6504 : xrot = xrotIn; 87 6504 : yorig = yorigIn; 88 6504 : yrot = yrotIn; 89 6504 : yscale = yscaleIn; 90 6504 : } 91 : 92 : /** Element accessor. idx must be in [0,5] range */ 93 13829 : template <typename T> inline double operator[](T idx) const 94 : { 95 13829 : return *(&xorig + idx); 96 : } 97 : 98 : /** Element accessor. idx must be in [0,5] range */ 99 81777497 : template <typename T> inline double &operator[](T idx) 100 : { 101 81777497 : return *(&xorig + idx); 102 : } 103 : 104 : /** Equality test operator */ 105 4325 : inline bool operator==(const GDALGeoTransform &other) const 106 : { 107 3175 : return xorig == other.xorig && xscale == other.xscale && 108 3149 : xrot == other.xrot && yorig == other.yorig && 109 7500 : yrot == other.yrot && yscale == other.yscale; 110 : } 111 : 112 : /** Inequality test operator */ 113 4262 : inline bool operator!=(const GDALGeoTransform &other) const 114 : { 115 4262 : return !(operator==(other)); 116 : } 117 : 118 : /** Cast to const double* */ 119 100173 : inline const double *data() const 120 : { 121 100173 : return &xorig; 122 : } 123 : 124 : /** Cast to double* */ 125 24889 : inline double *data() 126 : { 127 24889 : 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 8971 : inline void Apply(double dfPixel, double dfLine, double *pdfGeoX, 151 : double *pdfGeoY) const 152 : { 153 8971 : GDALApplyGeoTransform(data(), dfPixel, dfLine, pdfGeoX, pdfGeoY); 154 8971 : } 155 : 156 : /** Apply a geotransform to an OGREnvelope in geographic coordinates. 157 : * 158 : * @param env An envelope in geographic coordinates 159 : * @param 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 env An envelope in geographic 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 90934 : inline std::pair<double, double> Apply(double dfPixel, double dfLine) const 190 : { 191 : double dfOutX, dfOutY; 192 90934 : GDALApplyGeoTransform(data(), dfPixel, dfLine, &dfOutX, &dfOutY); 193 90934 : 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 268 : inline bool GetInverse(GDALGeoTransform &inverse) const 207 : { 208 268 : 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 1947 : inline void Rescale(double dfXRatio, double dfYRatio) 219 : { 220 1947 : xscale *= dfXRatio; 221 1947 : xrot *= dfYRatio; 222 1947 : yrot *= dfXRatio; 223 1947 : yscale *= dfYRatio; 224 1947 : } 225 : 226 : /** Check whether the geotransform has a rotation component. 227 : */ 228 517 : inline bool IsAxisAligned() const 229 : { 230 517 : return xrot == 0 && yrot == 0; 231 : } 232 : }; 233 : 234 : #endif