Skip to content

Commit

Permalink
Implement promoteTo3D() / demoteTo2D() for DerivedGeographicCRS (fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
rouault committed Aug 16, 2021
1 parent 88322b4 commit bac2521
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 14 deletions.
4 changes: 4 additions & 0 deletions include/proj/crs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions scripts/reference_exported_symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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&)
Expand Down
76 changes: 62 additions & 14 deletions src/iso19111/crs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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 =
Expand All @@ -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();
Expand Down Expand Up @@ -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 {
Expand All @@ -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];
Expand Down Expand Up @@ -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>>
Expand Down
26 changes: 26 additions & 0 deletions test/unit/test_crs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()));
}
}

// ---------------------------------------------------------------------------
Expand Down

0 comments on commit bac2521

Please sign in to comment.