diff options
| -rw-r--r-- | src/iso19111/coordinateoperation.cpp | 31 | ||||
| -rw-r--r-- | test/unit/test_operation.cpp | 32 |
2 files changed, 62 insertions, 1 deletions
diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp index 58e97272..24e5f8ab 100644 --- a/src/iso19111/coordinateoperation.cpp +++ b/src/iso19111/coordinateoperation.cpp @@ -11729,7 +11729,6 @@ CoordinateOperationFactory::Private::createOperations( return applyInverse(createOperations(targetCRS, sourceCRS, context)); } - // boundCRS to a geogCRS that is the same as the hubCRS auto boundSrc = dynamic_cast<const crs::BoundCRS *>(sourceCRS.get()); auto geogDst = dynamic_cast<const crs::GeographicCRS *>(targetCRS.get()); if (boundSrc && geogDst) { @@ -11738,6 +11737,7 @@ CoordinateOperationFactory::Private::createOperations( dynamic_cast<const crs::GeographicCRS *>(hubSrc.get()); auto geogCRSOfBaseOfBoundSrc = boundSrc->baseCRS()->extractGeographicCRS(); + // Is it: boundCRS to a geogCRS that is the same as the hubCRS ? if (hubSrcGeog && geogCRSOfBaseOfBoundSrc && (hubSrcGeog->_isEquivalentTo( geogDst, util::IComparable::Criterion::EQUIVALENT) || @@ -11855,6 +11855,35 @@ CoordinateOperationFactory::Private::createOperations( return res; } + if (hubSrcGeog && geogCRSOfBaseOfBoundSrc) { + // This one should go to the above 'Is it: boundCRS to a geogCRS + // that is the same as the hubCRS ?' case + auto opsFirst = createOperations(sourceCRS, hubSrc, context); + auto opsLast = createOperations(hubSrc, targetCRS, context); + if (!opsFirst.empty() && !opsLast.empty()) { + for (const auto &opFirst : opsFirst) { + for (const auto &opLast : opsLast) { + // Exclude artificial transformations from the hub + // to the target CRS + if (!opLast->hasBallparkTransformation()) { + try { + res.emplace_back( + ConcatenatedOperation:: + createComputeMetadata( + {opFirst, opLast}, + !allowEmptyIntersection)); + } catch ( + const InvalidOperationEmptyIntersection &) { + } + } + } + } + if (!res.empty()) { + return res; + } + } + } + return createOperations(boundSrc->baseCRS(), targetCRS, context); } diff --git a/test/unit/test_operation.cpp b/test/unit/test_operation.cpp index a1774416..4e3ceb56 100644 --- a/test/unit/test_operation.cpp +++ b/test/unit/test_operation.cpp @@ -5485,6 +5485,38 @@ TEST(operation, boundCRS_of_geogCRS_to_projCRS) { // --------------------------------------------------------------------------- +TEST(operation, boundCRS_of_geogCRS_to_unrelated_geogCRS_context) { + auto src = BoundCRS::createFromTOWGS84( + GeographicCRS::EPSG_4807, std::vector<double>{1, 2, 3, 4, 5, 6, 7}); + auto authFactory = + AuthorityFactory::create(DatabaseContext::create(), "EPSG"); + // ETRS89 + auto dst = authFactory->createCoordinateReferenceSystem("4258"); + auto ctxt = CoordinateOperationContext::create(authFactory, nullptr, 0.0); + auto list = + CoordinateOperationFactory::create()->createOperations(src, dst, ctxt); + ASSERT_EQ(list.size(), 1U); + // Check with it is a concatenated operation, since it doesn't particularly + // show up in the PROJ string + EXPECT_TRUE(dynamic_cast<ConcatenatedOperation *>(list[0].get()) != + nullptr); + EXPECT_EQ(list[0]->nameStr(), "Transformation from NTF (Paris) to WGS84 + " + "Inverse of ETRS89 to WGS 84 (1)"); + EXPECT_EQ(list[0]->exportToPROJString(PROJStringFormatter::create().get()), + "+proj=pipeline " + "+step +proj=axisswap +order=2,1 " + "+step +proj=unitconvert +xy_in=grad +xy_out=rad " + "+step +inv +proj=longlat +ellps=clrk80ign +pm=paris " + "+step +proj=push +v_3 +step +proj=cart +ellps=clrk80ign " + "+step +proj=helmert +x=1 +y=2 +z=3 +rx=4 +ry=5 +rz=6 +s=7 " + "+convention=position_vector " + "+step +inv +proj=cart +ellps=GRS80 +step +proj=pop +v_3 " + "+step +proj=unitconvert +xy_in=rad +xy_out=deg " + "+step +proj=axisswap +order=2,1"); +} + +// --------------------------------------------------------------------------- + TEST(operation, geogCRS_to_boundCRS_of_geogCRS) { auto boundCRS = BoundCRS::createFromTOWGS84( GeographicCRS::EPSG_4807, std::vector<double>{1, 2, 3, 4, 5, 6, 7}); |
