aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2021-08-19 10:11:47 +0200
committergithub-actions[bot] <github-actions[bot]@users.noreply.github.com>2021-08-19 08:34:01 +0000
commitdff8e5df3f5e80a88590fc87aca17b39008289cc (patch)
tree0a5e285a6383537a8318a5d2bc01a36ab8ac5e2a /src
parentb8ab9150834257bcb197ca73b5a81eef7becdbdc (diff)
downloadPROJ-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.cpp53
-rw-r--r--src/iso19111/io.cpp54
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);
}
// ---------------------------------------------------------------------------