diff options
| -rw-r--r-- | include/proj/internal/coordinateoperation_constants.hpp | 5 | ||||
| -rw-r--r-- | src/iso19111/io.cpp | 57 | ||||
| -rw-r--r-- | test/unit/test_io.cpp | 36 |
3 files changed, 87 insertions, 11 deletions
diff --git a/include/proj/internal/coordinateoperation_constants.hpp b/include/proj/internal/coordinateoperation_constants.hpp index 53213424..79b47a6a 100644 --- a/include/proj/internal/coordinateoperation_constants.hpp +++ b/include/proj/internal/coordinateoperation_constants.hpp @@ -560,6 +560,11 @@ static const MethodMapping projectionMethodMappings[] = { EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP, "Lambert_Conformal_Conic_2SP", "lcc", nullptr, paramsLCC2SP}, + // Oracle WKT + {EPSG_NAME_METHOD_LAMBERT_CONIC_CONFORMAL_2SP, + EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP, "Lambert Conformal Conic", + "lcc", nullptr, paramsLCC2SP}, + {EPSG_NAME_METHOD_LAMBERT_CONIC_CONFORMAL_2SP_MICHIGAN, EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP_MICHIGAN, nullptr, // no mapping to WKT1_GDAL diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index 57f358df..6680ab00 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -1535,6 +1535,19 @@ PropertyMap &WKTParser::Private::buildProperties(const WKTNodeNNPtr &node, std::string codeFromAlias; const auto *nodeP = node->GP(); const auto &nodeChildren = nodeP->children(); + + auto identifiers = ArrayOfBaseObject::create(); + for (const auto &subNode : nodeChildren) { + const auto &subNodeName(subNode->GP()->value()); + if (ci_equal(subNodeName, WKTConstants::ID) || + ci_equal(subNodeName, WKTConstants::AUTHORITY)) { + auto id = buildId(subNode, true, removeInverseOf); + if (id) { + identifiers->add(NN_NO_CHECK(id)); + } + } + } + if (!nodeChildren.empty()) { const auto &nodeName(nodeP->value()); auto name(stripQuotes(nodeChildren[0])); @@ -1547,6 +1560,26 @@ PropertyMap &WKTParser::Private::buildProperties(const WKTNodeNNPtr &node, properties->set(common::IdentifiedObject::DEPRECATED_KEY, true); } + // Oracle WKT can contain names like + // "Reseau Geodesique Francais 1993 (EPSG ID 6171)" + // for WKT attributes to the auth_name = "IGN - Paris" + // Strip that suffix from the name and assign a true EPSG code to the + // object + if (identifiers->empty()) { + const auto pos = name.find(" (EPSG ID "); + if (pos != std::string::npos && name.back() == ')') { + const auto code = + name.substr(pos + strlen(" (EPSG ID "), + name.size() - 1 - pos - strlen(" (EPSG ID ")); + name.resize(pos); + + PropertyMap propertiesId; + propertiesId.set(Identifier::CODESPACE_KEY, Identifier::EPSG); + propertiesId.set(Identifier::AUTHORITY_KEY, Identifier::EPSG); + identifiers->add(Identifier::create(code, propertiesId)); + } + } + const char *tableNameForAlias = nullptr; if (ci_equal(nodeName, WKTConstants::GEOGCS)) { if (starts_with(name, "GCS_")) { @@ -1589,17 +1622,6 @@ PropertyMap &WKTParser::Private::buildProperties(const WKTNodeNNPtr &node, properties->set(IdentifiedObject::NAME_KEY, name); } - auto identifiers = ArrayOfBaseObject::create(); - for (const auto &subNode : nodeChildren) { - const auto &subNodeName(subNode->GP()->value()); - if (ci_equal(subNodeName, WKTConstants::ID) || - ci_equal(subNodeName, WKTConstants::AUTHORITY)) { - auto id = buildId(subNode, true, removeInverseOf); - if (id) { - identifiers->add(NN_NO_CHECK(id)); - } - } - } if (identifiers->empty() && !authNameFromAlias.empty()) { identifiers->add(Identifier::create( codeFromAlias, @@ -3606,6 +3628,7 @@ ConversionNNPtr WKTParser::Private::buildProjectionStandard( } foundParameters.resize(countParams); } + bool found2ndStdParallel = false; for (const auto &childNode : projCRSNode->GP()->children()) { if (ci_equal(childNode->GP()->value(), WKTConstants::PARAMETER)) { const auto &childNodeChildren = childNode->GP()->children(); @@ -3658,6 +3681,10 @@ ConversionNNPtr WKTParser::Private::buildProjectionStandard( propertiesParameter.set(Identifier::CODESPACE_KEY, Identifier::EPSG); } + if (paramMapping->epsg_code == + EPSG_CODE_PARAMETER_LATITUDE_2ND_STD_PARALLEL) { + found2ndStdParallel = true; + } } propertiesParameter.set(IdentifiedObject::NAME_KEY, parameterName); parameters.push_back( @@ -3674,6 +3701,14 @@ ConversionNNPtr WKTParser::Private::buildProjectionStandard( } } + // Oracle WKT: make sure that the 2nd std parallel parameter is found to + // select the LCC_2SP mapping + if (metadata::Identifier::isEquivalentName(wkt1ProjectionName.c_str(), + "Lambert Conformal Conic") && + !found2ndStdParallel) { + propertiesMethod.set(IdentifiedObject::NAME_KEY, wkt1ProjectionName); + } + // Add back important parameters that should normally be present, but // are sometimes missing. Currently we only deal with Scale factor at // natural origin. This is to avoid a default value of 0 to slip in later. diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp index 433e3e6d..f2464e5c 100644 --- a/test/unit/test_io.cpp +++ b/test/unit/test_io.cpp @@ -5910,6 +5910,42 @@ TEST(wkt_parse, wkt1_esri_gauss_kruger) { // --------------------------------------------------------------------------- +TEST(wkt_parse, wkt1_oracle) { + // WKT from mdsys.cs_srs Oracle table + auto wkt = "PROJCS[\"RGF93 / Lambert-93\", GEOGCS [ \"RGF93\", " + "DATUM [\"Reseau Geodesique Francais 1993 (EPSG ID 6171)\", " + "SPHEROID [\"GRS 1980 (EPSG ID 7019)\", 6378137.0, " + "298.257222101]], PRIMEM [ \"Greenwich\", 0.000000000 ], " + "UNIT [\"Decimal Degree\", 0.0174532925199433]], " + "PROJECTION [\"Lambert Conformal Conic\"], " + "PARAMETER [\"Latitude_Of_Origin\", 46.5], " + "PARAMETER [\"Central_Meridian\", 3.0], " + "PARAMETER [\"Standard_Parallel_1\", 49.0], " + "PARAMETER [\"Standard_Parallel_2\", 44.0], " + "PARAMETER [\"False_Easting\", 700000.0], " + "PARAMETER [\"False_Northing\", 6600000.0], " + "UNIT [\"Meter\", 1.0]]"; + + auto dbContext = DatabaseContext::create(); + auto obj = WKTParser().attachDatabaseContext(dbContext).createFromWKT(wkt); + auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj); + ASSERT_TRUE(crs != nullptr); + + EXPECT_EQ(crs->baseCRS()->datum()->nameStr(), + "Reseau Geodesique Francais 1993"); + EXPECT_EQ(crs->baseCRS()->datum()->getEPSGCode(), 6171); + EXPECT_EQ(crs->derivingConversion()->method()->nameStr(), + "Lambert Conic Conformal (2SP)"); + + auto factoryAll = AuthorityFactory::create(dbContext, std::string()); + auto res = crs->identify(factoryAll); + ASSERT_GE(res.size(), 1U); + EXPECT_EQ(res.front().first->getEPSGCode(), 2154); + EXPECT_EQ(res.front().second, 100); +} + +// --------------------------------------------------------------------------- + TEST(wkt_parse, invalid) { EXPECT_THROW(WKTParser().createFromWKT(""), ParsingException); EXPECT_THROW(WKTParser().createFromWKT("A"), ParsingException); |
