diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2019-08-09 17:10:20 +0200 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2019-08-09 17:41:23 +0200 |
| commit | f0d766e45640800412c08a7cb9ab4f8823d88d05 (patch) | |
| tree | 1973086c9f52043d61fb1a71cbbc1c3a794c3afc /src | |
| parent | 81bd57dfd8cfae609288643d1b09a4805f1bcded (diff) | |
| download | PROJ-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.cpp | 174 | ||||
| -rw-r--r-- | src/iso19111/crs.cpp | 275 | ||||
| -rw-r--r-- | src/iso19111/datum.cpp | 88 | ||||
| -rw-r--r-- | src/iso19111/io.cpp | 263 |
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 ¶m : 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 ¶m : 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 // --------------------------------------------------------------------------- |
