Skip to content

Commit

Permalink
PROJJSON export: for a Projected CRS, add an explicit type=Geographic…
Browse files Browse the repository at this point in the history
…CRS/GeodeticCRS members to the base_crs member

This can make consumption/validation of PROJJSON easier. This doesn't
affect forward/backward compatibility as the importer is tolerant about
presence or absence of base_crs.type, and the schema too.
  • Loading branch information
rouault committed Nov 26, 2024
1 parent d0f0341 commit 17fe008
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 5 deletions.
7 changes: 7 additions & 0 deletions docs/source/specifications/projjson.rst
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,7 @@ The EPSG:32631 / "WGS 84 / UTM zone 31N" projected CRS can be expressed as
"type": "ProjectedCRS",
"name": "WGS 84 / UTM zone 31N",
"base_crs": {
"type": "GeographicCRS",
"name": "WGS 84",
"datum": {
"type": "GeodeticReferenceFrame",
Expand Down Expand Up @@ -623,6 +624,12 @@ The EPSG:32631 / "WGS 84 / UTM zone 31N" projected CRS can be expressed as
}
}
.. note::

The ``type`` member of the ``base_crs`` member was omitted in PROJ export of PROJJSON
prior to PROJ 9.6.

CompoundCRS
+++++++++++

Expand Down
1 change: 0 additions & 1 deletion src/iso19111/crs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4533,7 +4533,6 @@ void ProjectedCRS::_exportToJSON(

writer->AddObjKey("base_crs");
formatter->setAllowIDInImmediateChild();
formatter->setOmitTypeInImmediateChild();
baseCRS()->_exportToJSON(formatter);

writer->AddObjKey("conversion");
Expand Down
22 changes: 18 additions & 4 deletions test/unit/test_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15133,8 +15133,14 @@ TEST(json_import, projected_crs) {
auto obj = createFromUserInput(json, nullptr);
auto pcrs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
ASSERT_TRUE(pcrs != nullptr);
EXPECT_EQ(pcrs->exportToJSON(&(JSONFormatter::create()->setSchema("foo"))),
json);
std::string got_json =
pcrs->exportToJSON(&(JSONFormatter::create()->setSchema("foo")));
const char *typeGeogCRS = " \"type\": \"GeographicCRS\",\n";
const auto posTypeGeogCRS = got_json.find(typeGeogCRS);
EXPECT_TRUE(posTypeGeogCRS != std::string::npos) << got_json;
got_json = got_json.substr(0, posTypeGeogCRS) +
got_json.substr(posTypeGeogCRS + strlen(typeGeogCRS));
EXPECT_STREQ(got_json.c_str(), json);
}

// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -15363,8 +15369,14 @@ TEST(json_import, projected_crs_with_geocentric_base) {
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);
std::string got_json =
pcrs->exportToJSON(&(JSONFormatter::create()->setSchema("foo")));
const char *typeGeodCRS = " \"type\": \"GeodeticCRS\",\n";
const auto posTypeGeodCRS = got_json.find(typeGeodCRS);
EXPECT_TRUE(posTypeGeodCRS != std::string::npos) << got_json;
got_json = got_json.substr(0, posTypeGeodCRS) +
got_json.substr(posTypeGeodCRS + strlen(typeGeodCRS));
EXPECT_STREQ(got_json.c_str(), json);
}

// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -16153,6 +16165,7 @@ TEST(json_import, concatenated_operation) {
" \"type\": \"ProjectedCRS\",\n"
" \"name\": \"GDA94 / Vicgrid\",\n"
" \"base_crs\": {\n"
" \"type\": \"GeographicCRS\",\n"
" \"name\": \"GDA94\",\n"
" \"datum\": {\n"
" \"type\": \"GeodeticReferenceFrame\",\n"
Expand Down Expand Up @@ -17371,6 +17384,7 @@ TEST(json_import, derived_projected_crs) {
" \"type\": \"ProjectedCRS\",\n"
" \"name\": \"WGS 84 / UTM zone 31N\",\n"
" \"base_crs\": {\n"
" \"type\": \"GeographicCRS\",\n"
" \"name\": \"WGS 84\",\n"
" \"datum\": {\n"
" \"type\": \"GeodeticReferenceFrame\",\n"
Expand Down

0 comments on commit 17fe008

Please sign in to comment.