Skip to content

Commit 1ba5f49

Browse files
committed
TopoJSON: read a top level 'crs' member (fixes OSGeo#12216)
1 parent b143404 commit 1ba5f49

File tree

3 files changed

+54
-11
lines changed

3 files changed

+54
-11
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/ogrtopojsonreader.cpp

Lines changed: 24 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,
@@ -498,6 +499,9 @@ ParseObjectMain(const char *pszId, json_object *poObj,
498499
poLayer->SetSupportsZGeometries(false);
499500
OGRFeatureDefn *poDefn = poLayer->GetLayerDefn();
500501

502+
whileUnsealing(poDefn)->GetGeomFieldDefn(0)->SetSpatialRef(
503+
poSRS);
504+
501505
const auto nGeometries =
502506
json_object_array_length(poGeometries);
503507
// First pass to establish schema.
@@ -573,6 +577,10 @@ ParseObjectMain(const char *pszId, json_object *poObj,
573577

574578
(*ppoMainLayer)->SetSupportsZGeometries(false);
575579

580+
whileUnsealing((*ppoMainLayer)->GetLayerDefn())
581+
->GetGeomFieldDefn(0)
582+
->SetSpatialRef(poSRS);
583+
576584
apoFieldDefn.emplace_back(
577585
std::make_unique<OGRFieldDefn>("id", OFTString));
578586
oMapFieldNameToIdx["id"] = 0;
@@ -701,6 +709,8 @@ void OGRTopoJSONReader::ReadLayers(OGRGeoJSONDataSource *poDS)
701709
if (poObjects == nullptr)
702710
return;
703711

712+
OGRSpatialReference *poSRS = OGRGeoJSONReadSpatialReference(poGJObject_);
713+
704714
std::vector<int> anCurFieldIndices;
705715
std::map<std::string, int> oMapFieldNameToIdx;
706716
std::vector<std::unique_ptr<OGRFieldDefn>> apoFieldDefn;
@@ -717,10 +727,10 @@ void OGRTopoJSONReader::ReadLayers(OGRGeoJSONDataSource *poDS)
717727
json_object_object_foreachC(poObjects, it)
718728
{
719729
json_object *poObj = it.val;
720-
bNeedSecondPass |=
721-
ParseObjectMain(it.key, poObj, poDS, &poMainLayer, poArcs,
722-
&sParams, anCurFieldIndices, oMapFieldNameToIdx,
723-
apoFieldDefn, dag, aoSetUndeterminedTypeFields);
730+
bNeedSecondPass |= ParseObjectMain(
731+
it.key, poObj, poSRS, poDS, &poMainLayer, poArcs, &sParams,
732+
anCurFieldIndices, oMapFieldNameToIdx, apoFieldDefn, dag,
733+
aoSetUndeterminedTypeFields);
724734
}
725735
if (bNeedSecondPass)
726736
{
@@ -751,10 +761,10 @@ void OGRTopoJSONReader::ReadLayers(OGRGeoJSONDataSource *poDS)
751761
for (auto i = decltype(nObjects){0}; i < nObjects; i++)
752762
{
753763
json_object *poObj = json_object_array_get_idx(poObjects, i);
754-
bNeedSecondPass |=
755-
ParseObjectMain(nullptr, poObj, poDS, &poMainLayer, poArcs,
756-
&sParams, anCurFieldIndices, oMapFieldNameToIdx,
757-
apoFieldDefn, dag, aoSetUndeterminedTypeFields);
764+
bNeedSecondPass |= ParseObjectMain(
765+
nullptr, poObj, poSRS, poDS, &poMainLayer, poArcs, &sParams,
766+
anCurFieldIndices, oMapFieldNameToIdx, apoFieldDefn, dag,
767+
aoSetUndeterminedTypeFields);
758768
}
759769
if (bNeedSecondPass)
760770
{
@@ -781,4 +791,7 @@ void OGRTopoJSONReader::ReadLayers(OGRGeoJSONDataSource *poDS)
781791
poMainLayer->DetectGeometryType();
782792
poDS->AddLayer(poMainLayer);
783793
}
794+
795+
if (poSRS)
796+
poSRS->Release();
784797
}

0 commit comments

Comments
 (0)