aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/proj/internal/coordinateoperation_constants.hpp5
-rw-r--r--src/iso19111/io.cpp57
-rw-r--r--test/unit/test_io.cpp36
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);