aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2021-08-16 12:25:07 +0200
committerGitHub <noreply@github.com>2021-08-16 12:25:07 +0200
commit2ddf80a41b90e866ecf113030ff2e241464cb1c8 (patch)
treeeb4942d69214eabd8e10398cfe852016dcf0ea36
parent0d64108dc8c91bed36ea49ac04e56f4f43a84d27 (diff)
parentbc97ca635668e5457afc9dbb491c5aa5525ca7de (diff)
downloadPROJ-2ddf80a41b90e866ecf113030ff2e241464cb1c8.tar.gz
PROJ-2ddf80a41b90e866ecf113030ff2e241464cb1c8.zip
Merge pull request #2806 from OSGeo/backport-2805-to-8.1
[Backport 8.1] Implement promoteTo3D() / demoteTo2D() for DerivedGeographicCRS (fixes #2803)
-rw-r--r--include/proj/crs.hpp4
-rw-r--r--scripts/reference_exported_symbols.txt1
-rw-r--r--src/iso19111/crs.cpp76
-rw-r--r--test/unit/test_crs.cpp26
4 files changed, 93 insertions, 14 deletions
diff --git a/include/proj/crs.hpp b/include/proj/crs.hpp
index 0f8c5e42..44dda0c5 100644
--- a/include/proj/crs.hpp
+++ b/include/proj/crs.hpp
@@ -1168,6 +1168,10 @@ class PROJ_GCC_DLL DerivedGeographicCRS final : public GeographicCRS,
const operation::ConversionNNPtr &derivingConversionIn,
const cs::EllipsoidalCSNNPtr &csIn);
+ PROJ_DLL DerivedGeographicCRSNNPtr
+ demoteTo2D(const std::string &newName,
+ const io::DatabaseContextPtr &dbContext) const;
+
//! @cond Doxygen_Suppress
PROJ_INTERNAL void _exportToWKT(io::WKTFormatter *formatter)
const override; // throw(io::FormattingException)
diff --git a/scripts/reference_exported_symbols.txt b/scripts/reference_exported_symbols.txt
index 4f853090..f8066394 100644
--- a/scripts/reference_exported_symbols.txt
+++ b/scripts/reference_exported_symbols.txt
@@ -131,6 +131,7 @@ osgeo::proj::crs::DerivedGeodeticCRS::~DerivedGeodeticCRS()
osgeo::proj::crs::DerivedGeodeticCRS::_exportToWKT(osgeo::proj::io::WKTFormatter*) const
osgeo::proj::crs::DerivedGeographicCRS::baseCRS() const
osgeo::proj::crs::DerivedGeographicCRS::create(osgeo::proj::util::PropertyMap const&, dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::crs::GeodeticCRS> > const&, dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::operation::Conversion> > const&, dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::cs::EllipsoidalCS> > const&)
+osgeo::proj::crs::DerivedGeographicCRS::demoteTo2D(std::string const&, std::shared_ptr<osgeo::proj::io::DatabaseContext> const&) const
osgeo::proj::crs::DerivedGeographicCRS::~DerivedGeographicCRS()
osgeo::proj::crs::DerivedProjectedCRS::baseCRS() const
osgeo::proj::crs::DerivedProjectedCRS::create(osgeo::proj::util::PropertyMap const&, dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::crs::ProjectedCRS> > const&, dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::operation::Conversion> > const&, dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::cs::CoordinateSystem> > const&)
diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp
index 28f55ffe..62bb24c3 100644
--- a/src/iso19111/crs.cpp
+++ b/src/iso19111/crs.cpp
@@ -1079,8 +1079,24 @@ CRSNNPtr CRS::promoteTo3D(const std::string &newName,
return props;
};
- const auto geogCRS = dynamic_cast<const GeographicCRS *>(this);
- if (geogCRS) {
+ if (auto derivedGeogCRS =
+ dynamic_cast<const DerivedGeographicCRS *>(this)) {
+ const auto &axisList = derivedGeogCRS->coordinateSystem()->axisList();
+ if (axisList.size() == 2) {
+ auto cs = cs::EllipsoidalCS::create(
+ util::PropertyMap(), axisList[0], axisList[1],
+ verticalAxisIfNotAlreadyPresent);
+ auto baseGeog3DCRS = util::nn_dynamic_pointer_cast<GeodeticCRS>(
+ derivedGeogCRS->baseCRS()->promoteTo3D(
+ std::string(), dbContext, verticalAxisIfNotAlreadyPresent));
+ return util::nn_static_pointer_cast<CRS>(
+ DerivedGeographicCRS::create(
+ createProperties(), NN_CHECK_THROW(baseGeog3DCRS),
+ derivedGeogCRS->derivingConversion(), cs));
+ }
+ }
+
+ else if (auto geogCRS = dynamic_cast<const GeographicCRS *>(this)) {
const auto &axisList = geogCRS->coordinateSystem()->axisList();
if (axisList.size() == 2) {
const auto &l_identifiers = identifiers();
@@ -1120,8 +1136,7 @@ CRSNNPtr CRS::promoteTo3D(const std::string &newName,
}
}
- const auto projCRS = dynamic_cast<const ProjectedCRS *>(this);
- if (projCRS) {
+ else if (auto projCRS = dynamic_cast<const ProjectedCRS *>(this)) {
const auto &axisList = projCRS->coordinateSystem()->axisList();
if (axisList.size() == 2) {
auto base3DCRS =
@@ -1137,8 +1152,7 @@ CRSNNPtr CRS::promoteTo3D(const std::string &newName,
}
}
- const auto boundCRS = dynamic_cast<const BoundCRS *>(this);
- if (boundCRS) {
+ else if (auto boundCRS = dynamic_cast<const BoundCRS *>(this)) {
auto base3DCRS = boundCRS->baseCRS()->promoteTo3D(
newName, dbContext, verticalAxisIfNotAlreadyPresent);
auto transf = boundCRS->transformation();
@@ -1174,18 +1188,21 @@ CRSNNPtr CRS::promoteTo3D(const std::string &newName,
*/
CRSNNPtr CRS::demoteTo2D(const std::string &newName,
const io::DatabaseContextPtr &dbContext) const {
- const auto geogCRS = dynamic_cast<const GeographicCRS *>(this);
- if (geogCRS) {
+
+ if (auto derivedGeogCRS =
+ dynamic_cast<const DerivedGeographicCRS *>(this)) {
+ return derivedGeogCRS->demoteTo2D(newName, dbContext);
+ }
+
+ else if (auto geogCRS = dynamic_cast<const GeographicCRS *>(this)) {
return geogCRS->demoteTo2D(newName, dbContext);
}
- const auto projCRS = dynamic_cast<const ProjectedCRS *>(this);
- if (projCRS) {
+ else if (auto projCRS = dynamic_cast<const ProjectedCRS *>(this)) {
return projCRS->demoteTo2D(newName, dbContext);
}
- const auto boundCRS = dynamic_cast<const BoundCRS *>(this);
- if (boundCRS) {
+ else if (auto boundCRS = dynamic_cast<const BoundCRS *>(this)) {
auto base2DCRS = boundCRS->baseCRS()->demoteTo2D(newName, dbContext);
auto transf = boundCRS->transformation();
try {
@@ -1199,8 +1216,7 @@ CRSNNPtr CRS::demoteTo2D(const std::string &newName,
}
}
- const auto compoundCRS = dynamic_cast<const CompoundCRS *>(this);
- if (compoundCRS) {
+ else if (auto compoundCRS = dynamic_cast<const CompoundCRS *>(this)) {
const auto &components = compoundCRS->componentReferenceSystems();
if (components.size() >= 2) {
return components[0];
@@ -5898,6 +5914,38 @@ bool DerivedGeographicCRS::_isEquivalentTo(
// ---------------------------------------------------------------------------
+/** \brief Return a variant of this CRS "demoted" to a 2D one, if not already
+ * the case.
+ *
+ *
+ * @param newName Name of the new CRS. If empty, nameStr() will be used.
+ * @param dbContext Database context to look for potentially already registered
+ * 2D CRS. May be nullptr.
+ * @return a new CRS demoted to 2D, or the current one if already 2D or not
+ * applicable.
+ * @since 8.1.1
+ */
+DerivedGeographicCRSNNPtr DerivedGeographicCRS::demoteTo2D(
+ const std::string &newName, const io::DatabaseContextPtr &dbContext) const {
+
+ const auto &axisList = coordinateSystem()->axisList();
+ if (axisList.size() == 3) {
+ auto cs = cs::EllipsoidalCS::create(util::PropertyMap(), axisList[0],
+ axisList[1]);
+ auto baseGeog2DCRS = util::nn_dynamic_pointer_cast<GeodeticCRS>(
+ baseCRS()->demoteTo2D(std::string(), dbContext));
+ return DerivedGeographicCRS::create(
+ util::PropertyMap().set(common::IdentifiedObject::NAME_KEY,
+ !newName.empty() ? newName : nameStr()),
+ NN_CHECK_THROW(baseGeog2DCRS), derivingConversion(), cs);
+ }
+
+ return NN_NO_CHECK(std::dynamic_pointer_cast<DerivedGeographicCRS>(
+ shared_from_this().as_nullable()));
+}
+
+// ---------------------------------------------------------------------------
+
//! @cond Doxygen_Suppress
std::list<std::pair<CRSNNPtr, int>>
diff --git a/test/unit/test_crs.cpp b/test/unit/test_crs.cpp
index 10b21ee5..fb3c14ae 100644
--- a/test/unit/test_crs.cpp
+++ b/test/unit/test_crs.cpp
@@ -6403,6 +6403,32 @@ TEST(crs, promoteTo3D_and_demoteTo2D) {
EXPECT_TRUE(dynamic_cast<const ProjectedCRS *>(demoted.get()) !=
nullptr);
}
+
+ {
+ auto crs = createDerivedGeographicCRS();
+ auto crs3D = crs->promoteTo3D(std::string(), dbContext);
+ auto crs3DAsDerivedGeog =
+ nn_dynamic_pointer_cast<DerivedGeographicCRS>(crs3D);
+ ASSERT_TRUE(crs3DAsDerivedGeog != nullptr);
+ EXPECT_EQ(crs3DAsDerivedGeog->baseCRS()
+ ->coordinateSystem()
+ ->axisList()
+ .size(),
+ 3U);
+ EXPECT_EQ(crs3DAsDerivedGeog->coordinateSystem()->axisList().size(),
+ 3U);
+ EXPECT_TRUE(crs3DAsDerivedGeog->promoteTo3D(std::string(), nullptr)
+ ->isEquivalentTo(crs3DAsDerivedGeog.get()));
+
+ auto demoted = crs3DAsDerivedGeog->demoteTo2D(std::string(), dbContext);
+ EXPECT_EQ(demoted->baseCRS()->coordinateSystem()->axisList().size(),
+ 2U);
+ EXPECT_EQ(demoted->coordinateSystem()->axisList().size(), 2U);
+ EXPECT_TRUE(demoted->isEquivalentTo(
+ crs.get(), IComparable::Criterion::EQUIVALENT));
+ EXPECT_TRUE(demoted->demoteTo2D(std::string(), nullptr)
+ ->isEquivalentTo(demoted.get()));
+ }
}
// ---------------------------------------------------------------------------