aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2019-08-09 17:10:20 +0200
committerEven Rouault <even.rouault@spatialys.com>2019-08-09 17:41:23 +0200
commitf0d766e45640800412c08a7cb9ab4f8823d88d05 (patch)
tree1973086c9f52043d61fb1a71cbbc1c3a794c3afc /src
parent81bd57dfd8cfae609288643d1b09a4805f1bcded (diff)
downloadPROJ-f0d766e45640800412c08a7cb9ab4f8823d88d05.tar.gz
PROJ-f0d766e45640800412c08a7cb9ab4f8823d88d05.zip
PROJSJON: add import/export of VerticalCRS, CompoundCRS, BoundCRS, Transformation and ConcatenatedOperation
Diffstat (limited to 'src')
-rw-r--r--src/iso19111/coordinateoperation.cpp174
-rw-r--r--src/iso19111/crs.cpp275
-rw-r--r--src/iso19111/datum.cpp88
-rw-r--r--src/iso19111/io.cpp263
4 files changed, 721 insertions, 79 deletions
diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp
index f4e90fe8..27a22b51 100644
--- a/src/iso19111/coordinateoperation.cpp
+++ b/src/iso19111/coordinateoperation.cpp
@@ -5484,13 +5484,16 @@ void Conversion::_exportToJSON(
formatter->setAllowIDInImmediateChild();
method()->_exportToJSON(formatter);
- writer.AddObjKey("parameters");
- {
- auto parametersContext(writer.MakeArrayContext(false));
- for (const auto &genOpParamvalue : parameterValues()) {
- formatter->setAllowIDInImmediateChild();
- formatter->setOmitTypeInImmediateChild();
- genOpParamvalue->_exportToJSON(formatter);
+ const auto &l_parameterValues = parameterValues();
+ if (!l_parameterValues.empty()) {
+ writer.AddObjKey("parameters");
+ {
+ auto parametersContext(writer.MakeArrayContext(false));
+ for (const auto &genOpParamvalue : l_parameterValues) {
+ formatter->setAllowIDInImmediateChild();
+ formatter->setOmitTypeInImmediateChild();
+ genOpParamvalue->_exportToJSON(formatter);
+ }
}
}
@@ -7862,6 +7865,76 @@ void Transformation::_exportToWKT(io::WKTFormatter *formatter) const {
// ---------------------------------------------------------------------------
+//! @cond Doxygen_Suppress
+void Transformation::_exportToJSON(
+ io::JSONFormatter *formatter) const // throw(FormattingException)
+{
+ auto &writer = formatter->writer();
+ auto objectContext(formatter->MakeObjectContext(
+ formatter->abridgedTransformation() ? "AbridgedTransformation"
+ : "Transformation",
+ !identifiers().empty()));
+
+ writer.AddObjKey("name");
+ auto l_name = nameStr();
+ if (l_name.empty()) {
+ writer.Add("unnamed");
+ } else {
+ writer.Add(l_name);
+ }
+
+ if (!formatter->abridgedTransformation()) {
+ writer.AddObjKey("source_crs");
+ formatter->setAllowIDInImmediateChild();
+ sourceCRS()->_exportToJSON(formatter);
+
+ writer.AddObjKey("target_crs");
+ formatter->setAllowIDInImmediateChild();
+ targetCRS()->_exportToJSON(formatter);
+
+ const auto &l_interpolationCRS = interpolationCRS();
+ if (l_interpolationCRS) {
+ writer.AddObjKey("interpolation_crs");
+ formatter->setAllowIDInImmediateChild();
+ l_interpolationCRS->_exportToJSON(formatter);
+ }
+ }
+
+ writer.AddObjKey("method");
+ formatter->setOmitTypeInImmediateChild();
+ formatter->setAllowIDInImmediateChild();
+ method()->_exportToJSON(formatter);
+
+ writer.AddObjKey("parameters");
+ {
+ auto parametersContext(writer.MakeArrayContext(false));
+ for (const auto &genOpParamvalue : parameterValues()) {
+ formatter->setAllowIDInImmediateChild();
+ formatter->setOmitTypeInImmediateChild();
+ genOpParamvalue->_exportToJSON(formatter);
+ }
+ }
+
+ if (!formatter->abridgedTransformation()) {
+ if (!coordinateOperationAccuracies().empty()) {
+ writer.AddObjKey("accuracy");
+ writer.Add(coordinateOperationAccuracies()[0]->value());
+ }
+ }
+
+ if (formatter->abridgedTransformation()) {
+ if (formatter->outputId()) {
+ formatID(formatter);
+ }
+ } else {
+ ObjectUsage::baseExportToJSON(formatter);
+ }
+}
+
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
static void exportSourceCRSAndTargetCRSToWKT(const CoordinateOperation *co,
io::WKTFormatter *formatter) {
auto l_sourceCRS = co->sourceCRS();
@@ -9678,6 +9751,46 @@ void ConcatenatedOperation::_exportToWKT(io::WKTFormatter *formatter) const {
// ---------------------------------------------------------------------------
//! @cond Doxygen_Suppress
+void ConcatenatedOperation::_exportToJSON(
+ io::JSONFormatter *formatter) const // throw(FormattingException)
+{
+ auto &writer = formatter->writer();
+ auto objectContext(formatter->MakeObjectContext("ConcatenatedOperation",
+ !identifiers().empty()));
+
+ writer.AddObjKey("name");
+ auto l_name = nameStr();
+ if (l_name.empty()) {
+ writer.Add("unnamed");
+ } else {
+ writer.Add(l_name);
+ }
+
+ writer.AddObjKey("source_crs");
+ formatter->setAllowIDInImmediateChild();
+ sourceCRS()->_exportToJSON(formatter);
+
+ writer.AddObjKey("target_crs");
+ formatter->setAllowIDInImmediateChild();
+ targetCRS()->_exportToJSON(formatter);
+
+ writer.AddObjKey("steps");
+ {
+ auto parametersContext(writer.MakeArrayContext(false));
+ for (const auto &operation : operations()) {
+ formatter->setAllowIDInImmediateChild();
+ operation->_exportToJSON(formatter);
+ }
+ }
+
+ ObjectUsage::baseExportToJSON(formatter);
+}
+
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
+//! @cond Doxygen_Suppress
CoordinateOperationNNPtr ConcatenatedOperation::_shallowClone() const {
auto op =
ConcatenatedOperation::nn_make_shared<ConcatenatedOperation>(*this);
@@ -13148,6 +13261,53 @@ void PROJBasedOperation::_exportToWKT(io::WKTFormatter *formatter) const {
// ---------------------------------------------------------------------------
+void PROJBasedOperation::_exportToJSON(
+ io::JSONFormatter *formatter) const // throw(FormattingException)
+{
+ auto &writer = formatter->writer();
+ auto objectContext(formatter->MakeObjectContext(
+ (sourceCRS() && targetCRS()) ? "Transformation" : "Conversion",
+ !identifiers().empty()));
+
+ writer.AddObjKey("name");
+ auto l_name = nameStr();
+ if (l_name.empty()) {
+ writer.Add("unnamed");
+ } else {
+ writer.Add(l_name);
+ }
+
+ if (sourceCRS() && targetCRS()) {
+ writer.AddObjKey("source_crs");
+ formatter->setAllowIDInImmediateChild();
+ sourceCRS()->_exportToJSON(formatter);
+
+ writer.AddObjKey("target_crs");
+ formatter->setAllowIDInImmediateChild();
+ targetCRS()->_exportToJSON(formatter);
+ }
+
+ writer.AddObjKey("method");
+ formatter->setOmitTypeInImmediateChild();
+ formatter->setAllowIDInImmediateChild();
+ method()->_exportToJSON(formatter);
+
+ const auto &l_parameterValues = parameterValues();
+ if (!l_parameterValues.empty()) {
+ writer.AddObjKey("parameters");
+ {
+ auto parametersContext(writer.MakeArrayContext(false));
+ for (const auto &genOpParamvalue : l_parameterValues) {
+ formatter->setAllowIDInImmediateChild();
+ formatter->setOmitTypeInImmediateChild();
+ genOpParamvalue->_exportToJSON(formatter);
+ }
+ }
+ }
+}
+
+// ---------------------------------------------------------------------------
+
void PROJBasedOperation::_exportToPROJString(
io::PROJStringFormatter *formatter) const {
if (projStringExportable_) {
diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp
index 670d0c1a..4f2ab7c6 100644
--- a/src/iso19111/crs.cpp
+++ b/src/iso19111/crs.cpp
@@ -2265,6 +2265,7 @@ void VerticalCRS::_exportToWKT(io::WKTFormatter *formatter) const {
// ---------------------------------------------------------------------------
+//! @cond Doxygen_Suppress
void VerticalCRS::_exportToPROJString(
io::PROJStringFormatter *formatter) const // throw(io::FormattingException)
{
@@ -2284,6 +2285,36 @@ void VerticalCRS::_exportToPROJString(
}
}
}
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
+//! @cond Doxygen_Suppress
+void VerticalCRS::_exportToJSON(
+ io::JSONFormatter *formatter) const // throw(io::FormattingException)
+{
+ auto &writer = formatter->writer();
+ auto objectContext(
+ formatter->MakeObjectContext("VerticalCRS", !identifiers().empty()));
+
+ writer.AddObjKey("name");
+ auto l_name = nameStr();
+ if (l_name.empty()) {
+ writer.Add("unnamed");
+ } else {
+ writer.Add(l_name);
+ }
+
+ writer.AddObjKey("datum");
+ datum()->_exportToJSON(formatter);
+
+ writer.AddObjKey("coordinate_system");
+ formatter->setOmitTypeInImmediateChild();
+ coordinateSystem()->_exportToJSON(formatter);
+
+ ObjectUsage::baseExportToJSON(formatter);
+}
+//! @endcond
// ---------------------------------------------------------------------------
@@ -2650,6 +2681,38 @@ void DerivedCRS::baseExportToWKT(io::WKTFormatter *formatter,
// ---------------------------------------------------------------------------
//! @cond Doxygen_Suppress
+void DerivedCRS::_exportToJSON(
+ io::JSONFormatter *formatter) const // throw(io::FormattingException)
+{
+ auto &writer = formatter->writer();
+ auto objectContext(
+ formatter->MakeObjectContext(className(), !identifiers().empty()));
+
+ writer.AddObjKey("name");
+ auto l_name = nameStr();
+ if (l_name.empty()) {
+ writer.Add("unnamed");
+ } else {
+ writer.Add(l_name);
+ }
+
+ writer.AddObjKey("base_crs");
+ baseCRS()->_exportToJSON(formatter);
+
+ writer.AddObjKey("conversion");
+ derivingConversionRef()->_exportToJSON(formatter);
+
+ writer.AddObjKey("coordinate_system");
+ formatter->setOmitTypeInImmediateChild();
+ coordinateSystem()->_exportToJSON(formatter);
+
+ ObjectUsage::baseExportToJSON(formatter);
+}
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
+//! @cond Doxygen_Suppress
struct ProjectedCRS::Private {
GeodeticCRSNNPtr baseCRS_;
cs::CartesianCSNNPtr cs_;
@@ -3514,6 +3577,36 @@ void CompoundCRS::_exportToWKT(io::WKTFormatter *formatter) const {
// ---------------------------------------------------------------------------
+//! @cond Doxygen_Suppress
+void CompoundCRS::_exportToJSON(
+ io::JSONFormatter *formatter) const // throw(io::FormattingException)
+{
+ auto &writer = formatter->writer();
+ auto objectContext(
+ formatter->MakeObjectContext("CompoundCRS", !identifiers().empty()));
+
+ writer.AddObjKey("name");
+ auto l_name = nameStr();
+ if (l_name.empty()) {
+ writer.Add("unnamed");
+ } else {
+ writer.Add(l_name);
+ }
+
+ writer.AddObjKey("components");
+ {
+ auto componentsContext(writer.MakeArrayContext(false));
+ for (const auto &crs : componentReferenceSystems()) {
+ crs->_exportToJSON(formatter);
+ }
+ }
+
+ ObjectUsage::baseExportToJSON(formatter);
+}
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
void CompoundCRS::_exportToPROJString(
io::PROJStringFormatter *formatter) const // throw(io::FormattingException)
{
@@ -4004,6 +4097,30 @@ void BoundCRS::_exportToWKT(io::WKTFormatter *formatter) const {
// ---------------------------------------------------------------------------
+//! @cond Doxygen_Suppress
+void BoundCRS::_exportToJSON(
+ io::JSONFormatter *formatter) const // throw(io::FormattingException)
+{
+ auto &writer = formatter->writer();
+ auto objectContext(
+ formatter->MakeObjectContext("BoundCRS", !identifiers().empty()));
+
+ writer.AddObjKey("source_crs");
+ d->baseCRS()->_exportToJSON(formatter);
+
+ writer.AddObjKey("target_crs");
+ d->hubCRS()->_exportToJSON(formatter);
+
+ writer.AddObjKey("transformation");
+ formatter->setOmitTypeInImmediateChild();
+ formatter->setAbridgedTransformation(true);
+ d->transformation()->_exportToJSON(formatter);
+ formatter->setAbridgedTransformation(false);
+}
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
void BoundCRS::_exportToPROJString(
io::PROJStringFormatter *formatter) const // throw(io::FormattingException)
{
@@ -4298,38 +4415,6 @@ void DerivedGeodeticCRS::_exportToWKT(io::WKTFormatter *formatter) const {
// ---------------------------------------------------------------------------
-//! @cond Doxygen_Suppress
-void DerivedGeodeticCRS::_exportToJSON(
- io::JSONFormatter *formatter) const // throw(io::FormattingException)
-{
- auto &writer = formatter->writer();
- auto objectContext(formatter->MakeObjectContext("DerivedGeodeticCRS",
- !identifiers().empty()));
-
- writer.AddObjKey("name");
- auto l_name = nameStr();
- if (l_name.empty()) {
- writer.Add("unnamed");
- } else {
- writer.Add(l_name);
- }
-
- writer.AddObjKey("base_crs");
- baseCRS()->_exportToJSON(formatter);
-
- writer.AddObjKey("conversion");
- derivingConversionRef()->_exportToJSON(formatter);
-
- writer.AddObjKey("coordinate_system");
- formatter->setOmitTypeInImmediateChild();
- coordinateSystem()->_exportToJSON(formatter);
-
- ObjectUsage::baseExportToJSON(formatter);
-}
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
void DerivedGeodeticCRS::_exportToPROJString(
io::PROJStringFormatter *) const // throw(io::FormattingException)
{
@@ -4468,38 +4553,6 @@ void DerivedGeographicCRS::_exportToWKT(io::WKTFormatter *formatter) const {
// ---------------------------------------------------------------------------
-//! @cond Doxygen_Suppress
-void DerivedGeographicCRS::_exportToJSON(
- io::JSONFormatter *formatter) const // throw(io::FormattingException)
-{
- auto &writer = formatter->writer();
- auto objectContext(formatter->MakeObjectContext("DerivedGeographicCRS",
- !identifiers().empty()));
-
- writer.AddObjKey("name");
- auto l_name = nameStr();
- if (l_name.empty()) {
- writer.Add("unnamed");
- } else {
- writer.Add(l_name);
- }
-
- writer.AddObjKey("base_crs");
- baseCRS()->_exportToJSON(formatter);
-
- writer.AddObjKey("conversion");
- derivingConversionRef()->_exportToJSON(formatter);
-
- writer.AddObjKey("coordinate_system");
- formatter->setOmitTypeInImmediateChild();
- coordinateSystem()->_exportToJSON(formatter);
-
- ObjectUsage::baseExportToJSON(formatter);
-}
-//! @endcond
-
-// ---------------------------------------------------------------------------
-
void DerivedGeographicCRS::_exportToPROJString(
io::PROJStringFormatter *) const // throw(io::FormattingException)
{
@@ -4756,6 +4809,35 @@ void TemporalCRS::_exportToWKT(io::WKTFormatter *formatter) const {
// ---------------------------------------------------------------------------
+//! @cond Doxygen_Suppress
+void TemporalCRS::_exportToJSON(
+ io::JSONFormatter *formatter) const // throw(io::FormattingException)
+{
+ auto &writer = formatter->writer();
+ auto objectContext(
+ formatter->MakeObjectContext("TemporalCRS", !identifiers().empty()));
+
+ writer.AddObjKey("name");
+ auto l_name = nameStr();
+ if (l_name.empty()) {
+ writer.Add("unnamed");
+ } else {
+ writer.Add(l_name);
+ }
+
+ writer.AddObjKey("datum");
+ datum()->_exportToJSON(formatter);
+
+ writer.AddObjKey("coordinate_system");
+ formatter->setOmitTypeInImmediateChild();
+ coordinateSystem()->_exportToJSON(formatter);
+
+ ObjectUsage::baseExportToJSON(formatter);
+}
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
bool TemporalCRS::_isEquivalentTo(
const util::IComparable *other,
util::IComparable::Criterion criterion) const {
@@ -4864,6 +4946,35 @@ void EngineeringCRS::_exportToWKT(io::WKTFormatter *formatter) const {
// ---------------------------------------------------------------------------
+//! @cond Doxygen_Suppress
+void EngineeringCRS::_exportToJSON(
+ io::JSONFormatter *formatter) const // throw(io::FormattingException)
+{
+ auto &writer = formatter->writer();
+ auto objectContext(
+ formatter->MakeObjectContext("EngineeringCRS", !identifiers().empty()));
+
+ writer.AddObjKey("name");
+ auto l_name = nameStr();
+ if (l_name.empty()) {
+ writer.Add("unnamed");
+ } else {
+ writer.Add(l_name);
+ }
+
+ writer.AddObjKey("datum");
+ datum()->_exportToJSON(formatter);
+
+ writer.AddObjKey("coordinate_system");
+ formatter->setOmitTypeInImmediateChild();
+ coordinateSystem()->_exportToJSON(formatter);
+
+ ObjectUsage::baseExportToJSON(formatter);
+}
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
bool EngineeringCRS::_isEquivalentTo(
const util::IComparable *other,
util::IComparable::Criterion criterion) const {
@@ -4966,6 +5077,35 @@ void ParametricCRS::_exportToWKT(io::WKTFormatter *formatter) const {
// ---------------------------------------------------------------------------
+//! @cond Doxygen_Suppress
+void ParametricCRS::_exportToJSON(
+ io::JSONFormatter *formatter) const // throw(io::FormattingException)
+{
+ auto &writer = formatter->writer();
+ auto objectContext(
+ formatter->MakeObjectContext("ParametricCRS", !identifiers().empty()));
+
+ writer.AddObjKey("name");
+ auto l_name = nameStr();
+ if (l_name.empty()) {
+ writer.Add("unnamed");
+ } else {
+ writer.Add(l_name);
+ }
+
+ writer.AddObjKey("datum");
+ datum()->_exportToJSON(formatter);
+
+ writer.AddObjKey("coordinate_system");
+ formatter->setOmitTypeInImmediateChild();
+ coordinateSystem()->_exportToJSON(formatter);
+
+ ObjectUsage::baseExportToJSON(formatter);
+}
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
bool ParametricCRS::_isEquivalentTo(
const util::IComparable *other,
util::IComparable::Criterion criterion) const {
@@ -5160,6 +5300,13 @@ DerivedCRSTemplate<DerivedCRSTraits>::create(
// ---------------------------------------------------------------------------
+template <class DerivedCRSTraits>
+const char *DerivedCRSTemplate<DerivedCRSTraits>::className() const {
+ return DerivedCRSTraits::CRSName().c_str();
+}
+
+// ---------------------------------------------------------------------------
+
static void DerivedCRSTemplateCheckExportToWKT(io::WKTFormatter *formatter,
const std::string &crsName,
bool wkt2_2018_only) {
diff --git a/src/iso19111/datum.cpp b/src/iso19111/datum.cpp
index 2944da1e..d6e6bc21 100644
--- a/src/iso19111/datum.cpp
+++ b/src/iso19111/datum.cpp
@@ -1726,6 +1726,30 @@ void VerticalReferenceFrame::_exportToWKT(
// ---------------------------------------------------------------------------
//! @cond Doxygen_Suppress
+void VerticalReferenceFrame::_exportToJSON(
+ io::JSONFormatter *formatter) const // throw(FormattingException)
+{
+ auto objectContext(formatter->MakeObjectContext("VerticalReferenceFrame",
+ !identifiers().empty()));
+ auto &writer = formatter->writer();
+
+ writer.AddObjKey("name");
+ auto l_name = nameStr();
+ if (l_name.empty()) {
+ writer.Add("unnamed");
+ } else {
+ writer.Add(l_name);
+ }
+
+ Datum::getPrivate()->exportAnchorDefinition(formatter);
+
+ ObjectUsage::baseExportToJSON(formatter);
+}
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
+//! @cond Doxygen_Suppress
bool VerticalReferenceFrame::_isEquivalentTo(
const util::IComparable *other,
util::IComparable::Criterion criterion) const {
@@ -1989,6 +2013,32 @@ void TemporalDatum::_exportToWKT(
// ---------------------------------------------------------------------------
//! @cond Doxygen_Suppress
+void TemporalDatum::_exportToJSON(
+ io::JSONFormatter *formatter) const // throw(FormattingException)
+{
+ auto objectContext(
+ formatter->MakeObjectContext("TemporalDatum", !identifiers().empty()));
+ auto &writer = formatter->writer();
+
+ writer.AddObjKey("name");
+ writer.Add(nameStr());
+
+ writer.AddObjKey("calendar");
+ writer.Add(calendar());
+
+ const auto &timeOriginStr = temporalOrigin().toString();
+ if (!timeOriginStr.empty()) {
+ writer.AddObjKey("time_origin");
+ writer.Add(timeOriginStr);
+ }
+
+ ObjectUsage::baseExportToJSON(formatter);
+}
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
+//! @cond Doxygen_Suppress
bool TemporalDatum::_isEquivalentTo(
const util::IComparable *other,
util::IComparable::Criterion criterion) const {
@@ -2062,6 +2112,25 @@ void EngineeringDatum::_exportToWKT(
// ---------------------------------------------------------------------------
//! @cond Doxygen_Suppress
+void EngineeringDatum::_exportToJSON(
+ io::JSONFormatter *formatter) const // throw(FormattingException)
+{
+ auto objectContext(formatter->MakeObjectContext("EngineeringDatum",
+ !identifiers().empty()));
+ auto &writer = formatter->writer();
+
+ writer.AddObjKey("name");
+ writer.Add(nameStr());
+
+ Datum::getPrivate()->exportAnchorDefinition(formatter);
+
+ ObjectUsage::baseExportToJSON(formatter);
+}
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
+//! @cond Doxygen_Suppress
bool EngineeringDatum::_isEquivalentTo(
const util::IComparable *other,
util::IComparable::Criterion criterion) const {
@@ -2128,6 +2197,25 @@ void ParametricDatum::_exportToWKT(
// ---------------------------------------------------------------------------
//! @cond Doxygen_Suppress
+void ParametricDatum::_exportToJSON(
+ io::JSONFormatter *formatter) const // throw(FormattingException)
+{
+ auto objectContext(formatter->MakeObjectContext("ParametricDatum",
+ !identifiers().empty()));
+ auto &writer = formatter->writer();
+
+ writer.AddObjKey("name");
+ writer.Add(nameStr());
+
+ Datum::getPrivate()->exportAnchorDefinition(formatter);
+
+ ObjectUsage::baseExportToJSON(formatter);
+}
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
+//! @cond Doxygen_Suppress
bool ParametricDatum::_isEquivalentTo(
const util::IComparable *other,
util::IComparable::Criterion criterion) const {
diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp
index bcd14429..eadc54cc 100644
--- a/src/iso19111/io.cpp
+++ b/src/iso19111/io.cpp
@@ -4390,17 +4390,24 @@ class JSONParser {
static Measure getMeasure(const json &j);
ObjectDomainPtr buildObjectDomain(const json &j);
- PropertyMap buildProperties(const json &j);
+ PropertyMap buildProperties(const json &j, bool removeInverseOf = false);
GeographicCRSNNPtr buildGeographicCRS(const json &j);
GeodeticCRSNNPtr buildGeodeticCRS(const json &j);
ProjectedCRSNNPtr buildProjectedCRS(const json &j);
ConversionNNPtr buildConversion(const json &j);
GeodeticReferenceFrameNNPtr buildGeodeticReferenceFrame(const json &j);
+ VerticalReferenceFrameNNPtr buildVerticalReferenceFrame(const json &j);
EllipsoidNNPtr buildEllipsoid(const json &j);
PrimeMeridianNNPtr buildPrimeMeridian(const json &j);
CoordinateSystemNNPtr buildCS(const json &j);
CoordinateSystemAxisNNPtr buildAxis(const json &j);
+ VerticalCRSNNPtr buildVerticalCRS(const json &j);
+ CRSNNPtr buildCRS(const json &j);
+ CompoundCRSNNPtr buildCompoundCRS(const json &j);
+ BoundCRSNNPtr buildBoundCRS(const json &j);
+ TransformationNNPtr buildTransformation(const json &j);
+ ConcatenatedOperationNNPtr buildConcatenatedOperation(const json &j);
public:
JSONParser() = default;
@@ -4592,14 +4599,23 @@ ObjectDomainPtr JSONParser::buildObjectDomain(const json &j) {
// ---------------------------------------------------------------------------
-PropertyMap JSONParser::buildProperties(const json &j) {
+PropertyMap JSONParser::buildProperties(const json &j, bool removeInverseOf) {
PropertyMap map;
- map.set(IdentifiedObject::NAME_KEY, getName(j));
+ std::string name(getName(j));
+ if (removeInverseOf && starts_with(name, "Inverse of ")) {
+ name = name.substr(strlen("Inverse of "));
+ }
+ map.set(IdentifiedObject::NAME_KEY, name);
if (j.contains("id")) {
auto id = getObject(j, "id");
- map.set(metadata::Identifier::CODESPACE_KEY,
- getString(id, "authority"));
+ auto codeSpace(getString(id, "authority"));
+ if (removeInverseOf && starts_with(codeSpace, "INVERSE(") &&
+ codeSpace.back() == ')') {
+ codeSpace = codeSpace.substr(strlen("INVERSE("));
+ codeSpace.resize(codeSpace.size() - 1);
+ }
+ map.set(metadata::Identifier::CODESPACE_KEY, codeSpace);
if (!id.contains("code")) {
throw ParsingException("Missing \"code\" key");
}
@@ -4652,7 +4668,7 @@ PropertyMap JSONParser::buildProperties(const json &j) {
BaseObjectNNPtr JSONParser::create(const json &j)
{
- if (j.type() != json::value_t::object) {
+ if (!j.is_object()) {
throw ParsingException("JSON object expected");
}
auto type = getString(j, "type");
@@ -4665,9 +4681,21 @@ BaseObjectNNPtr JSONParser::create(const json &j)
if (type == "ProjectedCRS") {
return buildProjectedCRS(j);
}
+ if (type == "VerticalCRS") {
+ return buildVerticalCRS(j);
+ }
+ if (type == "CompoundCRS") {
+ return buildCompoundCRS(j);
+ }
+ if (type == "BoundCRS") {
+ return buildBoundCRS(j);
+ }
if (type == "GeodeticReferenceFrame") {
return buildGeodeticReferenceFrame(j);
}
+ if (type == "VerticalReferenceFrame") {
+ return buildVerticalReferenceFrame(j);
+ }
if (type == "Ellipsoid") {
return buildEllipsoid(j);
}
@@ -4677,6 +4705,15 @@ BaseObjectNNPtr JSONParser::create(const json &j)
if (type == "CoordinateSystem") {
return buildCS(j);
}
+ if (type == "Conversion") {
+ return buildConversion(j);
+ }
+ if (type == "Transformation") {
+ return buildTransformation(j);
+ }
+ if (type == "ConcatenatedOperation") {
+ return buildConcatenatedOperation(j);
+ }
throw ParsingException("Unsupported value of \"type\"");
}
@@ -4755,6 +4792,48 @@ ProjectedCRSNNPtr JSONParser::buildProjectedCRS(const json &j) {
// ---------------------------------------------------------------------------
+VerticalCRSNNPtr JSONParser::buildVerticalCRS(const json &j) {
+ auto datumJ = getObject(j, "datum");
+ if (getType(datumJ) != "VerticalReferenceFrame") {
+ throw ParsingException("Unsupported type for datum.");
+ }
+ auto datum = buildVerticalReferenceFrame(datumJ);
+ auto csJ = getObject(j, "coordinate_system");
+ auto verticalCS = util::nn_dynamic_pointer_cast<VerticalCS>(buildCS(csJ));
+ if (!verticalCS) {
+ throw ParsingException("expected a vertical CS");
+ }
+ return VerticalCRS::create(buildProperties(j), datum,
+ NN_NO_CHECK(verticalCS));
+}
+
+// ---------------------------------------------------------------------------
+
+CRSNNPtr JSONParser::buildCRS(const json &j) {
+ auto crs = util::nn_dynamic_pointer_cast<CRS>(create(j));
+ if (crs) {
+ return NN_NO_CHECK(crs);
+ }
+ throw ParsingException("Object is not a CRS");
+}
+
+// ---------------------------------------------------------------------------
+
+CompoundCRSNNPtr JSONParser::buildCompoundCRS(const json &j) {
+ auto componentsJ = getArray(j, "components");
+ std::vector<CRSNNPtr> components;
+ for (const auto &componentJ : componentsJ) {
+ if (!componentJ.is_object()) {
+ throw ParsingException(
+ "Unexpected type for a \"components\" child");
+ }
+ components.push_back(buildCRS(componentJ));
+ }
+ return CompoundCRS::create(buildProperties(j), components);
+}
+
+// ---------------------------------------------------------------------------
+
ConversionNNPtr JSONParser::buildConversion(const json &j) {
auto methodJ = getObject(j, "method");
auto convProps = buildProperties(j);
@@ -4775,11 +4854,152 @@ ConversionNNPtr JSONParser::buildConversion(const json &j) {
OperationParameter::create(buildProperties(param)));
values.emplace_back(ParameterValue::create(getMeasure(param)));
}
+
+ std::string convName;
+ std::string methodName;
+ if (convProps.getStringValue(IdentifiedObject::NAME_KEY, convName) &&
+ methodProps.getStringValue(IdentifiedObject::NAME_KEY, methodName) &&
+ starts_with(convName, "Inverse of ") &&
+ starts_with(methodName, "Inverse of ")) {
+
+ auto invConvProps = buildProperties(j, true);
+ auto invMethodProps = buildProperties(methodJ, true);
+ return NN_NO_CHECK(util::nn_dynamic_pointer_cast<Conversion>(
+ Conversion::create(invConvProps, invMethodProps, parameters, values)
+ ->inverse()));
+ }
return Conversion::create(convProps, methodProps, parameters, values);
}
// ---------------------------------------------------------------------------
+BoundCRSNNPtr JSONParser::buildBoundCRS(const json &j) {
+
+ auto sourceCRS = buildCRS(getObject(j, "source_crs"));
+ auto targetCRS = buildCRS(getObject(j, "target_crs"));
+ auto transformationJ = getObject(j, "transformation");
+ auto methodJ = getObject(transformationJ, "method");
+ auto parametersJ = getArray(transformationJ, "parameters");
+ std::vector<OperationParameterNNPtr> parameters;
+ std::vector<ParameterValueNNPtr> values;
+ for (const auto &param : parametersJ) {
+ if (!param.is_object()) {
+ throw ParsingException(
+ "Unexpected type for a \"parameters\" child");
+ }
+ parameters.emplace_back(
+ OperationParameter::create(buildProperties(param)));
+ if (param.contains("value")) {
+ auto v = param["value"];
+ if (v.is_string()) {
+ values.emplace_back(
+ ParameterValue::createFilename(v.get<std::string>()));
+ continue;
+ }
+ }
+ values.emplace_back(ParameterValue::create(getMeasure(param)));
+ }
+
+ CRSPtr sourceTransformationCRS;
+ if (dynamic_cast<GeographicCRS *>(targetCRS.get())) {
+ sourceTransformationCRS = sourceCRS->extractGeographicCRS();
+ if (!sourceTransformationCRS) {
+ sourceTransformationCRS =
+ std::dynamic_pointer_cast<VerticalCRS>(sourceCRS.as_nullable());
+ if (!sourceTransformationCRS) {
+ throw ParsingException(
+ "Cannot find GeographicCRS or VerticalCRS in sourceCRS");
+ }
+ }
+ } else {
+ sourceTransformationCRS = sourceCRS;
+ }
+
+ auto transformation = Transformation::create(
+ buildProperties(transformationJ), NN_NO_CHECK(sourceTransformationCRS),
+ targetCRS, nullptr, buildProperties(methodJ), parameters, values,
+ std::vector<PositionalAccuracyNNPtr>());
+
+ return BoundCRS::create(sourceCRS, targetCRS, transformation);
+}
+
+// ---------------------------------------------------------------------------
+
+TransformationNNPtr JSONParser::buildTransformation(const json &j) {
+
+ auto sourceCRS = buildCRS(getObject(j, "source_crs"));
+ auto targetCRS = buildCRS(getObject(j, "target_crs"));
+ auto methodJ = getObject(j, "method");
+ auto parametersJ = getArray(j, "parameters");
+ std::vector<OperationParameterNNPtr> parameters;
+ std::vector<ParameterValueNNPtr> values;
+ for (const auto &param : parametersJ) {
+ if (!param.is_object()) {
+ throw ParsingException(
+ "Unexpected type for a \"parameters\" child");
+ }
+ parameters.emplace_back(
+ OperationParameter::create(buildProperties(param)));
+ if (param.contains("value")) {
+ auto v = param["value"];
+ if (v.is_string()) {
+ values.emplace_back(
+ ParameterValue::createFilename(v.get<std::string>()));
+ continue;
+ }
+ }
+ values.emplace_back(ParameterValue::create(getMeasure(param)));
+ }
+ CRSPtr interpolationCRS;
+ if (j.contains("interpolation_crs")) {
+ interpolationCRS =
+ buildCRS(getObject(j, "interpolation_crs")).as_nullable();
+ }
+ std::vector<PositionalAccuracyNNPtr> accuracies;
+ if (j.contains("accuracy")) {
+ accuracies.push_back(
+ PositionalAccuracy::create(getString(j, "accuracy")));
+ }
+
+ return Transformation::create(buildProperties(j), sourceCRS, targetCRS,
+ interpolationCRS, buildProperties(methodJ),
+ parameters, values, accuracies);
+}
+
+// ---------------------------------------------------------------------------
+
+ConcatenatedOperationNNPtr
+JSONParser::buildConcatenatedOperation(const json &j) {
+
+ auto sourceCRS = buildCRS(getObject(j, "source_crs"));
+ auto targetCRS = buildCRS(getObject(j, "target_crs"));
+ auto stepsJ = getArray(j, "steps");
+ std::vector<CoordinateOperationNNPtr> operations;
+ for (const auto &stepJ : stepsJ) {
+ if (!stepJ.is_object()) {
+ throw ParsingException("Unexpected type for a \"steps\" child");
+ }
+ auto op = nn_dynamic_pointer_cast<CoordinateOperation>(create(stepJ));
+ if (!op) {
+ throw ParsingException("Invalid content in a \"steps\" child");
+ }
+ operations.emplace_back(NN_NO_CHECK(op));
+ }
+
+ ConcatenatedOperation::fixStepsDirection(sourceCRS, targetCRS, operations);
+
+ try {
+ return ConcatenatedOperation::create(
+ buildProperties(j), operations,
+ std::vector<PositionalAccuracyNNPtr>());
+ } catch (const InvalidOperation &e) {
+ throw ParsingException(
+ std::string("Cannot build concatenated operation: ") + e.what());
+ }
+}
+
+// ---------------------------------------------------------------------------
+
CoordinateSystemAxisNNPtr JSONParser::buildAxis(const json &j) {
auto dirString = getString(j, "direction");
auto abbreviation = getString(j, "abbreviation");
@@ -4884,9 +5104,23 @@ JSONParser::buildGeodeticReferenceFrame(const json &j) {
auto pm = j.contains("prime_meridian")
? buildPrimeMeridian(getObject(j, "prime_meridian"))
: PrimeMeridian::GREENWICH;
+ optional<std::string> anchor;
+ if (j.contains("anchor")) {
+ anchor = getString(j, "anchor");
+ }
return GeodeticReferenceFrame::create(
- buildProperties(j), buildEllipsoid(ellipsoidJ),
- optional<std::string>() /* anchor */, pm);
+ buildProperties(j), buildEllipsoid(ellipsoidJ), anchor, pm);
+}
+
+// ---------------------------------------------------------------------------
+
+VerticalReferenceFrameNNPtr
+JSONParser::buildVerticalReferenceFrame(const json &j) {
+ optional<std::string> anchor;
+ if (j.contains("anchor")) {
+ anchor = getString(j, "anchor");
+ }
+ return VerticalReferenceFrame::create(buildProperties(j), anchor);
}
// ---------------------------------------------------------------------------
@@ -8605,6 +8839,7 @@ struct JSONFormatter::Private {
std::vector<bool> outputIdStack_{true};
bool allowIDInImmediateChild_ = false;
bool omitTypeInImmediateChild_ = false;
+ bool abridgedTransformation_ = false;
std::string result_{};
@@ -8717,6 +8952,18 @@ JSONFormatter::ObjectContext::~ObjectContext() {
m_formatter.d->popOutputId();
}
+// ---------------------------------------------------------------------------
+
+void JSONFormatter::setAbridgedTransformation(bool outputIn) {
+ d->abridgedTransformation_ = outputIn;
+}
+
+// ---------------------------------------------------------------------------
+
+bool JSONFormatter::abridgedTransformation() const {
+ return d->abridgedTransformation_;
+}
+
//! @endcond
// ---------------------------------------------------------------------------