aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2019-08-10 15:15:44 +0200
committerEven Rouault <even.rouault@spatialys.com>2019-08-10 15:27:59 +0200
commit63981af418d84749cd4d70752f83fd551100389f (patch)
tree10ddaceb884aa02ea1f3a75334853766cce958d9 /src
parent17dc5eb1b6d09d436c80470497dd2abfb902cf6d (diff)
downloadPROJ-63981af418d84749cd4d70752f83fd551100389f.tar.gz
PROJ-63981af418d84749cd4d70752f83fd551100389f.zip
PROJJSON: add support for DatumEnsemble and Dynamic[Geodetic|Vertical]ReferenceFrame
Diffstat (limited to 'src')
-rw-r--r--src/iso19111/crs.cpp19
-rw-r--r--src/iso19111/datum.cpp94
-rw-r--r--src/iso19111/io.cpp156
3 files changed, 247 insertions, 22 deletions
diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp
index 4f2ab7c6..b03ece23 100644
--- a/src/iso19111/crs.cpp
+++ b/src/iso19111/crs.cpp
@@ -1362,7 +1362,9 @@ void GeodeticCRS::_exportToJSON(
writer.AddObjKey("datum");
l_datum->_exportToJSON(formatter);
} else {
- // TODO DatumEnsemble
+ writer.AddObjKey("datum_ensemble");
+ formatter->setOmitTypeInImmediateChild();
+ datumEnsemble()->_exportToJSON(formatter);
}
writer.AddObjKey("coordinate_system");
@@ -2113,7 +2115,9 @@ void GeographicCRS::_exportToJSON(
writer.AddObjKey("datum");
l_datum->_exportToJSON(formatter);
} else {
- // TODO DatumEnsemble
+ writer.AddObjKey("datum_ensemble");
+ formatter->setOmitTypeInImmediateChild();
+ datumEnsemble()->_exportToJSON(formatter);
}
writer.AddObjKey("coordinate_system");
@@ -2305,8 +2309,15 @@ void VerticalCRS::_exportToJSON(
writer.Add(l_name);
}
- writer.AddObjKey("datum");
- datum()->_exportToJSON(formatter);
+ const auto &l_datum(datum());
+ if (l_datum) {
+ writer.AddObjKey("datum");
+ l_datum->_exportToJSON(formatter);
+ } else {
+ writer.AddObjKey("datum_ensemble");
+ formatter->setOmitTypeInImmediateChild();
+ datumEnsemble()->_exportToJSON(formatter);
+ }
writer.AddObjKey("coordinate_system");
formatter->setOmitTypeInImmediateChild();
diff --git a/src/iso19111/datum.cpp b/src/iso19111/datum.cpp
index d6e6bc21..65905ca9 100644
--- a/src/iso19111/datum.cpp
+++ b/src/iso19111/datum.cpp
@@ -1264,8 +1264,11 @@ void GeodeticReferenceFrame::_exportToWKT(
void GeodeticReferenceFrame::_exportToJSON(
io::JSONFormatter *formatter) const // throw(FormattingException)
{
- auto objectContext(formatter->MakeObjectContext("GeodeticReferenceFrame",
- !identifiers().empty()));
+ auto dynamicGRF = dynamic_cast<const DynamicGeodeticReferenceFrame *>(this);
+
+ auto objectContext(formatter->MakeObjectContext(
+ dynamicGRF ? "DynamicGeodeticReferenceFrame" : "GeodeticReferenceFrame",
+ !identifiers().empty()));
auto &writer = formatter->writer();
writer.AddObjKey("name");
@@ -1278,6 +1281,17 @@ void GeodeticReferenceFrame::_exportToJSON(
Datum::getPrivate()->exportAnchorDefinition(formatter);
+ if (dynamicGRF) {
+ writer.AddObjKey("frame_reference_epoch");
+ writer.Add(dynamicGRF->frameReferenceEpoch().value());
+
+ const auto &deformationModel = dynamicGRF->deformationModelName();
+ if (deformationModel.has_value()) {
+ writer.AddObjKey("deformation_model");
+ writer.Add(*deformationModel);
+ }
+ }
+
writer.AddObjKey("ellipsoid");
formatter->setOmitTypeInImmediateChild();
ellipsoid()->_exportToJSON(formatter);
@@ -1422,7 +1436,7 @@ void DynamicGeodeticReferenceFrame::_exportToWKT(
// ---------------------------------------------------------------------------
-/** \brief Instantiate a DyanmicGeodeticReferenceFrame
+/** \brief Instantiate a DynamicGeodeticReferenceFrame
*
* @param properties See \ref general_properties.
* At minimum the name should be defined.
@@ -1431,7 +1445,7 @@ void DynamicGeodeticReferenceFrame::_exportToWKT(
* @param primeMeridian the PrimeMeridian.
* @param frameReferenceEpochIn the frame reference epoch.
* @param deformationModelNameIn deformation model name, or empty
- * @return new DyanmicGeodeticReferenceFrame.
+ * @return new DynamicGeodeticReferenceFrame.
*/
DynamicGeodeticReferenceFrameNNPtr DynamicGeodeticReferenceFrame::create(
const util::PropertyMap &properties, const EllipsoidNNPtr &ellipsoid,
@@ -1562,6 +1576,56 @@ void DatumEnsemble::_exportToWKT(
// ---------------------------------------------------------------------------
+//! @cond Doxygen_Suppress
+void DatumEnsemble::_exportToJSON(
+ io::JSONFormatter *formatter) const // throw(FormattingException)
+{
+ auto objectContext(
+ formatter->MakeObjectContext("DatumEnsemble", !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);
+ }
+
+ auto l_datums = datums();
+ writer.AddObjKey("members");
+ {
+ auto membersContext(writer.MakeArrayContext(false));
+ for (const auto &datum : l_datums) {
+ auto memberContext(writer.MakeObjectContext());
+ writer.AddObjKey("name");
+ const auto &l_datum_name = datum->nameStr();
+ if (!l_datum_name.empty()) {
+ writer.Add(l_datum_name);
+ } else {
+ writer.Add("unnamed");
+ }
+ datum->formatID(formatter);
+ }
+ }
+
+ auto grfFirst = std::dynamic_pointer_cast<GeodeticReferenceFrame>(
+ l_datums[0].as_nullable());
+ if (grfFirst) {
+ writer.AddObjKey("ellipsoid");
+ formatter->setOmitTypeInImmediateChild();
+ grfFirst->ellipsoid()->_exportToJSON(formatter);
+ }
+
+ writer.AddObjKey("accuracy");
+ writer.Add(positionalAccuracy()->value());
+
+ formatID(formatter);
+}
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
/** \brief Instantiate a DatumEnsemble.
*
* @param properties See \ref general_properties.
@@ -1729,8 +1793,11 @@ void VerticalReferenceFrame::_exportToWKT(
void VerticalReferenceFrame::_exportToJSON(
io::JSONFormatter *formatter) const // throw(FormattingException)
{
- auto objectContext(formatter->MakeObjectContext("VerticalReferenceFrame",
- !identifiers().empty()));
+ auto dynamicGRF = dynamic_cast<const DynamicVerticalReferenceFrame *>(this);
+
+ auto objectContext(formatter->MakeObjectContext(
+ dynamicGRF ? "DynamicVerticalReferenceFrame" : "VerticalReferenceFrame",
+ !identifiers().empty()));
auto &writer = formatter->writer();
writer.AddObjKey("name");
@@ -1743,6 +1810,17 @@ void VerticalReferenceFrame::_exportToJSON(
Datum::getPrivate()->exportAnchorDefinition(formatter);
+ if (dynamicGRF) {
+ writer.AddObjKey("frame_reference_epoch");
+ writer.Add(dynamicGRF->frameReferenceEpoch().value());
+
+ const auto &deformationModel = dynamicGRF->deformationModelName();
+ if (deformationModel.has_value()) {
+ writer.AddObjKey("deformation_model");
+ writer.Add(*deformationModel);
+ }
+ }
+
ObjectUsage::baseExportToJSON(formatter);
}
//! @endcond
@@ -1882,7 +1960,7 @@ void DynamicVerticalReferenceFrame::_exportToWKT(
// ---------------------------------------------------------------------------
-/** \brief Instantiate a DyanmicVerticalReferenceFrame
+/** \brief Instantiate a DynamicVerticalReferenceFrame
*
* @param properties See \ref general_properties.
* At minimum the name should be defined.
@@ -1890,7 +1968,7 @@ void DynamicVerticalReferenceFrame::_exportToWKT(
* @param realizationMethodIn the realization method, or empty.
* @param frameReferenceEpochIn the frame reference epoch.
* @param deformationModelNameIn deformation model name, or empty
- * @return new DyanmicVerticalReferenceFrame.
+ * @return new DynamicVerticalReferenceFrame.
*/
DynamicVerticalReferenceFrameNNPtr DynamicVerticalReferenceFrame::create(
const util::PropertyMap &properties,
diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp
index eadc54cc..8467a9e1 100644
--- a/src/iso19111/io.cpp
+++ b/src/iso19111/io.cpp
@@ -4396,8 +4396,13 @@ class JSONParser {
GeodeticCRSNNPtr buildGeodeticCRS(const json &j);
ProjectedCRSNNPtr buildProjectedCRS(const json &j);
ConversionNNPtr buildConversion(const json &j);
+ DatumEnsembleNNPtr buildDatumEnsemble(const json &j);
GeodeticReferenceFrameNNPtr buildGeodeticReferenceFrame(const json &j);
VerticalReferenceFrameNNPtr buildVerticalReferenceFrame(const json &j);
+ DynamicGeodeticReferenceFrameNNPtr
+ buildDynamicGeodeticReferenceFrame(const json &j);
+ DynamicVerticalReferenceFrameNNPtr
+ buildDynamicVerticalReferenceFrame(const json &j);
EllipsoidNNPtr buildEllipsoid(const json &j);
PrimeMeridianNNPtr buildPrimeMeridian(const json &j);
CoordinateSystemNNPtr buildCS(const json &j);
@@ -4690,12 +4695,21 @@ BaseObjectNNPtr JSONParser::create(const json &j)
if (type == "BoundCRS") {
return buildBoundCRS(j);
}
+ if (type == "DatumEnsemble") {
+ return buildDatumEnsemble(j);
+ }
if (type == "GeodeticReferenceFrame") {
return buildGeodeticReferenceFrame(j);
}
if (type == "VerticalReferenceFrame") {
return buildVerticalReferenceFrame(j);
}
+ if (type == "DynamicGeodeticReferenceFrame") {
+ return buildDynamicGeodeticReferenceFrame(j);
+ }
+ if (type == "DynamicVerticalReferenceFrame") {
+ return buildDynamicVerticalReferenceFrame(j);
+ }
if (type == "Ellipsoid") {
return buildEllipsoid(j);
}
@@ -4720,12 +4734,20 @@ BaseObjectNNPtr JSONParser::create(const json &j)
// ---------------------------------------------------------------------------
GeographicCRSNNPtr JSONParser::buildGeographicCRS(const json &j) {
- auto datumJ = getObject(j, "datum");
- if (getType(datumJ) != "GeodeticReferenceFrame") {
- throw ParsingException("Unsupported type for datum.");
- }
- auto datum = buildGeodeticReferenceFrame(datumJ);
+ GeodeticReferenceFramePtr datum;
DatumEnsemblePtr datumEnsemble;
+ if (j.contains("datum")) {
+ auto datumJ = getObject(j, "datum");
+ datum = util::nn_dynamic_pointer_cast<GeodeticReferenceFrame>(
+ create(datumJ));
+ if (!datum) {
+ throw ParsingException("datum of wrong type");
+ }
+
+ } else {
+ datumEnsemble =
+ buildDatumEnsemble(getObject(j, "datum_ensemble")).as_nullable();
+ }
auto csJ = getObject(j, "coordinate_system");
auto ellipsoidalCS =
util::nn_dynamic_pointer_cast<EllipsoidalCS>(buildCS(csJ));
@@ -4793,17 +4815,25 @@ 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.");
+ VerticalReferenceFramePtr datum;
+ DatumEnsemblePtr datumEnsemble;
+ if (j.contains("datum")) {
+ auto datumJ = getObject(j, "datum");
+ datum = util::nn_dynamic_pointer_cast<VerticalReferenceFrame>(
+ create(datumJ));
+ if (!datum) {
+ throw ParsingException("datum of wrong type");
+ }
+ } else {
+ datumEnsemble =
+ buildDatumEnsemble(getObject(j, "datum_ensemble")).as_nullable();
}
- 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,
+ return VerticalCRS::create(buildProperties(j), datum, datumEnsemble,
NN_NO_CHECK(verticalCS));
}
@@ -5098,6 +5128,70 @@ CoordinateSystemNNPtr JSONParser::buildCS(const json &j) {
// ---------------------------------------------------------------------------
+DatumEnsembleNNPtr JSONParser::buildDatumEnsemble(const json &j) {
+ auto membersJ = getArray(j, "members");
+ std::vector<DatumNNPtr> datums;
+ const bool hasEllipsoid(j.contains("ellipsoid"));
+ for (const auto &memberJ : membersJ) {
+ if (!memberJ.is_object()) {
+ throw ParsingException(
+ "Unexpected type for value of a \"members\" member");
+ }
+ auto datumName(getName(memberJ));
+ if (dbContext_ && memberJ.contains("id")) {
+ auto id = getObject(memberJ, "id");
+ auto authority = getString(id, "authority");
+ auto authFactory =
+ AuthorityFactory::create(NN_NO_CHECK(dbContext_), authority);
+ auto code = id["code"];
+ std::string codeStr;
+ if (code.is_string()) {
+ codeStr = code.get<std::string>();
+ } else if (code.is_number_integer()) {
+ codeStr = internal::toString(code.get<int>());
+ } else {
+ throw ParsingException("Unexpected type for value of \"code\"");
+ }
+ try {
+ datums.push_back(authFactory->createDatum(codeStr));
+ } catch (const std::exception &) {
+ throw ParsingException("No Datum of code " + codeStr);
+ }
+ continue;
+ } else if (dbContext_) {
+ auto authFactory = AuthorityFactory::create(NN_NO_CHECK(dbContext_),
+ std::string());
+ auto list = authFactory->createObjectsFromName(
+ datumName, {AuthorityFactory::ObjectType::DATUM},
+ false /* approximate=false*/);
+ if (!list.empty()) {
+ auto datum = util::nn_dynamic_pointer_cast<Datum>(list.front());
+ if (!datum)
+ throw ParsingException(
+ "DatumEnsemble member is not a datum");
+ datums.push_back(NN_NO_CHECK(datum));
+ continue;
+ }
+ }
+
+ // Fallback if no db match
+ if (hasEllipsoid) {
+ datums.emplace_back(GeodeticReferenceFrame::create(
+ buildProperties(memberJ),
+ buildEllipsoid(getObject(j, "ellipsoid")),
+ optional<std::string>(), PrimeMeridian::GREENWICH));
+ } else {
+ datums.emplace_back(
+ VerticalReferenceFrame::create(buildProperties(memberJ)));
+ }
+ }
+ return DatumEnsemble::create(
+ buildProperties(j), datums,
+ PositionalAccuracy::create(getString(j, "accuracy")));
+}
+
+// ---------------------------------------------------------------------------
+
GeodeticReferenceFrameNNPtr
JSONParser::buildGeodeticReferenceFrame(const json &j) {
auto ellipsoidJ = getObject(j, "ellipsoid");
@@ -5114,6 +5208,29 @@ JSONParser::buildGeodeticReferenceFrame(const json &j) {
// ---------------------------------------------------------------------------
+DynamicGeodeticReferenceFrameNNPtr
+JSONParser::buildDynamicGeodeticReferenceFrame(const json &j) {
+ auto ellipsoidJ = getObject(j, "ellipsoid");
+ 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");
+ }
+ Measure frameReferenceEpoch(getNumber(j, "frame_reference_epoch"),
+ UnitOfMeasure::YEAR);
+ optional<std::string> deformationModel;
+ if (j.contains("deformation_model")) {
+ deformationModel = getString(j, "deformation_model");
+ }
+ return DynamicGeodeticReferenceFrame::create(
+ buildProperties(j), buildEllipsoid(ellipsoidJ), anchor, pm,
+ frameReferenceEpoch, deformationModel);
+}
+
+// ---------------------------------------------------------------------------
+
VerticalReferenceFrameNNPtr
JSONParser::buildVerticalReferenceFrame(const json &j) {
optional<std::string> anchor;
@@ -5125,6 +5242,25 @@ JSONParser::buildVerticalReferenceFrame(const json &j) {
// ---------------------------------------------------------------------------
+DynamicVerticalReferenceFrameNNPtr
+JSONParser::buildDynamicVerticalReferenceFrame(const json &j) {
+ optional<std::string> anchor;
+ if (j.contains("anchor")) {
+ anchor = getString(j, "anchor");
+ }
+ Measure frameReferenceEpoch(getNumber(j, "frame_reference_epoch"),
+ UnitOfMeasure::YEAR);
+ optional<std::string> deformationModel;
+ if (j.contains("deformation_model")) {
+ deformationModel = getString(j, "deformation_model");
+ }
+ return DynamicVerticalReferenceFrame::create(
+ buildProperties(j), anchor, util::optional<RealizationMethod>(),
+ frameReferenceEpoch, deformationModel);
+}
+
+// ---------------------------------------------------------------------------
+
PrimeMeridianNNPtr JSONParser::buildPrimeMeridian(const json &j) {
if (!j.contains("longitude")) {
throw ParsingException("Missing \"longitude\" key");