aboutsummaryrefslogtreecommitdiff
path: root/src/iso19111/crs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/iso19111/crs.cpp')
-rw-r--r--src/iso19111/crs.cpp122
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