Skip to content

Commit

Permalink
JSON TileMatrixSet parser: accept crs.uri and crs.wkt encodings
Browse files Browse the repository at this point in the history
Fixes #10989
  • Loading branch information
rouault committed Oct 11, 2024
1 parent 6cf71ee commit b979373
Show file tree
Hide file tree
Showing 3 changed files with 280 additions and 3 deletions.
243 changes: 243 additions & 0 deletions autotest/cpp/test_gdal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2548,6 +2548,249 @@ TEST_F(test_gdal, TileMatrixSet)
}
}
}

// TMS v2 with crs.uri
{
auto poTMS = gdal::TileMatrixSet::parse(
"{"
" \"id\" : \"test\","
" \"title\" : \"test\","
" \"uri\" : "
"\"http://www.opengis.net/def/tilematrixset/OGC/1.0/test\","
" \"crs\" : {\"uri\": "
"\"http://www.opengis.net/def/crs/EPSG/0/4326\"},"
" \"orderedAxes\" : ["
" \"Lat\","
" \"Lon\""
" ],"
" \"wellKnownScaleSet\" : "
"\"http://www.opengis.net/def/wkss/OGC/1.0/GoogleCRS84Quad\","
" \"tileMatrices\" : ["
" {"
" \"id\" : \"0\","
" \"scaleDenominator\" : 139770566.0071794390678,"
" \"cellSize\" : 0.3515625,"
" \"cornerOfOrigin\" : \"topLeft\","
" \"pointOfOrigin\" : [ 90, -180 ],"
" \"matrixWidth\" : 4,"
" \"matrixHeight\" : 2,"
" \"tileWidth\" : 256,"
" \"tileHeight\" : 256"
" }"
" ]"
"}");
EXPECT_TRUE(poTMS != nullptr);
if (poTMS)
{
EXPECT_EQ(poTMS->crs(),
"http://www.opengis.net/def/crs/EPSG/0/4326");
}
}

// TMS v2 with crs.wkt
{
auto poTMS = gdal::TileMatrixSet::parse(
"{"
" \"id\" : \"test\","
" \"title\" : \"test\","
" \"uri\" : "
"\"http://www.opengis.net/def/tilematrixset/OGC/1.0/test\","
" \"crs\" : {\"wkt\": \"GEOGCRS[\\\"WGS 84\\\","
"ENSEMBLE[\\\"World Geodetic System 1984 ensemble\\\","
"MEMBER[\\\"World Geodetic System 1984 (Transit)\\\"],"
"MEMBER[\\\"World Geodetic System 1984 (G730)\\\"],"
"MEMBER[\\\"World Geodetic System 1984 (G873)\\\"],"
"MEMBER[\\\"World Geodetic System 1984 (G1150)\\\"],"
"MEMBER[\\\"World Geodetic System 1984 (G1674)\\\"],"
"MEMBER[\\\"World Geodetic System 1984 (G1762)\\\"],"
"MEMBER[\\\"World Geodetic System 1984 (G2139)\\\"],"
"MEMBER[\\\"World Geodetic System 1984 (G2296)\\\"],"
"ELLIPSOID[\\\"WGS 84\\\",6378137,298.257223563,"
"LENGTHUNIT[\\\"metre\\\",1]],"
"ENSEMBLEACCURACY[2.0]],"
"PRIMEM[\\\"Greenwich\\\",0,"
"ANGLEUNIT[\\\"degree\\\",0.0174532925199433]],"
"CS[ellipsoidal,2],"
"AXIS[\\\"geodetic latitude (Lat)\\\",north,"
"ORDER[1],"
"ANGLEUNIT[\\\"degree\\\",0.0174532925199433]],"
"AXIS[\\\"geodetic longitude (Lon)\\\",east,"
"ORDER[2],"
"ANGLEUNIT[\\\"degree\\\",0.0174532925199433]],"
"USAGE["
"SCOPE[\\\"Horizontal component of 3D system.\\\"],"
"AREA[\\\"World.\\\"],"
"BBOX[-90,-180,90,180]],"
"ID[\\\"EPSG\\\",4326]]\" },"
" \"orderedAxes\" : ["
" \"Lat\","
" \"Lon\""
" ],"
" \"wellKnownScaleSet\" : "
"\"http://www.opengis.net/def/wkss/OGC/1.0/GoogleCRS84Quad\","
" \"tileMatrices\" : ["
" {"
" \"id\" : \"0\","
" \"scaleDenominator\" : 139770566.0071794390678,"
" \"cellSize\" : 0.3515625,"
" \"cornerOfOrigin\" : \"topLeft\","
" \"pointOfOrigin\" : [ 90, -180 ],"
" \"matrixWidth\" : 4,"
" \"matrixHeight\" : 2,"
" \"tileWidth\" : 256,"
" \"tileHeight\" : 256"
" }"
" ]"
"}");
EXPECT_TRUE(poTMS != nullptr);
if (poTMS)
{
EXPECT_TRUE(
STARTS_WITH(poTMS->crs().c_str(), "GEOGCRS[\"WGS 84\""));
}
}

// TMS v2 with crs.wkt with JSON content
{
auto poTMS = gdal::TileMatrixSet::parse(
"{"
" \"id\" : \"test\","
" \"title\" : \"test\","
" \"uri\" : "
"\"http://www.opengis.net/def/tilematrixset/OGC/1.0/test\","
" \"crs\" : {\"wkt\": "
"{"
" \"type\": \"GeographicCRS\","
" \"name\": \"WGS 84\","
" \"datum_ensemble\": {"
" \"name\": \"World Geodetic System 1984 ensemble\","
" \"members\": ["
" {"
" \"name\": \"World Geodetic System 1984 (Transit)\","
" \"id\": {"
" \"authority\": \"EPSG\","
" \"code\": 1166"
" }"
" },"
" {"
" \"name\": \"World Geodetic System 1984 (G730)\","
" \"id\": {"
" \"authority\": \"EPSG\","
" \"code\": 1152"
" }"
" },"
" {"
" \"name\": \"World Geodetic System 1984 (G873)\","
" \"id\": {"
" \"authority\": \"EPSG\","
" \"code\": 1153"
" }"
" },"
" {"
" \"name\": \"World Geodetic System 1984 (G1150)\","
" \"id\": {"
" \"authority\": \"EPSG\","
" \"code\": 1154"
" }"
" },"
" {"
" \"name\": \"World Geodetic System 1984 (G1674)\","
" \"id\": {"
" \"authority\": \"EPSG\","
" \"code\": 1155"
" }"
" },"
" {"
" \"name\": \"World Geodetic System 1984 (G1762)\","
" \"id\": {"
" \"authority\": \"EPSG\","
" \"code\": 1156"
" }"
" },"
" {"
" \"name\": \"World Geodetic System 1984 (G2139)\","
" \"id\": {"
" \"authority\": \"EPSG\","
" \"code\": 1309"
" }"
" },"
" {"
" \"name\": \"World Geodetic System 1984 (G2296)\","
" \"id\": {"
" \"authority\": \"EPSG\","
" \"code\": 1383"
" }"
" }"
" ],"
" \"ellipsoid\": {"
" \"name\": \"WGS 84\","
" \"semi_major_axis\": 6378137,"
" \"inverse_flattening\": 298.257223563"
" },"
" \"accuracy\": \"2.0\","
" \"id\": {"
" \"authority\": \"EPSG\","
" \"code\": 6326"
" }"
" },"
" \"coordinate_system\": {"
" \"subtype\": \"ellipsoidal\","
" \"axis\": ["
" {"
" \"name\": \"Geodetic latitude\","
" \"abbreviation\": \"Lat\","
" \"direction\": \"north\","
" \"unit\": \"degree\""
" },"
" {"
" \"name\": \"Geodetic longitude\","
" \"abbreviation\": \"Lon\","
" \"direction\": \"east\","
" \"unit\": \"degree\""
" }"
" ]"
" },"
" \"scope\": \"Horizontal component of 3D system.\","
" \"area\": \"World.\","
" \"bbox\": {"
" \"south_latitude\": -90,"
" \"west_longitude\": -180,"
" \"north_latitude\": 90,"
" \"east_longitude\": 180"
" },"
" \"id\": {"
" \"authority\": \"EPSG\","
" \"code\": 4326"
" }"
"}"
"},"
" \"orderedAxes\" : ["
" \"Lat\","
" \"Lon\""
" ],"
" \"wellKnownScaleSet\" : "
"\"http://www.opengis.net/def/wkss/OGC/1.0/GoogleCRS84Quad\","
" \"tileMatrices\" : ["
" {"
" \"id\" : \"0\","
" \"scaleDenominator\" : 139770566.0071794390678,"
" \"cellSize\" : 0.3515625,"
" \"cornerOfOrigin\" : \"topLeft\","
" \"pointOfOrigin\" : [ 90, -180 ],"
" \"matrixWidth\" : 4,"
" \"matrixHeight\" : 2,"
" \"tileWidth\" : 256,"
" \"tileHeight\" : 256"
" }"
" ]"
"}");
EXPECT_TRUE(poTMS != nullptr);
if (poTMS)
{
EXPECT_TRUE(STARTS_WITH(poTMS->crs().c_str(),
"{ \"type\": \"GeographicCRS\""));
}
}
}

// Test that PCIDSK GetMetadataItem() return is stable
Expand Down
37 changes: 35 additions & 2 deletions gcore/tilematrixset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,13 +197,46 @@ std::unique_ptr<TileMatrixSet> TileMatrixSet::parse(const char *fileOrDef)
return nullptr;
}

const auto GetCRS = [](const CPLJSONObject &j)
{
if (j.IsValid())
{
if (j.GetType() == CPLJSONObject::Type::String)
return j.ToString();

else if (j.GetType() == CPLJSONObject::Type::Object)
{
const std::string osURI = j.GetString("uri");
if (!osURI.empty())
return osURI;

// Quite a bit of confusion around wkt.
// See https://github.com/opengeospatial/ogcapi-tiles/issues/170
const auto jWKT = j.GetObj("wkt");
if (jWKT.GetType() == CPLJSONObject::Type::String)
{
const std::string osWKT = jWKT.ToString();
if (!osWKT.empty())
return osWKT;
}
else if (jWKT.GetType() == CPLJSONObject::Type::Object)
{
const std::string osWKT = jWKT.ToString();
if (!osWKT.empty())
return osWKT;
}
}
}
return std::string();
};

poTMS->mIdentifier = oRoot.GetString(bIsTMSv2 ? "id" : "identifier");
poTMS->mTitle = oRoot.GetString("title");
poTMS->mAbstract = oRoot.GetString(bIsTMSv2 ? "description" : "abstract");
const auto oBbox = oRoot.GetObj("boundingBox");
if (oBbox.IsValid())
{
poTMS->mBbox.mCrs = oBbox.GetString("crs");
poTMS->mBbox.mCrs = GetCRS(oBbox.GetObj("crs"));
const auto oLowerCorner = oBbox.GetArray("lowerCorner");
if (oLowerCorner.IsValid() && oLowerCorner.Size() == 2)
{
Expand All @@ -217,7 +250,7 @@ std::unique_ptr<TileMatrixSet> TileMatrixSet::parse(const char *fileOrDef)
poTMS->mBbox.mUpperCornerY = oUpperCorner[1].ToDouble(NaN);
}
}
poTMS->mCrs = oRoot.GetString(bIsTMSv2 ? "crs" : "supportedCRS");
poTMS->mCrs = GetCRS(oRoot.GetObj(bIsTMSv2 ? "crs" : "supportedCRS"));
poTMS->mWellKnownScaleSet = oRoot.GetString("wellKnownScaleSet");

OGRSpatialReference oCrs;
Expand Down
3 changes: 2 additions & 1 deletion gcore/tilematrixset.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class CPL_DLL TileMatrixSet

struct CPL_DLL BoundingBox
{
std::string mCrs{};
std::string mCrs{}; //! Can be a URL, a URI, a WKT or PROJJSON string.
double mLowerCornerX{NaN};
double mLowerCornerY{NaN};
double mUpperCornerX{NaN};
Expand All @@ -61,6 +61,7 @@ class CPL_DLL TileMatrixSet
return mBbox;
}

//! Can be a URL, a URI, a WKT or PROJJSON string.
const std::string &crs() const
{
return mCrs;
Expand Down

0 comments on commit b979373

Please sign in to comment.