Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: Classes for manipulating spatial reference systems in a
5 : * platform non-specific manner.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1999, Les Technologies SoftMap Inc.
10 : * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com>
11 : *
12 : * SPDX-License-Identifier: MIT
13 : ****************************************************************************/
14 :
15 : #ifndef OGR_SPATIALREF_H_INCLUDED
16 : #define OGR_SPATIALREF_H_INCLUDED
17 :
18 : #include "cpl_string.h"
19 : #include "ogr_srs_api.h"
20 :
21 : #include <cstddef>
22 : #include <map>
23 : #include <memory>
24 : #include <vector>
25 :
26 : /**
27 : * \file ogr_spatialref.h
28 : *
29 : * Coordinate systems services.
30 : */
31 :
32 : /************************************************************************/
33 : /* OGR_SRSNode */
34 : /************************************************************************/
35 :
36 : /**
37 : * Objects of this class are used to represent value nodes in the parsed
38 : * representation of the WKT SRS format. For instance UNIT["METER",1]
39 : * would be rendered into three OGR_SRSNodes. The root node would have a
40 : * value of UNIT, and two children, the first with a value of METER, and the
41 : * second with a value of 1.
42 : *
43 : * Normally application code just interacts with the OGRSpatialReference
44 : * object, which uses the OGR_SRSNode to implement its data structure;
45 : * however, this class is user accessible for detailed access to components
46 : * of an SRS definition.
47 : */
48 :
49 : class CPL_DLL OGR_SRSNode
50 : {
51 : public:
52 : /** Listener that is notified of modification to nodes. */
53 219852 : struct Listener
54 : {
55 : virtual ~Listener();
56 : /** Method triggered when a node is modified. */
57 : virtual void notifyChange(OGR_SRSNode *) = 0;
58 : };
59 :
60 : explicit OGR_SRSNode(const char * = nullptr);
61 : ~OGR_SRSNode();
62 :
63 : /** Register a (single) listener. */
64 : void RegisterListener(const std::shared_ptr<Listener> &listener);
65 :
66 : /** Return whether this is a leaf node.
67 : * @return TRUE or FALSE
68 : */
69 : int IsLeafNode() const
70 : {
71 : return nChildren == 0;
72 : }
73 :
74 428866 : int GetChildCount() const
75 : {
76 428866 : return nChildren;
77 : }
78 :
79 : OGR_SRSNode *GetChild(int);
80 : const OGR_SRSNode *GetChild(int) const;
81 :
82 : OGR_SRSNode *GetNode(const char *);
83 : const OGR_SRSNode *GetNode(const char *) const;
84 :
85 : void InsertChild(OGR_SRSNode *, int);
86 : void AddChild(OGR_SRSNode *);
87 : int FindChild(const char *) const;
88 : void DestroyChild(int);
89 : void ClearChildren();
90 : void StripNodes(const char *);
91 :
92 601010 : const char *GetValue() const
93 : {
94 601010 : return pszValue;
95 : }
96 :
97 : void SetValue(const char *);
98 :
99 : void MakeValueSafe();
100 :
101 : OGR_SRSNode *Clone() const;
102 :
103 : OGRErr importFromWkt(char **)
104 : /*! @cond Doxygen_Suppress */
105 : CPL_WARN_DEPRECATED("Use importFromWkt(const char**)")
106 : /*! @endcond */
107 : ;
108 : OGRErr importFromWkt(const char **);
109 : OGRErr exportToWkt(char **) const;
110 : OGRErr exportToPrettyWkt(char **, int = 1) const;
111 :
112 : private:
113 : char *pszValue;
114 :
115 : OGR_SRSNode **papoChildNodes;
116 : OGR_SRSNode *poParent;
117 :
118 : int nChildren;
119 :
120 : int NeedsQuoting() const;
121 : OGRErr importFromWkt(const char **, int nRecLevel, int *pnNodes);
122 :
123 : std::weak_ptr<Listener> m_listener{};
124 : void notifyChange();
125 :
126 : CPL_DISALLOW_COPY_ASSIGN(OGR_SRSNode)
127 : };
128 :
129 : /************************************************************************/
130 : /* OGRSpatialReference */
131 : /************************************************************************/
132 :
133 : /**
134 : * This class represents an OpenGIS Spatial Reference System, and contains
135 : * methods for converting between this object organization and well known
136 : * text (WKT) format. This object is reference counted as one instance of
137 : * the object is normally shared between many OGRGeometry objects.
138 : *
139 : * Normally application code can fetch needed parameter values for this
140 : * SRS using GetAttrValue(), but in special cases the underlying parse tree
141 : * (or OGR_SRSNode objects) can be accessed more directly.
142 : *
143 : * See <a href="https://gdal.org/tutorials/osr_api_tut.html">the tutorial
144 : * </a> for more information on how to use this class.
145 : *
146 : * Consult also the <a href="https://gdal.org/tutorials/wktproblems.html">
147 : * OGC WKT Coordinate System Issues</a> page for implementation details of
148 : * WKT in OGR.
149 : */
150 :
151 : class CPL_DLL OGRSpatialReference
152 : {
153 : struct Private;
154 : std::unique_ptr<Private> d;
155 :
156 : void GetNormInfo() const;
157 :
158 : // No longer used with PROJ >= 8.1.0
159 : OGRErr importFromURNPart(const char *pszAuthority, const char *pszCode,
160 : const char *pszURN);
161 :
162 : static CPLString lookupInDict(const char *pszDictFile, const char *pszCode);
163 :
164 : OGRErr GetWKT2ProjectionMethod(const char **ppszMethodName,
165 : const char **ppszMethodAuthName = nullptr,
166 : const char **ppszMethodCode = nullptr) const;
167 :
168 : public:
169 : explicit OGRSpatialReference(const char * = nullptr);
170 : OGRSpatialReference(const OGRSpatialReference &);
171 : OGRSpatialReference(OGRSpatialReference &&);
172 :
173 : virtual ~OGRSpatialReference();
174 :
175 : static void DestroySpatialReference(OGRSpatialReference *poSRS);
176 :
177 : OGRSpatialReference &operator=(const OGRSpatialReference &);
178 : OGRSpatialReference &operator=(OGRSpatialReference &&);
179 :
180 : OGRSpatialReference &AssignAndSetThreadSafe(const OGRSpatialReference &);
181 :
182 : int Reference();
183 : int Dereference();
184 : int GetReferenceCount() const;
185 : void Release();
186 :
187 : const char *GetName() const;
188 :
189 : OGRSpatialReference *Clone() const;
190 : OGRSpatialReference *CloneGeogCS() const;
191 :
192 : void dumpReadable();
193 : OGRErr exportToWkt(char **) const;
194 : OGRErr exportToWkt(char **ppszWKT, const char *const *papszOptions) const;
195 : std::string exportToWkt(const char *const *papszOptions = nullptr) const;
196 : OGRErr exportToPrettyWkt(char **, int = FALSE) const;
197 : // cppcheck-suppress functionStatic
198 : OGRErr exportToPROJJSON(char **, const char *const *papszOptions) const;
199 : OGRErr exportToProj4(char **) const;
200 : OGRErr exportToPCI(char **, char **, double **) const;
201 : OGRErr exportToUSGS(long *, long *, double **, long *) const;
202 : OGRErr exportToXML(char **, const char * = nullptr) const;
203 : OGRErr exportToPanorama(long *, long *, long *, long *, double *) const;
204 : OGRErr exportVertCSToPanorama(int *) const;
205 : OGRErr exportToERM(char *pszProj, char *pszDatum, char *pszUnits);
206 : OGRErr exportToMICoordSys(char **) const;
207 : OGRErr exportToCF1(char **ppszGridMappingName, char ***ppapszKeyValues,
208 : char **ppszUnits, CSLConstList papszOptions) const;
209 :
210 : OGRErr importFromWkt(char **)
211 : /*! @cond Doxygen_Suppress */
212 : CPL_WARN_DEPRECATED(
213 : "Use importFromWkt(const char**) or importFromWkt(const char*)")
214 : /*! @endcond */
215 : ;
216 :
217 : OGRErr importFromWkt(const char **);
218 : /*! @cond Doxygen_Suppress */
219 : OGRErr importFromWkt(const char *pszInput, CSLConstList papszOptions);
220 : OGRErr importFromWkt(const char **ppszInput, CSLConstList papszOptions);
221 : /*! @endcond */
222 : OGRErr importFromWkt(const char *);
223 : OGRErr importFromProj4(const char *);
224 : OGRErr importFromEPSG(int);
225 : OGRErr importFromEPSGA(int);
226 : OGRErr importFromESRI(char **);
227 : OGRErr importFromPCI(const char *, const char * = nullptr,
228 : const double * = nullptr);
229 :
230 : #define USGS_ANGLE_DECIMALDEGREES 0 /**< Angle is in decimal degrees. */
231 : #define USGS_ANGLE_PACKEDDMS \
232 : TRUE /**< Angle is in packed degree minute second. */
233 : #define USGS_ANGLE_RADIANS 2 /**< Angle is in radians. */
234 : OGRErr importFromUSGS(long iProjSys, long iZone, double *padfPrjParams,
235 : long iDatum,
236 : int nUSGSAngleFormat = USGS_ANGLE_PACKEDDMS);
237 : OGRErr importFromPanorama(long, long, long, double *, bool bNorth = true);
238 : OGRErr importVertCSFromPanorama(int);
239 : OGRErr importFromOzi(const char *const *papszLines);
240 : OGRErr importFromWMSAUTO(const char *pszAutoDef);
241 : OGRErr importFromXML(const char *);
242 : OGRErr importFromDict(const char *pszDict, const char *pszCode);
243 : OGRErr importFromURN(const char *);
244 : OGRErr importFromCRSURL(const char *);
245 : OGRErr importFromERM(const char *pszProj, const char *pszDatum,
246 : const char *pszUnits);
247 : OGRErr importFromUrl(const char *);
248 : OGRErr importFromMICoordSys(const char *);
249 : OGRErr importFromCF1(CSLConstList papszKeyValues, const char *pszUnits);
250 :
251 : OGRErr morphToESRI();
252 : OGRErr morphFromESRI();
253 :
254 : OGRSpatialReference *
255 : convertToOtherProjection(const char *pszTargetProjection,
256 : const char *const *papszOptions = nullptr) const;
257 :
258 : OGRErr Validate() const;
259 : OGRErr StripVertical();
260 :
261 : bool StripTOWGS84IfKnownDatumAndAllowed();
262 : bool StripTOWGS84IfKnownDatum();
263 :
264 : int EPSGTreatsAsLatLong() const;
265 : int EPSGTreatsAsNorthingEasting() const;
266 : int GetAxesCount() const;
267 : const char *GetAxis(const char *pszTargetKey, int iAxis,
268 : OGRAxisOrientation *peOrientation,
269 : double *pdfConvFactor = nullptr) const;
270 : OGRErr SetAxes(const char *pszTargetKey, const char *pszXAxisName,
271 : OGRAxisOrientation eXAxisOrientation,
272 : const char *pszYAxisName,
273 : OGRAxisOrientation eYAxisOrientation);
274 :
275 : OSRAxisMappingStrategy GetAxisMappingStrategy() const;
276 : void SetAxisMappingStrategy(OSRAxisMappingStrategy);
277 : const std::vector<int> &GetDataAxisToSRSAxisMapping() const;
278 : OGRErr SetDataAxisToSRSAxisMapping(const std::vector<int> &mapping);
279 :
280 : // Machinery for accessing parse nodes
281 :
282 : //! Return root node
283 : OGR_SRSNode *GetRoot();
284 : //! Return root node
285 : const OGR_SRSNode *GetRoot() const;
286 : void SetRoot(OGR_SRSNode *);
287 :
288 : OGR_SRSNode *GetAttrNode(const char *);
289 : const OGR_SRSNode *GetAttrNode(const char *) const;
290 : const char *GetAttrValue(const char *, int = 0) const;
291 :
292 : OGRErr SetNode(const char *, const char *);
293 : // cppcheck-suppress functionStatic
294 : OGRErr SetNode(const char *, double);
295 :
296 : OGRErr
297 : SetLinearUnitsAndUpdateParameters(const char *pszName, double dfInMeters,
298 : const char *pszUnitAuthority = nullptr,
299 : const char *pszUnitCode = nullptr);
300 : OGRErr SetLinearUnits(const char *pszName, double dfInMeters);
301 : OGRErr SetTargetLinearUnits(const char *pszTargetKey, const char *pszName,
302 : double dfInMeters,
303 : const char *pszUnitAuthority = nullptr,
304 : const char *pszUnitCode = nullptr);
305 :
306 : double GetLinearUnits(char **) const
307 : /*! @cond Doxygen_Suppress */
308 : CPL_WARN_DEPRECATED("Use GetLinearUnits(const char**) instead")
309 : /*! @endcond */
310 : ;
311 : double GetLinearUnits(const char ** = nullptr) const;
312 :
313 : /*! @cond Doxygen_Suppress */
314 5203 : double GetLinearUnits(std::nullptr_t) const
315 : {
316 5203 : return GetLinearUnits(static_cast<const char **>(nullptr));
317 : }
318 :
319 : /*! @endcond */
320 :
321 : double GetTargetLinearUnits(const char *pszTargetKey,
322 : char **ppszRetName) const
323 : /*! @cond Doxygen_Suppress */
324 : CPL_WARN_DEPRECATED(
325 : "Use GetTargetLinearUnits(const char*, const char**)")
326 : /*! @endcond */
327 : ;
328 : double GetTargetLinearUnits(const char *pszTargetKey,
329 : const char **ppszRetName = nullptr) const;
330 :
331 : /*! @cond Doxygen_Suppress */
332 : double GetTargetLinearUnits(const char *pszTargetKey, std::nullptr_t) const
333 : {
334 : return GetTargetLinearUnits(pszTargetKey,
335 : static_cast<const char **>(nullptr));
336 : }
337 :
338 : /*! @endcond */
339 :
340 : OGRErr SetAngularUnits(const char *pszName, double dfInRadians);
341 : double GetAngularUnits(char **) const
342 : /*! @cond Doxygen_Suppress */
343 : CPL_WARN_DEPRECATED("Use GetAngularUnits(const char**) instead")
344 : /*! @endcond */
345 : ;
346 : double GetAngularUnits(const char ** = nullptr) const;
347 :
348 : /*! @cond Doxygen_Suppress */
349 1564 : double GetAngularUnits(std::nullptr_t) const
350 : {
351 1564 : return GetAngularUnits(static_cast<const char **>(nullptr));
352 : }
353 :
354 : /*! @endcond */
355 :
356 : double GetPrimeMeridian(char **) const
357 : /*! @cond Doxygen_Suppress */
358 : CPL_WARN_DEPRECATED("Use GetPrimeMeridian(const char**) instead")
359 : /*! @endcond */
360 : ;
361 : double GetPrimeMeridian(const char ** = nullptr) const;
362 :
363 : /*! @cond Doxygen_Suppress */
364 1143 : double GetPrimeMeridian(std::nullptr_t) const
365 : {
366 1143 : return GetPrimeMeridian(static_cast<const char **>(nullptr));
367 : }
368 :
369 : /*! @endcond */
370 :
371 : bool IsEmpty() const;
372 : int IsGeographic() const;
373 : int IsDerivedGeographic() const;
374 : int IsProjected() const;
375 : int IsDerivedProjected() const;
376 : int IsGeocentric() const;
377 : bool IsDynamic() const;
378 :
379 : // cppcheck-suppress functionStatic
380 : bool HasPointMotionOperation() const;
381 :
382 : int IsLocal() const;
383 : int IsVertical() const;
384 : int IsCompound() const;
385 : int IsSameGeogCS(const OGRSpatialReference *) const;
386 : int IsSameGeogCS(const OGRSpatialReference *,
387 : const char *const *papszOptions) const;
388 : int IsSameVertCS(const OGRSpatialReference *) const;
389 : int IsSame(const OGRSpatialReference *) const;
390 : int IsSame(const OGRSpatialReference *,
391 : const char *const *papszOptions) const;
392 :
393 : const char *GetCelestialBodyName() const;
394 :
395 : void Clear();
396 : OGRErr SetLocalCS(const char *);
397 : OGRErr SetProjCS(const char *);
398 : OGRErr SetProjection(const char *);
399 : OGRErr SetGeocCS(const char *pszGeocName);
400 : OGRErr SetGeogCS(const char *pszGeogName, const char *pszDatumName,
401 : const char *pszEllipsoidName, double dfSemiMajor,
402 : double dfInvFlattening, const char *pszPMName = nullptr,
403 : double dfPMOffset = 0.0, const char *pszUnits = nullptr,
404 : double dfConvertToRadians = 0.0);
405 : OGRErr SetWellKnownGeogCS(const char *);
406 : OGRErr CopyGeogCSFrom(const OGRSpatialReference *poSrcSRS);
407 : OGRErr SetVertCS(const char *pszVertCSName, const char *pszVertDatumName,
408 : int nVertDatumClass = 2005);
409 : OGRErr SetCompoundCS(const char *pszName,
410 : const OGRSpatialReference *poHorizSRS,
411 : const OGRSpatialReference *poVertSRS);
412 :
413 : void SetCoordinateEpoch(double dfCoordinateEpoch);
414 : double GetCoordinateEpoch() const;
415 :
416 : // cppcheck-suppress functionStatic
417 : OGRErr PromoteTo3D(const char *pszName);
418 : // cppcheck-suppress functionStatic
419 : OGRErr DemoteTo2D(const char *pszName);
420 :
421 : OGRErr SetFromUserInput(const char *);
422 :
423 : static const char *const SET_FROM_USER_INPUT_LIMITATIONS[];
424 : static CSLConstList SET_FROM_USER_INPUT_LIMITATIONS_get();
425 :
426 : OGRErr SetFromUserInput(const char *, CSLConstList papszOptions);
427 :
428 : OGRErr SetTOWGS84(double, double, double, double = 0.0, double = 0.0,
429 : double = 0.0, double = 0.0);
430 : OGRErr GetTOWGS84(double *padfCoef, int nCoeff = 7) const;
431 : OGRErr AddGuessedTOWGS84();
432 :
433 : double GetSemiMajor(OGRErr * = nullptr) const;
434 : double GetSemiMinor(OGRErr * = nullptr) const;
435 : double GetInvFlattening(OGRErr * = nullptr) const;
436 : double GetEccentricity() const;
437 : double GetSquaredEccentricity() const;
438 :
439 : OGRErr SetAuthority(const char *pszTargetKey, const char *pszAuthority,
440 : int nCode);
441 :
442 : OGRErr AutoIdentifyEPSG();
443 : OGRSpatialReferenceH *FindMatches(char **papszOptions, int *pnEntries,
444 : int **ppanMatchConfidence) const;
445 : OGRSpatialReference *
446 : FindBestMatch(int nMinimumMatchConfidence = 90,
447 : const char *pszPreferredAuthority = "EPSG",
448 : CSLConstList papszOptions = nullptr) const;
449 :
450 : int GetEPSGGeogCS() const;
451 :
452 : const char *GetAuthorityCode(const char *pszTargetKey) const;
453 : const char *GetAuthorityName(const char *pszTargetKey) const;
454 : char *GetOGCURN() const;
455 :
456 : bool GetAreaOfUse(double *pdfWestLongitudeDeg, double *pdfSouthLatitudeDeg,
457 : double *pdfEastLongitudeDeg, double *pdfNorthLatitudeDeg,
458 : const char **ppszAreaName) const;
459 :
460 : const char *GetExtension(const char *pszTargetKey, const char *pszName,
461 : const char *pszDefault = nullptr) const;
462 : OGRErr SetExtension(const char *pszTargetKey, const char *pszName,
463 : const char *pszValue);
464 :
465 : int FindProjParm(const char *pszParameter,
466 : const OGR_SRSNode *poPROJCS = nullptr) const;
467 : OGRErr SetProjParm(const char *, double);
468 : double GetProjParm(const char *, double = 0.0, OGRErr * = nullptr) const;
469 :
470 : OGRErr SetNormProjParm(const char *, double);
471 : double GetNormProjParm(const char *, double = 0.0,
472 : OGRErr * = nullptr) const;
473 :
474 : static int IsAngularParameter(const char *);
475 : static int IsLongitudeParameter(const char *);
476 : static int IsLinearParameter(const char *);
477 :
478 : /** Albers Conic Equal Area */
479 : OGRErr SetACEA(double dfStdP1, double dfStdP2, double dfCenterLat,
480 : double dfCenterLong, double dfFalseEasting,
481 : double dfFalseNorthing);
482 :
483 : /** Azimuthal Equidistant */
484 : OGRErr SetAE(double dfCenterLat, double dfCenterLong, double dfFalseEasting,
485 : double dfFalseNorthing);
486 :
487 : /** Bonne */
488 : OGRErr SetBonne(double dfStdP1, double dfCentralMeridian,
489 : double dfFalseEasting, double dfFalseNorthing);
490 :
491 : /** Cylindrical Equal Area */
492 : OGRErr SetCEA(double dfStdP1, double dfCentralMeridian,
493 : double dfFalseEasting, double dfFalseNorthing);
494 :
495 : /** Cassini-Soldner */
496 : OGRErr SetCS(double dfCenterLat, double dfCenterLong, double dfFalseEasting,
497 : double dfFalseNorthing);
498 :
499 : /** Equidistant Conic */
500 : OGRErr SetEC(double dfStdP1, double dfStdP2, double dfCenterLat,
501 : double dfCenterLong, double dfFalseEasting,
502 : double dfFalseNorthing);
503 :
504 : /** Eckert I */
505 : OGRErr SetEckert(int nVariation, double dfCentralMeridian,
506 : double dfFalseEasting, double dfFalseNorthing);
507 :
508 : /** Eckert IV */
509 : OGRErr SetEckertIV(double dfCentralMeridian, double dfFalseEasting,
510 : double dfFalseNorthing);
511 :
512 : /** Eckert VI */
513 : OGRErr SetEckertVI(double dfCentralMeridian, double dfFalseEasting,
514 : double dfFalseNorthing);
515 :
516 : /** Equirectangular */
517 : OGRErr SetEquirectangular(double dfCenterLat, double dfCenterLong,
518 : double dfFalseEasting, double dfFalseNorthing);
519 : /** Equirectangular generalized form : */
520 : OGRErr SetEquirectangular2(double dfCenterLat, double dfCenterLong,
521 : double dfPseudoStdParallel1,
522 : double dfFalseEasting, double dfFalseNorthing);
523 :
524 : /** Geostationary Satellite */
525 : OGRErr SetGEOS(double dfCentralMeridian, double dfSatelliteHeight,
526 : double dfFalseEasting, double dfFalseNorthing);
527 :
528 : /** Goode Homolosine */
529 : OGRErr SetGH(double dfCentralMeridian, double dfFalseEasting,
530 : double dfFalseNorthing);
531 :
532 : /** Interrupted Goode Homolosine */
533 : OGRErr SetIGH();
534 :
535 : /** Gall Stereographic */
536 : OGRErr SetGS(double dfCentralMeridian, double dfFalseEasting,
537 : double dfFalseNorthing);
538 :
539 : /** Gauss Schreiber Transverse Mercator */
540 : OGRErr SetGaussSchreiberTMercator(double dfCenterLat, double dfCenterLong,
541 : double dfScale, double dfFalseEasting,
542 : double dfFalseNorthing);
543 :
544 : /** Gnomonic */
545 : OGRErr SetGnomonic(double dfCenterLat, double dfCenterLong,
546 : double dfFalseEasting, double dfFalseNorthing);
547 :
548 : /** Hotine Oblique Mercator */
549 : OGRErr SetHOM(double dfCenterLat, double dfCenterLong, double dfAzimuth,
550 : double dfRectToSkew, double dfScale, double dfFalseEasting,
551 : double dfFalseNorthing);
552 :
553 : /** Hotine Oblique Mercator 2 points */
554 : OGRErr SetHOM2PNO(double dfCenterLat, double dfLat1, double dfLong1,
555 : double dfLat2, double dfLong2, double dfScale,
556 : double dfFalseEasting, double dfFalseNorthing);
557 :
558 : /** Hotine Oblique Mercator Azimuth Center / Variant B */
559 : OGRErr SetHOMAC(double dfCenterLat, double dfCenterLong, double dfAzimuth,
560 : double dfRectToSkew, double dfScale, double dfFalseEasting,
561 : double dfFalseNorthing);
562 :
563 : /** Laborde Oblique Mercator */
564 : OGRErr SetLOM(double dfCenterLat, double dfCenterLong, double dfAzimuth,
565 : double dfScale, double dfFalseEasting,
566 : double dfFalseNorthing);
567 :
568 : /** International Map of the World Polyconic */
569 : OGRErr SetIWMPolyconic(double dfLat1, double dfLat2, double dfCenterLong,
570 : double dfFalseEasting, double dfFalseNorthing);
571 :
572 : /** Krovak Oblique Conic Conformal */
573 : OGRErr SetKrovak(double dfCenterLat, double dfCenterLong, double dfAzimuth,
574 : double dfPseudoStdParallelLat, double dfScale,
575 : double dfFalseEasting, double dfFalseNorthing);
576 :
577 : /** Lambert Azimuthal Equal-Area */
578 : OGRErr SetLAEA(double dfCenterLat, double dfCenterLong,
579 : double dfFalseEasting, double dfFalseNorthing);
580 :
581 : /** Lambert Conformal Conic */
582 : OGRErr SetLCC(double dfStdP1, double dfStdP2, double dfCenterLat,
583 : double dfCenterLong, double dfFalseEasting,
584 : double dfFalseNorthing);
585 :
586 : /** Lambert Conformal Conic 1SP */
587 : OGRErr SetLCC1SP(double dfCenterLat, double dfCenterLong, double dfScale,
588 : double dfFalseEasting, double dfFalseNorthing);
589 :
590 : /** Lambert Conformal Conic (Belgium) */
591 : OGRErr SetLCCB(double dfStdP1, double dfStdP2, double dfCenterLat,
592 : double dfCenterLong, double dfFalseEasting,
593 : double dfFalseNorthing);
594 :
595 : /** Miller Cylindrical */
596 : OGRErr SetMC(double dfCenterLat, double dfCenterLong, double dfFalseEasting,
597 : double dfFalseNorthing);
598 :
599 : /** Mercator 1SP */
600 : OGRErr SetMercator(double dfCenterLat, double dfCenterLong, double dfScale,
601 : double dfFalseEasting, double dfFalseNorthing);
602 :
603 : /** Mercator 2SP */
604 : OGRErr SetMercator2SP(double dfStdP1, double dfCenterLat,
605 : double dfCenterLong, double dfFalseEasting,
606 : double dfFalseNorthing);
607 :
608 : /** Mollweide */
609 : OGRErr SetMollweide(double dfCentralMeridian, double dfFalseEasting,
610 : double dfFalseNorthing);
611 :
612 : /** New Zealand Map Grid */
613 : OGRErr SetNZMG(double dfCenterLat, double dfCenterLong,
614 : double dfFalseEasting, double dfFalseNorthing);
615 :
616 : /** Oblique Stereographic */
617 : OGRErr SetOS(double dfOriginLat, double dfCMeridian, double dfScale,
618 : double dfFalseEasting, double dfFalseNorthing);
619 :
620 : /** Orthographic */
621 : OGRErr SetOrthographic(double dfCenterLat, double dfCenterLong,
622 : double dfFalseEasting, double dfFalseNorthing);
623 :
624 : /** Polyconic */
625 : OGRErr SetPolyconic(double dfCenterLat, double dfCenterLong,
626 : double dfFalseEasting, double dfFalseNorthing);
627 :
628 : /** Polar Stereographic */
629 : OGRErr SetPS(double dfCenterLat, double dfCenterLong, double dfScale,
630 : double dfFalseEasting, double dfFalseNorthing);
631 :
632 : /** Robinson */
633 : OGRErr SetRobinson(double dfCenterLong, double dfFalseEasting,
634 : double dfFalseNorthing);
635 :
636 : /** Sinusoidal */
637 : OGRErr SetSinusoidal(double dfCenterLong, double dfFalseEasting,
638 : double dfFalseNorthing);
639 :
640 : /** Stereographic */
641 : OGRErr SetStereographic(double dfCenterLat, double dfCenterLong,
642 : double dfScale, double dfFalseEasting,
643 : double dfFalseNorthing);
644 :
645 : /** Swiss Oblique Cylindrical */
646 : OGRErr SetSOC(double dfLatitudeOfOrigin, double dfCentralMeridian,
647 : double dfFalseEasting, double dfFalseNorthing);
648 :
649 : /** Transverse Mercator */
650 : OGRErr SetTM(double dfCenterLat, double dfCenterLong, double dfScale,
651 : double dfFalseEasting, double dfFalseNorthing);
652 :
653 : /** Transverse Mercator variants. */
654 : OGRErr SetTMVariant(const char *pszVariantName, double dfCenterLat,
655 : double dfCenterLong, double dfScale,
656 : double dfFalseEasting, double dfFalseNorthing);
657 :
658 : /** Tunesia Mining Grid */
659 : OGRErr SetTMG(double dfCenterLat, double dfCenterLong,
660 : double dfFalseEasting, double dfFalseNorthing);
661 :
662 : /** Transverse Mercator (South Oriented) */
663 : OGRErr SetTMSO(double dfCenterLat, double dfCenterLong, double dfScale,
664 : double dfFalseEasting, double dfFalseNorthing);
665 :
666 : /** Two Point Equidistant */
667 : OGRErr SetTPED(double dfLat1, double dfLong1, double dfLat2, double dfLong2,
668 : double dfFalseEasting, double dfFalseNorthing);
669 :
670 : /** VanDerGrinten */
671 : OGRErr SetVDG(double dfCenterLong, double dfFalseEasting,
672 : double dfFalseNorthing);
673 :
674 : /** Universal Transverse Mercator */
675 : OGRErr SetUTM(int nZone, int bNorth = TRUE);
676 : int GetUTMZone(int *pbNorth = nullptr) const;
677 :
678 : /** Wagner I \-- VII */
679 : OGRErr SetWagner(int nVariation, double dfCenterLat, double dfFalseEasting,
680 : double dfFalseNorthing);
681 :
682 : /** Quadrilateralized Spherical Cube */
683 : OGRErr SetQSC(double dfCenterLat, double dfCenterLong);
684 :
685 : /** Spherical, Cross-track, Height */
686 : OGRErr SetSCH(double dfPegLat, double dfPegLong, double dfPegHeading,
687 : double dfPegHgt);
688 :
689 : /** Vertical Perspective / Near-sided Perspective */
690 : OGRErr
691 : SetVerticalPerspective(double dfTopoOriginLat, double dfTopoOriginLon,
692 : double dfTopoOriginHeight, double dfViewPointHeight,
693 : double dfFalseEasting, double dfFalseNorthing);
694 :
695 : /** Pole rotation (GRIB convention) */
696 : OGRErr SetDerivedGeogCRSWithPoleRotationGRIBConvention(
697 : const char *pszCRSName, double dfSouthPoleLat, double dfSouthPoleLon,
698 : double dfAxisRotation);
699 :
700 : /** Pole rotation (netCDF CF convention) */
701 : OGRErr SetDerivedGeogCRSWithPoleRotationNetCDFCFConvention(
702 : const char *pszCRSName, double dfGridNorthPoleLat,
703 : double dfGridNorthPoleLon, double dfNorthPoleGridLon);
704 :
705 : /** State Plane */
706 : OGRErr SetStatePlane(int nZone, int bNAD83 = TRUE,
707 : const char *pszOverrideUnitName = nullptr,
708 : double dfOverrideUnit = 0.0);
709 :
710 : /** ImportFromESRIStatePlaneWKT */
711 : OGRErr ImportFromESRIStatePlaneWKT(int nCode, const char *pszDatumName,
712 : const char *pszUnitsName, int nPCSCode,
713 : const char *pszCRSName = nullptr);
714 :
715 : /** ImportFromESRIWisconsinWKT */
716 : OGRErr ImportFromESRIWisconsinWKT(const char *pszPrjName,
717 : double dfCentralMeridian,
718 : double dfLatOfOrigin,
719 : const char *pszUnitsName,
720 : const char *pszCRSName = nullptr);
721 :
722 : /*! @cond Doxygen_Suppress */
723 : void UpdateCoordinateSystemFromGeogCRS();
724 : /*! @endcond */
725 :
726 : static OGRSpatialReference *GetWGS84SRS();
727 :
728 : /** Convert a OGRSpatialReference* to a OGRSpatialReferenceH.
729 : * @since GDAL 2.3
730 : */
731 29788 : static inline OGRSpatialReferenceH ToHandle(OGRSpatialReference *poSRS)
732 : {
733 29788 : return reinterpret_cast<OGRSpatialReferenceH>(poSRS);
734 : }
735 :
736 : /** Convert a OGRSpatialReferenceH to a OGRSpatialReference*.
737 : * @since GDAL 2.3
738 : */
739 201505 : static inline OGRSpatialReference *FromHandle(OGRSpatialReferenceH hSRS)
740 : {
741 201505 : return reinterpret_cast<OGRSpatialReference *>(hSRS);
742 : }
743 : };
744 :
745 : /*! @cond Doxygen_Suppress */
746 : struct CPL_DLL OGRSpatialReferenceReleaser
747 : {
748 4307 : void operator()(OGRSpatialReference *poSRS) const
749 : {
750 4307 : if (poSRS)
751 4307 : poSRS->Release();
752 4307 : }
753 : };
754 :
755 : /*! @endcond */
756 :
757 : /************************************************************************/
758 : /* OGRCoordinateTransformation */
759 : /* */
760 : /* This is really just used as a base class for a private */
761 : /* implementation. */
762 : /************************************************************************/
763 :
764 : /**
765 : * Interface for transforming between coordinate systems.
766 : *
767 : * Currently, the only implementation within OGR is OGRProjCT, which
768 : * requires the PROJ library.
769 : *
770 : * Also, see OGRCreateCoordinateTransformation() for creating transformations.
771 : */
772 :
773 19130 : class CPL_DLL OGRCoordinateTransformation
774 : {
775 : public:
776 : virtual ~OGRCoordinateTransformation();
777 :
778 : static void DestroyCT(OGRCoordinateTransformation *poCT);
779 :
780 : // From CT_CoordinateTransformation
781 :
782 : /** Fetch internal source coordinate system. */
783 : virtual const OGRSpatialReference *GetSourceCS() const = 0;
784 :
785 : /** Fetch internal target coordinate system. */
786 : virtual const OGRSpatialReference *GetTargetCS() const = 0;
787 :
788 : /** Whether the transformer will emit CPLError */
789 0 : virtual bool GetEmitErrors() const
790 : {
791 0 : return false;
792 : }
793 :
794 : /** Set if the transformer must emit CPLError */
795 0 : virtual void SetEmitErrors(bool /*bEmitErrors*/)
796 : {
797 0 : }
798 :
799 : // From CT_MathTransform
800 :
801 : /**
802 : * Transform points from source to destination space.
803 : *
804 : * This method is the same as the C function OCTTransformEx().
805 : *
806 : * @param nCount number of points to transform (`size_t` type since 3.9,
807 : * `int` in previous versions).
808 : * @param x array of nCount X vertices, modified in place. Should not be
809 : * NULL.
810 : * @param y array of nCount Y vertices, modified in place. Should not be
811 : * NULL.
812 : * @param z array of nCount Z vertices, modified in place. Might be NULL.
813 : * @param pabSuccess array of per-point flags set to TRUE if that point
814 : * transforms, or FALSE if it does not. Might be NULL.
815 : *
816 : * @return TRUE on success, or FALSE if some or all points fail to
817 : * transform. When FALSE is returned the pabSuccess[] array indicates which
818 : * points succeeded or failed to transform. When TRUE is returned, all
819 : * values in pabSuccess[] are set to true.
820 : */
821 : int Transform(size_t nCount, double *x, double *y, double *z = nullptr,
822 : int *pabSuccess = nullptr);
823 :
824 : /**
825 : * Transform points from source to destination space.
826 : *
827 : * This method is the same as the C function OCTTransform4D().
828 : *
829 : * @param nCount number of points to transform (`size_t` type since 3.9,
830 : * `int` in previous versions).
831 : * @param x array of nCount X vertices, modified in place. Should not be
832 : * NULL.
833 : * @param y array of nCount Y vertices, modified in place. Should not be
834 : * NULL.
835 : * @param z array of nCount Z vertices, modified in place. Might be NULL.
836 : * @param t array of nCount time values, modified in place. Might be NULL.
837 : * @param pabSuccess array of per-point flags set to TRUE if that point
838 : * transforms, or FALSE if it does not. Might be NULL.
839 : *
840 : * @return TRUE on success, or FALSE if some or all points fail to
841 : * transform. When FALSE is returned the pabSuccess[] array indicates which
842 : * points succeeded or failed to transform. When TRUE is returned, all
843 : * values in pabSuccess[] are set to true.
844 : * Caution: prior to GDAL 3.11, TRUE could be returned if a
845 : * transformation could be found but not all points may
846 : * have necessarily succeed to transform.
847 : */
848 : virtual int Transform(size_t nCount, double *x, double *y, double *z,
849 : double *t, int *pabSuccess) = 0;
850 :
851 : /**
852 : * Transform points from source to destination space.
853 : *
854 : * This method is the same as the C function OCTTransform4DWithErrorCodes().
855 : *
856 : * @param nCount number of points to transform (`size_t` type since 3.9,
857 : * `int` in previous versions).
858 : * @param x array of nCount X vertices, modified in place. Should not be
859 : * NULL.
860 : * @param y array of nCount Y vertices, modified in place. Should not be
861 : * NULL.
862 : * @param z array of nCount Z vertices, modified in place. Might be NULL.
863 : * @param t array of nCount time values, modified in place. Might be NULL.
864 : * @param panErrorCodes Output array of nCount value that will be set to 0
865 : * for success, or a non-zero value for failure. Refer to PROJ 8 public
866 : * error codes. Might be NULL
867 : * @return TRUE on success, or FALSE if some or all points fail to
868 : * transform. When FALSE is returned the panErrorCodes[] array indicates
869 : * which points succeeded or failed to transform. When TRUE is returned, all
870 : * values in panErrorCodes[] are set to zero.
871 : * Caution: prior to GDAL 3.11, TRUE could be returned if a
872 : * transformation could be found but not all points may
873 : * have necessarily succeed to transform.
874 : * @since GDAL 3.3, and PROJ 8 to be able to use PROJ public error codes
875 : */
876 : virtual int TransformWithErrorCodes(size_t nCount, double *x, double *y,
877 : double *z, double *t,
878 : int *panErrorCodes);
879 :
880 : /** \brief Transform boundary.
881 : *
882 : * This method is the same as the C function OCTTransformBounds().
883 : *
884 : * Transform boundary densifying the edges to account for nonlinear
885 : * transformations along these edges and extracting the outermost bounds.
886 : *
887 : * If the destination CRS is geographic, the first axis is longitude,
888 : * and xmax < xmin then the bounds crossed the antimeridian.
889 : * In this scenario there are two polygons, one on each side of the
890 : * antimeridian. The first polygon should be constructed with (xmin, ymin,
891 : * 180, ymax) and the second with (-180, ymin, xmax, ymax).
892 : *
893 : * If the destination CRS is geographic, the first axis is latitude,
894 : * and ymax < ymin then the bounds crossed the antimeridian.
895 : * In this scenario there are two polygons, one on each side of the
896 : * antimeridian. The first polygon should be constructed with (ymin, xmin,
897 : * ymax, 180) and the second with (ymin, -180, ymax, xmax).
898 : *
899 : * @param xmin Minimum bounding coordinate of the first axis in source CRS.
900 : * @param ymin Minimum bounding coordinate of the second axis in source CRS.
901 : * @param xmax Maximum bounding coordinate of the first axis in source CRS.
902 : * @param ymax Maximum bounding coordinate of the second axis in source CRS.
903 : * @param out_xmin Minimum bounding coordinate of the first axis in target
904 : * CRS
905 : * @param out_ymin Minimum bounding coordinate of the second axis in target
906 : * CRS.
907 : * @param out_xmax Maximum bounding coordinate of the first axis in target
908 : * CRS.
909 : * @param out_ymax Maximum bounding coordinate of the second axis in target
910 : * CRS.
911 : * @param densify_pts Recommended to use 21. This is the number of points
912 : * to use to densify the bounding polygon in the transformation.
913 : * @return TRUE if successful. FALSE if failures encountered.
914 : * @since 3.4
915 : */
916 0 : virtual int TransformBounds(const double xmin, const double ymin,
917 : const double xmax, const double ymax,
918 : double *out_xmin, double *out_ymin,
919 : double *out_xmax, double *out_ymax,
920 : const int densify_pts)
921 : {
922 : (void)xmin;
923 : (void)xmax;
924 : (void)ymin;
925 : (void)ymax;
926 : (void)densify_pts;
927 0 : *out_xmin = HUGE_VAL;
928 0 : *out_ymin = HUGE_VAL;
929 0 : *out_xmax = HUGE_VAL;
930 0 : *out_ymax = HUGE_VAL;
931 0 : CPLError(CE_Failure, CPLE_AppDefined,
932 : "TransformBounds not implemented.");
933 0 : return false;
934 : }
935 :
936 : /** Convert a OGRCoordinateTransformation* to a
937 : * OGRCoordinateTransformationH.
938 : * @since GDAL 2.3
939 : */
940 : static inline OGRCoordinateTransformationH
941 3 : ToHandle(OGRCoordinateTransformation *poCT)
942 : {
943 3 : return reinterpret_cast<OGRCoordinateTransformationH>(poCT);
944 : }
945 :
946 : /** Convert a OGRCoordinateTransformationH to a
947 : * OGRCoordinateTransformation*.
948 : * @since GDAL 2.3
949 : */
950 : static inline OGRCoordinateTransformation *
951 1552 : FromHandle(OGRCoordinateTransformationH hCT)
952 : {
953 1552 : return reinterpret_cast<OGRCoordinateTransformation *>(hCT);
954 : }
955 :
956 : /** Clone
957 : * @since GDAL 3.1
958 : */
959 : virtual OGRCoordinateTransformation *Clone() const = 0;
960 :
961 : /** Return a coordinate transformation that performs the inverse
962 : * transformation of the current one.
963 : *
964 : * In some cases, this is not possible, and this method might return
965 : * nullptr, or fail to perform the transformations.
966 : *
967 : * @return the new coordinate transformation, or nullptr in case of error.
968 : * @since GDAL 3.3
969 : */
970 : virtual OGRCoordinateTransformation *GetInverse() const = 0;
971 :
972 : protected:
973 : /*! @cond Doxygen_Suppress */
974 8290 : OGRCoordinateTransformation() = default;
975 932 : OGRCoordinateTransformation(const OGRCoordinateTransformation &) = default;
976 : OGRCoordinateTransformation &
977 : operator=(const OGRCoordinateTransformation &) = default;
978 1292 : OGRCoordinateTransformation(OGRCoordinateTransformation &&) = default;
979 : OGRCoordinateTransformation &
980 : operator=(OGRCoordinateTransformation &&) = default;
981 : /*! @endcond */
982 : };
983 :
984 : OGRCoordinateTransformation CPL_DLL *
985 : OGRCreateCoordinateTransformation(const OGRSpatialReference *poSource,
986 : const OGRSpatialReference *poTarget);
987 :
988 : /**
989 : * Context for coordinate transformation.
990 : *
991 : * @since GDAL 3.0
992 : */
993 :
994 : struct CPL_DLL OGRCoordinateTransformationOptions
995 : {
996 : /*! @cond Doxygen_Suppress */
997 : private:
998 : friend class OGRProjCT;
999 : struct Private;
1000 : std::unique_ptr<Private> d;
1001 : /*! @endcond */
1002 :
1003 : public:
1004 : OGRCoordinateTransformationOptions();
1005 : OGRCoordinateTransformationOptions(
1006 : const OGRCoordinateTransformationOptions &);
1007 : OGRCoordinateTransformationOptions &
1008 : operator=(const OGRCoordinateTransformationOptions &);
1009 : ~OGRCoordinateTransformationOptions();
1010 :
1011 : bool SetAreaOfInterest(double dfWestLongitudeDeg, double dfSouthLatitudeDeg,
1012 : double dfEastLongitudeDeg,
1013 : double dfNorthLatitudeDeg);
1014 : bool SetDesiredAccuracy(double dfAccuracy);
1015 : bool SetBallparkAllowed(bool bAllowBallpark);
1016 : bool SetOnlyBest(bool bOnlyBest);
1017 :
1018 : bool SetCoordinateOperation(const char *pszCT, bool bReverseCT);
1019 : /*! @cond Doxygen_Suppress */
1020 : void SetSourceCenterLong(double dfCenterLong);
1021 : void SetTargetCenterLong(double dfCenterLong);
1022 : /*! @endcond */
1023 : };
1024 :
1025 : OGRCoordinateTransformation CPL_DLL *OGRCreateCoordinateTransformation(
1026 : const OGRSpatialReference *poSource, const OGRSpatialReference *poTarget,
1027 : const OGRCoordinateTransformationOptions &options);
1028 :
1029 : #endif /* ndef OGR_SPATIALREF_H_INCLUDED */
|