diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2019-03-25 13:56:43 +0100 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2019-03-25 13:56:43 +0100 |
| commit | 09db4826d4a1e5df900cb4b93a4b3eae2c487cb9 (patch) | |
| tree | ee4ba388d7d9507397b5cbad5814cb7e1ee540c0 /src | |
| parent | 46f08f1434f66a4160d7c74923efcfb81505b398 (diff) | |
| download | PROJ-09db4826d4a1e5df900cb4b93a4b3eae2c487cb9.tar.gz PROJ-09db4826d4a1e5df900cb4b93a4b3eae2c487cb9.zip | |
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
Diffstat (limited to 'src')
| -rw-r--r-- | src/iso19111/common.cpp | 2 | ||||
| -rw-r--r-- | src/iso19111/coordinateoperation.cpp | 88 | ||||
| -rw-r--r-- | src/iso19111/io.cpp | 28 |
3 files changed, 98 insertions, 20 deletions
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<bool> stackHasChild_{}; std::vector<bool> stackHasId_{false}; std::vector<bool> stackEmptyKeyword_{}; + std::vector<bool> stackDisableUsage_{}; std::vector<bool> outputUnitStack_{true}; std::vector<bool> outputIdStack_{true}; std::vector<UnitOfMeasureNNPtr> 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); } |
