diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2019-11-02 15:43:42 +0100 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2019-11-02 15:43:42 +0100 |
| commit | 31fd3de9c2b2f823c01b3c2dbadddf4a7101fa16 (patch) | |
| tree | 08a18c05d5138ad6af8e5a506bccded6c22614ed | |
| parent | 3b25b5011fcb04ea56a98cf6fa5fcdb9c9aa36ae (diff) | |
| download | PROJ-31fd3de9c2b2f823c01b3c2dbadddf4a7101fa16.tar.gz PROJ-31fd3de9c2b2f823c01b3c2dbadddf4a7101fa16.zip | |
WKT and PROJJSON: add import/export of geoid model of VertCRS
| -rw-r--r-- | data/projjson.schema.json | 11 | ||||
| -rw-r--r-- | include/proj/internal/io_internal.hpp | 1 | ||||
| -rw-r--r-- | src/iso19111/crs.cpp | 31 | ||||
| -rw-r--r-- | src/iso19111/io.cpp | 35 | ||||
| -rw-r--r-- | src/iso19111/static.cpp | 1 | ||||
| -rw-r--r-- | test/cli/testprojinfo_out.dist | 2 | ||||
| -rw-r--r-- | test/unit/test_c_api.cpp | 2 | ||||
| -rw-r--r-- | test/unit/test_io.cpp | 56 |
8 files changed, 125 insertions, 14 deletions
diff --git a/data/projjson.schema.json b/data/projjson.schema.json index 60fca6df..e71e5031 100644 --- a/data/projjson.schema.json +++ b/data/projjson.schema.json @@ -1,5 +1,5 @@ { - "$id": "https://proj.org/schemas/v0.1/projjson.schema.json", + "$id": "https://proj.org/schemas/v0.2/projjson.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", "description": "Schema for PROJJSON", "$comment": "This file exists both in data/ and in schemas/vXXX/. Keep both in sync. And if changing the value of $id, change PROJJSON_CURRENT_VERSION accordingly in io.cpp", @@ -932,6 +932,15 @@ }, "datum_ensemble": { "$ref": "#/definitions/datum_ensemble" }, "coordinate_system": { "$ref": "#/definitions/coordinate_system" }, + "geoid_model": { + "type": "object", + "properties": { + "name": { "type": "string" }, + "id": { "$ref": "#/definitions/id" } + }, + "required" : [ "name" ], + "additionalProperties": false + }, "$schema" : {}, "scope": {}, "area": {}, diff --git a/include/proj/internal/io_internal.hpp b/include/proj/internal/io_internal.hpp index 781dfa6c..1e2508cc 100644 --- a/include/proj/internal/io_internal.hpp +++ b/include/proj/internal/io_internal.hpp @@ -134,6 +134,7 @@ class WKTConstants { static const std::string BASEPARAMCRS; static const std::string BASETIMECRS; static const std::string VERSION; + static const std::string GEOIDMODEL; // WKT2-2019 // WKT2 alternate (longer or shorter) static const std::string GEODETICCRS; diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp index 26725e24..b9b38c80 100644 --- a/src/iso19111/crs.cpp +++ b/src/iso19111/crs.cpp @@ -2478,6 +2478,14 @@ void VerticalCRS::_exportToWKT(io::WKTFormatter *formatter) const { cs->_exportToWKT(formatter); formatter->setOutputAxis(oldAxisOutputRule); + if (isWKT2 && formatter->use2019Keywords() && !d->geoidModel.empty()) { + const auto &model = d->geoidModel[0]; + formatter->startNode(io::WKTConstants::GEOIDMODEL, false); + formatter->addQuotedString(model->nameStr()); + model->formatID(formatter); + formatter->endNode(); + } + ObjectUsage::baseExportToWKT(formatter); formatter->endNode(); } @@ -2539,6 +2547,15 @@ void VerticalCRS::_exportToJSON( formatter->setOmitTypeInImmediateChild(); coordinateSystem()->_exportToJSON(formatter); + if (!d->geoidModel.empty()) { + const auto &model = d->geoidModel[0]; + writer.AddObjKey("geoid_model"); + auto objectContext2(formatter->MakeObjectContext(nullptr, false)); + writer.AddObjKey("name"); + writer.Add(model->nameStr()); + model->formatID(formatter); + } + ObjectUsage::baseExportToJSON(formatter); } //! @endcond @@ -2572,7 +2589,8 @@ void VerticalCRS::addLinearUnitConvert( * cs::VerticalCS. * * @param properties See \ref general_properties. - * At minimum the name should be defined. + * At minimum the name should be defined. The GEOID_MODEL property can be set + * to a TransformationNNPtr object. * @param datumIn The datum of the CRS. * @param csIn a VerticalCS. * @return new VerticalCRS. @@ -2592,7 +2610,8 @@ VerticalCRS::create(const util::PropertyMap &properties, * One and only one of datum or datumEnsemble should be set to a non-null value. * * @param properties See \ref general_properties. - * At minimum the name should be defined. + * At minimum the name should be defined. The GEOID_MODEL property can be set + * to a TransformationNNPtr object. * @param datumIn The datum of the CRS, or nullptr * @param datumEnsembleIn The datum ensemble of the CRS, or nullptr. * @param csIn a VerticalCS. @@ -2607,6 +2626,14 @@ VerticalCRS::create(const util::PropertyMap &properties, csIn)); crs->assignSelf(crs); crs->setProperties(properties); + const auto geoidModelPtr = properties.get("GEOID_MODEL"); + if (geoidModelPtr) { + auto transf = util::nn_dynamic_pointer_cast<operation::Transformation>( + *geoidModelPtr); + if (transf) { + crs->d->geoidModel.emplace_back(NN_NO_CHECK(transf)); + } + } return crs; } diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index fc66b6c9..116a8b78 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -89,7 +89,7 @@ static const std::string emptyString{}; // If changing that value, change it in data/projjson.schema.json as well #define PROJJSON_CURRENT_VERSION \ - "https://proj.org/schemas/v0.1/projjson.schema.json" + "https://proj.org/schemas/v0.2/projjson.schema.json" //! @endcond #if 0 @@ -3820,8 +3820,22 @@ CRSNNPtr WKTParser::Private::buildVerticalCRS(const WKTNodeNNPtr &node) { ThrowNotExpectedCSType("vertical"); } + auto &props = buildProperties(node); + auto &geoidModelNode = nodeP->lookForChild(WKTConstants::GEOIDMODEL); + if (!isNull(geoidModelNode)) { + auto &propsModel = buildProperties(geoidModelNode); + const auto dummyCRS = VerticalCRS::create( + PropertyMap(), datum, datumEnsemble, NN_NO_CHECK(verticalCS)); + const auto model(Transformation::create( + propsModel, dummyCRS, dummyCRS, nullptr, + OperationMethod::create(PropertyMap(), + std::vector<OperationParameterNNPtr>()), + {}, {})); + props.set("GEOID_MODEL", model); + } + auto crs = nn_static_pointer_cast<CRS>(VerticalCRS::create( - buildProperties(node), datum, datumEnsemble, NN_NO_CHECK(verticalCS))); + props, datum, datumEnsemble, NN_NO_CHECK(verticalCS))); if (!isNull(datumNode)) { auto &extensionNode = datumNode->lookForChild(WKTConstants::EXTENSION); @@ -4987,7 +5001,22 @@ VerticalCRSNNPtr JSONParser::buildVerticalCRS(const json &j) { if (!verticalCS) { throw ParsingException("expected a vertical CS"); } - return VerticalCRS::create(buildProperties(j), datum, datumEnsemble, + + auto props = buildProperties(j); + if (j.contains("geoid_model")) { + auto geoidModelJ = getObject(j, "geoid_model"); + auto propsModel = buildProperties(geoidModelJ); + const auto dummyCRS = VerticalCRS::create( + PropertyMap(), datum, datumEnsemble, NN_NO_CHECK(verticalCS)); + const auto model(Transformation::create( + propsModel, dummyCRS, dummyCRS, nullptr, + OperationMethod::create(PropertyMap(), + std::vector<OperationParameterNNPtr>()), + {}, {})); + props.set("GEOID_MODEL", model); + } + + return VerticalCRS::create(props, datum, datumEnsemble, NN_NO_CHECK(verticalCS)); } diff --git a/src/iso19111/static.cpp b/src/iso19111/static.cpp index 824047f0..0ed08c95 100644 --- a/src/iso19111/static.cpp +++ b/src/iso19111/static.cpp @@ -274,6 +274,7 @@ DEFINE_WKT_CONSTANT(BASEENGCRS); DEFINE_WKT_CONSTANT(BASEPARAMCRS); DEFINE_WKT_CONSTANT(BASETIMECRS); DEFINE_WKT_CONSTANT(VERSION); +DEFINE_WKT_CONSTANT(GEOIDMODEL); DEFINE_WKT_CONSTANT(GEODETICCRS); DEFINE_WKT_CONSTANT(GEODETICDATUM); diff --git a/test/cli/testprojinfo_out.dist b/test/cli/testprojinfo_out.dist index c1d9f3e0..40b8330a 100644 --- a/test/cli/testprojinfo_out.dist +++ b/test/cli/testprojinfo_out.dist @@ -137,7 +137,7 @@ GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.25722 PROJJSON: { - "$schema": "https://proj.org/schemas/v0.1/projjson.schema.json", + "$schema": "https://proj.org/schemas/v0.2/projjson.schema.json", "type": "GeographicCRS", "name": "WGS 84", "datum": { diff --git a/test/unit/test_c_api.cpp b/test/unit/test_c_api.cpp index 8ac5a511..5e6d1924 100644 --- a/test/unit/test_c_api.cpp +++ b/test/unit/test_c_api.cpp @@ -3600,7 +3600,7 @@ TEST_F(CApi, proj_as_projjson) { EXPECT_EQ(std::string(projjson), "{\n" " \"$schema\": " - "\"https://proj.org/schemas/v0.1/projjson.schema.json\",\n" + "\"https://proj.org/schemas/v0.2/projjson.schema.json\",\n" " \"type\": \"Ellipsoid\",\n" " \"name\": \"WGS 84\",\n" " \"semi_major_axis\": 6378137,\n" diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp index 074a59b9..6bb93e97 100644 --- a/test/unit/test_io.cpp +++ b/test/unit/test_io.cpp @@ -1960,16 +1960,21 @@ TEST(wkt_parse, vertcrs_VRF_WKT2) { // --------------------------------------------------------------------------- TEST(wkt_parse, vertcrs_with_GEOIDMODEL) { - auto wkt = "VERTCRS[\"CGVD2013\"," - " VRF[\"Canadian Geodetic Vertical Datum of 2013\"]," - " CS[vertical,1]," - " AXIS[\"gravity-related height (H)\",up]," - " LENGTHUNIT[\"metre\",1.0]," - " GEOIDMODEL[\"CGG2013\",ID[\"EPSG\",6648]]]"; + auto wkt = "VERTCRS[\"CGVD2013\",\n" + " VDATUM[\"Canadian Geodetic Vertical Datum of 2013\"],\n" + " CS[vertical,1],\n" + " AXIS[\"gravity-related height (H)\",up,\n" + " LENGTHUNIT[\"metre\",1]],\n" + " GEOIDMODEL[\"CGG2013\",\n" + " ID[\"EPSG\",6648]]]"; auto obj = WKTParser().createFromWKT(wkt); auto crs = nn_dynamic_pointer_cast<VerticalCRS>(obj); ASSERT_TRUE(crs != nullptr); + EXPECT_EQ( + crs->exportToWKT( + WKTFormatter::create(WKTFormatter::Convention::WKT2_2019).get()), + wkt); } // --------------------------------------------------------------------------- @@ -10808,6 +10813,45 @@ TEST(json_import, vertical_crs_with_datum_ensemble) { // --------------------------------------------------------------------------- +TEST(json_import, vertical_crs_with_geoid_model) { + auto json = "{\n" + " \"$schema\": \"foo\",\n" + " \"type\": \"VerticalCRS\",\n" + " \"name\": \"CGVD2013\",\n" + " \"datum\": {\n" + " \"type\": \"VerticalReferenceFrame\",\n" + " \"name\": \"Canadian Geodetic Vertical Datum of 2013\"\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" + " \"geoid_model\": {\n" + " \"name\": \"CGG2013\",\n" + " \"id\": {\n" + " \"authority\": \"EPSG\",\n" + " \"code\": 6648\n" + " }\n" + " }\n" + "}"; + + // No database + auto obj = createFromUserInput(json, nullptr); + auto vcrs = nn_dynamic_pointer_cast<VerticalCRS>(obj); + ASSERT_TRUE(vcrs != nullptr); + EXPECT_EQ(vcrs->exportToJSON(&(JSONFormatter::create()->setSchema("foo"))), + json); +} + +// --------------------------------------------------------------------------- + TEST(json_import, parametric_crs) { auto json = "{\n" " \"$schema\": \"foo\",\n" |
