diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2021-08-19 10:11:47 +0200 |
|---|---|---|
| committer | github-actions[bot] <github-actions[bot]@users.noreply.github.com> | 2021-08-19 08:34:01 +0000 |
| commit | dff8e5df3f5e80a88590fc87aca17b39008289cc (patch) | |
| tree | 0a5e285a6383537a8318a5d2bc01a36ab8ac5e2a /src | |
| parent | b8ab9150834257bcb197ca73b5a81eef7becdbdc (diff) | |
| download | PROJ-dff8e5df3f5e80a88590fc87aca17b39008289cc.tar.gz PROJ-dff8e5df3f5e80a88590fc87aca17b39008289cc.zip | |
Merge pull request #2814 from rouault/fix_2813
BoundCRS: accept importing/exporting in WKT2 and PROJJSON the scope/area/extent/id attributes (fixes #2813)
Diffstat (limited to 'src')
| -rw-r--r-- | src/iso19111/crs.cpp | 53 | ||||
| -rw-r--r-- | src/iso19111/io.cpp | 54 |
2 files changed, 83 insertions, 24 deletions
diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp index 942e2d43..3e825ff0 100644 --- a/src/iso19111/crs.cpp +++ b/src/iso19111/crs.cpp @@ -1217,7 +1217,7 @@ CRSNNPtr CRS::promoteTo3D(const std::string &newName, try { transf->getTOWGS84Parameters(); return BoundCRS::create( - base3DCRS, + createProperties(), base3DCRS, boundCRS->hubCRS()->promoteTo3D(std::string(), dbContext), transf->promoteTo3D(std::string(), dbContext)); } catch (const io::FormattingException &) { @@ -5294,27 +5294,50 @@ BoundCRS::transformation() PROJ_PURE_DEFN { /** \brief Instantiate a BoundCRS from a base CRS, a hub CRS and a * transformation. * + * @param properties See \ref general_properties. * @param baseCRSIn base CRS. * @param hubCRSIn hub CRS. * @param transformationIn transformation from base CRS to hub CRS. * @return new BoundCRS. + * @since PROJ 8.2 */ BoundCRSNNPtr -BoundCRS::create(const CRSNNPtr &baseCRSIn, const CRSNNPtr &hubCRSIn, +BoundCRS::create(const util::PropertyMap &properties, const CRSNNPtr &baseCRSIn, + const CRSNNPtr &hubCRSIn, const operation::TransformationNNPtr &transformationIn) { auto crs = BoundCRS::nn_make_shared<BoundCRS>(baseCRSIn, hubCRSIn, transformationIn); crs->assignSelf(crs); const auto &l_name = baseCRSIn->nameStr(); - if (!l_name.empty()) { - crs->setProperties(util::PropertyMap().set( - common::IdentifiedObject::NAME_KEY, l_name)); + if (properties.get(common::IdentifiedObject::NAME_KEY) == nullptr && + !l_name.empty()) { + auto newProperties(properties); + newProperties.set(common::IdentifiedObject::NAME_KEY, l_name); + crs->setProperties(newProperties); + } else { + crs->setProperties(properties); } return crs; } // --------------------------------------------------------------------------- +/** \brief Instantiate a BoundCRS from a base CRS, a hub CRS and a + * transformation. + * + * @param baseCRSIn base CRS. + * @param hubCRSIn hub CRS. + * @param transformationIn transformation from base CRS to hub CRS. + * @return new BoundCRS. + */ +BoundCRSNNPtr +BoundCRS::create(const CRSNNPtr &baseCRSIn, const CRSNNPtr &hubCRSIn, + const operation::TransformationNNPtr &transformationIn) { + return create(util::PropertyMap(), baseCRSIn, hubCRSIn, transformationIn); +} + +// --------------------------------------------------------------------------- + /** \brief Instantiate a BoundCRS from a base CRS and TOWGS84 parameters * * @param baseCRSIn base CRS. @@ -5415,6 +5438,7 @@ void BoundCRS::_exportToWKT(io::WKTFormatter *formatter) const { formatter->setAbridgedTransformation(true); d->transformation()->_exportToWKT(formatter); formatter->setAbridgedTransformation(false); + ObjectUsage::baseExportToWKT(formatter); formatter->endNode(); } else { @@ -5455,8 +5479,21 @@ void BoundCRS::_exportToJSON( io::JSONFormatter *formatter) const // throw(io::FormattingException) { auto writer = formatter->writer(); - auto objectContext( - formatter->MakeObjectContext("BoundCRS", !identifiers().empty())); + const auto &l_name = nameStr(); + if ((formatter->outputUsage(true) && !domains().empty()) || + (formatter->outputId() && !identifiers().empty()) || + !remarks().empty() || + (!l_name.empty() && l_name != d->baseCRS()->nameStr())) { + // Only upgrades to v0.3 schema if needed + formatter->setSchema(io::JSONFormatter::PROJJSON_v0_3); + } + + auto objectContext(formatter->MakeObjectContext("BoundCRS", false)); + + if (!l_name.empty() && l_name != d->baseCRS()->nameStr()) { + writer->AddObjKey("name"); + writer->Add(l_name); + } writer->AddObjKey("source_crs"); d->baseCRS()->_exportToJSON(formatter); @@ -5469,6 +5506,8 @@ void BoundCRS::_exportToJSON( formatter->setAbridgedTransformation(true); d->transformation()->_exportToJSON(formatter); formatter->setAbridgedTransformation(false); + + ObjectUsage::baseExportToJSON(formatter); } //! @endcond diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index ccbb0ffe..867e08ed 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -89,10 +89,6 @@ using json = nlohmann::json; //! @cond Doxygen_Suppress static const std::string emptyString{}; - -// If changing that value, change it in data/projjson.schema.json as well -#define PROJJSON_CURRENT_VERSION \ - "https://proj.org/schemas/v0.2/projjson.schema.json" //! @endcond #if 0 @@ -109,6 +105,18 @@ template<> nn<std::unique_ptr<NS_PROJ::io::WKTNode, std::default_delete<NS_PROJ: NS_PROJ_START namespace io { +//! @cond Doxygen_Suppress +const char *JSONFormatter::PROJJSON_v0_2 = + "https://proj.org/schemas/v0.2/projjson.schema.json"; + +const char *JSONFormatter::PROJJSON_v0_3 = + "https://proj.org/schemas/v0.3/projjson.schema.json"; + +// v0.2 is our base version. We only upgrade to 0.3 for usage node in BoundCRS +#define PROJJSON_DEFAULT_VERSION JSONFormatter::PROJJSON_v0_2 + +//! @endcond + // --------------------------------------------------------------------------- //! @cond Doxygen_Suppress @@ -4593,8 +4601,8 @@ BoundCRSNNPtr WKTParser::Private::buildBoundCRS(const WKTNodeNNPtr &node) { NN_NO_CHECK(targetCRS), nullptr, buildProperties(methodNode), parameters, values, std::vector<PositionalAccuracyNNPtr>()); - return BoundCRS::create(NN_NO_CHECK(sourceCRS), NN_NO_CHECK(targetCRS), - transformation); + return BoundCRS::create(buildProperties(node), NN_NO_CHECK(sourceCRS), + NN_NO_CHECK(targetCRS), transformation); } // --------------------------------------------------------------------------- @@ -5057,7 +5065,8 @@ class JSONParser { IdentifierNNPtr buildId(const json &j, bool removeInverseOf); static ObjectDomainPtr buildObjectDomain(const json &j); - PropertyMap buildProperties(const json &j, bool removeInverseOf = false); + PropertyMap buildProperties(const json &j, bool removeInverseOf = false, + bool nameRequired = true); GeographicCRSNNPtr buildGeographicCRS(const json &j); GeodeticCRSNNPtr buildGeodeticCRS(const json &j); @@ -5358,13 +5367,17 @@ IdentifierNNPtr JSONParser::buildId(const json &j, bool removeInverseOf) { // --------------------------------------------------------------------------- -PropertyMap JSONParser::buildProperties(const json &j, bool removeInverseOf) { +PropertyMap JSONParser::buildProperties(const json &j, bool removeInverseOf, + bool nameRequired) { PropertyMap map; - std::string name(getName(j)); - if (removeInverseOf && starts_with(name, "Inverse of ")) { - name = name.substr(strlen("Inverse of ")); + + if (j.contains("name") || nameRequired) { + std::string name(getName(j)); + if (removeInverseOf && starts_with(name, "Inverse of ")) { + name = name.substr(strlen("Inverse of ")); + } + map.set(IdentifiedObject::NAME_KEY, name); } - map.set(IdentifiedObject::NAME_KEY, name); if (j.contains("ids")) { auto idsJ = getArray(j, "ids"); @@ -5782,7 +5795,10 @@ BoundCRSNNPtr JSONParser::buildBoundCRS(const json &j) { nullptr, buildProperties(methodJ), parameters, values, std::vector<PositionalAccuracyNNPtr>()); - return BoundCRS::create(sourceCRS, targetCRS, transformation); + return BoundCRS::create(buildProperties(j, + /* removeInverseOf= */ false, + /* nameRequired=*/false), + sourceCRS, targetCRS, transformation); } // --------------------------------------------------------------------------- @@ -10529,7 +10545,7 @@ struct JSONFormatter::Private { bool allowIDInImmediateChild_ = false; bool omitTypeInImmediateChild_ = false; bool abridgedTransformation_ = false; - std::string schema_ = PROJJSON_CURRENT_VERSION; + std::string schema_ = PROJJSON_DEFAULT_VERSION; std::string result_{}; @@ -10580,7 +10596,10 @@ JSONFormatter &JSONFormatter::setIndentationWidth(int width) noexcept { * If set to empty string, it will not be written. */ JSONFormatter &JSONFormatter::setSchema(const std::string &schema) noexcept { - d->schema_ = schema; + // Upgrade only to v0.3 if the default was v0.2 + if (schema != PROJJSON_v0_3 || d->schema_ == PROJJSON_v0_2) { + d->schema_ = schema; + } return *this; } @@ -10604,8 +10623,9 @@ bool JSONFormatter::outputId() const { return d->outputIdStack_.back(); } // --------------------------------------------------------------------------- -bool JSONFormatter::outputUsage() const { - return outputId() && d->outputIdStack_.size() == 2; +bool JSONFormatter::outputUsage(bool calledBeforeObjectContext) const { + return outputId() && + d->outputIdStack_.size() == (calledBeforeObjectContext ? 1U : 2U); } // --------------------------------------------------------------------------- |
