1 /******************************************************************************
2  *
3  * Project:  PROJ
4  * Purpose:  ISO19111:2019 implementation
5  * Author:   Even Rouault <even dot rouault at spatialys dot com>
6  *
7  ******************************************************************************
8  * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com>
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included
18  * in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  * DEALINGS IN THE SOFTWARE.
27  ****************************************************************************/
28 
29 #ifndef CRS_HH_INCLUDED
30 #define CRS_HH_INCLUDED
31 
32 #include <memory>
33 #include <string>
34 #include <vector>
35 
36 #include "common.hpp"
37 #include "coordinateoperation.hpp"
38 #include "coordinatesystem.hpp"
39 #include "datum.hpp"
40 #include "io.hpp"
41 #include "util.hpp"
42 
43 NS_PROJ_START
44 
45 /** osgeo.proj.crs namespace
46 
47     \brief CRS (coordinate reference system = coordinate system with a datum).
48 */
49 namespace crs {
50 
51 // ---------------------------------------------------------------------------
52 
53 class GeographicCRS;
54 /** Shared pointer of GeographicCRS */
55 using GeographicCRSPtr = std::shared_ptr<GeographicCRS>;
56 /** Non-null shared pointer of GeographicCRS */
57 using GeographicCRSNNPtr = util::nn<GeographicCRSPtr>;
58 
59 class VerticalCRS;
60 /** Shared pointer of VerticalCRS */
61 using VerticalCRSPtr = std::shared_ptr<VerticalCRS>;
62 /** Non-null shared pointer of VerticalCRS */
63 using VerticalCRSNNPtr = util::nn<VerticalCRSPtr>;
64 
65 class BoundCRS;
66 /** Shared pointer of BoundCRS */
67 using BoundCRSPtr = std::shared_ptr<BoundCRS>;
68 /** Non-null shared pointer of BoundCRS */
69 using BoundCRSNNPtr = util::nn<BoundCRSPtr>;
70 
71 class CompoundCRS;
72 /** Shared pointer of CompoundCRS */
73 using CompoundCRSPtr = std::shared_ptr<CompoundCRS>;
74 /** Non-null shared pointer of CompoundCRS */
75 using CompoundCRSNNPtr = util::nn<CompoundCRSPtr>;
76 
77 // ---------------------------------------------------------------------------
78 
79 class CRS;
80 /** Shared pointer of CRS */
81 using CRSPtr = std::shared_ptr<CRS>;
82 /** Non-null shared pointer of CRS */
83 using CRSNNPtr = util::nn<CRSPtr>;
84 
85 /** \brief Abstract class modelling a coordinate reference system which is
86  * usually single but may be compound.
87  *
88  * \remark Implements CRS from \ref ISO_19111_2019
89  */
90 class PROJ_GCC_DLL CRS : public common::ObjectUsage,
91                          public io::IJSONExportable {
92   public:
93     //! @cond Doxygen_Suppress
94     PROJ_DLL ~CRS() override;
95     //! @endcond
96 
97     // Non-standard
98 
99     PROJ_DLL GeodeticCRSPtr extractGeodeticCRS() const;
100     PROJ_DLL GeographicCRSPtr extractGeographicCRS() const;
101     PROJ_DLL VerticalCRSPtr extractVerticalCRS() const;
102     PROJ_DLL CRSNNPtr createBoundCRSToWGS84IfPossible(
103         const io::DatabaseContextPtr &dbContext,
104         operation::CoordinateOperationContext::IntermediateCRSUse
105             allowIntermediateCRSUse) const;
106     PROJ_DLL CRSNNPtr stripVerticalComponent() const;
107 
108     PROJ_DLL const BoundCRSPtr &canonicalBoundCRS() PROJ_PURE_DECL;
109 
110     PROJ_DLL std::list<std::pair<CRSNNPtr, int>>
111     identify(const io::AuthorityFactoryPtr &authorityFactory) const;
112 
113     PROJ_DLL std::list<CRSNNPtr>
114     getNonDeprecated(const io::DatabaseContextNNPtr &dbContext) const;
115 
116     PROJ_DLL CRSNNPtr
117     promoteTo3D(const std::string &newName,
118                 const io::DatabaseContextPtr &dbContext) const;
119 
120     PROJ_DLL CRSNNPtr demoteTo2D(const std::string &newName,
121                                  const io::DatabaseContextPtr &dbContext) const;
122 
123     PROJ_PRIVATE :
124         //! @cond Doxygen_Suppress
125         PROJ_INTERNAL const GeodeticCRS *
126         extractGeodeticCRSRaw() const;
127 
128     PROJ_FOR_TEST CRSNNPtr shallowClone() const;
129 
130     PROJ_FOR_TEST CRSNNPtr alterName(const std::string &newName) const;
131 
132     PROJ_FOR_TEST CRSNNPtr alterId(const std::string &authName,
133                                    const std::string &code) const;
134 
135     PROJ_INTERNAL const std::string &getExtensionProj4() const noexcept;
136 
137     PROJ_FOR_TEST CRSNNPtr
138     alterGeodeticCRS(const GeodeticCRSNNPtr &newGeodCRS) const;
139 
140     PROJ_FOR_TEST CRSNNPtr
141     alterCSLinearUnit(const common::UnitOfMeasure &unit) const;
142 
143     PROJ_INTERNAL bool mustAxisOrderBeSwitchedForVisualization() const;
144 
145     PROJ_INTERNAL CRSNNPtr normalizeForVisualization() const;
146 
147     PROJ_INTERNAL CRSNNPtr allowNonConformantWKT1Export() const;
148 
149     PROJ_INTERNAL CRSNNPtr
150     attachOriginalCompoundCRS(const CompoundCRSNNPtr &compoundCRS) const;
151 
152     PROJ_INTERNAL CRSNNPtr promoteTo3D(
153         const std::string &newName, const io::DatabaseContextPtr &dbContext,
154         const cs::CoordinateSystemAxisNNPtr &verticalAxisIfNotAlreadyPresent)
155         const;
156 
157     PROJ_INTERNAL bool hasImplicitCS() const;
158 
159     PROJ_INTERNAL static CRSNNPtr
160     getResolvedCRS(const CRSNNPtr &crs,
161                    const io::AuthorityFactoryPtr &authFactory,
162                    metadata::ExtentPtr &extentOut);
163     //! @endcond
164 
165   protected:
166     PROJ_INTERNAL CRS();
167     PROJ_INTERNAL CRS(const CRS &other);
168     friend class BoundCRS;
169     PROJ_INTERNAL void setCanonicalBoundCRS(const BoundCRSNNPtr &boundCRS);
170 
171     PROJ_INTERNAL virtual CRSNNPtr _shallowClone() const = 0;
172 
173     PROJ_INTERNAL virtual std::list<std::pair<CRSNNPtr, int>>
174     _identify(const io::AuthorityFactoryPtr &authorityFactory) const;
175 
176   private:
177     PROJ_OPAQUE_PRIVATE_DATA
178 };
179 
180 // ---------------------------------------------------------------------------
181 
182 /** \brief Abstract class modelling a coordinate reference system consisting of
183  * one Coordinate System and either one datum::Datum or one
184  * datum::DatumEnsemble.
185  *
186  * \remark Implements SingleCRS from \ref ISO_19111_2019
187  */
188 class PROJ_GCC_DLL SingleCRS : public CRS {
189   public:
190     //! @cond Doxygen_Suppress
191     PROJ_DLL ~SingleCRS() override;
192     //! @endcond
193 
194     PROJ_DLL const datum::DatumPtr &datum() PROJ_PURE_DECL;
195     PROJ_DLL const datum::DatumEnsemblePtr &datumEnsemble() PROJ_PURE_DECL;
196     PROJ_DLL const cs::CoordinateSystemNNPtr &coordinateSystem() PROJ_PURE_DECL;
197 
198     PROJ_PRIVATE :
199         //! @cond Doxygen_Suppress
200         PROJ_INTERNAL void
201         exportDatumOrDatumEnsembleToWkt(io::WKTFormatter *formatter)
202             const; // throw(io::FormattingException)
203 
204     PROJ_INTERNAL const datum::DatumNNPtr
205     datumNonNull(const io::DatabaseContextPtr &dbContext) const;
206     //! @endcond
207 
208   protected:
209     PROJ_INTERNAL SingleCRS(const datum::DatumPtr &datumIn,
210                             const datum::DatumEnsemblePtr &datumEnsembleIn,
211                             const cs::CoordinateSystemNNPtr &csIn);
212     PROJ_INTERNAL SingleCRS(const SingleCRS &other);
213 
214     PROJ_INTERNAL bool
215     baseIsEquivalentTo(const util::IComparable *other,
216                        util::IComparable::Criterion criterion =
217                            util::IComparable::Criterion::STRICT,
218                        const io::DatabaseContextPtr &dbContext = nullptr) const;
219 
220   private:
221     PROJ_OPAQUE_PRIVATE_DATA
222     SingleCRS &operator=(const SingleCRS &other) = delete;
223 };
224 
225 /** Shared pointer of SingleCRS */
226 using SingleCRSPtr = std::shared_ptr<SingleCRS>;
227 /** Non-null shared pointer of SingleCRS */
228 using SingleCRSNNPtr = util::nn<SingleCRSPtr>;
229 
230 // ---------------------------------------------------------------------------
231 
232 class GeodeticCRS;
233 /** Shared pointer of GeodeticCRS */
234 using GeodeticCRSPtr = std::shared_ptr<GeodeticCRS>;
235 /** Non-null shared pointer of GeodeticCRS */
236 using GeodeticCRSNNPtr = util::nn<GeodeticCRSPtr>;
237 
238 /** \brief A coordinate reference system associated with a geodetic reference
239  * frame and a three-dimensional Cartesian or spherical coordinate system.
240  *
241  * If the geodetic reference frame is dynamic or if the geodetic CRS has an
242  * association to a velocity model then the geodetic CRS is dynamic, else it
243  * is static.
244  *
245  * \remark Implements GeodeticCRS from \ref ISO_19111_2019
246  */
247 class PROJ_GCC_DLL GeodeticCRS : virtual public SingleCRS,
248                                  public io::IPROJStringExportable {
249   public:
250     //! @cond Doxygen_Suppress
251     PROJ_DLL ~GeodeticCRS() override;
252     //! @endcond
253 
254     PROJ_DLL const datum::GeodeticReferenceFramePtr &datum() PROJ_PURE_DECL;
255 
256     PROJ_DLL const datum::PrimeMeridianNNPtr &primeMeridian() PROJ_PURE_DECL;
257     PROJ_DLL const datum::EllipsoidNNPtr &ellipsoid() PROJ_PURE_DECL;
258 
259     // coordinateSystem() returns either a EllipsoidalCS, SphericalCS or
260     // CartesianCS
261 
262     PROJ_DLL const std::vector<operation::PointMotionOperationNNPtr> &
263     velocityModel() PROJ_PURE_DECL;
264 
265     // Non-standard
266 
267     PROJ_DLL bool isGeocentric() PROJ_PURE_DECL;
268 
269     PROJ_DLL static GeodeticCRSNNPtr
270     create(const util::PropertyMap &properties,
271            const datum::GeodeticReferenceFrameNNPtr &datum,
272            const cs::SphericalCSNNPtr &cs);
273 
274     PROJ_DLL static GeodeticCRSNNPtr
275     create(const util::PropertyMap &properties,
276            const datum::GeodeticReferenceFrameNNPtr &datum,
277            const cs::CartesianCSNNPtr &cs);
278 
279     PROJ_DLL static GeodeticCRSNNPtr
280     create(const util::PropertyMap &properties,
281            const datum::GeodeticReferenceFramePtr &datum,
282            const datum::DatumEnsemblePtr &datumEnsemble,
283            const cs::SphericalCSNNPtr &cs);
284 
285     PROJ_DLL static GeodeticCRSNNPtr
286     create(const util::PropertyMap &properties,
287            const datum::GeodeticReferenceFramePtr &datum,
288            const datum::DatumEnsemblePtr &datumEnsemble,
289            const cs::CartesianCSNNPtr &cs);
290 
291     PROJ_DLL static const GeodeticCRSNNPtr EPSG_4978; // WGS 84 Geocentric
292 
293     PROJ_DLL std::list<std::pair<GeodeticCRSNNPtr, int>>
294     identify(const io::AuthorityFactoryPtr &authorityFactory) const;
295 
296     PROJ_PRIVATE :
297         //! @cond Doxygen_Suppress
298         PROJ_INTERNAL void
299         addDatumInfoToPROJString(io::PROJStringFormatter *formatter) const;
300 
301     PROJ_INTERNAL const datum::GeodeticReferenceFrameNNPtr
302     datumNonNull(const io::DatabaseContextPtr &dbContext) const;
303 
304     PROJ_INTERNAL void addGeocentricUnitConversionIntoPROJString(
305         io::PROJStringFormatter *formatter) const;
306 
307     PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter)
308         const override; // throw(io::FormattingException)
309 
310     PROJ_INTERNAL void _exportToPROJString(io::PROJStringFormatter *formatter)
311         const override; // throw(FormattingException)
312 
313     PROJ_INTERNAL void _exportToJSON(io::JSONFormatter *formatter)
314         const override; // throw(FormattingException)
315 
316     PROJ_INTERNAL bool _isEquivalentTo(
317         const util::IComparable *other,
318         util::IComparable::Criterion criterion =
319             util::IComparable::Criterion::STRICT,
320         const io::DatabaseContextPtr &dbContext = nullptr) const override;
321 
322     //! @endcond
323 
324   protected:
325     PROJ_INTERNAL GeodeticCRS(const datum::GeodeticReferenceFramePtr &datumIn,
326                               const datum::DatumEnsemblePtr &datumEnsembleIn,
327                               const cs::EllipsoidalCSNNPtr &csIn);
328     PROJ_INTERNAL GeodeticCRS(const datum::GeodeticReferenceFramePtr &datumIn,
329                               const datum::DatumEnsemblePtr &datumEnsembleIn,
330                               const cs::SphericalCSNNPtr &csIn);
331     PROJ_INTERNAL GeodeticCRS(const datum::GeodeticReferenceFramePtr &datumIn,
332                               const datum::DatumEnsemblePtr &datumEnsembleIn,
333                               const cs::CartesianCSNNPtr &csIn);
334     PROJ_INTERNAL GeodeticCRS(const GeodeticCRS &other);
335 
336     PROJ_INTERNAL static GeodeticCRSNNPtr createEPSG_4978();
337 
338     PROJ_INTERNAL CRSNNPtr _shallowClone() const override;
339 
340     PROJ_INTERNAL std::list<std::pair<CRSNNPtr, int>>
341     _identify(const io::AuthorityFactoryPtr &authorityFactory) const override;
342 
343     PROJ_INTERNAL bool
344     _isEquivalentToNoTypeCheck(const util::IComparable *other,
345                                util::IComparable::Criterion criterion,
346                                const io::DatabaseContextPtr &dbContext) const;
347 
348     INLINED_MAKE_SHARED
349 
350   private:
351     PROJ_OPAQUE_PRIVATE_DATA
352 
353     GeodeticCRS &operator=(const GeodeticCRS &other) = delete;
354 };
355 
356 // ---------------------------------------------------------------------------
357 
358 /** \brief A coordinate reference system associated with a geodetic reference
359  * frame and a two- or three-dimensional ellipsoidal coordinate system.
360  *
361  * If the geodetic reference frame is dynamic or if the geographic CRS has an
362  * association to a velocity model then the geodetic CRS is dynamic, else it is
363  * static.
364  *
365  * \remark Implements GeographicCRS from \ref ISO_19111_2019
366  */
367 class PROJ_GCC_DLL GeographicCRS : public GeodeticCRS {
368   public:
369     //! @cond Doxygen_Suppress
370     PROJ_DLL ~GeographicCRS() override;
371     //! @endcond
372 
373     PROJ_DLL const cs::EllipsoidalCSNNPtr &coordinateSystem() PROJ_PURE_DECL;
374 
375     // Non-standard
376     PROJ_DLL static GeographicCRSNNPtr
377     create(const util::PropertyMap &properties,
378            const datum::GeodeticReferenceFrameNNPtr &datum,
379            const cs::EllipsoidalCSNNPtr &cs);
380     PROJ_DLL static GeographicCRSNNPtr
381     create(const util::PropertyMap &properties,
382            const datum::GeodeticReferenceFramePtr &datum,
383            const datum::DatumEnsemblePtr &datumEnsemble,
384            const cs::EllipsoidalCSNNPtr &cs);
385 
386     PROJ_DLL GeographicCRSNNPtr
387     demoteTo2D(const std::string &newName,
388                const io::DatabaseContextPtr &dbContext) const;
389 
390     PROJ_DLL static const GeographicCRSNNPtr EPSG_4267; // NAD27
391     PROJ_DLL static const GeographicCRSNNPtr EPSG_4269; // NAD83
392     PROJ_DLL static const GeographicCRSNNPtr EPSG_4326; // WGS 84 2D
393     PROJ_DLL static const GeographicCRSNNPtr OGC_CRS84; // CRS84 (Long, Lat)
394     PROJ_DLL static const GeographicCRSNNPtr EPSG_4807; // NTF Paris
395     PROJ_DLL static const GeographicCRSNNPtr EPSG_4979; // WGS 84 3D
396 
397     PROJ_PRIVATE :
398         //! @cond Doxygen_Suppress
399         PROJ_INTERNAL void
400         addAngularUnitConvertAndAxisSwap(
401             io::PROJStringFormatter *formatter) const;
402 
403     PROJ_INTERNAL void _exportToPROJString(io::PROJStringFormatter *formatter)
404         const override; // throw(FormattingException)
405 
406     PROJ_INTERNAL void _exportToJSON(io::JSONFormatter *formatter)
407         const override; // throw(FormattingException)
408 
409     PROJ_DLL bool is2DPartOf3D(
410         util::nn<const GeographicCRS *> other,
411         const io::DatabaseContextPtr &dbContext = nullptr) PROJ_PURE_DECL;
412 
413     PROJ_INTERNAL bool _isEquivalentTo(
414         const util::IComparable *other,
415         util::IComparable::Criterion criterion =
416             util::IComparable::Criterion::STRICT,
417         const io::DatabaseContextPtr &dbContext = nullptr) const override;
418 
419     //! @endcond
420 
421   protected:
422     PROJ_INTERNAL GeographicCRS(const datum::GeodeticReferenceFramePtr &datumIn,
423                                 const datum::DatumEnsemblePtr &datumEnsembleIn,
424                                 const cs::EllipsoidalCSNNPtr &csIn);
425     PROJ_INTERNAL GeographicCRS(const GeographicCRS &other);
426 
427     PROJ_INTERNAL static GeographicCRSNNPtr createEPSG_4267();
428     PROJ_INTERNAL static GeographicCRSNNPtr createEPSG_4269();
429     PROJ_INTERNAL static GeographicCRSNNPtr createEPSG_4326();
430     PROJ_INTERNAL static GeographicCRSNNPtr createOGC_CRS84();
431     PROJ_INTERNAL static GeographicCRSNNPtr createEPSG_4807();
432     PROJ_INTERNAL static GeographicCRSNNPtr createEPSG_4979();
433 
434     PROJ_INTERNAL CRSNNPtr _shallowClone() const override;
435 
436     INLINED_MAKE_SHARED
437 
438   private:
439     PROJ_OPAQUE_PRIVATE_DATA
440 
441     GeographicCRS &operator=(const GeographicCRS &other) = delete;
442 };
443 
444 // ---------------------------------------------------------------------------
445 
446 /** \brief A coordinate reference system having a vertical reference frame and
447  * a one-dimensional vertical coordinate system used for recording
448  * gravity-related heights or depths.
449  *
450  * Vertical CRSs make use of the direction of gravity to define the concept of
451  * height or depth, but the relationship with gravity may not be
452  * straightforward. If the vertical reference frame is dynamic or if the
453  * vertical CRS has an association to a velocity model then the CRS is dynamic,
454  * else it is static.
455  *
456  * \note Ellipsoidal heights cannot be captured in a vertical coordinate
457  * reference system. They exist only as an inseparable part of a 3D coordinate
458  * tuple defined in a geographic 3D coordinate reference system.
459  *
460  * \remark Implements VerticalCRS from \ref ISO_19111_2019
461  */
462 class PROJ_GCC_DLL VerticalCRS : virtual public SingleCRS,
463                                  public io::IPROJStringExportable {
464   public:
465     //! @cond Doxygen_Suppress
466     PROJ_DLL ~VerticalCRS() override;
467     //! @endcond
468 
469     PROJ_DLL const datum::VerticalReferenceFramePtr datum() const;
470     PROJ_DLL const cs::VerticalCSNNPtr coordinateSystem() const;
471     PROJ_DLL const std::vector<operation::TransformationNNPtr> &
472     geoidModel() PROJ_PURE_DECL;
473     PROJ_DLL const std::vector<operation::PointMotionOperationNNPtr> &
474     velocityModel() PROJ_PURE_DECL;
475 
476     PROJ_DLL static VerticalCRSNNPtr
477     create(const util::PropertyMap &properties,
478            const datum::VerticalReferenceFrameNNPtr &datumIn,
479            const cs::VerticalCSNNPtr &csIn);
480 
481     PROJ_DLL static VerticalCRSNNPtr
482     create(const util::PropertyMap &properties,
483            const datum::VerticalReferenceFramePtr &datumIn,
484            const datum::DatumEnsemblePtr &datumEnsembleIn,
485            const cs::VerticalCSNNPtr &csIn);
486 
487     PROJ_DLL std::list<std::pair<VerticalCRSNNPtr, int>>
488     identify(const io::AuthorityFactoryPtr &authorityFactory) const;
489 
490     PROJ_PRIVATE :
491         //! @cond Doxygen_Suppress
492         PROJ_INTERNAL void
493         addLinearUnitConvert(io::PROJStringFormatter *formatter) const;
494 
495     PROJ_INTERNAL const datum::VerticalReferenceFrameNNPtr
496     datumNonNull(const io::DatabaseContextPtr &dbContext) const;
497 
498     PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter)
499         const override; // throw(io::FormattingException)
500 
501     PROJ_INTERNAL void _exportToPROJString(io::PROJStringFormatter *formatter)
502         const override; // throw(FormattingException)
503 
504     PROJ_INTERNAL void _exportToJSON(io::JSONFormatter *formatter)
505         const override; // throw(FormattingException)
506 
507     PROJ_INTERNAL bool _isEquivalentTo(
508         const util::IComparable *other,
509         util::IComparable::Criterion criterion =
510             util::IComparable::Criterion::STRICT,
511         const io::DatabaseContextPtr &dbContext = nullptr) const override;
512 
513     //! @endcond
514 
515   protected:
516     PROJ_INTERNAL VerticalCRS(const datum::VerticalReferenceFramePtr &datumIn,
517                               const datum::DatumEnsemblePtr &datumEnsembleIn,
518                               const cs::VerticalCSNNPtr &csIn);
519     PROJ_INTERNAL VerticalCRS(const VerticalCRS &other);
520 
521     PROJ_INTERNAL std::list<std::pair<CRSNNPtr, int>>
522     _identify(const io::AuthorityFactoryPtr &authorityFactory) const override;
523 
524     INLINED_MAKE_SHARED
525 
526     PROJ_INTERNAL CRSNNPtr _shallowClone() const override;
527 
528   private:
529     PROJ_OPAQUE_PRIVATE_DATA
530     VerticalCRS &operator=(const VerticalCRS &other) = delete;
531 };
532 
533 // ---------------------------------------------------------------------------
534 
535 /** \brief Abstract class modelling a single coordinate reference system that
536  * is defined through the application of a specified coordinate conversion to
537  * the definition of a previously established single coordinate reference
538  * system referred to as the base CRS.
539  *
540  * A derived coordinate reference system inherits its datum (or datum ensemble)
541  * from its base CRS. The coordinate conversion between the base and derived
542  * coordinate reference system is implemented using the parameters and
543  * formula(s) specified in the definition of the coordinate conversion.
544  *
545  * \remark Implements DerivedCRS from \ref ISO_19111_2019
546  */
547 class PROJ_GCC_DLL DerivedCRS : virtual public SingleCRS {
548   public:
549     //! @cond Doxygen_Suppress
550     PROJ_DLL ~DerivedCRS() override;
551     //! @endcond
552 
553     PROJ_DLL const SingleCRSNNPtr &baseCRS() PROJ_PURE_DECL;
554     PROJ_DLL const operation::ConversionNNPtr derivingConversion() const;
555 
556     PROJ_PRIVATE :
557         //! @cond Doxygen_Suppress
558 
559         // Use this method with extreme care ! It should never be used
560         // to recreate a new Derived/ProjectedCRS !
561         PROJ_INTERNAL const operation::ConversionNNPtr &
562         derivingConversionRef() PROJ_PURE_DECL;
563 
564     PROJ_INTERNAL void _exportToJSON(io::JSONFormatter *formatter)
565         const override; // throw(FormattingException)
566 
567     //! @endcond
568 
569   protected:
570     PROJ_INTERNAL
571     DerivedCRS(const SingleCRSNNPtr &baseCRSIn,
572                const operation::ConversionNNPtr &derivingConversionIn,
573                const cs::CoordinateSystemNNPtr &cs);
574     PROJ_INTERNAL DerivedCRS(const DerivedCRS &other);
575 
576     PROJ_INTERNAL void setDerivingConversionCRS();
577 
578     PROJ_INTERNAL void baseExportToWKT(
579         io::WKTFormatter *formatter, const std::string &keyword,
580         const std::string &baseKeyword) const; // throw(FormattingException)
581 
582     PROJ_INTERNAL bool _isEquivalentTo(
583         const util::IComparable *other,
584         util::IComparable::Criterion criterion =
585             util::IComparable::Criterion::STRICT,
586         const io::DatabaseContextPtr &dbContext = nullptr) const override;
587 
588     PROJ_INTERNAL virtual const char *className() const = 0;
589 
590   private:
591     PROJ_OPAQUE_PRIVATE_DATA
592     DerivedCRS &operator=(const DerivedCRS &other) = delete;
593 };
594 
595 /** Shared pointer of DerivedCRS */
596 using DerivedCRSPtr = std::shared_ptr<DerivedCRS>;
597 /** Non-null shared pointer of DerivedCRS */
598 using DerivedCRSNNPtr = util::nn<DerivedCRSPtr>;
599 
600 // ---------------------------------------------------------------------------
601 
602 class ProjectedCRS;
603 /** Shared pointer of ProjectedCRS */
604 using ProjectedCRSPtr = std::shared_ptr<ProjectedCRS>;
605 /** Non-null shared pointer of ProjectedCRS */
606 using ProjectedCRSNNPtr = util::nn<ProjectedCRSPtr>;
607 
608 /** \brief A derived coordinate reference system which has a geodetic
609  * (usually geographic) coordinate reference system as its base CRS, thereby
610  * inheriting a geodetic reference frame, and is converted using a map
611  * projection.
612  *
613  * It has a Cartesian coordinate system, usually two-dimensional but may be
614  * three-dimensional; in the 3D case the base geographic CRSs ellipsoidal
615  * height is passed through unchanged and forms the vertical axis of the
616  * projected CRS's Cartesian coordinate system.
617  *
618  * \remark Implements ProjectedCRS from \ref ISO_19111_2019
619  */
620 class PROJ_GCC_DLL ProjectedCRS final : public DerivedCRS,
621                                         public io::IPROJStringExportable {
622   public:
623     //! @cond Doxygen_Suppress
624     PROJ_DLL ~ProjectedCRS() override;
625     //! @endcond
626 
627     PROJ_DLL const GeodeticCRSNNPtr &baseCRS() PROJ_PURE_DECL;
628     PROJ_DLL const cs::CartesianCSNNPtr &coordinateSystem() PROJ_PURE_DECL;
629 
630     PROJ_DLL static ProjectedCRSNNPtr
631     create(const util::PropertyMap &properties,
632            const GeodeticCRSNNPtr &baseCRSIn,
633            const operation::ConversionNNPtr &derivingConversionIn,
634            const cs::CartesianCSNNPtr &csIn);
635 
636     PROJ_DLL std::list<std::pair<ProjectedCRSNNPtr, int>>
637     identify(const io::AuthorityFactoryPtr &authorityFactory) const;
638 
639     PROJ_DLL ProjectedCRSNNPtr
640     demoteTo2D(const std::string &newName,
641                const io::DatabaseContextPtr &dbContext) const;
642 
643     PROJ_PRIVATE :
644         //! @cond Doxygen_Suppress
645         PROJ_INTERNAL void
646         addUnitConvertAndAxisSwap(io::PROJStringFormatter *formatter,
647                                   bool axisSpecFound) const;
648 
649     PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter)
650         const override; // throw(io::FormattingException)
651 
652     PROJ_INTERNAL void _exportToJSON(io::JSONFormatter *formatter)
653         const override; // throw(FormattingException)
654 
655     PROJ_FOR_TEST ProjectedCRSNNPtr alterParametersLinearUnit(
656         const common::UnitOfMeasure &unit, bool convertToNewUnit) const;
657 
658     //! @endcond
659 
660   protected:
661     PROJ_INTERNAL
662     ProjectedCRS(const GeodeticCRSNNPtr &baseCRSIn,
663                  const operation::ConversionNNPtr &derivingConversionIn,
664                  const cs::CartesianCSNNPtr &csIn);
665     PROJ_INTERNAL ProjectedCRS(const ProjectedCRS &other);
666 
667     PROJ_INTERNAL void _exportToPROJString(io::PROJStringFormatter *formatter)
668         const override; // throw(FormattingException)
669 
670     PROJ_INTERNAL bool _isEquivalentTo(
671         const util::IComparable *other,
672         util::IComparable::Criterion criterion =
673             util::IComparable::Criterion::STRICT,
674         const io::DatabaseContextPtr &dbContext = nullptr) const override;
675 
676     PROJ_INTERNAL std::list<std::pair<CRSNNPtr, int>>
677     _identify(const io::AuthorityFactoryPtr &authorityFactory) const override;
678 
className() const679     PROJ_INTERNAL const char *className() const override {
680         return "ProjectedCRS";
681     }
682 
683     INLINED_MAKE_SHARED
684 
685     PROJ_INTERNAL CRSNNPtr _shallowClone() const override;
686 
687   private:
688     PROJ_OPAQUE_PRIVATE_DATA
689     ProjectedCRS &operator=(const ProjectedCRS &other) = delete;
690 };
691 
692 // ---------------------------------------------------------------------------
693 
694 class TemporalCRS;
695 /** Shared pointer of TemporalCRS */
696 using TemporalCRSPtr = std::shared_ptr<TemporalCRS>;
697 /** Non-null shared pointer of TemporalCRS */
698 using TemporalCRSNNPtr = util::nn<TemporalCRSPtr>;
699 
700 /** \brief A coordinate reference system associated with a temporal datum and a
701  * one-dimensional temporal coordinate system.
702  *
703  * \remark Implements TemporalCRS from \ref ISO_19111_2019
704  */
705 class PROJ_GCC_DLL TemporalCRS : virtual public SingleCRS {
706   public:
707     //! @cond Doxygen_Suppress
708     PROJ_DLL ~TemporalCRS() override;
709     //! @endcond
710 
711     PROJ_DLL const datum::TemporalDatumNNPtr datum() const;
712 
713     PROJ_DLL const cs::TemporalCSNNPtr coordinateSystem() const;
714 
715     PROJ_DLL static TemporalCRSNNPtr
716     create(const util::PropertyMap &properties,
717            const datum::TemporalDatumNNPtr &datumIn,
718            const cs::TemporalCSNNPtr &csIn);
719 
720     //! @cond Doxygen_Suppress
721     PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter)
722         const override; // throw(io::FormattingException)
723 
724     PROJ_INTERNAL void _exportToJSON(io::JSONFormatter *formatter)
725         const override; // throw(FormattingException)
726 
727     //! @endcond
728 
729   protected:
730     PROJ_INTERNAL TemporalCRS(const datum::TemporalDatumNNPtr &datumIn,
731                               const cs::TemporalCSNNPtr &csIn);
732     PROJ_INTERNAL TemporalCRS(const TemporalCRS &other);
733 
734     INLINED_MAKE_SHARED
735 
736     PROJ_INTERNAL CRSNNPtr _shallowClone() const override;
737 
738     PROJ_INTERNAL bool _isEquivalentTo(
739         const util::IComparable *other,
740         util::IComparable::Criterion criterion =
741             util::IComparable::Criterion::STRICT,
742         const io::DatabaseContextPtr &dbContext = nullptr) const override;
743 
744   private:
745     PROJ_OPAQUE_PRIVATE_DATA
746     TemporalCRS &operator=(const TemporalCRS &other) = delete;
747 };
748 
749 // ---------------------------------------------------------------------------
750 
751 class EngineeringCRS;
752 /** Shared pointer of EngineeringCRS */
753 using EngineeringCRSPtr = std::shared_ptr<EngineeringCRS>;
754 /** Non-null shared pointer of EngineeringCRS */
755 using EngineeringCRSNNPtr = util::nn<EngineeringCRSPtr>;
756 
757 /** \brief Contextually local coordinate reference system associated with an
758  * engineering datum.
759  *
760  * It is applied either to activities on or near the surface of the Earth
761  * without geodetic corrections, or on moving platforms such as road vehicles,
762  * vessels, aircraft or spacecraft, or as the internal CRS of an image.
763  *
764  * In \ref WKT2, it maps to a ENGINEERINGCRS / ENGCRS keyword. In \ref WKT1,
765  * it maps to a LOCAL_CS keyword.
766  *
767  * \remark Implements EngineeringCRS from \ref ISO_19111_2019
768  */
769 class PROJ_GCC_DLL EngineeringCRS : virtual public SingleCRS {
770   public:
771     //! @cond Doxygen_Suppress
772     PROJ_DLL ~EngineeringCRS() override;
773     //! @endcond
774 
775     PROJ_DLL const datum::EngineeringDatumNNPtr datum() const;
776 
777     PROJ_DLL static EngineeringCRSNNPtr
778     create(const util::PropertyMap &properties,
779            const datum::EngineeringDatumNNPtr &datumIn,
780            const cs::CoordinateSystemNNPtr &csIn);
781 
782     //! @cond Doxygen_Suppress
783     PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter)
784         const override; // throw(io::FormattingException)
785 
786     PROJ_INTERNAL void _exportToJSON(io::JSONFormatter *formatter)
787         const override; // throw(FormattingException)
788 
789     //! @endcond
790 
791   protected:
792     PROJ_INTERNAL EngineeringCRS(const datum::EngineeringDatumNNPtr &datumIn,
793                                  const cs::CoordinateSystemNNPtr &csIn);
794     PROJ_INTERNAL EngineeringCRS(const EngineeringCRS &other);
795 
796     PROJ_INTERNAL CRSNNPtr _shallowClone() const override;
797 
798     PROJ_INTERNAL bool _isEquivalentTo(
799         const util::IComparable *other,
800         util::IComparable::Criterion criterion =
801             util::IComparable::Criterion::STRICT,
802         const io::DatabaseContextPtr &dbContext = nullptr) const override;
803 
804     INLINED_MAKE_SHARED
805 
806   private:
807     PROJ_OPAQUE_PRIVATE_DATA
808     EngineeringCRS &operator=(const EngineeringCRS &other) = delete;
809 };
810 
811 // ---------------------------------------------------------------------------
812 
813 class ParametricCRS;
814 /** Shared pointer of ParametricCRS */
815 using ParametricCRSPtr = std::shared_ptr<ParametricCRS>;
816 /** Non-null shared pointer of ParametricCRS */
817 using ParametricCRSNNPtr = util::nn<ParametricCRSPtr>;
818 
819 /** \brief Contextually local coordinate reference system associated with an
820  * engineering datum.
821  *
822  * This is applied either to activities on or near the surface of the Earth
823  * without geodetic corrections, or on moving platforms such as road vehicles
824  * vessels, aircraft or spacecraft, or as the internal CRS of an image.
825  *
826  * \remark Implements ParametricCRS from \ref ISO_19111_2019
827  */
828 class PROJ_GCC_DLL ParametricCRS : virtual public SingleCRS {
829   public:
830     //! @cond Doxygen_Suppress
831     PROJ_DLL ~ParametricCRS() override;
832     //! @endcond
833 
834     PROJ_DLL const datum::ParametricDatumNNPtr datum() const;
835 
836     PROJ_DLL const cs::ParametricCSNNPtr coordinateSystem() const;
837 
838     PROJ_DLL static ParametricCRSNNPtr
839     create(const util::PropertyMap &properties,
840            const datum::ParametricDatumNNPtr &datumIn,
841            const cs::ParametricCSNNPtr &csIn);
842 
843     //! @cond Doxygen_Suppress
844     PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter)
845         const override; // throw(io::FormattingException)
846 
847     PROJ_INTERNAL void _exportToJSON(io::JSONFormatter *formatter)
848         const override; // throw(FormattingException)
849 
850     //! @endcond
851 
852   protected:
853     PROJ_INTERNAL ParametricCRS(const datum::ParametricDatumNNPtr &datumIn,
854                                 const cs::ParametricCSNNPtr &csIn);
855     PROJ_INTERNAL ParametricCRS(const ParametricCRS &other);
856 
857     PROJ_INTERNAL CRSNNPtr _shallowClone() const override;
858 
859     PROJ_INTERNAL bool _isEquivalentTo(
860         const util::IComparable *other,
861         util::IComparable::Criterion criterion =
862             util::IComparable::Criterion::STRICT,
863         const io::DatabaseContextPtr &dbContext = nullptr) const override;
864 
865     INLINED_MAKE_SHARED
866 
867   private:
868     PROJ_OPAQUE_PRIVATE_DATA
869     ParametricCRS &operator=(const ParametricCRS &other) = delete;
870 };
871 
872 // ---------------------------------------------------------------------------
873 
874 /** \brief Exception thrown when attempting to create an invalid compound CRS
875  */
876 class PROJ_GCC_DLL InvalidCompoundCRSException : public util::Exception {
877   public:
878     //! @cond Doxygen_Suppress
879     PROJ_INTERNAL explicit InvalidCompoundCRSException(const char *message);
880     PROJ_INTERNAL explicit InvalidCompoundCRSException(
881         const std::string &message);
882     PROJ_DLL
883     InvalidCompoundCRSException(const InvalidCompoundCRSException &other);
884     PROJ_DLL ~InvalidCompoundCRSException() override;
885     //! @endcond
886 };
887 
888 // ---------------------------------------------------------------------------
889 
890 /** \brief A coordinate reference system describing the position of points
891  * through two or more independent single coordinate reference systems.
892  *
893  * \note Two coordinate reference systems are independent of each other
894  * if coordinate values in one cannot be converted or transformed into
895  * coordinate values in the other.
896  *
897  * \note As a departure to \ref ISO_19111_2019, we allow to build a CompoundCRS
898  * from CRS objects, whereas ISO19111:2019 restricts the components to
899  * SingleCRS.
900  *
901  * \remark Implements CompoundCRS from \ref ISO_19111_2019
902  */
903 class PROJ_GCC_DLL CompoundCRS final : public CRS,
904                                        public io::IPROJStringExportable {
905   public:
906     //! @cond Doxygen_Suppress
907     PROJ_DLL ~CompoundCRS() override;
908     //! @endcond
909 
910     PROJ_DLL const std::vector<CRSNNPtr> &
911     componentReferenceSystems() PROJ_PURE_DECL;
912 
913     PROJ_DLL std::list<std::pair<CompoundCRSNNPtr, int>>
914     identify(const io::AuthorityFactoryPtr &authorityFactory) const;
915 
916     //! @cond Doxygen_Suppress
917     PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter)
918         const override; // throw(io::FormattingException)
919     //! @endcond
920 
921     PROJ_DLL static CompoundCRSNNPtr
922     create(const util::PropertyMap &properties,
923            const std::vector<CRSNNPtr>
924                &components); // throw InvalidCompoundCRSException
925 
926     //! @cond Doxygen_Suppress
927     PROJ_INTERNAL static CRSNNPtr
928     createLax(const util::PropertyMap &properties,
929               const std::vector<CRSNNPtr> &components,
930               const io::DatabaseContextPtr
931                   &dbContext); // throw InvalidCompoundCRSException
932                                //! @endcond
933 
934   protected:
935     // relaxed: standard say SingleCRSNNPtr
936     PROJ_INTERNAL explicit CompoundCRS(const std::vector<CRSNNPtr> &components);
937     PROJ_INTERNAL CompoundCRS(const CompoundCRS &other);
938 
939     PROJ_INTERNAL void _exportToPROJString(io::PROJStringFormatter *formatter)
940         const override; // throw(FormattingException)
941 
942     PROJ_INTERNAL void _exportToJSON(io::JSONFormatter *formatter)
943         const override; // throw(FormattingException)
944 
945     PROJ_INTERNAL CRSNNPtr _shallowClone() const override;
946 
947     PROJ_INTERNAL bool _isEquivalentTo(
948         const util::IComparable *other,
949         util::IComparable::Criterion criterion =
950             util::IComparable::Criterion::STRICT,
951         const io::DatabaseContextPtr &dbContext = nullptr) const override;
952 
953     PROJ_INTERNAL std::list<std::pair<CRSNNPtr, int>>
954     _identify(const io::AuthorityFactoryPtr &authorityFactory) const override;
955 
956     INLINED_MAKE_SHARED
957 
958   private:
959     PROJ_OPAQUE_PRIVATE_DATA
960     CompoundCRS &operator=(const CompoundCRS &other) = delete;
961 };
962 
963 // ---------------------------------------------------------------------------
964 
965 /** \brief A coordinate reference system with an associated transformation to
966  * a target/hub CRS.
967  *
968  * The definition of a CRS is not dependent upon any relationship to an
969  * independent CRS. However in an implementation that merges datasets
970  * referenced to differing CRSs, it is sometimes useful to associate the
971  * definition of the transformation that has been used with the CRS definition.
972  * This facilitates the interrelationship of CRS by concatenating
973  * transformations via a common or hub CRS. This is sometimes referred to as
974  * "early-binding". \ref WKT2 permits the association of an abridged coordinate
975  * transformation description with a coordinate reference system description in
976  * a single text string. In a BoundCRS, the abridged coordinate transformation
977  * is applied to the source CRS with the target CRS being the common or hub
978  * system.
979  *
980  * Coordinates referring to a BoundCRS are expressed into its source/base CRS.
981  *
982  * This abstraction can for example model the concept of TOWGS84 datum shift
983  * present in \ref WKT1.
984  *
985  * \note Contrary to other CRS classes of this package, there is no
986  * \ref ISO_19111_2019 modelling of a BoundCRS.
987  *
988  * \remark Implements BoundCRS from \ref WKT2
989  */
990 class PROJ_GCC_DLL BoundCRS final : public CRS,
991                                     public io::IPROJStringExportable {
992   public:
993     //! @cond Doxygen_Suppress
994     PROJ_DLL ~BoundCRS() override;
995     //! @endcond
996 
997     PROJ_DLL const CRSNNPtr &baseCRS() PROJ_PURE_DECL;
998     PROJ_DLL CRSNNPtr baseCRSWithCanonicalBoundCRS() const;
999 
1000     PROJ_DLL const CRSNNPtr &hubCRS() PROJ_PURE_DECL;
1001     PROJ_DLL const operation::TransformationNNPtr &
1002     transformation() PROJ_PURE_DECL;
1003 
1004     //! @cond Doxygen_Suppress
1005     PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter)
1006         const override; // throw(io::FormattingException)
1007     //! @endcond
1008 
1009     PROJ_DLL static BoundCRSNNPtr
1010     create(const CRSNNPtr &baseCRSIn, const CRSNNPtr &hubCRSIn,
1011            const operation::TransformationNNPtr &transformationIn);
1012 
1013     PROJ_DLL static BoundCRSNNPtr
1014     createFromTOWGS84(const CRSNNPtr &baseCRSIn,
1015                       const std::vector<double> &TOWGS84Parameters);
1016 
1017     PROJ_DLL static BoundCRSNNPtr
1018     createFromNadgrids(const CRSNNPtr &baseCRSIn, const std::string &filename);
1019 
1020   protected:
1021     PROJ_INTERNAL
1022     BoundCRS(const CRSNNPtr &baseCRSIn, const CRSNNPtr &hubCRSIn,
1023              const operation::TransformationNNPtr &transformationIn);
1024     PROJ_INTERNAL BoundCRS(const BoundCRS &other);
1025 
1026     PROJ_INTERNAL CRSNNPtr _shallowClone() const override;
1027 
1028     PROJ_INTERNAL void _exportToPROJString(io::PROJStringFormatter *formatter)
1029         const override; // throw(FormattingException)
1030 
1031     PROJ_INTERNAL void _exportToJSON(io::JSONFormatter *formatter)
1032         const override; // throw(FormattingException)
1033 
1034     PROJ_INTERNAL bool _isEquivalentTo(
1035         const util::IComparable *other,
1036         util::IComparable::Criterion criterion =
1037             util::IComparable::Criterion::STRICT,
1038         const io::DatabaseContextPtr &dbContext = nullptr) const override;
1039 
1040     PROJ_INTERNAL BoundCRSNNPtr shallowCloneAsBoundCRS() const;
1041     PROJ_INTERNAL bool isTOWGS84Compatible() const;
1042     PROJ_INTERNAL std::string getHDatumPROJ4GRIDS() const;
1043     PROJ_INTERNAL std::string getVDatumPROJ4GRIDS() const;
1044 
1045     PROJ_INTERNAL std::list<std::pair<CRSNNPtr, int>>
1046     _identify(const io::AuthorityFactoryPtr &authorityFactory) const override;
1047 
1048     INLINED_MAKE_SHARED
1049 
1050   private:
1051     PROJ_OPAQUE_PRIVATE_DATA
1052     BoundCRS &operator=(const BoundCRS &other) = delete;
1053 };
1054 
1055 // ---------------------------------------------------------------------------
1056 
1057 class DerivedGeodeticCRS;
1058 /** Shared pointer of DerivedGeodeticCRS */
1059 using DerivedGeodeticCRSPtr = std::shared_ptr<DerivedGeodeticCRS>;
1060 /** Non-null shared pointer of DerivedGeodeticCRS */
1061 using DerivedGeodeticCRSNNPtr = util::nn<DerivedGeodeticCRSPtr>;
1062 
1063 /** \brief A derived coordinate reference system which has either a geodetic
1064  * or a geographic coordinate reference system as its base CRS, thereby
1065  * inheriting a geodetic reference frame, and associated with a 3D Cartesian
1066  * or spherical coordinate system.
1067  *
1068  * \remark Implements DerivedGeodeticCRS from \ref ISO_19111_2019
1069  */
1070 class PROJ_GCC_DLL DerivedGeodeticCRS final : public GeodeticCRS,
1071                                               public DerivedCRS {
1072   public:
1073     //! @cond Doxygen_Suppress
1074     PROJ_DLL ~DerivedGeodeticCRS() override;
1075     //! @endcond
1076 
1077     PROJ_DLL const GeodeticCRSNNPtr baseCRS() const;
1078 
1079     PROJ_DLL static DerivedGeodeticCRSNNPtr
1080     create(const util::PropertyMap &properties,
1081            const GeodeticCRSNNPtr &baseCRSIn,
1082            const operation::ConversionNNPtr &derivingConversionIn,
1083            const cs::CartesianCSNNPtr &csIn);
1084 
1085     PROJ_DLL static DerivedGeodeticCRSNNPtr
1086     create(const util::PropertyMap &properties,
1087            const GeodeticCRSNNPtr &baseCRSIn,
1088            const operation::ConversionNNPtr &derivingConversionIn,
1089            const cs::SphericalCSNNPtr &csIn);
1090 
1091     //! @cond Doxygen_Suppress
1092     void _exportToWKT(io::WKTFormatter *formatter)
1093         const override; // throw(io::FormattingException)
1094 
1095     PROJ_INTERNAL void
_exportToJSON(io::JSONFormatter * formatter) const1096     _exportToJSON(io::JSONFormatter *formatter) const override {
1097         return DerivedCRS::_exportToJSON(formatter);
1098     }
1099 
1100     //! @endcond
1101 
1102   protected:
1103     PROJ_INTERNAL
1104     DerivedGeodeticCRS(const GeodeticCRSNNPtr &baseCRSIn,
1105                        const operation::ConversionNNPtr &derivingConversionIn,
1106                        const cs::CartesianCSNNPtr &csIn);
1107     PROJ_INTERNAL
1108     DerivedGeodeticCRS(const GeodeticCRSNNPtr &baseCRSIn,
1109                        const operation::ConversionNNPtr &derivingConversionIn,
1110                        const cs::SphericalCSNNPtr &csIn);
1111     PROJ_INTERNAL DerivedGeodeticCRS(const DerivedGeodeticCRS &other);
1112 
1113     PROJ_INTERNAL CRSNNPtr _shallowClone() const override;
1114 
1115     PROJ_INTERNAL bool _isEquivalentTo(
1116         const util::IComparable *other,
1117         util::IComparable::Criterion criterion =
1118             util::IComparable::Criterion::STRICT,
1119         const io::DatabaseContextPtr &dbContext = nullptr) const override;
1120 
1121     PROJ_INTERNAL std::list<std::pair<CRSNNPtr, int>>
1122     _identify(const io::AuthorityFactoryPtr &authorityFactory) const override;
1123 
1124     // cppcheck-suppress functionStatic
1125     PROJ_INTERNAL void _exportToPROJString(io::PROJStringFormatter *formatter)
1126         const override; // throw(FormattingException)
1127 
className() const1128     PROJ_INTERNAL const char *className() const override {
1129         return "DerivedGeodeticCRS";
1130     }
1131 
1132     INLINED_MAKE_SHARED
1133 
1134   private:
1135     PROJ_OPAQUE_PRIVATE_DATA
1136     DerivedGeodeticCRS &operator=(const DerivedGeodeticCRS &other) = delete;
1137 };
1138 
1139 // ---------------------------------------------------------------------------
1140 
1141 class DerivedGeographicCRS;
1142 /** Shared pointer of DerivedGeographicCRS */
1143 using DerivedGeographicCRSPtr = std::shared_ptr<DerivedGeographicCRS>;
1144 /** Non-null shared pointer of DerivedGeographicCRS */
1145 using DerivedGeographicCRSNNPtr = util::nn<DerivedGeographicCRSPtr>;
1146 
1147 /** \brief A derived coordinate reference system which has either a geodetic or
1148  * a geographic coordinate reference system as its base CRS, thereby inheriting
1149  * a geodetic reference frame, and an ellipsoidal coordinate system.
1150  *
1151  * A derived geographic CRS can be based on a geodetic CRS only if that
1152  * geodetic CRS definition includes an ellipsoid.
1153  *
1154  * \remark Implements DerivedGeographicCRS from \ref ISO_19111_2019
1155  */
1156 class PROJ_GCC_DLL DerivedGeographicCRS final : public GeographicCRS,
1157                                                 public DerivedCRS {
1158   public:
1159     //! @cond Doxygen_Suppress
1160     PROJ_DLL ~DerivedGeographicCRS() override;
1161     //! @endcond
1162 
1163     PROJ_DLL const GeodeticCRSNNPtr baseCRS() const;
1164 
1165     PROJ_DLL static DerivedGeographicCRSNNPtr
1166     create(const util::PropertyMap &properties,
1167            const GeodeticCRSNNPtr &baseCRSIn,
1168            const operation::ConversionNNPtr &derivingConversionIn,
1169            const cs::EllipsoidalCSNNPtr &csIn);
1170 
1171     //! @cond Doxygen_Suppress
1172     PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter)
1173         const override; // throw(io::FormattingException)
1174 
1175     PROJ_INTERNAL void
_exportToJSON(io::JSONFormatter * formatter) const1176     _exportToJSON(io::JSONFormatter *formatter) const override {
1177         return DerivedCRS::_exportToJSON(formatter);
1178     }
1179 
1180     //! @endcond
1181 
1182   protected:
1183     PROJ_INTERNAL
1184     DerivedGeographicCRS(const GeodeticCRSNNPtr &baseCRSIn,
1185                          const operation::ConversionNNPtr &derivingConversionIn,
1186                          const cs::EllipsoidalCSNNPtr &csIn);
1187     PROJ_INTERNAL DerivedGeographicCRS(const DerivedGeographicCRS &other);
1188 
1189     PROJ_INTERNAL CRSNNPtr _shallowClone() const override;
1190 
1191     PROJ_INTERNAL bool _isEquivalentTo(
1192         const util::IComparable *other,
1193         util::IComparable::Criterion criterion =
1194             util::IComparable::Criterion::STRICT,
1195         const io::DatabaseContextPtr &dbContext = nullptr) const override;
1196 
1197     PROJ_INTERNAL std::list<std::pair<CRSNNPtr, int>>
1198     _identify(const io::AuthorityFactoryPtr &authorityFactory) const override;
1199 
className() const1200     PROJ_INTERNAL const char *className() const override {
1201         return "DerivedGeographicCRS";
1202     }
1203 
1204     // cppcheck-suppress functionStatic
1205     PROJ_INTERNAL void _exportToPROJString(io::PROJStringFormatter *formatter)
1206         const override; // throw(FormattingException)
1207 
1208     INLINED_MAKE_SHARED
1209 
1210   private:
1211     PROJ_OPAQUE_PRIVATE_DATA
1212     DerivedGeographicCRS &operator=(const DerivedGeographicCRS &other) = delete;
1213 };
1214 
1215 // ---------------------------------------------------------------------------
1216 
1217 class DerivedProjectedCRS;
1218 /** Shared pointer of DerivedProjectedCRS */
1219 using DerivedProjectedCRSPtr = std::shared_ptr<DerivedProjectedCRS>;
1220 /** Non-null shared pointer of DerivedProjectedCRS */
1221 using DerivedProjectedCRSNNPtr = util::nn<DerivedProjectedCRSPtr>;
1222 
1223 /** \brief A derived coordinate reference system which has a projected
1224  * coordinate reference system as its base CRS, thereby inheriting a geodetic
1225  * reference frame, but also inheriting the distortion characteristics of the
1226  * base projected CRS.
1227  *
1228  * A DerivedProjectedCRS is not a ProjectedCRS.
1229  *
1230  * \remark Implements DerivedProjectedCRS from \ref ISO_19111_2019
1231  */
1232 class PROJ_GCC_DLL DerivedProjectedCRS final : public DerivedCRS {
1233   public:
1234     //! @cond Doxygen_Suppress
1235     PROJ_DLL ~DerivedProjectedCRS() override;
1236     //! @endcond
1237 
1238     PROJ_DLL const ProjectedCRSNNPtr baseCRS() const;
1239 
1240     PROJ_DLL static DerivedProjectedCRSNNPtr
1241     create(const util::PropertyMap &properties,
1242            const ProjectedCRSNNPtr &baseCRSIn,
1243            const operation::ConversionNNPtr &derivingConversionIn,
1244            const cs::CoordinateSystemNNPtr &csIn);
1245 
1246     //! @cond Doxygen_Suppress
1247     PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter)
1248         const override; // throw(io::FormattingException)
1249                         //! @endcond
1250 
1251   protected:
1252     PROJ_INTERNAL
1253     DerivedProjectedCRS(const ProjectedCRSNNPtr &baseCRSIn,
1254                         const operation::ConversionNNPtr &derivingConversionIn,
1255                         const cs::CoordinateSystemNNPtr &csIn);
1256     PROJ_INTERNAL DerivedProjectedCRS(const DerivedProjectedCRS &other);
1257 
1258     PROJ_INTERNAL CRSNNPtr _shallowClone() const override;
1259 
1260     PROJ_INTERNAL bool _isEquivalentTo(
1261         const util::IComparable *other,
1262         util::IComparable::Criterion criterion =
1263             util::IComparable::Criterion::STRICT,
1264         const io::DatabaseContextPtr &dbContext = nullptr) const override;
1265 
className() const1266     PROJ_INTERNAL const char *className() const override {
1267         return "DerivedProjectedCRS";
1268     }
1269 
1270     INLINED_MAKE_SHARED
1271 
1272   private:
1273     PROJ_OPAQUE_PRIVATE_DATA
1274     DerivedProjectedCRS &operator=(const DerivedProjectedCRS &other) = delete;
1275 };
1276 
1277 // ---------------------------------------------------------------------------
1278 
1279 class DerivedVerticalCRS;
1280 /** Shared pointer of DerivedVerticalCRS */
1281 using DerivedVerticalCRSPtr = std::shared_ptr<DerivedVerticalCRS>;
1282 /** Non-null shared pointer of DerivedVerticalCRS */
1283 using DerivedVerticalCRSNNPtr = util::nn<DerivedVerticalCRSPtr>;
1284 
1285 /** \brief A derived coordinate reference system which has a vertical
1286  * coordinate reference system as its base CRS, thereby inheriting a vertical
1287  * reference frame, and a vertical coordinate system.
1288  *
1289  * \remark Implements DerivedVerticalCRS from \ref ISO_19111_2019
1290  */
1291 class PROJ_GCC_DLL DerivedVerticalCRS final : public VerticalCRS,
1292                                               public DerivedCRS {
1293   public:
1294     //! @cond Doxygen_Suppress
1295     PROJ_DLL ~DerivedVerticalCRS() override;
1296     //! @endcond
1297 
1298     PROJ_DLL const VerticalCRSNNPtr baseCRS() const;
1299 
1300     PROJ_DLL static DerivedVerticalCRSNNPtr
1301     create(const util::PropertyMap &properties,
1302            const VerticalCRSNNPtr &baseCRSIn,
1303            const operation::ConversionNNPtr &derivingConversionIn,
1304            const cs::VerticalCSNNPtr &csIn);
1305 
1306     //! @cond Doxygen_Suppress
1307     PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter)
1308         const override; // throw(io::FormattingException)
1309 
1310     PROJ_INTERNAL void
_exportToJSON(io::JSONFormatter * formatter) const1311     _exportToJSON(io::JSONFormatter *formatter) const override {
1312         return DerivedCRS::_exportToJSON(formatter);
1313     }
1314 
1315     //! @endcond
1316 
1317   protected:
1318     PROJ_INTERNAL
1319     DerivedVerticalCRS(const VerticalCRSNNPtr &baseCRSIn,
1320                        const operation::ConversionNNPtr &derivingConversionIn,
1321                        const cs::VerticalCSNNPtr &csIn);
1322     PROJ_INTERNAL DerivedVerticalCRS(const DerivedVerticalCRS &other);
1323 
1324     PROJ_INTERNAL CRSNNPtr _shallowClone() const override;
1325 
1326     PROJ_INTERNAL bool _isEquivalentTo(
1327         const util::IComparable *other,
1328         util::IComparable::Criterion criterion =
1329             util::IComparable::Criterion::STRICT,
1330         const io::DatabaseContextPtr &dbContext = nullptr) const override;
1331 
1332     PROJ_INTERNAL std::list<std::pair<CRSNNPtr, int>>
1333     _identify(const io::AuthorityFactoryPtr &authorityFactory) const override;
1334 
className() const1335     PROJ_INTERNAL const char *className() const override {
1336         return "DerivedVerticalCRS";
1337     }
1338 
1339     // cppcheck-suppress functionStatic
1340     PROJ_INTERNAL void _exportToPROJString(io::PROJStringFormatter *formatter)
1341         const override; // throw(FormattingException)
1342 
1343     INLINED_MAKE_SHARED
1344 
1345   private:
1346     PROJ_OPAQUE_PRIVATE_DATA
1347     DerivedVerticalCRS &operator=(const DerivedVerticalCRS &other) = delete;
1348 };
1349 
1350 // ---------------------------------------------------------------------------
1351 
1352 /** \brief Template representing a derived coordinate reference system.
1353  */
1354 template <class DerivedCRSTraits>
1355 class PROJ_GCC_DLL DerivedCRSTemplate final : public DerivedCRSTraits::BaseType,
1356                                               public DerivedCRS {
1357   protected:
1358     /** Base type */
1359     typedef typename DerivedCRSTraits::BaseType BaseType;
1360     /** CSType */
1361     typedef typename DerivedCRSTraits::CSType CSType;
1362 
1363   public:
1364     //! @cond Doxygen_Suppress
1365     PROJ_DLL ~DerivedCRSTemplate() override;
1366     //! @endcond
1367 
1368     /** Non-null shared pointer of DerivedCRSTemplate */
1369     typedef typename util::nn<std::shared_ptr<DerivedCRSTemplate>> NNPtr;
1370     /** Non-null shared pointer of BaseType */
1371     typedef util::nn<std::shared_ptr<BaseType>> BaseNNPtr;
1372     /** Non-null shared pointer of CSType */
1373     typedef util::nn<std::shared_ptr<CSType>> CSNNPtr;
1374 
1375     /** \brief Return the base CRS of a DerivedCRSTemplate.
1376      *
1377      * @return the base CRS.
1378      */
1379     PROJ_DLL const BaseNNPtr baseCRS() const;
1380 
1381     /** \brief Instantiate a DerivedCRSTemplate from a base CRS, a deriving
1382      * conversion and a cs::CoordinateSystem.
1383      *
1384      * @param properties See \ref general_properties.
1385      * At minimum the name should be defined.
1386      * @param baseCRSIn base CRS.
1387      * @param derivingConversionIn the deriving conversion from the base CRS to
1388      * this
1389      * CRS.
1390      * @param csIn the coordinate system.
1391      * @return new DerivedCRSTemplate.
1392      */
1393     PROJ_DLL static NNPtr
1394     create(const util::PropertyMap &properties, const BaseNNPtr &baseCRSIn,
1395            const operation::ConversionNNPtr &derivingConversionIn,
1396            const CSNNPtr &csIn);
1397 
1398     //! @cond Doxygen_Suppress
1399     PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter)
1400         const override; // throw(io::FormattingException)
1401 
1402     PROJ_INTERNAL void
_exportToJSON(io::JSONFormatter * formatter) const1403     _exportToJSON(io::JSONFormatter *formatter) const override {
1404         return DerivedCRS::_exportToJSON(formatter);
1405     }
1406     //! @endcond
1407 
1408   protected:
1409     PROJ_INTERNAL
1410     DerivedCRSTemplate(const BaseNNPtr &baseCRSIn,
1411                        const operation::ConversionNNPtr &derivingConversionIn,
1412                        const CSNNPtr &csIn);
1413     PROJ_INTERNAL DerivedCRSTemplate(const DerivedCRSTemplate &other);
1414 
1415     PROJ_INTERNAL CRSNNPtr _shallowClone() const override;
1416 
1417     PROJ_INTERNAL bool _isEquivalentTo(
1418         const util::IComparable *other,
1419         util::IComparable::Criterion criterion =
1420             util::IComparable::Criterion::STRICT,
1421         const io::DatabaseContextPtr &dbContext = nullptr) const override;
1422 
1423     PROJ_INTERNAL const char *className() const override;
1424 
1425     INLINED_MAKE_SHARED
1426 
1427   private:
1428     struct PROJ_INTERNAL Private;
1429     std::unique_ptr<Private> d;
1430 
1431     DerivedCRSTemplate &operator=(const DerivedCRSTemplate &other) = delete;
1432 };
1433 
1434 // ---------------------------------------------------------------------------
1435 
1436 //! @cond Doxygen_Suppress
1437 struct PROJ_GCC_DLL DerivedEngineeringCRSTraits {
1438     typedef EngineeringCRS BaseType;
1439     typedef cs::CoordinateSystem CSType;
1440     // old x86_64-w64-mingw32-g++ has issues with static variables. use method
1441     // instead
1442     inline static const std::string &CRSName();
1443     inline static const std::string &WKTKeyword();
1444     inline static const std::string &WKTBaseKeyword();
1445     static const bool wkt2_2019_only = true;
1446 };
1447 //! @endcond
1448 
1449 /** \brief A derived coordinate reference system which has an engineering
1450  * coordinate reference system as its base CRS, thereby inheriting an
1451  * engineering datum, and is associated with one of the coordinate system
1452  * types for an EngineeringCRS
1453  *
1454  * \remark Implements DerivedEngineeringCRS from \ref ISO_19111_2019
1455  */
1456 #ifdef DOXYGEN_ENABLED
1457 class DerivedEngineeringCRS
1458     : public DerivedCRSTemplate<DerivedEngineeringCRSTraits> {};
1459 #else
1460 using DerivedEngineeringCRS = DerivedCRSTemplate<DerivedEngineeringCRSTraits>;
1461 #endif
1462 
1463 #ifndef DO_NOT_DEFINE_EXTERN_DERIVED_CRS_TEMPLATE
1464 extern template class DerivedCRSTemplate<DerivedEngineeringCRSTraits>;
1465 #endif
1466 
1467 /** Shared pointer of DerivedEngineeringCRS */
1468 using DerivedEngineeringCRSPtr = std::shared_ptr<DerivedEngineeringCRS>;
1469 /** Non-null shared pointer of DerivedEngineeringCRS */
1470 using DerivedEngineeringCRSNNPtr = util::nn<DerivedEngineeringCRSPtr>;
1471 
1472 // ---------------------------------------------------------------------------
1473 
1474 //! @cond Doxygen_Suppress
1475 struct PROJ_GCC_DLL DerivedParametricCRSTraits {
1476     typedef ParametricCRS BaseType;
1477     typedef cs::ParametricCS CSType;
1478     // old x86_64-w64-mingw32-g++ has issues with static variables. use method
1479     // instead
1480     inline static const std::string &CRSName();
1481     inline static const std::string &WKTKeyword();
1482     inline static const std::string &WKTBaseKeyword();
1483     static const bool wkt2_2019_only = false;
1484 };
1485 //! @endcond
1486 
1487 /** \brief A derived coordinate reference system which has a parametric
1488  * coordinate reference system as its base CRS, thereby inheriting a parametric
1489  * datum, and a parametric coordinate system.
1490  *
1491  * \remark Implements DerivedParametricCRS from \ref ISO_19111_2019
1492  */
1493 #ifdef DOXYGEN_ENABLED
1494 class DerivedParametricCRS
1495     : public DerivedCRSTemplate<DerivedParametricCRSTraits> {};
1496 #else
1497 using DerivedParametricCRS = DerivedCRSTemplate<DerivedParametricCRSTraits>;
1498 #endif
1499 
1500 #ifndef DO_NOT_DEFINE_EXTERN_DERIVED_CRS_TEMPLATE
1501 extern template class DerivedCRSTemplate<DerivedParametricCRSTraits>;
1502 #endif
1503 
1504 /** Shared pointer of DerivedParametricCRS */
1505 using DerivedParametricCRSPtr = std::shared_ptr<DerivedParametricCRS>;
1506 /** Non-null shared pointer of DerivedParametricCRS */
1507 using DerivedParametricCRSNNPtr = util::nn<DerivedParametricCRSPtr>;
1508 
1509 // ---------------------------------------------------------------------------
1510 
1511 //! @cond Doxygen_Suppress
1512 struct PROJ_GCC_DLL DerivedTemporalCRSTraits {
1513     typedef TemporalCRS BaseType;
1514     typedef cs::TemporalCS CSType;
1515     // old x86_64-w64-mingw32-g++ has issues with static variables. use method
1516     // instead
1517     inline static const std::string &CRSName();
1518     inline static const std::string &WKTKeyword();
1519     inline static const std::string &WKTBaseKeyword();
1520     static const bool wkt2_2019_only = false;
1521 };
1522 //! @endcond
1523 
1524 /** \brief A derived coordinate reference system which has a temporal
1525  * coordinate reference system as its base CRS, thereby inheriting a temporal
1526  * datum, and a temporal coordinate system.
1527  *
1528  * \remark Implements DerivedTemporalCRS from \ref ISO_19111_2019
1529  */
1530 #ifdef DOXYGEN_ENABLED
1531 class DerivedTemporalCRS : public DerivedCRSTemplate<DerivedTemporalCRSTraits> {
1532 };
1533 #else
1534 using DerivedTemporalCRS = DerivedCRSTemplate<DerivedTemporalCRSTraits>;
1535 #endif
1536 
1537 #ifndef DO_NOT_DEFINE_EXTERN_DERIVED_CRS_TEMPLATE
1538 extern template class DerivedCRSTemplate<DerivedTemporalCRSTraits>;
1539 #endif
1540 
1541 /** Shared pointer of DerivedTemporalCRS */
1542 using DerivedTemporalCRSPtr = std::shared_ptr<DerivedTemporalCRS>;
1543 /** Non-null shared pointer of DerivedTemporalCRS */
1544 using DerivedTemporalCRSNNPtr = util::nn<DerivedTemporalCRSPtr>;
1545 
1546 // ---------------------------------------------------------------------------
1547 
1548 } // namespace crs
1549 
1550 NS_PROJ_END
1551 
1552 #endif //  CRS_HH_INCLUDED
1553