diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2018-11-30 18:37:12 +0100 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2018-12-01 17:36:29 +0100 |
| commit | 9d19d5578705e06990fb716adcb9e6a1529424aa (patch) | |
| tree | e2bba1f4f1f07d61ea1b18638bd07e02c9b3b996 | |
| parent | b6a5c445e202e61c64b0986679a6e0a83724c322 (diff) | |
| download | PROJ-9d19d5578705e06990fb716adcb9e6a1529424aa.tar.gz PROJ-9d19d5578705e06990fb716adcb9e6a1529424aa.zip | |
importFromWKT: morph GDAL_WKT1 datum names into their EPSG spelling
| -rw-r--r-- | src/c_api.cpp | 48 | ||||
| -rw-r--r-- | src/io.cpp | 31 | ||||
| -rw-r--r-- | test/unit/test_c_api.cpp | 57 | ||||
| -rw-r--r-- | test/unit/test_io.cpp | 27 |
4 files changed, 156 insertions, 7 deletions
diff --git a/src/c_api.cpp b/src/c_api.cpp index a0dbecc2..30365297 100644 --- a/src/c_api.cpp +++ b/src/c_api.cpp @@ -409,8 +409,13 @@ PJ_OBJ *proj_obj_create_from_wkt(PJ_CONTEXT *ctx, const char *wkt, assert(wkt); (void)options; try { + WKTParser parser; + auto dbContext = getDBcontextNoException(ctx, __FUNCTION__); + if (dbContext) { + parser.attachDatabaseContext(NN_NO_CHECK(dbContext)); + } auto identifiedObject = nn_dynamic_pointer_cast<IdentifiedObject>( - WKTParser().createFromWKT(wkt)); + parser.createFromWKT(wkt)); if (identifiedObject) { return PJ_OBJ::create(NN_NO_CHECK(identifiedObject)); } @@ -442,8 +447,13 @@ PJ_OBJ *proj_obj_create_from_proj_string(PJ_CONTEXT *ctx, (void)options; assert(proj_string); try { + PROJStringParser parser; + auto dbContext = getDBcontextNoException(ctx, __FUNCTION__); + if (dbContext) { + parser.attachDatabaseContext(NN_NO_CHECK(dbContext)); + } auto identifiedObject = nn_dynamic_pointer_cast<IdentifiedObject>( - PROJStringParser().createFromPROJString(proj_string)); + parser.createFromPROJString(proj_string)); if (identifiedObject) { return PJ_OBJ::create(NN_NO_CHECK(identifiedObject)); } @@ -961,7 +971,8 @@ const char *proj_obj_as_wkt(PJ_CONTEXT *ctx, const PJ_OBJ *obj, const WKTFormatter::Convention convention = static_cast<WKTFormatter::Convention>(type); try { - auto formatter = WKTFormatter::create(convention); + auto dbContext = getDBcontextNoException(ctx, __FUNCTION__); + auto formatter = WKTFormatter::create(convention, dbContext); for (auto iter = options; iter && iter[0]; ++iter) { const char *value; if ((value = getOptionValue(*iter, "MULTILINE="))) { @@ -1827,7 +1838,7 @@ static GeodeticReferenceFrameNNPtr createGeodeticReferenceFrame( const char *angular_units, double angular_units_conv) { const UnitOfMeasure angUnit( createAngularUnit(angular_units, angular_units_conv)); - auto dbContext = getDBcontext(ctx); + auto dbContext = getDBcontextNoException(ctx, __FUNCTION__); auto body = Ellipsoid::guessBodyName(dbContext, semi_major_metre); auto ellpsName = createPropertyMapName(ellps_name); auto ellps = inv_flattening != 0.0 @@ -1847,9 +1858,32 @@ static GeodeticReferenceFrameNNPtr createGeodeticReferenceFrame( : "Reference meridian") : "unnamed"), Angle(prime_meridian_offset, angUnit)); - return GeodeticReferenceFrame::create(createPropertyMapName(datum_name), - ellps, util::optional<std::string>(), - pm); + + std::string datumName(datum_name ? datum_name : "unnamed"); + if (datumName == "WGS_1984") { + datumName = GeodeticReferenceFrame::EPSG_6326->nameStr(); + } else if (datumName.find('_') != std::string::npos) { + // Likely coming from WKT1 + if (dbContext) { + auto authFactory = + AuthorityFactory::create(NN_NO_CHECK(dbContext), std::string()); + auto res = authFactory->createObjectsFromName( + datumName, + {AuthorityFactory::ObjectType::GEODETIC_REFERENCE_FRAME}, true, + 1); + if (!res.empty()) { + const auto &refDatum = res.front(); + if (metadata::Identifier::isEquivalentName( + datumName.c_str(), refDatum->nameStr().c_str())) { + datumName = refDatum->nameStr(); + } + } + } + } + + return GeodeticReferenceFrame::create( + createPropertyMapName(datumName.c_str()), ellps, + util::optional<std::string>(), pm); } //! @endcond @@ -1925,6 +1925,37 @@ GeodeticReferenceFrameNNPtr WKTParser::Private::buildGeodeticReferenceFrame( .set(Identifier::AUTHORITY_KEY, authNameFromAlias))); properties.set(IdentifiedObject::IDENTIFIERS_KEY, identifiers); } + } else if (name.find('_') != std::string::npos) { + // Likely coming from WKT1 + if (dbContext_) { + auto authFactory = AuthorityFactory::create(NN_NO_CHECK(dbContext_), + std::string()); + auto res = authFactory->createObjectsFromName( + name, {AuthorityFactory::ObjectType::GEODETIC_REFERENCE_FRAME}, + true, 1); + if (!res.empty()) { + const auto &refDatum = res.front(); + if (metadata::Identifier::isEquivalentName( + name.c_str(), refDatum->nameStr().c_str())) { + properties.set(IdentifiedObject::NAME_KEY, + refDatum->nameStr()); + if (properties.find(Identifier::CODESPACE_KEY) == + properties.end() && + refDatum->identifiers().size() == 1) { + const auto &id = refDatum->identifiers()[0]; + auto identifiers = ArrayOfBaseObject::create(); + identifiers->add(Identifier::create( + id->code(), PropertyMap() + .set(Identifier::CODESPACE_KEY, + *id->codeSpace()) + .set(Identifier::AUTHORITY_KEY, + *id->codeSpace()))); + properties.set(IdentifiedObject::IDENTIFIERS_KEY, + identifiers); + } + } + } + } } auto ellipsoid = buildEllipsoid(ellipsoidNode); diff --git a/test/unit/test_c_api.cpp b/test/unit/test_c_api.cpp index 59ba12ca..855ebf36 100644 --- a/test/unit/test_c_api.cpp +++ b/test/unit/test_c_api.cpp @@ -292,6 +292,25 @@ TEST_F(CApi, proj_obj_as_wkt) { // --------------------------------------------------------------------------- +TEST_F(CApi, proj_obj_as_wkt_check_db_use) { + auto obj = proj_obj_create_from_wkt( + m_ctxt, "GEOGCS[\"AGD66\",DATUM[\"Australian_Geodetic_Datum_1966\"," + "SPHEROID[\"Australian National Spheroid\",6378160,298.25]]," + "PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]]", + nullptr); + ObjectKeeper keeper(obj); + ASSERT_NE(obj, nullptr); + + auto wkt = proj_obj_as_wkt(m_ctxt, obj, PJ_WKT1_ESRI, nullptr); + EXPECT_EQ(std::string(wkt), + "GEOGCS[\"GCS_Australian_1966\",DATUM[\"D_Australian_1966\"," + "SPHEROID[\"Australian\",6378160.0,298.25]]," + "PRIMEM[\"Greenwich\",0.0]," + "UNIT[\"Degree\",0.0174532925199433]]"); +} + +// --------------------------------------------------------------------------- + TEST_F(CApi, proj_obj_as_wkt_incompatible_WKT1) { auto obj = proj_obj_create_from_wkt( m_ctxt, @@ -1547,6 +1566,44 @@ TEST_F(CApi, proj_obj_create_geographic_crs) { ObjectKeeper keeper(obj); ASSERT_NE(obj, nullptr); } + + // Datum with GDAL_WKT1 spelling: special case of WGS_1984 + { + auto obj = proj_obj_create_geographic_crs( + m_ctxt, "WGS 84", "WGS_1984", "WGS 84", 6378137, 298.257223563, + "Greenwich", 0.0, "Degree", 0.0174532925199433, cs); + ObjectKeeper keeper(obj); + ASSERT_NE(obj, nullptr); + + auto objRef = proj_obj_create_from_user_input( + m_ctxt, + GeographicCRS::EPSG_4326->exportToWKT(WKTFormatter::create().get()) + .c_str(), + nullptr); + ObjectKeeper keeperobjRef(objRef); + EXPECT_NE(objRef, nullptr); + + EXPECT_TRUE(proj_obj_is_equivalent_to(obj, objRef, PJ_COMP_EQUIVALENT)); + } + + // Datum with GDAL_WKT1 spelling: database query + { + auto obj = proj_obj_create_geographic_crs( + m_ctxt, "NAD83", "North_American_Datum_1983", "GRS 1980", 6378137, + 298.257222101, "Greenwich", 0.0, "Degree", 0.0174532925199433, cs); + ObjectKeeper keeper(obj); + ASSERT_NE(obj, nullptr); + + auto objRef = proj_obj_create_from_user_input( + m_ctxt, + GeographicCRS::EPSG_4269->exportToWKT(WKTFormatter::create().get()) + .c_str(), + nullptr); + ObjectKeeper keeperobjRef(objRef); + EXPECT_NE(objRef, nullptr); + + EXPECT_TRUE(proj_obj_is_equivalent_to(obj, objRef, PJ_COMP_EQUIVALENT)); + } } // --------------------------------------------------------------------------- diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp index 0cf36766..6a2de028 100644 --- a/test/unit/test_io.cpp +++ b/test/unit/test_io.cpp @@ -401,6 +401,33 @@ TEST(wkt_parse, wkt1_EPSG_4326) { // --------------------------------------------------------------------------- +TEST(wkt_parse, wkt1_EPSG_4267) { + auto obj = + WKTParser() + .attachDatabaseContext(DatabaseContext::create()) + .createFromWKT( + "GEOGCS[\"NAD27\"," + " DATUM[\"North_American_Datum_1927\"," + " SPHEROID[\"Clarke 1866\",6378206.4,294.978698213898," + " AUTHORITY[\"EPSG\",\"7008\"]]," + " AUTHORITY[\"EPSG\",\"6267\"]]," + " PRIMEM[\"Greenwich\",0," + " AUTHORITY[\"EPSG\",\"8901\"]]," + " UNIT[\"degree\",0.0174532925199433," + " AUTHORITY[\"EPSG\",\"9122\"]]," + " AUTHORITY[\"EPSG\",\"4267\"]]"); + auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj); + ASSERT_TRUE(crs != nullptr); + + auto datum = crs->datum(); + ASSERT_EQ(datum->identifiers().size(), 1); + EXPECT_EQ(datum->identifiers()[0]->code(), "6267"); + EXPECT_EQ(*(datum->identifiers()[0]->codeSpace()), "EPSG"); + EXPECT_EQ(datum->nameStr(), "North American Datum 1927"); +} + +// --------------------------------------------------------------------------- + TEST(wkt_parse, wkt1_EPSG_4807_grad_mess) { auto obj = WKTParser().createFromWKT( "GEOGCS[\"NTF (Paris)\",\n" |
