diff options
Diffstat (limited to 'src/iso19111/crs.cpp')
| -rw-r--r-- | src/iso19111/crs.cpp | 122 |
1 files changed, 109 insertions, 13 deletions
diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp index 52b10119..edc8a71f 100644 --- a/src/iso19111/crs.cpp +++ b/src/iso19111/crs.cpp @@ -1578,6 +1578,49 @@ GeodeticCRS::create(const util::PropertyMap &properties, // --------------------------------------------------------------------------- //! @cond Doxygen_Suppress + +// Try to format a Geographic/ProjectedCRS 3D CRS as a +// GEOGCS[]/PROJCS[],VERTCS[...,DATUM[],...] if we find corresponding objects +static bool exportAsESRIWktCompoundCRSWithEllipsoidalHeight( + const CRS *self, const GeodeticCRS *geodCRS, io::WKTFormatter *formatter) { + const auto &dbContext = formatter->databaseContext(); + if (!dbContext) { + return false; + } + const auto l_datum = geodCRS->datumNonNull(formatter->databaseContext()); + auto l_alias = dbContext->getAliasFromOfficialName( + l_datum->nameStr(), "geodetic_datum", "ESRI"); + if (l_alias.empty()) { + return false; + } + auto authFactory = + io::AuthorityFactory::create(NN_NO_CHECK(dbContext), std::string()); + auto list = authFactory->createObjectsFromName( + l_alias, {io::AuthorityFactory::ObjectType::GEODETIC_REFERENCE_FRAME}, + false /* approximate=false*/); + if (list.empty()) { + return false; + } + auto gdatum = util::nn_dynamic_pointer_cast<datum::Datum>(list.front()); + if (gdatum == nullptr || gdatum->identifiers().empty()) { + return false; + } + const auto &gdatum_ids = gdatum->identifiers(); + auto vertCRSList = authFactory->createVerticalCRSFromDatum( + "ESRI", "from_geogdatum_" + *gdatum_ids[0]->codeSpace() + '_' + + gdatum_ids[0]->code()); + if (vertCRSList.size() != 1) { + return false; + } + self->demoteTo2D(std::string(), dbContext)->_exportToWKT(formatter); + vertCRSList.front()->_exportToWKT(formatter); + return true; +} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress void GeodeticCRS::_exportToWKT(io::WKTFormatter *formatter) const { const bool isWKT2 = formatter->version() == io::WKTFormatter::Version::WKT2; const bool isGeographic = @@ -1589,11 +1632,21 @@ void GeodeticCRS::_exportToWKT(io::WKTFormatter *formatter) const { auto l_name = nameStr(); const auto &dbContext = formatter->databaseContext(); - if (formatter->useESRIDialect()) { - if (axisList.size() != 2) { + if (!isWKT2 && formatter->useESRIDialect() && axisList.size() == 3) { + if (!isGeographic) { io::FormattingException::Throw( - "Only export of Geographic 2D CRS is supported in WKT1_ESRI"); + "Geocentric CRS not supported in WKT1_ESRI"); + } + // Try to format the Geographic 3D CRS as a GEOGCS[],VERTCS[...,DATUM[]] + // if we find corresponding objects + if (dbContext) { + if (exportAsESRIWktCompoundCRSWithEllipsoidalHeight(this, this, + formatter)) { + return; + } } + io::FormattingException::Throw( + "Cannot export this Geographic 3D CRS in WKT1_ESRI"); } if (!isWKT2 && formatter->isStrict() && isGeographic && @@ -2853,9 +2906,9 @@ void VerticalCRS::_exportToWKT(io::WKTFormatter *formatter) const { !identifiers().empty()); auto l_name = nameStr(); + const auto &dbContext = formatter->databaseContext(); if (formatter->useESRIDialect()) { bool aliasFound = false; - const auto &dbContext = formatter->databaseContext(); if (dbContext) { auto l_alias = dbContext->getAliasFromOfficialName( l_name, "vertical_crs", "ESRI"); @@ -2870,7 +2923,34 @@ void VerticalCRS::_exportToWKT(io::WKTFormatter *formatter) const { } formatter->addQuotedString(l_name); - exportDatumOrDatumEnsembleToWkt(formatter); + + const auto l_datum = datum(); + if (formatter->useESRIDialect() && l_datum && + l_datum->getWKT1DatumType() == "2002") { + bool foundMatch = false; + if (dbContext) { + auto authFactory = io::AuthorityFactory::create( + NN_NO_CHECK(dbContext), std::string()); + auto list = authFactory->createObjectsFromName( + l_datum->nameStr(), + {io::AuthorityFactory::ObjectType::GEODETIC_REFERENCE_FRAME}, + false /* approximate=false*/); + if (!list.empty()) { + auto gdatum = + util::nn_dynamic_pointer_cast<datum::Datum>(list.front()); + if (gdatum) { + gdatum->_exportToWKT(formatter); + foundMatch = true; + } + } + } + if (!foundMatch) { + // We should export a geodetic datum, but we cannot really do better + l_datum->_exportToWKT(formatter); + } + } else { + exportDatumOrDatumEnsembleToWkt(formatter); + } const auto &cs = SingleCRS::getPrivate()->coordinateSystem; const auto &axisList = cs->axisList(); @@ -3497,6 +3577,16 @@ void ProjectedCRS::_exportToWKT(io::WKTFormatter *formatter) const { } } + if (formatter->useESRIDialect() && dbContext) { + // Try to format the ProjecteD 3D CRS as a + // PROJCS[],VERTCS[...,DATUM[]] + // if we find corresponding objects + if (exportAsESRIWktCompoundCRSWithEllipsoidalHeight( + this, baseCRS().as_nullable().get(), formatter)) { + return; + } + } + if (!formatter->useESRIDialect() && CRS::getPrivate()->allowNonConformantWKT1Export_) { formatter->startNode(io::WKTConstants::COMPD_CS, false); @@ -4528,15 +4618,21 @@ CRSNNPtr CompoundCRS::createLax(const util::PropertyMap &properties, //! @cond Doxygen_Suppress void CompoundCRS::_exportToWKT(io::WKTFormatter *formatter) const { const bool isWKT2 = formatter->version() == io::WKTFormatter::Version::WKT2; - formatter->startNode(isWKT2 ? io::WKTConstants::COMPOUNDCRS - : io::WKTConstants::COMPD_CS, - !identifiers().empty()); - formatter->addQuotedString(nameStr()); - for (const auto &crs : componentReferenceSystems()) { - crs->_exportToWKT(formatter); + const auto &l_components = componentReferenceSystems(); + if (!isWKT2 && formatter->useESRIDialect() && l_components.size() == 2) { + l_components[0]->_exportToWKT(formatter); + l_components[1]->_exportToWKT(formatter); + } else { + formatter->startNode(isWKT2 ? io::WKTConstants::COMPOUNDCRS + : io::WKTConstants::COMPD_CS, + !identifiers().empty()); + formatter->addQuotedString(nameStr()); + for (const auto &crs : l_components) { + crs->_exportToWKT(formatter); + } + ObjectUsage::baseExportToWKT(formatter); + formatter->endNode(); } - ObjectUsage::baseExportToWKT(formatter); - formatter->endNode(); } //! @endcond |
