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