aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2019-12-16 15:23:22 +0100
committerEven Rouault <even.rouault@spatialys.com>2019-12-16 17:50:39 +0100
commitbd9ecbacf575a1926fb8e223c4add1a4cc45d7f3 (patch)
tree770cc59bf111f8b427d9bc14ea7548ff3edbc9b3 /src
parenta68c146d7f3c1efb0f42b46c708a0a195e51a2ff (diff)
downloadPROJ-bd9ecbacf575a1926fb8e223c4add1a4cc45d7f3.tar.gz
PROJ-bd9ecbacf575a1926fb8e223c4add1a4cc45d7f3.zip
identify(): take into datum name aliases (fixes #1800)
Diffstat (limited to 'src')
-rw-r--r--src/iso19111/c_api.cpp57
-rw-r--r--src/iso19111/common.cpp33
-rw-r--r--src/iso19111/coordinateoperation.cpp91
-rw-r--r--src/iso19111/coordinatesystem.cpp15
-rw-r--r--src/iso19111/crs.cpp259
-rw-r--r--src/iso19111/datum.cpp115
-rw-r--r--src/iso19111/factory.cpp62
-rw-r--r--src/iso19111/metadata.cpp21
-rw-r--r--src/iso19111/util.cpp8
-rw-r--r--src/proj.h4
10 files changed, 439 insertions, 226 deletions
diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp
index 5e2ac522..5a5e97f6 100644
--- a/src/iso19111/c_api.cpp
+++ b/src/iso19111/c_api.cpp
@@ -1142,15 +1142,9 @@ PJ_OBJ_LIST *proj_get_non_deprecated(PJ_CONTEXT *ctx, const PJ *obj) {
// ---------------------------------------------------------------------------
-/** \brief Return whether two objects are equivalent.
- *
- * @param obj Object (must not be NULL)
- * @param other Other object (must not be NULL)
- * @param criterion Comparison criterion
- * @return TRUE if they are equivalent
- */
-int proj_is_equivalent_to(const PJ *obj, const PJ *other,
- PJ_COMPARISON_CRITERION criterion) {
+static int proj_is_equivalent_to_internal(PJ_CONTEXT *ctx, const PJ *obj,
+ const PJ *other,
+ PJ_COMPARISON_CRITERION criterion) {
assert(obj);
assert(other);
if (!obj->iso_obj) {
@@ -1172,7 +1166,50 @@ int proj_is_equivalent_to(const PJ *obj, const PJ *other,
return IComparable::Criterion::EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS;
})(criterion);
- return obj->iso_obj->isEquivalentTo(other->iso_obj.get(), cppCriterion);
+ int res = obj->iso_obj->isEquivalentTo(
+ other->iso_obj.get(), cppCriterion,
+ ctx ? getDBcontextNoException(ctx, "proj_is_equivalent_to_with_ctx")
+ : nullptr);
+ if (ctx && ctx->cpp_context) {
+ ctx->cpp_context->autoCloseDbIfNeeded();
+ }
+ return res;
+}
+
+// ---------------------------------------------------------------------------
+
+/** \brief Return whether two objects are equivalent.
+ *
+ * Use proj_is_equivalent_to_with_ctx() to be able to use database information.
+ *
+ * @param obj Object (must not be NULL)
+ * @param other Other object (must not be NULL)
+ * @param criterion Comparison criterion
+ * @return TRUE if they are equivalent
+ */
+int proj_is_equivalent_to(const PJ *obj, const PJ *other,
+ PJ_COMPARISON_CRITERION criterion) {
+ return proj_is_equivalent_to_internal(nullptr, obj, other, criterion);
+}
+
+// ---------------------------------------------------------------------------
+
+/** \brief Return whether two objects are equivalent
+ *
+ * Possibly using database to check for name aliases.
+ *
+ * @param ctx PROJ context, or NULL for default context
+ * @param obj Object (must not be NULL)
+ * @param other Other object (must not be NULL)
+ * @param criterion Comparison criterion
+ * @return TRUE if they are equivalent
+ * @since 6.3
+ */
+int proj_is_equivalent_to_with_ctx(PJ_CONTEXT *ctx, const PJ *obj,
+ const PJ *other,
+ PJ_COMPARISON_CRITERION criterion) {
+ SANITIZE_CTX(ctx);
+ return proj_is_equivalent_to_internal(ctx, obj, other, criterion);
}
// ---------------------------------------------------------------------------
diff --git a/src/iso19111/common.cpp b/src/iso19111/common.cpp
index 97900bda..f2e4de4c 100644
--- a/src/iso19111/common.cpp
+++ b/src/iso19111/common.cpp
@@ -901,19 +901,19 @@ void IdentifiedObject::formatRemarks(JSONFormatter *formatter) const {
// ---------------------------------------------------------------------------
bool IdentifiedObject::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherIdObj = dynamic_cast<const IdentifiedObject *>(other);
if (!otherIdObj)
return false;
- return _isEquivalentTo(otherIdObj, criterion);
+ return _isEquivalentTo(otherIdObj, criterion, dbContext);
}
// ---------------------------------------------------------------------------
-bool IdentifiedObject::_isEquivalentTo(const IdentifiedObject *otherIdObj,
- util::IComparable::Criterion criterion)
- PROJ_PURE_DEFN {
+bool IdentifiedObject::_isEquivalentTo(
+ const IdentifiedObject *otherIdObj, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) PROJ_PURE_DEFN {
if (criterion == util::IComparable::Criterion::STRICT) {
if (!ci_equal(nameStr(), otherIdObj->nameStr())) {
return false;
@@ -922,12 +922,19 @@ bool IdentifiedObject::_isEquivalentTo(const IdentifiedObject *otherIdObj,
} else {
if (!metadata::Identifier::isEquivalentName(
nameStr().c_str(), otherIdObj->nameStr().c_str())) {
- return false;
+ return hasEquivalentNameToUsingAlias(otherIdObj, dbContext);
}
}
return true;
}
+// ---------------------------------------------------------------------------
+
+bool IdentifiedObject::hasEquivalentNameToUsingAlias(
+ const IdentifiedObject *, const io::DatabaseContextPtr &) const {
+ return false;
+}
+
//! @endcond
// ---------------------------------------------------------------------------
@@ -1092,8 +1099,8 @@ void ObjectDomain::_exportToJSON(JSONFormatter *formatter) const {
//! @cond Doxygen_Suppress
bool ObjectDomain::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherDomain = dynamic_cast<const ObjectDomain *>(other);
if (!otherDomain)
return false;
@@ -1106,7 +1113,7 @@ bool ObjectDomain::_isEquivalentTo(
return false;
return domainOfValidity().get() == nullptr ||
domainOfValidity()->_isEquivalentTo(
- otherDomain->domainOfValidity().get(), criterion);
+ otherDomain->domainOfValidity().get(), criterion, dbContext);
}
//! @endcond
@@ -1249,14 +1256,14 @@ void ObjectUsage::baseExportToJSON(JSONFormatter *formatter) const {
//! @cond Doxygen_Suppress
bool ObjectUsage::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherObjUsage = dynamic_cast<const ObjectUsage *>(other);
if (!otherObjUsage)
return false;
// TODO: incomplete
- return IdentifiedObject::_isEquivalentTo(other, criterion);
+ return IdentifiedObject::_isEquivalentTo(other, criterion, dbContext);
}
//! @endcond
diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp
index 2c3e38ac..62d72e65 100644
--- a/src/iso19111/coordinateoperation.cpp
+++ b/src/iso19111/coordinateoperation.cpp
@@ -1068,11 +1068,11 @@ void OperationMethod::_exportToJSON(
//! @cond Doxygen_Suppress
bool OperationMethod::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherOM = dynamic_cast<const OperationMethod *>(other);
if (otherOM == nullptr ||
- !IdentifiedObject::_isEquivalentTo(other, criterion)) {
+ !IdentifiedObject::_isEquivalentTo(other, criterion, dbContext)) {
return false;
}
// TODO test formula and formulaCitation
@@ -1084,7 +1084,8 @@ bool OperationMethod::_isEquivalentTo(
}
if (criterion == util::IComparable::Criterion::STRICT) {
for (size_t i = 0; i < paramsSize; i++) {
- if (!params[i]->_isEquivalentTo(otherParams[i].get(), criterion)) {
+ if (!params[i]->_isEquivalentTo(otherParams[i].get(), criterion,
+ dbContext)) {
return false;
}
}
@@ -1094,8 +1095,8 @@ bool OperationMethod::_isEquivalentTo(
bool found = false;
for (size_t j = 0; j < paramsSize; j++) {
if (candidateIndices[j] &&
- params[i]->_isEquivalentTo(otherParams[j].get(),
- criterion)) {
+ params[i]->_isEquivalentTo(otherParams[j].get(), criterion,
+ dbContext)) {
candidateIndices[j] = false;
found = true;
break;
@@ -1341,14 +1342,14 @@ bool OperationParameterValue::convertFromAbridged(
//! @cond Doxygen_Suppress
bool OperationParameterValue::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherOPV = dynamic_cast<const OperationParameterValue *>(other);
if (otherOPV == nullptr) {
return false;
}
- if (!d->parameter->_isEquivalentTo(otherOPV->d->parameter.get(),
- criterion)) {
+ if (!d->parameter->_isEquivalentTo(otherOPV->d->parameter.get(), criterion,
+ dbContext)) {
return false;
}
if (criterion == util::IComparable::Criterion::STRICT) {
@@ -1356,7 +1357,7 @@ bool OperationParameterValue::_isEquivalentTo(
otherOPV->d->parameterValue.get(), criterion);
}
if (d->parameterValue->_isEquivalentTo(otherOPV->d->parameterValue.get(),
- criterion)) {
+ criterion, dbContext)) {
return true;
}
if (d->parameter->getEPSGCode() ==
@@ -1446,16 +1447,16 @@ OperationParameter::create(const util::PropertyMap &properties) {
//! @cond Doxygen_Suppress
bool OperationParameter::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherOP = dynamic_cast<const OperationParameter *>(other);
if (otherOP == nullptr) {
return false;
}
if (criterion == util::IComparable::Criterion::STRICT) {
- return IdentifiedObject::_isEquivalentTo(other, criterion);
+ return IdentifiedObject::_isEquivalentTo(other, criterion, dbContext);
}
- if (IdentifiedObject::_isEquivalentTo(other, criterion)) {
+ if (IdentifiedObject::_isEquivalentTo(other, criterion, dbContext)) {
return true;
}
auto l_epsgCode = getEPSGCode();
@@ -1759,19 +1760,20 @@ static SingleOperationNNPtr createPROJBased(
//! @cond Doxygen_Suppress
bool SingleOperation::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
- return _isEquivalentTo(other, criterion, false);
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
+ return _isEquivalentTo(other, criterion, dbContext, false);
}
bool SingleOperation::_isEquivalentTo(const util::IComparable *other,
util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext,
bool inOtherDirection) const {
auto otherSO = dynamic_cast<const SingleOperation *>(other);
if (otherSO == nullptr ||
(criterion == util::IComparable::Criterion::STRICT &&
- !ObjectUsage::_isEquivalentTo(other, criterion))) {
+ !ObjectUsage::_isEquivalentTo(other, criterion, dbContext))) {
return false;
}
@@ -1781,7 +1783,8 @@ bool SingleOperation::_isEquivalentTo(const util::IComparable *other,
bool equivalentMethods =
(criterion == util::IComparable::Criterion::EQUIVALENT &&
methodEPSGCode != 0 && methodEPSGCode == otherMethodEPSGCode) ||
- d->method_->_isEquivalentTo(otherSO->d->method_.get(), criterion);
+ d->method_->_isEquivalentTo(otherSO->d->method_.get(), criterion,
+ dbContext);
if (!equivalentMethods &&
criterion == util::IComparable::Criterion::EQUIVALENT) {
if ((methodEPSGCode == EPSG_CODE_METHOD_LAMBERT_AZIMUTHAL_EQUAL_AREA &&
@@ -1854,7 +1857,7 @@ bool SingleOperation::_isEquivalentTo(const util::IComparable *other,
EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP) {
// Convert from 2SP to 1SP as the other direction has more
// degree of liberties.
- return otherSO->_isEquivalentTo(this, criterion);
+ return otherSO->_isEquivalentTo(this, criterion, dbContext);
} else if ((methodEPSGCode == EPSG_CODE_METHOD_MERCATOR_VARIANT_A &&
otherMethodEPSGCode ==
EPSG_CODE_METHOD_MERCATOR_VARIANT_B) ||
@@ -1870,7 +1873,8 @@ bool SingleOperation::_isEquivalentTo(const util::IComparable *other,
auto eqConv =
conv->convertToOtherMethod(otherMethodEPSGCode);
if (eqConv) {
- return eqConv->_isEquivalentTo(other, criterion);
+ return eqConv->_isEquivalentTo(other, criterion,
+ dbContext);
}
}
}
@@ -1888,7 +1892,8 @@ bool SingleOperation::_isEquivalentTo(const util::IComparable *other,
return false;
}
for (size_t i = 0; i < valuesSize; i++) {
- if (!values[i]->_isEquivalentTo(otherValues[i].get(), criterion)) {
+ if (!values[i]->_isEquivalentTo(otherValues[i].get(), criterion,
+ dbContext)) {
return false;
}
}
@@ -1909,7 +1914,8 @@ bool SingleOperation::_isEquivalentTo(const util::IComparable *other,
bool sameNameDifferentValue = false;
for (size_t j = 0; j < otherValuesSize; j++) {
if (candidateIndices[j] &&
- values[i]->_isEquivalentTo(otherValues[j].get(), criterion)) {
+ values[i]->_isEquivalentTo(otherValues[j].get(), criterion,
+ dbContext)) {
candidateIndices[j] = false;
equivalent = true;
break;
@@ -1921,7 +1927,8 @@ bool SingleOperation::_isEquivalentTo(const util::IComparable *other,
return false;
sameNameDifferentValue =
opParamvalue->parameter()->_isEquivalentTo(
- otherOpParamvalue->parameter().get(), criterion);
+ otherOpParamvalue->parameter().get(), criterion,
+ dbContext);
if (sameNameDifferentValue) {
candidateIndices[j] = false;
break;
@@ -1949,13 +1956,13 @@ bool SingleOperation::_isEquivalentTo(const util::IComparable *other,
->parameterValue(
EPSG_CODE_PARAMETER_LATITUDE_2ND_STD_PARALLEL)
.get(),
- criterion) &&
+ criterion, dbContext) &&
value_2nd->_isEquivalentTo(
otherSO
->parameterValue(
EPSG_CODE_PARAMETER_LATITUDE_1ST_STD_PARALLEL)
.get(),
- criterion);
+ criterion, dbContext);
}
}
}
@@ -1987,7 +1994,7 @@ bool SingleOperation::_isEquivalentTo(const util::IComparable *other,
// In the case the arguments don't perfectly match, try the reverse
// check.
if (equivalent && foundMissingArgs && !inOtherDirection) {
- return otherSO->_isEquivalentTo(this, criterion, true);
+ return otherSO->_isEquivalentTo(this, criterion, dbContext, true);
}
// Equivalent formulations of 2SP can have different parameters
@@ -2002,8 +2009,8 @@ bool SingleOperation::_isEquivalentTo(const util::IComparable *other,
auto otherAs1SP = otherConv->convertToOtherMethod(
EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_1SP);
if (thisAs1SP && otherAs1SP) {
- equivalent =
- thisAs1SP->_isEquivalentTo(otherAs1SP.get(), criterion);
+ equivalent = thisAs1SP->_isEquivalentTo(otherAs1SP.get(),
+ criterion, dbContext);
}
}
}
@@ -2412,9 +2419,9 @@ void ParameterValue::_exportToWKT(io::WKTFormatter *formatter) const {
// ---------------------------------------------------------------------------
//! @cond Doxygen_Suppress
-bool ParameterValue::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+bool ParameterValue::_isEquivalentTo(const util::IComparable *other,
+ util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &) const {
auto otherPV = dynamic_cast<const ParameterValue *>(other);
if (otherPV == nullptr) {
return false;
@@ -10186,12 +10193,12 @@ void ConcatenatedOperation::_exportToPROJString(
//! @cond Doxygen_Suppress
bool ConcatenatedOperation::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherCO = dynamic_cast<const ConcatenatedOperation *>(other);
if (otherCO == nullptr ||
(criterion == util::IComparable::Criterion::STRICT &&
- !ObjectUsage::_isEquivalentTo(other, criterion))) {
+ !ObjectUsage::_isEquivalentTo(other, criterion, dbContext))) {
return false;
}
const auto &steps = operations();
@@ -10200,7 +10207,8 @@ bool ConcatenatedOperation::_isEquivalentTo(
return false;
}
for (size_t i = 0; i < steps.size(); i++) {
- if (!steps[i]->_isEquivalentTo(otherSteps[i].get(), criterion)) {
+ if (!steps[i]->_isEquivalentTo(otherSteps[i].get(), criterion,
+ dbContext)) {
return false;
}
}
@@ -14841,14 +14849,15 @@ void InverseCoordinateOperation::_exportToPROJString(
// ---------------------------------------------------------------------------
bool InverseCoordinateOperation::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherICO = dynamic_cast<const InverseCoordinateOperation *>(other);
if (otherICO == nullptr ||
- !ObjectUsage::_isEquivalentTo(other, criterion)) {
+ !ObjectUsage::_isEquivalentTo(other, criterion, dbContext)) {
return false;
}
- return inverse()->_isEquivalentTo(otherICO->inverse().get(), criterion);
+ return inverse()->_isEquivalentTo(otherICO->inverse().get(), criterion,
+ dbContext);
}
// ---------------------------------------------------------------------------
diff --git a/src/iso19111/coordinatesystem.cpp b/src/iso19111/coordinatesystem.cpp
index 6769b486..163f0f43 100644
--- a/src/iso19111/coordinatesystem.cpp
+++ b/src/iso19111/coordinatesystem.cpp
@@ -429,8 +429,8 @@ void CoordinateSystemAxis::_exportToJSON(
//! @cond Doxygen_Suppress
bool CoordinateSystemAxis::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherCSA = dynamic_cast<const CoordinateSystemAxis *>(other);
if (otherCSA == nullptr) {
return false;
@@ -441,7 +441,7 @@ bool CoordinateSystemAxis::_isEquivalentTo(
return false;
}
if (criterion == util::IComparable::Criterion::STRICT) {
- if (!IdentifiedObject::_isEquivalentTo(other, criterion)) {
+ if (!IdentifiedObject::_isEquivalentTo(other, criterion, dbContext)) {
return false;
}
if (abbreviation() != otherCSA->abbreviation()) {
@@ -599,11 +599,11 @@ void CoordinateSystem::_exportToJSON(
//! @cond Doxygen_Suppress
bool CoordinateSystem::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherCS = dynamic_cast<const CoordinateSystem *>(other);
if (otherCS == nullptr ||
- !IdentifiedObject::_isEquivalentTo(other, criterion)) {
+ !IdentifiedObject::_isEquivalentTo(other, criterion, dbContext)) {
return false;
}
const auto &list = axisList();
@@ -615,7 +615,8 @@ bool CoordinateSystem::_isEquivalentTo(
return false;
}
for (size_t i = 0; i < list.size(); i++) {
- if (!list[i]->_isEquivalentTo(otherList[i].get(), criterion)) {
+ if (!list[i]->_isEquivalentTo(otherList[i].get(), criterion,
+ dbContext)) {
return false;
}
}
diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp
index f231d072..cf90c388 100644
--- a/src/iso19111/crs.cpp
+++ b/src/iso19111/crs.cpp
@@ -391,7 +391,7 @@ CRSNNPtr CRS::createBoundCRSToWGS84IfPossible(
if (boundCRS) {
if (boundCRS->hubCRS()->_isEquivalentTo(
GeographicCRS::EPSG_4326.get(),
- util::IComparable::Criterion::EQUIVALENT)) {
+ util::IComparable::Criterion::EQUIVALENT, dbContext)) {
return NN_NO_CHECK(boundCRS);
}
}
@@ -400,16 +400,16 @@ CRSNNPtr CRS::createBoundCRSToWGS84IfPossible(
auto geogCRS = extractGeographicCRS();
auto hubCRS = util::nn_static_pointer_cast<CRS>(GeographicCRS::EPSG_4326);
if (geodCRS && !geogCRS) {
- if (geodCRS->_isEquivalentTo(
- GeographicCRS::EPSG_4978.get(),
- util::IComparable::Criterion::EQUIVALENT)) {
+ if (geodCRS->_isEquivalentTo(GeographicCRS::EPSG_4978.get(),
+ util::IComparable::Criterion::EQUIVALENT,
+ dbContext)) {
return thisAsCRS;
}
hubCRS = util::nn_static_pointer_cast<CRS>(GeodeticCRS::EPSG_4978);
} else if (!geogCRS ||
geogCRS->_isEquivalentTo(
GeographicCRS::EPSG_4326.get(),
- util::IComparable::Criterion::EQUIVALENT)) {
+ util::IComparable::Criterion::EQUIVALENT, dbContext)) {
return thisAsCRS;
} else {
geodCRS = geogCRS;
@@ -1022,18 +1022,19 @@ const cs::CoordinateSystemNNPtr &SingleCRS::coordinateSystem() PROJ_PURE_DEFN {
// ---------------------------------------------------------------------------
bool SingleCRS::baseIsEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherSingleCRS = dynamic_cast<const SingleCRS *>(other);
if (otherSingleCRS == nullptr ||
(criterion == util::IComparable::Criterion::STRICT &&
- !ObjectUsage::_isEquivalentTo(other, criterion))) {
+ !ObjectUsage::_isEquivalentTo(other, criterion, dbContext))) {
return false;
}
const auto &thisDatum = d->datum;
const auto &otherDatum = otherSingleCRS->d->datum;
if (thisDatum) {
- if (!thisDatum->_isEquivalentTo(otherDatum.get(), criterion)) {
+ if (!thisDatum->_isEquivalentTo(otherDatum.get(), criterion,
+ dbContext)) {
return false;
}
} else {
@@ -1044,7 +1045,8 @@ bool SingleCRS::baseIsEquivalentTo(
// TODO test DatumEnsemble
return d->coordinateSystem->_isEquivalentTo(
- otherSingleCRS->d->coordinateSystem.get(), criterion) &&
+ otherSingleCRS->d->coordinateSystem.get(), criterion,
+ dbContext) &&
getExtensionProj4() == otherSingleCRS->getExtensionProj4();
}
@@ -1579,13 +1581,13 @@ getStandardCriterion(util::IComparable::Criterion criterion) {
//! @cond Doxygen_Suppress
bool GeodeticCRS::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ 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);
+ SingleCRS::baseIsEquivalentTo(other, standardCriterion, dbContext);
}
//! @endcond
@@ -1686,6 +1688,9 @@ GeodeticCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
std::list<Pair> res;
const auto &thisName(nameStr());
+ io::DatabaseContextPtr dbContext =
+ authorityFactory ? authorityFactory->databaseContext().as_nullable()
+ : nullptr;
const bool l_implicitCS = CRS::getPrivate()->implicitCS_;
const auto crsCriterion =
l_implicitCS
@@ -1699,7 +1704,7 @@ GeodeticCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
const bool nameEquivalent = metadata::Identifier::isEquivalentName(
thisName.c_str(), crs->nameStr().c_str());
const bool nameEqual = thisName == crs->nameStr();
- const bool isEq = _isEquivalentTo(crs.get(), crsCriterion);
+ const bool isEq = _isEquivalentTo(crs.get(), crsCriterion, dbContext);
if (nameEquivalent && isEq && (!authorityFactory || nameEqual)) {
res.emplace_back(util::nn_static_pointer_cast<GeodeticCRS>(crs),
nameEqual ? 100 : 90);
@@ -1734,13 +1739,14 @@ GeodeticCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
const auto &thisDatum(datum());
auto searchByDatum = [this, &authorityFactory, &res, &thisDatum,
- &geodetic_crs_type, crsCriterion]() {
+ &geodetic_crs_type, crsCriterion, &dbContext]() {
for (const auto &id : thisDatum->identifiers()) {
try {
auto tempRes = authorityFactory->createGeodeticCRSFromDatum(
*id->codeSpace(), id->code(), geodetic_crs_type);
for (const auto &crs : tempRes) {
- if (_isEquivalentTo(crs.get(), crsCriterion)) {
+ if (_isEquivalentTo(crs.get(), crsCriterion,
+ dbContext)) {
res.emplace_back(crs, 70);
}
}
@@ -1752,7 +1758,7 @@ GeodeticCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
const auto &thisEllipsoid(ellipsoid());
auto searchByEllipsoid = [this, &authorityFactory, &res, &thisDatum,
&thisEllipsoid, &geodetic_crs_type,
- l_implicitCS]() {
+ l_implicitCS, &dbContext]() {
const auto ellipsoids =
thisEllipsoid->identifiers().empty()
? authorityFactory->createEllipsoidFromExisting(
@@ -1770,15 +1776,17 @@ GeodeticCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
if (crsDatum &&
crsDatum->ellipsoid()->_isEquivalentTo(
ellps.get(),
- util::IComparable::Criterion::EQUIVALENT) &&
+ util::IComparable::Criterion::EQUIVALENT,
+ dbContext) &&
crsDatum->primeMeridian()->_isEquivalentTo(
thisDatum->primeMeridian().get(),
- util::IComparable::Criterion::EQUIVALENT) &&
+ util::IComparable::Criterion::EQUIVALENT,
+ dbContext) &&
(!l_implicitCS ||
coordinateSystem()->_isEquivalentTo(
crs->coordinateSystem().get(),
- util::IComparable::Criterion::
- EQUIVALENT))) {
+ util::IComparable::Criterion::EQUIVALENT,
+ dbContext))) {
res.emplace_back(crs, 60);
}
}
@@ -1811,7 +1819,8 @@ GeodeticCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
authorityFactory->databaseContext(),
*id->codeSpace())
->createGeodeticCRS(id->code());
- bool match = _isEquivalentTo(crs.get(), crsCriterion);
+ bool match =
+ _isEquivalentTo(crs.get(), crsCriterion, dbContext);
res.emplace_back(crs, match ? 100 : 25);
return res;
} catch (const std::exception &) {
@@ -1829,7 +1838,7 @@ GeodeticCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
auto crs = util::nn_dynamic_pointer_cast<GeodeticCRS>(obj);
assert(crs);
auto crsNN = NN_NO_CHECK(crs);
- if (_isEquivalentTo(crs.get(), crsCriterion)) {
+ if (_isEquivalentTo(crs.get(), crsCriterion, dbContext)) {
if (crs->nameStr() == thisName) {
res.clear();
res.emplace_back(crsNN, 100);
@@ -1859,8 +1868,8 @@ GeodeticCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
const auto &thisCS(coordinateSystem());
// Sort results
- res.sort([&thisName, &thisDatum, &thisCS](const Pair &a,
- const Pair &b) {
+ res.sort([&thisName, &thisDatum, &thisCS, &dbContext](const Pair &a,
+ const Pair &b) {
// First consider confidence
if (a.second > b.second) {
return true;
@@ -1884,9 +1893,11 @@ GeodeticCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
const auto &bDatum(b.first->datum());
if (thisDatum && aDatum && bDatum) {
const auto thisEquivADatum(thisDatum->_isEquivalentTo(
- aDatum.get(), util::IComparable::Criterion::EQUIVALENT));
+ aDatum.get(), util::IComparable::Criterion::EQUIVALENT,
+ dbContext));
const auto thisEquivBDatum(thisDatum->_isEquivalentTo(
- bDatum.get(), util::IComparable::Criterion::EQUIVALENT));
+ bDatum.get(), util::IComparable::Criterion::EQUIVALENT,
+ dbContext));
if (thisEquivADatum && !thisEquivBDatum) {
return true;
@@ -1900,9 +1911,11 @@ GeodeticCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
const auto &aCS(a.first->coordinateSystem());
const auto &bCS(b.first->coordinateSystem());
const auto thisEquivACs(thisCS->_isEquivalentTo(
- aCS.get(), util::IComparable::Criterion::EQUIVALENT));
+ aCS.get(), util::IComparable::Criterion::EQUIVALENT,
+ dbContext));
const auto thisEquivBCs(thisCS->_isEquivalentTo(
- bCS.get(), util::IComparable::Criterion::EQUIVALENT));
+ bCS.get(), util::IComparable::Criterion::EQUIVALENT,
+ dbContext));
if (thisEquivACs && !thisEquivBCs) {
return true;
}
@@ -2119,14 +2132,14 @@ bool GeographicCRS::is2DPartOf3D(util::nn<const GeographicCRS *> other)
//! @cond Doxygen_Suppress
bool GeographicCRS::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherGeogCRS = dynamic_cast<const GeographicCRS *>(other);
if (otherGeogCRS == nullptr) {
return false;
}
const auto standardCriterion = getStandardCriterion(criterion);
- if (GeodeticCRS::_isEquivalentTo(other, standardCriterion)) {
+ if (GeodeticCRS::_isEquivalentTo(other, standardCriterion, dbContext)) {
return true;
}
if (criterion !=
@@ -2145,7 +2158,7 @@ bool GeographicCRS::_isEquivalentTo(
cs::EllipsoidalCS::AxisOrder::LONG_EAST_LAT_NORTH
? cs::EllipsoidalCS::createLatitudeLongitude(unit)
: cs::EllipsoidalCS::createLongitudeLatitude(unit))
- ->GeodeticCRS::_isEquivalentTo(other, standardCriterion);
+ ->GeodeticCRS::_isEquivalentTo(other, standardCriterion, dbContext);
}
return false;
}
@@ -2717,12 +2730,12 @@ VerticalCRS::create(const util::PropertyMap &properties,
//! @cond Doxygen_Suppress
bool VerticalCRS::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherVertCRS = dynamic_cast<const VerticalCRS *>(other);
// TODO test geoidModel and velocityModel
return otherVertCRS != nullptr &&
- SingleCRS::baseIsEquivalentTo(other, criterion);
+ SingleCRS::baseIsEquivalentTo(other, criterion, dbContext);
}
//! @endcond
@@ -2757,6 +2770,8 @@ VerticalCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
const auto &thisName(nameStr());
if (authorityFactory) {
+ const io::DatabaseContextNNPtr &dbContext =
+ authorityFactory->databaseContext();
const bool unsignificantName = thisName.empty() ||
ci_equal(thisName, "unknown") ||
@@ -2768,12 +2783,11 @@ VerticalCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
if (hasCodeCompatibleOfAuthorityFactory(id, authorityFactory)) {
try {
auto crs = io::AuthorityFactory::create(
- authorityFactory->databaseContext(),
- *id->codeSpace())
+ dbContext, *id->codeSpace())
->createVerticalCRS(id->code());
bool match = _isEquivalentTo(
- crs.get(),
- util::IComparable::Criterion::EQUIVALENT);
+ crs.get(), util::IComparable::Criterion::EQUIVALENT,
+ dbContext);
res.emplace_back(crs, match ? 100 : 25);
return res;
} catch (const std::exception &) {
@@ -2791,8 +2805,8 @@ VerticalCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
assert(crs);
auto crsNN = NN_NO_CHECK(crs);
if (_isEquivalentTo(
- crs.get(),
- util::IComparable::Criterion::EQUIVALENT)) {
+ crs.get(), util::IComparable::Criterion::EQUIVALENT,
+ dbContext)) {
if (crs->nameStr() == thisName) {
res.clear();
res.emplace_back(crsNN, 100);
@@ -2957,19 +2971,20 @@ DerivedCRS::derivingConversionRef() PROJ_PURE_DEFN {
// ---------------------------------------------------------------------------
-bool DerivedCRS::_isEquivalentTo(const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+bool DerivedCRS::_isEquivalentTo(
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherDerivedCRS = dynamic_cast<const DerivedCRS *>(other);
const auto standardCriterion = getStandardCriterion(criterion);
if (otherDerivedCRS == nullptr ||
- !SingleCRS::baseIsEquivalentTo(other, standardCriterion)) {
+ !SingleCRS::baseIsEquivalentTo(other, standardCriterion, dbContext)) {
return false;
}
return d->baseCRS_->_isEquivalentTo(otherDerivedCRS->d->baseCRS_.get(),
- criterion) &&
+ criterion, dbContext) &&
d->derivingConversion_->_isEquivalentTo(
- otherDerivedCRS->d->derivingConversion_.get(),
- standardCriterion);
+ otherDerivedCRS->d->derivingConversion_.get(), standardCriterion,
+ dbContext);
}
// ---------------------------------------------------------------------------
@@ -3402,11 +3417,11 @@ ProjectedCRS::create(const util::PropertyMap &properties,
// ---------------------------------------------------------------------------
bool ProjectedCRS::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherProjCRS = dynamic_cast<const ProjectedCRS *>(other);
return otherProjCRS != nullptr &&
- DerivedCRS::_isEquivalentTo(other, criterion);
+ DerivedCRS::_isEquivalentTo(other, criterion, dbContext);
}
// ---------------------------------------------------------------------------
@@ -3580,14 +3595,19 @@ ProjectedCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
const auto &conv = derivingConversionRef();
const auto &cs = coordinateSystem();
+ io::DatabaseContextPtr dbContext =
+ authorityFactory ? authorityFactory->databaseContext().as_nullable()
+ : nullptr;
+
if (baseRes.size() == 1 && baseRes.front().second >= 70 &&
conv->isUTM(zone, north) &&
cs->_isEquivalentTo(
cs::CartesianCS::createEastingNorthing(common::UnitOfMeasure::METRE)
- .get())) {
+ .get(),
+ util::IComparable::Criterion::EQUIVALENT, dbContext)) {
if (baseRes.front().first->_isEquivalentTo(
GeographicCRS::EPSG_4326.get(),
- util::IComparable::Criterion::EQUIVALENT)) {
+ util::IComparable::Criterion::EQUIVALENT, dbContext)) {
std::string crsName(
computeUTMCRSName("WGS 84 / UTM zone ", zone, north));
res.emplace_back(
@@ -3601,7 +3621,7 @@ ProjectedCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
north &&
baseRes.front().first->_isEquivalentTo(
GeographicCRS::EPSG_4267.get(),
- util::IComparable::Criterion::EQUIVALENT)) {
+ util::IComparable::Criterion::EQUIVALENT, dbContext)) {
std::string crsName(
computeUTMCRSName("NAD27 / UTM zone ", zone, north));
res.emplace_back(
@@ -3616,7 +3636,7 @@ ProjectedCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
north &&
baseRes.front().first->_isEquivalentTo(
GeographicCRS::EPSG_4269.get(),
- util::IComparable::Criterion::EQUIVALENT)) {
+ util::IComparable::Criterion::EQUIVALENT, dbContext)) {
std::string crsName(
computeUTMCRSName("NAD83 / UTM zone ", zone, north));
res.emplace_back(
@@ -3648,9 +3668,9 @@ ProjectedCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
*id->codeSpace())
->createProjectedCRS(id->code());
bool match = _isEquivalentTo(
- crs.get(),
- util::IComparable::Criterion::
- EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS);
+ crs.get(), util::IComparable::Criterion::
+ EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS,
+ dbContext);
res.emplace_back(crs, match ? 100 : 25);
return res;
} catch (const std::exception &) {
@@ -3671,9 +3691,9 @@ ProjectedCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
thisName.c_str(), crs->nameStr().c_str());
foundEquivalentName |= eqName;
if (_isEquivalentTo(
- crs.get(),
- util::IComparable::Criterion::
- EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS)) {
+ crs.get(), util::IComparable::Criterion::
+ EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS,
+ dbContext)) {
if (crs->nameStr() == thisName) {
res.clear();
res.emplace_back(crsNN, 100);
@@ -3685,10 +3705,12 @@ ProjectedCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
l_baseCRS->_isEquivalentTo(
crs->baseCRS().get(),
util::IComparable::Criterion::
- EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS) &&
+ EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS,
+ dbContext) &&
derivingConversionRef()->_isEquivalentTo(
crs->derivingConversionRef().get(),
- util::IComparable::Criterion::EQUIVALENT) &&
+ util::IComparable::Criterion::EQUIVALENT,
+ dbContext) &&
objects.size() == 1) {
res.clear();
res.emplace_back(crsNN, 100);
@@ -3755,17 +3777,21 @@ ProjectedCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
if (_isEquivalentTo(crs.get(),
util::IComparable::Criterion::
- EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS)) {
+ EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS,
+ dbContext)) {
res.emplace_back(crs, unsignificantName ? 90 : 70);
} else if (ellipsoid->_isEquivalentTo(
crs->baseCRS()->ellipsoid().get(),
- util::IComparable::Criterion::EQUIVALENT) &&
+ util::IComparable::Criterion::EQUIVALENT,
+ dbContext) &&
derivingConversionRef()->_isEquivalentTo(
crs->derivingConversionRef().get(),
- util::IComparable::Criterion::EQUIVALENT)) {
+ util::IComparable::Criterion::EQUIVALENT,
+ dbContext)) {
if (coordinateSystem()->_isEquivalentTo(
crs->coordinateSystem().get(),
- util::IComparable::Criterion::EQUIVALENT)) {
+ util::IComparable::Criterion::EQUIVALENT,
+ dbContext)) {
res.emplace_back(crs, 70);
} else {
res.emplace_back(crs, 50);
@@ -3995,12 +4021,12 @@ void CompoundCRS::_exportToPROJString(
// ---------------------------------------------------------------------------
bool CompoundCRS::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherCompoundCRS = dynamic_cast<const CompoundCRS *>(other);
if (otherCompoundCRS == nullptr ||
(criterion == util::IComparable::Criterion::STRICT &&
- !ObjectUsage::_isEquivalentTo(other, criterion))) {
+ !ObjectUsage::_isEquivalentTo(other, criterion, dbContext))) {
return false;
}
const auto &components = componentReferenceSystems();
@@ -4009,8 +4035,8 @@ bool CompoundCRS::_isEquivalentTo(
return false;
}
for (size_t i = 0; i < components.size(); i++) {
- if (!components[i]->_isEquivalentTo(otherComponents[i].get(),
- criterion)) {
+ if (!components[i]->_isEquivalentTo(otherComponents[i].get(), criterion,
+ dbContext)) {
return false;
}
}
@@ -4050,6 +4076,8 @@ CompoundCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
const auto &thisName(nameStr());
if (authorityFactory) {
+ const io::DatabaseContextNNPtr &dbContext =
+ authorityFactory->databaseContext();
const bool unsignificantName = thisName.empty() ||
ci_equal(thisName, "unknown") ||
@@ -4063,12 +4091,11 @@ CompoundCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
if (hasCodeCompatibleOfAuthorityFactory(id, authorityFactory)) {
try {
auto crs = io::AuthorityFactory::create(
- authorityFactory->databaseContext(),
- *id->codeSpace())
+ dbContext, *id->codeSpace())
->createCompoundCRS(id->code());
bool match = _isEquivalentTo(
- crs.get(),
- util::IComparable::Criterion::EQUIVALENT);
+ crs.get(), util::IComparable::Criterion::EQUIVALENT,
+ dbContext);
res.emplace_back(crs, match ? 100 : 25);
return res;
} catch (const std::exception &) {
@@ -4089,8 +4116,8 @@ CompoundCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
thisName.c_str(), crs->nameStr().c_str());
foundEquivalentName |= eqName;
if (_isEquivalentTo(
- crs.get(),
- util::IComparable::Criterion::EQUIVALENT)) {
+ crs.get(), util::IComparable::Criterion::EQUIVALENT,
+ dbContext)) {
if (crs->nameStr() == thisName) {
res.clear();
res.emplace_back(crsNN, 100);
@@ -4157,7 +4184,8 @@ CompoundCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const {
}
if (_isEquivalentTo(crs.get(),
- util::IComparable::Criterion::EQUIVALENT)) {
+ util::IComparable::Criterion::EQUIVALENT,
+ dbContext)) {
res.emplace_back(crs, unsignificantName ? 90 : 70);
} else {
res.emplace_back(crs, 25);
@@ -4529,20 +4557,22 @@ void BoundCRS::_exportToPROJString(
// ---------------------------------------------------------------------------
bool BoundCRS::_isEquivalentTo(const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherBoundCRS = dynamic_cast<const BoundCRS *>(other);
if (otherBoundCRS == nullptr ||
(criterion == util::IComparable::Criterion::STRICT &&
- !ObjectUsage::_isEquivalentTo(other, criterion))) {
+ !ObjectUsage::_isEquivalentTo(other, criterion, dbContext))) {
return false;
}
const auto standardCriterion = getStandardCriterion(criterion);
return d->baseCRS_->_isEquivalentTo(otherBoundCRS->d->baseCRS_.get(),
- criterion) &&
+ criterion, dbContext) &&
d->hubCRS_->_isEquivalentTo(otherBoundCRS->d->hubCRS_.get(),
- criterion) &&
+ criterion, dbContext) &&
d->transformation_->_isEquivalentTo(
- otherBoundCRS->d->transformation_.get(), standardCriterion);
+ otherBoundCRS->d->transformation_.get(), standardCriterion,
+ dbContext);
}
// ---------------------------------------------------------------------------
@@ -4553,10 +4583,14 @@ std::list<std::pair<CRSNNPtr, int>>
BoundCRS::_identify(const io::AuthorityFactoryPtr &authorityFactory) const {
typedef std::pair<CRSNNPtr, int> Pair;
std::list<Pair> res;
+ if (!authorityFactory)
+ return res;
std::list<Pair> resMatchOfTransfToWGS84;
- if (authorityFactory &&
- d->hubCRS_->_isEquivalentTo(GeographicCRS::EPSG_4326.get(),
- util::IComparable::Criterion::EQUIVALENT)) {
+ const io::DatabaseContextNNPtr &dbContext =
+ authorityFactory->databaseContext();
+ if (d->hubCRS_->_isEquivalentTo(GeographicCRS::EPSG_4326.get(),
+ util::IComparable::Criterion::EQUIVALENT,
+ dbContext)) {
auto resTemp = d->baseCRS_->identify(authorityFactory);
std::string refTransfPROJString;
@@ -4627,7 +4661,8 @@ BoundCRS::_identify(const io::AuthorityFactoryPtr &authorityFactory) const {
refTransfPROJString == opTransfPROJString) ||
opNormalized->_isEquivalentTo(
refTransf.get(),
- util::IComparable::Criterion::EQUIVALENT)) {
+ util::IComparable::Criterion::EQUIVALENT,
+ dbContext)) {
resMatchOfTransfToWGS84.emplace_back(
create(candidateBaseCRS, d->hubCRS_,
NN_NO_CHECK(util::nn_dynamic_pointer_cast<
@@ -4807,11 +4842,11 @@ void DerivedGeodeticCRS::_exportToPROJString(
// ---------------------------------------------------------------------------
bool DerivedGeodeticCRS::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherDerivedCRS = dynamic_cast<const DerivedGeodeticCRS *>(other);
return otherDerivedCRS != nullptr &&
- DerivedCRS::_isEquivalentTo(other, criterion);
+ DerivedCRS::_isEquivalentTo(other, criterion, dbContext);
}
// ---------------------------------------------------------------------------
@@ -4957,11 +4992,11 @@ void DerivedGeographicCRS::_exportToPROJString(
// ---------------------------------------------------------------------------
bool DerivedGeographicCRS::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherDerivedCRS = dynamic_cast<const DerivedGeographicCRS *>(other);
return otherDerivedCRS != nullptr &&
- DerivedCRS::_isEquivalentTo(other, criterion);
+ DerivedCRS::_isEquivalentTo(other, criterion, dbContext);
}
// ---------------------------------------------------------------------------
@@ -5104,11 +5139,11 @@ void DerivedProjectedCRS::_exportToWKT(io::WKTFormatter *formatter) const {
// ---------------------------------------------------------------------------
bool DerivedProjectedCRS::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherDerivedCRS = dynamic_cast<const DerivedProjectedCRS *>(other);
return otherDerivedCRS != nullptr &&
- DerivedCRS::_isEquivalentTo(other, criterion);
+ DerivedCRS::_isEquivalentTo(other, criterion, dbContext);
}
// ---------------------------------------------------------------------------
@@ -5234,11 +5269,11 @@ void TemporalCRS::_exportToJSON(
// ---------------------------------------------------------------------------
bool TemporalCRS::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherTemporalCRS = dynamic_cast<const TemporalCRS *>(other);
return otherTemporalCRS != nullptr &&
- SingleCRS::baseIsEquivalentTo(other, criterion);
+ SingleCRS::baseIsEquivalentTo(other, criterion, dbContext);
}
// ---------------------------------------------------------------------------
@@ -5372,11 +5407,11 @@ void EngineeringCRS::_exportToJSON(
// ---------------------------------------------------------------------------
bool EngineeringCRS::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherEngineeringCRS = dynamic_cast<const EngineeringCRS *>(other);
return otherEngineeringCRS != nullptr &&
- SingleCRS::baseIsEquivalentTo(other, criterion);
+ SingleCRS::baseIsEquivalentTo(other, criterion, dbContext);
}
// ---------------------------------------------------------------------------
@@ -5504,11 +5539,11 @@ void ParametricCRS::_exportToJSON(
// ---------------------------------------------------------------------------
bool ParametricCRS::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherParametricCRS = dynamic_cast<const ParametricCRS *>(other);
return otherParametricCRS != nullptr &&
- SingleCRS::baseIsEquivalentTo(other, criterion);
+ SingleCRS::baseIsEquivalentTo(other, criterion, dbContext);
}
// ---------------------------------------------------------------------------
@@ -5609,11 +5644,11 @@ void DerivedVerticalCRS::_exportToPROJString(
// ---------------------------------------------------------------------------
bool DerivedVerticalCRS::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherDerivedCRS = dynamic_cast<const DerivedVerticalCRS *>(other);
return otherDerivedCRS != nullptr &&
- DerivedCRS::_isEquivalentTo(other, criterion);
+ DerivedCRS::_isEquivalentTo(other, criterion, dbContext);
}
// ---------------------------------------------------------------------------
@@ -5730,11 +5765,11 @@ void DerivedCRSTemplate<DerivedCRSTraits>::_exportToWKT(
template <class DerivedCRSTraits>
bool DerivedCRSTemplate<DerivedCRSTraits>::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherDerivedCRS = dynamic_cast<const DerivedCRSTemplate *>(other);
return otherDerivedCRS != nullptr &&
- DerivedCRS::_isEquivalentTo(other, criterion);
+ DerivedCRS::_isEquivalentTo(other, criterion, dbContext);
}
//! @endcond
diff --git a/src/iso19111/datum.cpp b/src/iso19111/datum.cpp
index 321fe93f..255f9822 100644
--- a/src/iso19111/datum.cpp
+++ b/src/iso19111/datum.cpp
@@ -213,11 +213,13 @@ void Datum::setProperties(
// ---------------------------------------------------------------------------
-bool Datum::__isEquivalentTo(const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+//! @cond Doxygen_Suppress
+bool Datum::_isEquivalentTo(const util::IComparable *other,
+ util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherDatum = dynamic_cast<const Datum *>(other);
if (otherDatum == nullptr ||
- !ObjectUsage::_isEquivalentTo(other, criterion)) {
+ !ObjectUsage::_isEquivalentTo(other, criterion, dbContext)) {
return false;
}
if (criterion == util::IComparable::Criterion::STRICT) {
@@ -248,12 +250,13 @@ bool Datum::__isEquivalentTo(const util::IComparable *other,
}
if (conventionalRS() && otherDatum->conventionalRS() &&
conventionalRS()->_isEquivalentTo(
- otherDatum->conventionalRS().get(), criterion)) {
+ otherDatum->conventionalRS().get(), criterion, dbContext)) {
return false;
}
}
return true;
}
+//! @endcond
// ---------------------------------------------------------------------------
@@ -450,11 +453,11 @@ void PrimeMeridian::_exportToPROJString(
//! @cond Doxygen_Suppress
bool PrimeMeridian::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherPM = dynamic_cast<const PrimeMeridian *>(other);
if (otherPM == nullptr ||
- !IdentifiedObject::_isEquivalentTo(other, criterion)) {
+ !IdentifiedObject::_isEquivalentTo(other, criterion, dbContext)) {
return false;
}
// In MapInfo, the Paris prime meridian is returned as 2.3372291666667
@@ -984,11 +987,12 @@ EllipsoidNNPtr Ellipsoid::identify() const {
//! @cond Doxygen_Suppress
bool Ellipsoid::_isEquivalentTo(const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherEllipsoid = dynamic_cast<const Ellipsoid *>(other);
if (otherEllipsoid == nullptr ||
(criterion == util::IComparable::Criterion::STRICT &&
- !IdentifiedObject::_isEquivalentTo(other, criterion))) {
+ !IdentifiedObject::_isEquivalentTo(other, criterion, dbContext))) {
return false;
}
@@ -1324,20 +1328,63 @@ void GeodeticReferenceFrame::_exportToJSON(
//! @cond Doxygen_Suppress
bool GeodeticReferenceFrame::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherGRF = dynamic_cast<const GeodeticReferenceFrame *>(other);
- if (otherGRF == nullptr || !Datum::_isEquivalentTo(other, criterion)) {
+ if (otherGRF == nullptr ||
+ !Datum::_isEquivalentTo(other, criterion, dbContext)) {
return false;
}
return primeMeridian()->_isEquivalentTo(otherGRF->primeMeridian().get(),
- criterion) &&
- ellipsoid()->_isEquivalentTo(otherGRF->ellipsoid().get(), criterion);
+ criterion, dbContext) &&
+ ellipsoid()->_isEquivalentTo(otherGRF->ellipsoid().get(), criterion,
+ dbContext);
}
//! @endcond
// ---------------------------------------------------------------------------
+bool GeodeticReferenceFrame::hasEquivalentNameToUsingAlias(
+ const IdentifiedObject *other,
+ const io::DatabaseContextPtr &dbContext) const {
+ if (dbContext) {
+ if (!identifiers().empty()) {
+ const auto &id = identifiers().front();
+ auto aliases =
+ dbContext->getAliases(*(id->codeSpace()), id->code(), nameStr(),
+ "geodetic_datum", std::string());
+ const char *otherName = other->nameStr().c_str();
+ for (const auto &alias : aliases) {
+ if (metadata::Identifier::isEquivalentName(otherName,
+ alias.c_str())) {
+ return true;
+ }
+ }
+ return false;
+ } else if (!other->identifiers().empty()) {
+ auto otherGRF = dynamic_cast<const GeodeticReferenceFrame *>(other);
+ if (otherGRF) {
+ return otherGRF->hasEquivalentNameToUsingAlias(this, dbContext);
+ }
+ return false;
+ }
+
+ auto aliases =
+ dbContext->getAliases(std::string(), std::string(), nameStr(),
+ "geodetic_datum", std::string());
+ const char *otherName = other->nameStr().c_str();
+ for (const auto &alias : aliases) {
+ if (metadata::Identifier::isEquivalentName(otherName,
+ alias.c_str())) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// ---------------------------------------------------------------------------
+
//! @cond Doxygen_Suppress
struct DynamicGeodeticReferenceFrame::Private {
common::Measure frameReferenceEpoch{};
@@ -1407,11 +1454,11 @@ DynamicGeodeticReferenceFrame::deformationModelName() const {
//! @cond Doxygen_Suppress
bool DynamicGeodeticReferenceFrame::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherDGRF = dynamic_cast<const DynamicGeodeticReferenceFrame *>(other);
if (otherDGRF == nullptr ||
- !GeodeticReferenceFrame::_isEquivalentTo(other, criterion)) {
+ !GeodeticReferenceFrame::_isEquivalentTo(other, criterion, dbContext)) {
return false;
}
return frameReferenceEpoch()._isEquivalentTo(
@@ -1842,10 +1889,11 @@ void VerticalReferenceFrame::_exportToJSON(
//! @cond Doxygen_Suppress
bool VerticalReferenceFrame::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherVRF = dynamic_cast<const VerticalReferenceFrame *>(other);
- if (otherVRF == nullptr || !Datum::_isEquivalentTo(other, criterion)) {
+ if (otherVRF == nullptr ||
+ !Datum::_isEquivalentTo(other, criterion, dbContext)) {
return false;
}
if ((realizationMethod().has_value() ^
@@ -1932,11 +1980,11 @@ DynamicVerticalReferenceFrame::deformationModelName() const {
//! @cond Doxygen_Suppress
bool DynamicVerticalReferenceFrame::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherDGRF = dynamic_cast<const DynamicVerticalReferenceFrame *>(other);
if (otherDGRF == nullptr ||
- !VerticalReferenceFrame::_isEquivalentTo(other, criterion)) {
+ !VerticalReferenceFrame::_isEquivalentTo(other, criterion, dbContext)) {
return false;
}
return frameReferenceEpoch()._isEquivalentTo(
@@ -2131,10 +2179,11 @@ void TemporalDatum::_exportToJSON(
//! @cond Doxygen_Suppress
bool TemporalDatum::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherTD = dynamic_cast<const TemporalDatum *>(other);
- if (otherTD == nullptr || !Datum::_isEquivalentTo(other, criterion)) {
+ if (otherTD == nullptr ||
+ !Datum::_isEquivalentTo(other, criterion, dbContext)) {
return false;
}
return temporalOrigin().toString() ==
@@ -2223,10 +2272,11 @@ void EngineeringDatum::_exportToJSON(
//! @cond Doxygen_Suppress
bool EngineeringDatum::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherTD = dynamic_cast<const EngineeringDatum *>(other);
- if (otherTD == nullptr || !Datum::_isEquivalentTo(other, criterion)) {
+ if (otherTD == nullptr ||
+ !Datum::_isEquivalentTo(other, criterion, dbContext)) {
return false;
}
return true;
@@ -2308,10 +2358,11 @@ void ParametricDatum::_exportToJSON(
//! @cond Doxygen_Suppress
bool ParametricDatum::_isEquivalentTo(
- const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherTD = dynamic_cast<const ParametricDatum *>(other);
- if (otherTD == nullptr || !Datum::_isEquivalentTo(other, criterion)) {
+ if (otherTD == nullptr ||
+ !Datum::_isEquivalentTo(other, criterion, dbContext)) {
return false;
}
return true;
diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp
index f0ad157e..0bd44308 100644
--- a/src/iso19111/factory.cpp
+++ b/src/iso19111/factory.cpp
@@ -262,6 +262,9 @@ struct DatabaseContext::Private {
std::map<std::string, std::vector<std::string>> cacheAllowedAuthorities_{};
+ lru11::Cache<std::string, std::list<std::string>> cacheAliasNames_{
+ CACHE_SIZE};
+
static void insertIntoCache(LRUCacheOfObjects &cache,
const std::string &code,
const util::BaseObjectPtr &obj);
@@ -1100,7 +1103,7 @@ bool DatabaseContext::isKnownName(const std::string &name,
/** \brief Gets the alias name from an official name.
*
- * @param officialName Official name.
+ * @param officialName Official name. Mandatory
* @param tableName Table name/category. Mandatory
* @param source Source of the alias. Mandatory
* @return Alias name (or empty if not found).
@@ -1132,6 +1135,63 @@ DatabaseContext::getAliasFromOfficialName(const std::string &officialName,
// ---------------------------------------------------------------------------
+/** \brief Gets the alias names for an object.
+ *
+ * Either authName + code or officialName must be non empty.
+ *
+ * @param authName Authority.
+ * @param code Code.
+ * @param officialName Official name.
+ * @param tableName Table name/category. Mandatory
+ * @param source Source of the alias. May be empty.
+ * @return Aliases
+ */
+std::list<std::string> DatabaseContext::getAliases(
+ const std::string &authName, const std::string &code,
+ const std::string &officialName, const std::string &tableName,
+ const std::string &source) const {
+
+ std::list<std::string> res;
+ const auto key(authName + code + officialName + tableName + source);
+ if (d->cacheAliasNames_.tryGet(key, res)) {
+ return res;
+ }
+
+ std::string resolvedAuthName(authName);
+ std::string resolvedCode(code);
+ if (authName.empty() || code.empty()) {
+ std::string sql("SELECT auth_name, code FROM \"");
+ sql += replaceAll(tableName, "\"", "\"\"");
+ sql += "\" WHERE name = ?";
+ if (tableName == "geodetic_crs") {
+ sql += " AND type = " GEOG_2D_SINGLE_QUOTED;
+ }
+ auto resSql = d->run(sql, {officialName});
+ if (resSql.empty()) {
+ d->cacheAliasNames_.insert(key, res);
+ return res;
+ }
+ const auto &row = resSql.front();
+ resolvedAuthName = row[0];
+ resolvedCode = row[1];
+ }
+ std::string sql("SELECT alt_name FROM alias_name WHERE table_name = ? AND "
+ "auth_name = ? AND code = ?");
+ ListOfParams params{tableName, resolvedAuthName, resolvedCode};
+ if (!source.empty()) {
+ sql += " AND source = ?";
+ params.emplace_back(source);
+ }
+ auto resSql = d->run(sql, params);
+ for (const auto &row : resSql) {
+ res.emplace_back(row[0]);
+ }
+ d->cacheAliasNames_.insert(key, res);
+ return res;
+}
+
+// ---------------------------------------------------------------------------
+
/** \brief Return the 'text_definition' column of a table for an object
*
* @param tableName Table name/category.
diff --git a/src/iso19111/metadata.cpp b/src/iso19111/metadata.cpp
index 41653b32..6266a86d 100644
--- a/src/iso19111/metadata.cpp
+++ b/src/iso19111/metadata.cpp
@@ -237,7 +237,8 @@ GeographicBoundingBoxNNPtr GeographicBoundingBox::create(double west,
//! @cond Doxygen_Suppress
bool GeographicBoundingBox::_isEquivalentTo(
- const util::IComparable *other, util::IComparable::Criterion) const {
+ const util::IComparable *other, util::IComparable::Criterion,
+ const io::DatabaseContextPtr &) const {
auto otherExtent = dynamic_cast<const GeographicBoundingBox *>(other);
if (!otherExtent)
return false;
@@ -502,7 +503,8 @@ VerticalExtent::create(double minimumIn, double maximumIn,
//! @cond Doxygen_Suppress
bool VerticalExtent::_isEquivalentTo(const util::IComparable *other,
- util::IComparable::Criterion) const {
+ util::IComparable::Criterion,
+ const io::DatabaseContextPtr &) const {
auto otherExtent = dynamic_cast<const VerticalExtent *>(other);
if (!otherExtent)
return false;
@@ -587,7 +589,8 @@ TemporalExtentNNPtr TemporalExtent::create(const std::string &start,
//! @cond Doxygen_Suppress
bool TemporalExtent::_isEquivalentTo(const util::IComparable *other,
- util::IComparable::Criterion) const {
+ util::IComparable::Criterion,
+ const io::DatabaseContextPtr &) const {
auto otherExtent = dynamic_cast<const TemporalExtent *>(other);
if (!otherExtent)
return false;
@@ -734,7 +737,8 @@ Extent::createFromBBOX(double west, double south, double east, double north,
//! @cond Doxygen_Suppress
bool Extent::_isEquivalentTo(const util::IComparable *other,
- util::IComparable::Criterion criterion) const {
+ util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
auto otherExtent = dynamic_cast<const Extent *>(other);
bool ret =
(otherExtent &&
@@ -749,15 +753,18 @@ bool Extent::_isEquivalentTo(const util::IComparable *other,
if (ret) {
for (size_t i = 0; ret && i < d->geographicElements_.size(); ++i) {
ret = d->geographicElements_[i]->_isEquivalentTo(
- otherExtent->d->geographicElements_[i].get(), criterion);
+ otherExtent->d->geographicElements_[i].get(), criterion,
+ dbContext);
}
for (size_t i = 0; ret && i < d->verticalElements_.size(); ++i) {
ret = d->verticalElements_[i]->_isEquivalentTo(
- otherExtent->d->verticalElements_[i].get(), criterion);
+ otherExtent->d->verticalElements_[i].get(), criterion,
+ dbContext);
}
for (size_t i = 0; ret && i < d->temporalElements_.size(); ++i) {
ret = d->temporalElements_[i]->_isEquivalentTo(
- otherExtent->d->temporalElements_[i].get(), criterion);
+ otherExtent->d->temporalElements_[i].get(), criterion,
+ dbContext);
}
}
return ret;
diff --git a/src/iso19111/util.cpp b/src/iso19111/util.cpp
index 25207d5c..2a6178e2 100644
--- a/src/iso19111/util.cpp
+++ b/src/iso19111/util.cpp
@@ -687,11 +687,13 @@ IComparable::~IComparable() = default;
/** \brief Returns whether an object is equivalent to another one.
* @param other other object to compare to
* @param criterion comparaison criterion.
+ * @param dbContext Database context, or nullptr.
* @return true if objects are equivalent.
*/
-bool IComparable::isEquivalentTo(const IComparable *other,
- Criterion criterion) const {
- return _isEquivalentTo(other, criterion);
+bool IComparable::isEquivalentTo(
+ const IComparable *other, Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
+ return _isEquivalentTo(other, criterion, dbContext);
}
// ---------------------------------------------------------------------------
diff --git a/src/proj.h b/src/proj.h
index b8b90277..f31c778b 100644
--- a/src/proj.h
+++ b/src/proj.h
@@ -836,6 +836,10 @@ PJ_OBJ_LIST PROJ_DLL *proj_get_non_deprecated(PJ_CONTEXT *ctx,
int PROJ_DLL proj_is_equivalent_to(const PJ *obj, const PJ *other,
PJ_COMPARISON_CRITERION criterion);
+int PROJ_DLL proj_is_equivalent_to_with_ctx(PJ_CONTEXT *ctx,
+ const PJ *obj, const PJ *other,
+ PJ_COMPARISON_CRITERION criterion);
+
int PROJ_DLL proj_is_crs(const PJ *obj);
const char PROJ_DLL* proj_get_name(const PJ *obj);