diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2018-11-14 17:40:42 +0100 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2018-11-14 22:48:29 +0100 |
| commit | d928db15d53805d9b728b440079756081961c536 (patch) | |
| tree | e862a961d26bedb34c58e4f28ef0bdeedb5f3225 /include | |
| parent | 330e8bf686f9c4524075ca1ff50cbca6c9e091da (diff) | |
| download | PROJ-d928db15d53805d9b728b440079756081961c536.tar.gz PROJ-d928db15d53805d9b728b440079756081961c536.zip | |
Implement RFC 2: Initial integration of "GDAL SRS barn" work
This work mostly consists of:
- a C++ implementation of the ISO-19111:2018 / OGC Topic 2
"Referencing by coordinates" classes to represent Datums,
Coordinate systems, CRSs (Coordinate Reference Systems) and
Coordinate Operations.
- methods to convert between this C++ modeling and WKT1, WKT2
and PROJ string representations of those objects
- management and query of a SQLite3 database of CRS and Coordinate Operation definition
- a C API binding part of those capabilities
This is all-in-one squashed commit of the work of
https://github.com/OSGeo/proj.4/pull/1040
Diffstat (limited to 'include')
| -rw-r--r-- | include/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | include/Makefile.am | 3 | ||||
| -rw-r--r-- | include/proj/CMakeLists.txt | 7 | ||||
| -rw-r--r-- | include/proj/Makefile.am | 8 | ||||
| -rw-r--r-- | include/proj/common.hpp | 445 | ||||
| -rw-r--r-- | include/proj/coordinateoperation.hpp | 1764 | ||||
| -rw-r--r-- | include/proj/coordinatesystem.hpp | 701 | ||||
| -rw-r--r-- | include/proj/crs.hpp | 1361 | ||||
| -rw-r--r-- | include/proj/datum.hpp | 779 | ||||
| -rw-r--r-- | include/proj/internal/Makefile.am | 8 | ||||
| -rw-r--r-- | include/proj/internal/coordinateoperation_constants.hpp | 898 | ||||
| -rw-r--r-- | include/proj/internal/coordinateoperation_internal.hpp | 274 | ||||
| -rw-r--r-- | include/proj/internal/coordinatesystem_internal.hpp | 104 | ||||
| -rw-r--r-- | include/proj/internal/esri_projection_mappings.hpp | 887 | ||||
| -rw-r--r-- | include/proj/internal/internal.hpp | 190 | ||||
| -rw-r--r-- | include/proj/internal/io_internal.hpp | 163 | ||||
| -rw-r--r-- | include/proj/internal/lru_cache.hpp | 223 | ||||
| -rw-r--r-- | include/proj/io.hpp | 970 | ||||
| -rw-r--r-- | include/proj/metadata.hpp | 458 | ||||
| -rw-r--r-- | include/proj/nn.hpp | 385 | ||||
| -rw-r--r-- | include/proj/util.hpp | 752 |
21 files changed, 10381 insertions, 0 deletions
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt new file mode 100644 index 00000000..648a0650 --- /dev/null +++ b/include/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(proj) diff --git a/include/Makefile.am b/include/Makefile.am new file mode 100644 index 00000000..ba96cf80 --- /dev/null +++ b/include/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = proj + +EXTRA_DIST = CMakeLists.txt diff --git a/include/proj/CMakeLists.txt b/include/proj/CMakeLists.txt new file mode 100644 index 00000000..d112cf74 --- /dev/null +++ b/include/proj/CMakeLists.txt @@ -0,0 +1,7 @@ +set(installdest include/proj) + +install( + FILES util.hpp metadata.hpp common.hpp crs.hpp datum.hpp + coordinatesystem.hpp coordinateoperation.hpp io.hpp nn.hpp + DESTINATION ${installdest} +) diff --git a/include/proj/Makefile.am b/include/proj/Makefile.am new file mode 100644 index 00000000..e5ae5aed --- /dev/null +++ b/include/proj/Makefile.am @@ -0,0 +1,8 @@ +EXTRA_DIST = CMakeLists.txt + +SUBDIRS = internal + +projdir = $(includedir)/proj + +proj_HEADERS = util.hpp metadata.hpp common.hpp crs.hpp datum.hpp \ + coordinatesystem.hpp coordinateoperation.hpp io.hpp nn.hpp diff --git a/include/proj/common.hpp b/include/proj/common.hpp new file mode 100644 index 00000000..f1e683e7 --- /dev/null +++ b/include/proj/common.hpp @@ -0,0 +1,445 @@ +/****************************************************************************** + * + * Project: PROJ + * Purpose: ISO19111:2018 implementation + * Author: Even Rouault <even dot rouault at spatialys dot com> + * + ****************************************************************************** + * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ****************************************************************************/ + +#ifndef COMMON_HH_INCLUDED +#define COMMON_HH_INCLUDED + +#include <memory> +#include <string> +#include <vector> + +#include "io.hpp" +#include "metadata.hpp" +#include "util.hpp" + +NS_PROJ_START + +/** osgeo.proj.common namespace + * + * \brief Common classes. + */ +namespace common { + +// --------------------------------------------------------------------------- + +class UnitOfMeasure; +/** Shared pointer of UnitOfMeasure. */ +using UnitOfMeasurePtr = std::shared_ptr<UnitOfMeasure>; +/** Non-null shared pointer of UnitOfMeasure. */ +using UnitOfMeasureNNPtr = util::nn<UnitOfMeasurePtr>; + +/** \brief Unit of measure. + * + * This is a mutable object. + */ +class PROJ_GCC_DLL UnitOfMeasure : public util::BaseObject { + public: + /** \brief Type of unit of measure. */ + enum class PROJ_MSVC_DLL Type { + /** Unknown unit of measure */ + UNKNOWN, + /** No unit of measure */ + NONE, + /** Angular unit of measure */ + ANGULAR, + /** Linear unit of measure */ + LINEAR, + /** Scale unit of measure */ + SCALE, + /** Time unit of measure */ + TIME, + /** Parametric unit of measure */ + PARAMETRIC, + }; + + PROJ_DLL UnitOfMeasure(const std::string &nameIn = std::string(), + double toSIIn = 1.0, Type typeIn = Type::UNKNOWN, + const std::string &codeSpaceIn = std::string(), + const std::string &codeIn = std::string()); + + //! @cond Doxygen_Suppress + PROJ_DLL UnitOfMeasure(const UnitOfMeasure &other); + PROJ_DLL ~UnitOfMeasure() override; + PROJ_DLL UnitOfMeasure &operator=(const UnitOfMeasure &other); + PROJ_INTERNAL static UnitOfMeasureNNPtr create(const UnitOfMeasure &other); + //! @endcond + + PROJ_DLL const std::string &name() PROJ_PURE_DECL; + PROJ_DLL double conversionToSI() PROJ_PURE_DECL; + PROJ_DLL Type type() PROJ_PURE_DECL; + + PROJ_DLL const std::string &codeSpace() PROJ_PURE_DECL; + PROJ_DLL const std::string &code() PROJ_PURE_DECL; + + PROJ_DLL bool operator==(const UnitOfMeasure &other) PROJ_PURE_DECL; + PROJ_DLL bool operator!=(const UnitOfMeasure &other) PROJ_PURE_DECL; + + //! @cond Doxygen_Suppress + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter, + const std::string &unitType = std::string()) + const; // throw(io::FormattingException) + + PROJ_INTERNAL std::string exportToPROJString() const; + + PROJ_INTERNAL bool + _isEquivalentTo(const UnitOfMeasure &other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const; + + //! @endcond + + PROJ_DLL static const UnitOfMeasure NONE; + + PROJ_DLL static const UnitOfMeasure SCALE_UNITY; + PROJ_DLL static const UnitOfMeasure PARTS_PER_MILLION; + PROJ_DLL static const UnitOfMeasure PPM_PER_YEAR; + + PROJ_DLL static const UnitOfMeasure METRE; + PROJ_DLL static const UnitOfMeasure METRE_PER_YEAR; + + PROJ_DLL static const UnitOfMeasure RADIAN; + PROJ_DLL static const UnitOfMeasure MICRORADIAN; + PROJ_DLL static const UnitOfMeasure DEGREE; + PROJ_DLL static const UnitOfMeasure ARC_SECOND; + PROJ_DLL static const UnitOfMeasure GRAD; + PROJ_DLL static const UnitOfMeasure ARC_SECOND_PER_YEAR; + + PROJ_DLL static const UnitOfMeasure SECOND; + PROJ_DLL static const UnitOfMeasure YEAR; + + private: + PROJ_OPAQUE_PRIVATE_DATA +}; + +// --------------------------------------------------------------------------- + +/** \brief Numeric value associated with a UnitOfMeasure. */ +class Measure : public util::BaseObject { + public: + PROJ_DLL Measure(double valueIn = 0.0, + const UnitOfMeasure &unitIn = UnitOfMeasure()); + + //! @cond Doxygen_Suppress + PROJ_DLL Measure(const Measure &other); + PROJ_DLL ~Measure(); + //! @endcond + + PROJ_DLL const UnitOfMeasure &unit() PROJ_CONST_DECL; + PROJ_DLL double getSIValue() PROJ_CONST_DECL; + PROJ_DLL double value() PROJ_CONST_DECL; + + PROJ_DLL double + convertToUnit(const UnitOfMeasure &otherUnit) PROJ_CONST_DECL; + + PROJ_DLL bool operator==(const Measure &other) PROJ_CONST_DECL; + + PROJ_INTERNAL bool + _isEquivalentTo(const Measure &other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const; + + private: + PROJ_OPAQUE_PRIVATE_DATA + Measure &operator=(const Measure &) = delete; +}; + +// --------------------------------------------------------------------------- + +/** \brief Numeric value, without a physical unit of measure. */ +class Scale : public Measure { + public: + PROJ_DLL explicit Scale(double valueIn = 0.0); + PROJ_DLL explicit Scale(double valueIn, const UnitOfMeasure &unitIn); + + //! @cond Doxygen_Suppress + explicit Scale(const Measure &other) : Scale(other.value(), other.unit()) {} + PROJ_DLL Scale(const Scale &other); + PROJ_DLL ~Scale() override; + //! @endcond + + protected: + PROJ_FRIEND_OPTIONAL(Scale); + Scale &operator=(const Scale &) = delete; +}; + +// --------------------------------------------------------------------------- + +/** \brief Numeric value, with a angular unit of measure. */ +class Angle : public Measure { + public: + PROJ_DLL explicit Angle(double valueIn = 0.0); + PROJ_DLL Angle(double valueIn, const UnitOfMeasure &unitIn); + + //! @cond Doxygen_Suppress + explicit Angle(const Measure &other) : Angle(other.value(), other.unit()) {} + PROJ_DLL Angle(const Angle &other); + PROJ_DLL ~Angle() override; + //! @endcond + + protected: + PROJ_FRIEND_OPTIONAL(Angle); + Angle &operator=(const Angle &) = delete; +}; + +// --------------------------------------------------------------------------- + +/** \brief Numeric value, with a linear unit of measure. */ +class Length : public Measure { + public: + PROJ_DLL explicit Length(double valueIn = 0.0); + PROJ_DLL Length(double valueIn, const UnitOfMeasure &unitIn); + + //! @cond Doxygen_Suppress + explicit Length(const Measure &other) + : Length(other.value(), other.unit()) {} + PROJ_DLL Length(const Length &other); + PROJ_DLL ~Length() override; + //! @endcond + + protected: + PROJ_FRIEND_OPTIONAL(Length); + Length &operator=(const Length &) = delete; +}; + +// --------------------------------------------------------------------------- + +/** \brief Date-time value, as a ISO:8601 encoded string, or other string + * encoding */ +class DateTime { + public: + //! @cond Doxygen_Suppress + PROJ_DLL DateTime(const DateTime &other); + PROJ_DLL ~DateTime(); + //! @endcond + + PROJ_DLL bool isISO_8601() const; + PROJ_DLL std::string toString() const; + + PROJ_DLL static DateTime + create(const std::string &str); // may throw Exception + + protected: + DateTime(); + PROJ_FRIEND_OPTIONAL(DateTime); + + private: + explicit DateTime(const std::string &str); + DateTime &operator=(const DateTime &other) = delete; + + PROJ_OPAQUE_PRIVATE_DATA +}; + +// --------------------------------------------------------------------------- + +/** \brief Data epoch */ +class DataEpoch { + // FIXME + public: + /** FIXME */ + Measure coordinateEpoch{}; +}; + +// --------------------------------------------------------------------------- + +class IdentifiedObject; +/** Shared pointer of IdentifiedObject. */ +using IdentifiedObjectPtr = std::shared_ptr<IdentifiedObject>; +/** Non-null shared pointer of IdentifiedObject. */ +using IdentifiedObjectNNPtr = util::nn<IdentifiedObjectPtr>; + +/** \brief Abstract class representating a CRS-related object that has an + * identification. + * + * \remark Implements IdentifiedObject from \ref ISO_19111_2018 + */ +class IdentifiedObject : public util::BaseObject, + public util::IComparable, + public io::IWKTExportable { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~IdentifiedObject() override; + //! @endcond + + PROJ_DLL static const std::string NAME_KEY; + PROJ_DLL static const std::string IDENTIFIERS_KEY; + PROJ_DLL static const std::string ALIAS_KEY; + PROJ_DLL static const std::string REMARKS_KEY; + PROJ_DLL static const std::string DEPRECATED_KEY; + + // in practice only name().description() is used + PROJ_DLL const metadata::IdentifierNNPtr &name() PROJ_CONST_DECL; + PROJ_DLL const std::string &nameStr() PROJ_CONST_DECL; + PROJ_DLL const std::vector<metadata::IdentifierNNPtr> & + identifiers() PROJ_CONST_DECL; + PROJ_DLL const std::vector<util::GenericNameNNPtr> & + aliases() PROJ_CONST_DECL; + PROJ_DLL const std::string &remarks() PROJ_CONST_DECL; + + // from Apache SIS AbstractIdentifiedObject + PROJ_DLL bool isDeprecated() PROJ_CONST_DECL; + + // Non-standard + PROJ_DLL std::string alias() PROJ_CONST_DECL; + PROJ_DLL int getEPSGCode() PROJ_CONST_DECL; + + PROJ_PRIVATE : + //! @cond Doxygen_Suppress + void + formatID(io::WKTFormatter *formatter) const; + void formatRemarks(io::WKTFormatter *formatter) const; + + bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + + bool + _isEquivalentTo(const IdentifiedObject *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) PROJ_CONST_DECL; + //! @endcond + + protected: + PROJ_FRIEND_OPTIONAL(IdentifiedObject); + INLINED_MAKE_SHARED + IdentifiedObject(); + IdentifiedObject(const IdentifiedObject &other); + + void setProperties(const util::PropertyMap + &properties); // throw(InvalidValueTypeException) + + private: + PROJ_OPAQUE_PRIVATE_DATA + IdentifiedObject &operator=(const IdentifiedObject &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class ObjectDomain; +/** Shared pointer of ObjectDomain. */ +using ObjectDomainPtr = std::shared_ptr<ObjectDomain>; +/** Non-null shared pointer of ObjectDomain. */ +using ObjectDomainNNPtr = util::nn<ObjectDomainPtr>; + +/** \brief The scope and validity of a CRS-related object. + * + * \remark Implements ObjectDomain from \ref ISO_19111_2018 + */ +class ObjectDomain : public util::BaseObject, public util::IComparable { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~ObjectDomain() override; + //! @endcond + + // In ISO_19111:2018, scope and domain are compulsory, but in WKT2:2015, + // they + // are not necessarily both specified + PROJ_DLL const util::optional<std::string> &scope() PROJ_CONST_DECL; + PROJ_DLL const metadata::ExtentPtr &domainOfValidity() PROJ_CONST_DECL; + + PROJ_DLL static ObjectDomainNNPtr + create(const util::optional<std::string> &scopeIn, + const metadata::ExtentPtr &extent); + + PROJ_PRIVATE : + //! @cond Doxygen_Suppress + void + _exportToWKT(io::WKTFormatter *formatter) + const; // throw(io::FormattingException) + + bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + //! @endcond + + protected: + //! @cond Doxygen_Suppress + ObjectDomain(const util::optional<std::string> &scopeIn, + const metadata::ExtentPtr &extent); + //! @endcond + + ObjectDomain(const ObjectDomain &other); + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA + ObjectDomain &operator=(const ObjectDomain &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class ObjectUsage; +/** Shared pointer of ObjectUsage. */ +using ObjectUsagePtr = std::shared_ptr<ObjectUsage>; +/** Non-null shared pointer of ObjectUsage. */ +using ObjectUsageNNPtr = util::nn<ObjectUsagePtr>; + +/** \brief Abstract class of a CRS-related object that has usages. + * + * \remark Implements ObjectUsage from \ref ISO_19111_2018 + */ +class ObjectUsage : public IdentifiedObject { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~ObjectUsage() override; + //! @endcond + + PROJ_DLL const std::vector<ObjectDomainNNPtr> &domains() PROJ_CONST_DECL; + + PROJ_DLL static const std::string SCOPE_KEY; + PROJ_DLL static const std::string DOMAIN_OF_VALIDITY_KEY; + + PROJ_DLL static const std::string OBJECT_DOMAIN_KEY; + + //! @cond Doxygen_Suppress + bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + //! @endcond + + protected: + ObjectUsage(); + ObjectUsage(const ObjectUsage &other); + void setProperties(const util::PropertyMap + &properties); // throw(InvalidValueTypeException) + + void baseExportToWKT( + io::WKTFormatter *formatter) const; // throw(io::FormattingException) + + private: + PROJ_OPAQUE_PRIVATE_DATA + ObjectUsage &operator=(const ObjectUsage &other) = delete; +}; + +} // namespace common + +NS_PROJ_END + +#endif // COMMON_HH_INCLUDED diff --git a/include/proj/coordinateoperation.hpp b/include/proj/coordinateoperation.hpp new file mode 100644 index 00000000..5e3ecf0b --- /dev/null +++ b/include/proj/coordinateoperation.hpp @@ -0,0 +1,1764 @@ +/****************************************************************************** + * + * Project: PROJ + * Purpose: ISO19111:2018 implementation + * Author: Even Rouault <even dot rouault at spatialys dot com> + * + ****************************************************************************** + * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ****************************************************************************/ + +#ifndef COORDINATEOPERATION_HH_INCLUDED +#define COORDINATEOPERATION_HH_INCLUDED + +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "common.hpp" +#include "io.hpp" +#include "metadata.hpp" + +NS_PROJ_START + +namespace crs { +class CRS; +using CRSPtr = std::shared_ptr<CRS>; +using CRSNNPtr = util::nn<CRSPtr>; + +class DerivedCRS; +class ProjectedCRS; +} // namespace crs + +/** osgeo.proj.operation namespace + + \brief Coordinate operations (relationship between any two coordinate + reference systems). + + This covers Conversion, Transformation, + PointMotionOperation or ConcatenatedOperation. +*/ +namespace operation { + +// --------------------------------------------------------------------------- + +/** \brief Grid description */ +struct GridDescription { + std::string shortName{}; /**< Grid short filename */ + std::string fullName{}; /**< Grid full path name (if found) */ + std::string packageName{}; /**< Package name (or empty) */ + std::string url{}; /**< Grid URL (if packageName is empty), or package + URL (or empty) */ + bool directDownload = false; /**< Whether url can be fetched directly. */ + bool openLicense = + false; /**< Whether the grid is released with an open license. */ + bool available = false; /**< Whether GRID is available. */ + + //! @cond Doxygen_Suppress + bool operator<(const GridDescription &other) const { + return shortName < other.shortName; + } + + PROJ_DLL GridDescription(); + PROJ_DLL ~GridDescription(); + PROJ_DLL GridDescription(const GridDescription &); + PROJ_DLL GridDescription(GridDescription &&) noexcept; + //! @endcond +}; + +// --------------------------------------------------------------------------- + +class CoordinateOperation; +/** Shared pointer of CoordinateOperation */ +using CoordinateOperationPtr = std::shared_ptr<CoordinateOperation>; +/** Non-null shared pointer of CoordinateOperation */ +using CoordinateOperationNNPtr = util::nn<CoordinateOperationPtr>; + +/** \brief Abstract class for a mathematical operation on coordinates. + * + * A mathematical operation: + * <ul> + * <li>on coordinates that transforms or converts them from one coordinate + * reference system to another coordinate reference system</li> + * <li>or that describes the change of coordinate values within one coordinate + * reference system due to the motion of the point between one coordinate epoch + * and another coordinate epoch.</li> + * </ul> + * Many but not all coordinate operations (from CRS A to CRS B) also uniquely + * define the inverse coordinate operation (from CRS B to CRS A). In some cases, + * the coordinate operation method algorithm for the inverse coordinate + * operation is the same as for the forward algorithm, but the signs of some + * coordinate operation parameter values have to be reversed. In other cases, + * different algorithms are required for the forward and inverse coordinate + * operations, but the same coordinate operation parameter values are used. If + * (some) entirely different parameter values are needed, a different coordinate + * operation shall be defined. + * + * \remark Implements CoordinateOperation from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL CoordinateOperation : public common::ObjectUsage, + public io::IPROJStringExportable { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~CoordinateOperation() override; + //! @endcond + + PROJ_DLL const util::optional<std::string> &operationVersion() const; + PROJ_DLL const std::vector<metadata::PositionalAccuracyNNPtr> & + coordinateOperationAccuracies() const; + + PROJ_DLL const crs::CRSPtr sourceCRS() const; + PROJ_DLL const crs::CRSPtr targetCRS() const; + PROJ_DLL const crs::CRSPtr &interpolationCRS() const; + PROJ_DLL const util::optional<common::DataEpoch> & + sourceCoordinateEpoch() const; + PROJ_DLL const util::optional<common::DataEpoch> & + targetCoordinateEpoch() const; + + // virtual void transform(...) = 0; TODO + + /** \brief Return the inverse of the coordinate operation. + * @throw util::UnsupportedOperationException + */ + PROJ_DLL virtual CoordinateOperationNNPtr inverse() const = 0; + + /** \brief Return grids needed by an operation. */ + PROJ_DLL virtual std::set<GridDescription> + gridsNeeded(const io::DatabaseContextPtr &databaseContext) const = 0; + + PROJ_DLL bool + isPROJInstanciable(const io::DatabaseContextPtr &databaseContext) const; + + protected: + PROJ_INTERNAL CoordinateOperation(); + PROJ_INTERNAL CoordinateOperation(const CoordinateOperation &other); + + PROJ_FRIEND(crs::DerivedCRS); + PROJ_FRIEND(io::AuthorityFactory); + PROJ_FRIEND(CoordinateOperationFactory); + PROJ_INTERNAL void + setWeakSourceTargetCRS(std::weak_ptr<crs::CRS> sourceCRSIn, + std::weak_ptr<crs::CRS> targetCRSIn); + PROJ_INTERNAL void setCRSs(const crs::CRSNNPtr &sourceCRSIn, + const crs::CRSNNPtr &targetCRSIn, + const crs::CRSPtr &interpolationCRSIn); + PROJ_INTERNAL void setCRSs(const CoordinateOperation *in, + bool inverseSourceTarget); + PROJ_INTERNAL + void setAccuracies( + const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies); + + private: + PROJ_OPAQUE_PRIVATE_DATA + CoordinateOperation &operator=(const CoordinateOperation &other) = delete; +}; + +// --------------------------------------------------------------------------- + +/** \brief Abstract class modelling a parameter value (OperationParameter) + * or group of parameters. + * + * \remark Implements GeneralOperationParameter from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL GeneralOperationParameter : public common::IdentifiedObject { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~GeneralOperationParameter() override; + //! @endcond + + //! @cond Doxygen_Suppress + PROJ_INTERNAL bool _isEquivalentTo( + const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override = 0; + //! @endcond + + protected: + PROJ_INTERNAL GeneralOperationParameter(); + PROJ_INTERNAL + GeneralOperationParameter(const GeneralOperationParameter &other); + + private: + PROJ_OPAQUE_PRIVATE_DATA + GeneralOperationParameter & + operator=(const GeneralOperationParameter &other) = delete; +}; + +/** Shared pointer of GeneralOperationParameter */ +using GeneralOperationParameterPtr = std::shared_ptr<GeneralOperationParameter>; +/** Non-null shared pointer of GeneralOperationParameter */ +using GeneralOperationParameterNNPtr = util::nn<GeneralOperationParameterPtr>; + +// --------------------------------------------------------------------------- + +class OperationParameter; +/** Shared pointer of OperationParameter */ +using OperationParameterPtr = std::shared_ptr<OperationParameter>; +/** Non-null shared pointer of OperationParameter */ +using OperationParameterNNPtr = util::nn<OperationParameterPtr>; + +/** \brief The definition of a parameter used by a coordinate operation method. + * + * Most parameter values are numeric, but other types of parameter values are + * possible. + * + * \remark Implements OperationParameter from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL OperationParameter final : public GeneralOperationParameter { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~OperationParameter() override; + //! @endcond + + //! @cond Doxygen_Suppress + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + //! @endcond + + // non-standard + PROJ_DLL static OperationParameterNNPtr + create(const util::PropertyMap &properties); + + PROJ_DLL int getEPSGCode() PROJ_CONST_DECL; + + PROJ_DLL static const char *getNameForEPSGCode(int epsg_code) noexcept; + + protected: + PROJ_INTERNAL OperationParameter(); + PROJ_INTERNAL OperationParameter(const OperationParameter &other); + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA + OperationParameter &operator=(const OperationParameter &other) = delete; + + // cppcheck-suppress functionStatic + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) +}; + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +struct MethodMapping; +//! @endcond + +/** \brief Abstract class modelling a parameter value (OperationParameterValue) + * or group of parameter values. + * + * \remark Implements GeneralParameterValue from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL GeneralParameterValue : public util::BaseObject, + public io::IWKTExportable, + public util::IComparable { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~GeneralParameterValue() override; + + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override = 0; // throw(io::FormattingException) + + PROJ_INTERNAL bool _isEquivalentTo( + const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override = 0; + //! @endcond + + protected: + //! @cond Doxygen_Suppress + PROJ_INTERNAL GeneralParameterValue(); + PROJ_INTERNAL GeneralParameterValue(const GeneralParameterValue &other); + + friend class Conversion; + friend class SingleOperation; + PROJ_INTERNAL virtual void _exportToWKT(io::WKTFormatter *formatter, + const MethodMapping *mapping) + const = 0; // throw(io::FormattingException) + //! @endcond + + private: + PROJ_OPAQUE_PRIVATE_DATA + GeneralParameterValue & + operator=(const GeneralParameterValue &other) = delete; +}; + +/** Shared pointer of GeneralParameterValue */ +using GeneralParameterValuePtr = std::shared_ptr<GeneralParameterValue>; +/** Non-null shared pointer of GeneralParameterValue */ +using GeneralParameterValueNNPtr = util::nn<GeneralParameterValuePtr>; + +// --------------------------------------------------------------------------- + +class ParameterValue; +/** Shared pointer of ParameterValue */ +using ParameterValuePtr = std::shared_ptr<ParameterValue>; +/** Non-null shared pointer of ParameterValue */ +using ParameterValueNNPtr = util::nn<ParameterValuePtr>; + +/** \brief The value of the coordinate operation parameter. + * + * Most parameter values are numeric, but other types of parameter values are + * possible. + * + * \remark Implements ParameterValue from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL ParameterValue final : public util::BaseObject, + public io::IWKTExportable, + public util::IComparable { + public: + /** Type of the value. */ + enum class Type { + /** Measure (i.e. value with a unit) */ + MEASURE, + /** String */ + STRING, + /** Integer */ + INTEGER, + /** Boolean */ + BOOLEAN, + /** Filename */ + FILENAME + }; + //! @cond Doxygen_Suppress + PROJ_DLL ~ParameterValue() override; + + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + //! @endcond + + PROJ_DLL static ParameterValueNNPtr + create(const common::Measure &measureIn); + PROJ_DLL static ParameterValueNNPtr create(const char *stringValueIn); + PROJ_DLL static ParameterValueNNPtr + create(const std::string &stringValueIn); + PROJ_DLL static ParameterValueNNPtr create(int integerValueIn); + PROJ_DLL static ParameterValueNNPtr create(bool booleanValueIn); + PROJ_DLL static ParameterValueNNPtr + createFilename(const std::string &stringValueIn); + + PROJ_DLL const Type &type() PROJ_CONST_DECL; + PROJ_DLL const common::Measure &value() PROJ_CONST_DECL; + PROJ_DLL const std::string &stringValue() PROJ_CONST_DECL; + PROJ_DLL const std::string &valueFile() PROJ_CONST_DECL; + PROJ_DLL int integerValue() PROJ_CONST_DECL; + PROJ_DLL bool booleanValue() PROJ_CONST_DECL; + + //! @cond Doxygen_Suppress + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + //! @endcond + + protected: + PROJ_INTERNAL explicit ParameterValue(const common::Measure &measureIn); + PROJ_INTERNAL explicit ParameterValue(const std::string &stringValueIn, + Type typeIn); + PROJ_INTERNAL explicit ParameterValue(int integerValueIn); + PROJ_INTERNAL explicit ParameterValue(bool booleanValueIn); + INLINED_MAKE_SHARED + private: + PROJ_OPAQUE_PRIVATE_DATA + ParameterValue &operator=(const ParameterValue &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class OperationParameterValue; +/** Shared pointer of OperationParameterValue */ +using OperationParameterValuePtr = std::shared_ptr<OperationParameterValue>; +/** Non-null shared pointer of OperationParameterValue */ +using OperationParameterValueNNPtr = util::nn<OperationParameterValuePtr>; + +/** \brief A parameter value, ordered sequence of values, or reference to a + * file of parameter values. + * + * This combines a OperationParameter with the corresponding ParameterValue. + * + * \remark Implements OperationParameterValue from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL OperationParameterValue final + : public GeneralParameterValue { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~OperationParameterValue() override; + //! @endcond + + PROJ_DLL const OperationParameterNNPtr ¶meter() PROJ_CONST_DECL; + PROJ_DLL const ParameterValueNNPtr ¶meterValue() PROJ_CONST_DECL; + + PROJ_DLL static OperationParameterValueNNPtr + create(const OperationParameterNNPtr ¶meterIn, + const ParameterValueNNPtr &valueIn); + + PROJ_PRIVATE : + //! @cond Doxygen_Suppress + PROJ_INTERNAL static bool + convertFromAbridged(const std::string ¶mName, double &val, + const common::UnitOfMeasure *&unit, + int ¶mEPSGCode); + + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + //! @endcond + + protected: + PROJ_INTERNAL + OperationParameterValue(const OperationParameterNNPtr ¶meterIn, + const ParameterValueNNPtr &valueIn); + PROJ_INTERNAL OperationParameterValue(const OperationParameterValue &other); + INLINED_MAKE_SHARED + + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter, + const MethodMapping *mapping) + const override; // throw(io::FormattingException) + + private: + PROJ_OPAQUE_PRIVATE_DATA + OperationParameterValue & + operator=(const OperationParameterValue &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class OperationMethod; +/** Shared pointer of OperationMethod */ +using OperationMethodPtr = std::shared_ptr<OperationMethod>; +/** Non-null shared pointer of OperationMethod */ +using OperationMethodNNPtr = util::nn<OperationMethodPtr>; + +/** \brief The method (algorithm or procedure) used to perform the + * coordinate operation. + * + * For a projection method, this contains the name of the projection method + * and the name of the projection parameters. + * + * \remark Implements OperationMethod from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL OperationMethod : public common::IdentifiedObject { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~OperationMethod() override; + //! @endcond + + PROJ_DLL const util::optional<std::string> &formula() PROJ_CONST_DECL; + PROJ_DLL const util::optional<metadata::Citation> & + formulaCitation() PROJ_CONST_DECL; + PROJ_DLL const std::vector<GeneralOperationParameterNNPtr> & + parameters() PROJ_CONST_DECL; + + PROJ_DLL static OperationMethodNNPtr + create(const util::PropertyMap &properties, + const std::vector<GeneralOperationParameterNNPtr> ¶meters); + + PROJ_DLL static OperationMethodNNPtr + create(const util::PropertyMap &properties, + const std::vector<OperationParameterNNPtr> ¶meters); + + PROJ_DLL int getEPSGCode() PROJ_CONST_DECL; + + //! @cond Doxygen_Suppress + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + //! @endcond + + protected: + PROJ_INTERNAL OperationMethod(); + PROJ_INTERNAL OperationMethod(const OperationMethod &other); + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA + OperationMethod &operator=(const OperationMethod &other) = delete; +}; + +// --------------------------------------------------------------------------- + +/** \brief Exception that can be thrown when an invalid operation is attempted + * to be constructed. + */ +class PROJ_GCC_DLL InvalidOperation : public util::Exception { + public: + //! @cond Doxygen_Suppress + PROJ_INTERNAL explicit InvalidOperation(const char *message); + PROJ_INTERNAL explicit InvalidOperation(const std::string &message); + PROJ_DLL InvalidOperation(const InvalidOperation &other); + PROJ_DLL ~InvalidOperation() override; + //! @endcond +}; + +// --------------------------------------------------------------------------- + +class SingleOperation; +/** Shared pointer of SingleOperation */ +using SingleOperationPtr = std::shared_ptr<SingleOperation>; +/** Non-null shared pointer of SingleOperation */ +using SingleOperationNNPtr = util::nn<SingleOperationPtr>; + +/** \brief A single (not concatenated) coordinate operation + * (CoordinateOperation) + * + * \remark Implements SingleOperation from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL SingleOperation : virtual public CoordinateOperation { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~SingleOperation() override; + //! @endcond + + PROJ_DLL const std::vector<GeneralParameterValueNNPtr> & + parameterValues() PROJ_CONST_DECL; + PROJ_DLL const OperationMethodNNPtr &method() PROJ_CONST_DECL; + + PROJ_DLL const ParameterValuePtr & + parameterValue(const std::string ¶mName, int epsg_code = 0) const + noexcept; + + PROJ_DLL const ParameterValuePtr ¶meterValue(int epsg_code) const + noexcept; + + PROJ_DLL const common::Measure & + parameterValueMeasure(const std::string ¶mName, int epsg_code = 0) const + noexcept; + + PROJ_DLL const common::Measure ¶meterValueMeasure(int epsg_code) const + noexcept; + + PROJ_DLL static SingleOperationNNPtr createPROJBased( + const util::PropertyMap &properties, const std::string &PROJString, + const crs::CRSPtr &sourceCRS, const crs::CRSPtr &targetCRS, + const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies = + std::vector<metadata::PositionalAccuracyNNPtr>()); + + PROJ_DLL std::set<GridDescription> + gridsNeeded(const io::DatabaseContextPtr &databaseContext) const override; + + PROJ_PRIVATE : + //! @cond Doxygen_Suppress + + PROJ_DLL double + parameterValueNumeric(int epsg_code, + const common::UnitOfMeasure &targetUnit) const + noexcept; + + PROJ_INTERNAL double parameterValueNumericAsSI(int epsg_code) const + noexcept; + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + //! @endcond + + protected: + PROJ_INTERNAL explicit SingleOperation( + const OperationMethodNNPtr &methodIn); + PROJ_INTERNAL SingleOperation(const SingleOperation &other); + + PROJ_INTERNAL void + setParameterValues(const std::vector<GeneralParameterValueNNPtr> &values); + + PROJ_INTERNAL void + exportTransformationToWKT(io::WKTFormatter *formatter) const; + + PROJ_INTERNAL bool + exportToPROJStringGeneric(io::PROJStringFormatter *formatter) const; + + private: + PROJ_OPAQUE_PRIVATE_DATA + SingleOperation &operator=(const SingleOperation &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class Conversion; +/** Shared pointer of Conversion */ +using ConversionPtr = std::shared_ptr<Conversion>; +/** Non-null shared pointer of Conversion */ +using ConversionNNPtr = util::nn<ConversionPtr>; + +/** \brief A mathematical operation on coordinates in which the parameter + * values are defined rather than empirically derived. + * + * Application of the coordinate conversion introduces no error into output + * coordinates. The best-known example of a coordinate conversion is a map + * projection. For coordinate conversions the output coordinates are referenced + * to the same datum as are the input coordinates. + * + * Coordinate conversions forming a component of a derived CRS have a source + * crs::CRS and a target crs::CRS that are NOT specified through the source and + * target + * associations, but through associations from crs::DerivedCRS to + * crs::SingleCRS. + * + * \remark Implements Conversion from \ref ISO_19111_2018 + */ + +/*! + +\section projection_parameters Projection parameters + +\subsection colatitude_cone_axis Co-latitude of cone axis + +The rotation applied to spherical coordinates for the oblique projection, +measured on the conformal sphere in the plane of the meridian of origin. + +EPSG:1036 + +\subsection center_latitude Latitude of natural origin/Center Latitude + +The latitude of the point from which the values of both the geographical +coordinates on the ellipsoid and the grid coordinates on the projection are +deemed to increment or decrement for computational purposes. Alternatively it +may be considered as the latitude of the point which in the absence of +application of false coordinates has grid coordinates of (0,0). + +EPSG:8801 + +\subsection center_longitude Longitude of natural origin/Central Meridian + +The longitude of the point from which the values of both the geographical +coordinates on the ellipsoid and the grid coordinates on the projection are +deemed to increment or decrement for computational purposes. Alternatively it +may be considered as the longitude of the point which in the absence of +application of false coordinates has grid coordinates of (0,0). Sometimes known +as "central meridian (CM)". + +EPSG:8802 + +\subsection scale Scale Factor + +The factor by which the map grid is reduced or enlarged during the projection +process, defined by its value at the natural origin. + +EPSG:8805 + +\subsection false_easting False Easting + +Since the natural origin may be at or near the centre of the projection and +under normal coordinate circumstances would thus give rise to negative +coordinates over parts of the mapped area, this origin is usually given false +coordinates which are large enough to avoid this inconvenience. The False +Easting, FE, is the value assigned to the abscissa (east or west) axis of the +projection grid at the natural origin. + +EPSG:8806 + +\subsection false_northing False Northing + +Since the natural origin may be at or near the centre of the projection and +under normal coordinate circumstances would thus give rise to negative +coordinates over parts of the mapped area, this origin is usually given false +coordinates which are large enough to avoid this inconvenience. The False +Northing, FN, is the value assigned to the ordinate (north or south) axis of the +projection grid at the natural origin. + +EPSG:8807 + +\subsection latitude_projection_centre Latitute of projection centre + +For an oblique projection, this is the latitude of the point at which the +azimuth of the central line is defined. + +EPSG:8811 + +\subsection longitude_projection_centre Longitude of projection centre + +For an oblique projection, this is the longitude of the point at which the +azimuth of the central line is defined. + +EPSG:8812 + +\subsection azimuth_initial_line Azimuth of initial line + +The azimuthal direction (north zero, east of north being positive) of the great +circle which is the centre line of an oblique projection. The azimuth is given +at the projection centre. + +EPSG:8813 + +\subsection angle_from_recitfied_to_skrew_grid Angle from Rectified to Skew Grid + +The angle at the natural origin of an oblique projection through which the +natural coordinate reference system is rotated to make the projection north +axis parallel with true north. + +EPSG:8814 + +\subsection scale_factor_initial_line Scale factor on initial line + +The factor by which the map grid is reduced or enlarged during the projection +process, defined by its value at the projection center. + +EPSG:8815 + +\subsection easting_projection_centre Easting at projection centre + +The easting value assigned to the projection centre. + +EPSG:8816 + +\subsection northing_projection_centre Northing at projection centre + +The northing value assigned to the projection centre. + +EPSG:8817 + +\subsection latitude_pseudo_standard_parallel Latitude of pseudo standard +parallel + +Latitude of the parallel on which the conic or cylindrical projection is based. +This latitude is not geographic, but is defined on the conformal sphere AFTER +its rotation to obtain the oblique aspect of the projection. + +EPSG:8818 + +\subsection scale_factor_pseudo_standard_parallel Scale factor on pseudo +standard parallel + +The factor by which the map grid is reduced or enlarged during the projection +process, defined by its value at the pseudo-standard parallel. +EPSG:8819 + +\subsection latitude_false_origin Latitude of false origin + +The latitude of the point which is not the natural origin and at which grid +coordinate values false easting and false northing are defined. + +EPSG:8821 + +\subsection longitude_false_origin Longitude of false origin + +The longitude of the point which is not the natural origin and at which grid +coordinate values false easting and false northing are defined. + +EPSG:8822 + +\subsection latitude_first_std_parallel Latitude of 1st standard parallel + +For a conic projection with two standard parallels, this is the latitude of one +of the parallels of intersection of the cone with the ellipsoid. It is normally +but not necessarily that nearest to the pole. Scale is true along this parallel. + +EPSG:8823 + +\subsection latitude_second_std_parallel Latitude of 2nd standard parallel + +For a conic projection with two standard parallels, this is the latitude of one +of the parallels at which the cone intersects with the ellipsoid. It is normally +but not necessarily that nearest to the equator. Scale is true along this +parallel. + +EPSG:8824 + +\subsection easting_false_origin Easting of false origin + +The easting value assigned to the false origin. + +EPSG:8826 + +\subsection northing_false_origin Northing of false origin + +The northing value assigned to the false origin. + +EPSG:8827 + +\subsection latitude_std_parallel Latitude of standard parallel + +For polar aspect azimuthal projections, the parallel on which the scale factor +is defined to be unity. + +EPSG:8832 + +\subsection longitude_of_origin Longitude of origin + +For polar aspect azimuthal projections, the meridian along which the +northing axis increments and also across which parallels of latitude +increment towards the north pole. + +EPSG:8833 + +*/ + +class PROJ_GCC_DLL Conversion : public SingleOperation { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~Conversion() override; + //! @endcond + + //! @cond Doxygen_Suppress + PROJ_INTERNAL ConversionNNPtr shallowClone() const; + //! @endcond + + PROJ_DLL CoordinateOperationNNPtr inverse() const override; + + //! @cond Doxygen_Suppress + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + //! @endcond + + PROJ_DLL bool isUTM(int &zone, bool &north) const; + + PROJ_DLL ConversionNNPtr identify() const; + + PROJ_DLL static ConversionNNPtr + create(const util::PropertyMap &properties, + const OperationMethodNNPtr &methodIn, + const std::vector<GeneralParameterValueNNPtr> + &values); // throw InvalidOperation + + PROJ_DLL static ConversionNNPtr + create(const util::PropertyMap &propertiesConversion, + const util::PropertyMap &propertiesOperationMethod, + const std::vector<OperationParameterNNPtr> ¶meters, + const std::vector<ParameterValueNNPtr> + &values); // throw InvalidOperation + + PROJ_DLL static ConversionNNPtr + createUTM(const util::PropertyMap &properties, int zone, bool north); + + PROJ_DLL static ConversionNNPtr createTransverseMercator( + const util::PropertyMap &properties, const common::Angle ¢erLat, + const common::Angle ¢erLong, const common::Scale &scale, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr createGaussSchreiberTransverseMercator( + const util::PropertyMap &properties, const common::Angle ¢erLat, + const common::Angle ¢erLong, const common::Scale &scale, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr createTransverseMercatorSouthOriented( + const util::PropertyMap &properties, const common::Angle ¢erLat, + const common::Angle ¢erLong, const common::Scale &scale, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createTwoPointEquidistant(const util::PropertyMap &properties, + const common::Angle &latitudeFirstPoint, + const common::Angle &longitudeFirstPoint, + const common::Angle &latitudeSecondPoint, + const common::Angle &longitudeSeconPoint, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr createTunisiaMappingGrid( + const util::PropertyMap &properties, const common::Angle ¢erLat, + const common::Angle ¢erLong, const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createAlbersEqualArea(const util::PropertyMap &properties, + const common::Angle &latitudeFalseOrigin, + const common::Angle &longitudeFalseOrigin, + const common::Angle &latitudeFirstParallel, + const common::Angle &latitudeSecondParallel, + const common::Length &eastingFalseOrigin, + const common::Length &northingFalseOrigin); + + PROJ_DLL static ConversionNNPtr createLambertConicConformal_1SP( + const util::PropertyMap &properties, const common::Angle ¢erLat, + const common::Angle ¢erLong, const common::Scale &scale, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createLambertConicConformal_2SP(const util::PropertyMap &properties, + const common::Angle &latitudeFalseOrigin, + const common::Angle &longitudeFalseOrigin, + const common::Angle &latitudeFirstParallel, + const common::Angle &latitudeSecondParallel, + const common::Length &eastingFalseOrigin, + const common::Length &northingFalseOrigin); + + PROJ_DLL static ConversionNNPtr createLambertConicConformal_2SP_Michigan( + const util::PropertyMap &properties, + const common::Angle &latitudeFalseOrigin, + const common::Angle &longitudeFalseOrigin, + const common::Angle &latitudeFirstParallel, + const common::Angle &latitudeSecondParallel, + const common::Length &eastingFalseOrigin, + const common::Length &northingFalseOrigin, + const common::Scale &ellipsoidScalingFactor); + + PROJ_DLL static ConversionNNPtr createLambertConicConformal_2SP_Belgium( + const util::PropertyMap &properties, + const common::Angle &latitudeFalseOrigin, + const common::Angle &longitudeFalseOrigin, + const common::Angle &latitudeFirstParallel, + const common::Angle &latitudeSecondParallel, + const common::Length &eastingFalseOrigin, + const common::Length &northingFalseOrigin); + + PROJ_DLL static ConversionNNPtr + createAzimuthalEquidistant(const util::PropertyMap &properties, + const common::Angle &latitudeNatOrigin, + const common::Angle &longitudeNatOrigin, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createGuamProjection(const util::PropertyMap &properties, + const common::Angle &latitudeNatOrigin, + const common::Angle &longitudeNatOrigin, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createBonne(const util::PropertyMap &properties, + const common::Angle &latitudeNatOrigin, + const common::Angle &longitudeNatOrigin, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr createLambertCylindricalEqualAreaSpherical( + const util::PropertyMap &properties, + const common::Angle &latitudeFirstParallel, + const common::Angle &longitudeNatOrigin, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr createLambertCylindricalEqualArea( + const util::PropertyMap &properties, + const common::Angle &latitudeFirstParallel, + const common::Angle &longitudeNatOrigin, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr createCassiniSoldner( + const util::PropertyMap &properties, const common::Angle ¢erLat, + const common::Angle ¢erLong, const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createEquidistantConic(const util::PropertyMap &properties, + const common::Angle ¢erLat, + const common::Angle ¢erLong, + const common::Angle &latitudeFirstParallel, + const common::Angle &latitudeSecondParallel, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createEckertI(const util::PropertyMap &properties, + const common::Angle ¢erLong, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createEckertII(const util::PropertyMap &properties, + const common::Angle ¢erLong, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createEckertIII(const util::PropertyMap &properties, + const common::Angle ¢erLong, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createEckertIV(const util::PropertyMap &properties, + const common::Angle ¢erLong, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createEckertV(const util::PropertyMap &properties, + const common::Angle ¢erLong, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createEckertVI(const util::PropertyMap &properties, + const common::Angle ¢erLong, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createEquidistantCylindrical(const util::PropertyMap &properties, + const common::Angle &latitudeFirstParallel, + const common::Angle &longitudeNatOrigin, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr createEquidistantCylindricalSpherical( + const util::PropertyMap &properties, + const common::Angle &latitudeFirstParallel, + const common::Angle &longitudeNatOrigin, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createGall(const util::PropertyMap &properties, + const common::Angle ¢erLong, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createGoodeHomolosine(const util::PropertyMap &properties, + const common::Angle ¢erLong, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createInterruptedGoodeHomolosine(const util::PropertyMap &properties, + const common::Angle ¢erLong, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr createGeostationarySatelliteSweepX( + const util::PropertyMap &properties, const common::Angle ¢erLong, + const common::Length &height, const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr createGeostationarySatelliteSweepY( + const util::PropertyMap &properties, const common::Angle ¢erLong, + const common::Length &height, const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr createGnomonic( + const util::PropertyMap &properties, const common::Angle ¢erLat, + const common::Angle ¢erLong, const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr createHotineObliqueMercatorVariantA( + const util::PropertyMap &properties, + const common::Angle &latitudeProjectionCentre, + const common::Angle &longitudeProjectionCentre, + const common::Angle &azimuthInitialLine, + const common::Angle &angleFromRectifiedToSkrewGrid, + const common::Scale &scale, const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr createHotineObliqueMercatorVariantB( + const util::PropertyMap &properties, + const common::Angle &latitudeProjectionCentre, + const common::Angle &longitudeProjectionCentre, + const common::Angle &azimuthInitialLine, + const common::Angle &angleFromRectifiedToSkrewGrid, + const common::Scale &scale, + const common::Length &eastingProjectionCentre, + const common::Length &northingProjectionCentre); + + PROJ_DLL static ConversionNNPtr + createHotineObliqueMercatorTwoPointNaturalOrigin( + const util::PropertyMap &properties, + const common::Angle &latitudeProjectionCentre, + const common::Angle &latitudePoint1, + const common::Angle &longitudePoint1, + const common::Angle &latitudePoint2, + const common::Angle &longitudePoint2, const common::Scale &scale, + const common::Length &eastingProjectionCentre, + const common::Length &northingProjectionCentre); + + PROJ_DLL static ConversionNNPtr createInternationalMapWorldPolyconic( + const util::PropertyMap &properties, const common::Angle ¢erLong, + const common::Angle &latitudeFirstParallel, + const common::Angle &latitudeSecondParallel, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr createKrovakNorthOriented( + const util::PropertyMap &properties, + const common::Angle &latitudeProjectionCentre, + const common::Angle &longitudeOfOrigin, + const common::Angle &colatitudeConeAxis, + const common::Angle &latitudePseudoStandardParallel, + const common::Scale &scaleFactorPseudoStandardParallel, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createKrovak(const util::PropertyMap &properties, + const common::Angle &latitudeProjectionCentre, + const common::Angle &longitudeOfOrigin, + const common::Angle &colatitudeConeAxis, + const common::Angle &latitudePseudoStandardParallel, + const common::Scale &scaleFactorPseudoStandardParallel, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createLambertAzimuthalEqualArea(const util::PropertyMap &properties, + const common::Angle &latitudeNatOrigin, + const common::Angle &longitudeNatOrigin, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createMillerCylindrical(const util::PropertyMap &properties, + const common::Angle ¢erLong, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr createMercatorVariantA( + const util::PropertyMap &properties, const common::Angle ¢erLat, + const common::Angle ¢erLong, const common::Scale &scale, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createMercatorVariantB(const util::PropertyMap &properties, + const common::Angle &latitudeFirstParallel, + const common::Angle ¢erLong, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr createPopularVisualisationPseudoMercator( + const util::PropertyMap &properties, const common::Angle ¢erLat, + const common::Angle ¢erLong, const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createMollweide(const util::PropertyMap &properties, + const common::Angle ¢erLong, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr createNewZealandMappingGrid( + const util::PropertyMap &properties, const common::Angle ¢erLat, + const common::Angle ¢erLong, const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr createObliqueStereographic( + const util::PropertyMap &properties, const common::Angle ¢erLat, + const common::Angle ¢erLong, const common::Scale &scale, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr createOrthographic( + const util::PropertyMap &properties, const common::Angle ¢erLat, + const common::Angle ¢erLong, const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr createAmericanPolyconic( + const util::PropertyMap &properties, const common::Angle ¢erLat, + const common::Angle ¢erLong, const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr createPolarStereographicVariantA( + const util::PropertyMap &properties, const common::Angle ¢erLat, + const common::Angle ¢erLong, const common::Scale &scale, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr createPolarStereographicVariantB( + const util::PropertyMap &properties, + const common::Angle &latitudeStandardParallel, + const common::Angle &longitudeOfOrigin, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createRobinson(const util::PropertyMap &properties, + const common::Angle ¢erLong, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createSinusoidal(const util::PropertyMap &properties, + const common::Angle ¢erLong, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr createStereographic( + const util::PropertyMap &properties, const common::Angle ¢erLat, + const common::Angle ¢erLong, const common::Scale &scale, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createVanDerGrinten(const util::PropertyMap &properties, + const common::Angle ¢erLong, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createWagnerI(const util::PropertyMap &properties, + const common::Angle ¢erLong, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createWagnerII(const util::PropertyMap &properties, + const common::Angle ¢erLong, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createWagnerIII(const util::PropertyMap &properties, + const common::Angle &latitudeTrueScale, + const common::Angle ¢erLong, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createWagnerIV(const util::PropertyMap &properties, + const common::Angle ¢erLong, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createWagnerV(const util::PropertyMap &properties, + const common::Angle ¢erLong, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createWagnerVI(const util::PropertyMap &properties, + const common::Angle ¢erLong, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createWagnerVII(const util::PropertyMap &properties, + const common::Angle ¢erLong, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr createQuadrilateralizedSphericalCube( + const util::PropertyMap &properties, const common::Angle ¢erLat, + const common::Angle ¢erLong, const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr createSphericalCrossTrackHeight( + const util::PropertyMap &properties, const common::Angle &pegPointLat, + const common::Angle &pegPointLong, const common::Angle &pegPointHeading, + const common::Length &pegPointHeight); + + PROJ_DLL static ConversionNNPtr + createEqualEarth(const util::PropertyMap &properties, + const common::Angle ¢erLong, + const common::Length &falseEasting, + const common::Length &falseNorthing); + + PROJ_DLL static ConversionNNPtr + createChangeVerticalUnit(const util::PropertyMap &properties, + const common::Scale &factor); + + PROJ_DLL static ConversionNNPtr createAxisOrderReversal(bool is3D); + + PROJ_DLL static ConversionNNPtr + createGeographicGeocentric(const util::PropertyMap &properties); + + PROJ_DLL ConversionPtr convertToOtherMethod(int targetEPSGCode) const; + + PROJ_PRIVATE : + //! @cond Doxygen_Suppress + PROJ_INTERNAL void + _exportToPROJString(io::PROJStringFormatter *formatter) + const override; // throw(FormattingException) + + PROJ_INTERNAL const char *getESRIMethodName() const; + + PROJ_INTERNAL const char *getWKT1GDALMethodName() const; + //! @endcond + + protected: + PROJ_INTERNAL + Conversion(const OperationMethodNNPtr &methodIn, + const std::vector<GeneralParameterValueNNPtr> &values); + PROJ_INTERNAL Conversion(const Conversion &other); + INLINED_MAKE_SHARED + + PROJ_FRIEND(crs::ProjectedCRS); + PROJ_INTERNAL void addWKTExtensionNode(io::WKTFormatter *formatter) const; + + private: + PROJ_OPAQUE_PRIVATE_DATA + Conversion &operator=(const Conversion &other) = delete; + + PROJ_INTERNAL static ConversionNNPtr + create(const util::PropertyMap &properties, int method_epsg_code, + const std::vector<ParameterValueNNPtr> &values); + + PROJ_INTERNAL static ConversionNNPtr + create(const util::PropertyMap &properties, const char *method_wkt2_name, + const std::vector<ParameterValueNNPtr> &values); +}; + +// --------------------------------------------------------------------------- + +class Transformation; +/** Shared pointer of Transformation */ +using TransformationPtr = std::shared_ptr<Transformation>; +/** Non-null shared pointer of Transformation */ +using TransformationNNPtr = util::nn<TransformationPtr>; + +/** \brief A mathematical operation on coordinates in which parameters are + * empirically derived from data containing the coordinates of a series of + * points in both coordinate reference systems. + * + * This computational process is usually "over-determined", allowing derivation + * of error (or accuracy) estimates for the coordinate transformation. Also, + * the stochastic nature of the parameters may result in multiple (different) + * versions of the same coordinate transformations between the same source and + * target CRSs. Any single coordinate operation in which the input and output + * coordinates are referenced to different datums (reference frames) will be a + * coordinate transformation. + * + * \remark Implements Transformation from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL Transformation : public SingleOperation { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~Transformation() override; + //! @endcond + + PROJ_DLL const crs::CRSNNPtr &sourceCRS() PROJ_CONST_DECL; + PROJ_DLL const crs::CRSNNPtr &targetCRS() PROJ_CONST_DECL; + + PROJ_DLL CoordinateOperationNNPtr inverse() const override; + + PROJ_DLL static TransformationNNPtr + create(const util::PropertyMap &properties, + const crs::CRSNNPtr &sourceCRSIn, const crs::CRSNNPtr &targetCRSIn, + const crs::CRSPtr &interpolationCRSIn, + const OperationMethodNNPtr &methodIn, + const std::vector<GeneralParameterValueNNPtr> &values, + const std::vector<metadata::PositionalAccuracyNNPtr> + &accuracies); // throw InvalidOperation + + PROJ_DLL static TransformationNNPtr + create(const util::PropertyMap &propertiesTransformation, + const crs::CRSNNPtr &sourceCRSIn, const crs::CRSNNPtr &targetCRSIn, + const crs::CRSPtr &interpolationCRSIn, + const util::PropertyMap &propertiesOperationMethod, + const std::vector<OperationParameterNNPtr> ¶meters, + const std::vector<ParameterValueNNPtr> &values, + const std::vector<metadata::PositionalAccuracyNNPtr> + &accuracies); // throw InvalidOperation + + PROJ_DLL static TransformationNNPtr createGeocentricTranslations( + const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn, + const crs::CRSNNPtr &targetCRSIn, double translationXMetre, + double translationYMetre, double translationZMetre, + const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies); + + PROJ_DLL static TransformationNNPtr createPositionVector( + const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn, + const crs::CRSNNPtr &targetCRSIn, double translationXMetre, + double translationYMetre, double translationZMetre, + double rotationXArcSecond, double rotationYArcSecond, + double rotationZArcSecond, double scaleDifferencePPM, + const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies); + + PROJ_DLL static TransformationNNPtr createCoordinateFrameRotation( + const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn, + const crs::CRSNNPtr &targetCRSIn, double translationXMetre, + double translationYMetre, double translationZMetre, + double rotationXArcSecond, double rotationYArcSecond, + double rotationZArcSecond, double scaleDifferencePPM, + const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies); + + PROJ_DLL static TransformationNNPtr createTimeDependentPositionVector( + const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn, + const crs::CRSNNPtr &targetCRSIn, double translationXMetre, + double translationYMetre, double translationZMetre, + double rotationXArcSecond, double rotationYArcSecond, + double rotationZArcSecond, double scaleDifferencePPM, + double rateTranslationX, double rateTranslationY, + double rateTranslationZ, double rateRotationX, double rateRotationY, + double rateRotationZ, double rateScaleDifference, + double referenceEpochYear, + const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies); + + PROJ_DLL static TransformationNNPtr + createTimeDependentCoordinateFrameRotation( + const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn, + const crs::CRSNNPtr &targetCRSIn, double translationXMetre, + double translationYMetre, double translationZMetre, + double rotationXArcSecond, double rotationYArcSecond, + double rotationZArcSecond, double scaleDifferencePPM, + double rateTranslationX, double rateTranslationY, + double rateTranslationZ, double rateRotationX, double rateRotationY, + double rateRotationZ, double rateScaleDifference, + double referenceEpochYear, + const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies); + + PROJ_DLL static TransformationNNPtr createTOWGS84( + const crs::CRSNNPtr &sourceCRSIn, + const std::vector<double> &TOWGS84Parameters); // throw InvalidOperation + + PROJ_DLL static TransformationNNPtr createNTv2( + const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn, + const crs::CRSNNPtr &targetCRSIn, const std::string &filename, + const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies); + + PROJ_DLL static TransformationNNPtr createMolodensky( + const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn, + const crs::CRSNNPtr &targetCRSIn, double translationXMetre, + double translationYMetre, double translationZMetre, + double semiMajorAxisDifferenceMetre, double flattingDifference, + const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies); + + PROJ_DLL static TransformationNNPtr createAbridgedMolodensky( + const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn, + const crs::CRSNNPtr &targetCRSIn, double translationXMetre, + double translationYMetre, double translationZMetre, + double semiMajorAxisDifferenceMetre, double flattingDifference, + const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies); + + PROJ_DLL static TransformationNNPtr + createGravityRelatedHeightToGeographic3D( + const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn, + const crs::CRSNNPtr &targetCRSIn, const std::string &filename, + const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies); + + PROJ_DLL static TransformationNNPtr createVERTCON( + const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn, + const crs::CRSNNPtr &targetCRSIn, const std::string &filename, + const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies); + + PROJ_DLL static TransformationNNPtr createLongitudeRotation( + const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn, + const crs::CRSNNPtr &targetCRSIn, const common::Angle &offset); + + PROJ_DLL static TransformationNNPtr createGeographic2DOffsets( + const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn, + const crs::CRSNNPtr &targetCRSIn, const common::Angle &offsetLat, + const common::Angle &offsetLon, + const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies); + + PROJ_DLL static TransformationNNPtr createGeographic3DOffsets( + const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn, + const crs::CRSNNPtr &targetCRSIn, const common::Angle &offsetLat, + const common::Angle &offsetLon, const common::Length &offsetHeight, + const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies); + + PROJ_DLL static TransformationNNPtr createGeographic2DWithHeightOffsets( + const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn, + const crs::CRSNNPtr &targetCRSIn, const common::Angle &offsetLat, + const common::Angle &offsetLon, const common::Length &offsetHeight, + const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies); + + PROJ_DLL static TransformationNNPtr createVerticalOffset( + const util::PropertyMap &properties, const crs::CRSNNPtr &sourceCRSIn, + const crs::CRSNNPtr &targetCRSIn, const common::Length &offsetHeight, + const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies); + + PROJ_DLL TransformationNNPtr substitutePROJAlternativeGridNames( + io::DatabaseContextNNPtr databaseContext) const; + + PROJ_PRIVATE : + //! @cond Doxygen_Suppress + PROJ_INTERNAL const std::string & + getNTv2Filename() const; + + PROJ_FOR_TEST std::vector<double> + getTOWGS84Parameters() const; // throw(io::FormattingException) + + PROJ_INTERNAL const std::string &getHeightToGeographic3DFilename() const; + + PROJ_INTERNAL bool isLongitudeRotation() const; + + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + + //! @endcond + + protected: + PROJ_INTERNAL Transformation( + const crs::CRSNNPtr &sourceCRSIn, const crs::CRSNNPtr &targetCRSIn, + const crs::CRSPtr &interpolationCRSIn, + const OperationMethodNNPtr &methodIn, + const std::vector<GeneralParameterValueNNPtr> &values, + const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies); + INLINED_MAKE_SHARED + + PROJ_INTERNAL void _exportToPROJString(io::PROJStringFormatter *formatter) + const override; // throw(FormattingException) + + PROJ_INTERNAL TransformationNNPtr inverseAsTransformation() const; + + private: + PROJ_OPAQUE_PRIVATE_DATA + Transformation(const Transformation &) = delete; +}; + +// --------------------------------------------------------------------------- + +class PointMotionOperation; +/** Shared pointer of PointMotionOperation */ +using PointMotionOperationPtr = std::shared_ptr<PointMotionOperation>; +/** Non-null shared pointer of PointMotionOperation */ +using PointMotionOperationNNPtr = util::nn<PointMotionOperationPtr>; + +/** \brief A mathematical operation that describes the change of coordinate + * values within one coordinate reference system due to the motion of the + * point between one coordinate epoch and another coordinate epoch. + * + * The motion is due to tectonic plate movement or deformation. + * + * \remark Implements PointMotionOperation from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL PointMotionOperation : public SingleOperation { + public: + // TODO + //! @cond Doxygen_Suppress + PROJ_DLL ~PointMotionOperation() override; + //! @endcond + + private: + PointMotionOperation(const PointMotionOperation &) = delete; +}; + +// --------------------------------------------------------------------------- + +class ConcatenatedOperation; +/** Shared pointer of ConcatenatedOperation */ +using ConcatenatedOperationPtr = std::shared_ptr<ConcatenatedOperation>; +/** Non-null shared pointer of ConcatenatedOperation */ +using ConcatenatedOperationNNPtr = util::nn<ConcatenatedOperationPtr>; + +/** \brief An ordered sequence of two or more single coordinate operations + * (SingleOperation). + * + * The sequence of coordinate operations is constrained by the requirement + * that + * the source coordinate reference system of step n+1 shall be the same as + * the target coordinate reference system of step n. + * + * \remark Implements ConcatenatedOperation from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL ConcatenatedOperation final : public CoordinateOperation { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~ConcatenatedOperation() override; + //! @endcond + + PROJ_DLL const std::vector<CoordinateOperationNNPtr> &operations() const; + + PROJ_DLL CoordinateOperationNNPtr inverse() const override; + + //! @cond Doxygen_Suppress + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + //! @endcond + + PROJ_DLL static ConcatenatedOperationNNPtr + create(const util::PropertyMap &properties, + const std::vector<CoordinateOperationNNPtr> &operationsIn, + const std::vector<metadata::PositionalAccuracyNNPtr> + &accuracies); // throw InvalidOperation + + PROJ_DLL static CoordinateOperationNNPtr createComputeMetadata( + const std::vector<CoordinateOperationNNPtr> &operationsIn, + bool checkExtent); // throw InvalidOperation + + PROJ_DLL std::set<GridDescription> + gridsNeeded(const io::DatabaseContextPtr &databaseContext) const override; + + protected: + PROJ_INTERNAL explicit ConcatenatedOperation( + const std::vector<CoordinateOperationNNPtr> &operationsIn); + + PROJ_INTERNAL void _exportToPROJString(io::PROJStringFormatter *formatter) + const override; // throw(FormattingException) + + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA + ConcatenatedOperation & + operator=(const ConcatenatedOperation &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class CoordinateOperationContext; +/** Unique pointer of CoordinateOperationContext */ +using CoordinateOperationContextPtr = + std::unique_ptr<CoordinateOperationContext>; +/** Non-null unique pointer of CoordinateOperationContext */ +using CoordinateOperationContextNNPtr = util::nn<CoordinateOperationContextPtr>; + +/** \brief Context in which a coordinate operation is to be used. + * + * \remark Implements [CoordinateOperationFactory + * https://sis.apache.org/apidocs/org/apache/sis/referencing/operation/CoordinateOperationContext.html] + * from + * Apache SIS + */ + +class PROJ_GCC_DLL CoordinateOperationContext { + public: + //! @cond Doxygen_Suppress + PROJ_DLL virtual ~CoordinateOperationContext(); + //! @endcond + + PROJ_DLL const io::AuthorityFactoryPtr &getAuthorityFactory() const; + + PROJ_DLL const metadata::ExtentPtr &getAreaOfInterest() const; + + PROJ_DLL void setAreaOfInterest(const metadata::ExtentPtr &extent); + + PROJ_DLL double getDesiredAccuracy() const; + + PROJ_DLL void setDesiredAccuracy(double accuracy); + + /** Specify how source and target CRS extent should be used to restrict + * candidate operations (only taken into account if no explicit area of + * interest is specified. */ + enum class SourceTargetCRSExtentUse { + /** Ignore CRS extent */ + NONE, + /** Test coordinate operation extent against both CRS extent. */ + BOTH, + /** Test coordinate operation extent against the intersection of both + CRS extent. */ + INTERSECTION, + /** Test coordinate operation against the smallest of both CRS extent. + */ + SMALLEST, + }; + + PROJ_DLL void setSourceAndTargetCRSExtentUse(SourceTargetCRSExtentUse use); + + PROJ_DLL SourceTargetCRSExtentUse getSourceAndTargetCRSExtentUse() const; + + /** Spatial criterion to restrict candiate operations. */ + enum class SpatialCriterion { + /** The area of validity of transforms should strictly contain the + * are of interest. */ + STRICT_CONTAINMENT, + + /** The area of validity of transforms should at least intersect the + * area of interest. */ + PARTIAL_INTERSECTION + }; + + PROJ_DLL void setSpatialCriterion(SpatialCriterion criterion); + + PROJ_DLL SpatialCriterion getSpatialCriterion() const; + + PROJ_DLL void setUsePROJAlternativeGridNames(bool usePROJNames); + + PROJ_DLL bool getUsePROJAlternativeGridNames() const; + + /** Describe how grid availability is used. */ + enum class GridAvailabilityUse { + /** Grid availability is only used for sorting results. Operations + * where some grids are missing will be sorted last. */ + USE_FOR_SORTING, + + /** Completely discard an operation if a required grid is missing. */ + DISCARD_OPERATION_IF_MISSING_GRID, + + /** Ignore grid availability at all. Results will be presented as if + * all grids were available. */ + IGNORE_GRID_AVAILABILITY, + }; + + PROJ_DLL void setGridAvailabilityUse(GridAvailabilityUse use); + + PROJ_DLL GridAvailabilityUse getGridAvailabilityUse() const; + + PROJ_DLL void setAllowUseIntermediateCRS(bool use); + + PROJ_DLL bool getAllowUseIntermediateCRS() const; + + PROJ_DLL void + setIntermediateCRS(const std::vector<std::pair<std::string, std::string>> + &intermediateCRSAuthCodes); + + PROJ_DLL const std::vector<std::pair<std::string, std::string>> & + getIntermediateCRS() const; + + PROJ_DLL static CoordinateOperationContextNNPtr + create(const io::AuthorityFactoryPtr &authorityFactory, + const metadata::ExtentPtr &extent, double accuracy); + + protected: + PROJ_INTERNAL CoordinateOperationContext(); + INLINED_MAKE_UNIQUE + + private: + PROJ_OPAQUE_PRIVATE_DATA +}; + +// --------------------------------------------------------------------------- + +class CoordinateOperationFactory; +/** Unique pointer of CoordinateOperationFactory */ +using CoordinateOperationFactoryPtr = + std::unique_ptr<CoordinateOperationFactory>; +/** Non-null unique pointer of CoordinateOperationFactory */ +using CoordinateOperationFactoryNNPtr = util::nn<CoordinateOperationFactoryPtr>; + +/** \brief Creates coordinate operations. This factory is capable to find + * coordinate transformations or conversions between two coordinate + * reference + * systems. + * + * \remark Implements (partially) CoordinateOperationFactory from \ref + * GeoAPI + */ +class PROJ_GCC_DLL CoordinateOperationFactory { + public: + //! @cond Doxygen_Suppress + PROJ_DLL virtual ~CoordinateOperationFactory(); + //! @endcond + + PROJ_DLL CoordinateOperationPtr createOperation( + const crs::CRSNNPtr &sourceCRS, const crs::CRSNNPtr &targetCRS) const; + + PROJ_DLL std::vector<CoordinateOperationNNPtr> + createOperations(const crs::CRSNNPtr &sourceCRS, + const crs::CRSNNPtr &targetCRS, + const CoordinateOperationContextNNPtr &context) const; + + PROJ_DLL static CoordinateOperationFactoryNNPtr create(); + + protected: + PROJ_INTERNAL CoordinateOperationFactory(); + INLINED_MAKE_UNIQUE + + private: + PROJ_OPAQUE_PRIVATE_DATA +}; + +} // namespace operation + +NS_PROJ_END + +#endif // COORDINATEOPERATION_HH_INCLUDED diff --git a/include/proj/coordinatesystem.hpp b/include/proj/coordinatesystem.hpp new file mode 100644 index 00000000..89c2f99c --- /dev/null +++ b/include/proj/coordinatesystem.hpp @@ -0,0 +1,701 @@ +/****************************************************************************** + * + * Project: PROJ + * Purpose: ISO19111:2018 implementation + * Author: Even Rouault <even dot rouault at spatialys dot com> + * + ****************************************************************************** + * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ****************************************************************************/ + +#ifndef CS_HH_INCLUDED +#define CS_HH_INCLUDED + +#include <memory> +#include <set> +#include <string> +#include <vector> + +#include "common.hpp" +#include "io.hpp" +#include "util.hpp" + +NS_PROJ_START + +/** osgeo.proj.cs namespace + + \brief Coordinate systems and their axis. +*/ +namespace cs { + +// --------------------------------------------------------------------------- + +/** \brief The direction of positive increase in the coordinate value for a + * coordinate system axis. + * + * \remark Implements AxisDirection from \ref ISO_19111_2018 + */ +class AxisDirection : public util::CodeList { + public: + //! @cond Doxygen_Suppress + PROJ_DLL static const AxisDirection * + valueOf(const std::string &nameIn) noexcept; + //! @endcond + + PROJ_DLL static const AxisDirection NORTH; + PROJ_DLL static const AxisDirection NORTH_NORTH_EAST; + PROJ_DLL static const AxisDirection NORTH_EAST; + PROJ_DLL static const AxisDirection EAST_NORTH_EAST; + PROJ_DLL static const AxisDirection EAST; + PROJ_DLL static const AxisDirection EAST_SOUTH_EAST; + PROJ_DLL static const AxisDirection SOUTH_EAST; + PROJ_DLL static const AxisDirection SOUTH_SOUTH_EAST; + PROJ_DLL static const AxisDirection SOUTH; + PROJ_DLL static const AxisDirection SOUTH_SOUTH_WEST; + PROJ_DLL static const AxisDirection SOUTH_WEST; + PROJ_DLL static const AxisDirection + WEST_SOUTH_WEST; // note: was forgotten in WKT2-2015 + PROJ_DLL static const AxisDirection WEST; + PROJ_DLL static const AxisDirection WEST_NORTH_WEST; + PROJ_DLL static const AxisDirection NORTH_WEST; + PROJ_DLL static const AxisDirection NORTH_NORTH_WEST; + PROJ_DLL static const AxisDirection UP; + PROJ_DLL static const AxisDirection DOWN; + PROJ_DLL static const AxisDirection GEOCENTRIC_X; + PROJ_DLL static const AxisDirection GEOCENTRIC_Y; + PROJ_DLL static const AxisDirection GEOCENTRIC_Z; + PROJ_DLL static const AxisDirection COLUMN_POSITIVE; + PROJ_DLL static const AxisDirection COLUMN_NEGATIVE; + PROJ_DLL static const AxisDirection ROW_POSITIVE; + PROJ_DLL static const AxisDirection ROW_NEGATIVE; + PROJ_DLL static const AxisDirection DISPLAY_RIGHT; + PROJ_DLL static const AxisDirection DISPLAY_LEFT; + PROJ_DLL static const AxisDirection DISPLAY_UP; + PROJ_DLL static const AxisDirection DISPLAY_DOWN; + PROJ_DLL static const AxisDirection FORWARD; + PROJ_DLL static const AxisDirection AFT; + PROJ_DLL static const AxisDirection PORT; + PROJ_DLL static const AxisDirection STARBOARD; + PROJ_DLL static const AxisDirection CLOCKWISE; + PROJ_DLL static const AxisDirection COUNTER_CLOCKWISE; + PROJ_DLL static const AxisDirection TOWARDS; + PROJ_DLL static const AxisDirection AWAY_FROM; + PROJ_DLL static const AxisDirection FUTURE; + PROJ_DLL static const AxisDirection PAST; + PROJ_DLL static const AxisDirection UNSPECIFIED; + + private: + explicit AxisDirection(const std::string &nameIn); + + static std::map<std::string, const AxisDirection *> registry; +}; + +// --------------------------------------------------------------------------- + +class Meridian; +/** Shared pointer of Meridian. */ +using MeridianPtr = std::shared_ptr<Meridian>; +/** Non-null shared pointer of Meridian. */ +using MeridianNNPtr = util::nn<MeridianPtr>; + +/** \brief The meridian that the axis follows from the pole, for a coordinate + * reference system centered on a pole. + * + * \note There is no modelling for this concept in \ref ISO_19111_2018 + * + * \remark Implements MERIDIAN from \ref WKT2 + */ +class PROJ_GCC_DLL Meridian : public common::IdentifiedObject { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~Meridian() override; + //! @endcond + + PROJ_DLL const common::Angle &longitude() PROJ_CONST_DECL; + + // non-standard + PROJ_DLL static MeridianNNPtr create(const common::Angle &longitudeIn); + + //! @cond Doxygen_Suppress + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + //! @endcond + + protected: +#ifdef DOXYGEN_ENABLED + Angle angle_; +#endif + + PROJ_INTERNAL explicit Meridian(const common::Angle &longitudeIn); + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA + Meridian(const Meridian &other) = delete; + Meridian &operator=(const Meridian &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class CoordinateSystemAxis; +/** Shared pointer of CoordinateSystemAxis. */ +using CoordinateSystemAxisPtr = std::shared_ptr<CoordinateSystemAxis>; +/** Non-null shared pointer of CoordinateSystemAxis. */ +using CoordinateSystemAxisNNPtr = util::nn<CoordinateSystemAxisPtr>; + +/** \brief The definition of a coordinate system axis. + * + * \remark Implements CoordinateSystemAxis from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL CoordinateSystemAxis final + : public common::IdentifiedObject { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~CoordinateSystemAxis() override; + //! @endcond + + PROJ_DLL const std::string &abbreviation() PROJ_CONST_DECL; + PROJ_DLL const AxisDirection &direction() PROJ_CONST_DECL; + PROJ_DLL const common::UnitOfMeasure &unit() PROJ_CONST_DECL; + PROJ_DLL const util::optional<double> &minimumValue() PROJ_CONST_DECL; + PROJ_DLL const util::optional<double> &maximumValue() PROJ_CONST_DECL; + PROJ_DLL const MeridianPtr &meridian() PROJ_CONST_DECL; + + // Non-standard + PROJ_DLL static CoordinateSystemAxisNNPtr + create(const util::PropertyMap &properties, + const std::string &abbreviationIn, const AxisDirection &directionIn, + const common::UnitOfMeasure &unitIn, + const MeridianPtr &meridianIn = nullptr); + + PROJ_PRIVATE : + + //! @cond Doxygen_Suppress + PROJ_INTERNAL bool + _isEquivalentTo( + const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter, int order, + bool disableAbbrev) const; + + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + + PROJ_INTERNAL static std::string normalizeAxisName(const std::string &str); + + PROJ_INTERNAL static CoordinateSystemAxisNNPtr + createLAT_NORTH(const common::UnitOfMeasure &unit); + PROJ_INTERNAL static CoordinateSystemAxisNNPtr + createLONG_EAST(const common::UnitOfMeasure &unit); + + //! @endcond + + private: + PROJ_OPAQUE_PRIVATE_DATA + CoordinateSystemAxis(const CoordinateSystemAxis &other) = delete; + CoordinateSystemAxis &operator=(const CoordinateSystemAxis &other) = delete; + + PROJ_INTERNAL CoordinateSystemAxis(); + /* cppcheck-suppress unusedPrivateFunction */ + INLINED_MAKE_SHARED +}; + +// --------------------------------------------------------------------------- + +/** \brief Abstract class modelling a coordinate system (CS) + * + * A CS is the non-repeating sequence of coordinate system axes that spans a + * given coordinate space. A CS is derived from a set of mathematical rules for + * specifying how coordinates in a given space are to be assigned to points. + * The coordinate values in a coordinate tuple shall be recorded in the order + * in which the coordinate system axes associations are recorded. + * + * \remark Implements CoordinateSystem from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL CoordinateSystem : public common::IdentifiedObject { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~CoordinateSystem() override; + //! @endcond + + PROJ_DLL const std::vector<CoordinateSystemAxisNNPtr> & + axisList() PROJ_CONST_DECL; + + PROJ_PRIVATE : + + //! @cond Doxygen_Suppress + PROJ_INTERNAL void + _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + + PROJ_INTERNAL virtual std::string getWKT2Type(bool) const = 0; + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + //! @endcond + + protected: + PROJ_INTERNAL explicit CoordinateSystem( + const std::vector<CoordinateSystemAxisNNPtr> &axisIn); + + private: + PROJ_OPAQUE_PRIVATE_DATA + CoordinateSystem(const CoordinateSystem &other) = delete; + CoordinateSystem &operator=(const CoordinateSystem &other) = delete; +}; + +/** Shared pointer of CoordinateSystem. */ +using CoordinateSystemPtr = std::shared_ptr<CoordinateSystem>; +/** Non-null shared pointer of CoordinateSystem. */ +using CoordinateSystemNNPtr = util::nn<CoordinateSystemPtr>; + +// --------------------------------------------------------------------------- + +class SphericalCS; +/** Shared pointer of SphericalCS. */ +using SphericalCSPtr = std::shared_ptr<SphericalCS>; +/** Non-null shared pointer of SphericalCS. */ +using SphericalCSNNPtr = util::nn<SphericalCSPtr>; + +/** \brief A three-dimensional coordinate system in Euclidean space with one + * distance measured from the origin and two angular coordinates. + * + * Not to be confused with an ellipsoidal coordinate system based on an + * ellipsoid "degenerated" into a sphere. A SphericalCS shall have three + * axis associations. + * + * \remark Implements SphericalCS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL SphericalCS final : public CoordinateSystem { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~SphericalCS() override; + //! @endcond + + // non-standard + + PROJ_DLL static SphericalCSNNPtr + create(const util::PropertyMap &properties, + const CoordinateSystemAxisNNPtr &axis1, + const CoordinateSystemAxisNNPtr &axis2, + const CoordinateSystemAxisNNPtr &axis3); + + protected: + PROJ_INTERNAL explicit SphericalCS( + const std::vector<CoordinateSystemAxisNNPtr> &axisIn); + INLINED_MAKE_SHARED + + PROJ_INTERNAL std::string getWKT2Type(bool) const override { + return "spherical"; + } + + private: + SphericalCS(const SphericalCS &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class EllipsoidalCS; +/** Shared pointer of EllipsoidalCS. */ +using EllipsoidalCSPtr = std::shared_ptr<EllipsoidalCS>; +/** Non-null shared pointer of EllipsoidalCS. */ +using EllipsoidalCSNNPtr = util::nn<EllipsoidalCSPtr>; + +/** \brief A two- or three-dimensional coordinate system in which position is + * specified by geodetic latitude, geodetic longitude, and (in the + * three-dimensional case) ellipsoidal height. + * + * An EllipsoidalCS shall have two or three associations. + * + * \remark Implements EllipsoidalCS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL EllipsoidalCS final : public CoordinateSystem { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~EllipsoidalCS() override; + //! @endcond + + // non-standard + PROJ_DLL static EllipsoidalCSNNPtr + create(const util::PropertyMap &properties, + const CoordinateSystemAxisNNPtr &axis1, + const CoordinateSystemAxisNNPtr &axis2); + PROJ_DLL static EllipsoidalCSNNPtr + create(const util::PropertyMap &properties, + const CoordinateSystemAxisNNPtr &axis1, + const CoordinateSystemAxisNNPtr &axis2, + const CoordinateSystemAxisNNPtr &axis3); + PROJ_DLL static EllipsoidalCSNNPtr + createLatitudeLongitude(const common::UnitOfMeasure &unit); + PROJ_DLL static EllipsoidalCSNNPtr createLatitudeLongitudeEllipsoidalHeight( + const common::UnitOfMeasure &angularUnit, + const common::UnitOfMeasure &linearUnit); + PROJ_DLL static EllipsoidalCSNNPtr + createLongitudeLatitude(const common::UnitOfMeasure &unit); + + //! @cond Doxygen_Suppress + + /** \brief Typical axis order. */ + enum class AxisOrder { + /** Latitude(North), Longitude(East) */ + LAT_NORTH_LONG_EAST, + /** Latitude(North), Longitude(East), Height(up) */ + LAT_NORTH_LONG_EAST_HEIGHT_UP, + /** Longitude(East), Latitude(North) */ + LONG_EAST_LAT_NORTH, + /** Longitude(East), Latitude(North), Height(up) */ + LONG_EAST_LAT_NORTH_HEIGHT_UP, + /** Other axis order. */ + OTHER + }; + + PROJ_INTERNAL AxisOrder axisOrder() const; + //! @endcond + + protected: + PROJ_INTERNAL explicit EllipsoidalCS( + const std::vector<CoordinateSystemAxisNNPtr> &axisIn); + INLINED_MAKE_SHARED + + PROJ_INTERNAL std::string getWKT2Type(bool) const override { + return "ellipsoidal"; + } + + protected: + EllipsoidalCS(const EllipsoidalCS &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class VerticalCS; +/** Shared pointer of VerticalCS. */ +using VerticalCSPtr = std::shared_ptr<VerticalCS>; +/** Non-null shared pointer of VerticalCS. */ +using VerticalCSNNPtr = util::nn<VerticalCSPtr>; + +/** \brief A one-dimensional coordinate system used to record the heights or + * depths of points. + * + * Such a coordinate system is usually dependent on the Earth's gravity field. + * A VerticalCS shall have one axis association. + * + * \remark Implements VerticalCS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL VerticalCS final : public CoordinateSystem { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~VerticalCS() override; + //! @endcond + + PROJ_DLL static VerticalCSNNPtr + create(const util::PropertyMap &properties, + const CoordinateSystemAxisNNPtr &axis); + + PROJ_DLL static VerticalCSNNPtr + createGravityRelatedHeight(const common::UnitOfMeasure &unit); + + protected: + PROJ_INTERNAL explicit VerticalCS(const CoordinateSystemAxisNNPtr &axisIn); + INLINED_MAKE_SHARED + + PROJ_INTERNAL std::string getWKT2Type(bool) const override { + return "vertical"; + } + + private: + VerticalCS(const VerticalCS &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class CartesianCS; +/** Shared pointer of CartesianCS. */ +using CartesianCSPtr = std::shared_ptr<CartesianCS>; +/** Non-null shared pointer of CartesianCS. */ +using CartesianCSNNPtr = util::nn<CartesianCSPtr>; + +/** \brief A two- or three-dimensional coordinate system in Euclidean space + * with orthogonal straight axes. + * + * All axes shall have the same length unit. A CartesianCS shall have two or + * three axis associations; the number of associations shall equal the + * dimension of the CS. + * + * \remark Implements CartesianCS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL CartesianCS final : public CoordinateSystem { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~CartesianCS() override; + //! @endcond + + PROJ_DLL static CartesianCSNNPtr + create(const util::PropertyMap &properties, + const CoordinateSystemAxisNNPtr &axis1, + const CoordinateSystemAxisNNPtr &axis2); + PROJ_DLL static CartesianCSNNPtr + create(const util::PropertyMap &properties, + const CoordinateSystemAxisNNPtr &axis1, + const CoordinateSystemAxisNNPtr &axis2, + const CoordinateSystemAxisNNPtr &axis3); + PROJ_DLL static CartesianCSNNPtr + createEastingNorthing(const common::UnitOfMeasure &unit); + PROJ_DLL static CartesianCSNNPtr + createGeocentric(const common::UnitOfMeasure &unit); + + protected: + PROJ_INTERNAL explicit CartesianCS( + const std::vector<CoordinateSystemAxisNNPtr> &axisIn); + INLINED_MAKE_SHARED + + PROJ_INTERNAL std::string getWKT2Type(bool) const override { + return "Cartesian"; // uppercase is intended + } + + private: + CartesianCS(const CartesianCS &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class OrdinalCS; +/** Shared pointer of OrdinalCS. */ +using OrdinalCSPtr = std::shared_ptr<OrdinalCS>; +/** Non-null shared pointer of OrdinalCS. */ +using OrdinalCSNNPtr = util::nn<OrdinalCSPtr>; + +/** \brief n-dimensional coordinate system in which every axis uses integers. + * + * The number of associations shall equal the + * dimension of the CS. + * + * \remark Implements OrdinalCS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL OrdinalCS final : public CoordinateSystem { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~OrdinalCS() override; + //! @endcond + + PROJ_DLL static OrdinalCSNNPtr + create(const util::PropertyMap &properties, + const std::vector<CoordinateSystemAxisNNPtr> &axisIn); + + protected: + PROJ_INTERNAL explicit OrdinalCS( + const std::vector<CoordinateSystemAxisNNPtr> &axisIn); + INLINED_MAKE_SHARED + + PROJ_INTERNAL std::string getWKT2Type(bool) const override { + return "ordinal"; + } + + private: + OrdinalCS(const OrdinalCS &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class ParametricCS; +/** Shared pointer of ParametricCS. */ +using ParametricCSPtr = std::shared_ptr<ParametricCS>; +/** Non-null shared pointer of ParametricCS. */ +using ParametricCSNNPtr = util::nn<ParametricCSPtr>; + +/** \brief one-dimensional coordinate reference system which uses parameter + * values or functions that may vary monotonically with height. + * + * \remark Implements ParametricCS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL ParametricCS final : public CoordinateSystem { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~ParametricCS() override; + //! @endcond + + PROJ_DLL static ParametricCSNNPtr + create(const util::PropertyMap &properties, + const CoordinateSystemAxisNNPtr &axisIn); + + protected: + PROJ_INTERNAL explicit ParametricCS( + const std::vector<CoordinateSystemAxisNNPtr> &axisIn); + INLINED_MAKE_SHARED + + PROJ_INTERNAL std::string getWKT2Type(bool) const override { + return "parametric"; + } + + private: + ParametricCS(const ParametricCS &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class TemporalCS; +/** Shared pointer of TemporalCS. */ +using TemporalCSPtr = std::shared_ptr<TemporalCS>; +/** Non-null shared pointer of TemporalCS. */ +using TemporalCSNNPtr = util::nn<TemporalCSPtr>; + +/** \brief (Abstract class) A one-dimensional coordinate system used to record + * time. + * + * A TemporalCS shall have one axis association. + * + * \remark Implements TemporalCS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL TemporalCS : public CoordinateSystem { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~TemporalCS() override; + //! @endcond + + protected: + PROJ_INTERNAL explicit TemporalCS(const CoordinateSystemAxisNNPtr &axis); + INLINED_MAKE_SHARED + + PROJ_INTERNAL std::string + getWKT2Type(bool use2018Keywords) const override = 0; + + private: + TemporalCS(const TemporalCS &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class DateTimeTemporalCS; +/** Shared pointer of DateTimeTemporalCS. */ +using DateTimeTemporalCSPtr = std::shared_ptr<DateTimeTemporalCS>; +/** Non-null shared pointer of DateTimeTemporalCS. */ +using DateTimeTemporalCSNNPtr = util::nn<DateTimeTemporalCSPtr>; + +/** \brief A one-dimensional coordinate system used to record time in dateTime + * representation as defined in ISO 8601. + * + * A DateTimeTemporalCS shall have one axis association. It does not use + * axisUnitID; the temporal quantities are defined through the ISO 8601 + * representation. + * + * \remark Implements DateTimeTemporalCS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL DateTimeTemporalCS final : public TemporalCS { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~DateTimeTemporalCS() override; + //! @endcond + + PROJ_DLL static DateTimeTemporalCSNNPtr + create(const util::PropertyMap &properties, + const CoordinateSystemAxisNNPtr &axis); + + protected: + PROJ_INTERNAL explicit DateTimeTemporalCS( + const CoordinateSystemAxisNNPtr &axis); + INLINED_MAKE_SHARED + + PROJ_INTERNAL std::string getWKT2Type(bool use2018Keywords) const override; + + private: + DateTimeTemporalCS(const DateTimeTemporalCS &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class TemporalCountCS; +/** Shared pointer of TemporalCountCS. */ +using TemporalCountCSPtr = std::shared_ptr<TemporalCountCS>; +/** Non-null shared pointer of TemporalCountCS. */ +using TemporalCountCSNNPtr = util::nn<TemporalCountCSPtr>; + +/** \brief A one-dimensional coordinate system used to record time as an + * integer count. + * + * A TemporalCountCS shall have one axis association. + * + * \remark Implements TemporalCountCS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL TemporalCountCS final : public TemporalCS { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~TemporalCountCS() override; + //! @endcond + + PROJ_DLL static TemporalCountCSNNPtr + create(const util::PropertyMap &properties, + const CoordinateSystemAxisNNPtr &axis); + + protected: + PROJ_INTERNAL explicit TemporalCountCS( + const CoordinateSystemAxisNNPtr &axis); + INLINED_MAKE_SHARED + + PROJ_INTERNAL std::string getWKT2Type(bool use2018Keywords) const override; + + private: + TemporalCountCS(const TemporalCountCS &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class TemporalMeasureCS; +/** Shared pointer of TemporalMeasureCS. */ +using TemporalMeasureCSPtr = std::shared_ptr<TemporalMeasureCS>; +/** Non-null shared pointer of TemporalMeasureCS. */ +using TemporalMeasureCSNNPtr = util::nn<TemporalMeasureCSPtr>; + +/** \brief A one-dimensional coordinate system used to record a time as a + * real number. + * + * A TemporalMeasureCS shall have one axis association. + * + * \remark Implements TemporalMeasureCS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL TemporalMeasureCS final : public TemporalCS { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~TemporalMeasureCS() override; + //! @endcond + + PROJ_DLL static TemporalMeasureCSNNPtr + create(const util::PropertyMap &properties, + const CoordinateSystemAxisNNPtr &axis); + + protected: + PROJ_INTERNAL explicit TemporalMeasureCS( + const CoordinateSystemAxisNNPtr &axis); + INLINED_MAKE_SHARED + + PROJ_INTERNAL std::string getWKT2Type(bool use2018Keywords) const override; + + private: + TemporalMeasureCS(const TemporalMeasureCS &other) = delete; +}; + +} // namespace cs + +NS_PROJ_END + +#endif // CS_HH_INCLUDED diff --git a/include/proj/crs.hpp b/include/proj/crs.hpp new file mode 100644 index 00000000..252c90e3 --- /dev/null +++ b/include/proj/crs.hpp @@ -0,0 +1,1361 @@ +/****************************************************************************** + * + * Project: PROJ + * Purpose: ISO19111:2018 implementation + * Author: Even Rouault <even dot rouault at spatialys dot com> + * + ****************************************************************************** + * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ****************************************************************************/ + +#ifndef CRS_HH_INCLUDED +#define CRS_HH_INCLUDED + +#include <memory> +#include <string> +#include <vector> + +#include "common.hpp" +#include "coordinateoperation.hpp" +#include "coordinatesystem.hpp" +#include "datum.hpp" +#include "io.hpp" +#include "util.hpp" + +NS_PROJ_START + +/** osgeo.proj.crs namespace + + \brief CRS (coordinate reference system = coordinate system with a datum). +*/ +namespace crs { + +// --------------------------------------------------------------------------- + +class GeographicCRS; +/** Shared pointer of GeographicCRS */ +using GeographicCRSPtr = std::shared_ptr<GeographicCRS>; +/** Non-null shared pointer of GeographicCRS */ +using GeographicCRSNNPtr = util::nn<GeographicCRSPtr>; + +class VerticalCRS; +/** Shared pointer of VerticalCRS */ +using VerticalCRSPtr = std::shared_ptr<VerticalCRS>; +/** Non-null shared pointer of VerticalCRS */ +using VerticalCRSNNPtr = util::nn<VerticalCRSPtr>; + +class BoundCRS; +/** Shared pointer of BoundCRS */ +using BoundCRSPtr = std::shared_ptr<BoundCRS>; +/** Non-null shared pointer of BoundCRS */ +using BoundCRSNNPtr = util::nn<BoundCRSPtr>; + +// --------------------------------------------------------------------------- + +class CRS; +/** Shared pointer of CRS */ +using CRSPtr = std::shared_ptr<CRS>; +/** Non-null shared pointer of CRS */ +using CRSNNPtr = util::nn<CRSPtr>; + +/** \brief Abstract class modelling a coordinate reference system which is + * usually single but may be compound. + * + * \remark Implements CRS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL CRS : public common::ObjectUsage { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~CRS() override; + //! @endcond + + // Non-standard + + PROJ_DLL GeodeticCRSPtr extractGeodeticCRS() const; + PROJ_DLL GeographicCRSPtr extractGeographicCRS() const; + PROJ_DLL VerticalCRSPtr extractVerticalCRS() const; + PROJ_DLL CRSNNPtr createBoundCRSToWGS84IfPossible( + const io::DatabaseContextPtr &dbContext) const; + PROJ_DLL CRSNNPtr stripVerticalComponent() const; + + PROJ_DLL const BoundCRSPtr &canonicalBoundCRS() PROJ_CONST_DECL; + + PROJ_DLL std::list<std::pair<CRSNNPtr, int>> + identify(const io::AuthorityFactoryPtr &authorityFactory) const; + + PROJ_PRIVATE : + //! @cond Doxygen_Suppress + PROJ_INTERNAL const GeodeticCRS * + extractGeodeticCRSRaw() const; + + PROJ_FOR_TEST CRSNNPtr shallowClone() const; + + //! @endcond + + protected: + PROJ_INTERNAL CRS(); + PROJ_INTERNAL CRS(const CRS &other); + friend class BoundCRS; + PROJ_INTERNAL void setCanonicalBoundCRS(const BoundCRSNNPtr &boundCRS); + + PROJ_INTERNAL virtual CRSNNPtr _shallowClone() const = 0; + + PROJ_INTERNAL virtual std::list<std::pair<CRSNNPtr, int>> + _identify(const io::AuthorityFactoryPtr &authorityFactory) const; + + private: + PROJ_OPAQUE_PRIVATE_DATA +}; + +// --------------------------------------------------------------------------- + +/** \brief Abstract class modelling a coordinate reference system consisting of + * one Coordinate System and either one datum::Datum or one + * datum::DatumEnsemble. + * + * \remark Implements SingleCRS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL SingleCRS : public CRS { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~SingleCRS() override; + //! @endcond + + PROJ_DLL const datum::DatumPtr &datum() PROJ_CONST_DECL; + PROJ_DLL const datum::DatumEnsemblePtr &datumEnsemble() PROJ_CONST_DECL; + PROJ_DLL const cs::CoordinateSystemNNPtr & + coordinateSystem() PROJ_CONST_DECL; + + PROJ_PRIVATE : + //! @cond Doxygen_Suppress + PROJ_INTERNAL void + exportDatumOrDatumEnsembleToWkt(io::WKTFormatter *formatter) + const; // throw(io::FormattingException) + //! @endcond + + protected: + PROJ_INTERNAL SingleCRS(const datum::DatumPtr &datumIn, + const datum::DatumEnsemblePtr &datumEnsembleIn, + const cs::CoordinateSystemNNPtr &csIn); + PROJ_INTERNAL SingleCRS(const SingleCRS &other); + + PROJ_INTERNAL bool + baseIsEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const; + + private: + PROJ_OPAQUE_PRIVATE_DATA + SingleCRS &operator=(const SingleCRS &other) = delete; +}; + +/** Shared pointer of SingleCRS */ +using SingleCRSPtr = std::shared_ptr<SingleCRS>; +/** Non-null shared pointer of SingleCRS */ +using SingleCRSNNPtr = util::nn<SingleCRSPtr>; + +// --------------------------------------------------------------------------- + +class GeodeticCRS; +/** Shared pointer of GeodeticCRS */ +using GeodeticCRSPtr = std::shared_ptr<GeodeticCRS>; +/** Non-null shared pointer of GeodeticCRS */ +using GeodeticCRSNNPtr = util::nn<GeodeticCRSPtr>; + +/** \brief A coordinate reference system associated with a geodetic reference + * frame and a three-dimensional Cartesian or spherical coordinate system. + * + * If the geodetic reference frame is dynamic or if the geodetic CRS has an + * association to a velocity model then the geodetic CRS is dynamic, else it + * is static. + * + * \remark Implements GeodeticCRS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL GeodeticCRS : virtual public SingleCRS, + public io::IPROJStringExportable { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~GeodeticCRS() override; + //! @endcond + + PROJ_DLL const datum::GeodeticReferenceFramePtr &datum() PROJ_CONST_DECL; + + PROJ_DLL const datum::PrimeMeridianNNPtr &primeMeridian() PROJ_CONST_DECL; + PROJ_DLL const datum::EllipsoidNNPtr &ellipsoid() PROJ_CONST_DECL; + + // coordinateSystem() returns either a EllipsoidalCS, SphericalCS or + // CartesianCS + + PROJ_DLL const std::vector<operation::PointMotionOperationNNPtr> & + velocityModel() PROJ_CONST_DECL; + + // Non-standard + + PROJ_DLL bool isGeocentric() PROJ_CONST_DECL; + + PROJ_DLL static GeodeticCRSNNPtr + create(const util::PropertyMap &properties, + const datum::GeodeticReferenceFrameNNPtr &datum, + const cs::SphericalCSNNPtr &cs); + + PROJ_DLL static GeodeticCRSNNPtr + create(const util::PropertyMap &properties, + const datum::GeodeticReferenceFrameNNPtr &datum, + const cs::CartesianCSNNPtr &cs); + + PROJ_DLL static GeodeticCRSNNPtr + create(const util::PropertyMap &properties, + const datum::GeodeticReferenceFramePtr &datum, + const datum::DatumEnsemblePtr &datumEnsemble, + const cs::SphericalCSNNPtr &cs); + + PROJ_DLL static GeodeticCRSNNPtr + create(const util::PropertyMap &properties, + const datum::GeodeticReferenceFramePtr &datum, + const datum::DatumEnsemblePtr &datumEnsemble, + const cs::CartesianCSNNPtr &cs); + + PROJ_DLL static const GeodeticCRSNNPtr EPSG_4978; // WGS 84 Geocentric + + PROJ_DLL std::list<std::pair<GeodeticCRSNNPtr, int>> + identify(const io::AuthorityFactoryPtr &authorityFactory) const; + + PROJ_PRIVATE : + //! @cond Doxygen_Suppress + PROJ_INTERNAL void + addDatumInfoToPROJString(io::PROJStringFormatter *formatter) const; + + PROJ_INTERNAL void addGeocentricUnitConversionIntoPROJString( + io::PROJStringFormatter *formatter) const; + + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + + PROJ_INTERNAL void _exportToPROJString(io::PROJStringFormatter *formatter) + const override; // throw(FormattingException) + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + + //! @endcond + + protected: + PROJ_INTERNAL GeodeticCRS(const datum::GeodeticReferenceFramePtr &datumIn, + const datum::DatumEnsemblePtr &datumEnsembleIn, + const cs::EllipsoidalCSNNPtr &csIn); + PROJ_INTERNAL GeodeticCRS(const datum::GeodeticReferenceFramePtr &datumIn, + const datum::DatumEnsemblePtr &datumEnsembleIn, + const cs::SphericalCSNNPtr &csIn); + PROJ_INTERNAL GeodeticCRS(const datum::GeodeticReferenceFramePtr &datumIn, + const datum::DatumEnsemblePtr &datumEnsembleIn, + const cs::CartesianCSNNPtr &csIn); + PROJ_INTERNAL GeodeticCRS(const GeodeticCRS &other); + + PROJ_INTERNAL static GeodeticCRSNNPtr createEPSG_4978(); + + PROJ_INTERNAL CRSNNPtr _shallowClone() const override; + + PROJ_INTERNAL std::list<std::pair<CRSNNPtr, int>> + _identify(const io::AuthorityFactoryPtr &authorityFactory) const override; + + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA + + GeodeticCRS &operator=(const GeodeticCRS &other) = delete; +}; + +// --------------------------------------------------------------------------- + +/** \brief A coordinate reference system associated with a geodetic reference + * frame and a two- or three-dimensional ellipsoidal coordinate system. + * + * If the geodetic reference frame is dynamic or if the geographic CRS has an + * association to a velocity model then the geodetic CRS is dynamic, else it is + * static. + * + * \remark Implements GeographicCRS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL GeographicCRS : public GeodeticCRS { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~GeographicCRS() override; + //! @endcond + + PROJ_DLL const cs::EllipsoidalCSNNPtr &coordinateSystem() PROJ_CONST_DECL; + + // Non-standard + PROJ_DLL static GeographicCRSNNPtr + create(const util::PropertyMap &properties, + const datum::GeodeticReferenceFrameNNPtr &datum, + const cs::EllipsoidalCSNNPtr &cs); + PROJ_DLL static GeographicCRSNNPtr + create(const util::PropertyMap &properties, + const datum::GeodeticReferenceFramePtr &datum, + const datum::DatumEnsemblePtr &datumEnsemble, + const cs::EllipsoidalCSNNPtr &cs); + + PROJ_DLL static const GeographicCRSNNPtr EPSG_4267; // NAD27 + PROJ_DLL static const GeographicCRSNNPtr EPSG_4269; // NAD83 + PROJ_DLL static const GeographicCRSNNPtr EPSG_4326; // WGS 84 2D + PROJ_DLL static const GeographicCRSNNPtr OGC_CRS84; // CRS84 (Long, Lat) + PROJ_DLL static const GeographicCRSNNPtr EPSG_4807; // NTF Paris + PROJ_DLL static const GeographicCRSNNPtr EPSG_4979; // WGS 84 3D + + PROJ_PRIVATE : + //! @cond Doxygen_Suppress + PROJ_INTERNAL void + addAngularUnitConvertAndAxisSwap( + io::PROJStringFormatter *formatter) const; + + PROJ_INTERNAL void _exportToPROJString(io::PROJStringFormatter *formatter) + const override; // throw(FormattingException) + + PROJ_DLL bool + is2DPartOf3D(util::nn<const GeographicCRS *> other) PROJ_CONST_DECL; + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + + //! @endcond + + protected: + PROJ_INTERNAL GeographicCRS(const datum::GeodeticReferenceFramePtr &datumIn, + const datum::DatumEnsemblePtr &datumEnsembleIn, + const cs::EllipsoidalCSNNPtr &csIn); + PROJ_INTERNAL GeographicCRS(const GeographicCRS &other); + + PROJ_INTERNAL static GeographicCRSNNPtr createEPSG_4267(); + PROJ_INTERNAL static GeographicCRSNNPtr createEPSG_4269(); + PROJ_INTERNAL static GeographicCRSNNPtr createEPSG_4326(); + PROJ_INTERNAL static GeographicCRSNNPtr createOGC_CRS84(); + PROJ_INTERNAL static GeographicCRSNNPtr createEPSG_4807(); + PROJ_INTERNAL static GeographicCRSNNPtr createEPSG_4979(); + + PROJ_INTERNAL CRSNNPtr _shallowClone() const override; + + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA + + GeographicCRS &operator=(const GeographicCRS &other) = delete; +}; + +// --------------------------------------------------------------------------- + +/** \brief A coordinate reference system having a vertical reference frame and + * a one-dimensional vertical coordinate system used for recording + * gravity-related heights or depths. + * + * Vertical CRSs make use of the direction of gravity to define the concept of + * height or depth, but the relationship with gravity may not be + * straightforward. If the vertical reference frame is dynamic or if the + * vertical CRS has an association to a velocity model then the CRS is dynamic, + * else it is static. + * + * \note Ellipsoidal heights cannot be captured in a vertical coordinate + * reference system. They exist only as an inseparable part of a 3D coordinate + * tuple defined in a geographic 3D coordinate reference system. + * + * \remark Implements VerticalCRS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL VerticalCRS : virtual public SingleCRS, + public io::IPROJStringExportable { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~VerticalCRS() override; + //! @endcond + + PROJ_DLL const datum::VerticalReferenceFramePtr datum() const; + PROJ_DLL const cs::VerticalCSNNPtr coordinateSystem() const; + PROJ_DLL const std::vector<operation::TransformationNNPtr> & + geoidModel() PROJ_CONST_DECL; + PROJ_DLL const std::vector<operation::PointMotionOperationNNPtr> & + velocityModel() PROJ_CONST_DECL; + + PROJ_DLL static VerticalCRSNNPtr + create(const util::PropertyMap &properties, + const datum::VerticalReferenceFrameNNPtr &datumIn, + const cs::VerticalCSNNPtr &csIn); + + PROJ_DLL static VerticalCRSNNPtr + create(const util::PropertyMap &properties, + const datum::VerticalReferenceFramePtr &datumIn, + const datum::DatumEnsemblePtr &datumEnsembleIn, + const cs::VerticalCSNNPtr &csIn); + + PROJ_DLL std::list<std::pair<VerticalCRSNNPtr, int>> + identify(const io::AuthorityFactoryPtr &authorityFactory) const; + + PROJ_PRIVATE : + //! @cond Doxygen_Suppress + PROJ_INTERNAL void + addLinearUnitConvert(io::PROJStringFormatter *formatter) const; + + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + + //! @endcond + + protected: + PROJ_INTERNAL VerticalCRS(const datum::VerticalReferenceFramePtr &datumIn, + const datum::DatumEnsemblePtr &datumEnsembleIn, + const cs::VerticalCSNNPtr &csIn); + PROJ_INTERNAL VerticalCRS(const VerticalCRS &other); + + PROJ_INTERNAL void _exportToPROJString(io::PROJStringFormatter *formatter) + const override; // throw(FormattingException) + + PROJ_INTERNAL std::list<std::pair<CRSNNPtr, int>> + _identify(const io::AuthorityFactoryPtr &authorityFactory) const override; + + INLINED_MAKE_SHARED + + PROJ_INTERNAL CRSNNPtr _shallowClone() const override; + + private: + PROJ_OPAQUE_PRIVATE_DATA + VerticalCRS &operator=(const VerticalCRS &other) = delete; +}; + +// --------------------------------------------------------------------------- + +/** \brief Abstract class modelling a single coordinate reference system that + * is defined through the application of a specified coordinate conversion to + * the definition of a previously established single coordinate reference + * system referred to as the base CRS. + * + * A derived coordinate reference system inherits its datum (or datum ensemble) + * from its base CRS. The coordinate conversion between the base and derived + * coordinate reference system is implemented using the parameters and + * formula(s) specified in the definition of the coordinate conversion. + * + * \remark Implements DerivedCRS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL DerivedCRS : virtual public SingleCRS { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~DerivedCRS() override; + //! @endcond + + PROJ_DLL const SingleCRSNNPtr &baseCRS() PROJ_CONST_DECL; + PROJ_DLL const operation::ConversionNNPtr derivingConversion() const; + + PROJ_PRIVATE : + //! @cond Doxygen_Suppress + const operation::ConversionNNPtr & + derivingConversionRef() PROJ_CONST_DECL; + //! @endcond + + protected: + PROJ_INTERNAL + DerivedCRS(const SingleCRSNNPtr &baseCRSIn, + const operation::ConversionNNPtr &derivingConversionIn, + const cs::CoordinateSystemNNPtr &cs); + PROJ_INTERNAL DerivedCRS(const DerivedCRS &other); + + PROJ_INTERNAL void setDerivingConversionCRS(); + + PROJ_INTERNAL void baseExportToPROJString( + io::PROJStringFormatter *formatter) const; // throw(FormattingException) + + PROJ_INTERNAL void baseExportToWKT( + io::WKTFormatter *&formatter, const std::string &keyword, + const std::string &baseKeyword) const; // throw(FormattingException) + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + + private: + PROJ_OPAQUE_PRIVATE_DATA + DerivedCRS &operator=(const DerivedCRS &other) = delete; +}; + +/** Shared pointer of DerivedCRS */ +using DerivedCRSPtr = std::shared_ptr<DerivedCRS>; +/** Non-null shared pointer of DerivedCRS */ +using DerivedCRSNNPtr = util::nn<DerivedCRSPtr>; + +// --------------------------------------------------------------------------- + +class ProjectedCRS; +/** Shared pointer of ProjectedCRS */ +using ProjectedCRSPtr = std::shared_ptr<ProjectedCRS>; +/** Non-null shared pointer of ProjectedCRS */ +using ProjectedCRSNNPtr = util::nn<ProjectedCRSPtr>; + +/** \brief A derived coordinate reference system which has a geodetic + * (usually geographic) coordinate reference system as its base CRS, thereby + * inheriting a geodetic reference frame, and is converted using a map + * projection. + * + * It has a Cartesian coordinate system, usually two-dimensional but may be + * three-dimensional; in the 3D case the base geographic CRSs ellipsoidal + * height is passed through unchanged and forms the vertical axis of the + * projected CRS's Cartesian coordinate system. + * + * \remark Implements ProjectedCRS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL ProjectedCRS final : public DerivedCRS, + public io::IPROJStringExportable { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~ProjectedCRS() override; + //! @endcond + + PROJ_DLL const GeodeticCRSNNPtr &baseCRS() PROJ_CONST_DECL; + PROJ_DLL const cs::CartesianCSNNPtr &coordinateSystem() PROJ_CONST_DECL; + + PROJ_DLL static ProjectedCRSNNPtr + create(const util::PropertyMap &properties, + const GeodeticCRSNNPtr &baseCRSIn, + const operation::ConversionNNPtr &derivingConversionIn, + const cs::CartesianCSNNPtr &csIn); + + PROJ_DLL std::list<std::pair<ProjectedCRSNNPtr, int>> + identify(const io::AuthorityFactoryPtr &authorityFactory) const; + + PROJ_PRIVATE : + //! @cond Doxygen_Suppress + PROJ_INTERNAL void + addUnitConvertAndAxisSwap(io::PROJStringFormatter *formatter, + bool axisSpecFound) const; + + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + + //! @endcond + + protected: + PROJ_INTERNAL + ProjectedCRS(const GeodeticCRSNNPtr &baseCRSIn, + const operation::ConversionNNPtr &derivingConversionIn, + const cs::CartesianCSNNPtr &csIn); + PROJ_INTERNAL ProjectedCRS(const ProjectedCRS &other); + + PROJ_INTERNAL void _exportToPROJString(io::PROJStringFormatter *formatter) + const override; // throw(FormattingException) + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + + PROJ_INTERNAL std::list<std::pair<CRSNNPtr, int>> + _identify(const io::AuthorityFactoryPtr &authorityFactory) const override; + + INLINED_MAKE_SHARED + + PROJ_INTERNAL CRSNNPtr _shallowClone() const override; + + private: + PROJ_OPAQUE_PRIVATE_DATA + ProjectedCRS &operator=(const ProjectedCRS &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class TemporalCRS; +/** Shared pointer of TemporalCRS */ +using TemporalCRSPtr = std::shared_ptr<TemporalCRS>; +/** Non-null shared pointer of TemporalCRS */ +using TemporalCRSNNPtr = util::nn<TemporalCRSPtr>; + +/** \brief A coordinate reference system associated with a temporal datum and a + * one-dimensional temporal coordinate system. + * + * \remark Implements TemporalCRS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL TemporalCRS : virtual public SingleCRS { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~TemporalCRS() override; + //! @endcond + + PROJ_DLL const datum::TemporalDatumNNPtr datum() const; + + PROJ_DLL const cs::TemporalCSNNPtr coordinateSystem() const; + + PROJ_DLL static TemporalCRSNNPtr + create(const util::PropertyMap &properties, + const datum::TemporalDatumNNPtr &datumIn, + const cs::TemporalCSNNPtr &csIn); + + //! @cond Doxygen_Suppress + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + //! @endcond + + protected: + PROJ_INTERNAL TemporalCRS(const datum::TemporalDatumNNPtr &datumIn, + const cs::TemporalCSNNPtr &csIn); + PROJ_INTERNAL TemporalCRS(const TemporalCRS &other); + + INLINED_MAKE_SHARED + + PROJ_INTERNAL CRSNNPtr _shallowClone() const override; + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + + private: + PROJ_OPAQUE_PRIVATE_DATA + TemporalCRS &operator=(const TemporalCRS &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class EngineeringCRS; +/** Shared pointer of EngineeringCRS */ +using EngineeringCRSPtr = std::shared_ptr<EngineeringCRS>; +/** Non-null shared pointer of EngineeringCRS */ +using EngineeringCRSNNPtr = util::nn<EngineeringCRSPtr>; + +/** \brief Contextually local coordinate reference system associated with an + * engineering datum. + * + * It is applied either to activities on or near the surface of the Earth + * without geodetic corrections, or on moving platforms such as road vehicles, + * vessels, aircraft or spacecraft, or as the internal CRS of an image. + * + * In \ref WKT2, it maps to a ENGINEERINGCRS / ENGCRS keyword. In \ref WKT1, + * it maps to a LOCAL_CS keyword. + * + * \remark Implements EngineeringCRS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL EngineeringCRS : virtual public SingleCRS { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~EngineeringCRS() override; + //! @endcond + + PROJ_DLL const datum::EngineeringDatumNNPtr datum() const; + + PROJ_DLL static EngineeringCRSNNPtr + create(const util::PropertyMap &properties, + const datum::EngineeringDatumNNPtr &datumIn, + const cs::CoordinateSystemNNPtr &csIn); + + //! @cond Doxygen_Suppress + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + //! @endcond + + protected: + PROJ_INTERNAL EngineeringCRS(const datum::EngineeringDatumNNPtr &datumIn, + const cs::CoordinateSystemNNPtr &csIn); + PROJ_INTERNAL EngineeringCRS(const EngineeringCRS &other); + + PROJ_INTERNAL CRSNNPtr _shallowClone() const override; + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA + EngineeringCRS &operator=(const EngineeringCRS &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class ParametricCRS; +/** Shared pointer of ParametricCRS */ +using ParametricCRSPtr = std::shared_ptr<ParametricCRS>; +/** Non-null shared pointer of ParametricCRS */ +using ParametricCRSNNPtr = util::nn<ParametricCRSPtr>; + +/** \brief Contextually local coordinate reference system associated with an + * engineering datum. + * + * This is applied either to activities on or near the surface of the Earth + * without geodetic corrections, or on moving platforms such as road vehicles + * vessels, aircraft or spacecraft, or as the internal CRS of an image. + * + * \remark Implements ParametricCRS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL ParametricCRS : virtual public SingleCRS { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~ParametricCRS() override; + //! @endcond + + PROJ_DLL const datum::ParametricDatumNNPtr datum() const; + + PROJ_DLL const cs::ParametricCSNNPtr coordinateSystem() const; + + PROJ_DLL static ParametricCRSNNPtr + create(const util::PropertyMap &properties, + const datum::ParametricDatumNNPtr &datumIn, + const cs::ParametricCSNNPtr &csIn); + + //! @cond Doxygen_Suppress + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + //! @endcond + + protected: + PROJ_INTERNAL ParametricCRS(const datum::ParametricDatumNNPtr &datumIn, + const cs::ParametricCSNNPtr &csIn); + PROJ_INTERNAL ParametricCRS(const ParametricCRS &other); + + PROJ_INTERNAL CRSNNPtr _shallowClone() const override; + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA + ParametricCRS &operator=(const ParametricCRS &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class CompoundCRS; +/** Shared pointer of CompoundCRS */ +using CompoundCRSPtr = std::shared_ptr<CompoundCRS>; +/** Non-null shared pointer of CompoundCRS */ +using CompoundCRSNNPtr = util::nn<CompoundCRSPtr>; + +/** \brief A coordinate reference system describing the position of points + * through two or more independent single coordinate reference systems. + * + * \note Two coordinate reference systems are independent of each other + * if coordinate values in one cannot be converted or transformed into + * coordinate values in the other. + * + * \note As a departure to \ref ISO_19111_2018, we allow to build a CompoundCRS + * from CRS objects, whereas ISO19111:2018 restricts the components to + * SingleCRS. + * + * \remark Implements CompoundCRS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL CompoundCRS final : public CRS, + public io::IPROJStringExportable { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~CompoundCRS() override; + //! @endcond + + PROJ_DLL const std::vector<CRSNNPtr> & + componentReferenceSystems() PROJ_CONST_DECL; + + PROJ_DLL std::list<std::pair<CompoundCRSNNPtr, int>> + identify(const io::AuthorityFactoryPtr &authorityFactory) const; + + //! @cond Doxygen_Suppress + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + //! @endcond + + PROJ_DLL static CompoundCRSNNPtr + create(const util::PropertyMap &properties, + const std::vector<CRSNNPtr> &components); + + protected: + // relaxed: standard say SingleCRSNNPtr + PROJ_INTERNAL explicit CompoundCRS(const std::vector<CRSNNPtr> &components); + PROJ_INTERNAL CompoundCRS(const CompoundCRS &other); + + PROJ_INTERNAL void _exportToPROJString(io::PROJStringFormatter *formatter) + const override; // throw(FormattingException) + + PROJ_INTERNAL CRSNNPtr _shallowClone() const override; + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + + PROJ_INTERNAL std::list<std::pair<CRSNNPtr, int>> + _identify(const io::AuthorityFactoryPtr &authorityFactory) const override; + + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA + CompoundCRS &operator=(const CompoundCRS &other) = delete; +}; + +// --------------------------------------------------------------------------- + +/** \brief A coordinate reference system with an associated transformation to + * a target/hub CRS. + * + * The definition of a CRS is not dependent upon any relationship to an + * independent CRS. However in an implementation that merges datasets + * referenced to differing CRSs, it is sometimes useful to associate the + * definition of the transformation that has been used with the CRS definition. + * This facilitates the interrelationship of CRS by concatenating + * transformations via a common or hub CRS. This is sometimes referred to as + * "early-binding". \ref WKT2 permits the association of an abridged coordinate + * transformation description with a coordinate reference system description in + * a single text string. In a BoundCRS, the abridged coordinate transformation + * is applied to the source CRS with the target CRS being the common or hub + * system. + * + * Coordinates referring to a BoundCRS are expressed into its source/base CRS. + * + * This abstraction can for example model the concept of TOWGS84 datum shift + * present in \ref WKT1. + * + * \note Contrary to other CRS classes of this package, there is no + * \ref ISO_19111_2018 modelling of a BoundCRS. + * + * \remark Implements BoundCRS from \ref WKT2 + */ +class PROJ_GCC_DLL BoundCRS final : public CRS, + public io::IPROJStringExportable { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~BoundCRS() override; + //! @endcond + + PROJ_DLL const CRSNNPtr &baseCRS() PROJ_CONST_DECL; + PROJ_DLL CRSNNPtr baseCRSWithCanonicalBoundCRS() const; + + PROJ_DLL const CRSNNPtr &hubCRS() PROJ_CONST_DECL; + PROJ_DLL const operation::TransformationNNPtr & + transformation() PROJ_CONST_DECL; + + //! @cond Doxygen_Suppress + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + //! @endcond + + PROJ_DLL static BoundCRSNNPtr + create(const CRSNNPtr &baseCRSIn, const CRSNNPtr &hubCRSIn, + const operation::TransformationNNPtr &transformationIn); + + PROJ_DLL static BoundCRSNNPtr + createFromTOWGS84(const CRSNNPtr &baseCRSIn, + const std::vector<double> &TOWGS84Parameters); + + PROJ_DLL static BoundCRSNNPtr + createFromNadgrids(const CRSNNPtr &baseCRSIn, const std::string &filename); + + protected: + PROJ_INTERNAL + BoundCRS(const CRSNNPtr &baseCRSIn, const CRSNNPtr &hubCRSIn, + const operation::TransformationNNPtr &transformationIn); + PROJ_INTERNAL BoundCRS(const BoundCRS &other); + + PROJ_INTERNAL CRSNNPtr _shallowClone() const override; + + PROJ_INTERNAL void _exportToPROJString(io::PROJStringFormatter *formatter) + const override; // throw(FormattingException) + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + + PROJ_INTERNAL BoundCRSNNPtr shallowCloneAsBoundCRS() const; + PROJ_INTERNAL bool isTOWGS84Compatible() const; + PROJ_INTERNAL std::string getHDatumPROJ4GRIDS() const; + PROJ_INTERNAL std::string getVDatumPROJ4GRIDS() const; + + PROJ_INTERNAL std::list<std::pair<CRSNNPtr, int>> + _identify(const io::AuthorityFactoryPtr &authorityFactory) const override; + + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA + BoundCRS &operator=(const BoundCRS &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class DerivedGeodeticCRS; +/** Shared pointer of DerivedGeodeticCRS */ +using DerivedGeodeticCRSPtr = std::shared_ptr<DerivedGeodeticCRS>; +/** Non-null shared pointer of DerivedGeodeticCRS */ +using DerivedGeodeticCRSNNPtr = util::nn<DerivedGeodeticCRSPtr>; + +/** \brief A derived coordinate reference system which has either a geodetic + * or a geographic coordinate reference system as its base CRS, thereby + * inheriting a geodetic reference frame, and associated with a 3D Cartesian + * or spherical coordinate system. + * + * \remark Implements DerivedGeodeticCRS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL DerivedGeodeticCRS final : public GeodeticCRS, + public DerivedCRS { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~DerivedGeodeticCRS() override; + //! @endcond + + PROJ_DLL const GeodeticCRSNNPtr baseCRS() const; + + PROJ_DLL static DerivedGeodeticCRSNNPtr + create(const util::PropertyMap &properties, + const GeodeticCRSNNPtr &baseCRSIn, + const operation::ConversionNNPtr &derivingConversionIn, + const cs::CartesianCSNNPtr &csIn); + + PROJ_DLL static DerivedGeodeticCRSNNPtr + create(const util::PropertyMap &properties, + const GeodeticCRSNNPtr &baseCRSIn, + const operation::ConversionNNPtr &derivingConversionIn, + const cs::SphericalCSNNPtr &csIn); + + //! @cond Doxygen_Suppress + void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + //! @endcond + + protected: + PROJ_INTERNAL + DerivedGeodeticCRS(const GeodeticCRSNNPtr &baseCRSIn, + const operation::ConversionNNPtr &derivingConversionIn, + const cs::CartesianCSNNPtr &csIn); + PROJ_INTERNAL + DerivedGeodeticCRS(const GeodeticCRSNNPtr &baseCRSIn, + const operation::ConversionNNPtr &derivingConversionIn, + const cs::SphericalCSNNPtr &csIn); + PROJ_INTERNAL DerivedGeodeticCRS(const DerivedGeodeticCRS &other); + + PROJ_INTERNAL void _exportToPROJString(io::PROJStringFormatter *formatter) + const override; // throw(FormattingException) + + PROJ_INTERNAL CRSNNPtr _shallowClone() const override; + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + + PROJ_INTERNAL std::list<std::pair<CRSNNPtr, int>> + _identify(const io::AuthorityFactoryPtr &authorityFactory) const override; + + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA + DerivedGeodeticCRS &operator=(const DerivedGeodeticCRS &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class DerivedGeographicCRS; +/** Shared pointer of DerivedGeographicCRS */ +using DerivedGeographicCRSPtr = std::shared_ptr<DerivedGeographicCRS>; +/** Non-null shared pointer of DerivedGeographicCRS */ +using DerivedGeographicCRSNNPtr = util::nn<DerivedGeographicCRSPtr>; + +/** \brief A derived coordinate reference system which has either a geodetic or + * a geographic coordinate reference system as its base CRS, thereby inheriting + * a geodetic reference frame, and an ellipsoidal coordinate system. + * + * A derived geographic CRS can be based on a geodetic CRS only if that + * geodetic CRS definition includes an ellipsoid. + * + * \remark Implements DerivedGeographicCRS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL DerivedGeographicCRS final : public GeographicCRS, + public DerivedCRS { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~DerivedGeographicCRS() override; + //! @endcond + + PROJ_DLL const GeodeticCRSNNPtr baseCRS() const; + + PROJ_DLL static DerivedGeographicCRSNNPtr + create(const util::PropertyMap &properties, + const GeodeticCRSNNPtr &baseCRSIn, + const operation::ConversionNNPtr &derivingConversionIn, + const cs::EllipsoidalCSNNPtr &csIn); + + //! @cond Doxygen_Suppress + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + //! @endcond + + protected: + PROJ_INTERNAL + DerivedGeographicCRS(const GeodeticCRSNNPtr &baseCRSIn, + const operation::ConversionNNPtr &derivingConversionIn, + const cs::EllipsoidalCSNNPtr &csIn); + PROJ_INTERNAL DerivedGeographicCRS(const DerivedGeographicCRS &other); + + PROJ_INTERNAL void _exportToPROJString(io::PROJStringFormatter *formatter) + const override; // throw(FormattingException) + + PROJ_INTERNAL CRSNNPtr _shallowClone() const override; + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + + PROJ_INTERNAL std::list<std::pair<CRSNNPtr, int>> + _identify(const io::AuthorityFactoryPtr &authorityFactory) const override; + + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA + DerivedGeographicCRS &operator=(const DerivedGeographicCRS &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class DerivedProjectedCRS; +/** Shared pointer of DerivedProjectedCRS */ +using DerivedProjectedCRSPtr = std::shared_ptr<DerivedProjectedCRS>; +/** Non-null shared pointer of DerivedProjectedCRS */ +using DerivedProjectedCRSNNPtr = util::nn<DerivedProjectedCRSPtr>; + +/** \brief A derived coordinate reference system which has a projected + * coordinate reference system as its base CRS, thereby inheriting a geodetic + * reference frame, but also inheriting the distortion characteristics of the + * base projected CRS. + * + * A DerivedProjectedCRS is not a ProjectedCRS. + * + * \remark Implements DerivedProjectedCRS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL DerivedProjectedCRS final + : public DerivedCRS, + public io::IPROJStringExportable { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~DerivedProjectedCRS() override; + //! @endcond + + PROJ_DLL const ProjectedCRSNNPtr baseCRS() const; + + PROJ_DLL static DerivedProjectedCRSNNPtr + create(const util::PropertyMap &properties, + const ProjectedCRSNNPtr &baseCRSIn, + const operation::ConversionNNPtr &derivingConversionIn, + const cs::CoordinateSystemNNPtr &csIn); + + //! @cond Doxygen_Suppress + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + //! @endcond + + protected: + PROJ_INTERNAL + DerivedProjectedCRS(const ProjectedCRSNNPtr &baseCRSIn, + const operation::ConversionNNPtr &derivingConversionIn, + const cs::CoordinateSystemNNPtr &csIn); + PROJ_INTERNAL DerivedProjectedCRS(const DerivedProjectedCRS &other); + + PROJ_INTERNAL void _exportToPROJString(io::PROJStringFormatter *formatter) + const override; // throw(FormattingException) + + PROJ_INTERNAL CRSNNPtr _shallowClone() const override; + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA + DerivedProjectedCRS &operator=(const DerivedProjectedCRS &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class DerivedVerticalCRS; +/** Shared pointer of DerivedVerticalCRS */ +using DerivedVerticalCRSPtr = std::shared_ptr<DerivedVerticalCRS>; +/** Non-null shared pointer of DerivedVerticalCRS */ +using DerivedVerticalCRSNNPtr = util::nn<DerivedVerticalCRSPtr>; + +/** \brief A derived coordinate reference system which has a vertical + * coordinate reference system as its base CRS, thereby inheriting a vertical + * reference frame, and a vertical coordinate system. + * + * \remark Implements DerivedVerticalCRS from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL DerivedVerticalCRS final : public VerticalCRS, + public DerivedCRS { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~DerivedVerticalCRS() override; + //! @endcond + + PROJ_DLL const VerticalCRSNNPtr baseCRS() const; + + PROJ_DLL static DerivedVerticalCRSNNPtr + create(const util::PropertyMap &properties, + const VerticalCRSNNPtr &baseCRSIn, + const operation::ConversionNNPtr &derivingConversionIn, + const cs::VerticalCSNNPtr &csIn); + + //! @cond Doxygen_Suppress + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + //! @endcond + + protected: + PROJ_INTERNAL + DerivedVerticalCRS(const VerticalCRSNNPtr &baseCRSIn, + const operation::ConversionNNPtr &derivingConversionIn, + const cs::VerticalCSNNPtr &csIn); + PROJ_INTERNAL DerivedVerticalCRS(const DerivedVerticalCRS &other); + + PROJ_INTERNAL void _exportToPROJString(io::PROJStringFormatter *formatter) + const override; // throw(FormattingException) + + PROJ_INTERNAL CRSNNPtr _shallowClone() const override; + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + + PROJ_INTERNAL std::list<std::pair<CRSNNPtr, int>> + _identify(const io::AuthorityFactoryPtr &authorityFactory) const override; + + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA + DerivedVerticalCRS &operator=(const DerivedVerticalCRS &other) = delete; +}; + +// --------------------------------------------------------------------------- + +/** \brief Template representing a derived coordinate reference system. + */ +template <class DerivedCRSTraits> +class PROJ_GCC_DLL DerivedCRSTemplate final : public DerivedCRSTraits::BaseType, + public DerivedCRS { + protected: + /** Base type */ + typedef typename DerivedCRSTraits::BaseType BaseType; + /** CSType */ + typedef typename DerivedCRSTraits::CSType CSType; + + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~DerivedCRSTemplate() override; + //! @endcond + + /** Non-null shared pointer of DerivedCRSTemplate */ + typedef typename util::nn<std::shared_ptr<DerivedCRSTemplate>> NNPtr; + /** Non-null shared pointer of BaseType */ + typedef util::nn<std::shared_ptr<BaseType>> BaseNNPtr; + /** Non-null shared pointer of CSType */ + typedef util::nn<std::shared_ptr<CSType>> CSNNPtr; + + /** \brief Return the base CRS of a DerivedCRSTemplate. + * + * @return the base CRS. + */ + PROJ_DLL const BaseNNPtr baseCRS() const; + + /** \brief Instanciate a DerivedCRSTemplate from a base CRS, a deriving + * conversion and a cs::CoordinateSystem. + * + * @param properties See \ref general_properties. + * At minimum the name should be defined. + * @param baseCRSIn base CRS. + * @param derivingConversionIn the deriving conversion from the base CRS to + * this + * CRS. + * @param csIn the coordinate system. + * @return new DerivedCRSTemplate. + */ + PROJ_DLL static NNPtr + create(const util::PropertyMap &properties, const BaseNNPtr &baseCRSIn, + const operation::ConversionNNPtr &derivingConversionIn, + const CSNNPtr &csIn); + + //! @cond Doxygen_Suppress + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + //! @endcond + + protected: + PROJ_INTERNAL + DerivedCRSTemplate(const BaseNNPtr &baseCRSIn, + const operation::ConversionNNPtr &derivingConversionIn, + const CSNNPtr &csIn); + PROJ_INTERNAL DerivedCRSTemplate(const DerivedCRSTemplate &other); + + PROJ_INTERNAL CRSNNPtr _shallowClone() const override; + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + + INLINED_MAKE_SHARED + + private: + struct PROJ_INTERNAL Private; + std::unique_ptr<Private> d; + + DerivedCRSTemplate &operator=(const DerivedCRSTemplate &other) = delete; +}; + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +struct PROJ_GCC_DLL DerivedEngineeringCRSTraits { + typedef EngineeringCRS BaseType; + typedef cs::CoordinateSystem CSType; + // old x86_64-w64-mingw32-g++ has issues with static variables. use method + // instead + inline static const std::string &CRSName(); + inline static const std::string &WKTKeyword(); + inline static const std::string &WKTBaseKeyword(); + static const bool wkt2_2018_only = true; +}; +//! @endcond + +/** \brief A derived coordinate reference system which has an engineering + * coordinate reference system as its base CRS, thereby inheriting an + * engineering datum, and is associated with one of the coordinate system + * types for an EngineeringCRS + * + * \remark Implements DerivedEngineeringCRS from \ref ISO_19111_2018 + */ +#ifdef DOXYGEN_ENABLED +class DerivedEngineeringCRS + : public DerivedCRSTemplate<DerivedEngineeringCRSTraits> {}; +#else +using DerivedEngineeringCRS = DerivedCRSTemplate<DerivedEngineeringCRSTraits>; +#endif + +#ifndef DO_NOT_DEFINE_EXTERN_DERIVED_CRS_TEMPLATE +extern template class DerivedCRSTemplate<DerivedEngineeringCRSTraits>; +#endif + +/** Shared pointer of DerivedEngineeringCRS */ +using DerivedEngineeringCRSPtr = std::shared_ptr<DerivedEngineeringCRS>; +/** Non-null shared pointer of DerivedEngineeringCRS */ +using DerivedEngineeringCRSNNPtr = util::nn<DerivedEngineeringCRSPtr>; + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +struct PROJ_GCC_DLL DerivedParametricCRSTraits { + typedef ParametricCRS BaseType; + typedef cs::ParametricCS CSType; + // old x86_64-w64-mingw32-g++ has issues with static variables. use method + // instead + inline static const std::string &CRSName(); + inline static const std::string &WKTKeyword(); + inline static const std::string &WKTBaseKeyword(); + static const bool wkt2_2018_only = false; +}; +//! @endcond + +/** \brief A derived coordinate reference system which has a parametric + * coordinate reference system as its base CRS, thereby inheriting a parametric + * datum, and a parametric coordinate system. + * + * \remark Implements DerivedParametricCRS from \ref ISO_19111_2018 + */ +#ifdef DOXYGEN_ENABLED +class DerivedParametricCRS + : public DerivedCRSTemplate<DerivedParametricCRSTraits> {}; +#else +using DerivedParametricCRS = DerivedCRSTemplate<DerivedParametricCRSTraits>; +#endif + +#ifndef DO_NOT_DEFINE_EXTERN_DERIVED_CRS_TEMPLATE +extern template class DerivedCRSTemplate<DerivedParametricCRSTraits>; +#endif + +/** Shared pointer of DerivedParametricCRS */ +using DerivedParametricCRSPtr = std::shared_ptr<DerivedParametricCRS>; +/** Non-null shared pointer of DerivedParametricCRS */ +using DerivedParametricCRSNNPtr = util::nn<DerivedParametricCRSPtr>; + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +struct PROJ_GCC_DLL DerivedTemporalCRSTraits { + typedef TemporalCRS BaseType; + typedef cs::TemporalCS CSType; + // old x86_64-w64-mingw32-g++ has issues with static variables. use method + // instead + inline static const std::string &CRSName(); + inline static const std::string &WKTKeyword(); + inline static const std::string &WKTBaseKeyword(); + static const bool wkt2_2018_only = false; +}; +//! @endcond + +/** \brief A derived coordinate reference system which has a temporal + * coordinate reference system as its base CRS, thereby inheriting a temporal + * datum, and a temporal coordinate system. + * + * \remark Implements DerivedTemporalCRS from \ref ISO_19111_2018 + */ +#ifdef DOXYGEN_ENABLED +class DerivedTemporalCRS : public DerivedCRSTemplate<DerivedTemporalCRSTraits> { +}; +#else +using DerivedTemporalCRS = DerivedCRSTemplate<DerivedTemporalCRSTraits>; +#endif + +#ifndef DO_NOT_DEFINE_EXTERN_DERIVED_CRS_TEMPLATE +extern template class DerivedCRSTemplate<DerivedTemporalCRSTraits>; +#endif + +/** Shared pointer of DerivedTemporalCRS */ +using DerivedTemporalCRSPtr = std::shared_ptr<DerivedTemporalCRS>; +/** Non-null shared pointer of DerivedTemporalCRS */ +using DerivedTemporalCRSNNPtr = util::nn<DerivedTemporalCRSPtr>; + +// --------------------------------------------------------------------------- + +} // namespace crs + +NS_PROJ_END + +#endif // CRS_HH_INCLUDED diff --git a/include/proj/datum.hpp b/include/proj/datum.hpp new file mode 100644 index 00000000..12b93a04 --- /dev/null +++ b/include/proj/datum.hpp @@ -0,0 +1,779 @@ +/****************************************************************************** + * + * Project: PROJ + * Purpose: ISO19111:2018 implementation + * Author: Even Rouault <even dot rouault at spatialys dot com> + * + ****************************************************************************** + * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ****************************************************************************/ + +#ifndef DATUM_HH_INCLUDED +#define DATUM_HH_INCLUDED + +#include <memory> +#include <string> +#include <vector> + +#include "common.hpp" +#include "io.hpp" +#include "util.hpp" + +NS_PROJ_START + +/** osgeo.proj.datum namespace + + \brief Datum (the relationship of a coordinate system to the body). + */ +namespace datum { + +// --------------------------------------------------------------------------- + +/** \brief Abstract class of the relationship of a coordinate system to an + * object, thus creating a coordinate reference system. + * + * For geodetic and vertical coordinate reference systems, it relates a + * coordinate system to the Earth (or the celestial body considered). With + * other types of coordinate reference systems, the datum may relate the + * coordinate system to another physical or + * virtual object. A datum uses a parameter or set of parameters that determine + * the location of the origin of the coordinate reference system. Each datum + * subtype can be associated with only specific types of coordinate reference + * systems. + * + * \remark Implements Datum from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL Datum : public common::ObjectUsage { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~Datum() override; + //! @endcond + + PROJ_DLL const util::optional<std::string> &anchorDefinition() const; + PROJ_DLL const util::optional<common::DateTime> &publicationDate() const; + PROJ_DLL const common::IdentifiedObjectPtr &conventionalRS() const; + + protected: + PROJ_INTERNAL Datum(); + + PROJ_INTERNAL bool + __isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const; + +#ifdef DOXYGEN_ENABLED + std::string *anchorDefinition_; + Date *publicationDate_; + common::IdentifiedObject *conventionalRS_; +#endif + + protected: + PROJ_INTERNAL void setAnchor(const util::optional<std::string> &anchor); + + private: + PROJ_OPAQUE_PRIVATE_DATA + Datum &operator=(const Datum &other) = delete; + Datum(const Datum &other) = delete; +}; + +/** Shared pointer of Datum */ +using DatumPtr = std::shared_ptr<Datum>; +/** Non-null shared pointer of Datum */ +using DatumNNPtr = util::nn<DatumPtr>; + +// --------------------------------------------------------------------------- + +class DatumEnsemble; +/** Shared pointer of DatumEnsemble */ +using DatumEnsemblePtr = std::shared_ptr<DatumEnsemble>; +/** Non-null shared pointer of DatumEnsemble */ +using DatumEnsembleNNPtr = util::nn<DatumEnsemblePtr>; + +/** \brief A collection of two or more geodetic or vertical reference frames + * (or if not geodetic or vertical reference frame, a collection of two or more + * datums) which for all but the highest accuracy requirements may be + * considered to be insignificantly different from each other. + * + * Every frame within the datum ensemble must be a realizations of the same + * Terrestrial Reference System or Vertical Reference System. + * + * \remark Implements DatumEnsemble from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL DatumEnsemble final : public common::IdentifiedObject { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~DatumEnsemble() override; + //! @endcond + + PROJ_DLL const std::vector<DatumNNPtr> &datums() const; + PROJ_DLL const metadata::PositionalAccuracyNNPtr & + positionalAccuracy() const; + + PROJ_DLL static DatumEnsembleNNPtr create( + const util::PropertyMap &properties, + const std::vector<DatumNNPtr> &datumsIn, + const metadata::PositionalAccuracyNNPtr &accuracy); // throw(Exception) + + //! @cond Doxygen_Suppress + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + //! @endcond + + protected: +#ifdef DOXYGEN_ENABLED + Datum datums_[]; + PositionalAccuracy positionalAccuracy_; +#endif + + PROJ_INTERNAL + DatumEnsemble(const std::vector<DatumNNPtr> &datumsIn, + const metadata::PositionalAccuracyNNPtr &accuracy); + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA + + DatumEnsemble(const DatumEnsemble &other) = delete; + DatumEnsemble &operator=(const DatumEnsemble &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class PrimeMeridian; +/** Shared pointer of PrimeMeridian */ +using PrimeMeridianPtr = std::shared_ptr<PrimeMeridian>; +/** Non-null shared pointer of PrimeMeridian */ +using PrimeMeridianNNPtr = util::nn<PrimeMeridianPtr>; + +/** \brief The origin meridian from which longitude values are determined. + * + * \note The default value for prime meridian name is "Greenwich". When the + * default applies, the value for the longitude shall be 0 (degrees). + * + * \remark Implements PrimeMeridian from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL PrimeMeridian final : public common::IdentifiedObject, + public io::IPROJStringExportable { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~PrimeMeridian() override; + //! @endcond + + PROJ_DLL const common::Angle &longitude() PROJ_CONST_DECL; + + // non-standard + PROJ_DLL static PrimeMeridianNNPtr + create(const util::PropertyMap &properties, + const common::Angle &longitudeIn); + + PROJ_DLL static const PrimeMeridianNNPtr GREENWICH; + PROJ_DLL static const PrimeMeridianNNPtr PARIS; + + PROJ_PRIVATE : + + //! @cond Doxygen_Suppress + PROJ_INTERNAL void + _exportToPROJString(io::PROJStringFormatter *formatter) + const override; // throw(FormattingException) + + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + + PROJ_INTERNAL static std::string + getPROJStringWellKnownName(const common::Angle &angle); + //! @endcond + + protected: +#ifdef DOXYGEN_ENABLED + Angle greenwichLongitude_; +#endif + + PROJ_INTERNAL explicit PrimeMeridian( + const common::Angle &angle = common::Angle()); + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA + PrimeMeridian(const PrimeMeridian &other) = delete; + PrimeMeridian &operator=(const PrimeMeridian &other) = delete; + + PROJ_INTERNAL static const PrimeMeridianNNPtr createGREENWICH(); + PROJ_INTERNAL static const PrimeMeridianNNPtr createPARIS(); +}; + +// --------------------------------------------------------------------------- + +class Ellipsoid; +/** Shared pointer of Ellipsoid */ +using EllipsoidPtr = std::shared_ptr<Ellipsoid>; +/** Non-null shared pointer of Ellipsoid */ +using EllipsoidNNPtr = util::nn<EllipsoidPtr>; + +/** \brief A geometric figure that can be used to describe the approximate + * shape of an object. + * + * For the Earth an oblate biaxial ellipsoid is used: in mathematical terms, + * it is a surface formed by the rotation of an ellipse about its minor axis. + * + * \remark Implements Ellipsoid from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL Ellipsoid final : public common::IdentifiedObject, + public io::IPROJStringExportable { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~Ellipsoid() override; + //! @endcond + + PROJ_DLL const common::Length &semiMajorAxis() PROJ_CONST_DECL; + + // Inlined from SecondDefiningParameter union + PROJ_DLL const util::optional<common::Scale> & + inverseFlattening() PROJ_CONST_DECL; + PROJ_DLL const util::optional<common::Length> & + semiMinorAxis() PROJ_CONST_DECL; + PROJ_DLL bool isSphere() PROJ_CONST_DECL; + + PROJ_DLL const util::optional<common::Length> & + semiMedianAxis() PROJ_CONST_DECL; + + // non-standard + + PROJ_DLL double computedInverseFlattening() PROJ_CONST_DECL; + PROJ_DLL double squaredEccentricity() PROJ_CONST_DECL; + PROJ_DLL common::Length computeSemiMinorAxis() const; + + PROJ_DLL const std::string &celestialBody() PROJ_CONST_DECL; + + PROJ_DLL static const std::string EARTH; + + PROJ_DLL static EllipsoidNNPtr + createSphere(const util::PropertyMap &properties, + const common::Length &radius, + const std::string &celestialBody = EARTH); + + PROJ_DLL static EllipsoidNNPtr + createFlattenedSphere(const util::PropertyMap &properties, + const common::Length &semiMajorAxisIn, + const common::Scale &invFlattening, + const std::string &celestialBody = EARTH); + + PROJ_DLL static EllipsoidNNPtr + createTwoAxis(const util::PropertyMap &properties, + const common::Length &semiMajorAxisIn, + const common::Length &semiMinorAxisIn, + const std::string &celestialBody = EARTH); + + PROJ_DLL EllipsoidNNPtr identify() const; + + PROJ_DLL static const EllipsoidNNPtr CLARKE_1866; + PROJ_DLL static const EllipsoidNNPtr WGS84; + PROJ_DLL static const EllipsoidNNPtr GRS1980; + + PROJ_PRIVATE : + //! @cond Doxygen_Suppress + PROJ_INTERNAL void + _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + + PROJ_INTERNAL void _exportToPROJString(io::PROJStringFormatter *formatter) + const override; // throw(FormattingException) + //! @endcond + + PROJ_INTERNAL static std::string + guessBodyName(const io::DatabaseContextPtr &dbContext, double a); + + PROJ_INTERNAL bool lookForProjWellKnownEllps(std::string &projEllpsName, + std::string &ellpsName) const; + + protected: +#ifdef DOXYGEN_ENABLED + common::Length semiMajorAxis_; + common::Scale *inverseFlattening_; + common::Length *semiMinorAxis_; + bool isSphere_; + common::Length *semiMedianAxis_; +#endif + + PROJ_INTERNAL explicit Ellipsoid(const common::Length &radius, + const std::string &celestialBody); + + PROJ_INTERNAL Ellipsoid(const common::Length &semiMajorAxisIn, + const common::Scale &invFlattening, + const std::string &celestialBody); + + PROJ_INTERNAL Ellipsoid(const common::Length &semiMajorAxisIn, + const common::Length &semiMinorAxisIn, + const std::string &celestialBody); + + PROJ_INTERNAL Ellipsoid(const Ellipsoid &other); + + INLINED_MAKE_SHARED + + PROJ_INTERNAL static const EllipsoidNNPtr createCLARKE_1866(); + PROJ_INTERNAL static const EllipsoidNNPtr createWGS84(); + PROJ_INTERNAL static const EllipsoidNNPtr createGRS1980(); + + private: + PROJ_OPAQUE_PRIVATE_DATA + Ellipsoid &operator=(const Ellipsoid &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class GeodeticReferenceFrame; +/** Shared pointer of GeodeticReferenceFrame */ +using GeodeticReferenceFramePtr = std::shared_ptr<GeodeticReferenceFrame>; +/** Non-null shared pointer of GeodeticReferenceFrame */ +using GeodeticReferenceFrameNNPtr = util::nn<GeodeticReferenceFramePtr>; + +/** \brief The definition of the position, scale and orientation of a geocentric + * Cartesian 3D coordinate system relative to the Earth. + * + * It may also identify a defined ellipsoid (or sphere) that approximates + * the shape of the Earth and which is centred on and aligned to this + * geocentric coordinate system. Older geodetic datums define the location and + * orientation of a defined ellipsoid (or sphere) that approximates the shape + * of the earth. + * + * \note The terminology "Datum" is often used to mean a GeodeticReferenceFrame. + * + * \note In \ref ISO_19111_2007, this class was called GeodeticDatum. + * + * \remark Implements GeodeticReferenceFrame from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL GeodeticReferenceFrame : public Datum { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~GeodeticReferenceFrame() override; + //! @endcond + + PROJ_DLL const PrimeMeridianNNPtr &primeMeridian() PROJ_CONST_DECL; + + // We constraint more than the standard into which the ellipsoid might + // be omitted for a CRS with a non-ellipsoidal CS + PROJ_DLL const EllipsoidNNPtr &ellipsoid() PROJ_CONST_DECL; + + // non-standard + PROJ_DLL static GeodeticReferenceFrameNNPtr + create(const util::PropertyMap &properties, const EllipsoidNNPtr &ellipsoid, + const util::optional<std::string> &anchor, + const PrimeMeridianNNPtr &primeMeridian); + + PROJ_DLL static const GeodeticReferenceFrameNNPtr + EPSG_6267; // North American Datum 1927 + PROJ_DLL static const GeodeticReferenceFrameNNPtr + EPSG_6269; // North American Datum 1983 + PROJ_DLL static const GeodeticReferenceFrameNNPtr EPSG_6326; // WGS 84 + + //! @cond Doxygen_Suppress + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + //! @endcond + + protected: +#ifdef DOXYGEN_ENABLED + PrimeMeridian primeMeridian_; + Ellipsoid *ellipsoid_; +#endif + + PROJ_INTERNAL + GeodeticReferenceFrame(const EllipsoidNNPtr &ellipsoidIn, + const PrimeMeridianNNPtr &primeMeridianIn); + INLINED_MAKE_SHARED + + PROJ_INTERNAL static const GeodeticReferenceFrameNNPtr createEPSG_6267(); + PROJ_INTERNAL static const GeodeticReferenceFrameNNPtr createEPSG_6269(); + PROJ_INTERNAL static const GeodeticReferenceFrameNNPtr createEPSG_6326(); + + private: + PROJ_OPAQUE_PRIVATE_DATA + GeodeticReferenceFrame(const GeodeticReferenceFrame &other) = delete; + GeodeticReferenceFrame & + operator=(const GeodeticReferenceFrame &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class DynamicGeodeticReferenceFrame; +/** Shared pointer of DynamicGeodeticReferenceFrame */ +using DynamicGeodeticReferenceFramePtr = + std::shared_ptr<DynamicGeodeticReferenceFrame>; +/** Non-null shared pointer of DynamicGeodeticReferenceFrame */ +using DynamicGeodeticReferenceFrameNNPtr = + util::nn<DynamicGeodeticReferenceFramePtr>; + +/** \brief A geodetic reference frame in which some of the parameters describe + * time evolution of defining station coordinates. + * + * For example defining station coordinates having linear velocities to account + * for crustal motion. + * + * \remark Implements DynamicGeodeticReferenceFrame from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL DynamicGeodeticReferenceFrame final + : public GeodeticReferenceFrame { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~DynamicGeodeticReferenceFrame() override; + //! @endcond + + PROJ_DLL const common::Measure &frameReferenceEpoch() const; + PROJ_DLL const util::optional<std::string> &deformationModelName() const; + + // non-standard + PROJ_DLL static DynamicGeodeticReferenceFrameNNPtr + create(const util::PropertyMap &properties, const EllipsoidNNPtr &ellipsoid, + const util::optional<std::string> &anchor, + const PrimeMeridianNNPtr &primeMeridian, + const common::Measure &frameReferenceEpochIn, + const util::optional<std::string> &deformationModelNameIn); + + //! @cond Doxygen_Suppress + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + //! @endcond + + protected: +#ifdef DOXYGEN_ENABLED + Measure frameReferenceEpoch_; +#endif + + PROJ_INTERNAL DynamicGeodeticReferenceFrame( + const EllipsoidNNPtr &ellipsoidIn, + const PrimeMeridianNNPtr &primeMeridianIn, + const common::Measure &frameReferenceEpochIn, + const util::optional<std::string> &deformationModelNameIn); + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA + DynamicGeodeticReferenceFrame(const DynamicGeodeticReferenceFrame &other) = + delete; + DynamicGeodeticReferenceFrame & + operator=(const DynamicGeodeticReferenceFrame &other) = delete; +}; + +// --------------------------------------------------------------------------- + +/** \brief The specification of the method by which the vertical reference frame + * is realized. + * + * \remark Implements RealizationMethod from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL RealizationMethod : public util::CodeList { + public: + PROJ_DLL static const RealizationMethod LEVELLING; + PROJ_DLL static const RealizationMethod GEOID; + PROJ_DLL static const RealizationMethod TIDAL; + + private: + PROJ_FRIEND_OPTIONAL(RealizationMethod); + PROJ_DLL explicit RealizationMethod( + const std::string &nameIn = std::string()); + PROJ_DLL RealizationMethod(const RealizationMethod &other); + PROJ_DLL RealizationMethod &operator=(const RealizationMethod &other); +}; + +// --------------------------------------------------------------------------- + +class VerticalReferenceFrame; +/** Shared pointer of VerticalReferenceFrame */ +using VerticalReferenceFramePtr = std::shared_ptr<VerticalReferenceFrame>; +/** Non-null shared pointer of VerticalReferenceFrame */ +using VerticalReferenceFrameNNPtr = util::nn<VerticalReferenceFramePtr>; + +/** \brief A textual description and/or a set of parameters identifying a + * particular reference level surface used as a zero-height or zero-depth + * surface, including its position with respect to the Earth. + * + * \note In \ref ISO_19111_2007, this class was called VerticalDatum. + + * \remark Implements VerticalReferenceFrame from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL VerticalReferenceFrame : public Datum { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~VerticalReferenceFrame() override; + //! @endcond + + PROJ_DLL const util::optional<RealizationMethod> &realizationMethod() const; + + // non-standard + PROJ_DLL static VerticalReferenceFrameNNPtr + create(const util::PropertyMap &properties, + const util::optional<std::string> &anchor = + util::optional<std::string>(), + const util::optional<RealizationMethod> &realizationMethodIn = + util::optional<RealizationMethod>()); + + //! @cond Doxygen_Suppress + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + //! @endcond + + protected: +#ifdef DOXYGEN_ENABLED + RealizationMethod realizationMethod_; +#endif + + PROJ_INTERNAL explicit VerticalReferenceFrame( + const util::optional<RealizationMethod> &realizationMethodIn); + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA +}; + +// --------------------------------------------------------------------------- + +class DynamicVerticalReferenceFrame; +/** Shared pointer of DynamicVerticalReferenceFrame */ +using DynamicVerticalReferenceFramePtr = + std::shared_ptr<DynamicVerticalReferenceFrame>; +/** Non-null shared pointer of DynamicVerticalReferenceFrame */ +using DynamicVerticalReferenceFrameNNPtr = + util::nn<DynamicVerticalReferenceFramePtr>; + +/** \brief A vertical reference frame in which some of the defining parameters + * have time dependency. + * + * For example defining station heights have velocity to account for + * post-glacial isostatic rebound motion. + * + * \remark Implements DynamicVerticalReferenceFrame from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL DynamicVerticalReferenceFrame final + : public VerticalReferenceFrame { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~DynamicVerticalReferenceFrame() override; + //! @endcond + + PROJ_DLL const common::Measure &frameReferenceEpoch() const; + PROJ_DLL const util::optional<std::string> &deformationModelName() const; + + // non-standard + PROJ_DLL static DynamicVerticalReferenceFrameNNPtr + create(const util::PropertyMap &properties, + const util::optional<std::string> &anchor, + const util::optional<RealizationMethod> &realizationMethodIn, + const common::Measure &frameReferenceEpochIn, + const util::optional<std::string> &deformationModelNameIn); + + //! @cond Doxygen_Suppress + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + //! @endcond + + protected: +#ifdef DOXYGEN_ENABLED + Measure frameReferenceEpoch_; +#endif + + PROJ_INTERNAL DynamicVerticalReferenceFrame( + const util::optional<RealizationMethod> &realizationMethodIn, + const common::Measure &frameReferenceEpochIn, + const util::optional<std::string> &deformationModelNameIn); + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA + DynamicVerticalReferenceFrame(const DynamicVerticalReferenceFrame &other) = + delete; + DynamicVerticalReferenceFrame & + operator=(const DynamicVerticalReferenceFrame &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class TemporalDatum; +/** Shared pointer of TemporalDatum */ +using TemporalDatumPtr = std::shared_ptr<TemporalDatum>; +/** Non-null shared pointer of TemporalDatum */ +using TemporalDatumNNPtr = util::nn<TemporalDatumPtr>; + +/** \brief The definition of the relationship of a temporal coordinate system + * to an object. The object is normally time on the Earth. + * + * \remark Implements TemporalDatum from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL TemporalDatum final : public Datum { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~TemporalDatum() override; + //! @endcond + + PROJ_DLL const common::DateTime &temporalOrigin() const; + PROJ_DLL const std::string &calendar() const; + + PROJ_DLL static const std::string CALENDAR_PROLEPTIC_GREGORIAN; + + // non-standard + PROJ_DLL static TemporalDatumNNPtr + create(const util::PropertyMap &properties, + const common::DateTime &temporalOriginIn, + const std::string &calendarIn); + + //! @cond Doxygen_Suppress + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + //! @endcond + + protected: + PROJ_INTERNAL TemporalDatum(const common::DateTime &temporalOriginIn, + const std::string &calendarIn); + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA +}; + +// --------------------------------------------------------------------------- + +class EngineeringDatum; +/** Shared pointer of EngineeringDatum */ +using EngineeringDatumPtr = std::shared_ptr<EngineeringDatum>; +/** Non-null shared pointer of EngineeringDatum */ +using EngineeringDatumNNPtr = util::nn<EngineeringDatumPtr>; + +/** \brief The definition of the origin and orientation of an engineering + * coordinate reference system. + * + * \note The origin can be fixed with respect to the Earth (such as a defined + * point at a construction site), or be a defined point on a moving vehicle + * (such as on a ship or satellite), or a defined point of an image. + * + * \remark Implements EngineeringDatum from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL EngineeringDatum final : public Datum { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~EngineeringDatum() override; + //! @endcond + + // non-standard + PROJ_DLL static EngineeringDatumNNPtr + create(const util::PropertyMap &properties, + const util::optional<std::string> &anchor = + util::optional<std::string>()); + + //! @cond Doxygen_Suppress + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + //! @endcond + + protected: + PROJ_INTERNAL EngineeringDatum(); + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA +}; + +// --------------------------------------------------------------------------- + +class ParametricDatum; +/** Shared pointer of ParametricDatum */ +using ParametricDatumPtr = std::shared_ptr<ParametricDatum>; +/** Non-null shared pointer of ParametricDatum */ +using ParametricDatumNNPtr = util::nn<ParametricDatumPtr>; + +/** \brief Textual description and/or a set of parameters identifying a + * particular reference surface used as the origin of a parametric coordinate + * system, including its position with respect to the Earth. + * + * \remark Implements ParametricDatum from \ref ISO_19111_2018 + */ +class PROJ_GCC_DLL ParametricDatum final : public Datum { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~ParametricDatum() override; + //! @endcond + + // non-standard + PROJ_DLL static ParametricDatumNNPtr + create(const util::PropertyMap &properties, + const util::optional<std::string> &anchor = + util::optional<std::string>()); + + //! @cond Doxygen_Suppress + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + //! @endcond + + protected: + PROJ_INTERNAL ParametricDatum(); + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA +}; + +} // namespace datum + +NS_PROJ_END + +#endif // DATUM_HH_INCLUDED diff --git a/include/proj/internal/Makefile.am b/include/proj/internal/Makefile.am new file mode 100644 index 00000000..ddd2686c --- /dev/null +++ b/include/proj/internal/Makefile.am @@ -0,0 +1,8 @@ +noinst_HEADERS = \ + coordinateoperation_constants.hpp \ + coordinateoperation_internal.hpp \ + esri_projection_mappings.hpp \ + coordinatesystem_internal.hpp \ + internal.hpp \ + io_internal.hpp \ + lru_cache.hpp diff --git a/include/proj/internal/coordinateoperation_constants.hpp b/include/proj/internal/coordinateoperation_constants.hpp new file mode 100644 index 00000000..e999b3a6 --- /dev/null +++ b/include/proj/internal/coordinateoperation_constants.hpp @@ -0,0 +1,898 @@ +/****************************************************************************** + * + * Project: PROJ + * Purpose: ISO19111:2018 implementation + * Author: Even Rouault <even dot rouault at spatialys dot com> + * + ****************************************************************************** + * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ****************************************************************************/ + +#ifndef FROM_COORDINATE_OPERATION_CPP +#error This file should only be included from coordinateoperation.cpp +#endif + +#ifndef COORDINATEOPERATION_CONSTANTS_HH_INCLUDED +#define COORDINATEOPERATION_CONSTANTS_HH_INCLUDED + +#include "coordinateoperation_internal.hpp" +#include "proj_constants.h" + +//! @cond Doxygen_Suppress +// --------------------------------------------------------------------------- + +// anonymous namespace +namespace { + +using namespace ::NS_PROJ; +using namespace ::NS_PROJ::operation; + +static const char *WKT1_LATITUDE_OF_ORIGIN = "latitude_of_origin"; +static const char *WKT1_CENTRAL_MERIDIAN = "central_meridian"; +static const char *WKT1_SCALE_FACTOR = "scale_factor"; +static const char *WKT1_FALSE_EASTING = "false_easting"; +static const char *WKT1_FALSE_NORTHING = "false_northing"; +static const char *WKT1_STANDARD_PARALLEL_1 = "standard_parallel_1"; +static const char *WKT1_STANDARD_PARALLEL_2 = "standard_parallel_2"; +static const char *WKT1_LATITUDE_OF_CENTER = "latitude_of_center"; +static const char *WKT1_LONGITUDE_OF_CENTER = "longitude_of_center"; +static const char *WKT1_AZIMUTH = "azimuth"; +static const char *WKT1_RECTIFIED_GRID_ANGLE = "rectified_grid_angle"; + +static const char *lat_0 = "lat_0"; +static const char *lat_1 = "lat_1"; +static const char *lat_2 = "lat_2"; +static const char *lat_ts = "lat_ts"; +static const char *lon_0 = "lon_0"; +static const char *lon_1 = "lon_1"; +static const char *lon_2 = "lon_2"; +static const char *lonc = "lonc"; +static const char *alpha = "alpha"; +static const char *gamma = "gamma"; +static const char *k_0 = "k_0"; +static const char *k = "k"; +static const char *x_0 = "x_0"; +static const char *y_0 = "y_0"; +static const char *h = "h"; + +static const ParamMapping paramLatitudeNatOrigin = { + EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, WKT1_LATITUDE_OF_ORIGIN, + common::UnitOfMeasure::Type::ANGULAR, lat_0}; + +static const ParamMapping paramLongitudeNatOrigin = { + EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, WKT1_CENTRAL_MERIDIAN, + common::UnitOfMeasure::Type::ANGULAR, lon_0}; + +static const ParamMapping paramScaleFactor = { + EPSG_NAME_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN, WKT1_SCALE_FACTOR, + common::UnitOfMeasure::Type::SCALE, k_0}; + +static const ParamMapping paramFalseEasting = { + EPSG_NAME_PARAMETER_FALSE_EASTING, EPSG_CODE_PARAMETER_FALSE_EASTING, + WKT1_FALSE_EASTING, common::UnitOfMeasure::Type::LINEAR, x_0}; + +static const ParamMapping paramFalseNorthing = { + EPSG_NAME_PARAMETER_FALSE_NORTHING, EPSG_CODE_PARAMETER_FALSE_NORTHING, + WKT1_FALSE_NORTHING, common::UnitOfMeasure::Type::LINEAR, y_0}; + +static const ParamMapping paramLatitudeFalseOrigin = { + EPSG_NAME_PARAMETER_LATITUDE_FALSE_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_FALSE_ORIGIN, WKT1_LATITUDE_OF_ORIGIN, + common::UnitOfMeasure::Type::ANGULAR, lat_0}; + +static const ParamMapping paramLongitudeFalseOrigin = { + EPSG_NAME_PARAMETER_LONGITUDE_FALSE_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_FALSE_ORIGIN, WKT1_CENTRAL_MERIDIAN, + common::UnitOfMeasure::Type::ANGULAR, lon_0}; + +static const ParamMapping paramFalseEastingOrigin = { + EPSG_NAME_PARAMETER_EASTING_FALSE_ORIGIN, + EPSG_CODE_PARAMETER_EASTING_FALSE_ORIGIN, WKT1_FALSE_EASTING, + common::UnitOfMeasure::Type::LINEAR, x_0}; + +static const ParamMapping paramFalseNorthingOrigin = { + EPSG_NAME_PARAMETER_NORTHING_FALSE_ORIGIN, + EPSG_CODE_PARAMETER_NORTHING_FALSE_ORIGIN, WKT1_FALSE_NORTHING, + common::UnitOfMeasure::Type::LINEAR, y_0}; + +static const ParamMapping paramLatitude1stStdParallel = { + EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL, WKT1_STANDARD_PARALLEL_1, + common::UnitOfMeasure::Type::ANGULAR, lat_1}; + +static const ParamMapping paramLatitude2ndStdParallel = { + EPSG_NAME_PARAMETER_LATITUDE_2ND_STD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_2ND_STD_PARALLEL, WKT1_STANDARD_PARALLEL_2, + common::UnitOfMeasure::Type::ANGULAR, lat_2}; + +static const ParamMapping *const paramsNatOriginScale[] = { + ¶mLatitudeNatOrigin, ¶mLongitudeNatOrigin, ¶mScaleFactor, + ¶mFalseEasting, ¶mFalseNorthing, nullptr}; + +static const ParamMapping paramLatFirstPoint = { + "Latitude of 1st point", 0, "Latitude_Of_1st_Point", + common::UnitOfMeasure::Type::ANGULAR, lat_1}; +static const ParamMapping paramLongFirstPoint = { + "Longitude of 1st point", 0, "Longitude_Of_1st_Point", + common::UnitOfMeasure::Type::ANGULAR, lon_1}; +static const ParamMapping paramLatSecondPoint = { + "Latitude of 2nd point", 0, "Latitude_Of_2nd_Point", + common::UnitOfMeasure::Type::ANGULAR, lat_2}; +static const ParamMapping paramLongSecondPoint = { + "Longitude of 2nd point", 0, "Longitude_Of_2nd_Point", + common::UnitOfMeasure::Type::ANGULAR, lon_2}; + +static const ParamMapping *const paramsTPEQD[] = {¶mLatFirstPoint, + ¶mLongFirstPoint, + ¶mLatSecondPoint, + ¶mLongSecondPoint, + ¶mFalseEasting, + ¶mFalseNorthing, + nullptr}; + +static const ParamMapping *const paramsTMG[] = { + ¶mLatitudeFalseOrigin, ¶mLongitudeFalseOrigin, + ¶mFalseEastingOrigin, ¶mFalseNorthingOrigin, nullptr}; + +static const ParamMapping paramLatFalseOriginLatOfCenter = { + EPSG_NAME_PARAMETER_LATITUDE_FALSE_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_FALSE_ORIGIN, WKT1_LATITUDE_OF_CENTER, + common::UnitOfMeasure::Type::ANGULAR, lat_0}; + +static const ParamMapping paramLongFalseOriginLongOfCenter = { + EPSG_NAME_PARAMETER_LONGITUDE_FALSE_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_FALSE_ORIGIN, WKT1_LONGITUDE_OF_CENTER, + common::UnitOfMeasure::Type::ANGULAR, lon_0}; + +static const ParamMapping *const paramsAEA[] = { + ¶mLatFalseOriginLatOfCenter, + ¶mLongFalseOriginLongOfCenter, + ¶mLatitude1stStdParallel, + ¶mLatitude2ndStdParallel, + ¶mFalseEastingOrigin, + ¶mFalseNorthingOrigin, + nullptr}; + +static const ParamMapping *const paramsLCC2SP[] = { + ¶mLatitudeFalseOrigin, + ¶mLongitudeFalseOrigin, + ¶mLatitude1stStdParallel, + ¶mLatitude2ndStdParallel, + ¶mFalseEastingOrigin, + ¶mFalseNorthingOrigin, + nullptr, +}; + +static const ParamMapping paramEllipsoidScaleFactor = { + EPSG_NAME_PARAMETER_ELLIPSOID_SCALE_FACTOR, + EPSG_CODE_PARAMETER_ELLIPSOID_SCALE_FACTOR, nullptr, + common::UnitOfMeasure::Type::SCALE, k_0}; + +static const ParamMapping *const paramsLCC2SPMichigan[] = { + ¶mLatitudeFalseOrigin, ¶mLongitudeFalseOrigin, + ¶mLatitude1stStdParallel, ¶mLatitude2ndStdParallel, + ¶mFalseEastingOrigin, ¶mFalseNorthingOrigin, + ¶mEllipsoidScaleFactor, nullptr, +}; + +static const ParamMapping paramLatNatLatCenter = { + EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, WKT1_LATITUDE_OF_CENTER, + common::UnitOfMeasure::Type::ANGULAR, lat_0}; + +static const ParamMapping paramLonNatLonCenter = { + EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, WKT1_LONGITUDE_OF_CENTER, + common::UnitOfMeasure::Type::ANGULAR, lon_0}; + +static const ParamMapping *const paramsAEQD[]{ + ¶mLatNatLatCenter, ¶mLonNatLonCenter, ¶mFalseEasting, + ¶mFalseNorthing, nullptr}; + +static const ParamMapping *const paramsNatOrigin[] = { + ¶mLatitudeNatOrigin, ¶mLongitudeNatOrigin, ¶mFalseEasting, + ¶mFalseNorthing, nullptr}; + +static const ParamMapping paramLatNatOriginLat1 = { + EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, WKT1_STANDARD_PARALLEL_1, + common::UnitOfMeasure::Type::ANGULAR, lat_1}; + +static const ParamMapping *const paramsBonne[] = { + ¶mLatNatOriginLat1, ¶mLongitudeNatOrigin, ¶mFalseEasting, + ¶mFalseNorthing, nullptr}; + +static const ParamMapping paramLat1stParallelLatTs = { + EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL, WKT1_STANDARD_PARALLEL_1, + common::UnitOfMeasure::Type::ANGULAR, lat_ts}; + +static const ParamMapping *const paramsCEA[] = { + ¶mLat1stParallelLatTs, ¶mLongitudeNatOrigin, ¶mFalseEasting, + ¶mFalseNorthing, nullptr}; + +static const ParamMapping *const paramsEQDC[] = {¶mLatNatLatCenter, + ¶mLonNatLonCenter, + ¶mLatitude1stStdParallel, + ¶mLatitude2ndStdParallel, + ¶mFalseEasting, + ¶mFalseNorthing, + nullptr}; + +static const ParamMapping *const paramsLonNatOrigin[] = { + ¶mLongitudeNatOrigin, ¶mFalseEasting, ¶mFalseNorthing, nullptr}; + +static const ParamMapping *const paramsEqc[] = // same as paramsCEA + {¶mLat1stParallelLatTs, ¶mLongitudeNatOrigin, ¶mFalseEasting, + ¶mFalseNorthing, nullptr}; + +static const ParamMapping paramSatelliteHeight = { + "Satellite Height", 0, "satellite_height", + common::UnitOfMeasure::Type::LINEAR, h}; + +static const ParamMapping *const paramsGeos[] = { + ¶mLongitudeNatOrigin, ¶mSatelliteHeight, ¶mFalseEasting, + ¶mFalseNorthing, nullptr}; + +static const ParamMapping paramLatCentreLatCenter = { + EPSG_NAME_PARAMETER_LATITUDE_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_LATITUDE_PROJECTION_CENTRE, WKT1_LATITUDE_OF_CENTER, + common::UnitOfMeasure::Type::ANGULAR, lat_0}; + +static const ParamMapping paramLonCentreLonCenterLonc = { + EPSG_NAME_PARAMETER_LONGITUDE_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_LONGITUDE_PROJECTION_CENTRE, WKT1_LONGITUDE_OF_CENTER, + common::UnitOfMeasure::Type::ANGULAR, lonc}; + +static const ParamMapping paramLatCentreLatOrigin = { + EPSG_NAME_PARAMETER_LATITUDE_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_LATITUDE_PROJECTION_CENTRE, WKT1_LATITUDE_OF_ORIGIN, + common::UnitOfMeasure::Type::ANGULAR, lat_0}; + +static const ParamMapping paramAzimuth = { + EPSG_NAME_PARAMETER_AZIMUTH_INITIAL_LINE, + EPSG_CODE_PARAMETER_AZIMUTH_INITIAL_LINE, WKT1_AZIMUTH, + common::UnitOfMeasure::Type::ANGULAR, alpha}; + +static const ParamMapping paramAngleToSkewGrid = { + EPSG_NAME_PARAMETER_ANGLE_RECTIFIED_TO_SKEW_GRID, + EPSG_CODE_PARAMETER_ANGLE_RECTIFIED_TO_SKEW_GRID, WKT1_RECTIFIED_GRID_ANGLE, + common::UnitOfMeasure::Type::ANGULAR, gamma}; +static const ParamMapping paramScaleFactorInitialLine = { + EPSG_NAME_PARAMETER_SCALE_FACTOR_INITIAL_LINE, + EPSG_CODE_PARAMETER_SCALE_FACTOR_INITIAL_LINE, WKT1_SCALE_FACTOR, + common::UnitOfMeasure::Type::SCALE, k}; + +static const ParamMapping *const paramsHomVariantA[] = { + ¶mLatCentreLatCenter, + ¶mLonCentreLonCenterLonc, + ¶mAzimuth, + ¶mAngleToSkewGrid, + ¶mScaleFactorInitialLine, + ¶mFalseEasting, + ¶mFalseNorthing, + nullptr}; + +static const ParamMapping paramFalseEastingProjectionCentre = { + EPSG_NAME_PARAMETER_EASTING_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_EASTING_PROJECTION_CENTRE, WKT1_FALSE_EASTING, + common::UnitOfMeasure::Type::LINEAR, x_0}; + +static const ParamMapping paramFalseNorthingProjectionCentre = { + EPSG_NAME_PARAMETER_NORTHING_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_NORTHING_PROJECTION_CENTRE, WKT1_FALSE_NORTHING, + common::UnitOfMeasure::Type::LINEAR, y_0}; + +static const ParamMapping *const paramsHomVariantB[] = { + ¶mLatCentreLatCenter, + ¶mLonCentreLonCenterLonc, + ¶mAzimuth, + ¶mAngleToSkewGrid, + ¶mScaleFactorInitialLine, + ¶mFalseEastingProjectionCentre, + ¶mFalseNorthingProjectionCentre, + nullptr}; + +static const ParamMapping paramLatPoint1 = { + "Latitude of 1st point", 0, "latitude_of_point_1", + common::UnitOfMeasure::Type::ANGULAR, lat_1}; + +static const ParamMapping paramLonPoint1 = { + "Longitude of 1st point", 0, "longitude_of_point_1", + common::UnitOfMeasure::Type::ANGULAR, lon_1}; + +static const ParamMapping paramLatPoint2 = { + "Latitude of 2nd point", 0, "latitude_of_point_2", + common::UnitOfMeasure::Type::ANGULAR, lat_2}; + +static const ParamMapping paramLonPoint2 = { + "Longitude of 2nd point", 0, "longitude_of_point_2", + common::UnitOfMeasure::Type::ANGULAR, lon_2}; + +static const ParamMapping *const paramsHomTwoPoint[] = { + ¶mLatCentreLatOrigin, + ¶mLatPoint1, + ¶mLonPoint1, + ¶mLatPoint2, + ¶mLonPoint2, + ¶mScaleFactorInitialLine, + ¶mFalseEastingProjectionCentre, + ¶mFalseNorthingProjectionCentre, + nullptr}; + +static const ParamMapping *const paramsIMWP[] = { + ¶mLongitudeNatOrigin, ¶mLatitude1stStdParallel, + ¶mLatitude2ndStdParallel, ¶mFalseEasting, + ¶mFalseNorthing, nullptr}; + +static const ParamMapping paramLonCentreLonCenter = { + EPSG_NAME_PARAMETER_LONGITUDE_OF_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_ORIGIN, WKT1_LONGITUDE_OF_CENTER, + common::UnitOfMeasure::Type::ANGULAR, lon_0}; + +static const ParamMapping paramColatitudeConeAxis = { + EPSG_NAME_PARAMETER_COLATITUDE_CONE_AXIS, + EPSG_CODE_PARAMETER_COLATITUDE_CONE_AXIS, WKT1_AZIMUTH, + common::UnitOfMeasure::Type::ANGULAR, + nullptr}; /* ignored by PROJ currently */ + +static const ParamMapping paramLatitudePseudoStdParallel = { + EPSG_NAME_PARAMETER_LATITUDE_PSEUDO_STANDARD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_PSEUDO_STANDARD_PARALLEL, + "pseudo_standard_parallel_1", common::UnitOfMeasure::Type::ANGULAR, + nullptr}; /* ignored by PROJ currently */ + +static const ParamMapping paramScaleFactorPseudoStdParallel = { + EPSG_NAME_PARAMETER_SCALE_FACTOR_PSEUDO_STANDARD_PARALLEL, + EPSG_CODE_PARAMETER_SCALE_FACTOR_PSEUDO_STANDARD_PARALLEL, + WKT1_SCALE_FACTOR, common::UnitOfMeasure::Type::SCALE, + k}; /* ignored by PROJ currently */ + +static const ParamMapping *const krovakParameters[] = { + ¶mLatCentreLatCenter, + ¶mLonCentreLonCenter, + ¶mColatitudeConeAxis, + ¶mLatitudePseudoStdParallel, + ¶mScaleFactorPseudoStdParallel, + ¶mFalseEasting, + ¶mFalseNorthing, + nullptr}; + +static const ParamMapping *const paramsLaea[] = { + ¶mLatNatLatCenter, ¶mLonNatLonCenter, ¶mFalseEasting, + ¶mFalseNorthing, nullptr}; + +static const ParamMapping *const paramsMiller[] = { + ¶mLonNatLonCenter, ¶mFalseEasting, ¶mFalseNorthing, nullptr}; + +static const ParamMapping paramLatMerc1SP = { + EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + nullptr, // always set to zero, not to be exported in WKT1 + common::UnitOfMeasure::Type::ANGULAR, + nullptr}; // always set to zero, not to be exported in PROJ strings + +static const ParamMapping paramScaleFactorK = { + EPSG_NAME_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN, WKT1_SCALE_FACTOR, + common::UnitOfMeasure::Type::SCALE, k}; + +static const ParamMapping *const paramsMerc1SP[] = { + ¶mLatMerc1SP, ¶mLongitudeNatOrigin, ¶mScaleFactorK, + ¶mFalseEasting, ¶mFalseNorthing, nullptr}; + +static const ParamMapping *const paramsMerc2SP[] = { + ¶mLat1stParallelLatTs, ¶mLongitudeNatOrigin, ¶mFalseEasting, + ¶mFalseNorthing, nullptr}; + +static const ParamMapping *const paramsObliqueStereo[] = { + ¶mLatitudeNatOrigin, ¶mLongitudeNatOrigin, ¶mScaleFactorK, + ¶mFalseEasting, ¶mFalseNorthing, nullptr}; + +static const ParamMapping paramLatStdParallel = { + EPSG_NAME_PARAMETER_LATITUDE_STD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_STD_PARALLEL, WKT1_LATITUDE_OF_ORIGIN, + common::UnitOfMeasure::Type::ANGULAR, lat_ts}; + +static const ParamMapping paramsLonOrigin = { + EPSG_NAME_PARAMETER_LONGITUDE_OF_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_ORIGIN, WKT1_CENTRAL_MERIDIAN, + common::UnitOfMeasure::Type::ANGULAR, lon_0}; + +static const ParamMapping *const paramsPolarStereo[] = { + ¶mLatStdParallel, ¶msLonOrigin, ¶mFalseEasting, + ¶mFalseNorthing, nullptr}; + +static const ParamMapping *const paramsLonNatOriginLongitudeCentre[] = { + ¶mLonNatLonCenter, ¶mFalseEasting, ¶mFalseNorthing, nullptr}; + +static const ParamMapping paramLatTrueScaleWag3 = { + "Latitude of true scale", 0, WKT1_LATITUDE_OF_ORIGIN, + common::UnitOfMeasure::Type::ANGULAR, lat_ts}; + +static const ParamMapping *const paramsWag3[] = { + ¶mLatTrueScaleWag3, ¶mLongitudeNatOrigin, ¶mFalseEasting, + ¶mFalseNorthing, nullptr}; + +static const ParamMapping paramPegLat = { + "Peg point latitude", 0, "peg_point_latitude", + common::UnitOfMeasure::Type::ANGULAR, "plat_0"}; + +static const ParamMapping paramPegLon = { + "Peg point longitude", 0, "peg_point_longitude", + common::UnitOfMeasure::Type::ANGULAR, "plon_0"}; + +static const ParamMapping paramPegHeading = { + "Peg point heading", 0, "peg_point_heading", + common::UnitOfMeasure::Type::ANGULAR, "phdg_0"}; + +static const ParamMapping paramPegHeight = { + "Peg point height", 0, "peg_point_height", + common::UnitOfMeasure::Type::LINEAR, "h_0"}; + +static const ParamMapping *const paramsSch[] = { + ¶mPegLat, ¶mPegLon, ¶mPegHeading, ¶mPegHeight, nullptr}; + +static const ParamMapping *const paramsWink1[] = { + ¶mLongitudeNatOrigin, ¶mLat1stParallelLatTs, ¶mFalseEasting, + ¶mFalseNorthing, nullptr}; + +static const ParamMapping *const paramsWink2[] = { + ¶mLongitudeNatOrigin, ¶mLatitude1stStdParallel, ¶mFalseEasting, + ¶mFalseNorthing, nullptr}; + +static const ParamMapping paramLatLoxim = { + EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, WKT1_LATITUDE_OF_ORIGIN, + common::UnitOfMeasure::Type::ANGULAR, lat_1}; + +static const ParamMapping *const paramsLoxim[] = { + ¶mLatLoxim, ¶mLongitudeNatOrigin, ¶mFalseEasting, + ¶mFalseNorthing, nullptr}; + +static const ParamMapping paramLonCentre = { + EPSG_NAME_PARAMETER_LONGITUDE_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_LONGITUDE_PROJECTION_CENTRE, nullptr, + common::UnitOfMeasure::Type::ANGULAR, lon_0}; + +static const ParamMapping paramLabordeObliqueMercatorAzimuth = { + EPSG_NAME_PARAMETER_AZIMUTH_INITIAL_LINE, + EPSG_CODE_PARAMETER_AZIMUTH_INITIAL_LINE, nullptr, + common::UnitOfMeasure::Type::ANGULAR, "azi"}; + +static const ParamMapping *const paramsLabordeObliqueMercator[] = { + ¶mLatCentreLatOrigin, + ¶mLonCentre, + ¶mLabordeObliqueMercatorAzimuth, + ¶mScaleFactorInitialLine, + ¶mFalseEasting, + ¶mFalseNorthing, + nullptr}; + +static const MethodMapping methodMappings[] = { + {EPSG_NAME_METHOD_TRANSVERSE_MERCATOR, EPSG_CODE_METHOD_TRANSVERSE_MERCATOR, + "Transverse_Mercator", "tmerc", nullptr, paramsNatOriginScale}, + + {EPSG_NAME_METHOD_TRANSVERSE_MERCATOR_SOUTH_ORIENTATED, + EPSG_CODE_METHOD_TRANSVERSE_MERCATOR_SOUTH_ORIENTATED, + "Transverse_Mercator_South_Orientated", "tmerc", "axis=wsu", + paramsNatOriginScale}, + + {PROJ_WKT2_NAME_METHOD_TWO_POINT_EQUIDISTANT, 0, "Two_Point_Equidistant", + "tpeqd", nullptr, paramsTPEQD}, + + {EPSG_NAME_METHOD_TUNISIA_MAPPING_GRID, + EPSG_CODE_METHOD_TUNISIA_MAPPING_GRID, "Tunisia_Mapping_Grid", nullptr, + nullptr, // no proj equivalent + paramsTMG}, + + {EPSG_NAME_METHOD_ALBERS_EQUAL_AREA, EPSG_CODE_METHOD_ALBERS_EQUAL_AREA, + "Albers_Conic_Equal_Area", "aea", nullptr, paramsAEA}, + + {EPSG_NAME_METHOD_LAMBERT_CONIC_CONFORMAL_1SP, + EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_1SP, + "Lambert_Conformal_Conic_1SP", "lcc", nullptr, + []() { + static const ParamMapping paramLatLCC1SP = { + EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + WKT1_LATITUDE_OF_ORIGIN, common::UnitOfMeasure::Type::ANGULAR, + lat_1}; + + static const ParamMapping *const x[] = { + ¶mLatLCC1SP, ¶mLongitudeNatOrigin, ¶mScaleFactor, + ¶mFalseEasting, ¶mFalseNorthing, nullptr, + }; + return x; + }()}, + + {EPSG_NAME_METHOD_LAMBERT_CONIC_CONFORMAL_2SP, + EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP, + "Lambert_Conformal_Conic_2SP", "lcc", nullptr, paramsLCC2SP}, + + {EPSG_NAME_METHOD_LAMBERT_CONIC_CONFORMAL_2SP_MICHIGAN, + EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP_MICHIGAN, + nullptr, // no mapping to WKT1_GDAL + "lcc", nullptr, paramsLCC2SPMichigan}, + + {EPSG_NAME_METHOD_LAMBERT_CONIC_CONFORMAL_2SP_BELGIUM, + EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP_BELGIUM, + "Lambert_Conformal_Conic_2SP_Belgium", "lcc", + nullptr, // FIXME: this is what is done in GDAL, but the formula of + // LCC 2SP + // Belgium in the EPSG 7.2 guidance is difference from the regular + // LCC 2SP + paramsLCC2SP}, + + {EPSG_NAME_METHOD_MODIFIED_AZIMUTHAL_EQUIDISTANT, + EPSG_CODE_METHOD_MODIFIED_AZIMUTHAL_EQUIDISTANT, "Azimuthal_Equidistant", + "aeqd", nullptr, paramsAEQD}, + + {EPSG_NAME_METHOD_GUAM_PROJECTION, EPSG_CODE_METHOD_GUAM_PROJECTION, + nullptr, // no mapping to GDAL WKT1 + "aeqd", "guam", paramsNatOrigin}, + + {EPSG_NAME_METHOD_BONNE, EPSG_CODE_METHOD_BONNE, "Bonne", "bonne", nullptr, + paramsBonne}, + + {EPSG_NAME_METHOD_LAMBERT_CYLINDRICAL_EQUAL_AREA_SPHERICAL, + EPSG_CODE_METHOD_LAMBERT_CYLINDRICAL_EQUAL_AREA_SPHERICAL, + "Cylindrical_Equal_Area", "cea", nullptr, paramsCEA}, + + {EPSG_NAME_METHOD_LAMBERT_CYLINDRICAL_EQUAL_AREA, + EPSG_CODE_METHOD_LAMBERT_CYLINDRICAL_EQUAL_AREA, "Cylindrical_Equal_Area", + "cea", nullptr, paramsCEA}, + + {EPSG_NAME_METHOD_CASSINI_SOLDNER, EPSG_CODE_METHOD_CASSINI_SOLDNER, + "Cassini_Soldner", "cass", nullptr, paramsNatOrigin}, + + {PROJ_WKT2_NAME_METHOD_EQUIDISTANT_CONIC, 0, "Equidistant_Conic", "eqdc", + nullptr, paramsEQDC}, + + {PROJ_WKT2_NAME_METHOD_ECKERT_I, 0, "Eckert_I", "eck1", nullptr, + paramsLonNatOrigin}, + + {PROJ_WKT2_NAME_METHOD_ECKERT_II, 0, "Eckert_II", "eck2", nullptr, + paramsLonNatOrigin}, + + {PROJ_WKT2_NAME_METHOD_ECKERT_III, 0, "Eckert_III", "eck3", nullptr, + paramsLonNatOrigin}, + + {PROJ_WKT2_NAME_METHOD_ECKERT_IV, 0, "Eckert_IV", "eck4", nullptr, + paramsLonNatOrigin}, + + {PROJ_WKT2_NAME_METHOD_ECKERT_V, 0, "Eckert_V", "eck5", nullptr, + paramsLonNatOrigin}, + + {PROJ_WKT2_NAME_METHOD_ECKERT_VI, 0, "Eckert_VI", "eck6", nullptr, + paramsLonNatOrigin}, + + {EPSG_NAME_METHOD_EQUIDISTANT_CYLINDRICAL, + EPSG_CODE_METHOD_EQUIDISTANT_CYLINDRICAL, "Equirectangular", "eqc", + nullptr, paramsEqc}, + + {EPSG_NAME_METHOD_EQUIDISTANT_CYLINDRICAL_SPHERICAL, + EPSG_CODE_METHOD_EQUIDISTANT_CYLINDRICAL_SPHERICAL, "Equirectangular", + "eqc", nullptr, paramsEqc}, + + {PROJ_WKT2_NAME_METHOD_GALL_STEREOGRAPHIC, 0, "Gall_Stereographic", "gall", + nullptr, paramsLonNatOrigin}, + + {PROJ_WKT2_NAME_METHOD_GOODE_HOMOLOSINE, 0, "Goode_Homolosine", "goode", + nullptr, paramsLonNatOrigin}, + + {PROJ_WKT2_NAME_METHOD_INTERRUPTED_GOODE_HOMOLOSINE, 0, + "Interrupted_Goode_Homolosine", "igh", nullptr, paramsLonNatOrigin}, + + // No WKT1 representation fr sweep=x + {PROJ_WKT2_NAME_METHOD_GEOSTATIONARY_SATELLITE_SWEEP_X, 0, nullptr, "geos", + "sweep=x", paramsGeos}, + + {PROJ_WKT2_NAME_METHOD_GEOSTATIONARY_SATELLITE_SWEEP_Y, 0, + "Geostationary_Satellite", "geos", nullptr, paramsGeos}, + + {PROJ_WKT2_NAME_METHOD_GAUSS_SCHREIBER_TRANSVERSE_MERCATOR, 0, + "Gauss_Schreiber_Transverse_Mercator", "gstmerc", nullptr, + paramsNatOriginScale}, + + {PROJ_WKT2_NAME_METHOD_GNOMONIC, 0, "Gnomonic", "gnom", nullptr, + paramsNatOrigin}, + + {EPSG_NAME_METHOD_HOTINE_OBLIQUE_MERCATOR_VARIANT_A, + EPSG_CODE_METHOD_HOTINE_OBLIQUE_MERCATOR_VARIANT_A, + "Hotine_Oblique_Mercator", "omerc", "no_uoff", paramsHomVariantA}, + + {EPSG_NAME_METHOD_HOTINE_OBLIQUE_MERCATOR_VARIANT_B, + EPSG_CODE_METHOD_HOTINE_OBLIQUE_MERCATOR_VARIANT_B, + "Hotine_Oblique_Mercator_Azimuth_Center", "omerc", nullptr, + paramsHomVariantB}, + + {PROJ_WKT2_NAME_METHOD_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN, 0, + "Hotine_Oblique_Mercator_Two_Point_Natural_Origin", "omerc", nullptr, + paramsHomTwoPoint}, + + {PROJ_WKT2_NAME_INTERNATIONAL_MAP_WORLD_POLYCONIC, 0, + "International_Map_of_the_World_Polyconic", "imw_p", nullptr, paramsIMWP}, + + {EPSG_NAME_METHOD_KROVAK_NORTH_ORIENTED, + EPSG_CODE_METHOD_KROVAK_NORTH_ORIENTED, "Krovak", "krovak", nullptr, + krovakParameters}, + + {EPSG_NAME_METHOD_KROVAK, EPSG_CODE_METHOD_KROVAK, "Krovak", "krovak", + "axis=swu", krovakParameters}, + + {EPSG_NAME_METHOD_LAMBERT_AZIMUTHAL_EQUAL_AREA, + EPSG_CODE_METHOD_LAMBERT_AZIMUTHAL_EQUAL_AREA, + "Lambert_Azimuthal_Equal_Area", "laea", nullptr, paramsLaea}, + + {EPSG_NAME_METHOD_LAMBERT_AZIMUTHAL_EQUAL_AREA_SPHERICAL, + EPSG_CODE_METHOD_LAMBERT_AZIMUTHAL_EQUAL_AREA_SPHERICAL, + "Lambert_Azimuthal_Equal_Area", "laea", nullptr, paramsLaea}, + + {PROJ_WKT2_NAME_METHOD_MILLER_CYLINDRICAL, 0, "Miller_Cylindrical", "mill", + "R_A", paramsMiller}, + + {EPSG_NAME_METHOD_MERCATOR_VARIANT_A, EPSG_CODE_METHOD_MERCATOR_VARIANT_A, + "Mercator_1SP", "merc", nullptr, paramsMerc1SP}, + + {EPSG_NAME_METHOD_MERCATOR_VARIANT_B, EPSG_CODE_METHOD_MERCATOR_VARIANT_B, + "Mercator_2SP", "merc", nullptr, paramsMerc2SP}, + + {EPSG_NAME_METHOD_POPULAR_VISUALISATION_PSEUDO_MERCATOR, + EPSG_CODE_METHOD_POPULAR_VISUALISATION_PSEUDO_MERCATOR, + "Popular_Visualisation_Pseudo_Mercator", // particular case actually + // handled manually + "webmerc", nullptr, paramsNatOrigin}, + + {PROJ_WKT2_NAME_METHOD_MOLLWEIDE, 0, "Mollweide", "moll", nullptr, + paramsLonNatOrigin}, + + {EPSG_NAME_METHOD_NZMG, EPSG_CODE_METHOD_NZMG, "New_Zealand_Map_Grid", + "nzmg", nullptr, paramsNatOrigin}, + + { + EPSG_NAME_METHOD_OBLIQUE_STEREOGRAPHIC, + EPSG_CODE_METHOD_OBLIQUE_STEREOGRAPHIC, "Oblique_Stereographic", + "sterea", nullptr, paramsObliqueStereo, + }, + + {EPSG_NAME_METHOD_ORTHOGRAPHIC, EPSG_CODE_METHOD_ORTHOGRAPHIC, + "Orthographic", "ortho", nullptr, paramsNatOrigin}, + + {EPSG_NAME_METHOD_AMERICAN_POLYCONIC, EPSG_CODE_METHOD_AMERICAN_POLYCONIC, + "Polyconic", "poly", nullptr, paramsNatOrigin}, + + {EPSG_NAME_METHOD_POLAR_STEREOGRAPHIC_VARIANT_A, + EPSG_CODE_METHOD_POLAR_STEREOGRAPHIC_VARIANT_A, "Polar_Stereographic", + "stere", nullptr, paramsObliqueStereo}, + + {EPSG_NAME_METHOD_POLAR_STEREOGRAPHIC_VARIANT_B, + EPSG_CODE_METHOD_POLAR_STEREOGRAPHIC_VARIANT_B, "Polar_Stereographic", + "stere", nullptr, paramsPolarStereo}, + + {PROJ_WKT2_NAME_METHOD_ROBINSON, 0, "Robinson", "robin", nullptr, + paramsLonNatOriginLongitudeCentre}, + + {PROJ_WKT2_NAME_METHOD_SINUSOIDAL, 0, "Sinusoidal", "sinu", nullptr, + paramsLonNatOriginLongitudeCentre}, + + {PROJ_WKT2_NAME_METHOD_STEREOGRAPHIC, 0, "Stereographic", "stere", nullptr, + paramsObliqueStereo}, + + {PROJ_WKT2_NAME_METHOD_VAN_DER_GRINTEN, 0, "VanDerGrinten", "vandg", "R_A", + paramsLonNatOrigin}, + + {PROJ_WKT2_NAME_METHOD_WAGNER_I, 0, "Wagner_I", "wag1", nullptr, + paramsLonNatOrigin}, + + {PROJ_WKT2_NAME_METHOD_WAGNER_II, 0, "Wagner_II", "wag2", nullptr, + paramsLonNatOrigin}, + + {PROJ_WKT2_NAME_METHOD_WAGNER_III, 0, "Wagner_III", "wag3", nullptr, + paramsWag3}, + + {PROJ_WKT2_NAME_METHOD_WAGNER_IV, 0, "Wagner_IV", "wag4", nullptr, + paramsLonNatOrigin}, + + {PROJ_WKT2_NAME_METHOD_WAGNER_V, 0, "Wagner_V", "wag5", nullptr, + paramsLonNatOrigin}, + + {PROJ_WKT2_NAME_METHOD_WAGNER_VI, 0, "Wagner_VI", "wag6", nullptr, + paramsLonNatOrigin}, + + {PROJ_WKT2_NAME_METHOD_WAGNER_VII, 0, "Wagner_VII", "wag7", nullptr, + paramsLonNatOrigin}, + + {PROJ_WKT2_NAME_METHOD_QUADRILATERALIZED_SPHERICAL_CUBE, 0, + "Quadrilateralized_Spherical_Cube", "qsc", nullptr, paramsNatOrigin}, + + {PROJ_WKT2_NAME_METHOD_SPHERICAL_CROSS_TRACK_HEIGHT, 0, + "Spherical_Cross_Track_Height", "sch", nullptr, paramsSch}, + + // The following methods have just the WKT <--> PROJ string mapping, but + // no setter. Similarly to GDAL + + {"Aitoff", 0, "Aitoff", "aitoff", nullptr, paramsLonNatOrigin}, + + {"Winkel I", 0, "Winkel_I", "wink1", nullptr, paramsWink1}, + + {"Winkel II", 0, "Winkel_II", "wink2", nullptr, paramsWink2}, + + {"Winkel Tripel", 0, "Winkel_Tripel", "wintri", nullptr, paramsWink2}, + + {"Craster Parabolic", 0, "Craster_Parabolic", "crast", nullptr, + paramsLonNatOrigin}, + + {"Loximuthal", 0, "Loximuthal", "loxim", nullptr, paramsLoxim}, + + {"Quartic Authalic", 0, "Quartic_Authalic", "qua_aut", nullptr, + paramsLonNatOrigin}, + + {EPSG_NAME_METHOD_EQUAL_EARTH, EPSG_CODE_METHOD_EQUAL_EARTH, nullptr, + "eqearth", nullptr, paramsLonNatOrigin}, + + {EPSG_NAME_METHOD_LABORDE_OBLIQUE_MERCATOR, + EPSG_CODE_METHOD_LABORDE_OBLIQUE_MERCATOR, nullptr, "labrd", nullptr, + paramsLabordeObliqueMercator}, + +}; + +#define METHOD_NAME_CODE(method) \ + { EPSG_NAME_METHOD_##method, EPSG_CODE_METHOD_##method } + +static const struct MethodNameCode { + const char *name; + int epsg_code; +} methodNameCodes[] = { + // Projection methods + METHOD_NAME_CODE(TRANSVERSE_MERCATOR), + METHOD_NAME_CODE(TRANSVERSE_MERCATOR_SOUTH_ORIENTATED), + METHOD_NAME_CODE(LAMBERT_CONIC_CONFORMAL_1SP), METHOD_NAME_CODE(NZMG), + METHOD_NAME_CODE(TUNISIA_MAPPING_GRID), METHOD_NAME_CODE(ALBERS_EQUAL_AREA), + METHOD_NAME_CODE(LAMBERT_CONIC_CONFORMAL_2SP), + METHOD_NAME_CODE(LAMBERT_CONIC_CONFORMAL_2SP_BELGIUM), + METHOD_NAME_CODE(LAMBERT_CONIC_CONFORMAL_2SP_MICHIGAN), + METHOD_NAME_CODE(MODIFIED_AZIMUTHAL_EQUIDISTANT), + METHOD_NAME_CODE(GUAM_PROJECTION), METHOD_NAME_CODE(BONNE), + METHOD_NAME_CODE(LAMBERT_CYLINDRICAL_EQUAL_AREA_SPHERICAL), + METHOD_NAME_CODE(LAMBERT_CYLINDRICAL_EQUAL_AREA), + METHOD_NAME_CODE(CASSINI_SOLDNER), + METHOD_NAME_CODE(EQUIDISTANT_CYLINDRICAL), + METHOD_NAME_CODE(EQUIDISTANT_CYLINDRICAL_SPHERICAL), + METHOD_NAME_CODE(HOTINE_OBLIQUE_MERCATOR_VARIANT_A), + METHOD_NAME_CODE(HOTINE_OBLIQUE_MERCATOR_VARIANT_B), + METHOD_NAME_CODE(KROVAK_NORTH_ORIENTED), METHOD_NAME_CODE(KROVAK), + METHOD_NAME_CODE(LAMBERT_AZIMUTHAL_EQUAL_AREA), + METHOD_NAME_CODE(POPULAR_VISUALISATION_PSEUDO_MERCATOR), + METHOD_NAME_CODE(MERCATOR_VARIANT_A), METHOD_NAME_CODE(MERCATOR_VARIANT_B), + METHOD_NAME_CODE(OBLIQUE_STEREOGRAPHIC), + METHOD_NAME_CODE(AMERICAN_POLYCONIC), + METHOD_NAME_CODE(POLAR_STEREOGRAPHIC_VARIANT_A), + METHOD_NAME_CODE(POLAR_STEREOGRAPHIC_VARIANT_B), + METHOD_NAME_CODE(EQUAL_EARTH), METHOD_NAME_CODE(LABORDE_OBLIQUE_MERCATOR), + // Other conversions + METHOD_NAME_CODE(CHANGE_VERTICAL_UNIT), + METHOD_NAME_CODE(AXIS_ORDER_REVERSAL_2D), + METHOD_NAME_CODE(AXIS_ORDER_REVERSAL_3D), + METHOD_NAME_CODE(GEOGRAPHIC_GEOCENTRIC), + // Transformations + METHOD_NAME_CODE(LONGITUDE_ROTATION), + METHOD_NAME_CODE(AFFINE_PARAMETRIC_TRANSFORMATION), + METHOD_NAME_CODE(COORDINATE_FRAME_GEOCENTRIC), + METHOD_NAME_CODE(COORDINATE_FRAME_GEOGRAPHIC_2D), + METHOD_NAME_CODE(COORDINATE_FRAME_GEOGRAPHIC_3D), + METHOD_NAME_CODE(POSITION_VECTOR_GEOCENTRIC), + METHOD_NAME_CODE(POSITION_VECTOR_GEOGRAPHIC_2D), + METHOD_NAME_CODE(POSITION_VECTOR_GEOGRAPHIC_3D), + METHOD_NAME_CODE(GEOCENTRIC_TRANSLATION_GEOCENTRIC), + METHOD_NAME_CODE(GEOCENTRIC_TRANSLATION_GEOGRAPHIC_2D), + METHOD_NAME_CODE(GEOCENTRIC_TRANSLATION_GEOGRAPHIC_3D), + METHOD_NAME_CODE(TIME_DEPENDENT_COORDINATE_FRAME_GEOCENTRIC), + METHOD_NAME_CODE(TIME_DEPENDENT_COORDINATE_FRAME_GEOGRAPHIC_2D), + METHOD_NAME_CODE(TIME_DEPENDENT_COORDINATE_FRAME_GEOGRAPHIC_3D), + METHOD_NAME_CODE(TIME_DEPENDENT_POSITION_VECTOR_GEOCENTRIC), + METHOD_NAME_CODE(TIME_DEPENDENT_POSITION_VECTOR_GEOGRAPHIC_2D), + METHOD_NAME_CODE(TIME_DEPENDENT_POSITION_VECTOR_GEOGRAPHIC_3D), + METHOD_NAME_CODE(MOLODENSKY_BADEKAS_CF_GEOCENTRIC), + METHOD_NAME_CODE(MOLODENSKY_BADEKAS_CF_GEOGRAPHIC_2D), + METHOD_NAME_CODE(MOLODENSKY_BADEKAS_CF_GEOGRAPHIC_3D), + METHOD_NAME_CODE(MOLODENSKY_BADEKAS_PV_GEOCENTRIC), + METHOD_NAME_CODE(MOLODENSKY_BADEKAS_PV_GEOGRAPHIC_2D), + METHOD_NAME_CODE(MOLODENSKY_BADEKAS_PV_GEOGRAPHIC_3D), + METHOD_NAME_CODE(MOLODENSKY), METHOD_NAME_CODE(ABRIDGED_MOLODENSKY), + METHOD_NAME_CODE(GEOGRAPHIC2D_OFFSETS), + METHOD_NAME_CODE(GEOGRAPHIC2D_WITH_HEIGHT_OFFSETS), + METHOD_NAME_CODE(GEOGRAPHIC3D_OFFSETS), METHOD_NAME_CODE(VERTICAL_OFFSET), + METHOD_NAME_CODE(NTV2), METHOD_NAME_CODE(NTV1), METHOD_NAME_CODE(NADCON), + METHOD_NAME_CODE(VERTCON), +}; + +#define PARAM_NAME_CODE(method) \ + { EPSG_NAME_PARAMETER_##method, EPSG_CODE_PARAMETER_##method } + +static const struct ParamNameCode { + const char *name; + int epsg_code; +} paramNameCodes[] = { + // Parameters of projection methods + PARAM_NAME_CODE(COLATITUDE_CONE_AXIS), + PARAM_NAME_CODE(LATITUDE_OF_NATURAL_ORIGIN), + PARAM_NAME_CODE(LONGITUDE_OF_NATURAL_ORIGIN), + PARAM_NAME_CODE(SCALE_FACTOR_AT_NATURAL_ORIGIN), + PARAM_NAME_CODE(FALSE_EASTING), PARAM_NAME_CODE(FALSE_NORTHING), + PARAM_NAME_CODE(LATITUDE_PROJECTION_CENTRE), + PARAM_NAME_CODE(LONGITUDE_PROJECTION_CENTRE), + PARAM_NAME_CODE(AZIMUTH_INITIAL_LINE), + PARAM_NAME_CODE(ANGLE_RECTIFIED_TO_SKEW_GRID), + PARAM_NAME_CODE(SCALE_FACTOR_INITIAL_LINE), + PARAM_NAME_CODE(EASTING_PROJECTION_CENTRE), + PARAM_NAME_CODE(NORTHING_PROJECTION_CENTRE), + PARAM_NAME_CODE(LATITUDE_PSEUDO_STANDARD_PARALLEL), + PARAM_NAME_CODE(SCALE_FACTOR_PSEUDO_STANDARD_PARALLEL), + PARAM_NAME_CODE(LATITUDE_FALSE_ORIGIN), + PARAM_NAME_CODE(LONGITUDE_FALSE_ORIGIN), + PARAM_NAME_CODE(LATITUDE_1ST_STD_PARALLEL), + PARAM_NAME_CODE(LATITUDE_2ND_STD_PARALLEL), + PARAM_NAME_CODE(EASTING_FALSE_ORIGIN), + PARAM_NAME_CODE(NORTHING_FALSE_ORIGIN), + PARAM_NAME_CODE(LATITUDE_STD_PARALLEL), + PARAM_NAME_CODE(LONGITUDE_OF_ORIGIN), + PARAM_NAME_CODE(ELLIPSOID_SCALE_FACTOR), + // Parameters of transformations + PARAM_NAME_CODE(SEMI_MAJOR_AXIS_DIFFERENCE), + PARAM_NAME_CODE(FLATTENING_DIFFERENCE), + PARAM_NAME_CODE(LATITUDE_LONGITUDE_DIFFERENCE_FILE), + PARAM_NAME_CODE(GEOID_CORRECTION_FILENAME), + PARAM_NAME_CODE(VERTICAL_OFFSET_FILE), + PARAM_NAME_CODE(LATITUDE_DIFFERENCE_FILE), + PARAM_NAME_CODE(LONGITUDE_DIFFERENCE_FILE), + PARAM_NAME_CODE(UNIT_CONVERSION_SCALAR), PARAM_NAME_CODE(LATITUDE_OFFSET), + PARAM_NAME_CODE(LONGITUDE_OFFSET), PARAM_NAME_CODE(VERTICAL_OFFSET), + PARAM_NAME_CODE(GEOID_UNDULATION), PARAM_NAME_CODE(A0), PARAM_NAME_CODE(A1), + PARAM_NAME_CODE(A2), PARAM_NAME_CODE(B0), PARAM_NAME_CODE(B1), + PARAM_NAME_CODE(B2), PARAM_NAME_CODE(X_AXIS_TRANSLATION), + PARAM_NAME_CODE(Y_AXIS_TRANSLATION), PARAM_NAME_CODE(Z_AXIS_TRANSLATION), + PARAM_NAME_CODE(X_AXIS_ROTATION), PARAM_NAME_CODE(Y_AXIS_ROTATION), + PARAM_NAME_CODE(Z_AXIS_ROTATION), PARAM_NAME_CODE(SCALE_DIFFERENCE), + PARAM_NAME_CODE(RATE_X_AXIS_TRANSLATION), + PARAM_NAME_CODE(RATE_Y_AXIS_TRANSLATION), + PARAM_NAME_CODE(RATE_Z_AXIS_TRANSLATION), + PARAM_NAME_CODE(RATE_X_AXIS_ROTATION), + PARAM_NAME_CODE(RATE_Y_AXIS_ROTATION), + PARAM_NAME_CODE(RATE_Z_AXIS_ROTATION), + PARAM_NAME_CODE(RATE_SCALE_DIFFERENCE), PARAM_NAME_CODE(REFERENCE_EPOCH), + PARAM_NAME_CODE(TRANSFORMATION_REFERENCE_EPOCH), + PARAM_NAME_CODE(ORDINATE_1_EVAL_POINT), + PARAM_NAME_CODE(ORDINATE_2_EVAL_POINT), + PARAM_NAME_CODE(ORDINATE_3_EVAL_POINT), +}; + +// end of anonymous namespace +} + +// --------------------------------------------------------------------------- + +//! @endcond + +#endif // COORDINATEOPERATION_CONSTANTS_HH_INCLUDED diff --git a/include/proj/internal/coordinateoperation_internal.hpp b/include/proj/internal/coordinateoperation_internal.hpp new file mode 100644 index 00000000..83e1e987 --- /dev/null +++ b/include/proj/internal/coordinateoperation_internal.hpp @@ -0,0 +1,274 @@ +/****************************************************************************** + * + * Project: PROJ + * Purpose: ISO19111:2018 implementation + * Author: Even Rouault <even dot rouault at spatialys dot com> + * + ****************************************************************************** + * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ****************************************************************************/ + +#ifndef FROM_PROJ_CPP +#error This file should only be included from a PROJ cpp file +#endif + +#ifndef COORDINATEOPERATION_INTERNAL_HH_INCLUDED +#define COORDINATEOPERATION_INTERNAL_HH_INCLUDED + +#include "proj/coordinateoperation.hpp" + +#include <vector> + +//! @cond Doxygen_Suppress + +NS_PROJ_START + +namespace operation { + +struct ParamMapping { + const char *wkt2_name; + const int epsg_code; + const char *wkt1_name; + const common::UnitOfMeasure::Type unit_type; + const char *proj_name; +}; + +struct MethodMapping { + const char *wkt2_name; + const int epsg_code; + const char *wkt1_name; + const char *proj_name_main; + const char *proj_name_aux; + const ParamMapping *const *params; +}; + +const MethodMapping *getMapping(int epsg_code) noexcept; +const MethodMapping *getMappingFromWKT1(const std::string &wkt1_name) noexcept; +const MethodMapping *getMapping(const char *wkt2_name) noexcept; +const MethodMapping *getMapping(const OperationMethod *method) noexcept; +std::vector<const MethodMapping *> +getMappingsFromPROJName(const std::string &projName); +const ParamMapping *getMapping(const MethodMapping *mapping, + const OperationParameterValue *param); +const ParamMapping *getMappingFromWKT1(const MethodMapping *mapping, + const std::string &wkt1_name); +// --------------------------------------------------------------------------- + +struct ESRIParamMapping { + const char *esri_name; + const char *wkt2_name; + int epsg_code; + float fixed_value; +}; + +struct ESRIMethodMapping { + const char *esri_name; + const char *wkt2_name; + int epsg_code; + const ESRIParamMapping *const params; +}; + +std::vector<const ESRIMethodMapping *> +getMappingsFromESRI(const std::string &esri_name); + +// --------------------------------------------------------------------------- + +bool isAxisOrderReversal(int methodEPSGCode); + +// --------------------------------------------------------------------------- + +class InverseCoordinateOperation; +/** Shared pointer of InverseCoordinateOperation */ +using InverseCoordinateOperationPtr = + std::shared_ptr<InverseCoordinateOperation>; +/** Non-null shared pointer of InverseCoordinateOperation */ +using InverseCoordinateOperationNNPtr = util::nn<InverseCoordinateOperationPtr>; + +/** \brief Inverse operation of a CoordinateOperation. + * + * This is used when there is no straightforward way of building another + * subclass of CoordinateOperation that models the inverse operation. + */ +class InverseCoordinateOperation : virtual public CoordinateOperation { + public: + InverseCoordinateOperation(const CoordinateOperationNNPtr &forwardOperation, + bool wktSupportsInversion); + + ~InverseCoordinateOperation() override; + + void _exportToPROJString(io::PROJStringFormatter *formatter) + const override; // throw(FormattingException) + + bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + + CoordinateOperationNNPtr inverse() const override; + + protected: + CoordinateOperationNNPtr forwardOperation_; + bool wktSupportsInversion_; + + void setPropertiesFromForward(); +}; + +// --------------------------------------------------------------------------- + +/** \brief Inverse of a conversion. */ +class InverseConversion : public Conversion, public InverseCoordinateOperation { + public: + explicit InverseConversion(const ConversionNNPtr &forward); + + ~InverseConversion() override; + + void _exportToWKT(io::WKTFormatter *formatter) const override { + Conversion::_exportToWKT(formatter); + } + + void + _exportToPROJString(io::PROJStringFormatter *formatter) const override { + InverseCoordinateOperation::_exportToPROJString(formatter); + } + + bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override { + return InverseCoordinateOperation::_isEquivalentTo(other, criterion); + } + + CoordinateOperationNNPtr inverse() const override { + return InverseCoordinateOperation::inverse(); + } + + ConversionNNPtr inverseAsConversion() const; + +#ifdef _MSC_VER + // To avoid a warning C4250: 'osgeo::proj::operation::InverseConversion': + // inherits + // 'osgeo::proj::operation::SingleOperation::osgeo::proj::operation::SingleOperation::gridsNeeded' + // via dominance + std::set<GridDescription> + gridsNeeded(const io::DatabaseContextPtr &databaseContext) const override { + return SingleOperation::gridsNeeded(databaseContext); + } +#endif + + static CoordinateOperationNNPtr create(const ConversionNNPtr &forward); +}; + +// --------------------------------------------------------------------------- + +/** \brief Inverse of a transformation. */ +class InverseTransformation : public Transformation, + public InverseCoordinateOperation { + public: + explicit InverseTransformation(const TransformationNNPtr &forward); + + ~InverseTransformation() override; + + void _exportToWKT(io::WKTFormatter *formatter) const override; + + void + _exportToPROJString(io::PROJStringFormatter *formatter) const override { + return InverseCoordinateOperation::_exportToPROJString(formatter); + } + + bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override { + return InverseCoordinateOperation::_isEquivalentTo(other, criterion); + } + + CoordinateOperationNNPtr inverse() const override { + return InverseCoordinateOperation::inverse(); + } + +#ifdef _MSC_VER + // To avoid a warning C4250: + // 'osgeo::proj::operation::InverseTransformation': inherits + // 'osgeo::proj::operation::SingleOperation::osgeo::proj::operation::SingleOperation::gridsNeeded' + // via dominance + std::set<GridDescription> + gridsNeeded(const io::DatabaseContextPtr &databaseContext) const override { + return SingleOperation::gridsNeeded(databaseContext); + } +#endif + + static TransformationNNPtr create(const TransformationNNPtr &forward); +}; + +// --------------------------------------------------------------------------- + +class PROJBasedOperation; +/** Shared pointer of PROJBasedOperation */ +using PROJBasedOperationPtr = std::shared_ptr<PROJBasedOperation>; +/** Non-null shared pointer of PROJBasedOperation */ +using PROJBasedOperationNNPtr = util::nn<PROJBasedOperationPtr>; + +/** \brief A PROJ-string based coordinate operation. + */ +class PROJBasedOperation : public SingleOperation { + public: + ~PROJBasedOperation() override; + + void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + + CoordinateOperationNNPtr inverse() const override; + + static PROJBasedOperationNNPtr + create(const util::PropertyMap &properties, const std::string &PROJString, + const crs::CRSPtr &sourceCRS, const crs::CRSPtr &targetCRS, + const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies); + + static PROJBasedOperationNNPtr + create(const util::PropertyMap &properties, + const io::IPROJStringExportableNNPtr &projExportable, bool inverse, + const crs::CRSNNPtr &sourceCRS, const crs::CRSNNPtr &targetCRS, + const std::vector<metadata::PositionalAccuracyNNPtr> &accuracies); + + std::set<GridDescription> + gridsNeeded(const io::DatabaseContextPtr &databaseContext) const override; + + protected: + PROJBasedOperation(const OperationMethodNNPtr &methodIn, + const std::vector<GeneralParameterValueNNPtr> &values); + + void _exportToPROJString(io::PROJStringFormatter *formatter) + const override; // throw(FormattingException) + + INLINED_MAKE_SHARED + + private: + io::IPROJStringExportablePtr projStringExportable_{}; + bool inverse_ = false; +}; + +} // namespace operation + +NS_PROJ_END + +//! @endcond + +#endif // COORDINATEOPERATION_INTERNAL_HH_INCLUDED diff --git a/include/proj/internal/coordinatesystem_internal.hpp b/include/proj/internal/coordinatesystem_internal.hpp new file mode 100644 index 00000000..63c5f7af --- /dev/null +++ b/include/proj/internal/coordinatesystem_internal.hpp @@ -0,0 +1,104 @@ +/****************************************************************************** + * + * Project: PROJ + * Purpose: ISO19111:2018 implementation + * Author: Even Rouault <even dot rouault at spatialys dot com> + * + ****************************************************************************** + * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ****************************************************************************/ + +#ifndef FROM_PROJ_CPP +#error This file should only be included from a PROJ cpp file +#endif + +#ifndef COORDINATESYSTEM_INTERNAL_HH_INCLUDED +#define COORDINATESYSTEM_INTERNAL_HH_INCLUDED + +#include "proj/util.hpp" + +#include <map> +#include <set> +#include <string> + +//! @cond Doxygen_Suppress + +NS_PROJ_START + +namespace cs { + +// --------------------------------------------------------------------------- + +class AxisDirectionWKT1 : public util::CodeList { + public: + static const AxisDirectionWKT1 *valueOf(const std::string &nameIn); + + static const AxisDirectionWKT1 NORTH; + static const AxisDirectionWKT1 SOUTH; + static const AxisDirectionWKT1 EAST; + static const AxisDirectionWKT1 WEST; + static const AxisDirectionWKT1 UP; + static const AxisDirectionWKT1 DOWN; + static const AxisDirectionWKT1 OTHER; + + private: + explicit AxisDirectionWKT1(const std::string &nameIn); + + static std::map<std::string, const AxisDirectionWKT1 *> registry; +}; + +// --------------------------------------------------------------------------- + +class AxisName { + public: + static const std::string Longitude; + static const std::string Latitude; + static const std::string Easting; + static const std::string Northing; + static const std::string Westing; + static const std::string Southing; + static const std::string Ellipsoidal_height; + static const std::string Geocentric_X; + static const std::string Geocentric_Y; + static const std::string Geocentric_Z; +}; + +// --------------------------------------------------------------------------- + +class AxisAbbreviation { + public: + static const std::string lon; + static const std::string lat; + static const std::string E; + static const std::string N; + static const std::string h; + static const std::string X; + static const std::string Y; + static const std::string Z; +}; + +} // namespace cs + +NS_PROJ_END + +//! @endcond + +#endif // COORDINATESYSTEM_INTERNAL_HH_INCLUDED diff --git a/include/proj/internal/esri_projection_mappings.hpp b/include/proj/internal/esri_projection_mappings.hpp new file mode 100644 index 00000000..4ceeb300 --- /dev/null +++ b/include/proj/internal/esri_projection_mappings.hpp @@ -0,0 +1,887 @@ +// This file was generated by scripts/build_esri_projection_mapping.py. DO NOT +// EDIT ! + +#ifndef FROM_COORDINATE_OPERATION_CPP +#error This file should only be included from coordinateoperation.cpp +#endif + +#ifndef ESRI_PROJECTION_MAPPINGS_HH_INCLUDED +#define ESRI_PROJECTION_MAPPINGS_HH_INCLUDED + +#include "coordinateoperation_internal.hpp" + +//! @cond Doxygen_Suppress + +// --------------------------------------------------------------------------- + +// anonymous namespace +namespace { + +using namespace ::NS_PROJ; +using namespace ::NS_PROJ::operation; + +static const ESRIParamMapping paramsESRI_Plate_Carree[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Equidistant_Cylindrical[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Standard_Parallel_1", EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Miller_Cylindrical[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Mercator[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Standard_Parallel_1", EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Gauss_Kruger[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Scale_Factor", EPSG_NAME_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN, 0.0}, + {"Latitude_Of_Origin", EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Transverse_Mercator[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Scale_Factor", EPSG_NAME_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN, 0.0}, + {"Latitude_Of_Origin", EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Albers[] = { + {"False_Easting", EPSG_NAME_PARAMETER_EASTING_FALSE_ORIGIN, + EPSG_CODE_PARAMETER_EASTING_FALSE_ORIGIN, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_NORTHING_FALSE_ORIGIN, + EPSG_CODE_PARAMETER_NORTHING_FALSE_ORIGIN, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_FALSE_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_FALSE_ORIGIN, 0.0}, + {"Standard_Parallel_1", EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL, 0.0}, + {"Standard_Parallel_2", EPSG_NAME_PARAMETER_LATITUDE_2ND_STD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_2ND_STD_PARALLEL, 0.0}, + {"Latitude_Of_Origin", EPSG_NAME_PARAMETER_LATITUDE_FALSE_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_FALSE_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Sinusoidal[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Mollweide[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Eckert_I[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Eckert_II[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Eckert_III[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Eckert_IV[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Eckert_V[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Eckert_VI[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Gall_Stereographic[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Winkel_I[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Standard_Parallel_1", EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Winkel_II[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Standard_Parallel_1", EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Lambert_Conformal_Conic_alt1[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Standard_Parallel_1", EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Scale_Factor", EPSG_NAME_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN, 0.0}, + {"Latitude_Of_Origin", EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; +static const ESRIParamMapping paramsESRI_Lambert_Conformal_Conic_alt2[] = { + {"False_Easting", EPSG_NAME_PARAMETER_EASTING_FALSE_ORIGIN, + EPSG_CODE_PARAMETER_EASTING_FALSE_ORIGIN, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_NORTHING_FALSE_ORIGIN, + EPSG_CODE_PARAMETER_NORTHING_FALSE_ORIGIN, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_FALSE_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_FALSE_ORIGIN, 0.0}, + {"Standard_Parallel_1", EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL, 0.0}, + {"Standard_Parallel_2", EPSG_NAME_PARAMETER_LATITUDE_2ND_STD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_2ND_STD_PARALLEL, 0.0}, + {"Latitude_Of_Origin", EPSG_NAME_PARAMETER_LATITUDE_FALSE_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_FALSE_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; +static const ESRIParamMapping paramsESRI_Lambert_Conformal_Conic_alt3[] = { + {"False_Easting", EPSG_NAME_PARAMETER_EASTING_FALSE_ORIGIN, + EPSG_CODE_PARAMETER_EASTING_FALSE_ORIGIN, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_NORTHING_FALSE_ORIGIN, + EPSG_CODE_PARAMETER_NORTHING_FALSE_ORIGIN, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_FALSE_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_FALSE_ORIGIN, 0.0}, + {"Standard_Parallel_1", EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL, 0.0}, + {"Standard_Parallel_2", EPSG_NAME_PARAMETER_LATITUDE_2ND_STD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_2ND_STD_PARALLEL, 0.0}, + {"Scale_Factor", nullptr, 0, 1.0}, + {"Latitude_Of_Origin", EPSG_NAME_PARAMETER_LATITUDE_FALSE_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_FALSE_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; +static const ESRIParamMapping paramsESRI_Lambert_Conformal_Conic_alt4[] = { + {"False_Easting", EPSG_NAME_PARAMETER_EASTING_FALSE_ORIGIN, + EPSG_CODE_PARAMETER_EASTING_FALSE_ORIGIN, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_NORTHING_FALSE_ORIGIN, + EPSG_CODE_PARAMETER_NORTHING_FALSE_ORIGIN, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_FALSE_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_FALSE_ORIGIN, 0.0}, + {"Standard_Parallel_1", EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL, 0.0}, + {"Standard_Parallel_2", EPSG_NAME_PARAMETER_LATITUDE_2ND_STD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_2ND_STD_PARALLEL, 0.0}, + {"Scale_Factor", EPSG_NAME_PARAMETER_ELLIPSOID_SCALE_FACTOR, + EPSG_CODE_PARAMETER_ELLIPSOID_SCALE_FACTOR, 0.0}, + {"Latitude_Of_Origin", EPSG_NAME_PARAMETER_LATITUDE_FALSE_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_FALSE_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Polyconic[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Latitude_Of_Origin", EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Quartic_Authalic[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Loximuthal[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Central_Parallel", EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Bonne[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Standard_Parallel_1", EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping + paramsESRI_Hotine_Oblique_Mercator_Two_Point_Natural_Origin[] = { + {"False_Easting", EPSG_NAME_PARAMETER_EASTING_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_EASTING_PROJECTION_CENTRE, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_NORTHING_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_NORTHING_PROJECTION_CENTRE, 0.0}, + {"Latitude_Of_1st_Point", "Latitude of 1st point", 0, 0.0}, + {"Latitude_Of_2nd_Point", "Latitude of 2nd point", 0, 0.0}, + {"Scale_Factor", EPSG_NAME_PARAMETER_SCALE_FACTOR_INITIAL_LINE, + EPSG_CODE_PARAMETER_SCALE_FACTOR_INITIAL_LINE, 0.0}, + {"Longitude_Of_1st_Point", "Longitude of 1st point", 0, 0.0}, + {"Longitude_Of_2nd_Point", "Longitude of 2nd point", 0, 0.0}, + {"Latitude_Of_Center", EPSG_NAME_PARAMETER_LATITUDE_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_LATITUDE_PROJECTION_CENTRE, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Stereographic[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Scale_Factor", EPSG_NAME_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN, 0.0}, + {"Latitude_Of_Origin", EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Equidistant_Conic[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Standard_Parallel_1", EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL, 0.0}, + {"Standard_Parallel_2", EPSG_NAME_PARAMETER_LATITUDE_2ND_STD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_2ND_STD_PARALLEL, 0.0}, + {"Latitude_Of_Origin", EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Cassini[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Scale_Factor", nullptr, 0, 1.0}, + {"Latitude_Of_Origin", EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Van_der_Grinten_I[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Robinson[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Two_Point_Equidistant[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Latitude_Of_1st_Point", "Latitude of 1st point", 0, 0.0}, + {"Latitude_Of_2nd_Point", "Latitude of 2nd point", 0, 0.0}, + {"Longitude_Of_1st_Point", "Longitude of 1st point", 0, 0.0}, + {"Longitude_Of_2nd_Point", "Longitude of 2nd point", 0, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Azimuthal_Equidistant[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Latitude_Of_Origin", EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Lambert_Azimuthal_Equal_Area[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Latitude_Of_Origin", EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Cylindrical_Equal_Area[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Standard_Parallel_1", EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping + paramsESRI_Hotine_Oblique_Mercator_Two_Point_Center[] = { + {"False_Easting", EPSG_NAME_PARAMETER_EASTING_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_EASTING_PROJECTION_CENTRE, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_NORTHING_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_NORTHING_PROJECTION_CENTRE, 0.0}, + {"Latitude_Of_1st_Point", "Latitude of 1st point", 0, 0.0}, + {"Latitude_Of_2nd_Point", "Latitude of 2nd point", 0, 0.0}, + {"Scale_Factor", EPSG_NAME_PARAMETER_SCALE_FACTOR_INITIAL_LINE, + EPSG_CODE_PARAMETER_SCALE_FACTOR_INITIAL_LINE, 0.0}, + {"Longitude_Of_1st_Point", "Longitude of 1st point", 0, 0.0}, + {"Longitude_Of_2nd_Point", "Longitude of 2nd point", 0, 0.0}, + {"Latitude_Of_Origin", EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping + paramsESRI_Hotine_Oblique_Mercator_Azimuth_Natural_Origin[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Scale_Factor", EPSG_NAME_PARAMETER_SCALE_FACTOR_INITIAL_LINE, + EPSG_CODE_PARAMETER_SCALE_FACTOR_INITIAL_LINE, 0.0}, + {"Azimuth", EPSG_NAME_PARAMETER_AZIMUTH_INITIAL_LINE, + EPSG_CODE_PARAMETER_AZIMUTH_INITIAL_LINE, 0.0}, + {"Longitude_Of_Center", EPSG_NAME_PARAMETER_LONGITUDE_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_LONGITUDE_PROJECTION_CENTRE, 0.0}, + {"Latitude_Of_Center", EPSG_NAME_PARAMETER_LATITUDE_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_LATITUDE_PROJECTION_CENTRE, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping + paramsESRI_Hotine_Oblique_Mercator_Azimuth_Center[] = { + {"False_Easting", EPSG_NAME_PARAMETER_EASTING_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_EASTING_PROJECTION_CENTRE, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_NORTHING_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_NORTHING_PROJECTION_CENTRE, 0.0}, + {"Scale_Factor", EPSG_NAME_PARAMETER_SCALE_FACTOR_INITIAL_LINE, + EPSG_CODE_PARAMETER_SCALE_FACTOR_INITIAL_LINE, 0.0}, + {"Azimuth", EPSG_NAME_PARAMETER_AZIMUTH_INITIAL_LINE, + EPSG_CODE_PARAMETER_AZIMUTH_INITIAL_LINE, 0.0}, + {"Longitude_Of_Center", EPSG_NAME_PARAMETER_LONGITUDE_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_LONGITUDE_PROJECTION_CENTRE, 0.0}, + {"Latitude_Of_Center", EPSG_NAME_PARAMETER_LATITUDE_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_LATITUDE_PROJECTION_CENTRE, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Double_Stereographic[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Scale_Factor", EPSG_NAME_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_SCALE_FACTOR_AT_NATURAL_ORIGIN, 0.0}, + {"Latitude_Of_Origin", EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Krovak_alt1[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Pseudo_Standard_Parallel_1", + EPSG_NAME_PARAMETER_LATITUDE_PSEUDO_STANDARD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_PSEUDO_STANDARD_PARALLEL, 0.0}, + {"Scale_Factor", EPSG_NAME_PARAMETER_SCALE_FACTOR_PSEUDO_STANDARD_PARALLEL, + EPSG_CODE_PARAMETER_SCALE_FACTOR_PSEUDO_STANDARD_PARALLEL, 0.0}, + {"Azimuth", EPSG_NAME_PARAMETER_COLATITUDE_CONE_AXIS, + EPSG_CODE_PARAMETER_COLATITUDE_CONE_AXIS, 0.0}, + {"Longitude_Of_Center", EPSG_NAME_PARAMETER_LONGITUDE_OF_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_ORIGIN, 0.0}, + {"Latitude_Of_Center", EPSG_NAME_PARAMETER_LATITUDE_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_LATITUDE_PROJECTION_CENTRE, 0.0}, + {"X_Scale", nullptr, 0, 1.0}, + {"Y_Scale", nullptr, 0, 1.0}, + {"XY_Plane_Rotation", nullptr, 0, 0.0}, + {nullptr, nullptr, 0, 0.0}}; +static const ESRIParamMapping paramsESRI_Krovak_alt2[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Pseudo_Standard_Parallel_1", + EPSG_NAME_PARAMETER_LATITUDE_PSEUDO_STANDARD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_PSEUDO_STANDARD_PARALLEL, 0.0}, + {"Scale_Factor", EPSG_NAME_PARAMETER_SCALE_FACTOR_PSEUDO_STANDARD_PARALLEL, + EPSG_CODE_PARAMETER_SCALE_FACTOR_PSEUDO_STANDARD_PARALLEL, 0.0}, + {"Azimuth", EPSG_NAME_PARAMETER_COLATITUDE_CONE_AXIS, + EPSG_CODE_PARAMETER_COLATITUDE_CONE_AXIS, 0.0}, + {"Longitude_Of_Center", EPSG_NAME_PARAMETER_LONGITUDE_OF_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_ORIGIN, 0.0}, + {"Latitude_Of_Center", EPSG_NAME_PARAMETER_LATITUDE_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_LATITUDE_PROJECTION_CENTRE, 0.0}, + {"X_Scale", nullptr, 0, -1.0}, + {"Y_Scale", nullptr, 0, 1.0}, + {"XY_Plane_Rotation", nullptr, 0, 90.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_New_Zealand_Map_Grid[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Longitude_Of_Origin", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Latitude_Of_Origin", EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Orthographic[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Longitude_Of_Center", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Latitude_Of_Center", EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Winkel_Tripel[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Standard_Parallel_1", EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Aitoff[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Craster_Parabolic[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Gnomonic[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Longitude_Of_Center", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Latitude_Of_Center", EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Stereographic_North_Pole[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_ORIGIN, 0.0}, + {"Standard_Parallel_1", EPSG_NAME_PARAMETER_LATITUDE_STD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_STD_PARALLEL, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Stereographic_South_Pole[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_ORIGIN, 0.0}, + {"Standard_Parallel_1", EPSG_NAME_PARAMETER_LATITUDE_STD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_STD_PARALLEL, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping + paramsESRI_Rectified_Skew_Orthomorphic_Natural_Origin[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Scale_Factor", EPSG_NAME_PARAMETER_SCALE_FACTOR_INITIAL_LINE, + EPSG_CODE_PARAMETER_SCALE_FACTOR_INITIAL_LINE, 0.0}, + {"Azimuth", EPSG_NAME_PARAMETER_AZIMUTH_INITIAL_LINE, + EPSG_CODE_PARAMETER_AZIMUTH_INITIAL_LINE, 0.0}, + {"Longitude_Of_Center", EPSG_NAME_PARAMETER_LONGITUDE_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_LONGITUDE_PROJECTION_CENTRE, 0.0}, + {"Latitude_Of_Center", EPSG_NAME_PARAMETER_LATITUDE_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_LATITUDE_PROJECTION_CENTRE, 0.0}, + {"XY_Plane_Rotation", EPSG_NAME_PARAMETER_ANGLE_RECTIFIED_TO_SKEW_GRID, + EPSG_CODE_PARAMETER_ANGLE_RECTIFIED_TO_SKEW_GRID, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Rectified_Skew_Orthomorphic_Center[] = + {{"False_Easting", EPSG_NAME_PARAMETER_EASTING_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_EASTING_PROJECTION_CENTRE, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_NORTHING_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_NORTHING_PROJECTION_CENTRE, 0.0}, + {"Scale_Factor", EPSG_NAME_PARAMETER_SCALE_FACTOR_INITIAL_LINE, + EPSG_CODE_PARAMETER_SCALE_FACTOR_INITIAL_LINE, 0.0}, + {"Azimuth", EPSG_NAME_PARAMETER_AZIMUTH_INITIAL_LINE, + EPSG_CODE_PARAMETER_AZIMUTH_INITIAL_LINE, 0.0}, + {"Longitude_Of_Center", EPSG_NAME_PARAMETER_LONGITUDE_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_LONGITUDE_PROJECTION_CENTRE, 0.0}, + {"Latitude_Of_Center", EPSG_NAME_PARAMETER_LATITUDE_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_LATITUDE_PROJECTION_CENTRE, 0.0}, + {"XY_Plane_Rotation", EPSG_NAME_PARAMETER_ANGLE_RECTIFIED_TO_SKEW_GRID, + EPSG_CODE_PARAMETER_ANGLE_RECTIFIED_TO_SKEW_GRID, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Goode_Homolosine[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Equidistant_Cylindrical_Ellipsoidal[] = + {{"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Standard_Parallel_1", EPSG_NAME_PARAMETER_LATITUDE_1ST_STD_PARALLEL, + EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Laborde_Oblique_Mercator[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Scale_Factor", EPSG_NAME_PARAMETER_SCALE_FACTOR_INITIAL_LINE, + EPSG_CODE_PARAMETER_SCALE_FACTOR_INITIAL_LINE, 0.0}, + {"Azimuth", EPSG_NAME_PARAMETER_AZIMUTH_INITIAL_LINE, + EPSG_CODE_PARAMETER_AZIMUTH_INITIAL_LINE, 0.0}, + {"Longitude_Of_Center", EPSG_NAME_PARAMETER_LONGITUDE_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_LONGITUDE_PROJECTION_CENTRE, 0.0}, + {"Latitude_Of_Center", EPSG_NAME_PARAMETER_LATITUDE_PROJECTION_CENTRE, + EPSG_CODE_PARAMETER_LATITUDE_PROJECTION_CENTRE, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Gnomonic_Ellipsoidal[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Longitude_Of_Center", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Latitude_Of_Center", EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Wagner_IV[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Latitude_Of_Origin", nullptr, 0, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Wagner_V[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Wagner_VII[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Geostationary_Satellite[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Longitude_Of_Center", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Height", "Satellite Height", 0, 0.0}, + {"Option", nullptr, 0, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIParamMapping paramsESRI_Mercator_Auxiliary_Sphere[] = { + {"False_Easting", EPSG_NAME_PARAMETER_FALSE_EASTING, + EPSG_CODE_PARAMETER_FALSE_EASTING, 0.0}, + {"False_Northing", EPSG_NAME_PARAMETER_FALSE_NORTHING, + EPSG_CODE_PARAMETER_FALSE_NORTHING, 0.0}, + {"Central_Meridian", EPSG_NAME_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LONGITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Standard_Parallel_1", EPSG_NAME_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, + EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN, 0.0}, + {"Auxiliary_Sphere_Type", nullptr, 0, 0.0}, + {nullptr, nullptr, 0, 0.0}}; + +static const ESRIMethodMapping esriMappings[] = { + {"Plate_Carree", EPSG_NAME_METHOD_EQUIDISTANT_CYLINDRICAL, + EPSG_CODE_METHOD_EQUIDISTANT_CYLINDRICAL, paramsESRI_Plate_Carree}, + {"Plate_Carree", EPSG_NAME_METHOD_EQUIDISTANT_CYLINDRICAL_SPHERICAL, + EPSG_CODE_METHOD_EQUIDISTANT_CYLINDRICAL_SPHERICAL, + paramsESRI_Plate_Carree}, + {"Equidistant_Cylindrical", EPSG_NAME_METHOD_EQUIDISTANT_CYLINDRICAL, + EPSG_CODE_METHOD_EQUIDISTANT_CYLINDRICAL, + paramsESRI_Equidistant_Cylindrical}, + {"Miller_Cylindrical", PROJ_WKT2_NAME_METHOD_MILLER_CYLINDRICAL, 0, + paramsESRI_Miller_Cylindrical}, + {"Mercator", EPSG_NAME_METHOD_MERCATOR_VARIANT_B, + EPSG_CODE_METHOD_MERCATOR_VARIANT_B, paramsESRI_Mercator}, + {"Gauss_Kruger", EPSG_NAME_METHOD_TRANSVERSE_MERCATOR, + EPSG_CODE_METHOD_TRANSVERSE_MERCATOR, paramsESRI_Gauss_Kruger}, + {"Transverse_Mercator", EPSG_NAME_METHOD_TRANSVERSE_MERCATOR, + EPSG_CODE_METHOD_TRANSVERSE_MERCATOR, paramsESRI_Transverse_Mercator}, + {"Albers", EPSG_NAME_METHOD_ALBERS_EQUAL_AREA, + EPSG_CODE_METHOD_ALBERS_EQUAL_AREA, paramsESRI_Albers}, + {"Sinusoidal", PROJ_WKT2_NAME_METHOD_SINUSOIDAL, 0, paramsESRI_Sinusoidal}, + {"Mollweide", PROJ_WKT2_NAME_METHOD_MOLLWEIDE, 0, paramsESRI_Mollweide}, + {"Eckert_I", PROJ_WKT2_NAME_METHOD_ECKERT_I, 0, paramsESRI_Eckert_I}, + {"Eckert_II", PROJ_WKT2_NAME_METHOD_ECKERT_II, 0, paramsESRI_Eckert_II}, + {"Eckert_III", PROJ_WKT2_NAME_METHOD_ECKERT_III, 0, paramsESRI_Eckert_III}, + {"Eckert_IV", PROJ_WKT2_NAME_METHOD_ECKERT_IV, 0, paramsESRI_Eckert_IV}, + {"Eckert_V", PROJ_WKT2_NAME_METHOD_ECKERT_V, 0, paramsESRI_Eckert_V}, + {"Eckert_VI", PROJ_WKT2_NAME_METHOD_ECKERT_VI, 0, paramsESRI_Eckert_VI}, + {"Gall_Stereographic", PROJ_WKT2_NAME_METHOD_GALL_STEREOGRAPHIC, 0, + paramsESRI_Gall_Stereographic}, + {"Winkel_I", "Winkel I", 0, paramsESRI_Winkel_I}, + {"Winkel_II", "Winkel II", 0, paramsESRI_Winkel_II}, + {"Lambert_Conformal_Conic", EPSG_NAME_METHOD_LAMBERT_CONIC_CONFORMAL_1SP, + EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_1SP, + paramsESRI_Lambert_Conformal_Conic_alt1}, + {"Lambert_Conformal_Conic", EPSG_NAME_METHOD_LAMBERT_CONIC_CONFORMAL_2SP, + EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP, + paramsESRI_Lambert_Conformal_Conic_alt2}, + {"Lambert_Conformal_Conic", EPSG_NAME_METHOD_LAMBERT_CONIC_CONFORMAL_2SP, + EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP, + paramsESRI_Lambert_Conformal_Conic_alt3}, + {"Lambert_Conformal_Conic", + EPSG_NAME_METHOD_LAMBERT_CONIC_CONFORMAL_2SP_MICHIGAN, + EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP_MICHIGAN, + paramsESRI_Lambert_Conformal_Conic_alt4}, + {"Polyconic", EPSG_NAME_METHOD_AMERICAN_POLYCONIC, + EPSG_CODE_METHOD_AMERICAN_POLYCONIC, paramsESRI_Polyconic}, + {"Quartic_Authalic", "Quartic Authalic", 0, paramsESRI_Quartic_Authalic}, + {"Loximuthal", "Loximuthal", 0, paramsESRI_Loximuthal}, + {"Bonne", EPSG_NAME_METHOD_BONNE, EPSG_CODE_METHOD_BONNE, paramsESRI_Bonne}, + {"Hotine_Oblique_Mercator_Two_Point_Natural_Origin", + PROJ_WKT2_NAME_METHOD_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN, 0, + paramsESRI_Hotine_Oblique_Mercator_Two_Point_Natural_Origin}, + {"Stereographic", PROJ_WKT2_NAME_METHOD_STEREOGRAPHIC, 0, + paramsESRI_Stereographic}, + {"Equidistant_Conic", PROJ_WKT2_NAME_METHOD_EQUIDISTANT_CONIC, 0, + paramsESRI_Equidistant_Conic}, + {"Cassini", EPSG_NAME_METHOD_CASSINI_SOLDNER, + EPSG_CODE_METHOD_CASSINI_SOLDNER, paramsESRI_Cassini}, + {"Van_der_Grinten_I", PROJ_WKT2_NAME_METHOD_VAN_DER_GRINTEN, 0, + paramsESRI_Van_der_Grinten_I}, + {"Robinson", PROJ_WKT2_NAME_METHOD_ROBINSON, 0, paramsESRI_Robinson}, + {"Two_Point_Equidistant", PROJ_WKT2_NAME_METHOD_TWO_POINT_EQUIDISTANT, 0, + paramsESRI_Two_Point_Equidistant}, + {"Azimuthal_Equidistant", EPSG_NAME_METHOD_MODIFIED_AZIMUTHAL_EQUIDISTANT, + EPSG_CODE_METHOD_MODIFIED_AZIMUTHAL_EQUIDISTANT, + paramsESRI_Azimuthal_Equidistant}, + {"Lambert_Azimuthal_Equal_Area", + EPSG_NAME_METHOD_LAMBERT_AZIMUTHAL_EQUAL_AREA, + EPSG_CODE_METHOD_LAMBERT_AZIMUTHAL_EQUAL_AREA, + paramsESRI_Lambert_Azimuthal_Equal_Area}, + {"Cylindrical_Equal_Area", + EPSG_NAME_METHOD_LAMBERT_CYLINDRICAL_EQUAL_AREA_SPHERICAL, + EPSG_CODE_METHOD_LAMBERT_CYLINDRICAL_EQUAL_AREA_SPHERICAL, + paramsESRI_Cylindrical_Equal_Area}, + {"Hotine_Oblique_Mercator_Two_Point_Center", + PROJ_WKT2_NAME_METHOD_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN, 0, + paramsESRI_Hotine_Oblique_Mercator_Two_Point_Center}, + {"Hotine_Oblique_Mercator_Azimuth_Natural_Origin", + EPSG_NAME_METHOD_HOTINE_OBLIQUE_MERCATOR_VARIANT_A, + EPSG_CODE_METHOD_HOTINE_OBLIQUE_MERCATOR_VARIANT_A, + paramsESRI_Hotine_Oblique_Mercator_Azimuth_Natural_Origin}, + {"Hotine_Oblique_Mercator_Azimuth_Center", + EPSG_NAME_METHOD_HOTINE_OBLIQUE_MERCATOR_VARIANT_B, + EPSG_CODE_METHOD_HOTINE_OBLIQUE_MERCATOR_VARIANT_B, + paramsESRI_Hotine_Oblique_Mercator_Azimuth_Center}, + {"Double_Stereographic", EPSG_NAME_METHOD_OBLIQUE_STEREOGRAPHIC, + EPSG_CODE_METHOD_OBLIQUE_STEREOGRAPHIC, paramsESRI_Double_Stereographic}, + {"Krovak", EPSG_NAME_METHOD_KROVAK, EPSG_CODE_METHOD_KROVAK, + paramsESRI_Krovak_alt1}, + {"Krovak", EPSG_NAME_METHOD_KROVAK_NORTH_ORIENTED, + EPSG_CODE_METHOD_KROVAK_NORTH_ORIENTED, paramsESRI_Krovak_alt2}, + {"New_Zealand_Map_Grid", EPSG_NAME_METHOD_NZMG, EPSG_CODE_METHOD_NZMG, + paramsESRI_New_Zealand_Map_Grid}, + {"Orthographic", EPSG_NAME_METHOD_ORTHOGRAPHIC, + EPSG_CODE_METHOD_ORTHOGRAPHIC, paramsESRI_Orthographic}, + {"Winkel_Tripel", "Winkel Tripel", 0, paramsESRI_Winkel_Tripel}, + {"Aitoff", "Aitoff", 0, paramsESRI_Aitoff}, + {"Craster_Parabolic", "Craster Parabolic", 0, paramsESRI_Craster_Parabolic}, + {"Gnomonic", PROJ_WKT2_NAME_METHOD_GNOMONIC, 0, paramsESRI_Gnomonic}, + {"Stereographic_North_Pole", EPSG_NAME_METHOD_POLAR_STEREOGRAPHIC_VARIANT_B, + EPSG_CODE_METHOD_POLAR_STEREOGRAPHIC_VARIANT_B, + paramsESRI_Stereographic_North_Pole}, + {"Stereographic_South_Pole", EPSG_NAME_METHOD_POLAR_STEREOGRAPHIC_VARIANT_B, + EPSG_CODE_METHOD_POLAR_STEREOGRAPHIC_VARIANT_B, + paramsESRI_Stereographic_South_Pole}, + {"Rectified_Skew_Orthomorphic_Natural_Origin", + EPSG_NAME_METHOD_HOTINE_OBLIQUE_MERCATOR_VARIANT_A, + EPSG_CODE_METHOD_HOTINE_OBLIQUE_MERCATOR_VARIANT_A, + paramsESRI_Rectified_Skew_Orthomorphic_Natural_Origin}, + {"Rectified_Skew_Orthomorphic_Center", + EPSG_NAME_METHOD_HOTINE_OBLIQUE_MERCATOR_VARIANT_B, + EPSG_CODE_METHOD_HOTINE_OBLIQUE_MERCATOR_VARIANT_B, + paramsESRI_Rectified_Skew_Orthomorphic_Center}, + {"Goode_Homolosine", "Goode Homolosine", 0, paramsESRI_Goode_Homolosine}, + {"Equidistant_Cylindrical_Ellipsoidal", + EPSG_NAME_METHOD_EQUIDISTANT_CYLINDRICAL, + EPSG_CODE_METHOD_EQUIDISTANT_CYLINDRICAL, + paramsESRI_Equidistant_Cylindrical_Ellipsoidal}, + {"Laborde_Oblique_Mercator", EPSG_NAME_METHOD_LABORDE_OBLIQUE_MERCATOR, + EPSG_CODE_METHOD_LABORDE_OBLIQUE_MERCATOR, + paramsESRI_Laborde_Oblique_Mercator}, + {"Gnomonic_Ellipsoidal", PROJ_WKT2_NAME_METHOD_GNOMONIC, 0, + paramsESRI_Gnomonic_Ellipsoidal}, + {"Wagner_IV", PROJ_WKT2_NAME_METHOD_WAGNER_IV, 0, paramsESRI_Wagner_IV}, + {"Wagner_V", PROJ_WKT2_NAME_METHOD_WAGNER_V, 0, paramsESRI_Wagner_V}, + {"Wagner_VII", PROJ_WKT2_NAME_METHOD_WAGNER_VII, 0, paramsESRI_Wagner_VII}, + {"Geostationary_Satellite", + PROJ_WKT2_NAME_METHOD_GEOSTATIONARY_SATELLITE_SWEEP_Y, 0, + paramsESRI_Geostationary_Satellite}, + {"Mercator_Auxiliary_Sphere", + EPSG_NAME_METHOD_POPULAR_VISUALISATION_PSEUDO_MERCATOR, + EPSG_CODE_METHOD_POPULAR_VISUALISATION_PSEUDO_MERCATOR, + paramsESRI_Mercator_Auxiliary_Sphere}, +}; + +// --------------------------------------------------------------------------- + +// end of anonymous namespace +} + +//! @endcond + +#endif // ESRI_PROJECTION_MAPPINGS_HH_INCLUDED diff --git a/include/proj/internal/internal.hpp b/include/proj/internal/internal.hpp new file mode 100644 index 00000000..cbf6e259 --- /dev/null +++ b/include/proj/internal/internal.hpp @@ -0,0 +1,190 @@ +/****************************************************************************** + * + * Project: PROJ + * Purpose: ISO19111:2018 implementation + * Author: Even Rouault <even dot rouault at spatialys dot com> + * + ****************************************************************************** + * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ****************************************************************************/ + +#ifndef FROM_PROJ_CPP +#error This file should only be included from a PROJ cpp file +#endif + +#ifndef INTERNAL_HH_INCLUDED +#define INTERNAL_HH_INCLUDED + +#if !(__cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)) +#error Must have C++11 or newer. +#endif + +#include <cassert> +#include <cstring> +#include <memory> +#include <string> +#ifndef DOXYGEN_ENABLED +#include <type_traits> // for std::is_base_of +#endif +#include <vector> + +#include "proj/util.hpp" + +//! @cond Doxygen_Suppress + +#if ((defined(__clang__) && \ + (__clang_major__ > 3 || \ + (__clang_major__ == 3 && __clang_minor__ >= 7))) || \ + __GNUC__ >= 7) +/** Macro for fallthrough in a switch case construct */ +#define PROJ_FALLTHROUGH [[clang::fallthrough]]; +#else +/** Macro for fallthrough in a switch case construct */ +#define PROJ_FALLTHROUGH +#endif + +#if defined(__clang__) || defined(_MSC_VER) +#define COMPILER_WARNS_ABOUT_ABSTRACT_VBASE_INIT +#endif + +#if !(defined(__clang__) && __clang_major__ < 5) && !defined(__INTEL_COMPILER) +#define SUPPORT_DELETED_FUNCTION +#endif + +NS_PROJ_START + +namespace operation { +class OperationParameterValue; +} // namespace operation + +namespace internal { + +/** Use cpl::down_cast<Derived*>(pointer_to_base) as equivalent of + * static_cast<Derived*>(pointer_to_base) with safe checking in debug + * mode. + * + * Only works if no virtual inheritance is involved. + * + * @param f pointer to a base class + * @return pointer to a derived class + */ +template <typename To, typename From> inline To down_cast(From *f) { + static_assert( + (std::is_base_of<From, typename std::remove_pointer<To>::type>::value), + "target type not derived from source type"); + assert(f == nullptr || dynamic_cast<To>(f) != nullptr); + return static_cast<To>(f); +} + +/* Borrowed from C++14 */ +template <typename T, typename... Args> +std::unique_ptr<T> make_unique(Args &&... args) { + return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); +} + +PROJ_FOR_TEST std::string replaceAll(const std::string &str, + const std::string &before, + const std::string &after); + +size_t ci_find(const std::string &osStr, const char *needle) noexcept; + +size_t ci_find(const std::string &osStr, const std::string &needle, + size_t startPos = 0) noexcept; + +inline bool starts_with(const std::string &str, + const std::string &prefix) noexcept { + if (str.size() < prefix.size()) { + return false; + } + return std::memcmp(str.c_str(), prefix.c_str(), prefix.size()) == 0; +} + +inline bool starts_with(const std::string &str, const char *prefix) noexcept { + const size_t prefixSize = std::strlen(prefix); + if (str.size() < prefixSize) { + return false; + } + return std::memcmp(str.c_str(), prefix, prefixSize) == 0; +} + +bool ci_starts_with(const char *str, const char *prefix) noexcept; + +bool ci_starts_with(const std::string &str, const std::string &prefix) noexcept; + +bool ends_with(const std::string &str, const std::string &suffix) noexcept; + +PROJ_FOR_TEST std::string tolower(const std::string &osStr); + +std::string toupper(const std::string &osStr); + +PROJ_FOR_TEST std::vector<std::string> split(const std::string &osStr, + char separator); + +bool ci_equal(const char *a, const char *b) noexcept; + +#ifdef SUPPORT_DELETED_FUNCTION +bool ci_equal(const char *a, const std::string &b) = delete; +#endif + +PROJ_FOR_TEST bool ci_equal(const std::string &a, const char *b) noexcept; + +PROJ_FOR_TEST bool ci_equal(const std::string &a, + const std::string &b) noexcept; + +std::string stripQuotes(const std::string &osStr); + +std::string toString(int val); + +PROJ_FOR_TEST std::string toString(double val, int precision = 15); + +PROJ_FOR_TEST double +c_locale_stod(const std::string &s); // throw(std::invalid_argument) + +#ifdef SUPPORT_DELETED_FUNCTION +std::string concat(const std::string &, const std::string &) = delete; +std::string concat(const char *, const char *) = delete; +#endif +std::string concat(const char *a, const std::string &b); +#ifdef SUPPORT_DELETED_FUNCTION +std::string concat(const std::string &, const char *) = delete; +std::string concat(const char *, const char *, const char *) = delete; +std::string concat(const char *, const char *, const std::string &) = delete; +#endif +std::string concat(const char *a, const std::string &b, const char *c); +#ifdef SUPPORT_DELETED_FUNCTION +std::string concat(const char *, const std::string &, + const std::string &) = delete; +std::string concat(const std::string &, const char *, const char *) = delete; +std::string concat(const std::string &, const char *, + const std::string &) = delete; +std::string concat(const std::string &, const std::string &, + const char *) = delete; +std::string concat(const std::string &, const std::string &, + const std::string &) = delete; +#endif + +} // namespace internal + +NS_PROJ_END + +//! @endcond + +#endif // INTERNAL_HH_INCLUDED diff --git a/include/proj/internal/io_internal.hpp b/include/proj/internal/io_internal.hpp new file mode 100644 index 00000000..8a32c6eb --- /dev/null +++ b/include/proj/internal/io_internal.hpp @@ -0,0 +1,163 @@ +/****************************************************************************** + * + * Project: PROJ + * Purpose: ISO19111:2018 implementation + * Author: Even Rouault <even dot rouault at spatialys dot com> + * + ****************************************************************************** + * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ****************************************************************************/ + +#ifndef FROM_PROJ_CPP +#error This file should only be included from a PROJ cpp file +#endif + +#ifndef IO_INTERNAL_HH_INCLUDED +#define IO_INTERNAL_HH_INCLUDED + +#include <string> +#include <vector> + +#include "proj/util.hpp" + +//! @cond Doxygen_Suppress + +NS_PROJ_START + +namespace io { + +// --------------------------------------------------------------------------- + +class WKTConstants { + public: + // WKT1 + static const std::string GEOCCS; + static const std::string GEOGCS; + static const std::string DATUM; // WKT2 preferred too + static const std::string UNIT; + static const std::string SPHEROID; + static const std::string AXIS; // WKT2 too + static const std::string PRIMEM; // WKT2 too + static const std::string AUTHORITY; + static const std::string PROJCS; + static const std::string PROJECTION; + static const std::string PARAMETER; // WKT2 too + static const std::string VERT_CS; + static const std::string VERT_DATUM; + static const std::string COMPD_CS; + static const std::string TOWGS84; // WKT1 only + static const std::string EXTENSION; // WKT1 only - GDAL specific + static const std::string LOCAL_CS; // WKT1 only + static const std::string LOCAL_DATUM; // WKT1 only + + // WKT2 preferred + static const std::string GEODCRS; + static const std::string LENGTHUNIT; + static const std::string ANGLEUNIT; + static const std::string SCALEUNIT; + static const std::string TIMEUNIT; + static const std::string ELLIPSOID; + static const std::string CS; + static const std::string ID; + static const std::string PROJCRS; + static const std::string BASEGEODCRS; + static const std::string MERIDIAN; + static const std::string ORDER; + static const std::string ANCHOR; + static const std::string CONVERSION; + static const std::string METHOD; + static const std::string REMARK; + static const std::string GEOGCRS; // WKT2-2018 + static const std::string BASEGEOGCRS; // WKT2-2018 + static const std::string SCOPE; + static const std::string AREA; + static const std::string BBOX; + static const std::string CITATION; + static const std::string URI; + static const std::string VERTCRS; + static const std::string VDATUM; + static const std::string COMPOUNDCRS; + static const std::string PARAMETERFILE; + static const std::string COORDINATEOPERATION; + static const std::string SOURCECRS; + static const std::string TARGETCRS; + static const std::string INTERPOLATIONCRS; + static const std::string OPERATIONACCURACY; + static const std::string CONCATENATEDOPERATION; // WKT2-2018 + static const std::string STEP; // WKT2-2018 + static const std::string BOUNDCRS; + static const std::string ABRIDGEDTRANSFORMATION; + static const std::string DERIVINGCONVERSION; + static const std::string TDATUM; + static const std::string CALENDAR; // WKT2-2018 + static const std::string TIMEORIGIN; + static const std::string TIMECRS; + static const std::string VERTICALEXTENT; + static const std::string TIMEEXTENT; + static const std::string USAGE; // WKT2-2018 + static const std::string DYNAMIC; // WKT2-2018 + static const std::string FRAMEEPOCH; // WKT2-2018 + static const std::string MODEL; // WKT2-2018 + static const std::string VELOCITYGRID; // WKT2-2018 + static const std::string ENSEMBLE; // WKT2-2018 + static const std::string MEMBER; // WKT2-2018 + static const std::string ENSEMBLEACCURACY; // WKT2-2018 + static const std::string DERIVEDPROJCRS; // WKT2-2018 + static const std::string BASEPROJCRS; // WKT2-2018 + static const std::string EDATUM; + static const std::string ENGCRS; + static const std::string PDATUM; + static const std::string PARAMETRICCRS; + static const std::string PARAMETRICUNIT; + static const std::string BASEVERTCRS; + static const std::string BASEENGCRS; + static const std::string BASEPARAMCRS; + static const std::string BASETIMECRS; + + // WKT2 alternate (longer or shorter) + static const std::string GEODETICCRS; + static const std::string GEODETICDATUM; + static const std::string PROJECTEDCRS; + static const std::string PRIMEMERIDIAN; + static const std::string GEOGRAPHICCRS; // WKT2-2018 + static const std::string TRF; // WKT2-2018 + static const std::string VERTICALCRS; + static const std::string VERTICALDATUM; + static const std::string VRF; // WKT2-2018 + static const std::string TIMEDATUM; + static const std::string ENGINEERINGDATUM; + static const std::string ENGINEERINGCRS; + static const std::string PARAMETRICDATUM; + + static const std::vector<std::string> &constants() { return constants_; } + + private: + static std::vector<std::string> constants_; + static const char *createAndAddToConstantList(const char *text); +}; + +} // namespace io + +NS_PROJ_END + +//! @endcond + +#endif // IO_INTERNAL_HH_INCLUDED diff --git a/include/proj/internal/lru_cache.hpp b/include/proj/internal/lru_cache.hpp new file mode 100644 index 00000000..2f2c8bd9 --- /dev/null +++ b/include/proj/internal/lru_cache.hpp @@ -0,0 +1,223 @@ +/* + * LRUCache11 - a templated C++11 based LRU cache class that allows + * specification of + * key, value and optionally the map container type (defaults to + * std::unordered_map) + * By using the std::map and a linked list of keys it allows O(1) insert, delete + * and + * refresh operations. + * + * This is a header-only library and all you need is the LRUCache11.hpp file + * + * Github: https://github.com/mohaps/lrucache11 + * + * This is a follow-up to the LRUCache project - + * https://github.com/mohaps/lrucache + * + * Copyright (c) 2012-22 SAURAV MOHAPATRA <mohaps@gmail.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/*! @cond Doxygen_Suppress */ + +#pragma once +#include <algorithm> +#include <cstdint> +#include <list> +#include <mutex> +#include <stdexcept> +#include <thread> +#include <unordered_map> + +NS_PROJ_START +namespace lru11 { +/* + * a noop lockable concept that can be used in place of std::mutex + */ +class NullLock { + public: + // cppcheck-suppress functionStatic + void lock() {} + // cppcheck-suppress functionStatic + void unlock() {} + // cppcheck-suppress functionStatic + bool try_lock() { return true; } +}; + +/** + * error raised when a key not in cache is passed to get() + */ +class KeyNotFound : public std::invalid_argument { + public: + KeyNotFound() : std::invalid_argument("key_not_found") {} + ~KeyNotFound() override; +}; + +#ifndef LRU11_DO_NOT_DEFINE_OUT_OF_CLASS_METHODS +KeyNotFound::~KeyNotFound() = default; +#endif + +template <typename K, typename V> +struct KeyValuePair { + public: + K key; + V value; + + KeyValuePair(const K& k, const V& v) : key(k), value(v) {} +}; + +/** + * The LRU Cache class templated by + * Key - key type + * Value - value type + * MapType - an associative container like std::unordered_map + * LockType - a lock type derived from the Lock class (default: + *NullLock = no synchronization) + * + * The default NullLock based template is not thread-safe, however passing + *Lock=std::mutex will make it + * thread-safe + */ +template <class Key, class Value, class Lock = NullLock, + class Map = std::unordered_map< + Key, typename std::list<KeyValuePair<Key, Value>>::iterator>> +class Cache { + public: + typedef KeyValuePair<Key, Value> node_type; + typedef std::list<KeyValuePair<Key, Value>> list_type; + typedef Map map_type; + typedef Lock lock_type; + using Guard = std::lock_guard<lock_type>; + /** + * the max size is the hard limit of keys and (maxSize + elasticity) is the + * soft limit + * the cache is allowed to grow till maxSize + elasticity and is pruned back + * to maxSize keys + * set maxSize = 0 for an unbounded cache (but in that case, you're better off + * using a std::unordered_map + * directly anyway! :) + */ + explicit Cache(size_t maxSize = 64, size_t elasticity = 10) + : maxSize_(maxSize), elasticity_(elasticity) {} + virtual ~Cache() = default; + size_t size() const { + Guard g(lock_); + return cache_.size(); + } + bool empty() const { + Guard g(lock_); + return cache_.empty(); + } + void clear() { + Guard g(lock_); + cache_.clear(); + keys_.clear(); + } + void insert(const Key& k, const Value& v) { + Guard g(lock_); + const auto iter = cache_.find(k); + if (iter != cache_.end()) { + iter->second->value = v; + keys_.splice(keys_.begin(), keys_, iter->second); + return; + } + + keys_.emplace_front(k, v); + cache_[k] = keys_.begin(); + prune(); + } + bool tryGet(const Key& kIn, Value& vOut) { + Guard g(lock_); + const auto iter = cache_.find(kIn); + if (iter == cache_.end()) { + return false; + } + keys_.splice(keys_.begin(), keys_, iter->second); + vOut = iter->second->value; + return true; + } + /** + * The const reference returned here is only + * guaranteed to be valid till the next insert/delete + */ + const Value& get(const Key& k) { + Guard g(lock_); + const auto iter = cache_.find(k); + if (iter == cache_.end()) { + throw KeyNotFound(); + } + keys_.splice(keys_.begin(), keys_, iter->second); + return iter->second->value; + } + /** + * returns a copy of the stored object (if found) + */ + Value getCopy(const Key& k) { + return get(k); + } + bool remove(const Key& k) { + Guard g(lock_); + auto iter = cache_.find(k); + if (iter == cache_.end()) { + return false; + } + keys_.erase(iter->second); + cache_.erase(iter); + return true; + } + bool contains(const Key& k) { + Guard g(lock_); + return cache_.find(k) != cache_.end(); + } + + size_t getMaxSize() const { return maxSize_; } + size_t getElasticity() const { return elasticity_; } + size_t getMaxAllowedSize() const { return maxSize_ + elasticity_; } + template <typename F> + void cwalk(F& f) const { + Guard g(lock_); + std::for_each(keys_.begin(), keys_.end(), f); + } + + protected: + size_t prune() { + size_t maxAllowed = maxSize_ + elasticity_; + if (maxSize_ == 0 || cache_.size() <= maxAllowed) { /* ERO: changed < to <= */ + return 0; + } + size_t count = 0; + while (cache_.size() > maxSize_) { + cache_.erase(keys_.back().key); + keys_.pop_back(); + ++count; + } + return count; + } + + private: + // Dissallow copying. + Cache(const Cache&) = delete; + Cache& operator=(const Cache&) = delete; + + mutable Lock lock_{}; + Map cache_{}; + list_type keys_{}; + size_t maxSize_; + size_t elasticity_; +}; + +} // namespace LRUCache11 +NS_PROJ_END + +/*! @endcond */ diff --git a/include/proj/io.hpp b/include/proj/io.hpp new file mode 100644 index 00000000..689fede1 --- /dev/null +++ b/include/proj/io.hpp @@ -0,0 +1,970 @@ +/****************************************************************************** + * + * Project: PROJ + * Purpose: ISO19111:2018 implementation + * Author: Even Rouault <even dot rouault at spatialys dot com> + * + ****************************************************************************** + * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ****************************************************************************/ + +#ifndef IO_HH_INCLUDED +#define IO_HH_INCLUDED + +#include <list> +#include <memory> +#include <set> +#include <string> +#include <utility> +#include <vector> + +#include "util.hpp" + +NS_PROJ_START + +namespace common { +class UnitOfMeasure; +using UnitOfMeasurePtr = std::shared_ptr<UnitOfMeasure>; +using UnitOfMeasureNNPtr = util::nn<UnitOfMeasurePtr>; + +class IdentifiedObject; +using IdentifiedObjectPtr = std::shared_ptr<IdentifiedObject>; +using IdentifiedObjectNNPtr = util::nn<IdentifiedObjectPtr>; +} // namespace common + +namespace cs { +class CoordinateSystem; +using CoordinateSystemPtr = std::shared_ptr<CoordinateSystem>; +using CoordinateSystemNNPtr = util::nn<CoordinateSystemPtr>; +} // namespace cs + +namespace metadata { +class Extent; +using ExtentPtr = std::shared_ptr<Extent>; +using ExtentNNPtr = util::nn<ExtentPtr>; +} // namespace metadata + +namespace datum { +class Datum; +using DatumPtr = std::shared_ptr<Datum>; +using DatumNNPtr = util::nn<DatumPtr>; + +class Ellipsoid; +using EllipsoidPtr = std::shared_ptr<Ellipsoid>; +using EllipsoidNNPtr = util::nn<EllipsoidPtr>; + +class PrimeMeridian; +using PrimeMeridianPtr = std::shared_ptr<PrimeMeridian>; +using PrimeMeridianNNPtr = util::nn<PrimeMeridianPtr>; + +class GeodeticReferenceFrame; +using GeodeticReferenceFramePtr = std::shared_ptr<GeodeticReferenceFrame>; +using GeodeticReferenceFrameNNPtr = util::nn<GeodeticReferenceFramePtr>; + +class VerticalReferenceFrame; +using VerticalReferenceFramePtr = std::shared_ptr<VerticalReferenceFrame>; +using VerticalReferenceFrameNNPtr = util::nn<VerticalReferenceFramePtr>; +} // namespace datum + +namespace crs { +class CRS; +using CRSPtr = std::shared_ptr<CRS>; +using CRSNNPtr = util::nn<CRSPtr>; + +class GeodeticCRS; +using GeodeticCRSPtr = std::shared_ptr<GeodeticCRS>; +using GeodeticCRSNNPtr = util::nn<GeodeticCRSPtr>; + +class GeographicCRS; +using GeographicCRSPtr = std::shared_ptr<GeographicCRS>; +using GeographicCRSNNPtr = util::nn<GeographicCRSPtr>; + +class VerticalCRS; +using VerticalCRSPtr = std::shared_ptr<VerticalCRS>; +using VerticalCRSNNPtr = util::nn<VerticalCRSPtr>; + +class ProjectedCRS; +using ProjectedCRSPtr = std::shared_ptr<ProjectedCRS>; +using ProjectedCRSNNPtr = util::nn<ProjectedCRSPtr>; + +class CompoundCRS; +using CompoundCRSPtr = std::shared_ptr<CompoundCRS>; +using CompoundCRSNNPtr = util::nn<CompoundCRSPtr>; +} // namespace crs + +namespace operation { +class Conversion; +using ConversionPtr = std::shared_ptr<Conversion>; +using ConversionNNPtr = util::nn<ConversionPtr>; + +class CoordinateOperation; +using CoordinateOperationPtr = std::shared_ptr<CoordinateOperation>; +using CoordinateOperationNNPtr = util::nn<CoordinateOperationPtr>; +} // namespace operation + +/** osgeo.proj.io namespace. + * + * \brief I/O classes + */ +namespace io { + +class DatabaseContext; +/** Shared pointer of DatabaseContext. */ +using DatabaseContextPtr = std::shared_ptr<DatabaseContext>; +/** Non-null shared pointer of DatabaseContext. */ +using DatabaseContextNNPtr = util::nn<DatabaseContextPtr>; + +// --------------------------------------------------------------------------- + +class WKTFormatter; +/** WKTFormatter unique pointer. */ +using WKTFormatterPtr = std::unique_ptr<WKTFormatter>; +/** Non-null WKTFormatter unique pointer. */ +using WKTFormatterNNPtr = util::nn<WKTFormatterPtr>; + +/** \brief Formatter to WKT strings. + * + * An instance of this class can only be used by a single + * thread at a time. + */ +class PROJ_GCC_DLL WKTFormatter { + public: + /** WKT variant. */ + enum class PROJ_MSVC_DLL Convention { + /** Full WKT2 string, conforming to ISO 19162:2015(E) / OGC 12-063r5 + * (\ref WKT2_2015) with all possible nodes and new keyword names. + */ + WKT2, + WKT2_2015 = WKT2, + + /** Same as WKT2 with the following exceptions: + * <ul> + * <li>UNIT keyword used.</li> + * <li>ID node only on top element.</li> + * <li>No ORDER element in AXIS element.</li> + * <li>PRIMEM node omitted if it is Greenwich.</li> + * <li>ELLIPSOID.UNIT node omitted if it is + * UnitOfMeasure::METRE.</li> + * <li>PARAMETER.UNIT / PRIMEM.UNIT omitted if same as AXIS.</li> + * <li>AXIS.UNIT omitted and replaced by a common GEODCRS.UNIT if + * they are all the same on all axis.</li> + * </ul> + */ + WKT2_SIMPLIFIED, + WKT2_2015_SIMPLIFIED = WKT2_SIMPLIFIED, + + /** Full WKT2 string, conforming to ISO 19162:2018 / OGC 18-010, with + * (\ref WKT2_2018) all possible nodes and new keyword names. + * Non-normative list of differences: + * <ul> + * <li>WKT2_2018 uses GEOGCRS / BASEGEOGCRS keywords for + * GeographicCRS.</li> + * </ul> + */ + WKT2_2018, + + /** WKT2_2018 with the simplification rule of WKT2_SIMPLIFIED */ + WKT2_2018_SIMPLIFIED, + + /** WKT1 as traditionally output by GDAL, deriving from OGC 01-009. + A notable departuPROJ_GCC_DLLre from WKT1_GDAL with respect to OGC + 01-009 is + that in WKT1_GDAL, the unit of the PRIMEM value is always degrees. + */ + WKT1_GDAL, + + /** WKT1 as traditionally output by ESRI software, + * deriving from OGC 99-049. */ + WKT1_ESRI, + }; + + PROJ_DLL static WKTFormatterNNPtr + create(Convention convention = Convention::WKT2, + DatabaseContextPtr dbContext = nullptr); + PROJ_DLL static WKTFormatterNNPtr create(const WKTFormatterNNPtr &other); + //! @cond Doxygen_Suppress + PROJ_DLL ~WKTFormatter(); + //! @endcond + + PROJ_DLL WKTFormatter &setMultiLine(bool multiLine) noexcept; + PROJ_DLL WKTFormatter &setIndentationWidth(int width) noexcept; + PROJ_DLL WKTFormatter &setOutputAxis(bool outputAxis) noexcept; + PROJ_DLL WKTFormatter &setStrict(bool strict) noexcept; + PROJ_DLL bool isStrict() const noexcept; + + PROJ_DLL const std::string &toString() const; + + PROJ_PRIVATE : + //! @cond Doxygen_Suppress + PROJ_DLL WKTFormatter & + setOutputId(bool outputIdIn); + + PROJ_INTERNAL void enter(); + PROJ_INTERNAL void leave(); + + PROJ_INTERNAL void startNode(const std::string &keyword, bool hasId); + PROJ_INTERNAL void endNode(); + + PROJ_DLL WKTFormatter &simulCurNodeHasId(); + + PROJ_INTERNAL void addQuotedString(const char *str); + PROJ_INTERNAL void addQuotedString(const std::string &str); + PROJ_INTERNAL void add(const std::string &str); + PROJ_INTERNAL void add(int number); + PROJ_INTERNAL void add(size_t number) = delete; + PROJ_INTERNAL void add(double number, int precision = 15); + + PROJ_INTERNAL void pushOutputUnit(bool outputUnitIn); + PROJ_INTERNAL void popOutputUnit(); + PROJ_INTERNAL bool outputUnit() const; + + PROJ_INTERNAL void pushOutputId(bool outputIdIn); + PROJ_INTERNAL void popOutputId(); + PROJ_INTERNAL bool outputId() const; + + PROJ_INTERNAL void + pushAxisLinearUnit(const common::UnitOfMeasureNNPtr &unit); + PROJ_INTERNAL void popAxisLinearUnit(); + PROJ_INTERNAL const common::UnitOfMeasureNNPtr &axisLinearUnit() const; + + PROJ_INTERNAL void + pushAxisAngularUnit(const common::UnitOfMeasureNNPtr &unit); + PROJ_INTERNAL void popAxisAngularUnit(); + PROJ_INTERNAL const common::UnitOfMeasureNNPtr &axisAngularUnit() const; + + PROJ_INTERNAL void setAbridgedTransformation(bool abriged); + PROJ_INTERNAL bool abridgedTransformation() const; + + PROJ_INTERNAL void setUseDerivingConversion(bool useDerivingConversionIn); + PROJ_INTERNAL bool useDerivingConversion() const; + + PROJ_INTERNAL void setTOWGS84Parameters(const std::vector<double> ¶ms); + PROJ_INTERNAL const std::vector<double> &getTOWGS84Parameters() const; + + PROJ_INTERNAL void setVDatumExtension(const std::string &filename); + PROJ_INTERNAL const std::string &getVDatumExtension() const; + + PROJ_INTERNAL void setHDatumExtension(const std::string &filename); + PROJ_INTERNAL const std::string &getHDatumExtension() const; + + PROJ_INTERNAL static std::string morphNameToESRI(const std::string &name); + +#ifdef unused + PROJ_INTERNAL void startInversion(); + PROJ_INTERNAL void stopInversion(); + PROJ_INTERNAL bool isInverted() const; +#endif + + PROJ_INTERNAL bool outputAxis() const; + PROJ_INTERNAL bool outputAxisOrder() const; + PROJ_INTERNAL bool primeMeridianOmittedIfGreenwich() const; + PROJ_INTERNAL bool ellipsoidUnitOmittedIfMetre() const; + PROJ_INTERNAL bool forceUNITKeyword() const; + PROJ_INTERNAL bool primeMeridianOrParameterUnitOmittedIfSameAsAxis() const; + PROJ_INTERNAL bool primeMeridianInDegree() const; + PROJ_INTERNAL bool outputCSUnitOnlyOnceIfSame() const; + + /** WKT version. */ + enum class Version { + /** WKT1 */ + WKT1, + /** WKT2 / ISO 19162 */ + WKT2 + }; + + PROJ_INTERNAL Version version() const; + PROJ_INTERNAL bool use2018Keywords() const; + PROJ_INTERNAL bool useESRIDialect() const; + + PROJ_INTERNAL const DatabaseContextPtr &databaseContext() const; + + //! @endcond + + protected: + //! @cond Doxygen_Suppress + PROJ_INTERNAL explicit WKTFormatter(Convention convention); + WKTFormatter(const WKTFormatter &other) = delete; + + INLINED_MAKE_UNIQUE + //! @endcond + + private: + PROJ_OPAQUE_PRIVATE_DATA +}; + +// --------------------------------------------------------------------------- + +class PROJStringFormatter; +/** PROJStringFormatter unique pointer. */ +using PROJStringFormatterPtr = std::unique_ptr<PROJStringFormatter>; +/** Non-null PROJStringFormatter unique pointer. */ +using PROJStringFormatterNNPtr = util::nn<PROJStringFormatterPtr>; + +/** \brief Formatter to PROJ strings. + * + * An instance of this class can only be used by a single + * thread at a time. + */ +class PROJ_GCC_DLL PROJStringFormatter { + public: + /** PROJ variant. */ + enum class PROJ_MSVC_DLL Convention { + /** PROJ v5 (or later versions) string. */ + PROJ_5, + + /** PROJ v4 string as output by GDAL exportToProj4() */ + PROJ_4 + }; + + PROJ_DLL static PROJStringFormatterNNPtr + create(Convention conventionIn = Convention::PROJ_5, + DatabaseContextPtr dbContext = nullptr); + //! @cond Doxygen_Suppress + PROJ_DLL ~PROJStringFormatter(); + //! @endcond + + PROJ_DLL void setUseETMercForTMerc(bool flag); + + PROJ_DLL const std::string &toString() const; + + PROJ_PRIVATE : + //! @cond Doxygen_Suppress + + PROJ_DLL void + startInversion(); + PROJ_DLL void stopInversion(); + PROJ_INTERNAL bool isInverted() const; + PROJ_INTERNAL bool getUseETMercForTMerc() const; + + PROJ_DLL void + ingestPROJString(const std::string &str); // throw ParsingException + + PROJ_DLL void addStep(const char *step); + PROJ_DLL void addStep(const std::string &step); + PROJ_DLL void setCurrentStepInverted(bool inverted); + PROJ_DLL void addParam(const std::string ¶mName); + PROJ_DLL void addParam(const char *paramName, double val); + PROJ_DLL void addParam(const std::string ¶mName, double val); + PROJ_DLL void addParam(const char *paramName, int val); + PROJ_DLL void addParam(const std::string ¶mName, int val); + PROJ_DLL void addParam(const char *paramName, const char *val); + PROJ_DLL void addParam(const char *paramName, const std::string &val); + PROJ_DLL void addParam(const std::string ¶mName, const char *val); + PROJ_DLL void addParam(const std::string ¶mName, + const std::string &val); + PROJ_DLL void addParam(const char *paramName, + const std::vector<double> &vals); + + PROJ_INTERNAL std::set<std::string> getUsedGridNames() const; + + PROJ_INTERNAL void setTOWGS84Parameters(const std::vector<double> ¶ms); + PROJ_INTERNAL const std::vector<double> &getTOWGS84Parameters() const; + + PROJ_INTERNAL void setVDatumExtension(const std::string &filename); + PROJ_INTERNAL const std::string &getVDatumExtension() const; + + PROJ_INTERNAL void setHDatumExtension(const std::string &filename); + PROJ_INTERNAL const std::string &getHDatumExtension() const; + + PROJ_INTERNAL void setOmitProjLongLatIfPossible(bool omit); + PROJ_INTERNAL bool omitProjLongLatIfPossible() const; + + PROJ_INTERNAL void setOmitZUnitConversion(bool omit); + PROJ_INTERNAL bool omitZUnitConversion() const; + + PROJ_INTERNAL const DatabaseContextPtr &databaseContext() const; + + PROJ_INTERNAL Convention convention() const; + + //! @endcond + + protected: + //! @cond Doxygen_Suppress + PROJ_INTERNAL explicit PROJStringFormatter( + Convention conventionIn, const DatabaseContextPtr &dbContext); + PROJStringFormatter(const PROJStringFormatter &other) = delete; + + INLINED_MAKE_UNIQUE + //! @endcond + + private: + PROJ_OPAQUE_PRIVATE_DATA +}; + +// --------------------------------------------------------------------------- + +/** \brief Exception possibly thrown by IWKTExportable::exportToWKT() or + * IPROJStringExportable::exportToPROJString(). */ +class PROJ_GCC_DLL FormattingException : public util::Exception { + public: + //! @cond Doxygen_Suppress + PROJ_INTERNAL explicit FormattingException(const char *message); + PROJ_INTERNAL explicit FormattingException(const std::string &message); + PROJ_DLL FormattingException(const FormattingException &other); + PROJ_DLL virtual ~FormattingException() override; + + PROJ_INTERNAL static void Throw(const char *msg) PROJ_NO_RETURN; + PROJ_INTERNAL static void Throw(const std::string &msg) PROJ_NO_RETURN; + //! @endcond +}; + +// --------------------------------------------------------------------------- + +/** \brief Exception possibly thrown by WKTNode::createFrom() or + * WKTParser::createFromWKT(). */ +class PROJ_GCC_DLL ParsingException : public util::Exception { + public: + //! @cond Doxygen_Suppress + PROJ_INTERNAL explicit ParsingException(const char *message); + PROJ_INTERNAL explicit ParsingException(const std::string &message); + PROJ_DLL ParsingException(const ParsingException &other); + PROJ_DLL virtual ~ParsingException() override; + //! @endcond +}; + +// --------------------------------------------------------------------------- + +/** \brief Interface for an object that can be exported to WKT. */ +class PROJ_GCC_DLL IWKTExportable { + public: + //! @cond Doxygen_Suppress + PROJ_DLL virtual ~IWKTExportable(); + //! @endcond + + /** Builds a WKT representation. May throw a FormattingException */ + PROJ_DLL std::string + exportToWKT(WKTFormatter *formatter) const; // throw(FormattingException) + + PROJ_PRIVATE : + + //! @cond Doxygen_Suppress + PROJ_INTERNAL virtual void + _exportToWKT( + WKTFormatter *formatter) const = 0; // throw(FormattingException) + //! @endcond +}; + +// --------------------------------------------------------------------------- + +class IPROJStringExportable; +/** Shared pointer of IPROJStringExportable. */ +using IPROJStringExportablePtr = std::shared_ptr<IPROJStringExportable>; +/** Non-null shared pointer of IPROJStringExportable. */ +using IPROJStringExportableNNPtr = util::nn<IPROJStringExportablePtr>; + +/** \brief Interface for an object that can be exported to a PROJ string. */ +class PROJ_GCC_DLL IPROJStringExportable { + public: + //! @cond Doxygen_Suppress + PROJ_DLL virtual ~IPROJStringExportable(); + //! @endcond + + /** \brief Builds a PROJ string representation. + * + * <ul> + * <li>For PROJStringFormatter::Convention::PROJ_5 (the default), return + * strings that generally express PROJ.5 pipelines. + * <ul> + * <li>For a crs::GeographicCRS, returns a string expressing the + * transformation from geographic coordinates expressed in radian with + * longitude, latitude order, and with respect to the international + * reference meridian, into geographic coordinates expressed in the units + * and axis order of the CRS, taking into account its prime meridian.</li> + * <li>For a geocentric crs::GeodeticCRS, returns a string expressing the + * transformation from geographic coordinates expressed in radian with + * longitude, latitude order, and with respect to the international + * reference meridian, into geocentric coordinates.</li> + * <li>For a + * crs::ProjectedCRS / crs::DerivedGeographicCRS / crs::DerivedProjectedCRS, + * returns a string expressing the transformation from the base CRS to the + * CRS</li> + * <li>For a crs::BoundCRS, throws a FormattingException.</li> + * <li>For operation::CoordinateTransformations, returns a PROJ + * pipeline.</li> + * </ul> + * + * <li>For PROJStringFormatter::Convention::PROJ_4, format a string + * compatible with the OGRSpatialReference::exportToProj4() of GDAL + * <=2.3. + * <ul> + * <li>For a crs::GeographicCRS, returns a proj=longlat string, with + * ellipsoid / datum / prime meridian information, ignoring axis order + * and unit information.</li> + * <li>For a geocentric crs::GeodeticCRS, returns the transformation from + * geographic coordinates into geocentric coordinates.</li> + * <li>For a crs::ProjectedCRS, returns the projection method, ignoring + * axis order.</li> + * <li>For a crs::BoundCRS, returns the PROJ string of its source/base CRS, + * amended with towgs84 / nadgrids parameter when the deriving conversion + * can be expressed in that way.</li> + * </ul> + * </li> + * + * </ul> + * + * @param formatter PROJ string formatter. + * @return a PROJ string. + * @throw FormattingException */ + PROJ_DLL std::string exportToPROJString( + PROJStringFormatter *formatter) const; // throw(FormattingException) + + PROJ_PRIVATE : + + //! @cond Doxygen_Suppress + PROJ_INTERNAL virtual void + _exportToPROJString(PROJStringFormatter *formatter) + const = 0; // throw(FormattingException) + //! @endcond +}; + +// --------------------------------------------------------------------------- + +class WKTNode; +/** Unique pointer of WKTNode. */ +using WKTNodePtr = std::unique_ptr<WKTNode>; +/** Non-null unique pointer of WKTNode. */ +using WKTNodeNNPtr = util::nn<WKTNodePtr>; + +/** \brief Node in the tree-splitted WKT representation. + */ +class PROJ_GCC_DLL WKTNode { + public: + PROJ_DLL explicit WKTNode(const std::string &valueIn); + //! @cond Doxygen_Suppress + PROJ_DLL ~WKTNode(); + //! @endcond + + PROJ_DLL const std::string &value() const; + PROJ_DLL const std::vector<WKTNodeNNPtr> &children() const; + + PROJ_DLL void addChild(WKTNodeNNPtr &&child); + PROJ_DLL const WKTNodePtr &lookForChild(const std::string &childName, + int occurrence = 0) const noexcept; + PROJ_DLL int countChildrenOfName(const std::string &childName) const + noexcept; + + PROJ_DLL std::string toString() const; + + PROJ_DLL static WKTNodeNNPtr createFrom(const std::string &wkt, + size_t indexStart = 0); + + protected: + PROJ_INTERNAL static WKTNodeNNPtr + createFrom(const std::string &wkt, size_t indexStart, int recLevel, + size_t &indexEnd); // throw(ParsingException) + + private: + friend class WKTParser; + PROJ_OPAQUE_PRIVATE_DATA +}; + +// --------------------------------------------------------------------------- + +PROJ_DLL util::BaseObjectNNPtr +createFromUserInput(const std::string &text, + const DatabaseContextPtr &dbContext); + +// --------------------------------------------------------------------------- + +/** \brief Parse a WKT string into the appropriate suclass of util::BaseObject. + */ +class PROJ_GCC_DLL WKTParser { + public: + PROJ_DLL WKTParser(); + //! @cond Doxygen_Suppress + PROJ_DLL ~WKTParser(); + //! @endcond + + PROJ_DLL WKTParser & + attachDatabaseContext(const DatabaseContextPtr &dbContext); + + PROJ_DLL WKTParser &setStrict(bool strict); + PROJ_DLL std::vector<std::string> warningList() const; + + PROJ_DLL util::BaseObjectNNPtr + createFromWKT(const std::string &wkt); // throw(ParsingException) + + /** Guessed WKT "dialect" */ + enum class PROJ_MSVC_DLL WKTGuessedDialect { + /** \ref WKT2_2018 */ + WKT2_2018, + /** \ref WKT2_2015 */ + WKT2_2015, + /** \ref WKT1 */ + WKT1_GDAL, + /** ESRI variant of WKT1 */ + WKT1_ESRI, + /** Not WKT / unrecognized */ + NOT_WKT + }; + + // cppcheck-suppress functionStatic + PROJ_DLL WKTGuessedDialect guessDialect(const std::string &wkt) noexcept; + + private: + PROJ_OPAQUE_PRIVATE_DATA +}; + +// --------------------------------------------------------------------------- + +/** \brief Parse a PROJ string into the appropriate suclass of util::BaseObject. + */ +class PROJ_GCC_DLL PROJStringParser { + public: + PROJ_DLL PROJStringParser(); + //! @cond Doxygen_Suppress + PROJ_DLL ~PROJStringParser(); + //! @endcond + + PROJ_DLL PROJStringParser & + attachDatabaseContext(const DatabaseContextPtr &dbContext); + + PROJ_DLL std::vector<std::string> warningList() const; + + PROJ_DLL util::BaseObjectNNPtr createFromPROJString( + const std::string &projString); // throw(ParsingException) + + private: + PROJ_OPAQUE_PRIVATE_DATA +}; + +// --------------------------------------------------------------------------- + +/** \brief Database context. + * + * A database context should be used only by one thread at a time. + */ +class PROJ_GCC_DLL DatabaseContext { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~DatabaseContext(); + //! @endcond + + PROJ_DLL static DatabaseContextNNPtr create(); + + PROJ_DLL static DatabaseContextNNPtr + create(const std::string &databasePath); + + PROJ_DLL static DatabaseContextNNPtr + create(const std::string &databasePath, + const std::vector<std::string> &auxiliaryDatabasePaths); + + PROJ_DLL const std::string &getPath() const; + + PROJ_DLL std::set<std::string> getAuthorities() const; + + PROJ_DLL std::vector<std::string> getDatabaseStructure() const; + + PROJ_PRIVATE : + //! @cond Doxygen_Suppress + PROJ_DLL void * + getSqliteHandle() const; + + PROJ_DLL static DatabaseContextNNPtr create(void *sqlite_handle); + + PROJ_INTERNAL void attachPJContext(void *pjCtxt); + + PROJ_INTERNAL bool lookForGridAlternative(const std::string &officialName, + std::string &projFilename, + std::string &projFormat, + bool &inverse) const; + + PROJ_DLL bool lookForGridInfo(const std::string &projFilename, + std::string &fullFilename, + std::string &packageName, std::string &url, + bool &directDownload, bool &openLicense, + bool &gridAvailable) const; + + PROJ_INTERNAL std::string + getAliasFromOfficialName(const std::string &officialName, + const std::string &tableName, + const std::string &source) const; + + PROJ_INTERNAL bool isKnownName(const std::string &name, + const std::string &tableName) const; + + //! @endcond + + protected: + PROJ_INTERNAL DatabaseContext(); + INLINED_MAKE_SHARED + PROJ_FRIEND(AuthorityFactory); + + private: + PROJ_OPAQUE_PRIVATE_DATA + DatabaseContext(const DatabaseContext &) = delete; + DatabaseContext &operator=(const DatabaseContext &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class AuthorityFactory; +/** Shared pointer of AuthorityFactory. */ +using AuthorityFactoryPtr = std::shared_ptr<AuthorityFactory>; +/** Non-null shared pointer of AuthorityFactory. */ +using AuthorityFactoryNNPtr = util::nn<AuthorityFactoryPtr>; + +/** \brief Builds object from an authority database. + * + * A AuthorityFactory should be used only by one thread at a time. + * + * \remark Implements [AuthorityFactory] + * (http://www.geoapi.org/3.0/javadoc/org/opengis/referencing/AuthorityFactory.html) + * from \ref GeoAPI + */ +class PROJ_GCC_DLL AuthorityFactory { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~AuthorityFactory(); + //! @endcond + + PROJ_DLL util::BaseObjectNNPtr createObject(const std::string &code) const; + + PROJ_DLL common::UnitOfMeasureNNPtr + createUnitOfMeasure(const std::string &code) const; + + PROJ_DLL metadata::ExtentNNPtr createExtent(const std::string &code) const; + + PROJ_DLL datum::PrimeMeridianNNPtr + createPrimeMeridian(const std::string &code) const; + + PROJ_DLL std::string identifyBodyFromSemiMajorAxis(double a, + double tolerance) const; + + PROJ_DLL datum::EllipsoidNNPtr + createEllipsoid(const std::string &code) const; + + PROJ_DLL datum::DatumNNPtr createDatum(const std::string &code) const; + + PROJ_DLL datum::GeodeticReferenceFrameNNPtr + createGeodeticDatum(const std::string &code) const; + + PROJ_DLL datum::VerticalReferenceFrameNNPtr + createVerticalDatum(const std::string &code) const; + + PROJ_DLL cs::CoordinateSystemNNPtr + createCoordinateSystem(const std::string &code) const; + + PROJ_DLL crs::GeodeticCRSNNPtr + createGeodeticCRS(const std::string &code) const; + + PROJ_DLL crs::GeographicCRSNNPtr + createGeographicCRS(const std::string &code) const; + + PROJ_DLL crs::VerticalCRSNNPtr + createVerticalCRS(const std::string &code) const; + + PROJ_DLL operation::ConversionNNPtr + createConversion(const std::string &code) const; + + PROJ_DLL crs::ProjectedCRSNNPtr + createProjectedCRS(const std::string &code) const; + + PROJ_DLL crs::CompoundCRSNNPtr + createCompoundCRS(const std::string &code) const; + + PROJ_DLL crs::CRSNNPtr + createCoordinateReferenceSystem(const std::string &code) const; + + PROJ_DLL operation::CoordinateOperationNNPtr + createCoordinateOperation(const std::string &code, + bool usePROJAlternativeGridNames) const; + + PROJ_DLL std::vector<operation::CoordinateOperationNNPtr> + createFromCoordinateReferenceSystemCodes( + const std::string &sourceCRSCode, + const std::string &targetCRSCode) const; + + PROJ_DLL const std::string &getAuthority() PROJ_CONST_DECL; + + /** Object type. */ + enum class ObjectType { + /** Object of type datum::PrimeMeridian */ + PRIME_MERIDIAN, + /** Object of type datum::Ellipsoid */ + ELLIPSOID, + /** Object of type datum::Datum (and derived classes) */ + DATUM, + /** Object of type datum::GeodeticReferenceFrame (and derived + classes) */ + GEODETIC_REFERENCE_FRAME, + /** Object of type datum::VerticalReferenceFrame (and derived + classes) */ + VERTICAL_REFERENCE_FRAME, + /** Object of type crs::CRS (and derived classes) */ + CRS, + /** Object of type crs::GeodeticCRS (and derived classes) */ + GEODETIC_CRS, + /** GEODETIC_CRS of type geocentric */ + GEOCENTRIC_CRS, + /** Object of type crs::GeographicCRS (and derived classes) */ + GEOGRAPHIC_CRS, + /** GEOGRAPHIC_CRS of type Geographic 2D */ + GEOGRAPHIC_2D_CRS, + /** GEOGRAPHIC_CRS of type Geographic 3D */ + GEOGRAPHIC_3D_CRS, + /** Object of type crs::ProjectedCRS (and derived classes) */ + PROJECTED_CRS, + /** Object of type crs::VerticalCRS (and derived classes) */ + VERTICAL_CRS, + /** Object of type crs::CompoundCRS (and derived classes) */ + COMPOUND_CRS, + /** Object of type operation::CoordinateOperation (and derived + classes) */ + COORDINATE_OPERATION, + /** Object of type operation::Conversion (and derived classes) */ + CONVERSION, + /** Object of type operation::Transformation (and derived classes) + */ + TRANSFORMATION, + /** Object of type operation::ConcatenatedOperation (and derived + classes) */ + CONCATENATED_OPERATION, + }; + + PROJ_DLL std::set<std::string> + getAuthorityCodes(const ObjectType &type, + bool allowDeprecated = true) const; + + PROJ_DLL std::string getDescriptionText(const std::string &code) const; + + // non-standard + PROJ_DLL static AuthorityFactoryNNPtr + create(const DatabaseContextNNPtr &context, + const std::string &authorityName); + + PROJ_DLL const DatabaseContextNNPtr &databaseContext() const; + + PROJ_DLL std::vector<operation::CoordinateOperationNNPtr> + createFromCoordinateReferenceSystemCodes( + const std::string &sourceCRSAuthName, const std::string &sourceCRSCode, + const std::string &targetCRSAuthName, const std::string &targetCRSCode, + bool usePROJAlternativeGridNames, bool discardIfMissingGrid) const; + + PROJ_DLL std::vector<operation::CoordinateOperationNNPtr> + createFromCRSCodesWithIntermediates( + const std::string &sourceCRSAuthName, const std::string &sourceCRSCode, + const std::string &targetCRSAuthName, const std::string &targetCRSCode, + bool usePROJAlternativeGridNames, bool discardIfMissingGrid, + const std::vector<std::pair<std::string, std::string>> + &intermediateCRSAuthCodes) const; + + PROJ_DLL std::string getOfficialNameFromAlias( + const std::string &aliasedName, const std::string &tableName, + const std::string &source, std::string &outTableName, + std::string &outAuthName, std::string &outCode) const; + + PROJ_DLL std::list<common::IdentifiedObjectNNPtr> + createObjectsFromName(const std::string &name, + const std::vector<ObjectType> &allowedObjectTypes = + std::vector<ObjectType>(), + bool approximateMatch = true, + size_t limitResultCount = 0); + + PROJ_PRIVATE : + //! @cond Doxygen_Suppress + + PROJ_INTERNAL std::list<datum::EllipsoidNNPtr> + createEllipsoidFromExisting( + const datum::EllipsoidNNPtr &ellipsoid) const; + + PROJ_INTERNAL std::list<crs::GeodeticCRSNNPtr> + createGeodeticCRSFromDatum(const std::string &datum_auth_name, + const std::string &datum_code, + const std::string &geodetic_crs_type) const; + + PROJ_INTERNAL std::list<crs::GeodeticCRSNNPtr> + createGeodeticCRSFromEllipsoid(const std::string &ellipsoid_auth_name, + const std::string &ellipsoid_code, + const std::string &geodetic_crs_type) const; + + PROJ_INTERNAL std::list<crs::ProjectedCRSNNPtr> + createProjectedCRSFromExisting(const crs::ProjectedCRSNNPtr &crs) const; + + PROJ_INTERNAL std::list<crs::CompoundCRSNNPtr> + createCompoundCRSFromExisting(const crs::CompoundCRSNNPtr &crs) const; + //! @endcond + + protected: + PROJ_INTERNAL AuthorityFactory(const DatabaseContextNNPtr &context, + const std::string &authorityName); + + PROJ_INTERNAL crs::CRSNNPtr + createCoordinateReferenceSystem(const std::string &code, + bool allowCompound) const; + + PROJ_INTERNAL crs::GeodeticCRSNNPtr + createGeodeticCRS(const std::string &code, bool geographicOnly) const; + + PROJ_INTERNAL operation::CoordinateOperationNNPtr + createCoordinateOperation(const std::string &code, bool allowConcatenated, + bool usePROJAlternativeGridNames) const; + + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA +}; + +// --------------------------------------------------------------------------- + +/** \brief Exception thrown when a factory can't create an instance of the + * requested object. + */ +class PROJ_GCC_DLL FactoryException : public util::Exception { + public: + //! @cond Doxygen_Suppress + PROJ_DLL explicit FactoryException(const char *message); + PROJ_DLL explicit FactoryException(const std::string &message); + PROJ_DLL + FactoryException(const FactoryException &other); + PROJ_DLL ~FactoryException() override; + //! @endcond +}; + +// --------------------------------------------------------------------------- + +/** \brief Exception thrown when an authority factory can't find the requested + * authority code. + */ +class PROJ_GCC_DLL NoSuchAuthorityCodeException : public FactoryException { + public: + //! @cond Doxygen_Suppress + PROJ_DLL explicit NoSuchAuthorityCodeException(const std::string &message, + const std::string &authority, + const std::string &code); + PROJ_DLL + NoSuchAuthorityCodeException(const NoSuchAuthorityCodeException &other); + PROJ_DLL ~NoSuchAuthorityCodeException() override; + //! @endcond + + PROJ_DLL const std::string &getAuthority() const; + PROJ_DLL const std::string &getAuthorityCode() const; + + private: + PROJ_OPAQUE_PRIVATE_DATA +}; + +} // namespace io + +NS_PROJ_END + +#endif // IO_HH_INCLUDED diff --git a/include/proj/metadata.hpp b/include/proj/metadata.hpp new file mode 100644 index 00000000..fc86693d --- /dev/null +++ b/include/proj/metadata.hpp @@ -0,0 +1,458 @@ +/****************************************************************************** + * + * Project: PROJ + * Purpose: ISO19111:2018 implementation + * Author: Even Rouault <even dot rouault at spatialys dot com> + * + ****************************************************************************** + * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ****************************************************************************/ + +#ifndef METADATA_HH_INCLUDED +#define METADATA_HH_INCLUDED + +#include <memory> +#include <string> +#include <vector> + +#include "io.hpp" +#include "util.hpp" + +NS_PROJ_START + +namespace common { +class UnitOfMeasure; +using UnitOfMeasurePtr = std::shared_ptr<UnitOfMeasure>; +using UnitOfMeasureNNPtr = util::nn<UnitOfMeasurePtr>; +class IdentifiedObject; +} // namespace common + +/** osgeo.proj.metadata namespace + * + * \brief Common classes from \ref ISO_19115 standard + */ +namespace metadata { + +// --------------------------------------------------------------------------- + +/** \brief Standardized resource reference. + * + * Local names are names which are directly accessible to and maintained by a + * NameSpace within which they are local, indicated by the scope. + * + * \remark Simplified version of [Citation] + * (http://www.geoapi.org/3.0/javadoc/org/opengis/metadata/citation/Citation.html) + * from \ref GeoAPI + */ +class PROJ_GCC_DLL Citation : public util::BaseObject { + public: + PROJ_DLL explicit Citation(const std::string &titleIn); + //! @cond Doxygen_Suppress + PROJ_DLL Citation(); + PROJ_DLL Citation(const Citation &other); + PROJ_DLL ~Citation(); + //! @endcond + + PROJ_DLL const util::optional<std::string> &title() PROJ_CONST_DECL; + + protected: + PROJ_FRIEND_OPTIONAL(Citation); + PROJ_INTERNAL Citation &operator=(const Citation &other); + + private: + PROJ_OPAQUE_PRIVATE_DATA +}; + +// --------------------------------------------------------------------------- + +class GeographicExtent; +/** Shared pointer of GeographicExtent. */ +using GeographicExtentPtr = std::shared_ptr<GeographicExtent>; +/** Non-null shared pointer of GeographicExtent. */ +using GeographicExtentNNPtr = util::nn<GeographicExtentPtr>; + +/** \brief Base interface for geographic area of the dataset. + * + * \remark Simplified version of [GeographicExtent] + * (http://www.geoapi.org/3.0/javadoc/org/opengis/metadata/extent/GeographicExtent.html) + * from \ref GeoAPI + */ +class PROJ_GCC_DLL GeographicExtent : public util::BaseObject, + public util::IComparable { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~GeographicExtent() override; + //! @endcond + + // GeoAPI has a getInclusion() method. We assume that it is included for our + // use + + //! @cond Doxygen_Suppress + PROJ_INTERNAL bool _isEquivalentTo( + const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override = 0; + //! @endcond + + /** \brief Returns whether this extent contains the other one. */ + PROJ_DLL virtual bool + contains(const GeographicExtentNNPtr &other) const = 0; + + /** \brief Returns whether this extent intersects the other one. */ + PROJ_DLL virtual bool + intersects(const GeographicExtentNNPtr &other) const = 0; + + /** \brief Returns the intersection of this extent with another one. */ + PROJ_DLL virtual GeographicExtentPtr + intersection(const GeographicExtentNNPtr &other) const = 0; + + protected: + PROJ_INTERNAL GeographicExtent(); + + private: + PROJ_OPAQUE_PRIVATE_DATA +}; + +// --------------------------------------------------------------------------- + +class GeographicBoundingBox; +/** Shared pointer of GeographicBoundingBox. */ +using GeographicBoundingBoxPtr = std::shared_ptr<GeographicBoundingBox>; +/** Non-null shared pointer of GeographicBoundingBox. */ +using GeographicBoundingBoxNNPtr = util::nn<GeographicBoundingBoxPtr>; + +/** \brief Geographic position of the dataset. + * + * This is only an approximate so specifying the co-ordinate reference system is + * unnecessary. + * + * \remark Implements [GeographicBoundingBox] + * (http://www.geoapi.org/3.0/javadoc/org/opengis/metadata/extent/GeographicBoundingBox.html) + * from \ref GeoAPI + */ +class PROJ_GCC_DLL GeographicBoundingBox : public GeographicExtent { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~GeographicBoundingBox() override; + //! @endcond + + PROJ_DLL double westBoundLongitude() PROJ_CONST_DECL; + PROJ_DLL double southBoundLatitude() PROJ_CONST_DECL; + PROJ_DLL double eastBoundLongitude() PROJ_CONST_DECL; + PROJ_DLL double northBoundLatitude() PROJ_CONST_DECL; + + PROJ_DLL static GeographicBoundingBoxNNPtr + create(double west, double south, double east, double north); + + //! @cond Doxygen_Suppress + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + //! @endcond + + PROJ_INTERNAL bool + contains(const GeographicExtentNNPtr &other) const override; + + PROJ_INTERNAL bool + intersects(const GeographicExtentNNPtr &other) const override; + + PROJ_INTERNAL GeographicExtentPtr + intersection(const GeographicExtentNNPtr &other) const override; + + protected: + PROJ_INTERNAL GeographicBoundingBox(double west, double south, double east, + double north); + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA +}; + +// --------------------------------------------------------------------------- + +class TemporalExtent; +/** Shared pointer of TemporalExtent. */ +using TemporalExtentPtr = std::shared_ptr<TemporalExtent>; +/** Non-null shared pointer of TemporalExtent. */ +using TemporalExtentNNPtr = util::nn<TemporalExtentPtr>; + +/** \brief Time period covered by the content of the dataset. + * + * \remark Simplified version of [TemporalExtent] + * (http://www.geoapi.org/3.0/javadoc/org/opengis/metadata/extent/TemporalExtent.html) + * from \ref GeoAPI + */ +class PROJ_GCC_DLL TemporalExtent : public util::BaseObject, + public util::IComparable { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~TemporalExtent() override; + //! @endcond + + PROJ_DLL const std::string &start() PROJ_CONST_DECL; + PROJ_DLL const std::string &stop() PROJ_CONST_DECL; + + PROJ_DLL static TemporalExtentNNPtr create(const std::string &start, + const std::string &stop); + + //! @cond Doxygen_Suppress + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + //! @endcond + + PROJ_DLL bool contains(const TemporalExtentNNPtr &other) const; + + PROJ_DLL bool intersects(const TemporalExtentNNPtr &other) const; + + protected: + PROJ_INTERNAL TemporalExtent(const std::string &start, + const std::string &stop); + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA +}; + +// --------------------------------------------------------------------------- + +class VerticalExtent; +/** Shared pointer of VerticalExtent. */ +using VerticalExtentPtr = std::shared_ptr<VerticalExtent>; +/** Non-null shared pointer of VerticalExtent. */ +using VerticalExtentNNPtr = util::nn<VerticalExtentPtr>; + +/** \brief Vertical domain of dataset. + * + * \remark Simplified version of [VerticalExtent] + * (http://www.geoapi.org/3.0/javadoc/org/opengis/metadata/extent/VerticalExtent.html) + * from \ref GeoAPI + */ +class PROJ_GCC_DLL VerticalExtent : public util::BaseObject, + public util::IComparable { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~VerticalExtent() override; + //! @endcond + + PROJ_DLL double minimumValue() PROJ_CONST_DECL; + PROJ_DLL double maximumValue() PROJ_CONST_DECL; + PROJ_DLL common::UnitOfMeasureNNPtr &unit() PROJ_CONST_DECL; + + PROJ_DLL static VerticalExtentNNPtr + create(double minimumValue, double maximumValue, + const common::UnitOfMeasureNNPtr &unitIn); + + //! @cond Doxygen_Suppress + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + //! @endcond + + PROJ_DLL bool contains(const VerticalExtentNNPtr &other) const; + + PROJ_DLL bool intersects(const VerticalExtentNNPtr &other) const; + + protected: + PROJ_INTERNAL VerticalExtent(double minimumValue, double maximumValue, + const common::UnitOfMeasureNNPtr &unitIn); + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA +}; + +// --------------------------------------------------------------------------- + +class Extent; +/** Shared pointer of Extent. */ +using ExtentPtr = std::shared_ptr<Extent>; +/** Non-null shared pointer of Extent. */ +using ExtentNNPtr = util::nn<ExtentPtr>; + +/** \brief Information about spatial, vertical, and temporal extent. + * + * \remark Simplified version of [Extent] + * (http://www.geoapi.org/3.0/javadoc/org/opengis/metadata/extent/Extent.html) + * from \ref GeoAPI + */ +class PROJ_GCC_DLL Extent : public util::BaseObject, public util::IComparable { + public: + //! @cond Doxygen_Suppress + PROJ_DLL Extent(const Extent &other); + PROJ_DLL ~Extent() override; + //! @endcond + + PROJ_DLL const util::optional<std::string> &description() PROJ_CONST_DECL; + PROJ_DLL const std::vector<GeographicExtentNNPtr> & + geographicElements() PROJ_CONST_DECL; + PROJ_DLL const std::vector<TemporalExtentNNPtr> & + temporalElements() PROJ_CONST_DECL; + PROJ_DLL const std::vector<VerticalExtentNNPtr> & + verticalElements() PROJ_CONST_DECL; + + PROJ_DLL static ExtentNNPtr + create(const util::optional<std::string> &descriptionIn, + const std::vector<GeographicExtentNNPtr> &geographicElementsIn, + const std::vector<VerticalExtentNNPtr> &verticalElementsIn, + const std::vector<TemporalExtentNNPtr> &temporalElementsIn); + + PROJ_DLL static ExtentNNPtr + createFromBBOX(double west, double south, double east, double north, + const util::optional<std::string> &descriptionIn = + util::optional<std::string>()); + + //! @cond Doxygen_Suppress + PROJ_INTERNAL bool + _isEquivalentTo(const util::IComparable *other, + util::IComparable::Criterion criterion = + util::IComparable::Criterion::STRICT) const override; + //! @endcond + + PROJ_DLL bool contains(const ExtentNNPtr &other) const; + + PROJ_DLL bool intersects(const ExtentNNPtr &other) const; + + PROJ_DLL ExtentPtr intersection(const ExtentNNPtr &other) const; + + PROJ_DLL static const ExtentNNPtr WORLD; + + protected: + PROJ_INTERNAL Extent(); + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA + Extent &operator=(const Extent &other) = delete; +}; + +// --------------------------------------------------------------------------- + +class Identifier; +/** Shared pointer of Identifier. */ +using IdentifierPtr = std::shared_ptr<Identifier>; +/** Non-null shared pointer of Identifier. */ +using IdentifierNNPtr = util::nn<IdentifierPtr>; + +/** \brief Value uniquely identifying an object within a namespace. + * + * \remark Implements Identifier as described in \ref ISO_19111_2018 but which + * originates from \ref ISO_19115 + */ +class PROJ_GCC_DLL Identifier : public util::BaseObject, + public io::IWKTExportable { + public: + //! @cond Doxygen_Suppress + PROJ_DLL Identifier(const Identifier &other); + PROJ_DLL ~Identifier() override; + //! @endcond + + PROJ_DLL static IdentifierNNPtr + create(const std::string &codeIn = std::string(), + const util::PropertyMap &properties = + util::PropertyMap()); // throw(InvalidValueTypeException) + + PROJ_DLL static const std::string AUTHORITY_KEY; + PROJ_DLL static const std::string CODE_KEY; + PROJ_DLL static const std::string CODESPACE_KEY; + PROJ_DLL static const std::string VERSION_KEY; + PROJ_DLL static const std::string DESCRIPTION_KEY; + PROJ_DLL static const std::string URI_KEY; + + PROJ_DLL static const std::string EPSG; + PROJ_DLL static const std::string OGC; + + PROJ_DLL const util::optional<Citation> &authority() PROJ_CONST_DECL; + PROJ_DLL const std::string &code() PROJ_CONST_DECL; + PROJ_DLL const util::optional<std::string> &codeSpace() PROJ_CONST_DECL; + PROJ_DLL const util::optional<std::string> &version() PROJ_CONST_DECL; + PROJ_DLL const util::optional<std::string> &description() PROJ_CONST_DECL; + PROJ_DLL const util::optional<std::string> &uri() PROJ_CONST_DECL; + + PROJ_DLL static bool isEquivalentName(const char *a, + const char *b) noexcept; + + PROJ_PRIVATE : + //! @cond Doxygen_Suppress + PROJ_INTERNAL static std::string + canonicalizeName(const std::string &str); + + PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter) + const override; // throw(io::FormattingException) + + //! @endcond + + protected: + PROJ_INTERNAL explicit Identifier(const std::string &codeIn, + const util::PropertyMap &properties); + + PROJ_FRIEND_OPTIONAL(Identifier); + INLINED_MAKE_SHARED + Identifier &operator=(const Identifier &other) = delete; + + PROJ_FRIEND(common::IdentifiedObject); + + private: + PROJ_OPAQUE_PRIVATE_DATA +}; + +// --------------------------------------------------------------------------- + +class PositionalAccuracy; +/** Shared pointer of PositionalAccuracy. */ +using PositionalAccuracyPtr = std::shared_ptr<PositionalAccuracy>; +/** Non-null shared pointer of PositionalAccuracy. */ +using PositionalAccuracyNNPtr = util::nn<PositionalAccuracyPtr>; + +/** \brief Accuracy of the position of features. + * + * \remark Simplified version of [PositionalAccuracy] + * (http://www.geoapi.org/3.0/javadoc/org/opengis/metadata/quality/PositionalAccuracy.html) + * from \ref GeoAPI, which originates from \ref ISO_19115 + */ +class PROJ_GCC_DLL PositionalAccuracy : public util::BaseObject { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~PositionalAccuracy() override; + //! @endcond + + PROJ_DLL const std::string &value() PROJ_CONST_DECL; + + PROJ_DLL static PositionalAccuracyNNPtr create(const std::string &valueIn); + + protected: + PROJ_INTERNAL explicit PositionalAccuracy(const std::string &valueIn); + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA + PositionalAccuracy(const PositionalAccuracy &other) = delete; + PositionalAccuracy &operator=(const PositionalAccuracy &other) = delete; +}; + +} // namespace metadata + +NS_PROJ_END + +#endif // METADATA_HH_INCLUDED diff --git a/include/proj/nn.hpp b/include/proj/nn.hpp new file mode 100644 index 00000000..4b17a17d --- /dev/null +++ b/include/proj/nn.hpp @@ -0,0 +1,385 @@ +#pragma once + +/* + * Copyright (c) 2015 Dropbox, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cassert> +#include <cstdlib> +#include <functional> +#include <memory> +#include <type_traits> + +namespace dropbox { +namespace oxygen { + +// Marker type and value for use by nn below. +struct i_promise_i_checked_for_null_t {}; +static constexpr i_promise_i_checked_for_null_t i_promise_i_checked_for_null{}; + +// Helper to get the type pointed to by a raw or smart pointer. This can be +// explicitly +// specialized if need be to provide compatibility with user-defined smart +// pointers. +namespace nn_detail { +template <typename T> struct element_type { + using type = typename T::element_type; +}; +template <typename Pointee> struct element_type<Pointee *> { + using type = Pointee; +}; +} + +template <typename PtrType> class nn; + +// Trait to check whether a given type is a non-nullable pointer +template <typename T> struct is_nn : public std::false_type {}; +template <typename PtrType> +struct is_nn<nn<PtrType>> : public std::true_type {}; + +/* nn<PtrType> + * + * Wrapper around a pointer that is guaranteed to not be null. This works with + * raw pointers + * as well as any smart pointer: nn<int *>, nn<shared_ptr<DbxTable>>, + * nn<unique_ptr<Foo>>, + * etc. An nn<PtrType> can be used just like a PtrType. + * + * An nn<PtrType> can be constructed from another nn<PtrType>, if the underlying + * type would + * allow such construction. For example, nn<shared_ptr<PtrType>> can be copied + * and moved, but + * nn<unique_ptr<PtrType>> can only be moved; an nn<unique_ptr<PtrType>> can be + * explicitly + * (but not implicitly) created from an nn<PtrType*>; implicit upcasts are + * allowed; and so on. + * + * Similarly, non-nullable pointers can be compared with regular or other + * non-nullable + * pointers, using the same rules as the underlying pointer types. + * + * This module also provides helpers for creating an nn<PtrType> from operations + * that would + * always return a non-null pointer: nn_make_unique, nn_make_shared, + * nn_shared_from_this, and + * nn_addr (a replacement for operator&). + * + * We abbreviate nn<unique_ptr> as nn_unique_ptr - it's a little more readable. + * Likewise, + * nn<shared_ptr> can be written as nn_shared_ptr. + * + * Finally, we define macros NN_CHECK_ASSERT and NN_CHECK_THROW, to convert a + * nullable pointer + * to a non-nullable pointer. At Dropbox, these use customized error-handling + * infrastructure + * and are in a separate file. We've included sample implementations here. + */ +template <typename PtrType> class nn { +public: + static_assert(!is_nn<PtrType>::value, "nn<nn<T>> is disallowed"); + + using element_type = typename nn_detail::element_type<PtrType>::type; + + // Pass through calls to operator* and operator-> transparently + element_type &operator*() const { return *ptr; } + element_type *operator->() const { return &*ptr; } + + // Expose the underlying PtrType + operator const PtrType &() const & { return ptr; } + operator PtrType &&() && { return std::move(ptr); } + + // Trying to use the assignment operator to assign a nn<PtrType> to a PtrType + // using the + // above conversion functions hits an ambiguous resolution bug in clang: + // http://llvm.org/bugs/show_bug.cgi?id=18359 + // While that exists, we can use these as simple ways of accessing the + // underlying type + // (instead of workarounds calling the operators explicitly or adding a + // constructor call). + const PtrType &as_nullable() const & { return ptr; } + PtrType &&as_nullable() && { return std::move(ptr); } + + // Can't convert to bool (that would be silly). The explicit delete results in + // "value of type 'nn<...>' is not contextually convertible to 'bool'", rather + // than + // "no viable conversion", which is a bit more clear. + operator bool() const = delete; + + // Explicitly deleted constructors. These help produce clearer error messages, + // as trying + // to use them will result in clang printing the whole line, including the + // comment. + nn(std::nullptr_t) = delete; // nullptr is not allowed here + nn &operator=(std::nullptr_t) = delete; // nullptr is not allowed here + nn(PtrType) = delete; // must use NN_CHECK_ASSERT or NN_CHECK_THROW + nn &operator=(PtrType) = delete; // must use NN_CHECK_ASSERT or NN_CHECK_THROW + //PROJ_DLL ~nn(); + + // Semi-private constructor for use by NN_CHECK_ macros. + explicit nn(i_promise_i_checked_for_null_t, const PtrType &arg) noexcept : ptr(arg) { + } + explicit nn(i_promise_i_checked_for_null_t, PtrType &&arg) noexcept + : ptr(std::move(arg)) { + } + + // Type-converting move and copy constructor. We have four separate cases + // here, for + // implicit and explicit move and copy. + template <typename OtherType, + typename std::enable_if< + std::is_constructible<PtrType, OtherType>::value && + !std::is_convertible<OtherType, PtrType>::value, + int>::type = 0> + explicit nn(const nn<OtherType> &other) + : ptr(other.operator const OtherType &()) {} + + template <typename OtherType, + typename std::enable_if< + std::is_constructible<PtrType, OtherType>::value && + !std::is_convertible<OtherType, PtrType>::value && + !std::is_pointer<OtherType>::value, + int>::type = 0> + explicit nn(nn<OtherType> &&other) + : ptr(std::move(other).operator OtherType &&()) {} + + template <typename OtherType, + typename std::enable_if< + std::is_convertible<OtherType, PtrType>::value, int>::type = 0> + nn(const nn<OtherType> &other) : ptr(other.operator const OtherType &()) {} + + template < + typename OtherType, + typename std::enable_if<std::is_convertible<OtherType, PtrType>::value && + !std::is_pointer<OtherType>::value, + int>::type = 0> + nn(nn<OtherType> &&other) : ptr(std::move(other).operator OtherType &&()) {} + + // A type-converting move and copy assignment operator aren't necessary; + // writing + // "base_ptr = derived_ptr;" will run the type-converting constructor followed + // by the + // implicit move assignment operator. + + // Two-argument constructor, designed for use with the shared_ptr aliasing + // constructor. + // This will not be instantiated if PtrType doesn't have a suitable + // constructor. + template < + typename OtherType, + typename std::enable_if< + std::is_constructible<PtrType, OtherType, element_type *>::value, + int>::type = 0> + nn(const nn<OtherType> &ownership_ptr, nn<element_type *> target_ptr) + : ptr(ownership_ptr.operator const OtherType &(), target_ptr) {} + + // Comparisons. Other comparisons are implemented in terms of these. + template <typename L, typename R> + friend bool operator==(const nn<L> &, const R &); + template <typename L, typename R> + friend bool operator==(const L &, const nn<R> &); + template <typename L, typename R> + friend bool operator==(const nn<L> &, const nn<R> &); + + template <typename L, typename R> + friend bool operator<(const nn<L> &, const R &); + template <typename L, typename R> + friend bool operator<(const L &, const nn<R> &); + template <typename L, typename R> + friend bool operator<(const nn<L> &, const nn<R> &); + + // ostream operator + template <typename T> + friend std::ostream &operator<<(std::ostream &, const nn<T> &); + + template <typename T = PtrType> element_type *get() const { + return ptr.get(); + } + +private: + // Backing pointer + PtrType ptr; +}; + +// Base comparisons - these are friends of nn<PtrType>, so they can access .ptr +// directly. +template <typename L, typename R> bool operator==(const nn<L> &l, const R &r) { + return l.ptr == r; +} +template <typename L, typename R> bool operator==(const L &l, const nn<R> &r) { + return l == r.ptr; +} +template <typename L, typename R> +bool operator==(const nn<L> &l, const nn<R> &r) { + return l.ptr == r.ptr; +} +template <typename L, typename R> bool operator<(const nn<L> &l, const R &r) { + return l.ptr < r; +} +template <typename L, typename R> bool operator<(const L &l, const nn<R> &r) { + return l < r.ptr; +} +template <typename L, typename R> +bool operator<(const nn<L> &l, const nn<R> &r) { + return l.ptr < r.ptr; +} +template <typename T> +std::ostream &operator<<(std::ostream &os, const nn<T> &p) { + return os << p.ptr; +} + +#define NN_DERIVED_OPERATORS(op, base) \ + template <typename L, typename R> \ + bool operator op(const nn<L> &l, const R &r) { \ + return base; \ + } \ + template <typename L, typename R> \ + bool operator op(const L &l, const nn<R> &r) { \ + return base; \ + } \ + template <typename L, typename R> \ + bool operator op(const nn<L> &l, const nn<R> &r) { \ + return base; \ + } + +NN_DERIVED_OPERATORS(>, r < l) +NN_DERIVED_OPERATORS(<=, !(l > r)) +NN_DERIVED_OPERATORS(>=, !(l < r)) +NN_DERIVED_OPERATORS(!=, !(l == r)) + +#undef NN_DERIVED_OPERATORS + +// Convenience typedefs +template <typename T> using nn_unique_ptr = nn<std::unique_ptr<T>>; +template <typename T> using nn_shared_ptr = nn<std::shared_ptr<T>>; + +template <typename T, typename... Args> +nn_unique_ptr<T> nn_make_unique(Args &&... args) { + return nn_unique_ptr<T>( + i_promise_i_checked_for_null, + std::unique_ptr<T>(new T(std::forward<Args>(args)...))); +} + +template <typename T, typename... Args> +nn_shared_ptr<T> nn_make_shared(Args &&... args) { + return nn_shared_ptr<T>(i_promise_i_checked_for_null, + std::make_shared<T>(std::forward<Args>(args)...)); +} + +template <typename T> +class nn_enable_shared_from_this : public std::enable_shared_from_this<T> { +public: + using std::enable_shared_from_this<T>::enable_shared_from_this; + nn_shared_ptr<T> nn_shared_from_this() { + return nn_shared_ptr<T>(i_promise_i_checked_for_null, + this->shared_from_this()); + } + nn_shared_ptr<const T> nn_shared_from_this() const { + return nn_shared_ptr<const T>(i_promise_i_checked_for_null, + this->shared_from_this()); + } +}; + +template <typename T> nn<T *> nn_addr(T &object) { + return nn<T *>(i_promise_i_checked_for_null, &object); +} + +template <typename T> nn<const T *> nn_addr(const T &object) { + return nn<const T *>(i_promise_i_checked_for_null, &object); +} + +/* Non-nullable equivalents of shared_ptr's specialized casting functions. + * These convert through a shared_ptr since nn<shared_ptr<T>> lacks the + * ref-count-sharing cast + * constructor, but thanks to moves there shouldn't be any significant extra + * cost. */ +template <typename T, typename U> +nn_shared_ptr<T> nn_static_pointer_cast(const nn_shared_ptr<U> &org_ptr) { + auto raw_ptr = + static_cast<typename nn_shared_ptr<T>::element_type *>(org_ptr.get()); + std::shared_ptr<T> nullable_ptr(org_ptr.as_nullable(), raw_ptr); + return nn_shared_ptr<T>(i_promise_i_checked_for_null, + std::move(nullable_ptr)); +} + +template <typename T, typename U> +std::shared_ptr<T> nn_dynamic_pointer_cast(const nn_shared_ptr<U> &org_ptr) { + auto raw_ptr = + dynamic_cast<typename std::shared_ptr<T>::element_type *>(org_ptr.get()); + if (!raw_ptr) { + return nullptr; + } else { + return std::shared_ptr<T>(org_ptr.as_nullable(), raw_ptr); + } +} + +template <typename T, typename U> +nn_shared_ptr<T> nn_const_pointer_cast(const nn_shared_ptr<U> &org_ptr) { + auto raw_ptr = + const_cast<typename nn_shared_ptr<T>::element_type *>(org_ptr.get()); + std::shared_ptr<T> nullable_ptr(org_ptr.as_nullable(), raw_ptr); + return nn_shared_ptr<T>(i_promise_i_checked_for_null, + std::move(nullable_ptr)); +} +} +} /* end namespace dropbox::oxygen */ + +namespace std { +template <typename T> struct hash<::dropbox::oxygen::nn<T>> { + using argument_type = ::dropbox::oxygen::nn<T>; + using result_type = size_t; + result_type operator()(const argument_type &obj) const { + return std::hash<T>{}(obj.as_nullable()); + } +}; +} + +/* These have to be macros because our internal versions invoke other macros + * that use + * __FILE__ and __LINE__, which we want to correctly point to the call site. + * We're looking + * forward to std::source_location :) + * + * The lambdas ensure that we only evaluate _e once. + */ +#include <stdexcept> + +// NN_CHECK_ASSERT takes a pointer of type PT (e.g. raw pointer, std::shared_ptr +// or std::unique_ptr) +// and returns a non-nullable pointer of type nn<PT>. +// Triggers an assertion if expression evaluates to null. +#define NN_CHECK_ASSERT(_e) \ + (([&](typename std::remove_reference<decltype(_e)>::type p) { \ + /* note: assert() alone is not sufficient here, because it might be \ + * compiled out. */ \ + assert(p &&#_e " must not be null"); \ + if (!p) \ + std::abort(); \ + return dropbox::oxygen::nn< \ + typename std::remove_reference<decltype(p)>::type>( \ + dropbox::oxygen::i_promise_i_checked_for_null, std::move(p)); \ + })(_e)) + +// NN_CHECK_THROW takes a pointer of type PT (e.g. raw pointer, std::shared_ptr +// or std::unique_ptr) +// and returns a non-nullable pointer of type nn<PT>. +// Throws if expression evaluates to null. +#define NN_CHECK_THROW(_e) \ + (([&](typename std::remove_reference<decltype(_e)>::type p) { \ + if (!p) \ + throw std::runtime_error(#_e " must not be null"); \ + return dropbox::oxygen::nn< \ + typename std::remove_reference<decltype(p)>::type>( \ + dropbox::oxygen::i_promise_i_checked_for_null, std::move(p)); \ + })(_e)) diff --git a/include/proj/util.hpp b/include/proj/util.hpp new file mode 100644 index 00000000..eb7288b2 --- /dev/null +++ b/include/proj/util.hpp @@ -0,0 +1,752 @@ +/****************************************************************************** + * + * Project: PROJ + * Purpose: ISO19111:2018 implementation + * Author: Even Rouault <even dot rouault at spatialys dot com> + * + ****************************************************************************** + * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ****************************************************************************/ + +#ifndef UTIL_HH_INCLUDED +#define UTIL_HH_INCLUDED + +#if !(__cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)) +#error Must have C++11 or newer. +#endif + +#include <exception> +#include <map> +#include <memory> +#include <string> +#include <vector> + +#ifndef NS_PROJ +/** osgeo namespace */ +namespace osgeo { +/** osgeo.proj namespace */ +namespace proj {} +} // namespace osgeo +#endif + +//! @cond Doxygen_Suppress + +#ifndef PROJ_DLL +#ifdef PROJ_MSVC_DLL_EXPORT +#define PROJ_DLL __declspec(dllexport) +#elif defined(PROJ_MSVC_DLL_IMPORT) +#define PROJ_DLL __declspec(dllimport) +#elif defined(__GNUC__) +#define PROJ_DLL __attribute__((visibility("default"))) +#else +#define PROJ_DLL +#endif +#endif + +#ifndef PROJ_MSVC_DLL + +#ifdef PROJ_MSVC_DLL_EXPORT +#define PROJ_MSVC_DLL PROJ_DLL +#define PROJ_GCC_DLL +#define PROJ_INTERNAL +#elif defined(PROJ_MSVC_DLL_IMPORT) +#define PROJ_MSVC_DLL PROJ_DLL +#define PROJ_GCC_DLL +#define PROJ_INTERNAL +#elif defined(__GNUC__) +#define PROJ_MSVC_DLL +#define PROJ_GCC_DLL PROJ_DLL +#if !defined(__MINGW32__) +#define PROJ_INTERNAL __attribute__((visibility("hidden"))) +#else +#define PROJ_INTERNAL +#endif +#else +#define PROJ_MSVC_DLL +#define PROJ_GCC_DLL +#define PROJ_INTERNAL +#endif + +#define PROJ_FOR_TEST PROJ_DLL + +#endif + +#include "nn.hpp" + +/* To allow customizing the base namespace of PROJ */ +#ifndef NS_PROJ +#define NS_PROJ osgeo::proj +#define NS_PROJ_START \ + namespace osgeo { \ + namespace proj { +#define NS_PROJ_END \ + } \ + } +#endif + +// Private-implementation (Pimpl) pattern +#define PROJ_OPAQUE_PRIVATE_DATA \ + private: \ + struct PROJ_INTERNAL Private; \ + std::unique_ptr<Private> d; \ + \ + protected: \ + PROJ_INTERNAL Private *getPrivate() noexcept { return d.get(); } \ + PROJ_INTERNAL const Private *getPrivate() const noexcept { \ + return d.get(); \ + } \ + \ + private: + +// To include in the protected/private section of a class definition, +// to be able to call make_shared on a protected/private constructor +#define INLINED_MAKE_SHARED \ + template <typename T, typename... Args> \ + static std::shared_ptr<T> make_shared(Args &&... args) { \ + return std::shared_ptr<T>(new T(std::forward<Args>(args)...)); \ + } \ + template <typename T, typename... Args> \ + static util::nn_shared_ptr<T> nn_make_shared(Args &&... args) { \ + return util::nn_shared_ptr<T>( \ + util::i_promise_i_checked_for_null, \ + std::shared_ptr<T>(new T(std::forward<Args>(args)...))); \ + } + +// To include in the protected/private section of a class definition, +// to be able to call make_unique on a protected/private constructor +#define INLINED_MAKE_UNIQUE \ + template <typename T, typename... Args> \ + static std::unique_ptr<T> make_unique(Args &&... args) { \ + return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); \ + } + +#ifdef DOXYGEN_ENABLED +#define PROJ_FRIEND(mytype) +#define PROJ_FRIEND_OPTIONAL(mytype) +#else +#define PROJ_FRIEND(mytype) friend class mytype +#define PROJ_FRIEND_OPTIONAL(mytype) friend class util::optional<mytype> +#endif + +#ifndef PROJ_PRIVATE +#define PROJ_PRIVATE public +#endif + +#if defined(__GNUC__) +#define PROJ_NO_INLINE __attribute__((noinline)) +#define PROJ_NO_RETURN __attribute__((noreturn)) +// Applies to a function that has no side effect, and its return will not +// change if the arguments are the same. But is return may change +// if the object state changes. So this is for getters of mutable objects. +#define PROJ_PURE_DECL const noexcept __attribute__((pure)) +// Applies to a function that has no side effect, and its return will not +// change if the arguments are the same, and their pointed value must not +// be modified. So this is for getters of immutable objets. This is stronger +// than PROJ_PURE_DECL. +#if defined(__INTEL_COMPILER) +// If using __attribute__((const)), ICC on an expression like +// Angle(x).getSIValue() will create the object, destroy it and then call +// getSIValue(). Fallback to ((pure)), which is weaker +#define PROJ_CONST_DECL const noexcept __attribute__((pure)) +#else +#define PROJ_CONST_DECL const noexcept __attribute__((const)) +#endif +#else +#define PROJ_NO_RETURN +#define PROJ_NO_INLINE +#define PROJ_PURE_DECL const noexcept +#define PROJ_CONST_DECL const noexcept +#endif +#define PROJ_PURE_DEFN const noexcept +#define PROJ_CONST_DEFN const noexcept + +//! @endcond + +NS_PROJ_START + +/** osgeo.proj.util namespace. + * + * \brief A set of base types from ISO 19103, \ref GeoAPI and other PROJ + * specific classes. + */ +namespace util { + +//! @cond Doxygen_Suppress +// Import a few classes from nn.hpp to expose them under our ::util namespace +// for conveniency. +using ::dropbox::oxygen::i_promise_i_checked_for_null; +using ::dropbox::oxygen::nn; +using ::dropbox::oxygen::nn_dynamic_pointer_cast; +using ::dropbox::oxygen::nn_make_shared; + +// For return statements, to convert from derived type to base type +using ::dropbox::oxygen::nn_static_pointer_cast; + +template <typename T> using nn_shared_ptr = nn<std::shared_ptr<T>>; + +#define NN_NO_CHECK(p) \ + ::dropbox::oxygen::nn<typename std::remove_const< \ + typename std::remove_reference<decltype(p)>::type>::type>( \ + dropbox::oxygen::i_promise_i_checked_for_null, (p)) + +//! @endcond + +// To avoid formatting differences between clang-format 3.8 and 7 +#define PROJ_NOEXCEPT noexcept + +/** \brief Loose transposition of [std::optional] + * (https://en.cppreference.com/w/cpp/utility/optional) available from C++17. */ +template <class T> class optional { + public: + //! @cond Doxygen_Suppress + inline optional() : hasVal_(false) {} + inline explicit optional(const T &val) : hasVal_(true), val_(val) {} + inline explicit optional(T &&val) + : hasVal_(true), val_(std::forward<T>(val)) {} + + inline optional(const optional &other) = default; + inline optional(optional &&other) PROJ_NOEXCEPT + : hasVal_(other.hasVal_), + // cppcheck-suppress functionStatic + val_(std::forward<T>(other.val_)) { + other.hasVal_ = false; + } + + inline optional &operator=(const T &val) { + hasVal_ = true; + val_ = val; + return *this; + } + inline optional &operator=(T &&val) noexcept { + hasVal_ = true; + val_ = std::forward<T>(val); + return *this; + } + inline optional &operator=(const optional &other) = default; + inline optional &operator=(optional &&other) noexcept { + hasVal_ = other.hasVal_; + val_ = std::forward<T>(other.val_); + other.hasVal_ = false; + return *this; + } + + inline T *operator->() { return &val_; } + inline T &operator*() { return val_; } + + //! @endcond + + /** Returns a pointer to the contained value. */ + inline const T *operator->() const { return &val_; } + + /** Returns a reference to the contained value. */ + inline const T &operator*() const { return val_; } + + /** Return whether the optional has a value */ + inline explicit operator bool() const noexcept { return hasVal_; } + + /** Return whether the optional has a value */ + inline bool has_value() const noexcept { return hasVal_; } + + private: + bool hasVal_; + T val_{}; +}; + +// --------------------------------------------------------------------------- + +class BaseObject; +/** Shared pointer of BaseObject. */ +using BaseObjectPtr = std::shared_ptr<BaseObject>; +#if 1 +/** Non-null shared pointer of BaseObject. */ +struct BaseObjectNNPtr : public util::nn<BaseObjectPtr> { + // This trick enables to avoid inlining of the destructor. + // This is mostly an alias of the base class. + //! @cond Doxygen_Suppress + template <class T> + // cppcheck-suppress noExplicitConstructor + BaseObjectNNPtr(const util::nn<std::shared_ptr<T>> &x) + : util::nn<BaseObjectPtr>(x) {} + + template <class T> + // cppcheck-suppress noExplicitConstructor + BaseObjectNNPtr(util::nn<std::shared_ptr<T>> &&x) noexcept + : util::nn<BaseObjectPtr>(NN_NO_CHECK(std::move(x.as_nullable()))) {} + + explicit BaseObjectNNPtr(::dropbox::oxygen::i_promise_i_checked_for_null_t, + BaseObjectPtr &&arg) noexcept + : util::nn<BaseObjectPtr>(i_promise_i_checked_for_null, + std::move(arg)) {} + BaseObjectNNPtr(const BaseObjectNNPtr &) = default; + BaseObjectNNPtr &operator=(const BaseObjectNNPtr &) = default; + + PROJ_DLL ~BaseObjectNNPtr(); + //! @endcond +}; +#else +using BaseObjectNNPtr = util::nn<BaseObjectPtr>; +#endif + +/** \brief Class that can be derived from, to emulate Java's Object behaviour. + */ +class PROJ_GCC_DLL BaseObject { + public: + //! @cond Doxygen_Suppress + virtual PROJ_DLL ~BaseObject(); + //! @endcond + + PROJ_PRIVATE : + //! @cond Doxygen_Suppress + PROJ_INTERNAL BaseObjectNNPtr + shared_from_this() const; + //! @endcond + + protected: + PROJ_INTERNAL BaseObject(); + PROJ_INTERNAL void assignSelf(const BaseObjectNNPtr &self); + + private: + PROJ_OPAQUE_PRIVATE_DATA +}; + +// --------------------------------------------------------------------------- + +/** \brief Interface for an object that can be compared to another. + */ +class PROJ_GCC_DLL IComparable { + public: + //! @cond Doxygen_Suppress + PROJ_DLL virtual ~IComparable(); + //! @endcond + + /** \brief Comparison criterion. */ + enum class PROJ_MSVC_DLL Criterion { + /** All properties are identical. */ + STRICT, + + /** The objects are equivalent for the purpose of coordinate + * operations. They can differ by the name of their objects, + * identifiers, other metadata. + * Parameters may be expressed in different units, provided that the + * value is (with some tolerance) the same once expressed in a + * common unit. + */ + EQUIVALENT, + + /** Same as EQUIVALENT, relaxed with an exception that the axis order + * of the base CRS of a DerivedCRS/ProjectedCRS or the axis order of + * a GeographicCRS is ignored. Only to be used + * with DerivedCRS/ProjectedCRS/GeographicCRS */ + EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS, + }; + + PROJ_DLL bool isEquivalentTo(const IComparable *other, + Criterion criterion = Criterion::STRICT) const; + + PROJ_PRIVATE : + + //! @cond Doxygen_Suppress + PROJ_INTERNAL virtual bool + _isEquivalentTo(const IComparable *other, + Criterion criterion = Criterion::STRICT) const = 0; + //! @endcond +}; + +// --------------------------------------------------------------------------- + +/** \brief Encapsulate standard datatypes in an object. + */ +class BoxedValue final : public BaseObject { + public: + //! @cond Doxygen_Suppress + /** Type of data stored in the BoxedValue. */ + enum class Type { + /** a std::string */ + STRING, + /** an integer */ + INTEGER, + /** a boolean */ + BOOLEAN + }; + //! @endcond + + // cppcheck-suppress noExplicitConstructor + PROJ_DLL BoxedValue(const char *stringValueIn); // needed to avoid the bool + // constructor to be taken ! + // cppcheck-suppress noExplicitConstructor + PROJ_DLL BoxedValue(const std::string &stringValueIn); + // cppcheck-suppress noExplicitConstructor + PROJ_DLL BoxedValue(int integerValueIn); + // cppcheck-suppress noExplicitConstructor + PROJ_DLL BoxedValue(bool booleanValueIn); + + PROJ_PRIVATE : + //! @cond Doxygen_Suppress + PROJ_INTERNAL + BoxedValue(const BoxedValue &other); + + PROJ_DLL ~BoxedValue() override; + + PROJ_INTERNAL const Type &type() const; + PROJ_INTERNAL const std::string &stringValue() const; + PROJ_INTERNAL int integerValue() const; + PROJ_INTERNAL bool booleanValue() const; + //! @endcond + + private: + PROJ_OPAQUE_PRIVATE_DATA + BoxedValue &operator=(const BoxedValue &) = delete; + + PROJ_INTERNAL BoxedValue(); +}; + +/** Shared pointer of BoxedValue. */ +using BoxedValuePtr = std::shared_ptr<BoxedValue>; +/** Non-null shared pointer of BoxedValue. */ +using BoxedValueNNPtr = util::nn<BoxedValuePtr>; + +// --------------------------------------------------------------------------- + +class ArrayOfBaseObject; +/** Shared pointer of ArrayOfBaseObject. */ +using ArrayOfBaseObjectPtr = std::shared_ptr<ArrayOfBaseObject>; +/** Non-null shared pointer of ArrayOfBaseObject. */ +using ArrayOfBaseObjectNNPtr = util::nn<ArrayOfBaseObjectPtr>; + +/** \brief Array of BaseObject. + */ +class ArrayOfBaseObject final : public BaseObject { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~ArrayOfBaseObject() override; + //! @endcond + + PROJ_DLL void add(const BaseObjectNNPtr &obj); + + PROJ_DLL static ArrayOfBaseObjectNNPtr create(); + + PROJ_PRIVATE : + //! @cond Doxygen_Suppress + std::vector<BaseObjectNNPtr>::const_iterator + begin() const; + std::vector<BaseObjectNNPtr>::const_iterator end() const; + bool empty() const; + //! @endcond + + protected: + ArrayOfBaseObject(); + INLINED_MAKE_SHARED + + private: + ArrayOfBaseObject(const ArrayOfBaseObject &other) = delete; + ArrayOfBaseObject &operator=(const ArrayOfBaseObject &other) = delete; + PROJ_OPAQUE_PRIVATE_DATA +}; + +// --------------------------------------------------------------------------- + +/** \brief Wrapper of a std::map<std::string, BaseObjectNNPtr> */ +class PropertyMap { + public: + PROJ_DLL PropertyMap(); + //! @cond Doxygen_Suppress + PROJ_DLL PropertyMap(const PropertyMap &other); + PROJ_DLL ~PropertyMap(); + //! @endcond + + PROJ_DLL PropertyMap &set(const std::string &key, + const BaseObjectNNPtr &val); + + //! @cond Doxygen_Suppress + template <class T> + inline PropertyMap &set(const std::string &key, + const nn_shared_ptr<T> &val) { + return set( + key, BaseObjectNNPtr(i_promise_i_checked_for_null, + BaseObjectPtr(val.as_nullable(), val.get()))); + } + //! @endcond + + // needed to avoid the bool constructor to be taken ! + PROJ_DLL PropertyMap &set(const std::string &key, const char *val); + + PROJ_DLL PropertyMap &set(const std::string &key, const std::string &val); + + PROJ_DLL PropertyMap &set(const std::string &key, int val); + + PROJ_DLL PropertyMap &set(const std::string &key, bool val); + + PROJ_DLL PropertyMap &set(const std::string &key, + const std::vector<std::string> &array); + + PROJ_PRIVATE : + //! @cond Doxygen_Suppress + std::map<std::string, BaseObjectNNPtr>::iterator + find(const std::string &key) const; + std::map<std::string, BaseObjectNNPtr>::iterator end() const; + + // throw(InvalidValueTypeException) + bool getStringValue(const std::string &key, std::string &outVal) const; + + static PropertyMap createAndSetName(const char *name); + static PropertyMap createAndSetName(const std::string &name); + //! @endcond + + private: + PropertyMap &operator=(const PropertyMap &) = delete; + + PropertyMap &set(const std::string &key, const BoxedValue &val); + + PROJ_OPAQUE_PRIVATE_DATA +}; + +// --------------------------------------------------------------------------- + +class LocalName; +/** Shared pointer of LocalName. */ +using LocalNamePtr = std::shared_ptr<LocalName>; +/** Non-null shared pointer of LocalName. */ +using LocalNameNNPtr = util::nn<LocalNamePtr>; + +class NameSpace; +/** Shared pointer of NameSpace. */ +using NameSpacePtr = std::shared_ptr<NameSpace>; +/** Non-null shared pointer of NameSpace. */ +using NameSpaceNNPtr = util::nn<NameSpacePtr>; + +class GenericName; +/** Shared pointer of GenericName. */ +using GenericNamePtr = std::shared_ptr<GenericName>; +/** Non-null shared pointer of GenericName. */ +using GenericNameNNPtr = util::nn<GenericNamePtr>; + +// --------------------------------------------------------------------------- + +/** \brief A sequence of identifiers rooted within the context of a namespace. + * + * \remark Simplified version of [GenericName] + * (http://www.geoapi.org/3.0/javadoc/org/opengis/util/GenericName.html) from + * \ref GeoAPI + */ +class GenericName : public BaseObject { + public: + //! @cond Doxygen_Suppress + PROJ_DLL virtual ~GenericName() override; + //! @endcond + + /** \brief Return the scope of the object, possibly a global one. */ + PROJ_DLL virtual const NameSpacePtr scope() const = 0; + + /** \brief Return the LocalName as a string. */ + PROJ_DLL virtual std::string toString() const = 0; + + /** \brief Return a fully qualified name corresponding to the local name. + * + * The namespace of the resulting name is a global one. + */ + PROJ_DLL virtual GenericNameNNPtr toFullyQualifiedName() const = 0; + + protected: + GenericName(); + GenericName(const GenericName &other); + + private: + PROJ_OPAQUE_PRIVATE_DATA + GenericName &operator=(const GenericName &other) = delete; +}; + +// --------------------------------------------------------------------------- + +/** \brief A domain in which names given by strings are defined. + * + * \remark Simplified version of [NameSpace] + * (http://www.geoapi.org/3.0/javadoc/org/opengis/util/NameSpace.html) from \ref + * GeoAPI + */ +class NameSpace { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~NameSpace(); + //! @endcond + + PROJ_DLL bool isGlobal() const; + PROJ_DLL const GenericNamePtr &name() const; + + protected: + PROJ_FRIEND(NameFactory); + PROJ_FRIEND(LocalName); + explicit NameSpace(const GenericNamePtr &name); + NameSpace(const NameSpace &other); + NameSpaceNNPtr getGlobalFromThis() const; + const std::string &separator() const; + static const NameSpaceNNPtr GLOBAL; + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA + NameSpace &operator=(const NameSpace &other) = delete; + + static NameSpaceNNPtr createGLOBAL(); +}; + +// --------------------------------------------------------------------------- + +/** \brief Identifier within a NameSpace for a local object. + * + * Local names are names which are directly accessible to and maintained by a + * NameSpace within which they are local, indicated by the scope. + * + * \remark Simplified version of [LocalName] + * (http://www.geoapi.org/3.0/javadoc/org/opengis/util/LocalName.html) from \ref + * GeoAPI + */ +class LocalName : public GenericName { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~LocalName() override; + //! @endcond + + PROJ_DLL const NameSpacePtr scope() const override; + PROJ_DLL std::string toString() const override; + PROJ_DLL GenericNameNNPtr toFullyQualifiedName() const override; + + protected: + PROJ_FRIEND(NameFactory); + PROJ_FRIEND(NameSpace); + explicit LocalName(const std::string &nameIn); + LocalName(const LocalName &other); + LocalName(const NameSpacePtr &ns, const std::string &name); + INLINED_MAKE_SHARED + + private: + PROJ_OPAQUE_PRIVATE_DATA + LocalName &operator=(const LocalName &other) = delete; +}; + +// --------------------------------------------------------------------------- + +/** \brief Factory for generic names. + * + * \remark Simplified version of [NameFactory] + * (http://www.geoapi.org/3.0/javadoc/org/opengis/util/NameFactory.html) from + * \ref GeoAPI + */ +class NameFactory { + public: + PROJ_DLL static NameSpaceNNPtr + createNameSpace(const GenericNameNNPtr &name, + const PropertyMap &properties); + PROJ_DLL static LocalNameNNPtr createLocalName(const NameSpacePtr &scope, + const std::string &name); + PROJ_DLL static GenericNameNNPtr + createGenericName(const NameSpacePtr &scope, + const std::vector<std::string> &parsedNames); +}; + +// --------------------------------------------------------------------------- + +/** \brief Abstract class to define an enumeration of values. + */ +class CodeList { + public: + //! @cond Doxygen_Suppress + PROJ_DLL ~CodeList(); + //! @endcond + + /** Return the CodeList item as a string. */ + // cppcheck-suppress functionStatic + inline const std::string &toString() PROJ_CONST_DECL { return name_; } + + /** Return the CodeList item as a string. */ + inline operator std::string() PROJ_CONST_DECL { return toString(); } + + //! @cond Doxygen_Suppress + inline bool operator==(const CodeList &other) PROJ_CONST_DECL { + return name_ == other.name_; + } + inline bool operator!=(const CodeList &other) PROJ_CONST_DECL { + return name_ != other.name_; + } + //! @endcond + protected: + explicit CodeList(const std::string &nameIn) : name_(nameIn) {} + CodeList(const CodeList &other) = default; + CodeList &operator=(const CodeList &other); + + private: + std::string name_{}; +}; + +// --------------------------------------------------------------------------- + +/** \brief Root exception class. + */ +class PROJ_GCC_DLL Exception : public std::exception { + std::string msg_; + + public: + //! @cond Doxygen_Suppress + PROJ_INTERNAL explicit Exception(const char *message); + PROJ_INTERNAL explicit Exception(const std::string &message); + PROJ_DLL Exception(const Exception &other); + PROJ_DLL ~Exception() override; + //! @endcond + PROJ_DLL virtual const char *what() const noexcept override; +}; + +// --------------------------------------------------------------------------- + +/** \brief Exception thrown when an invalid value type is set as the value of + * a key of a PropertyMap. + */ +class PROJ_GCC_DLL InvalidValueTypeException : public Exception { + public: + //! @cond Doxygen_Suppress + PROJ_INTERNAL explicit InvalidValueTypeException(const char *message); + PROJ_INTERNAL explicit InvalidValueTypeException( + const std::string &message); + PROJ_DLL InvalidValueTypeException(const InvalidValueTypeException &other); + PROJ_DLL ~InvalidValueTypeException() override; + //! @endcond +}; + +// --------------------------------------------------------------------------- + +/** \brief Exception Thrown to indicate that the requested operation is not + * supported. + */ +class PROJ_GCC_DLL UnsupportedOperationException : public Exception { + public: + //! @cond Doxygen_Suppress + PROJ_INTERNAL explicit UnsupportedOperationException(const char *message); + PROJ_INTERNAL explicit UnsupportedOperationException( + const std::string &message); + PROJ_DLL + UnsupportedOperationException(const UnsupportedOperationException &other); + PROJ_DLL ~UnsupportedOperationException() override; + //! @endcond +}; + +} // namespace util + +NS_PROJ_END + +#endif // UTIL_HH_INCLUDED |
