diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2020-05-19 12:57:22 +0200 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2020-05-19 14:21:01 +0200 |
| commit | 8dc8e1de06dcb71da11facaaff6af9e46294deb0 (patch) | |
| tree | 96841676e7ffe0f8de5180e1ad5f5edf61152ee3 | |
| parent | ec3fdd00f133736560f807765dd73367c85f4bdc (diff) | |
| download | PROJ-8dc8e1de06dcb71da11facaaff6af9e46294deb0.tar.gz PROJ-8dc8e1de06dcb71da11facaaff6af9e46294deb0.zip | |
createOperations(): fix wrong optimization in some instances of transforming a BoundCRS to a GeographicCRS (contributes to fixes #2232)
| -rw-r--r-- | src/iso19111/coordinateoperation.cpp | 39 | ||||
| -rw-r--r-- | test/unit/test_operation.cpp | 40 |
2 files changed, 66 insertions, 13 deletions
diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp index 231d31a0..32a4b9c7 100644 --- a/src/iso19111/coordinateoperation.cpp +++ b/src/iso19111/coordinateoperation.cpp @@ -14018,25 +14018,38 @@ void CoordinateOperationFactory::Private::createOperationsBoundToGeog( geogDst, util::IComparable::Criterion::EQUIVALENT) || hubSrcGeog->is2DPartOf3D(NN_NO_CHECK(geogDst)))) { triedBoundCrsToGeogCRSSameAsHubCRS = true; + + CoordinateOperationPtr opIntermediate; + if (!geogCRSOfBaseOfBoundSrc->_isEquivalentTo( + boundSrc->transformation()->sourceCRS().get(), + util::IComparable::Criterion::EQUIVALENT)) { + auto opsIntermediate = createOperations( + NN_NO_CHECK(geogCRSOfBaseOfBoundSrc), + boundSrc->transformation()->sourceCRS(), context); + assert(!opsIntermediate.empty()); + opIntermediate = opsIntermediate.front(); + } + if (boundSrc->baseCRS() == geogCRSOfBaseOfBoundSrc) { - // Optimization to avoid creating a useless concatenated - // operation - res.emplace_back(boundSrc->transformation()); + if (opIntermediate) { + try { + res.emplace_back( + ConcatenatedOperation::createComputeMetadata( + {NN_NO_CHECK(opIntermediate), + boundSrc->transformation()}, + !allowEmptyIntersection)); + } catch (const InvalidOperationEmptyIntersection &) { + } + } else { + // Optimization to avoid creating a useless concatenated + // operation + res.emplace_back(boundSrc->transformation()); + } return; } auto opsFirst = createOperations( boundSrc->baseCRS(), NN_NO_CHECK(geogCRSOfBaseOfBoundSrc), context); if (!opsFirst.empty()) { - CoordinateOperationPtr opIntermediate; - if (!geogCRSOfBaseOfBoundSrc->_isEquivalentTo( - boundSrc->transformation()->sourceCRS().get(), - util::IComparable::Criterion::EQUIVALENT)) { - auto opsIntermediate = createOperations( - NN_NO_CHECK(geogCRSOfBaseOfBoundSrc), - boundSrc->transformation()->sourceCRS(), context); - assert(!opsIntermediate.empty()); - opIntermediate = opsIntermediate.front(); - } for (const auto &opFirst : opsFirst) { try { std::vector<CoordinateOperationNNPtr> subops; diff --git a/test/unit/test_operation.cpp b/test/unit/test_operation.cpp index bdf648e4..0cd3b3f5 100644 --- a/test/unit/test_operation.cpp +++ b/test/unit/test_operation.cpp @@ -6399,6 +6399,46 @@ TEST(operation, boundCRS_to_geogCRS_same_datum_context) { // --------------------------------------------------------------------------- +TEST(operation, boundCRS_to_geogCRS_hubCRS_and_targetCRS_same_but_baseCRS_not) { + const char *wkt = + "COMPD_CS[\"NAD83 + Ellipsoid (US Feet)\",\n" + " GEOGCS[\"NAD83\",\n" + " DATUM[\"North_American_Datum_1983\",\n" + " SPHEROID[\"GRS 1980\",6378137,298.257222101,\n" + " AUTHORITY[\"EPSG\",\"7019\"]],\n" + " TOWGS84[0,0,0,0,0,0,0],\n" + " AUTHORITY[\"EPSG\",\"6269\"]],\n" + " PRIMEM[\"Greenwich\",0,\n" + " AUTHORITY[\"EPSG\",\"8901\"]],\n" + " UNIT[\"degree\",0.0174532925199433,\n" + " AUTHORITY[\"EPSG\",\"9122\"]],\n" + " AUTHORITY[\"EPSG\",\"4269\"]],\n" + " VERT_CS[\"Ellipsoid (US Feet)\",\n" + " VERT_DATUM[\"Ellipsoid\",2002],\n" + " UNIT[\"US survey foot\",0.304800609601219,\n" + " AUTHORITY[\"EPSG\",\"9003\"]],\n" + " AXIS[\"Up\",UP]]]"; + + auto dbContext = DatabaseContext::create(); + auto obj = WKTParser().attachDatabaseContext(dbContext).createFromWKT(wkt); + auto boundCRS = nn_dynamic_pointer_cast<BoundCRS>(obj); + ASSERT_TRUE(boundCRS != nullptr); + auto authFactory = AuthorityFactory::create(dbContext, "EPSG"); + auto ctxt = CoordinateOperationContext::create(authFactory, nullptr, 0.0); + ctxt->setGridAvailabilityUse( + CoordinateOperationContext::GridAvailabilityUse:: + IGNORE_GRID_AVAILABILITY); + ctxt->setSpatialCriterion( + CoordinateOperationContext::SpatialCriterion::PARTIAL_INTERSECTION); + auto list = CoordinateOperationFactory::create()->createOperations( + NN_NO_CHECK(boundCRS), GeographicCRS::EPSG_4979, ctxt); + ASSERT_EQ(list.size(), 1U); + EXPECT_EQ(list[0]->exportToPROJString(PROJStringFormatter::create().get()), + "+proj=unitconvert +z_in=us-ft +z_out=m"); +} + +// --------------------------------------------------------------------------- + TEST(operation, boundCRS_to_boundCRS) { auto utm31 = ProjectedCRS::create( PropertyMap(), GeographicCRS::EPSG_4807, |
