diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2020-10-20 21:14:30 +0200 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2020-10-20 21:14:30 +0200 |
| commit | 45c819b69fb401c21c5571ddc2a602a8e72385d6 (patch) | |
| tree | f2435121958cff58ee2191750c6e9ff2bdc77813 /src | |
| parent | 6b8ef545c4200180cc1b4bf7179d0b0951029ae5 (diff) | |
| download | PROJ-45c819b69fb401c21c5571ddc2a602a8e72385d6.tar.gz PROJ-45c819b69fb401c21c5571ddc2a602a8e72385d6.zip | |
Improve identification of compound CRS from ESRI WKT1, and for compound CRS whose result is not in the DB but whose horiz and vertical parts are known
Diffstat (limited to 'src')
| -rw-r--r-- | src/apps/projinfo.cpp | 58 | ||||
| -rw-r--r-- | src/iso19111/crs.cpp | 62 |
2 files changed, 91 insertions, 29 deletions
diff --git a/src/apps/projinfo.cpp b/src/apps/projinfo.cpp index e8c97576..37b76346 100644 --- a/src/apps/projinfo.cpp +++ b/src/apps/projinfo.cpp @@ -1198,26 +1198,48 @@ int main(int argc, char **argv) { std::cout << *ids[0]->codeSpace() << ":" << ids[0]->code() << ": " << pair.second << " %" << std::endl; - } else { - auto boundCRS = dynamic_cast<BoundCRS *>( - identifiedCRS.get()); - if (boundCRS && - !boundCRS->baseCRS() - ->identifiers() - .empty()) { - const auto &idsBase = - boundCRS->baseCRS()->identifiers(); - std::cout << "BoundCRS of " - << *idsBase[0]->codeSpace() << ":" - << idsBase[0]->code() << ": " - << pair.second << " %" - << std::endl; - } else { - std::cout - << "un-identifier CRS: " << pair.second - << " %" << std::endl; + continue; + } + + auto boundCRS = + dynamic_cast<BoundCRS *>(identifiedCRS.get()); + if (boundCRS && + !boundCRS->baseCRS()->identifiers().empty()) { + const auto &idsBase = + boundCRS->baseCRS()->identifiers(); + std::cout << "BoundCRS of " + << *idsBase[0]->codeSpace() << ":" + << idsBase[0]->code() << ": " + << pair.second << " %" << std::endl; + continue; + } + + auto compoundCRS = dynamic_cast<CompoundCRS *>( + identifiedCRS.get()); + if (compoundCRS) { + const auto &components = + compoundCRS->componentReferenceSystems(); + if (components.size() == 2 && + !components[0]->identifiers().empty() && + !components[1]->identifiers().empty()) { + const auto &idH = + components[0]->identifiers().front(); + const auto &idV = + components[1]->identifiers().front(); + if (*idH->codeSpace() == + *idV->codeSpace()) { + std::cout << *idH->codeSpace() << ":" + << idH->code() << '+' + << idV->code() << ": " + << pair.second << " %" + << std::endl; + continue; + } } } + + std::cout << "un-identified CRS: " << pair.second + << " %" << std::endl; } } catch (const std::exception &e) { std::cerr << "Identification failed: " << e.what() diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp index 051f9463..dbe3b211 100644 --- a/src/iso19111/crs.cpp +++ b/src/iso19111/crs.cpp @@ -132,6 +132,16 @@ CRS::~CRS() = default; // --------------------------------------------------------------------------- +//! @cond Doxygen_Suppress + +/** \brief Return whether the CRS has an implicit coordinate system + * (e.g from ESRI WKT) */ +bool CRS::hasImplicitCS() const { return d->implicitCS_; } + +//! @endcond + +// --------------------------------------------------------------------------- + /** \brief Return the BoundCRS potentially attached to this CRS. * * In the case this method is called on a object returned by @@ -1971,7 +1981,7 @@ GeodeticCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const { io::DatabaseContextPtr dbContext = authorityFactory ? authorityFactory->databaseContext().as_nullable() : nullptr; - const bool l_implicitCS = CRS::getPrivate()->implicitCS_; + const bool l_implicitCS = hasImplicitCS(); const auto crsCriterion = l_implicitCS ? util::IComparable::Criterion::EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS @@ -4020,7 +4030,7 @@ ProjectedCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const { } } - const bool l_implicitCS = CRS::getPrivate()->implicitCS_; + const bool l_implicitCS = hasImplicitCS(); const auto addCRS = [&](const ProjectedCRSNNPtr &crs, const bool eqName) { const auto &l_unit = cs->axisList()[0]->unit(); if (_isEquivalentTo(crs.get(), util::IComparable::Criterion:: @@ -4617,6 +4627,13 @@ CompoundCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const { const auto &thisName(nameStr()); + const auto &components = componentReferenceSystems(); + const bool l_implicitCS = components[0]->hasImplicitCS(); + const auto crsCriterion = + l_implicitCS + ? util::IComparable::Criterion::EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS + : util::IComparable::Criterion::EQUIVALENT; + if (authorityFactory) { const io::DatabaseContextNNPtr &dbContext = authorityFactory->databaseContext(); @@ -4635,9 +4652,8 @@ CompoundCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const { auto crs = io::AuthorityFactory::create( dbContext, *id->codeSpace()) ->createCompoundCRS(id->code()); - bool match = _isEquivalentTo( - crs.get(), util::IComparable::Criterion::EQUIVALENT, - dbContext); + bool match = + _isEquivalentTo(crs.get(), crsCriterion, dbContext); res.emplace_back(crs, match ? 100 : 25); return res; } catch (const std::exception &) { @@ -4657,9 +4673,7 @@ CompoundCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const { const bool eqName = metadata::Identifier::isEquivalentName( thisName.c_str(), crs->nameStr().c_str()); foundEquivalentName |= eqName; - if (_isEquivalentTo( - crs.get(), util::IComparable::Criterion::EQUIVALENT, - dbContext)) { + if (_isEquivalentTo(crs.get(), crsCriterion, dbContext)) { if (crs->nameStr() == thisName) { res.clear(); res.emplace_back(crsNN, 100); @@ -4667,6 +4681,7 @@ CompoundCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const { } res.emplace_back(crsNN, eqName ? 90 : 70); } else { + res.emplace_back(crsNN, 25); } } @@ -4725,9 +4740,7 @@ CompoundCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const { continue; } - if (_isEquivalentTo(crs.get(), - util::IComparable::Criterion::EQUIVALENT, - dbContext)) { + if (_isEquivalentTo(crs.get(), crsCriterion, dbContext)) { res.emplace_back(crs, unsignificantName ? 90 : 70); } else { res.emplace_back(crs, 25); @@ -4737,6 +4750,33 @@ CompoundCRS::identify(const io::AuthorityFactoryPtr &authorityFactory) const { res.sort(lambdaSort); } + // If we didn't find a match for the CompoundCRS, check if the + // horizontal and vertical parts are not themselves well known. + if (identifiers().empty() && res.empty() && components.size() == 2) { + auto candidatesHorizCRS = components[0]->identify(authorityFactory); + auto candidatesVertCRS = components[1]->identify(authorityFactory); + if (candidatesHorizCRS.size() == 1 && + candidatesVertCRS.size() == 1 && + candidatesHorizCRS.front().second >= 70 && + candidatesVertCRS.front().second >= 70) { + auto newCRS = CompoundCRS::create( + util::PropertyMap().set( + common::IdentifiedObject::NAME_KEY, + candidatesHorizCRS.front().first->nameStr() + " + " + + candidatesVertCRS.front().first->nameStr()), + {candidatesHorizCRS.front().first, + candidatesVertCRS.front().first}); + const bool eqName = metadata::Identifier::isEquivalentName( + thisName.c_str(), newCRS->nameStr().c_str()); + res.emplace_back( + newCRS, + std::min(thisName == newCRS->nameStr() ? 100 : eqName ? 90 + : 70, + std::min(candidatesHorizCRS.front().second, + candidatesVertCRS.front().second))); + } + } + // Keep only results of the highest confidence if (res.size() >= 2) { const auto highestConfidence = res.front().second; |
