Skip to content

Commit 5e750aa

Browse files
authored
Merge pull request OSGeo#12224 from rouault/fix_12216
TopoJSON: read a top level 'crs' member, and other fixes in GeoJSON and ESRIJSON drivers
2 parents 0454d8e + 1ba5f49 commit 5e750aa

File tree

9 files changed

+97
-16
lines changed

9 files changed

+97
-16
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"type":"Topology",
3+
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
4+
"arcs": [
5+
[[0.0, 0.0], [10, 0], [0, 10]],
6+
],
7+
"transform": {
8+
"scale": [1.0,10.0],"translate": [100.0,1000.0]
9+
},
10+
"objects": {
11+
"a_layer" : {"type": "GeometryCollection", "geometries" : [ {"type": "LineString", "arcs": [0], "properties": { "name": "line", "id": "foo"} } ] },
12+
"foo" : {"type": "LineString", "arcs": [0], "id" : "1" }
13+
}
14+
}

autotest/ogr/ogr_topojson.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,13 @@ def test_ogr_topojson_no_transform():
135135
ds = ogr.Open("data/topojson/topojson3.topojson")
136136
lyr = ds.GetLayer(0)
137137
assert lyr.GetName() == "a_layer"
138+
assert lyr.GetSpatialRef() is None
138139
feat = lyr.GetNextFeature()
139140
ogrtest.check_feature_geometry(feat, "LINESTRING (0 0,10 0,0 10,10 0,0 0)")
140141

141142
lyr = ds.GetLayer(1)
142143
assert lyr.GetName() == "TopoJSON"
144+
assert lyr.GetSpatialRef() is None
143145
feat = lyr.GetNextFeature()
144146
ogrtest.check_feature_geometry(feat, "LINESTRING (0 0,10 0,0 10,10 0,0 0)")
145147
ds = None
@@ -174,3 +176,17 @@ def test_ogr_topojson_force_opening_url():
174176

175177
drv = gdal.IdentifyDriverEx("http://example.com", allowed_drivers=["TopoJSON"])
176178
assert drv.GetDescription() == "TopoJSON"
179+
180+
181+
###############################################################################
182+
# Test CRS support
183+
184+
185+
def test_ogr_topojson_crs():
186+
187+
ds = ogr.Open("data/topojson/topojson_with_crs.topojson")
188+
lyr = ds.GetLayer(0)
189+
assert lyr.GetSpatialRef().GetAuthorityCode(None) == "4326"
190+
191+
lyr = ds.GetLayer(1)
192+
assert lyr.GetSpatialRef().GetAuthorityCode(None) == "4326"

ogr/ogrsf_frmts/geojson/ogr_geojson.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,16 @@ class OGRGeoJSONLayer final : public OGRMemLayer
127127
oWriteOptions_ = options;
128128
}
129129

130+
void SetSupportsMGeometries(bool bSupportsMGeometries)
131+
{
132+
m_bSupportsMGeometries = bSupportsMGeometries;
133+
}
134+
135+
void SetSupportsZGeometries(bool bSupportsZGeometries)
136+
{
137+
m_bSupportsZGeometries = bSupportsZGeometries;
138+
}
139+
130140
private:
131141
OGRGeoJSONDataSource *poDS_;
132142
OGRGeoJSONReader *poReader_;
@@ -135,6 +145,8 @@ class OGRGeoJSONLayer final : public OGRMemLayer
135145
bool bOriginalIdModified_;
136146
GIntBig nTotalFeatureCount_;
137147
GIntBig nFeatureReadSinceReset_ = 0;
148+
bool m_bSupportsMGeometries = false;
149+
bool m_bSupportsZGeometries = true;
138150

139151
//! Write options used by ICreateFeature() in append scenarios
140152
OGRGeoJSONWriteOptions oWriteOptions_;
@@ -292,6 +304,16 @@ class OGRGeoJSONDataSource final : public GDALDataset
292304
return osJSonFlavor_;
293305
}
294306

307+
void SetSupportsMGeometries(bool bSupportsMGeometries)
308+
{
309+
m_bSupportsMGeometries = bSupportsMGeometries;
310+
}
311+
312+
void SetSupportsZGeometries(bool bSupportsZGeometries)
313+
{
314+
m_bSupportsZGeometries = bSupportsZGeometries;
315+
}
316+
295317
virtual CPLErr FlushCache(bool bAtClosing) override;
296318

297319
CPLErr Close() override;
@@ -327,6 +349,9 @@ class OGRGeoJSONDataSource final : public GDALDataset
327349

328350
CPLString osJSonFlavor_;
329351

352+
bool m_bSupportsMGeometries = false;
353+
bool m_bSupportsZGeometries = true;
354+
330355
//
331356
// Private utility functions
332357
//

ogr/ogrsf_frmts/geojson/ogresrijsondriver.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ void RegisterOGRESRIJSON()
7777
poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC,
7878
"drivers/vector/esrijson.html");
7979
poDriver->SetMetadataItem(GDAL_DCAP_Z_GEOMETRIES, "YES");
80+
poDriver->SetMetadataItem(GDAL_DCAP_MEASURED_GEOMETRIES, "YES");
8081

8182
poDriver->SetMetadataItem(
8283
GDAL_DMD_OPENOPTIONLIST,

ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ void OGRESRIJSONReader::ReadLayers(OGRGeoJSONDataSource *poDS,
8787
{
8888
CPLAssert(nullptr == poLayer_);
8989

90+
poDS->SetSupportsMGeometries(true);
91+
9092
if (nullptr == poGJObject_)
9193
{
9294
CPLDebug("ESRIJSON",
@@ -143,6 +145,7 @@ void OGRESRIJSONReader::ReadLayers(OGRGeoJSONDataSource *poDS,
143145

144146
poLayer_ =
145147
new OGRGeoJSONLayer(osName.c_str(), poSRS, eGeomType, poDS, nullptr);
148+
poLayer_->SetSupportsMGeometries(true);
146149
if (poSRS != nullptr)
147150
poSRS->Release();
148151

ogr/ogrsf_frmts/geojson/ogrgeojsondatasource.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -752,9 +752,10 @@ int OGRGeoJSONDataSource::TestCapability(const char *pszCap)
752752
{
753753
if (EQUAL(pszCap, ODsCCreateLayer))
754754
return fpOut_ != nullptr && nLayers_ == 0;
755-
else if (EQUAL(pszCap, ODsCZGeometries) ||
756-
EQUAL(pszCap, ODsCMeasuredGeometries))
757-
return TRUE;
755+
else if (EQUAL(pszCap, ODsCMeasuredGeometries))
756+
return m_bSupportsMGeometries;
757+
else if (EQUAL(pszCap, ODsCZGeometries))
758+
return m_bSupportsZGeometries;
758759

759760
return FALSE;
760761
}

ogr/ogrsf_frmts/geojson/ogrgeojsondriver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -782,7 +782,7 @@ void RegisterOGRGeoJSON()
782782
"Integer64List RealList StringList Date DateTime");
783783
poDriver->SetMetadataItem(GDAL_DMD_CREATIONFIELDDATASUBTYPES, "Boolean");
784784
poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE");
785-
poDriver->SetMetadataItem(GDAL_DCAP_MEASURED_GEOMETRIES, "YES");
785+
786786
poDriver->SetMetadataItem(GDAL_DCAP_FLUSHCACHE_CONSISTENT_STATE, "YES");
787787
poDriver->SetMetadataItem(GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION, "YES");
788788

ogr/ogrsf_frmts/geojson/ogrgeojsonlayer.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,8 +504,10 @@ int OGRGeoJSONLayer::TestCapability(const char *pszCap)
504504
{
505505
if (EQUAL(pszCap, OLCCurveGeometries))
506506
return FALSE;
507+
else if (EQUAL(pszCap, OLCMeasuredGeometries))
508+
return m_bSupportsMGeometries;
507509
else if (EQUAL(pszCap, OLCZGeometries))
508-
return TRUE;
510+
return m_bSupportsZGeometries;
509511
else if (EQUAL(pszCap, OLCStringsAsUTF8))
510512
return TRUE;
511513
else if (EQUAL(pszCap, OLCFastGetExtent) ||

ogr/ogrsf_frmts/geojson/ogrtopojsonreader.cpp

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "ogrgeojsonutils.h"
1515
#include "ogrlibjsonutils.h"
1616
#include "ogr_geojson.h"
17+
#include "ogrgeojsongeometry.h"
1718
#include <json.h> // JSON-C
1819
#include "ogr_api.h"
1920

@@ -456,9 +457,9 @@ EstablishLayerDefn(int nPrevFieldIdx, std::vector<int> &anCurFieldIndices,
456457

457458
static bool
458459
ParseObjectMain(const char *pszId, json_object *poObj,
459-
OGRGeoJSONDataSource *poDS, OGRGeoJSONLayer **ppoMainLayer,
460-
json_object *poArcs, ScalingParams *psParams,
461-
std::vector<int> &anCurFieldIndices,
460+
const OGRSpatialReference *poSRS, OGRGeoJSONDataSource *poDS,
461+
OGRGeoJSONLayer **ppoMainLayer, json_object *poArcs,
462+
ScalingParams *psParams, std::vector<int> &anCurFieldIndices,
462463
std::map<std::string, int> &oMapFieldNameToIdx,
463464
std::vector<std::unique_ptr<OGRFieldDefn>> &apoFieldDefn,
464465
gdal::DirectedAcyclicGraph<int, std::string> &dag,
@@ -495,8 +496,12 @@ ParseObjectMain(const char *pszId, json_object *poObj,
495496
OGRGeoJSONLayer *poLayer =
496497
new OGRGeoJSONLayer(pszId ? pszId : "TopoJSON", nullptr,
497498
wkbUnknown, poDS, nullptr);
499+
poLayer->SetSupportsZGeometries(false);
498500
OGRFeatureDefn *poDefn = poLayer->GetLayerDefn();
499501

502+
whileUnsealing(poDefn)->GetGeomFieldDefn(0)->SetSpatialRef(
503+
poSRS);
504+
500505
const auto nGeometries =
501506
json_object_array_length(poGeometries);
502507
// First pass to establish schema.
@@ -569,6 +574,13 @@ ParseObjectMain(const char *pszId, json_object *poObj,
569574
{
570575
*ppoMainLayer = new OGRGeoJSONLayer(
571576
"TopoJSON", nullptr, wkbUnknown, poDS, nullptr);
577+
578+
(*ppoMainLayer)->SetSupportsZGeometries(false);
579+
580+
whileUnsealing((*ppoMainLayer)->GetLayerDefn())
581+
->GetGeomFieldDefn(0)
582+
->SetSpatialRef(poSRS);
583+
572584
apoFieldDefn.emplace_back(
573585
std::make_unique<OGRFieldDefn>("id", OFTString));
574586
oMapFieldNameToIdx["id"] = 0;
@@ -629,6 +641,8 @@ void OGRTopoJSONReader::ReadLayers(OGRGeoJSONDataSource *poDS)
629641
return;
630642
}
631643

644+
poDS->SetSupportsZGeometries(false);
645+
632646
ScalingParams sParams;
633647
sParams.dfScale0 = 1.0;
634648
sParams.dfScale1 = 1.0;
@@ -695,6 +709,8 @@ void OGRTopoJSONReader::ReadLayers(OGRGeoJSONDataSource *poDS)
695709
if (poObjects == nullptr)
696710
return;
697711

712+
OGRSpatialReference *poSRS = OGRGeoJSONReadSpatialReference(poGJObject_);
713+
698714
std::vector<int> anCurFieldIndices;
699715
std::map<std::string, int> oMapFieldNameToIdx;
700716
std::vector<std::unique_ptr<OGRFieldDefn>> apoFieldDefn;
@@ -711,10 +727,10 @@ void OGRTopoJSONReader::ReadLayers(OGRGeoJSONDataSource *poDS)
711727
json_object_object_foreachC(poObjects, it)
712728
{
713729
json_object *poObj = it.val;
714-
bNeedSecondPass |=
715-
ParseObjectMain(it.key, poObj, poDS, &poMainLayer, poArcs,
716-
&sParams, anCurFieldIndices, oMapFieldNameToIdx,
717-
apoFieldDefn, dag, aoSetUndeterminedTypeFields);
730+
bNeedSecondPass |= ParseObjectMain(
731+
it.key, poObj, poSRS, poDS, &poMainLayer, poArcs, &sParams,
732+
anCurFieldIndices, oMapFieldNameToIdx, apoFieldDefn, dag,
733+
aoSetUndeterminedTypeFields);
718734
}
719735
if (bNeedSecondPass)
720736
{
@@ -745,10 +761,10 @@ void OGRTopoJSONReader::ReadLayers(OGRGeoJSONDataSource *poDS)
745761
for (auto i = decltype(nObjects){0}; i < nObjects; i++)
746762
{
747763
json_object *poObj = json_object_array_get_idx(poObjects, i);
748-
bNeedSecondPass |=
749-
ParseObjectMain(nullptr, poObj, poDS, &poMainLayer, poArcs,
750-
&sParams, anCurFieldIndices, oMapFieldNameToIdx,
751-
apoFieldDefn, dag, aoSetUndeterminedTypeFields);
764+
bNeedSecondPass |= ParseObjectMain(
765+
nullptr, poObj, poSRS, poDS, &poMainLayer, poArcs, &sParams,
766+
anCurFieldIndices, oMapFieldNameToIdx, apoFieldDefn, dag,
767+
aoSetUndeterminedTypeFields);
752768
}
753769
if (bNeedSecondPass)
754770
{
@@ -775,4 +791,7 @@ void OGRTopoJSONReader::ReadLayers(OGRGeoJSONDataSource *poDS)
775791
poMainLayer->DetectGeometryType();
776792
poDS->AddLayer(poMainLayer);
777793
}
794+
795+
if (poSRS)
796+
poSRS->Release();
778797
}

0 commit comments

Comments
 (0)