From 72f0e8a895a861e4323cac61b73f807c8a5f1c0d Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Mon, 25 Mar 2019 12:11:21 +0100 Subject: crs.cpp: remove non-intented (harmless here) pass by reference of a pointer --- src/iso19111/crs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp index 9688883d..74f6f999 100644 --- a/src/iso19111/crs.cpp +++ b/src/iso19111/crs.cpp @@ -2421,7 +2421,7 @@ void DerivedCRS::setDerivingConversionCRS() { // --------------------------------------------------------------------------- -void DerivedCRS::baseExportToWKT(io::WKTFormatter *&formatter, +void DerivedCRS::baseExportToWKT(io::WKTFormatter *formatter, const std::string &keyword, const std::string &baseKeyword) const { formatter->startNode(keyword, !identifiers().empty()); @@ -4848,7 +4848,7 @@ DerivedCRSTemplate::create( // --------------------------------------------------------------------------- -static void DerivedCRSTemplateCheckExportToWKT(io::WKTFormatter *&formatter, +static void DerivedCRSTemplateCheckExportToWKT(io::WKTFormatter *formatter, const std::string &crsName, bool wkt2_2018_only) { const bool isWKT2 = formatter->version() == io::WKTFormatter::Version::WKT2; -- cgit v1.2.3 From d4fd50f10ecabb9e9642cb4f877262e082677be4 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Mon, 25 Mar 2019 12:07:35 +0100 Subject: WKT2_2018: export ID in base crs node, when there is none on top of upper node This is the standard logic, that is now possible since ID is allowed in BASEGEOGCRS and similar node --- src/iso19111/crs.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp index 74f6f999..9779d817 100644 --- a/src/iso19111/crs.cpp +++ b/src/iso19111/crs.cpp @@ -2428,9 +2428,13 @@ void DerivedCRS::baseExportToWKT(io::WKTFormatter *formatter, formatter->addQuotedString(nameStr()); const auto &l_baseCRS = d->baseCRS_; - formatter->startNode(baseKeyword, !l_baseCRS->identifiers().empty()); + formatter->startNode(baseKeyword, formatter->use2018Keywords() && + !l_baseCRS->identifiers().empty()); formatter->addQuotedString(l_baseCRS->nameStr()); l_baseCRS->exportDatumOrDatumEnsembleToWkt(formatter); + if (formatter->use2018Keywords() && formatter->outputId()) { + l_baseCRS->formatID(formatter); + } formatter->endNode(); formatter->setUseDerivingConversion(true); @@ -2658,7 +2662,7 @@ void ProjectedCRS::_exportToWKT(io::WKTFormatter *formatter) const { dynamic_cast(l_baseCRS.get())) ? io::WKTConstants::BASEGEOGCRS : io::WKTConstants::BASEGEODCRS, - !l_baseCRS->identifiers().empty()); + formatter->use2018Keywords() && !l_baseCRS->identifiers().empty()); formatter->addQuotedString(l_baseCRS->nameStr()); l_baseCRS->exportDatumOrDatumEnsembleToWkt(formatter); // insert ellipsoidal cs unit when the units of the map @@ -2669,6 +2673,9 @@ void ProjectedCRS::_exportToWKT(io::WKTFormatter *formatter) const { geodeticCRSAxisList[0]->unit()._exportToWKT(formatter); } l_baseCRS->primeMeridian()->_exportToWKT(formatter); + if (formatter->use2018Keywords() && formatter->outputId()) { + l_baseCRS->formatID(formatter); + } formatter->endNode(); } else { const auto oldAxisOutputRule = formatter->outputAxis(); -- cgit v1.2.3 From 46f08f1434f66a4160d7c74923efcfb81505b398 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Mon, 25 Mar 2019 12:44:05 +0100 Subject: WKT2_2018: always export ID in base crs node, even if there is one on upper node This is a particular logic allowed by paragraph 7.3.3 Identifier of OGC 18-010r6 --- src/iso19111/crs.cpp | 6 ++++-- src/iso19111/io.cpp | 12 ++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp index 9779d817..2dc6b3bf 100644 --- a/src/iso19111/crs.cpp +++ b/src/iso19111/crs.cpp @@ -2432,7 +2432,8 @@ void DerivedCRS::baseExportToWKT(io::WKTFormatter *formatter, !l_baseCRS->identifiers().empty()); formatter->addQuotedString(l_baseCRS->nameStr()); l_baseCRS->exportDatumOrDatumEnsembleToWkt(formatter); - if (formatter->use2018Keywords() && formatter->outputId()) { + if (formatter->use2018Keywords() && + !(formatter->idOnTopLevelOnly() && formatter->topLevelHasId())) { l_baseCRS->formatID(formatter); } formatter->endNode(); @@ -2673,7 +2674,8 @@ void ProjectedCRS::_exportToWKT(io::WKTFormatter *formatter) const { geodeticCRSAxisList[0]->unit()._exportToWKT(formatter); } l_baseCRS->primeMeridian()->_exportToWKT(formatter); - if (formatter->use2018Keywords() && formatter->outputId()) { + if (formatter->use2018Keywords() && + !(formatter->idOnTopLevelOnly() && formatter->topLevelHasId())) { l_baseCRS->formatID(formatter); } formatter->endNode(); diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index 220ee967..78b18719 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -634,6 +634,18 @@ bool WKTFormatter::primeMeridianInDegree() const { // --------------------------------------------------------------------------- +bool WKTFormatter::idOnTopLevelOnly() const { + return d->params_.idOnTopLevelOnly_; +} + +// --------------------------------------------------------------------------- + +bool WKTFormatter::topLevelHasId() const { + return d->stackHasId_.size() >= 2 && d->stackHasId_[1]; +} + +// --------------------------------------------------------------------------- + WKTFormatter::Version WKTFormatter::version() const { return d->params_.version_; } -- cgit v1.2.3 From 09db4826d4a1e5df900cb4b93a4b3eae2c487cb9 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Mon, 25 Mar 2019 13:56:43 +0100 Subject: WKT2_2018: always export ID of SOURCECRS/TARGETCRS and STEPs even if there is one on upper node This is a particular logic allowed by paragraph 7.3.3 Identifier of OGC 18-010r6 --- src/iso19111/common.cpp | 2 +- src/iso19111/coordinateoperation.cpp | 88 ++++++++++++++++++++++++++++-------- src/iso19111/io.cpp | 28 ++++++++++++ 3 files changed, 98 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/iso19111/common.cpp b/src/iso19111/common.cpp index 4b947dc9..d46da0da 100644 --- a/src/iso19111/common.cpp +++ b/src/iso19111/common.cpp @@ -1073,7 +1073,7 @@ void ObjectUsage::setProperties( void ObjectUsage::baseExportToWKT(WKTFormatter *formatter) const { const bool isWKT2 = formatter->version() == WKTFormatter::Version::WKT2; - if (isWKT2 && formatter->outputId()) { + if (isWKT2 && formatter->outputUsage()) { auto l_domains = domains(); if (!l_domains.empty()) { if (formatter->use2018Keywords()) { diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp index 80c1a572..d7f138a4 100644 --- a/src/iso19111/coordinateoperation.cpp +++ b/src/iso19111/coordinateoperation.cpp @@ -7639,6 +7639,53 @@ void Transformation::_exportToWKT(io::WKTFormatter *formatter) const { // --------------------------------------------------------------------------- +static void exportSourceCRSAndTargetCRSToWKT(const CoordinateOperation *co, + io::WKTFormatter *formatter) { + auto l_sourceCRS = co->sourceCRS(); + assert(l_sourceCRS); + auto l_targetCRS = co->targetCRS(); + assert(l_targetCRS); + const bool isWKT2 = formatter->version() == io::WKTFormatter::Version::WKT2; + const bool canExportCRSId = + (isWKT2 && formatter->use2018Keywords() && + !(formatter->idOnTopLevelOnly() && formatter->topLevelHasId())); + + const bool hasDomains = !co->domains().empty(); + if (hasDomains) { + formatter->pushDisableUsage(); + } + + formatter->startNode(io::WKTConstants::SOURCECRS, false); + if (canExportCRSId && !l_sourceCRS->identifiers().empty()) { + // fake that top node has no id, so that the sourceCRS id is + // considered + formatter->pushHasId(false); + l_sourceCRS->_exportToWKT(formatter); + formatter->popHasId(); + } else { + l_sourceCRS->_exportToWKT(formatter); + } + formatter->endNode(); + + formatter->startNode(io::WKTConstants::TARGETCRS, false); + if (canExportCRSId && !l_targetCRS->identifiers().empty()) { + // fake that top node has no id, so that the targetCRS id is + // considered + formatter->pushHasId(false); + l_targetCRS->_exportToWKT(formatter); + formatter->popHasId(); + } else { + l_targetCRS->_exportToWKT(formatter); + } + formatter->endNode(); + + if (hasDomains) { + formatter->popDisableUsage(); + } +} + +// --------------------------------------------------------------------------- + void SingleOperation::exportTransformationToWKT( io::WKTFormatter *formatter) const { const bool isWKT2 = formatter->version() == io::WKTFormatter::Version::WKT2; @@ -7647,11 +7694,6 @@ void SingleOperation::exportTransformationToWKT( "Transformation can only be exported to WKT2"); } - auto l_sourceCRS = sourceCRS(); - assert(l_sourceCRS); - auto l_targetCRS = targetCRS(); - assert(l_targetCRS); - if (formatter->abridgedTransformation()) { formatter->startNode(io::WKTConstants::ABRIDGEDTRANSFORMATION, !identifiers().empty()); @@ -7672,13 +7714,7 @@ void SingleOperation::exportTransformationToWKT( } if (!formatter->abridgedTransformation()) { - formatter->startNode(io::WKTConstants::SOURCECRS, false); - l_sourceCRS->_exportToWKT(formatter); - formatter->endNode(); - - formatter->startNode(io::WKTConstants::TARGETCRS, false); - l_targetCRS->_exportToWKT(formatter); - formatter->endNode(); + exportSourceCRSAndTargetCRSToWKT(this, formatter); } method()->_exportToWKT(formatter); @@ -9337,20 +9373,34 @@ void ConcatenatedOperation::_exportToWKT(io::WKTFormatter *formatter) const { } } - formatter->startNode(io::WKTConstants::SOURCECRS, false); - sourceCRS()->_exportToWKT(formatter); - formatter->endNode(); + exportSourceCRSAndTargetCRSToWKT(this, formatter); - formatter->startNode(io::WKTConstants::TARGETCRS, false); - targetCRS()->_exportToWKT(formatter); - formatter->endNode(); + const bool canExportOperationId = + !(formatter->idOnTopLevelOnly() && formatter->topLevelHasId()); + + const bool hasDomains = !domains().empty(); + if (hasDomains) { + formatter->pushDisableUsage(); + } for (const auto &operation : operations()) { formatter->startNode(io::WKTConstants::STEP, false); - operation->_exportToWKT(formatter); + if (canExportOperationId && !operation->identifiers().empty()) { + // fake that top node has no id, so that the operation id is + // considered + formatter->pushHasId(false); + operation->_exportToWKT(formatter); + formatter->popHasId(); + } else { + operation->_exportToWKT(formatter); + } formatter->endNode(); } + if (hasDomains) { + formatter->popDisableUsage(); + } + ObjectUsage::baseExportToWKT(formatter); formatter->endNode(); } diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index 78b18719..578234b4 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -141,6 +141,7 @@ struct WKTFormatter::Private { std::vector stackHasChild_{}; std::vector stackHasId_{false}; std::vector stackEmptyKeyword_{}; + std::vector stackDisableUsage_{}; std::vector outputUnitStack_{true}; std::vector outputIdStack_{true}; std::vector axisLinearUnitStack_{ @@ -272,6 +273,11 @@ const std::string &WKTFormatter::toString() const { if (d->outputUnitStack_.size() != 1) throw FormattingException( "Unbalanced pushOutputUnit() / popOutputUnit()"); + if (d->stackHasId_.size() != 1) + throw FormattingException("Unbalanced pushHasId() / popHasId()"); + if (!d->stackDisableUsage_.empty()) + throw FormattingException( + "Unbalanced pushDisableUsage() / popDisableUsage()"); return d->result_; } @@ -556,6 +562,28 @@ bool WKTFormatter::outputId() const { // --------------------------------------------------------------------------- +void WKTFormatter::pushHasId(bool hasId) { d->stackHasId_.push_back(hasId); } + +// --------------------------------------------------------------------------- + +void WKTFormatter::popHasId() { d->stackHasId_.pop_back(); } + +// --------------------------------------------------------------------------- + +void WKTFormatter::pushDisableUsage() { d->stackDisableUsage_.push_back(true); } + +// --------------------------------------------------------------------------- + +void WKTFormatter::popDisableUsage() { d->stackDisableUsage_.pop_back(); } + +// --------------------------------------------------------------------------- + +bool WKTFormatter::outputUsage() const { + return outputId() && d->stackDisableUsage_.empty(); +} + +// --------------------------------------------------------------------------- + void WKTFormatter::pushAxisLinearUnit(const UnitOfMeasureNNPtr &unit) { d->axisLinearUnitStack_.push_back(unit); } -- cgit v1.2.3