aboutsummaryrefslogtreecommitdiff
path: root/src/metadata.cpp
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2018-12-19 12:25:33 +0100
committerEven Rouault <even.rouault@spatialys.com>2018-12-26 10:08:54 +0100
commite6de172371ea203f6393d745641d66c82b5b13e2 (patch)
tree791fa07f431a2d1db6f6e813ab984db982587278 /src/metadata.cpp
parentce8075076b4e4ffebd32afaba419e1d9ab27cd03 (diff)
downloadPROJ-e6de172371ea203f6393d745641d66c82b5b13e2.tar.gz
PROJ-e6de172371ea203f6393d745641d66c82b5b13e2.zip
cpp conversion: move source files in apps/ iso19111/ conversions/ projections/ transformations/ tests/ subdirectories
Diffstat (limited to 'src/metadata.cpp')
-rw-r--r--src/metadata.cpp1285
1 files changed, 0 insertions, 1285 deletions
diff --git a/src/metadata.cpp b/src/metadata.cpp
deleted file mode 100644
index 2be9dac3..00000000
--- a/src/metadata.cpp
+++ /dev/null
@@ -1,1285 +0,0 @@
-/******************************************************************************
- *
- * 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/metadata.hpp"
-#include "proj/common.hpp"
-#include "proj/io.hpp"
-#include "proj/util.hpp"
-
-#include "proj/internal/internal.hpp"
-#include "proj/internal/io_internal.hpp"
-
-#include <algorithm>
-#include <memory>
-#include <string>
-#include <vector>
-
-using namespace NS_PROJ::internal;
-using namespace NS_PROJ::io;
-using namespace NS_PROJ::util;
-
-#if 0
-namespace dropbox{ namespace oxygen {
-template<> nn<std::shared_ptr<NS_PROJ::metadata::Citation>>::~nn() = default;
-template<> nn<NS_PROJ::metadata::ExtentPtr>::~nn() = default;
-template<> nn<NS_PROJ::metadata::GeographicBoundingBoxPtr>::~nn() = default;
-template<> nn<NS_PROJ::metadata::GeographicExtentPtr>::~nn() = default;
-template<> nn<NS_PROJ::metadata::VerticalExtentPtr>::~nn() = default;
-template<> nn<NS_PROJ::metadata::TemporalExtentPtr>::~nn() = default;
-template<> nn<NS_PROJ::metadata::IdentifierPtr>::~nn() = default;
-template<> nn<NS_PROJ::metadata::PositionalAccuracyPtr>::~nn() = default;
-}}
-#endif
-
-NS_PROJ_START
-namespace metadata {
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-struct Citation::Private {
- optional<std::string> title{};
-};
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-Citation::Citation() : d(internal::make_unique<Private>()) {}
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-/** \brief Constructs a citation by its title. */
-Citation::Citation(const std::string &titleIn)
- : d(internal::make_unique<Private>()) {
- d->title = titleIn;
-}
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-Citation::Citation(const Citation &other)
- : d(internal::make_unique<Private>(*(other.d))) {}
-
-// ---------------------------------------------------------------------------
-
-Citation::~Citation() = default;
-
-// ---------------------------------------------------------------------------
-
-Citation &Citation::operator=(const Citation &other) {
- if (this != &other) {
- *d = *other.d;
- }
- return *this;
-}
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-/** \brief Returns the name by which the cited resource is known. */
-const optional<std::string> &Citation::title() PROJ_CONST_DEFN {
- return d->title;
-}
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-struct GeographicExtent::Private {};
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-GeographicExtent::GeographicExtent() : d(internal::make_unique<Private>()) {}
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-GeographicExtent::~GeographicExtent() = default;
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-struct GeographicBoundingBox::Private {
- double west_{};
- double south_{};
- double east_{};
- double north_{};
-
- Private(double west, double south, double east, double north)
- : west_(west), south_(south), east_(east), north_(north) {}
-
- bool intersects(const Private &other) const;
-
- std::unique_ptr<Private> intersection(const Private &other) const;
-};
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-GeographicBoundingBox::GeographicBoundingBox(double west, double south,
- double east, double north)
- : GeographicExtent(),
- d(internal::make_unique<Private>(west, south, east, north)) {}
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-GeographicBoundingBox::~GeographicBoundingBox() = default;
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-/** \brief Returns the western-most coordinate of the limit of the dataset
- * extent.
- *
- * The unit is degrees.
- *
- * If eastBoundLongitude < westBoundLongitude(), then the bounding box crosses
- * the anti-meridian.
- */
-double GeographicBoundingBox::westBoundLongitude() PROJ_CONST_DEFN {
- return d->west_;
-}
-
-// ---------------------------------------------------------------------------
-
-/** \brief Returns the southern-most coordinate of the limit of the dataset
- * extent.
- *
- * The unit is degrees.
- */
-double GeographicBoundingBox::southBoundLatitude() PROJ_CONST_DEFN {
- return d->south_;
-}
-
-// ---------------------------------------------------------------------------
-
-/** \brief Returns the eastern-most coordinate of the limit of the dataset
- * extent.
- *
- * The unit is degrees.
- *
- * If eastBoundLongitude < westBoundLongitude(), then the bounding box crosses
- * the anti-meridian.
- */
-double GeographicBoundingBox::eastBoundLongitude() PROJ_CONST_DEFN {
- return d->east_;
-}
-
-// ---------------------------------------------------------------------------
-
-/** \brief Returns the northern-most coordinate of the limit of the dataset
- * extent.
- *
- * The unit is degrees.
- */
-double GeographicBoundingBox::northBoundLatitude() PROJ_CONST_DEFN {
- return d->north_;
-}
-
-// ---------------------------------------------------------------------------
-
-/** \brief Instanciate a GeographicBoundingBox.
- *
- * If east < west, then the bounding box crosses the anti-meridian.
- *
- * @param west Western-most coordinate of the limit of the dataset extent (in
- * degrees).
- * @param south Southern-most coordinate of the limit of the dataset extent (in
- * degrees).
- * @param east Eastern-most coordinate of the limit of the dataset extent (in
- * degrees).
- * @param north Northern-most coordinate of the limit of the dataset extent (in
- * degrees).
- * @return a new GeographicBoundingBox.
- */
-GeographicBoundingBoxNNPtr GeographicBoundingBox::create(double west,
- double south,
- double east,
- double north) {
- return GeographicBoundingBox::nn_make_shared<GeographicBoundingBox>(
- west, south, east, north);
-}
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-bool GeographicBoundingBox::_isEquivalentTo(
- const util::IComparable *other, util::IComparable::Criterion) const {
- auto otherExtent = dynamic_cast<const GeographicBoundingBox *>(other);
- if (!otherExtent)
- return false;
- return d->west_ == otherExtent->d->west_ &&
- d->south_ == otherExtent->d->south_ &&
- d->east_ == otherExtent->d->east_ &&
- d->north_ == otherExtent->d->north_;
-}
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-bool GeographicBoundingBox::contains(const GeographicExtentNNPtr &other) const {
- auto otherExtent = dynamic_cast<const GeographicBoundingBox *>(other.get());
- if (!otherExtent) {
- return false;
- }
- const double W = d->west_;
- const double E = d->east_;
- const double N = d->north_;
- const double S = d->south_;
- const double oW = otherExtent->d->west_;
- const double oE = otherExtent->d->east_;
- const double oN = otherExtent->d->north_;
- const double oS = otherExtent->d->south_;
-
- if (!(S <= oS && N >= oN)) {
- return false;
- }
-
- if (W == -180.0 && E == 180.0) {
- return true;
- }
-
- if (oW == -180.0 && oE == 180.0) {
- return false;
- }
-
- // Normal bounding box ?
- if (W < E) {
- if (oW < oE) {
- return W <= oW && E >= oE;
- } else {
- return false;
- }
- // No: crossing antimerian
- } else {
- if (oW < oE) {
- if (oW >= W) {
- return true;
- } else if (oE <= E) {
- return true;
- } else {
- return false;
- }
- } else {
- return W <= oW && E >= oE;
- }
- }
-}
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-bool GeographicBoundingBox::Private::intersects(const Private &other) const {
- const double W = west_;
- const double E = east_;
- const double N = north_;
- const double S = south_;
- const double oW = other.west_;
- const double oE = other.east_;
- const double oN = other.north_;
- const double oS = other.south_;
-
- if (N < oS || S > oN) {
- return false;
- }
-
- if (W == -180.0 && E == 180.0 && oW > oE) {
- return true;
- }
-
- if (oW == -180.0 && oE == 180.0 && W > E) {
- return true;
- }
-
- // Normal bounding box ?
- if (W <= E) {
- if (oW < oE) {
- if (std::max(W, oW) < std::min(E, oE)) {
- return true;
- }
- return false;
- }
-
- return intersects(Private(oW, oS, 180.0, oN)) ||
- intersects(Private(-180.0, oS, oE, oN));
-
- // No: crossing antimerian
- } else {
- if (oW <= oE) {
- return other.intersects(*this);
- }
-
- return true;
- }
-}
-//! @endcond
-
-bool GeographicBoundingBox::intersects(
- const GeographicExtentNNPtr &other) const {
- auto otherExtent = dynamic_cast<const GeographicBoundingBox *>(other.get());
- if (!otherExtent) {
- return false;
- }
- return d->intersects(*(otherExtent->d));
-}
-
-// ---------------------------------------------------------------------------
-
-GeographicExtentPtr
-GeographicBoundingBox::intersection(const GeographicExtentNNPtr &other) const {
- auto otherExtent = dynamic_cast<const GeographicBoundingBox *>(other.get());
- if (!otherExtent) {
- return nullptr;
- }
- auto ret = d->intersection(*(otherExtent->d));
- if (ret) {
- auto bbox = GeographicBoundingBox::create(ret->west_, ret->south_,
- ret->east_, ret->north_);
- return bbox.as_nullable();
- }
- return nullptr;
-}
-
-//! @cond Doxygen_Suppress
-std::unique_ptr<GeographicBoundingBox::Private>
-GeographicBoundingBox::Private::intersection(const Private &otherExtent) const {
- const double W = west_;
- const double E = east_;
- const double N = north_;
- const double S = south_;
- const double oW = otherExtent.west_;
- const double oE = otherExtent.east_;
- const double oN = otherExtent.north_;
- const double oS = otherExtent.south_;
-
- if (N < oS || S > oN) {
- return nullptr;
- }
-
- if (W == -180.0 && E == 180.0 && oW > oE) {
- return internal::make_unique<Private>(oW, std::max(S, oS), oE,
- std::min(N, oN));
- }
-
- if (oW == -180.0 && oE == 180.0 && W > E) {
- return internal::make_unique<Private>(W, std::max(S, oS), E,
- std::min(N, oN));
- }
-
- // Normal bounding box ?
- if (W <= E) {
- if (oW < oE) {
- auto res = internal::make_unique<Private>(
- std::max(W, oW), std::max(S, oS), std::min(E, oE),
- std::min(N, oN));
- if (res->west_ < res->east_) {
- return res;
- }
- return nullptr;
- }
-
- // Return larger of two parts of the multipolygon
- auto inter1 = intersection(Private(oW, oS, 180.0, oN));
- auto inter2 = intersection(Private(-180.0, oS, oE, oN));
- if (!inter1) {
- return inter2;
- }
- if (!inter2) {
- return inter1;
- }
- if (inter1->east_ - inter1->west_ > inter2->east_ - inter2->west_) {
- return inter1;
- }
- return inter2;
- // No: crossing antimerian
- } else {
- if (oW <= oE) {
- return otherExtent.intersection(*this);
- }
-
- return internal::make_unique<Private>(std::max(W, oW), std::max(S, oS),
- std::min(E, oE), std::min(N, oN));
- }
-}
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-struct VerticalExtent::Private {
- double minimum_{};
- double maximum_{};
- common::UnitOfMeasureNNPtr unit_;
-
- Private(double minimum, double maximum,
- const common::UnitOfMeasureNNPtr &unit)
- : minimum_(minimum), maximum_(maximum), unit_(unit) {}
-};
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-VerticalExtent::VerticalExtent(double minimumIn, double maximumIn,
- const common::UnitOfMeasureNNPtr &unitIn)
- : d(internal::make_unique<Private>(minimumIn, maximumIn, unitIn)) {}
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-VerticalExtent::~VerticalExtent() = default;
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-/** \brief Returns the minimum of the vertical extent.
- */
-double VerticalExtent::minimumValue() PROJ_CONST_DEFN { return d->minimum_; }
-
-// ---------------------------------------------------------------------------
-
-/** \brief Returns the maximum of the vertical extent.
- */
-double VerticalExtent::maximumValue() PROJ_CONST_DEFN { return d->maximum_; }
-
-// ---------------------------------------------------------------------------
-
-/** \brief Returns the unit of the vertical extent.
- */
-common::UnitOfMeasureNNPtr &VerticalExtent::unit() PROJ_CONST_DEFN {
- return d->unit_;
-}
-
-// ---------------------------------------------------------------------------
-
-/** \brief Instanciate a VerticalExtent.
- *
- * @param minimumIn minimum.
- * @param maximumIn maximum.
- * @param unitIn unit.
- * @return a new VerticalExtent.
- */
-VerticalExtentNNPtr
-VerticalExtent::create(double minimumIn, double maximumIn,
- const common::UnitOfMeasureNNPtr &unitIn) {
- return VerticalExtent::nn_make_shared<VerticalExtent>(minimumIn, maximumIn,
- unitIn);
-}
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-bool VerticalExtent::_isEquivalentTo(const util::IComparable *other,
- util::IComparable::Criterion) const {
- auto otherExtent = dynamic_cast<const VerticalExtent *>(other);
- if (!otherExtent)
- return false;
- return d->minimum_ == otherExtent->d->minimum_ &&
- d->maximum_ == otherExtent->d->maximum_ &&
- d->unit_ == otherExtent->d->unit_;
-}
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-/** \brief Returns whether this extent contains the other one.
- */
-bool VerticalExtent::contains(const VerticalExtentNNPtr &other) const {
- const double thisUnitToSI = d->unit_->conversionToSI();
- const double otherUnitToSI = other->d->unit_->conversionToSI();
- return d->minimum_ * thisUnitToSI <= other->d->minimum_ * otherUnitToSI &&
- d->maximum_ * thisUnitToSI >= other->d->maximum_ * otherUnitToSI;
-}
-
-// ---------------------------------------------------------------------------
-
-/** \brief Returns whether this extent intersects the other one.
- */
-bool VerticalExtent::intersects(const VerticalExtentNNPtr &other) const {
- const double thisUnitToSI = d->unit_->conversionToSI();
- const double otherUnitToSI = other->d->unit_->conversionToSI();
- return d->minimum_ * thisUnitToSI <= other->d->maximum_ * otherUnitToSI &&
- d->maximum_ * thisUnitToSI >= other->d->minimum_ * otherUnitToSI;
-}
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-struct TemporalExtent::Private {
- std::string start_{};
- std::string stop_{};
-
- Private(const std::string &start, const std::string &stop)
- : start_(start), stop_(stop) {}
-};
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-TemporalExtent::TemporalExtent(const std::string &startIn,
- const std::string &stopIn)
- : d(internal::make_unique<Private>(startIn, stopIn)) {}
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-TemporalExtent::~TemporalExtent() = default;
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-/** \brief Returns the start of the temporal extent.
- */
-const std::string &TemporalExtent::start() PROJ_CONST_DEFN { return d->start_; }
-
-// ---------------------------------------------------------------------------
-
-/** \brief Returns the end of the temporal extent.
- */
-const std::string &TemporalExtent::stop() PROJ_CONST_DEFN { return d->stop_; }
-
-// ---------------------------------------------------------------------------
-
-/** \brief Instanciate a TemporalExtent.
- *
- * @param start start.
- * @param stop stop.
- * @return a new TemporalExtent.
- */
-TemporalExtentNNPtr TemporalExtent::create(const std::string &start,
- const std::string &stop) {
- return TemporalExtent::nn_make_shared<TemporalExtent>(start, stop);
-}
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-bool TemporalExtent::_isEquivalentTo(const util::IComparable *other,
- util::IComparable::Criterion) const {
- auto otherExtent = dynamic_cast<const TemporalExtent *>(other);
- if (!otherExtent)
- return false;
- return start() == otherExtent->start() && stop() == otherExtent->stop();
-}
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-/** \brief Returns whether this extent contains the other one.
- */
-bool TemporalExtent::contains(const TemporalExtentNNPtr &other) const {
- return start() <= other->start() && stop() >= other->stop();
-}
-
-// ---------------------------------------------------------------------------
-
-/** \brief Returns whether this extent intersects the other one.
- */
-bool TemporalExtent::intersects(const TemporalExtentNNPtr &other) const {
- return start() <= other->stop() && stop() >= other->start();
-}
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-struct Extent::Private {
- optional<std::string> description_{};
- std::vector<GeographicExtentNNPtr> geographicElements_{};
- std::vector<VerticalExtentNNPtr> verticalElements_{};
- std::vector<TemporalExtentNNPtr> temporalElements_{};
-};
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-Extent::Extent() : d(internal::make_unique<Private>()) {}
-
-// ---------------------------------------------------------------------------
-
-Extent::Extent(const Extent &other)
- : d(internal::make_unique<Private>(*other.d)) {}
-
-// ---------------------------------------------------------------------------
-
-Extent::~Extent() = default;
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-/** Return a textual description of the extent.
- *
- * @return the description, or empty.
- */
-const optional<std::string> &Extent::description() PROJ_CONST_DEFN {
- return d->description_;
-}
-
-// ---------------------------------------------------------------------------
-
-/** Return the geographic element(s) of the extent
- *
- * @return the geographic element(s), or empty.
- */
-const std::vector<GeographicExtentNNPtr> &
-Extent::geographicElements() PROJ_CONST_DEFN {
- return d->geographicElements_;
-}
-
-// ---------------------------------------------------------------------------
-
-/** Return the vertical element(s) of the extent
- *
- * @return the vertical element(s), or empty.
- */
-const std::vector<VerticalExtentNNPtr> &
-Extent::verticalElements() PROJ_CONST_DEFN {
- return d->verticalElements_;
-}
-
-// ---------------------------------------------------------------------------
-
-/** Return the temporal element(s) of the extent
- *
- * @return the temporal element(s), or empty.
- */
-const std::vector<TemporalExtentNNPtr> &
-Extent::temporalElements() PROJ_CONST_DEFN {
- return d->temporalElements_;
-}
-
-// ---------------------------------------------------------------------------
-
-/** \brief Instanciate a Extent.
- *
- * @param descriptionIn Textual description, or empty.
- * @param geographicElementsIn Geographic element(s), or empty.
- * @param verticalElementsIn Vertical element(s), or empty.
- * @param temporalElementsIn Temporal element(s), or empty.
- * @return a new Extent.
- */
-ExtentNNPtr
-Extent::create(const optional<std::string> &descriptionIn,
- const std::vector<GeographicExtentNNPtr> &geographicElementsIn,
- const std::vector<VerticalExtentNNPtr> &verticalElementsIn,
- const std::vector<TemporalExtentNNPtr> &temporalElementsIn) {
- auto extent = Extent::nn_make_shared<Extent>();
- extent->assignSelf(extent);
- extent->d->description_ = descriptionIn;
- extent->d->geographicElements_ = geographicElementsIn;
- extent->d->verticalElements_ = verticalElementsIn;
- extent->d->temporalElements_ = temporalElementsIn;
- return extent;
-}
-
-// ---------------------------------------------------------------------------
-
-/** \brief Instanciate a Extent from a bounding box
- *
- * @param west Western-most coordinate of the limit of the dataset extent (in
- * degrees).
- * @param south Southern-most coordinate of the limit of the dataset extent (in
- * degrees).
- * @param east Eastern-most coordinate of the limit of the dataset extent (in
- * degrees).
- * @param north Northern-most coordinate of the limit of the dataset extent (in
- * degrees).
- * @param descriptionIn Textual description, or empty.
- * @return a new Extent.
- */
-ExtentNNPtr
-Extent::createFromBBOX(double west, double south, double east, double north,
- const util::optional<std::string> &descriptionIn) {
- return create(
- descriptionIn,
- std::vector<GeographicExtentNNPtr>{
- nn_static_pointer_cast<GeographicExtent>(
- GeographicBoundingBox::create(west, south, east, north))},
- std::vector<VerticalExtentNNPtr>(), std::vector<TemporalExtentNNPtr>());
-}
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-bool Extent::_isEquivalentTo(const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
- auto otherExtent = dynamic_cast<const Extent *>(other);
- bool ret =
- (otherExtent &&
- description().has_value() == otherExtent->description().has_value() &&
- *description() == *otherExtent->description() &&
- d->geographicElements_.size() ==
- otherExtent->d->geographicElements_.size() &&
- d->verticalElements_.size() ==
- otherExtent->d->verticalElements_.size() &&
- d->temporalElements_.size() ==
- otherExtent->d->temporalElements_.size());
- if (ret) {
- for (size_t i = 0; ret && i < d->geographicElements_.size(); ++i) {
- ret = d->geographicElements_[i]->_isEquivalentTo(
- otherExtent->d->geographicElements_[i].get(), criterion);
- }
- for (size_t i = 0; ret && i < d->verticalElements_.size(); ++i) {
- ret = d->verticalElements_[i]->_isEquivalentTo(
- otherExtent->d->verticalElements_[i].get(), criterion);
- }
- for (size_t i = 0; ret && i < d->temporalElements_.size(); ++i) {
- ret = d->temporalElements_[i]->_isEquivalentTo(
- otherExtent->d->temporalElements_[i].get(), criterion);
- }
- }
- return ret;
-}
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-/** \brief Returns whether this extent contains the other one.
- *
- * Behaviour only well specified if each sub-extent category as at most
- * one element.
- */
-bool Extent::contains(const ExtentNNPtr &other) const {
- bool res = true;
- if (d->geographicElements_.size() == 1 &&
- other->d->geographicElements_.size() == 1) {
- res = d->geographicElements_[0]->contains(
- other->d->geographicElements_[0]);
- }
- if (res && d->verticalElements_.size() == 1 &&
- other->d->verticalElements_.size() == 1) {
- res = d->verticalElements_[0]->contains(other->d->verticalElements_[0]);
- }
- if (res && d->temporalElements_.size() == 1 &&
- other->d->temporalElements_.size() == 1) {
- res = d->temporalElements_[0]->contains(other->d->temporalElements_[0]);
- }
- return res;
-}
-
-// ---------------------------------------------------------------------------
-
-/** \brief Returns whether this extent intersects the other one.
- *
- * Behaviour only well specified if each sub-extent category as at most
- * one element.
- */
-bool Extent::intersects(const ExtentNNPtr &other) const {
- bool res = true;
- if (d->geographicElements_.size() == 1 &&
- other->d->geographicElements_.size() == 1) {
- res = d->geographicElements_[0]->intersects(
- other->d->geographicElements_[0]);
- }
- if (res && d->verticalElements_.size() == 1 &&
- other->d->verticalElements_.size() == 1) {
- res =
- d->verticalElements_[0]->intersects(other->d->verticalElements_[0]);
- }
- if (res && d->temporalElements_.size() == 1 &&
- other->d->temporalElements_.size() == 1) {
- res =
- d->temporalElements_[0]->intersects(other->d->temporalElements_[0]);
- }
- return res;
-}
-
-// ---------------------------------------------------------------------------
-
-/** \brief Returns the intersection of this extent with another one.
- *
- * Behaviour only well specified if there is one single GeographicExtent
- * in each object.
- * Returns nullptr otherwise.
- */
-ExtentPtr Extent::intersection(const ExtentNNPtr &other) const {
- if (d->geographicElements_.size() == 1 &&
- other->d->geographicElements_.size() == 1) {
- if (contains(other)) {
- return other.as_nullable();
- }
- auto self = util::nn_static_pointer_cast<Extent>(shared_from_this());
- if (other->contains(self)) {
- return self.as_nullable();
- }
- auto geogIntersection = d->geographicElements_[0]->intersection(
- other->d->geographicElements_[0]);
- if (geogIntersection) {
- return create(util::optional<std::string>(),
- std::vector<GeographicExtentNNPtr>{
- NN_NO_CHECK(geogIntersection)},
- std::vector<VerticalExtentNNPtr>{},
- std::vector<TemporalExtentNNPtr>{});
- }
- }
- return nullptr;
-}
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-struct Identifier::Private {
- optional<Citation> authority_{};
- std::string code_{};
- optional<std::string> codeSpace_{};
- optional<std::string> version_{};
- optional<std::string> description_{};
- optional<std::string> uri_{};
-
- Private() = default;
-
- Private(const std::string &codeIn, const PropertyMap &properties)
- : code_(codeIn) {
- setProperties(properties);
- }
-
- private:
- // cppcheck-suppress functionStatic
- void setProperties(const PropertyMap &properties);
-};
-
-// ---------------------------------------------------------------------------
-
-void Identifier::Private::setProperties(
- const PropertyMap &properties) // throw(InvalidValueTypeException)
-{
- {
- const auto pVal = properties.get(AUTHORITY_KEY);
- if (pVal) {
- if (auto genVal = dynamic_cast<const BoxedValue *>(pVal->get())) {
- if (genVal->type() == BoxedValue::Type::STRING) {
- authority_ = Citation(genVal->stringValue());
- } else {
- throw InvalidValueTypeException("Invalid value type for " +
- AUTHORITY_KEY);
- }
- } else {
- if (auto citation =
- dynamic_cast<const Citation *>(pVal->get())) {
- authority_ = *citation;
- } else {
- throw InvalidValueTypeException("Invalid value type for " +
- AUTHORITY_KEY);
- }
- }
- }
- }
-
- {
- const auto pVal = properties.get(CODE_KEY);
- if (pVal) {
- if (auto genVal = dynamic_cast<const BoxedValue *>(pVal->get())) {
- if (genVal->type() == BoxedValue::Type::INTEGER) {
- code_ = toString(genVal->integerValue());
- } else if (genVal->type() == BoxedValue::Type::STRING) {
- code_ = genVal->stringValue();
- } else {
- throw InvalidValueTypeException("Invalid value type for " +
- CODE_KEY);
- }
- } else {
- throw InvalidValueTypeException("Invalid value type for " +
- CODE_KEY);
- }
- }
- }
-
- properties.getStringValue(CODESPACE_KEY, codeSpace_);
- properties.getStringValue(VERSION_KEY, version_);
- properties.getStringValue(DESCRIPTION_KEY, description_);
- properties.getStringValue(URI_KEY, uri_);
-}
-
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-Identifier::Identifier(const std::string &codeIn,
- const util::PropertyMap &properties)
- : d(internal::make_unique<Private>(codeIn, properties)) {}
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-
-// ---------------------------------------------------------------------------
-
-Identifier::Identifier() : d(internal::make_unique<Private>()) {}
-
-// ---------------------------------------------------------------------------
-
-Identifier::Identifier(const Identifier &other)
- : d(internal::make_unique<Private>(*(other.d))) {}
-
-// ---------------------------------------------------------------------------
-
-Identifier::~Identifier() = default;
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-/** \brief Instanciate a Identifier.
- *
- * @param codeIn Alphanumeric value identifying an instance in the codespace
- * @param properties See \ref general_properties.
- * Generally, the Identifier::CODESPACE_KEY should be set.
- * @return a new Identifier.
- */
-IdentifierNNPtr Identifier::create(const std::string &codeIn,
- const PropertyMap &properties) {
- return Identifier::nn_make_shared<Identifier>(codeIn, properties);
-}
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-IdentifierNNPtr
-Identifier::createFromDescription(const std::string &descriptionIn) {
- auto id = Identifier::nn_make_shared<Identifier>();
- id->d->description_ = descriptionIn;
- return id;
-}
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-/** \brief Return a citation for the organization responsible for definition and
- * maintenance of the code.
- *
- * @return the citation for the authority, or empty.
- */
-const optional<Citation> &Identifier::authority() PROJ_CONST_DEFN {
- return d->authority_;
-}
-
-// ---------------------------------------------------------------------------
-
-/** \brief Return the alphanumeric value identifying an instance in the
- * codespace.
- *
- * e.g. "4326" (for EPSG:4326 WGS 84 GeographicCRS)
- *
- * @return the code.
- */
-const std::string &Identifier::code() PROJ_CONST_DEFN { return d->code_; }
-
-// ---------------------------------------------------------------------------
-
-/** \brief Return the organization responsible for definition and maintenance of
- * the code.
- *
- * e.g "EPSG"
- *
- * @return the authority codespace, or empty.
- */
-const optional<std::string> &Identifier::codeSpace() PROJ_CONST_DEFN {
- return d->codeSpace_;
-}
-
-// ---------------------------------------------------------------------------
-
-/** \brief Return the version identifier for the namespace.
- *
- * When appropriate, the edition is identified by the effective date, coded
- * using ISO 8601 date format.
- *
- * @return the version or empty.
- */
-const optional<std::string> &Identifier::version() PROJ_CONST_DEFN {
- return d->version_;
-}
-
-// ---------------------------------------------------------------------------
-
-/** \brief Return the natural language description of the meaning of the code
- * value.
- *
- * @return the description or empty.
- */
-const optional<std::string> &Identifier::description() PROJ_CONST_DEFN {
- return d->description_;
-}
-
-// ---------------------------------------------------------------------------
-
-/** \brief Return the URI of the identifier.
- *
- * @return the URI or empty.
- */
-const optional<std::string> &Identifier::uri() PROJ_CONST_DEFN {
- return d->uri_;
-}
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-void Identifier::_exportToWKT(WKTFormatter *formatter) const {
- const bool isWKT2 = formatter->version() == WKTFormatter::Version::WKT2;
- const std::string &l_code = code();
- const std::string &l_codeSpace = *codeSpace();
- if (!l_codeSpace.empty() && !l_code.empty()) {
- if (isWKT2) {
- formatter->startNode(WKTConstants::ID, false);
- formatter->addQuotedString(l_codeSpace);
- try {
- (void)std::stoi(l_code);
- formatter->add(l_code);
- } catch (const std::exception &) {
- formatter->addQuotedString(l_code);
- }
- if (version().has_value()) {
- auto l_version = *(version());
- try {
- (void)c_locale_stod(l_version);
- formatter->add(l_version);
- } catch (const std::exception &) {
- formatter->addQuotedString(l_version);
- }
- }
- if (authority().has_value() &&
- *(authority()->title()) != l_codeSpace) {
- formatter->startNode(WKTConstants::CITATION, false);
- formatter->addQuotedString(*(authority()->title()));
- formatter->endNode();
- }
- if (uri().has_value()) {
- formatter->startNode(WKTConstants::URI, false);
- formatter->addQuotedString(*(uri()));
- formatter->endNode();
- }
- formatter->endNode();
- } else {
- formatter->startNode(WKTConstants::AUTHORITY, false);
- formatter->addQuotedString(l_codeSpace);
- formatter->addQuotedString(l_code);
- formatter->endNode();
- }
- }
-}
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-static bool isIgnoredChar(char ch) {
- return ch == ' ' || ch == '_' || ch == '-' || ch == '/' || ch == '(' ||
- ch == ')' || ch == '.' || ch == '&';
-}
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-static const struct utf8_to_lower {
- const char *utf8;
- char ascii;
-} map_utf8_to_lower[] = {
- {"\xc3\xa1", 'a'}, // a acute
- {"\xc3\xa4", 'a'}, // a tremma
-
- {"\xc4\x9b", 'e'}, // e reverse circumflex
- {"\xc3\xa8", 'e'}, // e grave
- {"\xc3\xa9", 'e'}, // e acute
- {"\xc3\xab", 'e'}, // e tremma
-
- {"\xc3\xad", 'i'}, // i grave
-
- {"\xc3\xb4", 'o'}, // o circumflex
- {"\xc3\xb6", 'o'}, // o tremma
-
- {"\xc3\xa7", 'c'}, // c cedilla
-};
-
-static const struct utf8_to_lower *get_ascii_replacement(const char *c_str) {
- for (const auto &pair : map_utf8_to_lower) {
- if (*c_str == pair.utf8[0] &&
- strncmp(c_str, pair.utf8, strlen(pair.utf8)) == 0) {
- return &pair;
- }
- }
- return nullptr;
-}
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-std::string Identifier::canonicalizeName(const std::string &str) {
- std::string res;
- const char *c_str = str.c_str();
- for (size_t i = 0; c_str[i] != 0; ++i) {
- const auto ch = c_str[i];
- if (ch == ' ' && c_str[i + 1] == '+' && c_str[i + 2] == ' ') {
- i += 2;
- continue;
- }
- if (ch == '1' && !res.empty() &&
- !(res.back() >= '0' && res.back() <= '9') && c_str[i + 1] == '9' &&
- c_str[i + 2] >= '0' && c_str[i + 2] <= '9') {
- ++i;
- continue;
- }
- if (static_cast<unsigned char>(ch) > 127) {
- const auto *replacement = get_ascii_replacement(c_str + i);
- if (replacement) {
- res.push_back(replacement->ascii);
- i += strlen(replacement->utf8) - 1;
- continue;
- }
- }
- if (!isIgnoredChar(ch)) {
- res.push_back(static_cast<char>(::tolower(ch)));
- }
- }
- return res;
-}
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-/** \brief Returns whether two names are considered equivalent.
- *
- * Two names are equivalent by removing any space, underscore, dash, slash,
- * { or } character from them, and comparing in a case insensitive way.
- */
-bool Identifier::isEquivalentName(const char *a, const char *b) noexcept {
- size_t i = 0;
- size_t j = 0;
- char lastValidA = 0;
- char lastValidB = 0;
- while (a[i] != 0 && b[j] != 0) {
- char aCh = a[i];
- char bCh = b[j];
- if (aCh == ' ' && a[i + 1] == '+' && a[i + 2] == ' ') {
- i += 3;
- continue;
- }
- if (bCh == ' ' && b[j + 1] == '+' && b[j + 2] == ' ') {
- j += 3;
- continue;
- }
- if (isIgnoredChar(aCh)) {
- ++i;
- continue;
- }
- if (isIgnoredChar(bCh)) {
- ++j;
- continue;
- }
- if (aCh == '1' && !(lastValidA >= '0' && lastValidA <= '9') &&
- a[i + 1] == '9' && a[i + 2] >= '0' && a[i + 2] <= '9') {
- i += 2;
- lastValidA = '9';
- continue;
- }
- if (bCh == '1' && !(lastValidB >= '0' && lastValidB <= '9') &&
- b[j + 1] == '9' && b[j + 2] >= '0' && b[j + 2] <= '9') {
- j += 2;
- lastValidB = '9';
- continue;
- }
- if (static_cast<unsigned char>(aCh) > 127) {
- const auto *replacement = get_ascii_replacement(a + i);
- if (replacement) {
- aCh = replacement->ascii;
- i += strlen(replacement->utf8) - 1;
- }
- }
- if (static_cast<unsigned char>(bCh) > 127) {
- const auto *replacement = get_ascii_replacement(b + j);
- if (replacement) {
- bCh = replacement->ascii;
- j += strlen(replacement->utf8) - 1;
- }
- }
- if (::tolower(aCh) != ::tolower(bCh)) {
- return false;
- }
- lastValidA = aCh;
- lastValidB = bCh;
- ++i;
- ++j;
- }
- while (a[i] != 0 && isIgnoredChar(a[i])) {
- ++i;
- }
- while (b[j] != 0 && isIgnoredChar(b[j])) {
- ++j;
- }
- return a[i] == b[j];
-}
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-struct PositionalAccuracy::Private {
- std::string value_{};
-};
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-PositionalAccuracy::PositionalAccuracy(const std::string &valueIn)
- : d(internal::make_unique<Private>()) {
- d->value_ = valueIn;
-}
-
-// ---------------------------------------------------------------------------
-
-//! @cond Doxygen_Suppress
-PositionalAccuracy::~PositionalAccuracy() = default;
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
-/** \brief Return the value of the positional accuracy.
- */
-const std::string &PositionalAccuracy::value() PROJ_CONST_DEFN {
- return d->value_;
-}
-
-// ---------------------------------------------------------------------------
-
-/** \brief Instanciate a PositionalAccuracy.
- *
- * @param valueIn positional accuracy value.
- * @return a new PositionalAccuracy.
- */
-PositionalAccuracyNNPtr PositionalAccuracy::create(const std::string &valueIn) {
- return PositionalAccuracy::nn_make_shared<PositionalAccuracy>(valueIn);
-}
-
-} // namespace metadata
-NS_PROJ_END