diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2020-12-14 21:12:43 +0100 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2020-12-14 21:12:43 +0100 |
| commit | 95340fb1d1011d6864d82b60194eb77df9e9e38f (patch) | |
| tree | 30e2d3909d33c04f7966f996f90c971cd7023ade /src/iso19111/operation/concatenatedoperation.cpp | |
| parent | bfc54bbac8550e18d352468032ad0b3d5ca2d328 (diff) | |
| download | PROJ-95340fb1d1011d6864d82b60194eb77df9e9e38f.tar.gz PROJ-95340fb1d1011d6864d82b60194eb77df9e9e38f.zip | |
createOperations(): fix inconsistent chaining exception when transforming from BoundCRS of projected CRS based on NTF Paris to BoundCRS of geog CRS NTF Paris. Fixes https://github.com/OSGeo/gdal/issues/3273
Diffstat (limited to 'src/iso19111/operation/concatenatedoperation.cpp')
| -rw-r--r-- | src/iso19111/operation/concatenatedoperation.cpp | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/src/iso19111/operation/concatenatedoperation.cpp b/src/iso19111/operation/concatenatedoperation.cpp index 1c65a24b..ce4b015a 100644 --- a/src/iso19111/operation/concatenatedoperation.cpp +++ b/src/iso19111/operation/concatenatedoperation.cpp @@ -446,6 +446,41 @@ CoordinateOperationNNPtr ConcatenatedOperation::createComputeMetadata( flattenOps.emplace_back(subOp); } } + + // Remove consecutive inverse operations + if (flattenOps.size() > 2) { + std::vector<size_t> indices; + for (size_t i = 0; i < flattenOps.size(); ++i) + indices.push_back(i); + while (true) { + bool bHasChanged = false; + for (size_t i = 0; i + 1 < indices.size(); ++i) { + if (flattenOps[indices[i]]->_isEquivalentTo( + flattenOps[indices[i + 1]]->inverse().get(), + util::IComparable::Criterion::EQUIVALENT) && + flattenOps[indices[i]]->sourceCRS()->_isEquivalentTo( + flattenOps[indices[i + 1]]->targetCRS().get(), + util::IComparable::Criterion::EQUIVALENT)) { + indices.erase(indices.begin() + i, indices.begin() + i + 2); + bHasChanged = true; + break; + } + } + // We bail out if indices.size() == 2, because potentially + // the last 2 remaining ones could auto-cancel, and we would have + // to have a special case for that (and this happens in practice). + if (!bHasChanged || indices.size() <= 2) + break; + } + if (indices.size() < flattenOps.size()) { + std::vector<CoordinateOperationNNPtr> flattenOpsNew; + for (size_t i = 0; i < indices.size(); ++i) { + flattenOpsNew.emplace_back(flattenOps[indices[i]]); + } + flattenOps = std::move(flattenOpsNew); + } + } + if (flattenOps.size() == 1) { return flattenOps[0]; } |
