diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2019-09-12 13:27:23 +0200 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2019-09-12 15:57:54 +0200 |
| commit | 2dd68f992680586f64b79807d049bc6c648197b5 (patch) | |
| tree | 979b84223d1d450561dc7be6a7f1caf2ba101f13 /src | |
| parent | 9350d9ee2ebbc4a68e2682a999cd08d91ea2c8b1 (diff) | |
| download | PROJ-2dd68f992680586f64b79807d049bc6c648197b5.tar.gz PROJ-2dd68f992680586f64b79807d049bc6c648197b5.zip | |
createOperations(): make it work when transforming between CompoundCRS and Geog3D when the DB has only VertCS to Geog2D
This is needed to fix cases that would not work if using the promoteTo3D()/--3d
functionnality just added per a6e1d72890615b42f54edad9b17acff8e7623844
In some cases, the EPSG database only contains a Geographic 2D CRS (like NAD83),
without a 3D version. Consequently vertical transformations between that
Geographic CRS and a Vertical CRS are only available with a 2D CRS code
(kind of a bug in modelization by the way...). So when promoting the
Geographic 2D CRS to a 3D one, we suddenly cannot find the available
transformations any more. So in such situation, try to fallback to the
2D CRS to restore the capability to find the available transformations.
Diffstat (limited to 'src')
| -rw-r--r-- | src/iso19111/coordinateoperation.cpp | 68 |
1 files changed, 58 insertions, 10 deletions
diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp index e86f1850..768ef76f 100644 --- a/src/iso19111/coordinateoperation.cpp +++ b/src/iso19111/coordinateoperation.cpp @@ -12106,11 +12106,16 @@ CoordinateOperationFactory::Private::createOperations( auto geodSrc = dynamic_cast<const crs::GeodeticCRS *>(sourceCRS.get()); auto geodDst = dynamic_cast<const crs::GeodeticCRS *>(targetCRS.get()); + auto geogSrc = dynamic_cast<const crs::GeographicCRS *>(sourceCRS.get()); + auto geogDst = dynamic_cast<const crs::GeographicCRS *>(targetCRS.get()); + auto vertSrc = dynamic_cast<const crs::VerticalCRS *>(sourceCRS.get()); + auto vertDst = dynamic_cast<const crs::VerticalCRS *>(targetCRS.get()); // First look-up if the registry provide us with operations. auto derivedSrc = dynamic_cast<const crs::DerivedCRS *>(sourceCRS.get()); auto derivedDst = dynamic_cast<const crs::DerivedCRS *>(targetCRS.get()); - if (context.context->getAuthorityFactory() && + const auto &authFactory = context.context->getAuthorityFactory(); + if (authFactory && (derivedSrc == nullptr || !derivedSrc->baseCRS()->_isEquivalentTo( targetCRS.get(), util::IComparable::Criterion::EQUIVALENT)) && @@ -12144,6 +12149,58 @@ CoordinateOperationFactory::Private::createOperations( util::IComparable::Criterion::EQUIVALENT); } + // NAD83 only exists in 2D version in EPSG, so if it has been + // promotted to 3D, when researching a vertical to geog + // transformation, + // try to down cast to 2D. + if (res.empty() && geogSrc && vertDst && + geogSrc->coordinateSystem()->axisList().size() == 3 && + geogSrc->datum()) { + const auto candidatesSrcGeod(findCandidateGeodCRSForDatum( + authFactory, geogSrc->datum().get())); + for (const auto &candidate : candidatesSrcGeod) { + auto geogCandidate = + util::nn_dynamic_pointer_cast<crs::GeographicCRS>( + candidate); + if (geogCandidate && + geogCandidate->coordinateSystem()->axisList().size() == + 2) { + res = + findOpsInRegistryDirect(NN_NO_CHECK(geogCandidate), + targetCRS, context.context); + if (res.empty()) { + res = applyInverse(findOpsInRegistryDirect( + targetCRS, NN_NO_CHECK(geogCandidate), + context.context)); + } + break; + } + } + } else if (res.empty() && geogDst && vertSrc && + geogDst->coordinateSystem()->axisList().size() == 3 && + geogDst->datum()) { + const auto candidatesDstGeod(findCandidateGeodCRSForDatum( + authFactory, geogDst->datum().get())); + for (const auto &candidate : candidatesDstGeod) { + auto geogCandidate = + util::nn_dynamic_pointer_cast<crs::GeographicCRS>( + candidate); + if (geogCandidate && + geogCandidate->coordinateSystem()->axisList().size() == + 2) { + res = findOpsInRegistryDirect( + sourceCRS, NN_NO_CHECK(geogCandidate), + context.context); + if (res.empty()) { + res = applyInverse(findOpsInRegistryDirect( + NN_NO_CHECK(geogCandidate), sourceCRS, + context.context)); + } + break; + } + } + } + if (res.empty() && !sameGeodeticDatum && !context.inCreateOperationsWithDatumPivotAntiRecursion && geodSrc && geodDst) { @@ -12202,10 +12259,6 @@ CoordinateOperationFactory::Private::createOperations( "celestial body"); } - auto geogSrc = - dynamic_cast<const crs::GeographicCRS *>(sourceCRS.get()); - auto geogDst = - dynamic_cast<const crs::GeographicCRS *>(targetCRS.get()); if (geogSrc && geogDst) { return createOperationsGeogToGeog(res, sourceCRS, targetCRS, geogSrc, geogDst); @@ -12293,7 +12346,6 @@ CoordinateOperationFactory::Private::createOperations( return applyInverse(createOperations(targetCRS, sourceCRS, context)); } - auto geogDst = dynamic_cast<const crs::GeographicCRS *>(targetCRS.get()); if (boundSrc && geogDst) { const auto &hubSrc = boundSrc->hubCRS(); auto hubSrcGeog = @@ -12482,14 +12534,12 @@ CoordinateOperationFactory::Private::createOperations( } // reverse of previous case - auto geogSrc = dynamic_cast<const crs::GeographicCRS *>(sourceCRS.get()); if (geogSrc && boundDst) { return applyInverse(createOperations(targetCRS, sourceCRS, context)); } // vertCRS (as boundCRS with transformation to target vertCRS) to // vertCRS - auto vertDst = dynamic_cast<const crs::VerticalCRS *>(targetCRS.get()); if (boundSrc && vertDst) { auto baseSrcVert = dynamic_cast<const crs::VerticalCRS *>(boundSrc->baseCRS().get()); @@ -12506,7 +12556,6 @@ CoordinateOperationFactory::Private::createOperations( } // reverse of previous case - auto vertSrc = dynamic_cast<const crs::VerticalCRS *>(sourceCRS.get()); if (boundDst && vertSrc) { return applyInverse(createOperations(targetCRS, sourceCRS, context)); } @@ -12550,7 +12599,6 @@ CoordinateOperationFactory::Private::createOperations( if (vertSrc && geogDst) { if (vertSrc->identifiers().empty()) { - const auto &authFactory = context.context->getAuthorityFactory(); const auto &vertSrcName = vertSrc->nameStr(); if (authFactory != nullptr && vertSrcName != "unnamed" && vertSrcName != "unknown") { |
