aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2020-05-19 12:57:22 +0200
committerEven Rouault <even.rouault@spatialys.com>2020-05-19 14:21:01 +0200
commit8dc8e1de06dcb71da11facaaff6af9e46294deb0 (patch)
tree96841676e7ffe0f8de5180e1ad5f5edf61152ee3
parentec3fdd00f133736560f807765dd73367c85f4bdc (diff)
downloadPROJ-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.cpp39
-rw-r--r--test/unit/test_operation.cpp40
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,