diff options
| -rw-r--r-- | include/proj/crs.hpp | 5 | ||||
| -rw-r--r-- | include/proj/util.hpp | 8 | ||||
| -rw-r--r-- | src/iso19111/crs.cpp | 27 | ||||
| -rw-r--r-- | test/unit/test_crs.cpp | 24 |
4 files changed, 55 insertions, 9 deletions
diff --git a/include/proj/crs.hpp b/include/proj/crs.hpp index ec755728..b921f4bb 100644 --- a/include/proj/crs.hpp +++ b/include/proj/crs.hpp @@ -340,6 +340,11 @@ class PROJ_GCC_DLL GeodeticCRS : virtual public SingleCRS, PROJ_INTERNAL std::list<std::pair<CRSNNPtr, int>> _identify(const io::AuthorityFactoryPtr &authorityFactory) const override; + PROJ_INTERNAL bool + _isEquivalentToNoTypeCheck(const util::IComparable *other, + util::IComparable::Criterion criterion, + const io::DatabaseContextPtr &dbContext) const; + INLINED_MAKE_SHARED private: diff --git a/include/proj/util.hpp b/include/proj/util.hpp index 3d85e579..2ada4f79 100644 --- a/include/proj/util.hpp +++ b/include/proj/util.hpp @@ -213,6 +213,14 @@ template <typename T> using nn_shared_ptr = nn<std::shared_ptr<T>>; // To avoid formatting differences between clang-format 3.8 and 7 #define PROJ_NOEXCEPT noexcept +//! @cond Doxygen_Suppress +// isOfExactType<MyType>(*p) checks that the type of *p is exactly MyType +template <typename TemplateT, typename ObjectT> +inline bool isOfExactType(const ObjectT &o) { + return typeid(TemplateT).hash_code() == typeid(o).hash_code(); +} +//! @endcond + /** \brief Loose transposition of [std::optional] * (https://en.cppreference.com/w/cpp/utility/optional) available from C++17. */ template <class T> class optional { diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp index 84b98984..de882105 100644 --- a/src/iso19111/crs.cpp +++ b/src/iso19111/crs.cpp @@ -1926,11 +1926,19 @@ getStandardCriterion(util::IComparable::Criterion criterion) { bool GeodeticCRS::_isEquivalentTo( const util::IComparable *other, util::IComparable::Criterion criterion, const io::DatabaseContextPtr &dbContext) const { + if (other == nullptr || !util::isOfExactType<GeodeticCRS>(*other)) { + return false; + } + return _isEquivalentToNoTypeCheck(other, criterion, dbContext); +} + +bool GeodeticCRS::_isEquivalentToNoTypeCheck( + const util::IComparable *other, util::IComparable::Criterion criterion, + const io::DatabaseContextPtr &dbContext) const { const auto standardCriterion = getStandardCriterion(criterion); - auto otherGeodCRS = dynamic_cast<const GeodeticCRS *>(other); + // TODO test velocityModel - return otherGeodCRS != nullptr && - SingleCRS::baseIsEquivalentTo(other, standardCriterion, dbContext); + return SingleCRS::baseIsEquivalentTo(other, standardCriterion, dbContext); } //! @endcond @@ -2486,12 +2494,13 @@ bool GeographicCRS::is2DPartOf3D(util::nn<const GeographicCRS *> other, bool GeographicCRS::_isEquivalentTo( const util::IComparable *other, util::IComparable::Criterion criterion, const io::DatabaseContextPtr &dbContext) const { - auto otherGeogCRS = dynamic_cast<const GeographicCRS *>(other); - if (otherGeogCRS == nullptr) { + if (other == nullptr || !util::isOfExactType<GeographicCRS>(*other)) { return false; } + const auto standardCriterion = getStandardCriterion(criterion); - if (GeodeticCRS::_isEquivalentTo(other, standardCriterion, dbContext)) { + if (GeodeticCRS::_isEquivalentToNoTypeCheck(other, standardCriterion, + dbContext)) { return true; } if (criterion != @@ -2510,7 +2519,8 @@ bool GeographicCRS::_isEquivalentTo( cs::EllipsoidalCS::AxisOrder::LONG_EAST_LAT_NORTH ? cs::EllipsoidalCS::createLatitudeLongitude(unit) : cs::EllipsoidalCS::createLongitudeLatitude(unit)) - ->GeodeticCRS::_isEquivalentTo(other, standardCriterion, dbContext); + ->GeodeticCRS::_isEquivalentToNoTypeCheck(other, standardCriterion, + dbContext); } return false; } @@ -3889,8 +3899,7 @@ ProjectedCRS::create(const util::PropertyMap &properties, bool ProjectedCRS::_isEquivalentTo( const util::IComparable *other, util::IComparable::Criterion criterion, const io::DatabaseContextPtr &dbContext) const { - auto otherProjCRS = dynamic_cast<const ProjectedCRS *>(other); - return otherProjCRS != nullptr && + return other != nullptr && util::isOfExactType<ProjectedCRS>(*other) && DerivedCRS::_isEquivalentTo(other, criterion, dbContext); } diff --git a/test/unit/test_crs.cpp b/test/unit/test_crs.cpp index 38afdce3..aea72da2 100644 --- a/test/unit/test_crs.cpp +++ b/test/unit/test_crs.cpp @@ -4750,6 +4750,18 @@ static DerivedGeographicCRSNNPtr createDerivedGeographicCRS() { // --------------------------------------------------------------------------- +TEST(crs, derivedGeographicCRS_basic) { + + auto derivedCRS = createDerivedGeographicCRS(); + EXPECT_TRUE(derivedCRS->isEquivalentTo(derivedCRS.get())); + EXPECT_FALSE(derivedCRS->isEquivalentTo( + derivedCRS->baseCRS().get(), IComparable::Criterion::EQUIVALENT)); + EXPECT_FALSE(derivedCRS->baseCRS()->isEquivalentTo( + derivedCRS.get(), IComparable::Criterion::EQUIVALENT)); +} + +// --------------------------------------------------------------------------- + TEST(crs, derivedGeographicCRS_WKT2) { auto expected = "GEODCRS[\"WMO Atlantic Pole\",\n" @@ -4950,6 +4962,18 @@ static DerivedGeodeticCRSNNPtr createDerivedGeodeticCRS() { // --------------------------------------------------------------------------- +TEST(crs, derivedGeodeticCRS_basic) { + + auto derivedCRS = createDerivedGeodeticCRS(); + EXPECT_TRUE(derivedCRS->isEquivalentTo(derivedCRS.get())); + EXPECT_FALSE(derivedCRS->isEquivalentTo( + derivedCRS->baseCRS().get(), IComparable::Criterion::EQUIVALENT)); + EXPECT_FALSE(derivedCRS->baseCRS()->isEquivalentTo( + derivedCRS.get(), IComparable::Criterion::EQUIVALENT)); +} + +// --------------------------------------------------------------------------- + TEST(crs, derivedGeodeticCRS_WKT2) { auto expected = "GEODCRS[\"Derived geodetic CRS\",\n" |
