aboutsummaryrefslogtreecommitdiff
path: root/src/iso19111/io.cpp
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2021-10-05 19:21:05 +0200
committerGitHub <noreply@github.com>2021-10-05 19:21:05 +0200
commitc50ba1b1a7ecde946544c03ab0951727dd87264d (patch)
tree2be4d809980ba1450d6e8a2af29c4e9822c9f2d1 /src/iso19111/io.cpp
parent6b58adb4b7396b9c2aff2fa26aae2340d5a62d21 (diff)
parent5d6bdadfca419c1d54d455e240743791e6cea44e (diff)
downloadPROJ-c50ba1b1a7ecde946544c03ab0951727dd87264d.tar.gz
PROJ-c50ba1b1a7ecde946544c03ab0951727dd87264d.zip
Merge pull request #2876 from rouault/iau
Add IAU_2015 CRS definitions
Diffstat (limited to 'src/iso19111/io.cpp')
-rw-r--r--src/iso19111/io.cpp205
1 files changed, 153 insertions, 52 deletions
diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp
index b317213a..1f193559 100644
--- a/src/iso19111/io.cpp
+++ b/src/iso19111/io.cpp
@@ -1518,6 +1518,23 @@ IdentifierPtr WKTParser::Private::buildId(const WKTNodeNNPtr &node,
codeSpace = codeSpace.substr(strlen("INVERSE("));
codeSpace.resize(codeSpace.size() - 1);
}
+
+ std::string version;
+ if (nodeChildren.size() >= 3 &&
+ nodeChildren[2]->GP()->childrenSize() == 0) {
+ version = stripQuotes(nodeChildren[2]);
+ }
+
+ // IAU + 2015 -> IAU_2015
+ if (dbContext_ && !version.empty()) {
+ std::string codeSpaceOut;
+ if (dbContext_->getVersionedAuthority(codeSpace, version,
+ codeSpaceOut)) {
+ codeSpace = codeSpaceOut;
+ version.clear();
+ }
+ }
+
auto code = stripQuotes(nodeChildren[1]);
auto &citationNode = nodeP->lookForChild(WKTConstants::CITATION);
auto &uriNode = nodeP->lookForChild(WKTConstants::URI);
@@ -1542,9 +1559,7 @@ IdentifierPtr WKTParser::Private::buildId(const WKTNodeNNPtr &node,
stripQuotes(uriNodeP->children()[0]));
}
}
- if (nodeChildren.size() >= 3 &&
- nodeChildren[2]->GP()->childrenSize() == 0) {
- auto version = stripQuotes(nodeChildren[2]);
+ if (!version.empty()) {
propertiesId.set(Identifier::VERSION_KEY, version);
}
return Identifier::create(code, propertiesId);
@@ -5381,24 +5396,10 @@ IdentifierNNPtr JSONParser::buildId(const json &j, bool removeInverseOf) {
codeSpace = codeSpace.substr(strlen("INVERSE("));
codeSpace.resize(codeSpace.size() - 1);
}
- propertiesId.set(metadata::Identifier::CODESPACE_KEY, codeSpace);
- propertiesId.set(metadata::Identifier::AUTHORITY_KEY, codeSpace);
- if (!j.contains("code")) {
- throw ParsingException("Missing \"code\" key");
- }
- std::string code;
- auto codeJ = j["code"];
- if (codeJ.is_string()) {
- code = codeJ.get<std::string>();
- } else if (codeJ.is_number_integer()) {
- code = internal::toString(codeJ.get<int>());
- } else {
- throw ParsingException("Unexpected type for value of \"code\"");
- }
+ std::string version;
if (j.contains("version")) {
auto versionJ = j["version"];
- std::string version;
if (versionJ.is_string()) {
version = versionJ.get<std::string>();
} else if (versionJ.is_number()) {
@@ -5413,6 +5414,34 @@ IdentifierNNPtr JSONParser::buildId(const json &j, bool removeInverseOf) {
} else {
throw ParsingException("Unexpected type for value of \"version\"");
}
+ }
+
+ // IAU + 2015 -> IAU_2015
+ if (dbContext_ && !version.empty()) {
+ std::string codeSpaceOut;
+ if (dbContext_->getVersionedAuthority(codeSpace, version,
+ codeSpaceOut)) {
+ codeSpace = codeSpaceOut;
+ version.clear();
+ }
+ }
+
+ propertiesId.set(metadata::Identifier::CODESPACE_KEY, codeSpace);
+ propertiesId.set(metadata::Identifier::AUTHORITY_KEY, codeSpace);
+ if (!j.contains("code")) {
+ throw ParsingException("Missing \"code\" key");
+ }
+ std::string code;
+ auto codeJ = j["code"];
+ if (codeJ.is_string()) {
+ code = codeJ.get<std::string>();
+ } else if (codeJ.is_number_integer()) {
+ code = internal::toString(codeJ.get<int>());
+ } else {
+ throw ParsingException("Unexpected type for value of \"code\"");
+ }
+
+ if (!version.empty()) {
propertiesId.set(Identifier::VERSION_KEY, version);
}
@@ -6392,6 +6421,61 @@ static CRSNNPtr importFromWMSAUTO(const std::string &text) {
// ---------------------------------------------------------------------------
+static BaseObjectNNPtr createFromURNPart(const DatabaseContextPtr &dbContext,
+ const std::string &type,
+ const std::string &authName,
+ const std::string &version,
+ const std::string &code) {
+ if (!dbContext) {
+ throw ParsingException("no database context specified");
+ }
+ try {
+ auto factory =
+ AuthorityFactory::create(NN_NO_CHECK(dbContext), authName);
+ if (type == "crs") {
+ return factory->createCoordinateReferenceSystem(code);
+ }
+ if (type == "coordinateOperation") {
+ return factory->createCoordinateOperation(code, true);
+ }
+ if (type == "datum") {
+ return factory->createDatum(code);
+ }
+ if (type == "ensemble") {
+ return factory->createDatumEnsemble(code);
+ }
+ if (type == "ellipsoid") {
+ return factory->createEllipsoid(code);
+ }
+ if (type == "meridian") {
+ return factory->createPrimeMeridian(code);
+ }
+ throw ParsingException(concat("unhandled object type: ", type));
+ } catch (...) {
+ if (version.empty()) {
+ const auto authoritiesFromAuthName =
+ dbContext->getVersionedAuthoritiesFromName(authName);
+ for (const auto &authNameVersioned : authoritiesFromAuthName) {
+ try {
+ return createFromURNPart(dbContext, type, authNameVersioned,
+ std::string(), code);
+ } catch (...) {
+ }
+ }
+ throw;
+ }
+ std::string authNameWithVersion;
+ if (!dbContext->getVersionedAuthority(authName, version,
+ authNameWithVersion)) {
+ throw;
+ }
+ return createFromURNPart(dbContext, type, authNameWithVersion,
+ std::string(), code);
+ }
+}
+
+// ---------------------------------------------------------------------------
+
static BaseObjectNNPtr createFromUserInput(const std::string &text,
const DatabaseContextPtr &dbContext,
bool usePROJ4InitRules,
@@ -6481,8 +6565,19 @@ static BaseObjectNNPtr createFromUserInput(const std::string &text,
return factory->createCoordinateReferenceSystem(code);
}
- const auto authorities = dbContextNNPtr->getAuthorities();
- for (const auto &authCandidate : authorities) {
+ const auto authoritiesFromAuthName =
+ dbContextNNPtr->getVersionedAuthoritiesFromName(authName);
+ for (const auto &authNameVersioned : authoritiesFromAuthName) {
+ factory =
+ AuthorityFactory::create(dbContextNNPtr, authNameVersioned);
+ try {
+ return factory->createCoordinateReferenceSystem(code);
+ } catch (...) {
+ }
+ }
+
+ const auto allAuthorities = dbContextNNPtr->getAuthorities();
+ for (const auto &authCandidate : allAuthorities) {
if (ci_equal(authCandidate, authName)) {
factory =
AuthorityFactory::create(dbContextNNPtr, authCandidate);
@@ -6740,42 +6835,14 @@ static BaseObjectNNPtr createFromUserInput(const std::string &text,
return ConcatenatedOperation::createComputeMetadata(components, true);
}
- const auto createFromURNPart =
- [&dbContext](const std::string &type, const std::string &authName,
- const std::string &code) -> BaseObjectNNPtr {
- if (!dbContext) {
- throw ParsingException("no database context specified");
- }
- auto factory =
- AuthorityFactory::create(NN_NO_CHECK(dbContext), authName);
- if (type == "crs") {
- return factory->createCoordinateReferenceSystem(code);
- }
- if (type == "coordinateOperation") {
- return factory->createCoordinateOperation(code, true);
- }
- if (type == "datum") {
- return factory->createDatum(code);
- }
- if (type == "ensemble") {
- return factory->createDatumEnsemble(code);
- }
- if (type == "ellipsoid") {
- return factory->createEllipsoid(code);
- }
- if (type == "meridian") {
- return factory->createPrimeMeridian(code);
- }
- throw ParsingException(concat("unhandled object type: ", type));
- };
-
// urn:ogc:def:crs:EPSG::4326
if (tokens.size() == 7 && tolower(tokens[0]) == "urn") {
const auto type = tokens[3] == "CRS" ? "crs" : tokens[3];
const auto &authName = tokens[4];
+ const auto &version = tokens[5];
const auto &code = tokens[6];
- return createFromURNPart(type, authName, code);
+ return createFromURNPart(dbContext, type, authName, version, code);
}
// urn:ogc:def:crs:OGC::AUTO42001:-117:33
@@ -6790,8 +6857,9 @@ static BaseObjectNNPtr createFromUserInput(const std::string &text,
if (tokens.size() == 6 && tokens[0] == "urn" && tokens[2] != "def") {
const auto &type = tokens[2];
const auto &authName = tokens[3];
+ const auto &version = tokens[4];
const auto &code = tokens[5];
- return createFromURNPart(type, authName, code);
+ return createFromURNPart(dbContext, type, authName, version, code);
}
// Legacy urn:x-ogc:def:crs:EPSG:4326 (note the missing version)
@@ -6799,7 +6867,8 @@ static BaseObjectNNPtr createFromUserInput(const std::string &text,
const auto &type = tokens[3];
const auto &authName = tokens[4];
const auto &code = tokens[5];
- return createFromURNPart(type, authName, code);
+ return createFromURNPart(dbContext, type, authName, std::string(),
+ code);
}
if (dbContext) {
@@ -7799,6 +7868,32 @@ const std::string &PROJStringFormatter::toString() const {
continue;
}
+ // axisswap order=2,-1 followed by axisswap order=-2,1 is a no-op
+ if (curStep.name == "axisswap" && prevStep.name == "axisswap" &&
+ curStepParamCount == 1 && prevStepParamCount == 1 &&
+ !prevStep.inverted &&
+ prevStep.paramValues[0].equals("order", "2,-1") &&
+ !curStep.inverted &&
+ curStep.paramValues[0].equals("order", "-2,1")) {
+ deletePrevAndCurIter();
+ continue;
+ }
+
+ // axisswap order=2,-1 followed by axisswap order=1,-2 is
+ // equivalent to axisswap order=2,1
+ if (curStep.name == "axisswap" && prevStep.name == "axisswap" &&
+ curStepParamCount == 1 && prevStepParamCount == 1 &&
+ !prevStep.inverted &&
+ prevStep.paramValues[0].equals("order", "2,-1") &&
+ !curStep.inverted &&
+ curStep.paramValues[0].equals("order", "1,-2")) {
+ prevStep.inverted = false;
+ prevStep.paramValues[0] = Step::KeyValue("order", "2,1");
+ // Delete this iter
+ iterCur = steps.erase(iterCur);
+ continue;
+ }
+
// axisswap order=2,1 followed by axisswap order=2,-1 is
// equivalent to axisswap order=1,-2
// Same for axisswap order=-2,1 followed by axisswap order=2,1
@@ -10784,6 +10879,12 @@ CPLJSonStreamingWriter *JSONFormatter::writer() const { return &(d->writer_); }
// ---------------------------------------------------------------------------
+const DatabaseContextPtr &JSONFormatter::databaseContext() const {
+ return d->dbContext_;
+}
+
+// ---------------------------------------------------------------------------
+
bool JSONFormatter::outputId() const { return d->outputIdStack_.back(); }
// ---------------------------------------------------------------------------