aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2020-11-21 13:55:11 +0100
committerEven Rouault <even.rouault@spatialys.com>2020-11-21 13:55:11 +0100
commit3dea81d9be4712aa90ba79f333338c0b3ecb21e2 (patch)
tree3cc07bee202b24748f2f27198d684db157e542b9
parent571096201bf2cb1dde8933eb3fb7091e12ebbbe4 (diff)
downloadPROJ-3dea81d9be4712aa90ba79f333338c0b3ecb21e2.tar.gz
PROJ-3dea81d9be4712aa90ba79f333338c0b3ecb21e2.zip
Make GeographicCRS/GeodeticCRS::isEquivalentTo() work properly when comparing to a DerivedGeographicCRS/DerivedGeodeticCRS
-rw-r--r--include/proj/crs.hpp5
-rw-r--r--include/proj/util.hpp8
-rw-r--r--src/iso19111/crs.cpp27
-rw-r--r--test/unit/test_crs.cpp24
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"