diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2018-12-19 12:25:33 +0100 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2018-12-26 10:08:54 +0100 |
| commit | e6de172371ea203f6393d745641d66c82b5b13e2 (patch) | |
| tree | 791fa07f431a2d1db6f6e813ab984db982587278 /src/iso19111/coordinatesystem.cpp | |
| parent | ce8075076b4e4ffebd32afaba419e1d9ab27cd03 (diff) | |
| download | PROJ-e6de172371ea203f6393d745641d66c82b5b13e2.tar.gz PROJ-e6de172371ea203f6393d745641d66c82b5b13e2.zip | |
cpp conversion: move source files in apps/ iso19111/ conversions/ projections/ transformations/ tests/ subdirectories
Diffstat (limited to 'src/iso19111/coordinatesystem.cpp')
| -rw-r--r-- | src/iso19111/coordinatesystem.cpp | 1279 |
1 files changed, 1279 insertions, 0 deletions
diff --git a/src/iso19111/coordinatesystem.cpp b/src/iso19111/coordinatesystem.cpp new file mode 100644 index 00000000..a3ad04e0 --- /dev/null +++ b/src/iso19111/coordinatesystem.cpp @@ -0,0 +1,1279 @@ +/****************************************************************************** + * + * 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 +#define FROM_PROJ_CPP +#endif + +#include "proj/coordinatesystem.hpp" +#include "proj/common.hpp" +#include "proj/io.hpp" +#include "proj/metadata.hpp" +#include "proj/util.hpp" + +#include "proj/internal/coordinatesystem_internal.hpp" +#include "proj/internal/internal.hpp" +#include "proj/internal/io_internal.hpp" + +#include <map> +#include <memory> +#include <set> +#include <string> +#include <vector> + +using namespace NS_PROJ::internal; + +#if 0 +namespace dropbox{ namespace oxygen { +template<> nn<NS_PROJ::cs::MeridianPtr>::~nn() = default; +template<> nn<NS_PROJ::cs::CoordinateSystemAxisPtr>::~nn() = default; +template<> nn<NS_PROJ::cs::CoordinateSystemPtr>::~nn() = default; +template<> nn<NS_PROJ::cs::SphericalCSPtr>::~nn() = default; +template<> nn<NS_PROJ::cs::EllipsoidalCSPtr>::~nn() = default; +template<> nn<NS_PROJ::cs::CartesianCSPtr>::~nn() = default; +template<> nn<NS_PROJ::cs::TemporalCSPtr>::~nn() = default; +template<> nn<NS_PROJ::cs::TemporalCountCSPtr>::~nn() = default; +template<> nn<NS_PROJ::cs::TemporalMeasureCSPtr>::~nn() = default; +template<> nn<NS_PROJ::cs::DateTimeTemporalCSPtr>::~nn() = default; +template<> nn<NS_PROJ::cs::VerticalCSPtr>::~nn() = default; +template<> nn<NS_PROJ::cs::ParametricCSPtr>::~nn() = default; +template<> nn<NS_PROJ::cs::OrdinalCSPtr>::~nn() = default; +}} +#endif + +NS_PROJ_START +namespace cs { + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +struct Meridian::Private { + common::Angle longitude_{}; + + explicit Private(const common::Angle &longitude) : longitude_(longitude) {} +}; +//! @endcond + +// --------------------------------------------------------------------------- + +Meridian::Meridian(const common::Angle &longitudeIn) + : d(internal::make_unique<Private>(longitudeIn)) {} + +// --------------------------------------------------------------------------- + +#ifdef notdef +Meridian::Meridian(const Meridian &other) + : IdentifiedObject(other), d(internal::make_unique<Private>(*other.d)) {} +#endif + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +Meridian::~Meridian() = default; +//! @endcond + +// --------------------------------------------------------------------------- + +/** \brief Return the longitude of the meridian that the axis follows from the + * pole. + * + * @return the longitude. + */ +const common::Angle &Meridian::longitude() PROJ_CONST_DEFN { + return d->longitude_; +} + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a Meridian. + * + * @param longitudeIn longitude of the meridian that the axis follows from the + * pole. + * @return new Meridian. + */ +MeridianNNPtr Meridian::create(const common::Angle &longitudeIn) { + return Meridian::nn_make_shared<Meridian>(longitudeIn); +} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +void Meridian::_exportToWKT( + io::WKTFormatter *formatter) const // throw(FormattingException) +{ + formatter->startNode(io::WKTConstants::MERIDIAN, !identifiers().empty()); + formatter->add(longitude().value()); + longitude().unit()._exportToWKT(formatter, io::WKTConstants::ANGLEUNIT); + if (formatter->outputId()) { + formatID(formatter); + } + formatter->endNode(); +} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +struct CoordinateSystemAxis::Private { + std::string abbreviation{}; + const AxisDirection *direction = &(AxisDirection::UNSPECIFIED); + common::UnitOfMeasure unit{}; + util::optional<double> minimumValue{}; + util::optional<double> maximumValue{}; + MeridianPtr meridian{}; + // TODO rangeMeaning +}; +//! @endcond + +// --------------------------------------------------------------------------- + +CoordinateSystemAxis::CoordinateSystemAxis() + : d(internal::make_unique<Private>()) {} + +// --------------------------------------------------------------------------- + +#ifdef notdef +CoordinateSystemAxis::CoordinateSystemAxis(const CoordinateSystemAxis &other) + : IdentifiedObject(other), d(internal::make_unique<Private>(*other.d)) {} +#endif + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +CoordinateSystemAxis::~CoordinateSystemAxis() = default; +//! @endcond + +// --------------------------------------------------------------------------- + +/** \brief Return the axis abbreviation. + * + * The abbreviation used for this coordinate system axis; this abbreviation + * is also used to identify the coordinates in the coordinate tuple. + * Examples are X and Y. + * + * @return the abbreviation. + */ +const std::string &CoordinateSystemAxis::abbreviation() PROJ_CONST_DEFN { + return d->abbreviation; +} + +// --------------------------------------------------------------------------- + +/** \brief Return the axis direction. + * + * The direction of this coordinate system axis (or in the case of Cartesian + * projected coordinates, the direction of this coordinate system axis locally) + * Examples: north or south, east or west, up or down. Within any set of + * coordinate system axes, only one of each pair of terms can be used. For + * Earth-fixed CRSs, this direction is often approximate and intended to + * provide a human interpretable meaning to the axis. When a geodetic reference + * frame is used, the precise directions of the axes may therefore vary + * slightly from this approximate direction. Note that an EngineeringCRS often + * requires specific descriptions of the directions of its coordinate system + * axes. + * + * @return the direction. + */ +const AxisDirection &CoordinateSystemAxis::direction() PROJ_CONST_DEFN { + return *(d->direction); +} + +// --------------------------------------------------------------------------- + +/** \brief Return the axis unit. + * + * This is the spatial unit or temporal quantity used for this coordinate + * system axis. The value of a coordinate in a coordinate tuple shall be + * recorded using this unit. + * + * @return the axis unit. + */ +const common::UnitOfMeasure &CoordinateSystemAxis::unit() PROJ_CONST_DEFN { + return d->unit; +} + +// --------------------------------------------------------------------------- + +/** \brief Return the minimum value normally allowed for this axis, in the unit + * for the axis. + * + * @return the minimum value, or empty. + */ +const util::optional<double> & +CoordinateSystemAxis::minimumValue() PROJ_CONST_DEFN { + return d->minimumValue; +} + +// --------------------------------------------------------------------------- + +/** \brief Return the maximum value normally allowed for this axis, in the unit + * for the axis. + * + * @return the maximum value, or empty. + */ +const util::optional<double> & +CoordinateSystemAxis::maximumValue() PROJ_CONST_DEFN { + return d->maximumValue; +} + +// --------------------------------------------------------------------------- + +/** \brief Return the meridian that the axis follows from the pole, for a + * coordinate + * reference system centered on a pole. + * + * @return the meridian, or null. + */ +const MeridianPtr &CoordinateSystemAxis::meridian() PROJ_CONST_DEFN { + return d->meridian; +} + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a CoordinateSystemAxis. + * + * @param properties See \ref general_properties. The name should generally be + * defined. + * @param abbreviationIn Axis abbreviation (might be empty) + * @param directionIn Axis direction + * @param unitIn Axis unit + * @param meridianIn The meridian that the axis follows from the pole, for a + * coordinate + * reference system centered on a pole, or nullptr + * @return a new CoordinateSystemAxis. + */ +CoordinateSystemAxisNNPtr CoordinateSystemAxis::create( + const util::PropertyMap &properties, const std::string &abbreviationIn, + const AxisDirection &directionIn, const common::UnitOfMeasure &unitIn, + const MeridianPtr &meridianIn) { + auto csa(CoordinateSystemAxis::nn_make_shared<CoordinateSystemAxis>()); + csa->setProperties(properties); + csa->d->abbreviation = abbreviationIn; + csa->d->direction = &directionIn; + csa->d->unit = unitIn; + csa->d->meridian = meridianIn; + return csa; +} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +void CoordinateSystemAxis::_exportToWKT( + // cppcheck-suppress passedByValue + io::WKTFormatter *formatter) const // throw(FormattingException) +{ + _exportToWKT(formatter, 0, false); +} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +std::string CoordinateSystemAxis::normalizeAxisName(const std::string &str) { + if (str.empty()) { + return str; + } + // on import, transform from WKT2 "longitude" to "Longitude", as in the + // EPSG database. + return toupper(str.substr(0, 1)) + str.substr(1); +} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +void CoordinateSystemAxis::_exportToWKT(io::WKTFormatter *formatter, int order, + bool disableAbbrev) const { + const bool isWKT2 = formatter->version() == io::WKTFormatter::Version::WKT2; + formatter->startNode(io::WKTConstants::AXIS, !identifiers().empty()); + std::string axisName = *(name()->description()); + std::string abbrev = abbreviation(); + std::string parenthesedAbbrev = "(" + abbrev + ")"; + std::string dir = direction().toString(); + std::string axisDesignation; + + // It seems that the convention in WKT2 for axis name is first letter in + // lower case. Whereas in WKT1 GDAL, it is in upper case (as in the EPSG + // database) + if (!axisName.empty()) { + if (isWKT2) { + axisDesignation = + tolower(axisName.substr(0, 1)) + axisName.substr(1); + } else { + if (axisName == "Geodetic latitude") { + axisDesignation = "Latitude"; + } else if (axisName == "Geodetic longitude") { + axisDesignation = "Longitude"; + } else { + axisDesignation = axisName; + } + } + } + + if (!disableAbbrev && isWKT2 && + // For geodetic CS, export the axis name without abbreviation + !(axisName == AxisName::Latitude || axisName == AxisName::Longitude)) { + if (!axisDesignation.empty() && !abbrev.empty()) { + axisDesignation += " "; + } + if (!abbrev.empty()) { + axisDesignation += parenthesedAbbrev; + } + } + if (!isWKT2) { + dir = toupper(dir); + + if (direction() == AxisDirection::GEOCENTRIC_Z) { + dir = AxisDirectionWKT1::NORTH; + } else if (AxisDirectionWKT1::valueOf(dir) == nullptr) { + dir = AxisDirectionWKT1::OTHER; + } + } else if (!abbrev.empty()) { + // For geocentric CS, just put the abbreviation + if (direction() == AxisDirection::GEOCENTRIC_X || + direction() == AxisDirection::GEOCENTRIC_Y || + direction() == AxisDirection::GEOCENTRIC_Z) { + axisDesignation = parenthesedAbbrev; + } + // For cartesian CS with Easting/Northing, export only the abbreviation + else if ((order == 1 && axisName == AxisName::Easting && + abbrev == AxisAbbreviation::E) || + (order == 2 && axisName == AxisName::Northing && + abbrev == AxisAbbreviation::N)) { + axisDesignation = parenthesedAbbrev; + } + } + formatter->addQuotedString(axisDesignation); + formatter->add(dir); + const auto &l_meridian = meridian(); + if (isWKT2 && l_meridian) { + l_meridian->_exportToWKT(formatter); + } + if (formatter->outputAxisOrder() && order > 0) { + formatter->startNode(io::WKTConstants::ORDER, false); + formatter->add(order); + formatter->endNode(); + } + if (formatter->outputUnit() && + unit().type() != common::UnitOfMeasure::Type::NONE) { + unit()._exportToWKT(formatter); + } + if (formatter->outputId()) { + formatID(formatter); + } + formatter->endNode(); +} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +bool CoordinateSystemAxis::_isEquivalentTo( + const util::IComparable *other, + util::IComparable::Criterion criterion) const { + auto otherCSA = dynamic_cast<const CoordinateSystemAxis *>(other); + if (otherCSA == nullptr) { + return false; + } + // For approximate comparison, only care about axis direction and unit. + if (!(*(d->direction) == *(otherCSA->d->direction) && + d->unit._isEquivalentTo(otherCSA->d->unit, criterion))) { + return false; + } + if (criterion == util::IComparable::Criterion::STRICT) { + if (!IdentifiedObject::_isEquivalentTo(other, criterion)) { + return false; + } + if (abbreviation() != otherCSA->abbreviation()) { + return false; + } + // TODO other metadata + } + + return true; +} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +CoordinateSystemAxisNNPtr +CoordinateSystemAxis::alterUnit(const common::UnitOfMeasure &newUnit) const { + return create(util::PropertyMap().set(IdentifiedObject::NAME_KEY, name()), + abbreviation(), direction(), newUnit, meridian()); +} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +struct CoordinateSystem::Private { + std::vector<CoordinateSystemAxisNNPtr> axisList{}; + + explicit Private(const std::vector<CoordinateSystemAxisNNPtr> &axisListIn) + : axisList(axisListIn) {} +}; +//! @endcond + +// --------------------------------------------------------------------------- + +CoordinateSystem::CoordinateSystem( + const std::vector<CoordinateSystemAxisNNPtr> &axisIn) + : d(internal::make_unique<Private>(axisIn)) {} + +// --------------------------------------------------------------------------- + +#ifdef notdef +CoordinateSystem::CoordinateSystem(const CoordinateSystem &other) + : IdentifiedObject(other), d(internal::make_unique<Private>(*other.d)) {} +#endif + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +CoordinateSystem::~CoordinateSystem() = default; +//! @endcond + +// --------------------------------------------------------------------------- + +/** \brief Return the list of axes of this coordinate system. + * + * @return the axes. + */ +const std::vector<CoordinateSystemAxisNNPtr> & +CoordinateSystem::axisList() PROJ_CONST_DEFN { + return d->axisList; +} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +void CoordinateSystem::_exportToWKT( + io::WKTFormatter *formatter) const // throw(FormattingException) +{ + if (formatter->outputAxis() != io::WKTFormatter::OutputAxisRule::YES) { + return; + } + const bool isWKT2 = formatter->version() == io::WKTFormatter::Version::WKT2; + + const auto &l_axisList = axisList(); + if (isWKT2) { + formatter->startNode(io::WKTConstants::CS, !identifiers().empty()); + formatter->add(getWKT2Type(formatter->use2018Keywords())); + formatter->add(static_cast<int>(l_axisList.size())); + formatter->endNode(); + formatter->startNode(std::string(), + false); // anonymous indentation level + } + + common::UnitOfMeasure unit = common::UnitOfMeasure::NONE; + bool bAllSameUnit = true; + bool bFirstUnit = true; + for (const auto &axis : l_axisList) { + const auto &l_unit = axis->unit(); + if (bFirstUnit) { + unit = l_unit; + bFirstUnit = false; + } else if (unit != l_unit) { + bAllSameUnit = false; + } + } + + formatter->pushOutputUnit( + isWKT2 && (!bAllSameUnit || !formatter->outputCSUnitOnlyOnceIfSame())); + + int order = 1; + const bool disableAbbrev = + (l_axisList.size() == 3 && + l_axisList[0]->nameStr() == AxisName::Latitude && + l_axisList[1]->nameStr() == AxisName::Longitude && + l_axisList[2]->nameStr() == AxisName::Ellipsoidal_height); + + for (auto &axis : l_axisList) { + int axisOrder = (isWKT2 && l_axisList.size() > 1) ? order : 0; + axis->_exportToWKT(formatter, axisOrder, disableAbbrev); + order++; + } + if (isWKT2 && !l_axisList.empty() && bAllSameUnit && + formatter->outputCSUnitOnlyOnceIfSame()) { + unit._exportToWKT(formatter); + } + + formatter->popOutputUnit(); + + if (isWKT2) { + formatter->endNode(); + } +} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +bool CoordinateSystem::_isEquivalentTo( + const util::IComparable *other, + util::IComparable::Criterion criterion) const { + auto otherCS = dynamic_cast<const CoordinateSystem *>(other); + if (otherCS == nullptr || + !IdentifiedObject::_isEquivalentTo(other, criterion)) { + return false; + } + const auto &list = axisList(); + const auto &otherList = otherCS->axisList(); + if (list.size() != otherList.size()) { + return false; + } + if (getWKT2Type(true) != otherCS->getWKT2Type(true)) { + return false; + } + for (size_t i = 0; i < list.size(); i++) { + if (!list[i]->_isEquivalentTo(otherList[i].get(), criterion)) { + return false; + } + } + return true; +} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +SphericalCS::~SphericalCS() = default; +//! @endcond + +// --------------------------------------------------------------------------- + +SphericalCS::SphericalCS(const std::vector<CoordinateSystemAxisNNPtr> &axisIn) + : CoordinateSystem(axisIn) {} + +// --------------------------------------------------------------------------- + +#ifdef notdef +SphericalCS::SphericalCS(const SphericalCS &) = default; +#endif + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a SphericalCS. + * + * @param properties See \ref general_properties. + * @param axis1 The first axis. + * @param axis2 The second axis. + * @param axis3 The third axis. + * @return a new SphericalCS. + */ +SphericalCSNNPtr SphericalCS::create(const util::PropertyMap &properties, + const CoordinateSystemAxisNNPtr &axis1, + const CoordinateSystemAxisNNPtr &axis2, + const CoordinateSystemAxisNNPtr &axis3) { + std::vector<CoordinateSystemAxisNNPtr> axis{axis1, axis2, axis3}; + auto cs(SphericalCS::nn_make_shared<SphericalCS>(axis)); + cs->setProperties(properties); + return cs; +} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +EllipsoidalCS::~EllipsoidalCS() = default; +//! @endcond + +// --------------------------------------------------------------------------- + +EllipsoidalCS::EllipsoidalCS( + const std::vector<CoordinateSystemAxisNNPtr> &axisIn) + : CoordinateSystem(axisIn) {} + +// --------------------------------------------------------------------------- + +#ifdef notdef +EllipsoidalCS::EllipsoidalCS(const EllipsoidalCS &) = default; +#endif + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a EllipsoidalCS. + * + * @param properties See \ref general_properties. + * @param axis1 The first axis. + * @param axis2 The second axis. + * @return a new EllipsoidalCS. + */ +EllipsoidalCSNNPtr +EllipsoidalCS::create(const util::PropertyMap &properties, + const CoordinateSystemAxisNNPtr &axis1, + const CoordinateSystemAxisNNPtr &axis2) { + std::vector<CoordinateSystemAxisNNPtr> axis{axis1, axis2}; + auto cs(EllipsoidalCS::nn_make_shared<EllipsoidalCS>(axis)); + cs->setProperties(properties); + return cs; +} + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a EllipsoidalCS. + * + * @param properties See \ref general_properties. + * @param axis1 The first axis. + * @param axis2 The second axis. + * @param axis3 The third axis. + * @return a new EllipsoidalCS. + */ +EllipsoidalCSNNPtr +EllipsoidalCS::create(const util::PropertyMap &properties, + const CoordinateSystemAxisNNPtr &axis1, + const CoordinateSystemAxisNNPtr &axis2, + const CoordinateSystemAxisNNPtr &axis3) { + std::vector<CoordinateSystemAxisNNPtr> axis{axis1, axis2, axis3}; + auto cs(EllipsoidalCS::nn_make_shared<EllipsoidalCS>(axis)); + cs->setProperties(properties); + return cs; +} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +CoordinateSystemAxisNNPtr +CoordinateSystemAxis::createLAT_NORTH(const common::UnitOfMeasure &unit) { + return create( + util::PropertyMap().set(IdentifiedObject::NAME_KEY, AxisName::Latitude), + AxisAbbreviation::lat, AxisDirection::NORTH, unit); +} + +CoordinateSystemAxisNNPtr +CoordinateSystemAxis::createLONG_EAST(const common::UnitOfMeasure &unit) { + return create(util::PropertyMap().set(IdentifiedObject::NAME_KEY, + AxisName::Longitude), + AxisAbbreviation::lon, AxisDirection::EAST, unit); +} +//! @endcond + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a EllipsoidalCS with a Latitude (first) and Longitude + * (second) axis. + * + * @param unit Angular unit of the axes. + * @return a new EllipsoidalCS. + */ +EllipsoidalCSNNPtr +EllipsoidalCS::createLatitudeLongitude(const common::UnitOfMeasure &unit) { + return EllipsoidalCS::create(util::PropertyMap(), + CoordinateSystemAxis::createLAT_NORTH(unit), + CoordinateSystemAxis::createLONG_EAST(unit)); +} + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a EllipsoidalCS with a Latitude (first), Longitude + * (second) axis and ellipsoidal height (third) axis. + * + * @param angularUnit Angular unit of the latitude and longitude axes. + * @param linearUnit Linear unit of the ellipsoidal height axis. + * @return a new EllipsoidalCS. + */ +EllipsoidalCSNNPtr EllipsoidalCS::createLatitudeLongitudeEllipsoidalHeight( + const common::UnitOfMeasure &angularUnit, + const common::UnitOfMeasure &linearUnit) { + return EllipsoidalCS::create( + util::PropertyMap(), CoordinateSystemAxis::createLAT_NORTH(angularUnit), + CoordinateSystemAxis::createLONG_EAST(angularUnit), + CoordinateSystemAxis::create( + util::PropertyMap().set(IdentifiedObject::NAME_KEY, + AxisName::Ellipsoidal_height), + AxisAbbreviation::h, AxisDirection::UP, linearUnit)); +} + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a EllipsoidalCS with a Longitude (first) and Latitude + * (second) axis. + * + * @param unit Angular unit of the axes. + * @return a new EllipsoidalCS. + */ +EllipsoidalCSNNPtr +EllipsoidalCS::createLongitudeLatitude(const common::UnitOfMeasure &unit) { + return EllipsoidalCS::create(util::PropertyMap(), + CoordinateSystemAxis::createLONG_EAST(unit), + CoordinateSystemAxis::createLAT_NORTH(unit)); +} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +/** \brief Return the axis order in an enumerated way. */ +EllipsoidalCS::AxisOrder EllipsoidalCS::axisOrder() const { + const auto &l_axisList = CoordinateSystem::getPrivate()->axisList; + const auto &dir0 = l_axisList[0]->direction(); + const auto &dir1 = l_axisList[1]->direction(); + if (&dir0 == &AxisDirection::NORTH && &dir1 == &AxisDirection::EAST) { + if (l_axisList.size() == 2) { + return AxisOrder::LAT_NORTH_LONG_EAST; + } else if (&l_axisList[2]->direction() == &AxisDirection::UP) { + return AxisOrder::LAT_NORTH_LONG_EAST_HEIGHT_UP; + } + } else if (&dir0 == &AxisDirection::EAST && + &dir1 == &AxisDirection::NORTH) { + if (l_axisList.size() == 2) { + return AxisOrder::LONG_EAST_LAT_NORTH; + } else if (&l_axisList[2]->direction() == &AxisDirection::UP) { + return AxisOrder::LONG_EAST_LAT_NORTH_HEIGHT_UP; + } + } + + return AxisOrder::OTHER; +} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +EllipsoidalCSNNPtr EllipsoidalCS::alterAngularUnit( + const common::UnitOfMeasure &angularUnit) const { + const auto &l_axisList = CoordinateSystem::getPrivate()->axisList; + if (l_axisList.size() == 2) { + return EllipsoidalCS::create(util::PropertyMap(), + l_axisList[0]->alterUnit(angularUnit), + l_axisList[1]->alterUnit(angularUnit)); + } else { + assert(l_axisList.size() == 3); + return EllipsoidalCS::create( + util::PropertyMap(), l_axisList[0]->alterUnit(angularUnit), + l_axisList[1]->alterUnit(angularUnit), l_axisList[2]); + } +} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +EllipsoidalCSNNPtr +EllipsoidalCS::alterLinearUnit(const common::UnitOfMeasure &linearUnit) const { + const auto &l_axisList = CoordinateSystem::getPrivate()->axisList; + if (l_axisList.size() == 2) { + return EllipsoidalCS::create(util::PropertyMap(), l_axisList[0], + l_axisList[1]); + } else { + assert(l_axisList.size() == 3); + return EllipsoidalCS::create(util::PropertyMap(), l_axisList[0], + l_axisList[1], + l_axisList[2]->alterUnit(linearUnit)); + } +} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +VerticalCS::~VerticalCS() = default; +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +VerticalCS::VerticalCS(const CoordinateSystemAxisNNPtr &axisIn) + : CoordinateSystem(std::vector<CoordinateSystemAxisNNPtr>{axisIn}) {} +//! @endcond + +// --------------------------------------------------------------------------- + +#ifdef notdef +VerticalCS::VerticalCS(const VerticalCS &) = default; +#endif + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a VerticalCS. + * + * @param properties See \ref general_properties. + * @param axis The axis. + * @return a new VerticalCS. + */ +VerticalCSNNPtr VerticalCS::create(const util::PropertyMap &properties, + const CoordinateSystemAxisNNPtr &axis) { + auto cs(VerticalCS::nn_make_shared<VerticalCS>(axis)); + cs->setProperties(properties); + return cs; +} + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a VerticalCS with a Gravity-related height axis + * + * @param unit linear unit. + * @return a new VerticalCS. + */ +VerticalCSNNPtr +VerticalCS::createGravityRelatedHeight(const common::UnitOfMeasure &unit) { + auto cs(VerticalCS::nn_make_shared<VerticalCS>(CoordinateSystemAxis::create( + util::PropertyMap().set(IdentifiedObject::NAME_KEY, + "Gravity-related height"), + "H", AxisDirection::UP, unit))); + return cs; +} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +VerticalCSNNPtr VerticalCS::alterUnit(const common::UnitOfMeasure &unit) const { + const auto &l_axisList = CoordinateSystem::getPrivate()->axisList; + return VerticalCS::nn_make_shared<VerticalCS>( + l_axisList[0]->alterUnit(unit)); +} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +CartesianCS::~CartesianCS() = default; +//! @endcond + +// --------------------------------------------------------------------------- + +CartesianCS::CartesianCS(const std::vector<CoordinateSystemAxisNNPtr> &axisIn) + : CoordinateSystem(axisIn) {} + +// --------------------------------------------------------------------------- + +#ifdef notdef +CartesianCS::CartesianCS(const CartesianCS &) = default; +#endif + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a CartesianCS. + * + * @param properties See \ref general_properties. + * @param axis1 The first axis. + * @param axis2 The second axis. + * @return a new CartesianCS. + */ +CartesianCSNNPtr CartesianCS::create(const util::PropertyMap &properties, + const CoordinateSystemAxisNNPtr &axis1, + const CoordinateSystemAxisNNPtr &axis2) { + std::vector<CoordinateSystemAxisNNPtr> axis{axis1, axis2}; + auto cs(CartesianCS::nn_make_shared<CartesianCS>(axis)); + cs->setProperties(properties); + return cs; +} + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a CartesianCS. + * + * @param properties See \ref general_properties. + * @param axis1 The first axis. + * @param axis2 The second axis. + * @param axis3 The third axis. + * @return a new CartesianCS. + */ +CartesianCSNNPtr CartesianCS::create(const util::PropertyMap &properties, + const CoordinateSystemAxisNNPtr &axis1, + const CoordinateSystemAxisNNPtr &axis2, + const CoordinateSystemAxisNNPtr &axis3) { + std::vector<CoordinateSystemAxisNNPtr> axis{axis1, axis2, axis3}; + auto cs(CartesianCS::nn_make_shared<CartesianCS>(axis)); + cs->setProperties(properties); + return cs; +} + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a CartesianCS with a Easting (first) and Northing + * (second) axis. + * + * @param unit Linear unit of the axes. + * @return a new CartesianCS. + */ +CartesianCSNNPtr +CartesianCS::createEastingNorthing(const common::UnitOfMeasure &unit) { + return create(util::PropertyMap(), + CoordinateSystemAxis::create( + util::PropertyMap().set(IdentifiedObject::NAME_KEY, + AxisName::Easting), + AxisAbbreviation::E, AxisDirection::EAST, unit), + CoordinateSystemAxis::create( + util::PropertyMap().set(IdentifiedObject::NAME_KEY, + AxisName::Northing), + AxisAbbreviation::N, AxisDirection::NORTH, unit)); +} + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a CartesianCS with a Northing (first) and Easting + * (second) axis. + * + * @param unit Linear unit of the axes. + * @return a new CartesianCS. + */ +CartesianCSNNPtr +CartesianCS::createNorthingEasting(const common::UnitOfMeasure &unit) { + return create(util::PropertyMap(), + CoordinateSystemAxis::create( + util::PropertyMap().set(IdentifiedObject::NAME_KEY, + AxisName::Northing), + AxisAbbreviation::N, AxisDirection::NORTH, unit), + CoordinateSystemAxis::create( + util::PropertyMap().set(IdentifiedObject::NAME_KEY, + AxisName::Easting), + AxisAbbreviation::E, AxisDirection::EAST, unit)); +} + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a CartesianCS with a Westing (first) and Southing + * (second) axis. + * + * @param unit Linear unit of the axes. + * @return a new CartesianCS. + */ +CartesianCSNNPtr +CartesianCS::createWestingSouthing(const common::UnitOfMeasure &unit) { + return create(util::PropertyMap(), + CoordinateSystemAxis::create( + util::PropertyMap().set(IdentifiedObject::NAME_KEY, + AxisName::Easting), + AxisAbbreviation::Y, AxisDirection::WEST, unit), + CoordinateSystemAxis::create( + util::PropertyMap().set(IdentifiedObject::NAME_KEY, + AxisName::Northing), + AxisAbbreviation::X, AxisDirection::SOUTH, unit)); +} + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a CartesianCS, north-pole centered, + * with a Easting (first) South-Oriented and + * Northing (second) South-Oriented axis. + * + * @param unit Linear unit of the axes. + * @return a new CartesianCS. + */ +CartesianCSNNPtr CartesianCS::createNorthPoleEastingSouthNorthingSouth( + const common::UnitOfMeasure &unit) { + return create(util::PropertyMap(), + CoordinateSystemAxis::create( + util::PropertyMap().set(IdentifiedObject::NAME_KEY, + AxisName::Easting), + AxisAbbreviation::E, AxisDirection::SOUTH, unit, + Meridian::create(common::Angle(90))), + CoordinateSystemAxis::create( + util::PropertyMap().set(IdentifiedObject::NAME_KEY, + AxisName::Northing), + AxisAbbreviation::N, AxisDirection::SOUTH, unit, + Meridian::create(common::Angle(180)))); +} + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a CartesianCS, south-pole centered, + * with a Easting (first) North-Oriented and + * Northing (second) North-Oriented axis. + * + * @param unit Linear unit of the axes. + * @return a new CartesianCS. + */ +CartesianCSNNPtr CartesianCS::createSouthPoleEastingNorthNorthingNorth( + const common::UnitOfMeasure &unit) { + return create(util::PropertyMap(), + CoordinateSystemAxis::create( + util::PropertyMap().set(IdentifiedObject::NAME_KEY, + AxisName::Easting), + AxisAbbreviation::E, AxisDirection::NORTH, unit, + Meridian::create(common::Angle(90))), + CoordinateSystemAxis::create( + util::PropertyMap().set(IdentifiedObject::NAME_KEY, + AxisName::Northing), + AxisAbbreviation::N, AxisDirection::NORTH, unit, + Meridian::create(common::Angle(0)))); +} + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a CartesianCS with the three geocentric axes. + * + * @param unit Liinear unit of the axes. + * @return a new CartesianCS. + */ +CartesianCSNNPtr +CartesianCS::createGeocentric(const common::UnitOfMeasure &unit) { + return create(util::PropertyMap(), + CoordinateSystemAxis::create( + util::PropertyMap().set(IdentifiedObject::NAME_KEY, + AxisName::Geocentric_X), + AxisAbbreviation::X, AxisDirection::GEOCENTRIC_X, unit), + CoordinateSystemAxis::create( + util::PropertyMap().set(IdentifiedObject::NAME_KEY, + AxisName::Geocentric_Y), + AxisAbbreviation::Y, AxisDirection::GEOCENTRIC_Y, unit), + CoordinateSystemAxis::create( + util::PropertyMap().set(IdentifiedObject::NAME_KEY, + AxisName::Geocentric_Z), + AxisAbbreviation::Z, AxisDirection::GEOCENTRIC_Z, unit)); +} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +CartesianCSNNPtr +CartesianCS::alterUnit(const common::UnitOfMeasure &unit) const { + const auto &l_axisList = CoordinateSystem::getPrivate()->axisList; + if (l_axisList.size() == 2) { + return CartesianCS::create(util::PropertyMap(), + l_axisList[0]->alterUnit(unit), + l_axisList[1]->alterUnit(unit)); + } else { + assert(l_axisList.size() == 3); + return CartesianCS::create( + util::PropertyMap(), l_axisList[0]->alterUnit(unit), + l_axisList[1]->alterUnit(unit), l_axisList[2]->alterUnit(unit)); + } +} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +OrdinalCS::~OrdinalCS() = default; +//! @endcond + +// --------------------------------------------------------------------------- + +OrdinalCS::OrdinalCS(const std::vector<CoordinateSystemAxisNNPtr> &axisIn) + : CoordinateSystem(axisIn) {} + +// --------------------------------------------------------------------------- + +#ifdef notdef +OrdinalCS::OrdinalCS(const OrdinalCS &) = default; +#endif + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a OrdinalCS. + * + * @param properties See \ref general_properties. + * @param axisIn List of axis. + * @return a new OrdinalCS. + */ +OrdinalCSNNPtr +OrdinalCS::create(const util::PropertyMap &properties, + const std::vector<CoordinateSystemAxisNNPtr> &axisIn) { + auto cs(OrdinalCS::nn_make_shared<OrdinalCS>(axisIn)); + cs->setProperties(properties); + return cs; +} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +ParametricCS::~ParametricCS() = default; +//! @endcond + +// --------------------------------------------------------------------------- + +ParametricCS::ParametricCS(const std::vector<CoordinateSystemAxisNNPtr> &axisIn) + : CoordinateSystem(axisIn) {} + +// --------------------------------------------------------------------------- + +#ifdef notdef +ParametricCS::ParametricCS(const ParametricCS &) = default; +#endif + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a ParametricCS. + * + * @param properties See \ref general_properties. + * @param axisIn Axis. + * @return a new ParametricCS. + */ +ParametricCSNNPtr +ParametricCS::create(const util::PropertyMap &properties, + const CoordinateSystemAxisNNPtr &axisIn) { + auto cs(ParametricCS::nn_make_shared<ParametricCS>( + std::vector<CoordinateSystemAxisNNPtr>{axisIn})); + cs->setProperties(properties); + return cs; +} + +// --------------------------------------------------------------------------- + +AxisDirection::AxisDirection(const std::string &nameIn) : CodeList(nameIn) { + assert(registry.find(nameIn) == registry.end()); + registry[nameIn] = this; +} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +const AxisDirection * +AxisDirection::valueOf(const std::string &nameIn) noexcept { + auto iter = registry.find(nameIn); + if (iter == registry.end()) + return nullptr; + return iter->second; +} +//! @endcond + +//! @cond Doxygen_Suppress +// --------------------------------------------------------------------------- + +AxisDirectionWKT1::AxisDirectionWKT1(const std::string &nameIn) + : CodeList(nameIn) { + assert(registry.find(nameIn) == registry.end()); + registry[nameIn] = this; +} + +// --------------------------------------------------------------------------- + +const AxisDirectionWKT1 *AxisDirectionWKT1::valueOf(const std::string &nameIn) { + auto iter = registry.find(nameIn); + if (iter == registry.end()) + return nullptr; + return iter->second; +} + +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +TemporalCS::~TemporalCS() = default; +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +TemporalCS::TemporalCS(const CoordinateSystemAxisNNPtr &axisIn) + : CoordinateSystem(std::vector<CoordinateSystemAxisNNPtr>{axisIn}) {} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +DateTimeTemporalCS::~DateTimeTemporalCS() = default; +//! @endcond + +// --------------------------------------------------------------------------- + +DateTimeTemporalCS::DateTimeTemporalCS(const CoordinateSystemAxisNNPtr &axisIn) + : TemporalCS(axisIn) {} + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a DateTimeTemporalCS. + * + * @param properties See \ref general_properties. + * @param axisIn The axis. + * @return a new DateTimeTemporalCS. + */ +DateTimeTemporalCSNNPtr +DateTimeTemporalCS::create(const util::PropertyMap &properties, + const CoordinateSystemAxisNNPtr &axisIn) { + auto cs(DateTimeTemporalCS::nn_make_shared<DateTimeTemporalCS>(axisIn)); + cs->setProperties(properties); + return cs; +} + +// --------------------------------------------------------------------------- + +std::string DateTimeTemporalCS::getWKT2Type(bool use2018Keywords) const { + return use2018Keywords ? "TemporalDateTime" : "temporal"; +} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +TemporalCountCS::~TemporalCountCS() = default; +//! @endcond + +// --------------------------------------------------------------------------- + +TemporalCountCS::TemporalCountCS(const CoordinateSystemAxisNNPtr &axisIn) + : TemporalCS(axisIn) {} + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a TemporalCountCS. + * + * @param properties See \ref general_properties. + * @param axisIn The axis. + * @return a new TemporalCountCS. + */ +TemporalCountCSNNPtr +TemporalCountCS::create(const util::PropertyMap &properties, + const CoordinateSystemAxisNNPtr &axisIn) { + auto cs(TemporalCountCS::nn_make_shared<TemporalCountCS>(axisIn)); + cs->setProperties(properties); + return cs; +} + +// --------------------------------------------------------------------------- + +std::string TemporalCountCS::getWKT2Type(bool use2018Keywords) const { + return use2018Keywords ? "TemporalCount" : "temporal"; +} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +TemporalMeasureCS::~TemporalMeasureCS() = default; +//! @endcond + +// --------------------------------------------------------------------------- + +TemporalMeasureCS::TemporalMeasureCS(const CoordinateSystemAxisNNPtr &axisIn) + : TemporalCS(axisIn) {} + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a TemporalMeasureCS. + * + * @param properties See \ref general_properties. + * @param axisIn The axis. + * @return a new TemporalMeasureCS. + */ +TemporalMeasureCSNNPtr +TemporalMeasureCS::create(const util::PropertyMap &properties, + const CoordinateSystemAxisNNPtr &axisIn) { + auto cs(TemporalMeasureCS::nn_make_shared<TemporalMeasureCS>(axisIn)); + cs->setProperties(properties); + return cs; +} + +// --------------------------------------------------------------------------- + +std::string TemporalMeasureCS::getWKT2Type(bool use2018Keywords) const { + return use2018Keywords ? "TemporalMeasure" : "temporal"; +} + +} // namespace cs +NS_PROJ_END |
