diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2021-10-05 19:21:05 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-10-05 19:21:05 +0200 |
| commit | c50ba1b1a7ecde946544c03ab0951727dd87264d (patch) | |
| tree | 2be4d809980ba1450d6e8a2af29c4e9822c9f2d1 /src/iso19111/io.cpp | |
| parent | 6b58adb4b7396b9c2aff2fa26aae2340d5a62d21 (diff) | |
| parent | 5d6bdadfca419c1d54d455e240743791e6cea44e (diff) | |
| download | PROJ-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.cpp | 205 |
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(); } // --------------------------------------------------------------------------- |
