aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2020-11-21 23:59:33 +0100
committerEven Rouault <even.rouault@spatialys.com>2020-11-21 23:59:33 +0100
commit650e37f159b96d18f5ff03784466784a769688e4 (patch)
tree830264fc953ccbca002eada48d50710499cac2c1
parenteb66679cde834096ff18f40b5b1d4bc10e3f4c1d (diff)
downloadPROJ-650e37f159b96d18f5ff03784466784a769688e4.tar.gz
PROJ-650e37f159b96d18f5ff03784466784a769688e4.zip
PROJJSON parsing: fix parsing of a Geodetic CRS with a DatumEnsemble, and fix parsing of a ProjectedCRS whose base is a Geocentric CRS
-rw-r--r--src/iso19111/io.cpp33
-rw-r--r--test/unit/test_io.cpp149
2 files changed, 173 insertions, 9 deletions
diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp
index 284729cd..713a471d 100644
--- a/src/iso19111/io.cpp
+++ b/src/iso19111/io.cpp
@@ -4980,6 +4980,10 @@ class JSONParser {
TransformationNNPtr buildTransformation(const json &j);
ConcatenatedOperationNNPtr buildConcatenatedOperation(const json &j);
+ void buildGeodeticDatumOrDatumEnsemble(const json &j,
+ GeodeticReferenceFramePtr &datum,
+ DatumEnsemblePtr &datumEnsemble);
+
static util::optional<std::string> getAnchor(const json &j) {
util::optional<std::string> anchor;
if (j.contains("anchor")) {
@@ -5439,9 +5443,9 @@ BaseObjectNNPtr JSONParser::create(const json &j)
// ---------------------------------------------------------------------------
-GeographicCRSNNPtr JSONParser::buildGeographicCRS(const json &j) {
- GeodeticReferenceFramePtr datum;
- DatumEnsemblePtr datumEnsemble;
+void JSONParser::buildGeodeticDatumOrDatumEnsemble(
+ const json &j, GeodeticReferenceFramePtr &datum,
+ DatumEnsemblePtr &datumEnsemble) {
if (j.contains("datum")) {
auto datumJ = getObject(j, "datum");
datum = util::nn_dynamic_pointer_cast<GeodeticReferenceFrame>(
@@ -5454,6 +5458,14 @@ GeographicCRSNNPtr JSONParser::buildGeographicCRS(const json &j) {
datumEnsemble =
buildDatumEnsemble(getObject(j, "datum_ensemble")).as_nullable();
}
+}
+
+// ---------------------------------------------------------------------------
+
+GeographicCRSNNPtr JSONParser::buildGeographicCRS(const json &j) {
+ GeodeticReferenceFramePtr datum;
+ DatumEnsemblePtr datumEnsemble;
+ buildGeodeticDatumOrDatumEnsemble(j, datum, datumEnsemble);
auto csJ = getObject(j, "coordinate_system");
auto ellipsoidalCS =
util::nn_dynamic_pointer_cast<EllipsoidalCS>(buildCS(csJ));
@@ -5467,12 +5479,9 @@ GeographicCRSNNPtr JSONParser::buildGeographicCRS(const json &j) {
// ---------------------------------------------------------------------------
GeodeticCRSNNPtr JSONParser::buildGeodeticCRS(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;
+ buildGeodeticDatumOrDatumEnsemble(j, datum, datumEnsemble);
auto csJ = getObject(j, "coordinate_system");
auto cs = buildCS(csJ);
auto props = buildProperties(j);
@@ -5507,7 +5516,13 @@ GeodeticCRSNNPtr JSONParser::buildGeodeticCRS(const json &j) {
// ---------------------------------------------------------------------------
ProjectedCRSNNPtr JSONParser::buildProjectedCRS(const json &j) {
- auto baseCRS = buildGeographicCRS(getObject(j, "base_crs"));
+ auto jBaseCRS = getObject(j, "base_crs");
+ auto jBaseCS = getObject(jBaseCRS, "coordinate_system");
+ auto baseCS = buildCS(jBaseCS);
+ auto baseCRS = dynamic_cast<EllipsoidalCS *>(baseCS.get()) != nullptr
+ ? util::nn_static_pointer_cast<GeodeticCRS>(
+ buildGeographicCRS(jBaseCRS))
+ : buildGeodeticCRS(jBaseCRS);
auto csJ = getObject(j, "coordinate_system");
auto cartesianCS = util::nn_dynamic_pointer_cast<CartesianCS>(buildCS(csJ));
if (!cartesianCS) {
diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp
index 558b2a6f..81894fb0 100644
--- a/test/unit/test_io.cpp
+++ b/test/unit/test_io.cpp
@@ -11206,6 +11206,155 @@ TEST(json_import, projected_crs) {
// ---------------------------------------------------------------------------
+TEST(json_import, projected_crs_with_geocentric_base) {
+ auto json = "{\n"
+ " \"$schema\": \"foo\",\n"
+ " \"type\": \"ProjectedCRS\",\n"
+ " \"name\": \"EPSG topocentric example B\",\n"
+ " \"base_crs\": {\n"
+ " \"name\": \"WGS 84\",\n"
+ " \"datum_ensemble\": {\n"
+ " \"name\": \"World Geodetic System 1984 ensemble\",\n"
+ " \"members\": [\n"
+ " {\n"
+ " \"name\": \"World Geodetic System 1984 (Transit)\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"World Geodetic System 1984 (G730)\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"World Geodetic System 1984 (G873)\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"World Geodetic System 1984 (G1150)\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"World Geodetic System 1984 (G1674)\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"World Geodetic System 1984 (G1762)\"\n"
+ " }\n"
+ " ],\n"
+ " \"ellipsoid\": {\n"
+ " \"name\": \"WGS 84\",\n"
+ " \"semi_major_axis\": 6378137,\n"
+ " \"inverse_flattening\": 298.257223563\n"
+ " },\n"
+ " \"accuracy\": \"2.0\"\n"
+ " },\n"
+ " \"coordinate_system\": {\n"
+ " \"subtype\": \"Cartesian\",\n"
+ " \"axis\": [\n"
+ " {\n"
+ " \"name\": \"Geocentric X\",\n"
+ " \"abbreviation\": \"X\",\n"
+ " \"direction\": \"geocentricX\",\n"
+ " \"unit\": \"metre\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"Geocentric Y\",\n"
+ " \"abbreviation\": \"Y\",\n"
+ " \"direction\": \"geocentricY\",\n"
+ " \"unit\": \"metre\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"Geocentric Z\",\n"
+ " \"abbreviation\": \"Z\",\n"
+ " \"direction\": \"geocentricZ\",\n"
+ " \"unit\": \"metre\"\n"
+ " }\n"
+ " ]\n"
+ " },\n"
+ " \"id\": {\n"
+ " \"authority\": \"EPSG\",\n"
+ " \"code\": 4978\n"
+ " }\n"
+ " },\n"
+ " \"conversion\": {\n"
+ " \"name\": \"EPSG topocentric example B\",\n"
+ " \"method\": {\n"
+ " \"name\": \"Geocentric/topocentric conversions\",\n"
+ " \"id\": {\n"
+ " \"authority\": \"EPSG\",\n"
+ " \"code\": 9836\n"
+ " }\n"
+ " },\n"
+ " \"parameters\": [\n"
+ " {\n"
+ " \"name\": \"Geocentric X of topocentric origin\",\n"
+ " \"value\": 3771793.97,\n"
+ " \"unit\": \"metre\",\n"
+ " \"id\": {\n"
+ " \"authority\": \"EPSG\",\n"
+ " \"code\": 8837\n"
+ " }\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"Geocentric Y of topocentric origin\",\n"
+ " \"value\": 140253.34,\n"
+ " \"unit\": \"metre\",\n"
+ " \"id\": {\n"
+ " \"authority\": \"EPSG\",\n"
+ " \"code\": 8838\n"
+ " }\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"Geocentric Z of topocentric origin\",\n"
+ " \"value\": 5124304.35,\n"
+ " \"unit\": \"metre\",\n"
+ " \"id\": {\n"
+ " \"authority\": \"EPSG\",\n"
+ " \"code\": 8839\n"
+ " }\n"
+ " }\n"
+ " ]\n"
+ " },\n"
+ " \"coordinate_system\": {\n"
+ " \"subtype\": \"Cartesian\",\n"
+ " \"axis\": [\n"
+ " {\n"
+ " \"name\": \"Topocentric East\",\n"
+ " \"abbreviation\": \"U\",\n"
+ " \"direction\": \"east\",\n"
+ " \"unit\": \"metre\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"Topocentric North\",\n"
+ " \"abbreviation\": \"V\",\n"
+ " \"direction\": \"north\",\n"
+ " \"unit\": \"metre\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"Topocentric height\",\n"
+ " \"abbreviation\": \"W\",\n"
+ " \"direction\": \"up\",\n"
+ " \"unit\": \"metre\"\n"
+ " }\n"
+ " ]\n"
+ " },\n"
+ " \"scope\": \"Example only (fictitious).\",\n"
+ " \"area\": \"Description of the extent of the CRS.\",\n"
+ " \"bbox\": {\n"
+ " \"south_latitude\": -90,\n"
+ " \"west_longitude\": -180,\n"
+ " \"north_latitude\": 90,\n"
+ " \"east_longitude\": 180\n"
+ " },\n"
+ " \"id\": {\n"
+ " \"authority\": \"EPSG\",\n"
+ " \"code\": 5820\n"
+ " }\n"
+ "}";
+ auto obj = createFromUserInput(json, nullptr);
+ auto pcrs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
+ ASSERT_TRUE(pcrs != nullptr);
+ EXPECT_TRUE(pcrs->baseCRS()->isGeocentric());
+ EXPECT_EQ(pcrs->exportToJSON(&(JSONFormatter::create()->setSchema("foo"))),
+ json);
+}
+
+// ---------------------------------------------------------------------------
+
TEST(json_import, compound_crs) {
auto json = "{\n"
" \"$schema\": \"foo\",\n"