diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2021-08-16 12:25:07 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-08-16 12:25:07 +0200 |
| commit | 2ddf80a41b90e866ecf113030ff2e241464cb1c8 (patch) | |
| tree | eb4942d69214eabd8e10398cfe852016dcf0ea36 | |
| parent | 0d64108dc8c91bed36ea49ac04e56f4f43a84d27 (diff) | |
| parent | bc97ca635668e5457afc9dbb491c5aa5525ca7de (diff) | |
| download | PROJ-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.hpp | 4 | ||||
| -rw-r--r-- | scripts/reference_exported_symbols.txt | 1 | ||||
| -rw-r--r-- | src/iso19111/crs.cpp | 76 | ||||
| -rw-r--r-- | test/unit/test_crs.cpp | 26 |
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())); + } } // --------------------------------------------------------------------------- |
