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 267976 : 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 474669 : int GetChildCount() const
75 : {
76 474669 : 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 673713 : const char *GetValue() const
93 : {
94 673713 : 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 : #ifdef DEPRECATE_OGRSPATIALREFERENCE_REF_COUNTING
183 : int Reference()
184 : CPL_WARN_DEPRECATED("Use OGRSpatialReferenceRefCountedPtr instead");
185 : int Dereference()
186 : CPL_WARN_DEPRECATED("Use OGRSpatialReferenceRefCountedPtr instead");
187 : int GetReferenceCount() const
188 : CPL_WARN_DEPRECATED("Use OGRSpatialReferenceRefCountedPtr instead");
189 : void Release()
190 : CPL_WARN_DEPRECATED("Use OGRSpatialReferenceRefCountedPtr instead");
191 : #else
192 : int Reference();
193 : int Dereference();
194 : int GetReferenceCount() const;
195 : void Release();
196 : #endif
197 :
198 : const char *GetName() const;
199 :
200 : OGRSpatialReference *Clone() const;
201 : OGRSpatialReference *CloneGeogCS() const;
202 :
203 : void dumpReadable();
204 : OGRErr exportToWkt(char **) const;
205 : OGRErr exportToWkt(char **ppszWKT, const char *const *papszOptions) const;
206 : std::string exportToWkt(const char *const *papszOptions = nullptr) const;
207 : OGRErr exportToPrettyWkt(char **, int = FALSE) const;
208 : // cppcheck-suppress functionStatic
209 : OGRErr exportToPROJJSON(char **, const char *const *papszOptions) const;
210 : OGRErr exportToProj4(char **) const;
211 : OGRErr exportToPCI(char **, char **, double **) const;
212 : OGRErr exportToUSGS(long *, long *, double **, long *) const;
213 : OGRErr exportToXML(char **, const char * = nullptr) const;
214 : OGRErr exportToPanorama(long *, long *, long *, long *, double *) const;
215 : OGRErr exportVertCSToPanorama(int *) const;
216 : OGRErr exportToERM(char *pszProj, char *pszDatum, char *pszUnits);
217 : OGRErr exportToMICoordSys(char **) const;
218 : OGRErr exportToCF1(char **ppszGridMappingName, char ***ppapszKeyValues,
219 : char **ppszUnits, CSLConstList papszOptions) const;
220 :
221 : OGRErr importFromWkt(char **)
222 : /*! @cond Doxygen_Suppress */
223 : CPL_WARN_DEPRECATED(
224 : "Use importFromWkt(const char**) or importFromWkt(const char*)")
225 : /*! @endcond */
226 : ;
227 :
228 : OGRErr importFromWkt(const char **);
229 : /*! @cond Doxygen_Suppress */
230 : OGRErr importFromWkt(const char *pszInput, CSLConstList papszOptions);
231 : OGRErr importFromWkt(const char **ppszInput, CSLConstList papszOptions);
232 : /*! @endcond */
233 : OGRErr importFromWkt(const char *);
234 : OGRErr importFromProj4(const char *);
235 : OGRErr importFromEPSG(int);
236 : OGRErr importFromEPSGA(int);
237 : OGRErr importFromESRI(char **);
238 : OGRErr importFromPCI(const char *, const char * = nullptr,
239 : const double * = nullptr);
240 :
241 : #define USGS_ANGLE_DECIMALDEGREES 0 /**< Angle is in decimal degrees. */
242 : #define USGS_ANGLE_PACKEDDMS \
243 : TRUE /**< Angle is in packed degree minute second. */
244 : #define USGS_ANGLE_RADIANS 2 /**< Angle is in radians. */
245 : OGRErr importFromUSGS(long iProjSys, long iZone, double *padfPrjParams,
246 : long iDatum,
247 : int nUSGSAngleFormat = USGS_ANGLE_PACKEDDMS);
248 : OGRErr importFromPanorama(long, long, long, double *, bool bNorth = true);
249 : OGRErr importVertCSFromPanorama(int);
250 : OGRErr importFromOzi(const char *const *papszLines);
251 : OGRErr importFromWMSAUTO(const char *pszAutoDef);
252 : OGRErr importFromXML(const char *);
253 : OGRErr importFromDict(const char *pszDict, const char *pszCode);
254 : OGRErr importFromURN(const char *);
255 : OGRErr importFromCRSURL(const char *);
256 : OGRErr importFromERM(const char *pszProj, const char *pszDatum,
257 : const char *pszUnits);
258 : OGRErr importFromUrl(const char *);
259 : OGRErr importFromMICoordSys(const char *);
260 : OGRErr importFromCF1(CSLConstList papszKeyValues, const char *pszUnits);
261 :
262 : OGRErr morphToESRI();
263 : OGRErr morphFromESRI();
264 :
265 : OGRSpatialReference *
266 : convertToOtherProjection(const char *pszTargetProjection,
267 : const char *const *papszOptions = nullptr) const;
268 :
269 : OGRErr Validate() const;
270 : OGRErr StripVertical();
271 :
272 : bool StripTOWGS84IfKnownDatumAndAllowed();
273 : bool StripTOWGS84IfKnownDatum();
274 :
275 : int EPSGTreatsAsLatLong() const;
276 : int EPSGTreatsAsNorthingEasting() const;
277 : int GetAxesCount() const;
278 : const char *GetAxis(const char *pszTargetKey, int iAxis,
279 : OGRAxisOrientation *peOrientation,
280 : double *pdfConvFactor = nullptr) const;
281 : OGRErr SetAxes(const char *pszTargetKey, const char *pszXAxisName,
282 : OGRAxisOrientation eXAxisOrientation,
283 : const char *pszYAxisName,
284 : OGRAxisOrientation eYAxisOrientation);
285 :
286 : OSRAxisMappingStrategy GetAxisMappingStrategy() const;
287 : void SetAxisMappingStrategy(OSRAxisMappingStrategy);
288 : const std::vector<int> &GetDataAxisToSRSAxisMapping() const;
289 : OGRErr SetDataAxisToSRSAxisMapping(const std::vector<int> &mapping);
290 :
291 : // Machinery for accessing parse nodes
292 :
293 : //! Return root node
294 : OGR_SRSNode *GetRoot();
295 : //! Return root node
296 : const OGR_SRSNode *GetRoot() const;
297 : void SetRoot(OGR_SRSNode *);
298 :
299 : OGR_SRSNode *GetAttrNode(const char *);
300 : const OGR_SRSNode *GetAttrNode(const char *) const;
301 : const char *GetAttrValue(const char *, int = 0) const;
302 :
303 : OGRErr SetNode(const char *, const char *);
304 : // cppcheck-suppress functionStatic
305 : OGRErr SetNode(const char *, double);
306 :
307 : OGRErr
308 : SetLinearUnitsAndUpdateParameters(const char *pszName, double dfInMeters,
309 : const char *pszUnitAuthority = nullptr,
310 : const char *pszUnitCode = nullptr);
311 : OGRErr SetLinearUnits(const char *pszName, double dfInMeters);
312 : OGRErr SetTargetLinearUnits(const char *pszTargetKey, const char *pszName,
313 : double dfInMeters,
314 : const char *pszUnitAuthority = nullptr,
315 : const char *pszUnitCode = nullptr);
316 :
317 : double GetLinearUnits(char **) const
318 : /*! @cond Doxygen_Suppress */
319 : CPL_WARN_DEPRECATED("Use GetLinearUnits(const char**) instead")
320 : /*! @endcond */
321 : ;
322 : double GetLinearUnits(const char ** = nullptr) const;
323 :
324 : /*! @cond Doxygen_Suppress */
325 5952 : double GetLinearUnits(std::nullptr_t) const
326 : {
327 5952 : return GetLinearUnits(static_cast<const char **>(nullptr));
328 : }
329 :
330 : /*! @endcond */
331 :
332 : double GetTargetLinearUnits(const char *pszTargetKey,
333 : char **ppszRetName) const
334 : /*! @cond Doxygen_Suppress */
335 : CPL_WARN_DEPRECATED(
336 : "Use GetTargetLinearUnits(const char*, const char**)")
337 : /*! @endcond */
338 : ;
339 : double GetTargetLinearUnits(const char *pszTargetKey,
340 : const char **ppszRetName = nullptr) const;
341 :
342 : /*! @cond Doxygen_Suppress */
343 : double GetTargetLinearUnits(const char *pszTargetKey, std::nullptr_t) const
344 : {
345 : return GetTargetLinearUnits(pszTargetKey,
346 : static_cast<const char **>(nullptr));
347 : }
348 :
349 : /*! @endcond */
350 :
351 : OGRErr SetAngularUnits(const char *pszName, double dfInRadians);
352 : double GetAngularUnits(char **) const
353 : /*! @cond Doxygen_Suppress */
354 : CPL_WARN_DEPRECATED("Use GetAngularUnits(const char**) instead")
355 : /*! @endcond */
356 : ;
357 : double GetAngularUnits(const char ** = nullptr) const;
358 :
359 : /*! @cond Doxygen_Suppress */
360 2266 : double GetAngularUnits(std::nullptr_t) const
361 : {
362 2266 : return GetAngularUnits(static_cast<const char **>(nullptr));
363 : }
364 :
365 : /*! @endcond */
366 :
367 : double GetPrimeMeridian(char **) const
368 : /*! @cond Doxygen_Suppress */
369 : CPL_WARN_DEPRECATED("Use GetPrimeMeridian(const char**) instead")
370 : /*! @endcond */
371 : ;
372 : double GetPrimeMeridian(const char ** = nullptr) const;
373 :
374 : /*! @cond Doxygen_Suppress */
375 1248 : double GetPrimeMeridian(std::nullptr_t) const
376 : {
377 1248 : return GetPrimeMeridian(static_cast<const char **>(nullptr));
378 : }
379 :
380 : /*! @endcond */
381 :
382 : bool IsEmpty() const;
383 : int IsGeographic() const;
384 : int IsDerivedGeographic() const;
385 : int IsProjected() const;
386 : int IsDerivedProjected() const;
387 : int IsGeocentric() const;
388 : bool IsDynamic() const;
389 :
390 : // cppcheck-suppress functionStatic
391 : bool HasPointMotionOperation() const;
392 :
393 : int IsLocal() const;
394 : int IsVertical() const;
395 : int IsCompound() const;
396 : int IsSameGeogCS(const OGRSpatialReference *) const;
397 : int IsSameGeogCS(const OGRSpatialReference *,
398 : const char *const *papszOptions) const;
399 : int IsSameVertCS(const OGRSpatialReference *) const;
400 : int IsSame(const OGRSpatialReference *) const;
401 : int IsSame(const OGRSpatialReference *,
402 : const char *const *papszOptions) const;
403 :
404 : const char *GetCelestialBodyName() const;
405 :
406 : void Clear();
407 : OGRErr SetLocalCS(const char *);
408 : OGRErr SetProjCS(const char *);
409 : OGRErr SetProjection(const char *);
410 : OGRErr SetGeocCS(const char *pszGeocName);
411 : OGRErr SetGeogCS(const char *pszGeogName, const char *pszDatumName,
412 : const char *pszEllipsoidName, double dfSemiMajor,
413 : double dfInvFlattening, const char *pszPMName = nullptr,
414 : double dfPMOffset = 0.0, const char *pszUnits = nullptr,
415 : double dfConvertToRadians = 0.0);
416 : OGRErr SetWellKnownGeogCS(const char *);
417 : OGRErr CopyGeogCSFrom(const OGRSpatialReference *poSrcSRS);
418 : OGRErr SetVertCS(const char *pszVertCSName, const char *pszVertDatumName,
419 : int nVertDatumClass = 2005);
420 : OGRErr SetCompoundCS(const char *pszName,
421 : const OGRSpatialReference *poHorizSRS,
422 : const OGRSpatialReference *poVertSRS);
423 :
424 : void SetCoordinateEpoch(double dfCoordinateEpoch);
425 : double GetCoordinateEpoch() const;
426 :
427 : // cppcheck-suppress functionStatic
428 : OGRErr PromoteTo3D(const char *pszName);
429 : // cppcheck-suppress functionStatic
430 : OGRErr DemoteTo2D(const char *pszName);
431 :
432 : OGRErr SetFromUserInput(const char *);
433 :
434 : static const char *const SET_FROM_USER_INPUT_LIMITATIONS[];
435 : static CSLConstList SET_FROM_USER_INPUT_LIMITATIONS_get();
436 :
437 : OGRErr SetFromUserInput(const char *, CSLConstList papszOptions);
438 :
439 : OGRErr SetTOWGS84(double, double, double, double = 0.0, double = 0.0,
440 : double = 0.0, double = 0.0);
441 : OGRErr GetTOWGS84(double *padfCoef, int nCoeff = 7) const;
442 : OGRErr AddGuessedTOWGS84();
443 :
444 : double GetSemiMajor(OGRErr * = nullptr) const;
445 : double GetSemiMinor(OGRErr * = nullptr) const;
446 : double GetInvFlattening(OGRErr * = nullptr) const;
447 : double GetEccentricity() const;
448 : double GetSquaredEccentricity() const;
449 :
450 : OGRErr SetAuthority(const char *pszTargetKey, const char *pszAuthority,
451 : int nCode);
452 :
453 : OGRErr AutoIdentifyEPSG();
454 : OGRSpatialReferenceH *FindMatches(CSLConstList papszOptions, int *pnEntries,
455 : int **ppanMatchConfidence) const;
456 : OGRSpatialReference *
457 : FindBestMatch(int nMinimumMatchConfidence = 90,
458 : const char *pszPreferredAuthority = "EPSG",
459 : CSLConstList papszOptions = nullptr) const;
460 :
461 : int GetEPSGGeogCS() const;
462 :
463 : const char *GetAuthorityCode(const char *pszTargetKey = nullptr) const;
464 : const char *GetAuthorityName(const char *pszTargetKey = nullptr) const;
465 : char *GetOGCURN() const;
466 :
467 : bool GetAreaOfUse(double *pdfWestLongitudeDeg, double *pdfSouthLatitudeDeg,
468 : double *pdfEastLongitudeDeg, double *pdfNorthLatitudeDeg,
469 : const char **ppszAreaName) const;
470 :
471 : const char *GetExtension(const char *pszTargetKey, const char *pszName,
472 : const char *pszDefault = nullptr) const;
473 : OGRErr SetExtension(const char *pszTargetKey, const char *pszName,
474 : const char *pszValue);
475 :
476 : int FindProjParm(const char *pszParameter,
477 : const OGR_SRSNode *poPROJCS = nullptr) const;
478 : OGRErr SetProjParm(const char *, double);
479 : double GetProjParm(const char *, double = 0.0, OGRErr * = nullptr) const;
480 :
481 : OGRErr SetNormProjParm(const char *, double);
482 : double GetNormProjParm(const char *, double = 0.0,
483 : OGRErr * = nullptr) const;
484 :
485 : static int IsAngularParameter(const char *);
486 : static int IsLongitudeParameter(const char *);
487 : static int IsLinearParameter(const char *);
488 :
489 : /** Albers Conic Equal Area */
490 : OGRErr SetACEA(double dfStdP1, double dfStdP2, double dfCenterLat,
491 : double dfCenterLong, double dfFalseEasting,
492 : double dfFalseNorthing);
493 :
494 : /** Azimuthal Equidistant */
495 : OGRErr SetAE(double dfCenterLat, double dfCenterLong, double dfFalseEasting,
496 : double dfFalseNorthing);
497 :
498 : /** Bonne */
499 : OGRErr SetBonne(double dfStdP1, double dfCentralMeridian,
500 : double dfFalseEasting, double dfFalseNorthing);
501 :
502 : /** Cylindrical Equal Area */
503 : OGRErr SetCEA(double dfStdP1, double dfCentralMeridian,
504 : double dfFalseEasting, double dfFalseNorthing);
505 :
506 : /** Cassini-Soldner */
507 : OGRErr SetCS(double dfCenterLat, double dfCenterLong, double dfFalseEasting,
508 : double dfFalseNorthing);
509 :
510 : /** Equidistant Conic */
511 : OGRErr SetEC(double dfStdP1, double dfStdP2, double dfCenterLat,
512 : double dfCenterLong, double dfFalseEasting,
513 : double dfFalseNorthing);
514 :
515 : /** Eckert I */
516 : OGRErr SetEckert(int nVariation, double dfCentralMeridian,
517 : double dfFalseEasting, double dfFalseNorthing);
518 :
519 : /** Eckert IV */
520 : OGRErr SetEckertIV(double dfCentralMeridian, double dfFalseEasting,
521 : double dfFalseNorthing);
522 :
523 : /** Eckert VI */
524 : OGRErr SetEckertVI(double dfCentralMeridian, double dfFalseEasting,
525 : double dfFalseNorthing);
526 :
527 : /** Equirectangular */
528 : OGRErr SetEquirectangular(double dfCenterLat, double dfCenterLong,
529 : double dfFalseEasting, double dfFalseNorthing);
530 : /** Equirectangular generalized form : */
531 : OGRErr SetEquirectangular2(double dfCenterLat, double dfCenterLong,
532 : double dfPseudoStdParallel1,
533 : double dfFalseEasting, double dfFalseNorthing);
534 :
535 : /** Geostationary Satellite */
536 : OGRErr SetGEOS(double dfCentralMeridian, double dfSatelliteHeight,
537 : double dfFalseEasting, double dfFalseNorthing);
538 :
539 : /** Goode Homolosine */
540 : OGRErr SetGH(double dfCentralMeridian, double dfFalseEasting,
541 : double dfFalseNorthing);
542 :
543 : /** Interrupted Goode Homolosine */
544 : OGRErr SetIGH();
545 :
546 : /** Gall Stereographic */
547 : OGRErr SetGS(double dfCentralMeridian, double dfFalseEasting,
548 : double dfFalseNorthing);
549 :
550 : /** Gauss Schreiber Transverse Mercator */
551 : OGRErr SetGaussSchreiberTMercator(double dfCenterLat, double dfCenterLong,
552 : double dfScale, double dfFalseEasting,
553 : double dfFalseNorthing);
554 :
555 : /** Gnomonic */
556 : OGRErr SetGnomonic(double dfCenterLat, double dfCenterLong,
557 : double dfFalseEasting, double dfFalseNorthing);
558 :
559 : /** Hotine Oblique Mercator */
560 : OGRErr SetHOM(double dfCenterLat, double dfCenterLong, double dfAzimuth,
561 : double dfRectToSkew, double dfScale, double dfFalseEasting,
562 : double dfFalseNorthing);
563 :
564 : /** Hotine Oblique Mercator 2 points */
565 : OGRErr SetHOM2PNO(double dfCenterLat, double dfLat1, double dfLong1,
566 : double dfLat2, double dfLong2, double dfScale,
567 : double dfFalseEasting, double dfFalseNorthing);
568 :
569 : /** Hotine Oblique Mercator Azimuth Center / Variant B */
570 : OGRErr SetHOMAC(double dfCenterLat, double dfCenterLong, double dfAzimuth,
571 : double dfRectToSkew, double dfScale, double dfFalseEasting,
572 : double dfFalseNorthing);
573 :
574 : /** Laborde Oblique Mercator */
575 : OGRErr SetLOM(double dfCenterLat, double dfCenterLong, double dfAzimuth,
576 : double dfScale, double dfFalseEasting,
577 : double dfFalseNorthing);
578 :
579 : /** International Map of the World Polyconic */
580 : OGRErr SetIWMPolyconic(double dfLat1, double dfLat2, double dfCenterLong,
581 : double dfFalseEasting, double dfFalseNorthing);
582 :
583 : /** Krovak Oblique Conic Conformal */
584 : OGRErr SetKrovak(double dfCenterLat, double dfCenterLong, double dfAzimuth,
585 : double dfPseudoStdParallelLat, double dfScale,
586 : double dfFalseEasting, double dfFalseNorthing);
587 :
588 : /** Lambert Azimuthal Equal-Area */
589 : OGRErr SetLAEA(double dfCenterLat, double dfCenterLong,
590 : double dfFalseEasting, double dfFalseNorthing);
591 :
592 : /** Lambert Conformal Conic */
593 : OGRErr SetLCC(double dfStdP1, double dfStdP2, double dfCenterLat,
594 : double dfCenterLong, double dfFalseEasting,
595 : double dfFalseNorthing);
596 :
597 : /** Lambert Conformal Conic 1SP */
598 : OGRErr SetLCC1SP(double dfCenterLat, double dfCenterLong, double dfScale,
599 : double dfFalseEasting, double dfFalseNorthing);
600 :
601 : /** Lambert Conformal Conic (Belgium) */
602 : OGRErr SetLCCB(double dfStdP1, double dfStdP2, double dfCenterLat,
603 : double dfCenterLong, double dfFalseEasting,
604 : double dfFalseNorthing);
605 :
606 : /** Miller Cylindrical */
607 : OGRErr SetMC(double dfCenterLat, double dfCenterLong, double dfFalseEasting,
608 : double dfFalseNorthing);
609 :
610 : /** Mercator 1SP */
611 : OGRErr SetMercator(double dfCenterLat, double dfCenterLong, double dfScale,
612 : double dfFalseEasting, double dfFalseNorthing);
613 :
614 : /** Mercator 2SP */
615 : OGRErr SetMercator2SP(double dfStdP1, double dfCenterLat,
616 : double dfCenterLong, double dfFalseEasting,
617 : double dfFalseNorthing);
618 :
619 : /** Mollweide */
620 : OGRErr SetMollweide(double dfCentralMeridian, double dfFalseEasting,
621 : double dfFalseNorthing);
622 :
623 : /** New Zealand Map Grid */
624 : OGRErr SetNZMG(double dfCenterLat, double dfCenterLong,
625 : double dfFalseEasting, double dfFalseNorthing);
626 :
627 : /** Oblique Stereographic */
628 : OGRErr SetOS(double dfOriginLat, double dfCMeridian, double dfScale,
629 : double dfFalseEasting, double dfFalseNorthing);
630 :
631 : /** Orthographic */
632 : OGRErr SetOrthographic(double dfCenterLat, double dfCenterLong,
633 : double dfFalseEasting, double dfFalseNorthing);
634 :
635 : /** Polyconic */
636 : OGRErr SetPolyconic(double dfCenterLat, double dfCenterLong,
637 : double dfFalseEasting, double dfFalseNorthing);
638 :
639 : /** Polar Stereographic */
640 : OGRErr SetPS(double dfCenterLat, double dfCenterLong, double dfScale,
641 : double dfFalseEasting, double dfFalseNorthing);
642 :
643 : /** Robinson */
644 : OGRErr SetRobinson(double dfCenterLong, double dfFalseEasting,
645 : double dfFalseNorthing);
646 :
647 : /** Sinusoidal */
648 : OGRErr SetSinusoidal(double dfCenterLong, double dfFalseEasting,
649 : double dfFalseNorthing);
650 :
651 : /** Stereographic */
652 : OGRErr SetStereographic(double dfCenterLat, double dfCenterLong,
653 : double dfScale, double dfFalseEasting,
654 : double dfFalseNorthing);
655 :
656 : /** Swiss Oblique Cylindrical */
657 : OGRErr SetSOC(double dfLatitudeOfOrigin, double dfCentralMeridian,
658 : double dfFalseEasting, double dfFalseNorthing);
659 :
660 : /** Transverse Mercator */
661 : OGRErr SetTM(double dfCenterLat, double dfCenterLong, double dfScale,
662 : double dfFalseEasting, double dfFalseNorthing);
663 :
664 : /** Transverse Mercator variants. */
665 : OGRErr SetTMVariant(const char *pszVariantName, double dfCenterLat,
666 : double dfCenterLong, double dfScale,
667 : double dfFalseEasting, double dfFalseNorthing);
668 :
669 : /** Tunesia Mining Grid */
670 : OGRErr SetTMG(double dfCenterLat, double dfCenterLong,
671 : double dfFalseEasting, double dfFalseNorthing);
672 :
673 : /** Transverse Mercator (South Oriented) */
674 : OGRErr SetTMSO(double dfCenterLat, double dfCenterLong, double dfScale,
675 : double dfFalseEasting, double dfFalseNorthing);
676 :
677 : /** Two Point Equidistant */
678 : OGRErr SetTPED(double dfLat1, double dfLong1, double dfLat2, double dfLong2,
679 : double dfFalseEasting, double dfFalseNorthing);
680 :
681 : /** VanDerGrinten */
682 : OGRErr SetVDG(double dfCenterLong, double dfFalseEasting,
683 : double dfFalseNorthing);
684 :
685 : /** Universal Transverse Mercator */
686 : OGRErr SetUTM(int nZone, int bNorth = TRUE);
687 : int GetUTMZone(int *pbNorth = nullptr) const;
688 :
689 : /** Wagner I \-- VII */
690 : OGRErr SetWagner(int nVariation, double dfCenterLat, double dfFalseEasting,
691 : double dfFalseNorthing);
692 :
693 : /** Quadrilateralized Spherical Cube */
694 : OGRErr SetQSC(double dfCenterLat, double dfCenterLong);
695 :
696 : /** Spherical, Cross-track, Height */
697 : OGRErr SetSCH(double dfPegLat, double dfPegLong, double dfPegHeading,
698 : double dfPegHgt);
699 :
700 : /** Vertical Perspective / Near-sided Perspective */
701 : OGRErr
702 : SetVerticalPerspective(double dfTopoOriginLat, double dfTopoOriginLon,
703 : double dfTopoOriginHeight, double dfViewPointHeight,
704 : double dfFalseEasting, double dfFalseNorthing);
705 :
706 : /** Pole rotation (GRIB convention) */
707 : OGRErr SetDerivedGeogCRSWithPoleRotationGRIBConvention(
708 : const char *pszCRSName, double dfSouthPoleLat, double dfSouthPoleLon,
709 : double dfAxisRotation);
710 :
711 : /** Pole rotation (netCDF CF convention) */
712 : OGRErr SetDerivedGeogCRSWithPoleRotationNetCDFCFConvention(
713 : const char *pszCRSName, double dfGridNorthPoleLat,
714 : double dfGridNorthPoleLon, double dfNorthPoleGridLon);
715 :
716 : /** State Plane */
717 : OGRErr SetStatePlane(int nZone, int bNAD83 = TRUE,
718 : const char *pszOverrideUnitName = nullptr,
719 : double dfOverrideUnit = 0.0);
720 :
721 : /** ImportFromESRIStatePlaneWKT */
722 : OGRErr ImportFromESRIStatePlaneWKT(int nCode, const char *pszDatumName,
723 : const char *pszUnitsName, int nPCSCode,
724 : const char *pszCRSName = nullptr);
725 :
726 : /** ImportFromESRIWisconsinWKT */
727 : OGRErr ImportFromESRIWisconsinWKT(const char *pszPrjName,
728 : double dfCentralMeridian,
729 : double dfLatOfOrigin,
730 : const char *pszUnitsName,
731 : const char *pszCRSName = nullptr);
732 :
733 : /*! @cond Doxygen_Suppress */
734 : void UpdateCoordinateSystemFromGeogCRS();
735 : /*! @endcond */
736 :
737 : static OGRSpatialReference *GetWGS84SRS();
738 :
739 : /** Convert a OGRSpatialReference* to a OGRSpatialReferenceH.
740 : */
741 33870 : static inline OGRSpatialReferenceH ToHandle(OGRSpatialReference *poSRS)
742 : {
743 33870 : return reinterpret_cast<OGRSpatialReferenceH>(poSRS);
744 : }
745 :
746 : /** Convert a OGRSpatialReferenceH to a OGRSpatialReference*.
747 : */
748 207634 : static inline OGRSpatialReference *FromHandle(OGRSpatialReferenceH hSRS)
749 : {
750 207634 : return reinterpret_cast<OGRSpatialReference *>(hSRS);
751 : }
752 : };
753 :
754 : /*! @cond Doxygen_Suppress */
755 :
756 : #include "ogr_refcountedptr.h"
757 :
758 : template <>
759 : struct OGRRefCountedPtr<OGRSpatialReference>
760 : : public OGRRefCountedPtrBase<OGRSpatialReference>
761 : {
762 : /** Constructs from a raw OGRSpatialReference instance.
763 : *
764 : * Be careful: a fresh OGRSpatialReference instance has a reference count
765 : * equal to one, so you generally want to set add_ref = false
766 : * So ``OGRSpatialReferenceRefCountedPtr srs(new OGRSpatialReference(), false)``
767 : * or less error prone ``auto srs = OGRSpatialReferenceRefCountedPtr::makeInstance()``
768 : */
769 20681 : inline explicit OGRRefCountedPtr(OGRSpatialReference *poSRS, bool add_ref)
770 20681 : : OGRRefCountedPtrBase<OGRSpatialReference>(poSRS, add_ref)
771 : {
772 20681 : }
773 :
774 : /** Constructs with a null OGRSpatialReference instance.
775 : */
776 27708 : inline OGRRefCountedPtr()
777 27708 : {
778 27708 : }
779 :
780 : /** Constructs with a null OGRSpatialReference instance.
781 : */
782 : // cppcheck-suppress noExplicitConstructor
783 123698 : inline /* implicit */ OGRRefCountedPtr(std::nullptr_t)
784 123698 : {
785 123698 : }
786 :
787 : /** Constructs with a new OGRSpatialReference instance initialized
788 : * with a WKT string (or in an empty state if pszWKT is nullptr).
789 : */
790 5735 : inline static OGRRefCountedPtr makeInstance(const char *pszWKT = nullptr)
791 : {
792 : // Initial ref_count of OGRSpatialReference is 1, so don't add a ref
793 5735 : return OGRRefCountedPtr(new OGRSpatialReference(pszWKT),
794 5735 : /* add_ref = */ false);
795 : }
796 :
797 : /** Constructs with a clone of an existing OGRSpatialReference instance.
798 : */
799 13933 : inline static OGRRefCountedPtr makeClone(const OGRSpatialReference *poSRS)
800 : {
801 5267 : return OGRRefCountedPtr(poSRS ? poSRS->Clone() : nullptr,
802 19200 : /* add_ref = */ false);
803 : }
804 :
805 : /** Constructs with a clone of an existing OGRSpatialReference instance.
806 : */
807 10 : inline static OGRRefCountedPtr makeClone(const OGRSpatialReference &oSRS)
808 : {
809 : return OGRRefCountedPtr(oSRS.Clone(),
810 10 : /* add_ref = */ false);
811 : }
812 :
813 : /** Reset the managed raw pointer.
814 : *
815 : * Release the current managed raw pointer.
816 : */
817 4 : inline void reset()
818 : {
819 4 : OGRRefCountedPtrBase<OGRSpatialReference>::reset(nullptr, false);
820 4 : }
821 :
822 : /** Reset the managed raw pointer.
823 : *
824 : * Release the current managed raw pointer and manages a new one.
825 : * By default, increases the reference count of the new raw pointer (when
826 : * not null).
827 : */
828 38476 : inline void reset(OGRSpatialReference *poRawPtr, bool add_ref)
829 : {
830 38476 : OGRRefCountedPtrBase<OGRSpatialReference>::reset(poRawPtr, add_ref);
831 38476 : }
832 :
833 : /** Use reset(OGRSpatialReference *poRawPtr, bool add_ref) to be explicit
834 : * about ref counting.
835 : */
836 : inline void reset(OGRSpatialReference *poRawPtr) = delete;
837 : };
838 :
839 : /** Smart pointer around OGRSpatialReference.
840 : *
841 : * It uses OGRSpatialReference built-in reference counting, to increase the reference
842 : * count when assigning a raw pointer to the smart pointer, and decrease it
843 : * when releasing it.
844 : * Somewhat similar to https://www.boost.org/doc/libs/latest/libs/smart_ptr/doc/html/smart_ptr.html#intrusive_ptr
845 : */
846 : using OGRSpatialReferenceRefCountedPtr = OGRRefCountedPtr<OGRSpatialReference>;
847 :
848 : /*! @endcond */
849 :
850 : /************************************************************************/
851 : /* OGRCoordinateTransformation */
852 : /* */
853 : /* This is really just used as a base class for a private */
854 : /* implementation. */
855 : /************************************************************************/
856 :
857 : /**
858 : * Interface for transforming between coordinate systems.
859 : *
860 : * Currently, the only implementation within OGR is OGRProjCT, which
861 : * requires the PROJ library.
862 : *
863 : * Also, see OGRCreateCoordinateTransformation() for creating transformations.
864 : */
865 :
866 20524 : class CPL_DLL OGRCoordinateTransformation
867 : {
868 : public:
869 : virtual ~OGRCoordinateTransformation();
870 :
871 : static void DestroyCT(OGRCoordinateTransformation *poCT);
872 :
873 : // From CT_CoordinateTransformation
874 :
875 : /** Fetch internal source coordinate system. */
876 : virtual const OGRSpatialReference *GetSourceCS() const = 0;
877 :
878 : /** Fetch internal target coordinate system. */
879 : virtual const OGRSpatialReference *GetTargetCS() const = 0;
880 :
881 : /** Whether the transformer will emit CPLError */
882 0 : virtual bool GetEmitErrors() const
883 : {
884 0 : return false;
885 : }
886 :
887 : /** Set if the transformer must emit CPLError */
888 0 : virtual void SetEmitErrors(bool /*bEmitErrors*/)
889 : {
890 0 : }
891 :
892 : // From CT_MathTransform
893 :
894 : /**
895 : * Transform points from source to destination space.
896 : *
897 : * This method is the same as the C function OCTTransformEx().
898 : *
899 : * @param nCount number of points to transform (`size_t` type since 3.9,
900 : * `int` in previous versions).
901 : * @param x array of nCount X vertices, modified in place. Should not be
902 : * NULL.
903 : * @param y array of nCount Y vertices, modified in place. Should not be
904 : * NULL.
905 : * @param z array of nCount Z vertices, modified in place. Might be NULL.
906 : * @param pabSuccess array of per-point flags set to TRUE if that point
907 : * transforms, or FALSE if it does not. Might be NULL.
908 : *
909 : * @return TRUE on success, or FALSE if some or all points fail to
910 : * transform. When FALSE is returned the pabSuccess[] array indicates which
911 : * points succeeded or failed to transform. When TRUE is returned, all
912 : * values in pabSuccess[] are set to true.
913 : */
914 : int Transform(size_t nCount, double *x, double *y, double *z = nullptr,
915 : int *pabSuccess = nullptr);
916 :
917 : /**
918 : * Transform points from source to destination space.
919 : *
920 : * This method is the same as the C function OCTTransform4D().
921 : *
922 : * @param nCount number of points to transform (`size_t` type since 3.9,
923 : * `int` in previous versions).
924 : * @param x array of nCount X vertices, modified in place. Should not be
925 : * NULL.
926 : * @param y array of nCount Y vertices, modified in place. Should not be
927 : * NULL.
928 : * @param z array of nCount Z vertices, modified in place. Might be NULL.
929 : * @param t array of nCount time values, modified in place. Might be NULL.
930 : * @param pabSuccess array of per-point flags set to TRUE if that point
931 : * transforms, or FALSE if it does not. Might be NULL.
932 : *
933 : * @return TRUE on success, or FALSE if some or all points fail to
934 : * transform. When FALSE is returned the pabSuccess[] array indicates which
935 : * points succeeded or failed to transform. When TRUE is returned, all
936 : * values in pabSuccess[] are set to true.
937 : * Caution: prior to GDAL 3.11, TRUE could be returned if a
938 : * transformation could be found but not all points may
939 : * have necessarily succeed to transform.
940 : */
941 : virtual int Transform(size_t nCount, double *x, double *y, double *z,
942 : double *t, int *pabSuccess) = 0;
943 :
944 : /**
945 : * Transform points from source to destination space.
946 : *
947 : * This method is the same as the C function OCTTransform4DWithErrorCodes().
948 : *
949 : * @param nCount number of points to transform (`size_t` type since 3.9,
950 : * `int` in previous versions).
951 : * @param x array of nCount X vertices, modified in place. Should not be
952 : * NULL.
953 : * @param y array of nCount Y vertices, modified in place. Should not be
954 : * NULL.
955 : * @param z array of nCount Z vertices, modified in place. Might be NULL.
956 : * @param t array of nCount time values, modified in place. Might be NULL.
957 : * @param panErrorCodes Output array of nCount value that will be set to 0
958 : * for success, or a non-zero value for failure. Refer to PROJ 8 public
959 : * error codes. Might be NULL
960 : * @return TRUE on success, or FALSE if some or all points fail to
961 : * transform. When FALSE is returned the panErrorCodes[] array indicates
962 : * which points succeeded or failed to transform. When TRUE is returned, all
963 : * values in panErrorCodes[] are set to zero.
964 : * Caution: prior to GDAL 3.11, TRUE could be returned if a
965 : * transformation could be found but not all points may
966 : * have necessarily succeed to transform.
967 : * @since GDAL 3.3, and PROJ 8 to be able to use PROJ public error codes
968 : */
969 : virtual int TransformWithErrorCodes(size_t nCount, double *x, double *y,
970 : double *z, double *t,
971 : int *panErrorCodes);
972 :
973 : /** \brief Transform boundary.
974 : *
975 : * This method is the same as the C function OCTTransformBounds().
976 : *
977 : * Transform boundary densifying the edges to account for nonlinear
978 : * transformations along these edges and extracting the outermost bounds.
979 : *
980 : * If the destination CRS is geographic, the first axis is longitude,
981 : * and xmax < xmin then the bounds crossed the antimeridian.
982 : * In this scenario there are two polygons, one on each side of the
983 : * antimeridian. The first polygon should be constructed with (xmin, ymin,
984 : * 180, ymax) and the second with (-180, ymin, xmax, ymax).
985 : *
986 : * If the destination CRS is geographic, the first axis is latitude,
987 : * and ymax < ymin then the bounds crossed the antimeridian.
988 : * In this scenario there are two polygons, one on each side of the
989 : * antimeridian. The first polygon should be constructed with (ymin, xmin,
990 : * ymax, 180) and the second with (ymin, -180, ymax, xmax).
991 : *
992 : * @param xmin Minimum bounding coordinate of the first axis in source CRS.
993 : * @param ymin Minimum bounding coordinate of the second axis in source CRS.
994 : * @param xmax Maximum bounding coordinate of the first axis in source CRS.
995 : * @param ymax Maximum bounding coordinate of the second axis in source CRS.
996 : * @param out_xmin Minimum bounding coordinate of the first axis in target
997 : * CRS
998 : * @param out_ymin Minimum bounding coordinate of the second axis in target
999 : * CRS.
1000 : * @param out_xmax Maximum bounding coordinate of the first axis in target
1001 : * CRS.
1002 : * @param out_ymax Maximum bounding coordinate of the second axis in target
1003 : * CRS.
1004 : * @param densify_pts Recommended to use 21. This is the number of points
1005 : * to use to densify the bounding polygon in the transformation.
1006 : * @return TRUE if successful. FALSE if failures encountered.
1007 : * @since 3.4
1008 : */
1009 0 : virtual int TransformBounds(const double xmin, const double ymin,
1010 : const double xmax, const double ymax,
1011 : double *out_xmin, double *out_ymin,
1012 : double *out_xmax, double *out_ymax,
1013 : const int densify_pts)
1014 : {
1015 : (void)xmin;
1016 : (void)xmax;
1017 : (void)ymin;
1018 : (void)ymax;
1019 : (void)densify_pts;
1020 0 : *out_xmin = HUGE_VAL;
1021 0 : *out_ymin = HUGE_VAL;
1022 0 : *out_xmax = HUGE_VAL;
1023 0 : *out_ymax = HUGE_VAL;
1024 0 : CPLError(CE_Failure, CPLE_AppDefined,
1025 : "TransformBounds not implemented.");
1026 0 : return false;
1027 : }
1028 :
1029 : /** Convert a OGRCoordinateTransformation* to a
1030 : * OGRCoordinateTransformationH.
1031 : */
1032 : static inline OGRCoordinateTransformationH
1033 3 : ToHandle(OGRCoordinateTransformation *poCT)
1034 : {
1035 3 : return reinterpret_cast<OGRCoordinateTransformationH>(poCT);
1036 : }
1037 :
1038 : /** Convert a OGRCoordinateTransformationH to a
1039 : * OGRCoordinateTransformation*.
1040 : */
1041 : static inline OGRCoordinateTransformation *
1042 1459 : FromHandle(OGRCoordinateTransformationH hCT)
1043 : {
1044 1459 : return reinterpret_cast<OGRCoordinateTransformation *>(hCT);
1045 : }
1046 :
1047 : /** Clone
1048 : * @since GDAL 3.1
1049 : */
1050 : virtual OGRCoordinateTransformation *Clone() const = 0;
1051 :
1052 : /** Return a coordinate transformation that performs the inverse
1053 : * transformation of the current one.
1054 : *
1055 : * In some cases, this is not possible, and this method might return
1056 : * nullptr, or fail to perform the transformations.
1057 : *
1058 : * @return the new coordinate transformation, or nullptr in case of error.
1059 : * @since GDAL 3.3
1060 : */
1061 : virtual OGRCoordinateTransformation *GetInverse() const = 0;
1062 :
1063 : protected:
1064 : /*! @cond Doxygen_Suppress */
1065 9866 : OGRCoordinateTransformation() = default;
1066 934 : OGRCoordinateTransformation(const OGRCoordinateTransformation &) = default;
1067 : OGRCoordinateTransformation &
1068 : operator=(const OGRCoordinateTransformation &) = default;
1069 1294 : OGRCoordinateTransformation(OGRCoordinateTransformation &&) = default;
1070 : OGRCoordinateTransformation &
1071 : operator=(OGRCoordinateTransformation &&) = default;
1072 : /*! @endcond */
1073 : };
1074 :
1075 : OGRCoordinateTransformation CPL_DLL *
1076 : OGRCreateCoordinateTransformation(const OGRSpatialReference *poSource,
1077 : const OGRSpatialReference *poTarget);
1078 :
1079 : /**
1080 : * Context for coordinate transformation.
1081 : *
1082 : * @since GDAL 3.0
1083 : */
1084 :
1085 : struct CPL_DLL OGRCoordinateTransformationOptions
1086 : {
1087 : /*! @cond Doxygen_Suppress */
1088 : private:
1089 : friend class OGRProjCT;
1090 : struct Private;
1091 : std::unique_ptr<Private> d;
1092 : /*! @endcond */
1093 :
1094 : public:
1095 : OGRCoordinateTransformationOptions();
1096 : OGRCoordinateTransformationOptions(
1097 : const OGRCoordinateTransformationOptions &);
1098 : OGRCoordinateTransformationOptions &
1099 : operator=(const OGRCoordinateTransformationOptions &);
1100 : ~OGRCoordinateTransformationOptions();
1101 :
1102 : bool SetAreaOfInterest(double dfWestLongitudeDeg, double dfSouthLatitudeDeg,
1103 : double dfEastLongitudeDeg,
1104 : double dfNorthLatitudeDeg);
1105 : bool SetDesiredAccuracy(double dfAccuracy);
1106 : bool SetBallparkAllowed(bool bAllowBallpark);
1107 : bool SetOnlyBest(bool bOnlyBest);
1108 :
1109 : bool SetCoordinateOperation(const char *pszCT, bool bReverseCT);
1110 : /*! @cond Doxygen_Suppress */
1111 : void SetSourceCenterLong(double dfCenterLong);
1112 : void SetTargetCenterLong(double dfCenterLong);
1113 : /*! @endcond */
1114 : };
1115 :
1116 : OGRCoordinateTransformation CPL_DLL *OGRCreateCoordinateTransformation(
1117 : const OGRSpatialReference *poSource, const OGRSpatialReference *poTarget,
1118 : const OGRCoordinateTransformationOptions &options);
1119 :
1120 : #endif /* ndef OGR_SPATIALREF_H_INCLUDED */
|