diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2022-03-22 19:07:50 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-03-22 19:07:50 +0100 |
| commit | 689189af924730a5663ceef9d9f74328e33670db (patch) | |
| tree | 171f26e1a9b4418bd02e5ac195ea529865c278bd | |
| parent | 8c51e3c99acc9083d82a5a7a6dae146e2a689f8e (diff) | |
| parent | 169e1c5691858e0846eb7ede6b3778f8ec0a2892 (diff) | |
| download | PROJ-689189af924730a5663ceef9d9f74328e33670db.tar.gz PROJ-689189af924730a5663ceef9d9f74328e33670db.zip | |
Fix datum names when importing from PROJ4 crs strings (affects some transformations using geoidgrids)
| -rw-r--r-- | src/iso19111/io.cpp | 75 | ||||
| -rw-r--r-- | test/unit/test_io.cpp | 4 | ||||
| -rw-r--r-- | test/unit/test_operationfactory.cpp | 47 |
3 files changed, 89 insertions, 37 deletions
diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index e09aee93..7492e624 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -9200,13 +9200,22 @@ PROJStringParser::Private::buildDatum(Step &step, const std::string &title) { PrimeMeridianNNPtr pm(buildPrimeMeridian(step)); PropertyMap grfMap; + const auto &nadgrids = getParamValue(step, "nadgrids"); + const auto &towgs84 = getParamValue(step, "towgs84"); + std::string datumNameSuffix; + if (!nadgrids.empty()) { + datumNameSuffix = " using nadgrids=" + nadgrids; + } else if (!towgs84.empty()) { + datumNameSuffix = " using towgs84=" + towgs84; + } + // It is arguable that we allow the prime meridian of a datum defined by // its name to be overridden, but this is found at least in a regression // test // of GDAL. So let's keep the ellipsoid part of the datum in that case and // use the specified prime meridian. const auto overridePmIfNeeded = - [&pm](const GeodeticReferenceFrameNNPtr &grf) { + [&pm, &datumNameSuffix](const GeodeticReferenceFrameNNPtr &grf) { if (pm->_isEquivalentTo(PrimeMeridian::GREENWICH.get())) { return grf; } else { @@ -9214,7 +9223,7 @@ PROJStringParser::Private::buildDatum(Step &step, const std::string &title) { PropertyMap().set(IdentifiedObject::NAME_KEY, "Unknown based on " + grf->ellipsoid()->nameStr() + - " ellipsoid"), + " ellipsoid" + datumNameSuffix), grf->ellipsoid(), grf->anchorDefinition(), pm); } }; @@ -9231,7 +9240,7 @@ PROJStringParser::Private::buildDatum(Step &step, const std::string &title) { Length(R), guessBodyName(R)); return GeodeticReferenceFrame::create( grfMap.set(IdentifiedObject::NAME_KEY, - title.empty() ? "unknown" : title.c_str()), + title.empty() ? "unknown" + datumNameSuffix : title), ellipsoid, optionalEmptyString, fixupPrimeMeridan(ellipsoid, pm)); } @@ -9280,21 +9289,23 @@ PROJStringParser::Private::buildDatum(Step &step, const std::string &title) { } else if (!ellpsStr.empty()) { - auto l_datum = [&ellpsStr, &title, &grfMap, &optionalEmptyString, - &pm]() { + auto l_datum = [&ellpsStr, &title, &grfMap, &optionalEmptyString, &pm, + &datumNameSuffix]() { if (ellpsStr == "WGS84") { return GeodeticReferenceFrame::create( grfMap.set(IdentifiedObject::NAME_KEY, title.empty() - ? "Unknown based on WGS84 ellipsoid" - : title.c_str()), + ? "Unknown based on WGS84 ellipsoid" + + datumNameSuffix + : title), Ellipsoid::WGS84, optionalEmptyString, pm); } else if (ellpsStr == "GRS80") { return GeodeticReferenceFrame::create( grfMap.set(IdentifiedObject::NAME_KEY, title.empty() - ? "Unknown based on GRS80 ellipsoid" - : title.c_str()), + ? "Unknown based on GRS80 ellipsoid" + + datumNameSuffix + : title), Ellipsoid::GRS1980, optionalEmptyString, pm); } else { auto proj_ellps = proj_list_ellps(); @@ -9330,7 +9341,7 @@ PROJStringParser::Private::buildDatum(Step &step, const std::string &title) { title.empty() ? std::string("Unknown based on ") + proj_ellps[i].name + - " ellipsoid" + " ellipsoid" + datumNameSuffix : title), NN_NO_CHECK(ellipsoid), optionalEmptyString, pm); } @@ -9357,6 +9368,15 @@ PROJStringParser::Private::buildDatum(Step &step, const std::string &title) { } } + const auto createGRF = [&grfMap, &title, &optionalEmptyString, + &datumNameSuffix, + &pm](const EllipsoidNNPtr &ellipsoid) { + return GeodeticReferenceFrame::create( + grfMap.set(IdentifiedObject::NAME_KEY, + title.empty() ? "unknown" + datumNameSuffix : title), + ellipsoid, optionalEmptyString, fixupPrimeMeridan(ellipsoid, pm)); + }; + if (a > 0 && (b > 0 || !bStr.empty())) { if (!bStr.empty()) { try { @@ -9369,10 +9389,7 @@ PROJStringParser::Private::buildDatum(Step &step, const std::string &title) { Ellipsoid::createTwoAxis(createMapWithUnknownName(), Length(a), Length(b), guessBodyName(a)) ->identify(); - return GeodeticReferenceFrame::create( - grfMap.set(IdentifiedObject::NAME_KEY, - title.empty() ? "unknown" : title.c_str()), - ellipsoid, optionalEmptyString, fixupPrimeMeridan(ellipsoid, pm)); + return createGRF(ellipsoid); } else if (a > 0 && (rf >= 0 || !rfStr.empty())) { @@ -9387,10 +9404,7 @@ PROJStringParser::Private::buildDatum(Step &step, const std::string &title) { createMapWithUnknownName(), Length(a), Scale(rf), guessBodyName(a)) ->identify(); - return GeodeticReferenceFrame::create( - grfMap.set(IdentifiedObject::NAME_KEY, - title.empty() ? "unknown" : title.c_str()), - ellipsoid, optionalEmptyString, fixupPrimeMeridan(ellipsoid, pm)); + return createGRF(ellipsoid); } else if (a > 0 && !fStr.empty()) { @@ -9404,10 +9418,7 @@ PROJStringParser::Private::buildDatum(Step &step, const std::string &title) { createMapWithUnknownName(), Length(a), Scale(f != 0.0 ? 1.0 / f : 0.0), guessBodyName(a)) ->identify(); - return GeodeticReferenceFrame::create( - grfMap.set(IdentifiedObject::NAME_KEY, - title.empty() ? "unknown" : title.c_str()), - ellipsoid, optionalEmptyString, fixupPrimeMeridan(ellipsoid, pm)); + return createGRF(ellipsoid); } else if (a > 0 && !eStr.empty()) { @@ -9423,10 +9434,7 @@ PROJStringParser::Private::buildDatum(Step &step, const std::string &title) { createMapWithUnknownName(), Length(a), Scale(f != 0.0 ? 1.0 / f : 0.0), guessBodyName(a)) ->identify(); - return GeodeticReferenceFrame::create( - grfMap.set(IdentifiedObject::NAME_KEY, - title.empty() ? "unknown" : title.c_str()), - ellipsoid, optionalEmptyString, fixupPrimeMeridan(ellipsoid, pm)); + return createGRF(ellipsoid); } else if (a > 0 && !esStr.empty()) { @@ -9441,10 +9449,7 @@ PROJStringParser::Private::buildDatum(Step &step, const std::string &title) { createMapWithUnknownName(), Length(a), Scale(f != 0.0 ? 1.0 / f : 0.0), guessBodyName(a)) ->identify(); - return GeodeticReferenceFrame::create( - grfMap.set(IdentifiedObject::NAME_KEY, - title.empty() ? "unknown" : title.c_str()), - ellipsoid, optionalEmptyString, fixupPrimeMeridan(ellipsoid, pm)); + return createGRF(ellipsoid); } // If only a is specified, create a sphere @@ -9452,10 +9457,7 @@ PROJStringParser::Private::buildDatum(Step &step, const std::string &title) { esStr.empty()) { auto ellipsoid = Ellipsoid::createSphere(createMapWithUnknownName(), Length(a), guessBodyName(a)); - return GeodeticReferenceFrame::create( - grfMap.set(IdentifiedObject::NAME_KEY, - title.empty() ? "unknown" : title.c_str()), - ellipsoid, optionalEmptyString, fixupPrimeMeridan(ellipsoid, pm)); + return createGRF(ellipsoid); } if (!bStr.empty() && aStr.empty()) { @@ -9833,8 +9835,9 @@ PROJStringParser::Private::buildBoundOrCompoundCRSIfNeeded(int iStep, const auto &geoidgrids = getParamValue(step, "geoidgrids"); if (!geoidgrids.empty()) { - auto vdatum = - VerticalReferenceFrame::create(createMapWithUnknownName()); + auto vdatum = VerticalReferenceFrame::create( + PropertyMap().set(common::IdentifiedObject::NAME_KEY, + "unknown using geoidgrids=" + geoidgrids)); const UnitOfMeasure unit = buildUnit(step, "vunits", "vto_meter"); diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp index f883ddb7..dc511b80 100644 --- a/test/unit/test_io.cpp +++ b/test/unit/test_io.cpp @@ -9852,7 +9852,9 @@ TEST(io, projparse_merc_not_quite_google_mercator) { EXPECT_TRUE(wkt.find("METHOD[\"Popular Visualisation Pseudo " "Mercator\",ID[\"EPSG\",1024]") != std::string::npos) << wkt; - EXPECT_TRUE(wkt.find("DATUM[\"unknown\",") != std::string::npos) << wkt; + EXPECT_TRUE(wkt.find("DATUM[\"unknown using nadgrids=@null\",") != + std::string::npos) + << wkt; EXPECT_EQ( replaceAll(crs->exportToPROJString(PROJStringFormatter::create().get()), diff --git a/test/unit/test_operationfactory.cpp b/test/unit/test_operationfactory.cpp index 01d0da9b..0ff3e827 100644 --- a/test/unit/test_operationfactory.cpp +++ b/test/unit/test_operationfactory.cpp @@ -4230,6 +4230,53 @@ TEST( TEST( operation, + compoundCRS_to_compoundCRS_with_bound_crs_in_horiz_and_vert_same_ellsp_but_different_towgs84_different_geoidgrids) { + auto objSrc = PROJStringParser().createFromPROJString( + "+proj=longlat +ellps=GRS80 +towgs84=1,2,3 +geoidgrids=@foo.gtx " + "+type=crs"); + auto src = nn_dynamic_pointer_cast<CRS>(objSrc); + ASSERT_TRUE(src != nullptr); + auto objDst = PROJStringParser().createFromPROJString( + "+proj=longlat +ellps=GRS80 +towgs84=4,5,6 +geoidgrids=@bar.gtx " + "+type=crs"); + auto dst = nn_dynamic_pointer_cast<CRS>(objDst); + ASSERT_TRUE(dst != nullptr); + + auto srcGeog = src->extractGeographicCRS(); + ASSERT_TRUE(srcGeog != nullptr); + ASSERT_TRUE(srcGeog->datum() != nullptr); + auto dstGeog = dst->extractGeographicCRS(); + ASSERT_TRUE(dstGeog != nullptr); + ASSERT_TRUE(dstGeog->datum() != nullptr); + EXPECT_FALSE(srcGeog->datum()->isEquivalentTo( + dstGeog->datum().get(), IComparable::Criterion::EQUIVALENT)); + + auto op = CoordinateOperationFactory::create()->createOperation( + NN_CHECK_ASSERT(src), NN_CHECK_ASSERT(dst)); + ASSERT_TRUE(op != nullptr); + // Check there's no proj=push +v_1 +v_2 + EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()), + "+proj=pipeline " + "+step +proj=unitconvert +xy_in=deg +xy_out=rad " + "+step +proj=push +v_3 " + "+step +proj=cart +ellps=GRS80 " + "+step +proj=helmert +x=1 +y=2 +z=3 " + "+step +inv +proj=cart +ellps=WGS84 " + "+step +proj=pop +v_3 " + "+step +proj=vgridshift +grids=@foo.gtx +multiplier=1 " + "+step +inv +proj=vgridshift +grids=@bar.gtx +multiplier=1 " + "+step +proj=push +v_3 " + "+step +proj=cart +ellps=WGS84 " + "+step +proj=helmert +x=-4 +y=-5 +z=-6 " + "+step +inv +proj=cart +ellps=GRS80 " + "+step +proj=pop +v_3 " + "+step +proj=unitconvert +xy_in=rad +xy_out=deg"); +} + +// --------------------------------------------------------------------------- + +TEST( + operation, compoundCRS_to_compoundCRS_with_bound_crs_in_horiz_and_vert_WKT1_same_geoidgrids_context) { auto objSrc = WKTParser().createFromWKT( "COMPD_CS[\"NAD83 / Alabama West + NAVD88 height - Geoid12B " |
