diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2019-08-10 17:44:53 +0200 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2019-08-10 17:44:53 +0200 |
| commit | 0a1261781de96d2bb8c76fbd905ebf8b0121d3a6 (patch) | |
| tree | bc08254e1603339aa5450a5ee1b680a92de66315 | |
| parent | 63981af418d84749cd4d70752f83fd551100389f (diff) | |
| download | PROJ-0a1261781de96d2bb8c76fbd905ebf8b0121d3a6.tar.gz PROJ-0a1261781de96d2bb8c76fbd905ebf8b0121d3a6.zip | |
PROJJSON: a few fixes, and add import of DerivedCRS, EngineeringCRS, ParametricCRS and TemporalCRS
| -rw-r--r-- | data/crsjson.schema.json | 55 | ||||
| -rw-r--r-- | src/iso19111/common.cpp | 2 | ||||
| -rw-r--r-- | src/iso19111/coordinatesystem.cpp | 5 | ||||
| -rw-r--r-- | src/iso19111/crs.cpp | 4 | ||||
| -rw-r--r-- | src/iso19111/io.cpp | 146 | ||||
| -rw-r--r-- | test/unit/test_io.cpp | 707 |
6 files changed, 891 insertions, 28 deletions
diff --git a/data/crsjson.schema.json b/data/crsjson.schema.json index e38f3038..10b17caa 100644 --- a/data/crsjson.schema.json +++ b/data/crsjson.schema.json @@ -37,11 +37,51 @@ "type": { "type": "string", "enum": ["Axis"] }, "name": { "type": "string" }, "abbreviation": { "type": "string" }, - "direction": { "type": "string" }, + "direction": { "type": "string", + "enum": [ "north", + "northNorthEast", + "northEast", + "eastNorthEast", + "east", + "eastSouthEast", + "southEast", + "southSouthEast", + "south", + "southSouthWest", + "southWest", + "westSouthWest", + "west", + "westNorthWest", + "northWest", + "northNorthWest", + "up", + "down", + "geocentricX", + "geocentricY", + "geocentricZ", + "columnPositive", + "columnNegative", + "rowPositive", + "rowNegative", + "displayRight", + "displayLeft", + "displayUp", + "displayDown", + "forward", + "aft", + "port", + "starboard", + "clockwise", + "counterClockwise", + "towards", + "awayFrom", + "future", + "past", + "unspecified" ] }, "unit": { "$ref": "#/definitions/unit" }, "id": { "$ref": "#/definitions/id" } }, - "required" : [ "name" ], + "required" : [ "name", "abbreviation", "direction" ], "additionalProperties": false }, @@ -135,7 +175,16 @@ "properties": { "type": { "type": "string", "enum": ["CoordinateSystem"] }, "name": { "type": "string" }, - "subtype": { "type": "string" }, + "subtype": { "type": "string", + "enum": ["Cartesian", + "spherical", + "ellipsoidal", + "vertical", + "ordinal", + "parametric", + "TemporalDateTime", + "TemporalCount", + "TemporalMeasure"] }, "axis": { "type": "array", "items": { "$ref": "#/definitions/axis" } diff --git a/src/iso19111/common.cpp b/src/iso19111/common.cpp index fb7a63c0..f375ea0a 100644 --- a/src/iso19111/common.cpp +++ b/src/iso19111/common.cpp @@ -257,7 +257,7 @@ void UnitOfMeasure::_exportToJSON( } else if (l_type == Type::TIME) { writer.Add("TimeUnit"); } else if (l_type == Type::PARAMETRIC) { - writer.Add("ParametericUnit"); + writer.Add("ParametricUnit"); } else { writer.Add("Unit"); } diff --git a/src/iso19111/coordinatesystem.cpp b/src/iso19111/coordinatesystem.cpp index ef53dd57..5a852b0d 100644 --- a/src/iso19111/coordinatesystem.cpp +++ b/src/iso19111/coordinatesystem.cpp @@ -409,12 +409,13 @@ void CoordinateSystemAxis::_exportToJSON( writer.AddObjKey("direction"); writer.Add(direction().toString()); - writer.AddObjKey("unit"); const auto &l_unit(unit()); if (l_unit == common::UnitOfMeasure::METRE || l_unit == common::UnitOfMeasure::DEGREE) { + writer.AddObjKey("unit"); writer.Add(l_unit.name()); - } else { + } else if (l_unit.type() != common::UnitOfMeasure::Type::NONE) { + writer.AddObjKey("unit"); l_unit._exportToJSON(formatter); } diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp index b03ece23..b9694ba2 100644 --- a/src/iso19111/crs.cpp +++ b/src/iso19111/crs.cpp @@ -2711,6 +2711,7 @@ void DerivedCRS::_exportToJSON( baseCRS()->_exportToJSON(formatter); writer.AddObjKey("conversion"); + formatter->setOmitTypeInImmediateChild(); derivingConversionRef()->_exportToJSON(formatter); writer.AddObjKey("coordinate_system"); @@ -4837,6 +4838,7 @@ void TemporalCRS::_exportToJSON( } writer.AddObjKey("datum"); + formatter->setOmitTypeInImmediateChild(); datum()->_exportToJSON(formatter); writer.AddObjKey("coordinate_system"); @@ -4974,6 +4976,7 @@ void EngineeringCRS::_exportToJSON( } writer.AddObjKey("datum"); + formatter->setOmitTypeInImmediateChild(); datum()->_exportToJSON(formatter); writer.AddObjKey("coordinate_system"); @@ -5105,6 +5108,7 @@ void ParametricCRS::_exportToJSON( } writer.AddObjKey("datum"); + formatter->setOmitTypeInImmediateChild(); datum()->_exportToJSON(formatter); writer.AddObjKey("coordinate_system"); diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index 8467a9e1..cd54f4ea 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -4414,6 +4414,61 @@ class JSONParser { TransformationNNPtr buildTransformation(const json &j); ConcatenatedOperationNNPtr buildConcatenatedOperation(const json &j); + static util::optional<std::string> getAnchor(const json &j) { + util::optional<std::string> anchor; + if (j.contains("anchor")) { + anchor = getString(j, "anchor"); + } + return anchor; + } + + EngineeringDatumNNPtr buildEngineeringDatum(const json &j) { + return EngineeringDatum::create(buildProperties(j), getAnchor(j)); + } + + ParametricDatumNNPtr buildParametricDatum(const json &j) { + return ParametricDatum::create(buildProperties(j), getAnchor(j)); + } + + TemporalDatumNNPtr buildTemporalDatum(const json &j) { + auto calendar = getString(j, "calendar"); + auto origin = DateTime::create(j.contains("time_origin") + ? getString(j, "time_origin") + : std::string()); + return TemporalDatum::create(buildProperties(j), origin, calendar); + } + + template <class TargetCRS, class DatumBuilderType, + class CS = CoordinateSystem> + util::nn<std::shared_ptr<TargetCRS>> buildCRS(const json &j, + DatumBuilderType f) { + auto datum = (this->*f)(getObject(j, "datum")); + auto cs = buildCS(getObject(j, "coordinate_system")); + auto csCast = util::nn_dynamic_pointer_cast<CS>(cs); + if (!csCast) { + throw ParsingException("coordinate_system not of expected type"); + } + return TargetCRS::create(buildProperties(j), datum, + NN_NO_CHECK(csCast)); + } + + template <class TargetCRS, class BaseCRS, class CS = CoordinateSystem> + util::nn<std::shared_ptr<TargetCRS>> buildDerivedCRS(const json &j) { + auto baseCRSObj = create(getObject(j, "base_crs")); + auto baseCRS = util::nn_dynamic_pointer_cast<BaseCRS>(baseCRSObj); + if (!baseCRS) { + throw ParsingException("base_crs not of expected type"); + } + auto cs = buildCS(getObject(j, "coordinate_system")); + auto csCast = util::nn_dynamic_pointer_cast<CS>(cs); + if (!csCast) { + throw ParsingException("coordinate_system not of expected type"); + } + auto conv = buildConversion(getObject(j, "conversion")); + return TargetCRS::create(buildProperties(j), NN_NO_CHECK(baseCRS), conv, + NN_NO_CHECK(csCast)); + } + public: JSONParser() = default; @@ -4511,7 +4566,7 @@ UnitOfMeasure JSONParser::getUnit(const json &j, const char *key) { type = UnitOfMeasure::Type::SCALE; } else if (typeStr == "TimeUnit") { type = UnitOfMeasure::Type::TIME; - } else if (typeStr == "ParametericUnit") { + } else if (typeStr == "ParametricUnit") { type = UnitOfMeasure::Type::PARAMETRIC; } else if (typeStr == "Unit") { type = UnitOfMeasure::Type::UNKNOWN; @@ -4695,6 +4750,58 @@ BaseObjectNNPtr JSONParser::create(const json &j) if (type == "BoundCRS") { return buildBoundCRS(j); } + if (type == "EngineeringCRS") { + return buildCRS<EngineeringCRS>(j, &JSONParser::buildEngineeringDatum); + } + if (type == "ParametricCRS") { + return buildCRS<ParametricCRS, + decltype(&JSONParser::buildParametricDatum), + ParametricCS>(j, &JSONParser::buildParametricDatum); + } + if (type == "TemporalCRS") { + return buildCRS<TemporalCRS, decltype(&JSONParser::buildTemporalDatum), + TemporalCS>(j, &JSONParser::buildTemporalDatum); + } + if (type == "DerivedGeodeticCRS") { + auto baseCRSObj = create(getObject(j, "base_crs")); + auto baseCRS = util::nn_dynamic_pointer_cast<GeodeticCRS>(baseCRSObj); + if (!baseCRS) { + throw ParsingException("base_crs not of expected type"); + } + auto cs = buildCS(getObject(j, "coordinate_system")); + auto conv = buildConversion(getObject(j, "conversion")); + auto csCartesian = util::nn_dynamic_pointer_cast<CartesianCS>(cs); + if (csCartesian) + return DerivedGeodeticCRS::create(buildProperties(j), + NN_NO_CHECK(baseCRS), conv, + NN_NO_CHECK(csCartesian)); + auto csSpherical = util::nn_dynamic_pointer_cast<SphericalCS>(cs); + if (csSpherical) + return DerivedGeodeticCRS::create(buildProperties(j), + NN_NO_CHECK(baseCRS), conv, + NN_NO_CHECK(csSpherical)); + throw ParsingException("coordinate_system not of expected type"); + } + if (type == "DerivedGeographicCRS") { + return buildDerivedCRS<DerivedGeographicCRS, GeodeticCRS, + EllipsoidalCS>(j); + } + if (type == "DerivedProjectedCRS") { + return buildDerivedCRS<DerivedProjectedCRS, ProjectedCRS>(j); + } + if (type == "DerivedVerticalCRS") { + return buildDerivedCRS<DerivedVerticalCRS, VerticalCRS, VerticalCS>(j); + } + if (type == "DerivedEngineeringCRS") { + return buildDerivedCRS<DerivedEngineeringCRS, EngineeringCRS>(j); + } + if (type == "DerivedParametricCRS") { + return buildDerivedCRS<DerivedParametricCRS, ParametricCRS, + ParametricCS>(j); + } + if (type == "DerivedTemporalCRS") { + return buildDerivedCRS<DerivedTemporalCRS, TemporalCRS, TemporalCS>(j); + } if (type == "DatumEnsemble") { return buildDatumEnsemble(j); } @@ -4710,6 +4817,15 @@ BaseObjectNNPtr JSONParser::create(const json &j) if (type == "DynamicVerticalReferenceFrame") { return buildDynamicVerticalReferenceFrame(j); } + if (type == "EngineeringDatum") { + return buildEngineeringDatum(j); + } + if (type == "ParametricDatum") { + return buildParametricDatum(j); + } + if (type == "TemporalDatum") { + return buildTemporalDatum(j); + } if (type == "Ellipsoid") { return buildEllipsoid(j); } @@ -5033,7 +5149,9 @@ JSONParser::buildConcatenatedOperation(const json &j) { CoordinateSystemAxisNNPtr JSONParser::buildAxis(const json &j) { auto dirString = getString(j, "direction"); auto abbreviation = getString(j, "abbreviation"); - auto unit = getUnit(j, "unit"); + auto unit = j.contains("unit") ? getUnit(j, "unit") + : UnitOfMeasure(std::string(), 1.0, + UnitOfMeasure::Type::NONE); auto direction = AxisDirection::valueOf(dirString); if (!direction) { throw ParsingException(concat("unhandled axis direction: ", dirString)); @@ -5198,12 +5316,8 @@ 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), anchor, pm); + buildProperties(j), buildEllipsoid(ellipsoidJ), getAnchor(j), pm); } // --------------------------------------------------------------------------- @@ -5214,10 +5328,6 @@ JSONParser::buildDynamicGeodeticReferenceFrame(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"); - } Measure frameReferenceEpoch(getNumber(j, "frame_reference_epoch"), UnitOfMeasure::YEAR); optional<std::string> deformationModel; @@ -5225,7 +5335,7 @@ JSONParser::buildDynamicGeodeticReferenceFrame(const json &j) { deformationModel = getString(j, "deformation_model"); } return DynamicGeodeticReferenceFrame::create( - buildProperties(j), buildEllipsoid(ellipsoidJ), anchor, pm, + buildProperties(j), buildEllipsoid(ellipsoidJ), getAnchor(j), pm, frameReferenceEpoch, deformationModel); } @@ -5233,21 +5343,13 @@ JSONParser::buildDynamicGeodeticReferenceFrame(const json &j) { VerticalReferenceFrameNNPtr JSONParser::buildVerticalReferenceFrame(const json &j) { - optional<std::string> anchor; - if (j.contains("anchor")) { - anchor = getString(j, "anchor"); - } - return VerticalReferenceFrame::create(buildProperties(j), anchor); + return VerticalReferenceFrame::create(buildProperties(j), getAnchor(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; @@ -5255,7 +5357,7 @@ JSONParser::buildDynamicVerticalReferenceFrame(const json &j) { deformationModel = getString(j, "deformation_model"); } return DynamicVerticalReferenceFrame::create( - buildProperties(j), anchor, util::optional<RealizationMethod>(), + buildProperties(j), getAnchor(j), util::optional<RealizationMethod>(), frameReferenceEpoch, deformationModel); } diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp index 67fdcb77..74ef82f3 100644 --- a/test/unit/test_io.cpp +++ b/test/unit/test_io.cpp @@ -10581,6 +10581,41 @@ TEST(json_import, datum_ensemble_without_ellipsoid) { // --------------------------------------------------------------------------- +TEST(json_import, vertical_crs) { + auto json = "{\n" + " \"type\": \"VerticalCRS\",\n" + " \"name\": \"EGM2008 height\",\n" + " \"datum\": {\n" + " \"type\": \"VerticalReferenceFrame\",\n" + " \"name\": \"EGM2008 geoid\"\n" + " },\n" + " \"coordinate_system\": {\n" + " \"subtype\": \"vertical\",\n" + " \"axis\": [\n" + " {\n" + " \"name\": \"Gravity-related height\",\n" + " \"abbreviation\": \"H\",\n" + " \"direction\": \"up\",\n" + " \"unit\": \"metre\"\n" + " }\n" + " ]\n" + " }\n" + "}"; + + auto obj = createFromUserInput(json, nullptr); + auto crs = nn_dynamic_pointer_cast<VerticalCRS>(obj); + ASSERT_TRUE(crs != nullptr); + EXPECT_EQ(crs->exportToJSON((JSONFormatter::create().get())), json); + + auto datum = crs->datum(); + auto datum_json = datum->exportToJSON((JSONFormatter::create().get())); + auto datum_obj = createFromUserInput(datum_json, nullptr); + auto datum_got = nn_dynamic_pointer_cast<VerticalReferenceFrame>(datum_obj); + ASSERT_TRUE(datum_got != nullptr); +} + +// --------------------------------------------------------------------------- + TEST(json_import, vertical_crs_with_datum_ensemble) { auto json = "{\n" " \"type\": \"VerticalCRS\",\n" @@ -10616,3 +10651,675 @@ TEST(json_import, vertical_crs_with_datum_ensemble) { ASSERT_TRUE(vcrs != nullptr); EXPECT_EQ(vcrs->exportToJSON((JSONFormatter::create().get())), json); } + +// --------------------------------------------------------------------------- + +TEST(json_import, parametric_crs) { + auto json = "{\n" + " \"type\": \"ParametricCRS\",\n" + " \"name\": \"WMO standard atmosphere layer 0\",\n" + " \"datum\": {\n" + " \"name\": \"Mean Sea Level\",\n" + " \"anchor\": \"1013.25 hPa at 15°C\"\n" + " },\n" + " \"coordinate_system\": {\n" + " \"subtype\": \"parametric\",\n" + " \"axis\": [\n" + " {\n" + " \"name\": \"Pressure\",\n" + " \"abbreviation\": \"hPa\",\n" + " \"direction\": \"up\",\n" + " \"unit\": {\n" + " \"type\": \"ParametricUnit\",\n" + " \"name\": \"HectoPascal\",\n" + " \"conversion_factor\": 100\n" + " }\n" + " }\n" + " ]\n" + " }\n" + "}"; + + auto obj = createFromUserInput(json, nullptr); + auto crs = nn_dynamic_pointer_cast<ParametricCRS>(obj); + ASSERT_TRUE(crs != nullptr); + EXPECT_EQ(crs->exportToJSON((JSONFormatter::create().get())), json); + + auto datum = crs->datum(); + auto datum_json = datum->exportToJSON((JSONFormatter::create().get())); + auto datum_obj = createFromUserInput(datum_json, nullptr); + auto datum_got = nn_dynamic_pointer_cast<ParametricDatum>(datum_obj); + ASSERT_TRUE(datum_got != nullptr); +} + +// --------------------------------------------------------------------------- + +TEST(json_import, engineering_crs) { + auto json = "{\n" + " \"type\": \"EngineeringCRS\",\n" + " \"name\": \"Engineering CRS\",\n" + " \"datum\": {\n" + " \"name\": \"Engineering datum\"\n" + " },\n" + " \"coordinate_system\": {\n" + " \"subtype\": \"Cartesian\",\n" + " \"axis\": [\n" + " {\n" + " \"name\": \"Easting\",\n" + " \"abbreviation\": \"E\",\n" + " \"direction\": \"east\",\n" + " \"unit\": \"metre\"\n" + " },\n" + " {\n" + " \"name\": \"Northing\",\n" + " \"abbreviation\": \"N\",\n" + " \"direction\": \"north\",\n" + " \"unit\": \"metre\"\n" + " }\n" + " ]\n" + " }\n" + "}"; + + auto obj = createFromUserInput(json, nullptr); + auto crs = nn_dynamic_pointer_cast<EngineeringCRS>(obj); + ASSERT_TRUE(crs != nullptr); + EXPECT_EQ(crs->exportToJSON((JSONFormatter::create().get())), json); + + auto datum = crs->datum(); + auto datum_json = datum->exportToJSON((JSONFormatter::create().get())); + auto datum_obj = createFromUserInput(datum_json, nullptr); + auto datum_got = nn_dynamic_pointer_cast<EngineeringDatum>(datum_obj); + ASSERT_TRUE(datum_got != nullptr); +} + +// --------------------------------------------------------------------------- + +TEST(json_import, temporal_crs) { + auto json = "{\n" + " \"type\": \"TemporalCRS\",\n" + " \"name\": \"Temporal CRS\",\n" + " \"datum\": {\n" + " \"name\": \"Gregorian calendar\",\n" + " \"calendar\": \"proleptic Gregorian\",\n" + " \"time_origin\": \"0000-01-01\"\n" + " },\n" + " \"coordinate_system\": {\n" + " \"subtype\": \"TemporalDateTime\",\n" + " \"axis\": [\n" + " {\n" + " \"name\": \"Time\",\n" + " \"abbreviation\": \"T\",\n" + " \"direction\": \"future\"\n" + " }\n" + " ]\n" + " }\n" + "}"; + + auto obj = createFromUserInput(json, nullptr); + auto crs = nn_dynamic_pointer_cast<TemporalCRS>(obj); + ASSERT_TRUE(crs != nullptr); + EXPECT_EQ(crs->exportToJSON((JSONFormatter::create().get())), json); + + auto datum = crs->datum(); + auto datum_json = datum->exportToJSON((JSONFormatter::create().get())); + auto datum_obj = createFromUserInput(datum_json, nullptr); + auto datum_got = nn_dynamic_pointer_cast<TemporalDatum>(datum_obj); + ASSERT_TRUE(datum_got != nullptr); +} + +// --------------------------------------------------------------------------- + +TEST(json_import, derived_geodetic_crs) { + auto json = "{\n" + " \"type\": \"DerivedGeodeticCRS\",\n" + " \"name\": \"Derived geodetic CRS\",\n" + " \"base_crs\": {\n" + " \"type\": \"GeographicCRS\",\n" + " \"name\": \"WGS 84\",\n" + " \"datum\": {\n" + " \"type\": \"GeodeticReferenceFrame\",\n" + " \"name\": \"World Geodetic System 1984\",\n" + " \"ellipsoid\": {\n" + " \"name\": \"WGS 84\",\n" + " \"semi_major_axis\": 6378137,\n" + " \"inverse_flattening\": 298.257223563\n" + " }\n" + " },\n" + " \"coordinate_system\": {\n" + " \"subtype\": \"ellipsoidal\",\n" + " \"axis\": [\n" + " {\n" + " \"name\": \"Latitude\",\n" + " \"abbreviation\": \"lat\",\n" + " \"direction\": \"north\",\n" + " \"unit\": \"degree\"\n" + " },\n" + " {\n" + " \"name\": \"Longitude\",\n" + " \"abbreviation\": \"lon\",\n" + " \"direction\": \"east\",\n" + " \"unit\": \"degree\"\n" + " }\n" + " ]\n" + " }\n" + " },\n" + " \"conversion\": {\n" + " \"name\": \"Some conversion\",\n" + " \"method\": {\n" + " \"name\": \"Some method\"\n" + " },\n" + " \"parameters\": [\n" + " {\n" + " \"name\": \"foo\",\n" + " \"value\": 1,\n" + " \"unit\": \"metre\"\n" + " }\n" + " ]\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" + "}"; + auto obj = createFromUserInput(json, nullptr); + auto crs = nn_dynamic_pointer_cast<DerivedGeodeticCRS>(obj); + ASSERT_TRUE(crs != nullptr); + EXPECT_EQ(crs->exportToJSON((JSONFormatter::create().get())), json); +} + +// --------------------------------------------------------------------------- + +TEST(json_import, derived_geographic_crs) { + auto json = "{\n" + " \"type\": \"DerivedGeographicCRS\",\n" + " \"name\": \"WMO Atlantic Pole\",\n" + " \"base_crs\": {\n" + " \"type\": \"GeographicCRS\",\n" + " \"name\": \"WGS 84\",\n" + " \"datum\": {\n" + " \"type\": \"GeodeticReferenceFrame\",\n" + " \"name\": \"World Geodetic System 1984\",\n" + " \"ellipsoid\": {\n" + " \"name\": \"WGS 84\",\n" + " \"semi_major_axis\": 6378137,\n" + " \"inverse_flattening\": 298.257223563\n" + " }\n" + " },\n" + " \"coordinate_system\": {\n" + " \"subtype\": \"ellipsoidal\",\n" + " \"axis\": [\n" + " {\n" + " \"name\": \"Latitude\",\n" + " \"abbreviation\": \"lat\",\n" + " \"direction\": \"north\",\n" + " \"unit\": \"degree\"\n" + " },\n" + " {\n" + " \"name\": \"Longitude\",\n" + " \"abbreviation\": \"lon\",\n" + " \"direction\": \"east\",\n" + " \"unit\": \"degree\"\n" + " }\n" + " ]\n" + " }\n" + " },\n" + " \"conversion\": {\n" + " \"name\": \"Atlantic pole\",\n" + " \"method\": {\n" + " \"name\": \"Pole rotation\"\n" + " },\n" + " \"parameters\": [\n" + " {\n" + " \"name\": \"Latitude of rotated pole\",\n" + " \"value\": 52,\n" + " \"unit\": \"degree\"\n" + " },\n" + " {\n" + " \"name\": \"Longitude of rotated pole\",\n" + " \"value\": -30,\n" + " \"unit\": \"degree\"\n" + " },\n" + " {\n" + " \"name\": \"Axis rotation\",\n" + " \"value\": -25,\n" + " \"unit\": \"degree\"\n" + " }\n" + " ]\n" + " },\n" + " \"coordinate_system\": {\n" + " \"subtype\": \"ellipsoidal\",\n" + " \"axis\": [\n" + " {\n" + " \"name\": \"Latitude\",\n" + " \"abbreviation\": \"lat\",\n" + " \"direction\": \"north\",\n" + " \"unit\": \"degree\"\n" + " },\n" + " {\n" + " \"name\": \"Longitude\",\n" + " \"abbreviation\": \"lon\",\n" + " \"direction\": \"east\",\n" + " \"unit\": \"degree\"\n" + " }\n" + " ]\n" + " }\n" + "}"; + auto obj = createFromUserInput(json, nullptr); + auto crs = nn_dynamic_pointer_cast<DerivedGeographicCRS>(obj); + ASSERT_TRUE(crs != nullptr); + EXPECT_EQ(crs->exportToJSON((JSONFormatter::create().get())), json); +} + +// --------------------------------------------------------------------------- + +TEST(json_import, derived_projected_crs) { + auto json = "{\n" + " \"type\": \"DerivedProjectedCRS\",\n" + " \"name\": \"derived projectedCRS\",\n" + " \"base_crs\": {\n" + " \"type\": \"ProjectedCRS\",\n" + " \"name\": \"WGS 84 / UTM zone 31N\",\n" + " \"base_crs\": {\n" + " \"name\": \"WGS 84\",\n" + " \"datum\": {\n" + " \"type\": \"GeodeticReferenceFrame\",\n" + " \"name\": \"World Geodetic System 1984\",\n" + " \"ellipsoid\": {\n" + " \"name\": \"WGS 84\",\n" + " \"semi_major_axis\": 6378137,\n" + " \"inverse_flattening\": 298.257223563\n" + " }\n" + " },\n" + " \"coordinate_system\": {\n" + " \"subtype\": \"ellipsoidal\",\n" + " \"axis\": [\n" + " {\n" + " \"name\": \"Latitude\",\n" + " \"abbreviation\": \"lat\",\n" + " \"direction\": \"north\",\n" + " \"unit\": \"degree\"\n" + " },\n" + " {\n" + " \"name\": \"Longitude\",\n" + " \"abbreviation\": \"lon\",\n" + " \"direction\": \"east\",\n" + " \"unit\": \"degree\"\n" + " }\n" + " ]\n" + " }\n" + " },\n" + " \"conversion\": {\n" + " \"name\": \"UTM zone 31N\",\n" + " \"method\": {\n" + " \"name\": \"Transverse Mercator\",\n" + " \"id\": {\n" + " \"authority\": \"EPSG\",\n" + " \"code\": 9807\n" + " }\n" + " },\n" + " \"parameters\": [\n" + " {\n" + " \"name\": \"Latitude of natural origin\",\n" + " \"value\": 0,\n" + " \"unit\": \"degree\",\n" + " \"id\": {\n" + " \"authority\": \"EPSG\",\n" + " \"code\": 8801\n" + " }\n" + " },\n" + " {\n" + " \"name\": \"Longitude of natural origin\",\n" + " \"value\": 3,\n" + " \"unit\": \"degree\",\n" + " \"id\": {\n" + " \"authority\": \"EPSG\",\n" + " \"code\": 8802\n" + " }\n" + " },\n" + " {\n" + " \"name\": \"Scale factor at natural origin\",\n" + " \"value\": 0.9996,\n" + " \"unit\": \"unity\",\n" + " \"id\": {\n" + " \"authority\": \"EPSG\",\n" + " \"code\": 8805\n" + " }\n" + " },\n" + " {\n" + " \"name\": \"False easting\",\n" + " \"value\": 500000,\n" + " \"unit\": \"metre\",\n" + " \"id\": {\n" + " \"authority\": \"EPSG\",\n" + " \"code\": 8806\n" + " }\n" + " },\n" + " {\n" + " \"name\": \"False northing\",\n" + " \"value\": 0,\n" + " \"unit\": \"metre\",\n" + " \"id\": {\n" + " \"authority\": \"EPSG\",\n" + " \"code\": 8807\n" + " }\n" + " }\n" + " ]\n" + " },\n" + " \"coordinate_system\": {\n" + " \"subtype\": \"Cartesian\",\n" + " \"axis\": [\n" + " {\n" + " \"name\": \"Easting\",\n" + " \"abbreviation\": \"E\",\n" + " \"direction\": \"east\",\n" + " \"unit\": \"metre\"\n" + " },\n" + " {\n" + " \"name\": \"Northing\",\n" + " \"abbreviation\": \"N\",\n" + " \"direction\": \"north\",\n" + " \"unit\": \"metre\"\n" + " }\n" + " ]\n" + " }\n" + " },\n" + " \"conversion\": {\n" + " \"name\": \"unnamed\",\n" + " \"method\": {\n" + " \"name\": \"PROJ unimplemented\"\n" + " },\n" + " \"parameters\": [\n" + " {\n" + " \"name\": \"foo\",\n" + " \"value\": 1,\n" + " \"unit\": \"metre\"\n" + " }\n" + " ]\n" + " },\n" + " \"coordinate_system\": {\n" + " \"subtype\": \"Cartesian\",\n" + " \"axis\": [\n" + " {\n" + " \"name\": \"Easting\",\n" + " \"abbreviation\": \"E\",\n" + " \"direction\": \"east\",\n" + " \"unit\": \"metre\"\n" + " },\n" + " {\n" + " \"name\": \"Northing\",\n" + " \"abbreviation\": \"N\",\n" + " \"direction\": \"north\",\n" + " \"unit\": \"metre\"\n" + " }\n" + " ]\n" + " }\n" + "}"; + auto obj = createFromUserInput(json, nullptr); + auto crs = nn_dynamic_pointer_cast<DerivedProjectedCRS>(obj); + ASSERT_TRUE(crs != nullptr); + EXPECT_EQ(crs->exportToJSON((JSONFormatter::create().get())), json); +} + +// --------------------------------------------------------------------------- + +TEST(json_import, derived_vertical_crs) { + auto json = "{\n" + " \"type\": \"DerivedVerticalCRS\",\n" + " \"name\": \"Derived vertCRS\",\n" + " \"base_crs\": {\n" + " \"type\": \"VerticalCRS\",\n" + " \"name\": \"ODN height\",\n" + " \"datum\": {\n" + " \"type\": \"VerticalReferenceFrame\",\n" + " \"name\": \"Ordnance Datum Newlyn\"\n" + " },\n" + " \"coordinate_system\": {\n" + " \"subtype\": \"vertical\",\n" + " \"axis\": [\n" + " {\n" + " \"name\": \"Gravity-related height\",\n" + " \"abbreviation\": \"H\",\n" + " \"direction\": \"up\",\n" + " \"unit\": \"metre\"\n" + " }\n" + " ]\n" + " }\n" + " },\n" + " \"conversion\": {\n" + " \"name\": \"unnamed\",\n" + " \"method\": {\n" + " \"name\": \"PROJ unimplemented\"\n" + " },\n" + " \"parameters\": [\n" + " {\n" + " \"name\": \"foo\",\n" + " \"value\": 1,\n" + " \"unit\": \"metre\"\n" + " }\n" + " ]\n" + " },\n" + " \"coordinate_system\": {\n" + " \"subtype\": \"vertical\",\n" + " \"axis\": [\n" + " {\n" + " \"name\": \"Gravity-related height\",\n" + " \"abbreviation\": \"H\",\n" + " \"direction\": \"up\",\n" + " \"unit\": \"metre\"\n" + " }\n" + " ]\n" + " }\n" + "}"; + auto obj = createFromUserInput(json, nullptr); + auto crs = nn_dynamic_pointer_cast<DerivedVerticalCRS>(obj); + ASSERT_TRUE(crs != nullptr); + EXPECT_EQ(crs->exportToJSON((JSONFormatter::create().get())), json); +} + +// --------------------------------------------------------------------------- + +TEST(json_import, derived_engineering_crs) { + auto json = "{\n" + " \"type\": \"DerivedEngineeringCRS\",\n" + " \"name\": \"Derived EngineeringCRS\",\n" + " \"base_crs\": {\n" + " \"type\": \"EngineeringCRS\",\n" + " \"name\": \"Engineering CRS\",\n" + " \"datum\": {\n" + " \"name\": \"Engineering datum\"\n" + " },\n" + " \"coordinate_system\": {\n" + " \"subtype\": \"Cartesian\",\n" + " \"axis\": [\n" + " {\n" + " \"name\": \"Easting\",\n" + " \"abbreviation\": \"E\",\n" + " \"direction\": \"east\",\n" + " \"unit\": \"metre\"\n" + " },\n" + " {\n" + " \"name\": \"Northing\",\n" + " \"abbreviation\": \"N\",\n" + " \"direction\": \"north\",\n" + " \"unit\": \"metre\"\n" + " }\n" + " ]\n" + " }\n" + " },\n" + " \"conversion\": {\n" + " \"name\": \"unnamed\",\n" + " \"method\": {\n" + " \"name\": \"PROJ unimplemented\"\n" + " },\n" + " \"parameters\": [\n" + " {\n" + " \"name\": \"foo\",\n" + " \"value\": 1,\n" + " \"unit\": \"metre\"\n" + " }\n" + " ]\n" + " },\n" + " \"coordinate_system\": {\n" + " \"subtype\": \"Cartesian\",\n" + " \"axis\": [\n" + " {\n" + " \"name\": \"Easting\",\n" + " \"abbreviation\": \"E\",\n" + " \"direction\": \"east\",\n" + " \"unit\": \"metre\"\n" + " },\n" + " {\n" + " \"name\": \"Northing\",\n" + " \"abbreviation\": \"N\",\n" + " \"direction\": \"north\",\n" + " \"unit\": \"metre\"\n" + " }\n" + " ]\n" + " }\n" + "}"; + auto obj = createFromUserInput(json, nullptr); + auto crs = nn_dynamic_pointer_cast<DerivedEngineeringCRS>(obj); + ASSERT_TRUE(crs != nullptr); + EXPECT_EQ(crs->exportToJSON((JSONFormatter::create().get())), json); +} + +// --------------------------------------------------------------------------- + +TEST(json_import, derived_parametric_crs) { + auto json = "{\n" + " \"type\": \"DerivedParametricCRS\",\n" + " \"name\": \"Derived ParametricCRS\",\n" + " \"base_crs\": {\n" + " \"type\": \"ParametricCRS\",\n" + " \"name\": \"Parametric CRS\",\n" + " \"datum\": {\n" + " \"name\": \"Parametric datum\"\n" + " },\n" + " \"coordinate_system\": {\n" + " \"subtype\": \"parametric\",\n" + " \"axis\": [\n" + " {\n" + " \"name\": \"unknown parametric\",\n" + " \"abbreviation\": \"\",\n" + " \"direction\": \"unspecified\",\n" + " \"unit\": {\n" + " \"type\": \"ParametricUnit\",\n" + " \"name\": \"unknown\",\n" + " \"conversion_factor\": 1\n" + " }\n" + " }\n" + " ]\n" + " }\n" + " },\n" + " \"conversion\": {\n" + " \"name\": \"unnamed\",\n" + " \"method\": {\n" + " \"name\": \"PROJ unimplemented\"\n" + " },\n" + " \"parameters\": [\n" + " {\n" + " \"name\": \"foo\",\n" + " \"value\": 1,\n" + " \"unit\": \"metre\"\n" + " }\n" + " ]\n" + " },\n" + " \"coordinate_system\": {\n" + " \"subtype\": \"parametric\",\n" + " \"axis\": [\n" + " {\n" + " \"name\": \"Pressure\",\n" + " \"abbreviation\": \"hPa\",\n" + " \"direction\": \"up\",\n" + " \"unit\": {\n" + " \"type\": \"ParametricUnit\",\n" + " \"name\": \"HectoPascal\",\n" + " \"conversion_factor\": 100\n" + " }\n" + " }\n" + " ]\n" + " }\n" + "}"; + auto obj = createFromUserInput(json, nullptr); + auto crs = nn_dynamic_pointer_cast<DerivedParametricCRS>(obj); + ASSERT_TRUE(crs != nullptr); + EXPECT_EQ(crs->exportToJSON((JSONFormatter::create().get())), json); +} + +// --------------------------------------------------------------------------- + +TEST(json_import, derived_temporal_crs) { + auto json = "{\n" + " \"type\": \"DerivedTemporalCRS\",\n" + " \"name\": \"Derived TemporalCRS\",\n" + " \"base_crs\": {\n" + " \"type\": \"TemporalCRS\",\n" + " \"name\": \"Temporal CRS\",\n" + " \"datum\": {\n" + " \"name\": \"Gregorian calendar\",\n" + " \"calendar\": \"proleptic Gregorian\",\n" + " \"time_origin\": \"0000-01-01\"\n" + " },\n" + " \"coordinate_system\": {\n" + " \"subtype\": \"TemporalDateTime\",\n" + " \"axis\": [\n" + " {\n" + " \"name\": \"unknown temporal\",\n" + " \"abbreviation\": \"\",\n" + " \"direction\": \"future\",\n" + " \"unit\": {\n" + " \"type\": \"TimeUnit\",\n" + " \"name\": \"unknown\",\n" + " \"conversion_factor\": 1\n" + " }\n" + " }\n" + " ]\n" + " }\n" + " },\n" + " \"conversion\": {\n" + " \"name\": \"unnamed\",\n" + " \"method\": {\n" + " \"name\": \"PROJ unimplemented\"\n" + " },\n" + " \"parameters\": [\n" + " {\n" + " \"name\": \"foo\",\n" + " \"value\": 1,\n" + " \"unit\": \"metre\"\n" + " }\n" + " ]\n" + " },\n" + " \"coordinate_system\": {\n" + " \"subtype\": \"TemporalDateTime\",\n" + " \"axis\": [\n" + " {\n" + " \"name\": \"Time\",\n" + " \"abbreviation\": \"T\",\n" + " \"direction\": \"future\"\n" + " }\n" + " ]\n" + " }\n" + "}"; + auto obj = createFromUserInput(json, nullptr); + auto crs = nn_dynamic_pointer_cast<DerivedTemporalCRS>(obj); + ASSERT_TRUE(crs != nullptr); + EXPECT_EQ(crs->exportToJSON((JSONFormatter::create().get())), json); +} |
