Skip to content

Commit ec74ca3

Browse files
committed
EP-3981 #114 DriverVectorCube: add from_geojson and to_wkt
1 parent 4a4bb5b commit ec74ca3

File tree

2 files changed

+101
-1
lines changed

2 files changed

+101
-1
lines changed

openeo_driver/datacube.py

+22-1
Original file line numberDiff line numberDiff line change
@@ -182,14 +182,30 @@ def with_cube(self, cube: xarray.DataArray, flatten_prefix: str = FLATTEN_PREFIX
182182
return DriverVectorCube(geometries=self._geometries, cube=cube, flatten_prefix=flatten_prefix)
183183

184184
@classmethod
185-
def from_fiona(cls, paths: List[str], driver: str, options: dict):
185+
def from_fiona(cls, paths: List[str], driver: str, options: dict) -> "DriverVectorCube":
186186
"""Factory to load vector cube data using fiona/GeoPandas."""
187187
if len(paths) != 1:
188188
# TODO #114 EP-3981: support multiple paths
189189
raise FeatureUnsupportedException(message="Loading a vector cube from multiple files is not supported")
190190
# TODO #114 EP-3981: lazy loading like/with DelayedVector
191191
return cls(geometries=gpd.read_file(paths[0], driver=driver))
192192

193+
@classmethod
194+
def from_geojson(cls, geojson: dict) -> "DriverVectorCube":
195+
"""Construct vector cube from GeoJson dict structure"""
196+
# TODO support more geojson types?
197+
if geojson["type"] in {"Polygon", "MultiPolygon"}:
198+
features = [{"type": "Feature", "geometry": geojson, "properties": {}}]
199+
elif geojson["type"] in {"Feature"}:
200+
features = [geojson]
201+
elif geojson["type"] in {"FeatureCollection"}:
202+
features = geojson
203+
else:
204+
raise FeatureUnsupportedException(
205+
f"Can not construct DriverVectorCube from {geojson.get('type', type(geojson))!r}"
206+
)
207+
return cls(geometries=gpd.GeoDataFrame.from_features(features))
208+
193209
def _as_geopandas_df(self) -> gpd.GeoDataFrame:
194210
"""Join geometries and cube as a geopandas dataframe"""
195211
# TODO: avoid copy?
@@ -213,6 +229,11 @@ def _as_geopandas_df(self) -> gpd.GeoDataFrame:
213229
def to_geojson(self):
214230
return shapely.geometry.mapping(self._as_geopandas_df())
215231

232+
def to_wkt(self) -> Tuple[List[str], str]:
233+
wkts = [str(g) for g in self._geometries.geometry]
234+
crs = self._geometries.crs.to_string() if self._geometries.crs else "EPSG:4326"
235+
return wkts, crs
236+
216237
def write_assets(
217238
self, directory: Union[str, Path], format: str, options: Optional[dict] = None
218239
) -> Dict[str, StacAsset]:

tests/test_vectorcube.py

+79
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ def test_to_geojson(self, gdf):
6060
]
6161
})
6262

63+
def test_to_wkt(self, gdf):
64+
vc = DriverVectorCube(gdf)
65+
assert vc.to_wkt() == (
66+
['POLYGON ((1 1, 3 1, 2 3, 1 1))', 'POLYGON ((4 2, 5 4, 3 4, 4 2))'],
67+
'EPSG:4326',
68+
)
69+
6370
def test_with_cube_to_geojson(self, gdf):
6471
vc1 = DriverVectorCube(gdf)
6572
dims, coords = vc1.get_xarray_cube_basics()
@@ -97,3 +104,75 @@ def test_with_cube_to_geojson(self, gdf):
97104
}),
98105
]
99106
})
107+
108+
@pytest.mark.parametrize(["geojson", "expected"], [
109+
(
110+
{"type": "Polygon", "coordinates": [[(1, 1), (3, 1), (2, 3), (1, 1)]]},
111+
[
112+
DictSubSet({
113+
"type": "Feature",
114+
"geometry": {"type": "Polygon", "coordinates": (((1, 1), (3, 1), (2, 3), (1, 1),),)},
115+
"properties": {},
116+
}),
117+
],
118+
),
119+
(
120+
{"type": "MultiPolygon", "coordinates": [[[(1, 1), (3, 1), (2, 3), (1, 1)]]]},
121+
[
122+
DictSubSet({
123+
"type": "Feature",
124+
"geometry": {"type": "MultiPolygon", "coordinates": [(((1, 1), (3, 1), (2, 3), (1, 1),),)]},
125+
"properties": {},
126+
}),
127+
],
128+
),
129+
(
130+
{
131+
"type": "Feature",
132+
"geometry": {"type": "MultiPolygon", "coordinates": [[[(1, 1), (3, 1), (2, 3), (1, 1)]]]},
133+
"properties": {"id": "12_3"},
134+
},
135+
[
136+
DictSubSet({
137+
"type": "Feature",
138+
"geometry": {"type": "MultiPolygon", "coordinates": [(((1, 1), (3, 1), (2, 3), (1, 1),),)]},
139+
"properties": {"id": "12_3"},
140+
}),
141+
],
142+
),
143+
(
144+
{
145+
"type": "FeatureCollection",
146+
"features": [
147+
{
148+
"type": "Feature",
149+
"geometry": {"type": "Polygon", "coordinates": [[(1, 1), (3, 1), (2, 3), (1, 1)]]},
150+
"properties": {"id": 1},
151+
},
152+
{
153+
"type": "Feature",
154+
"geometry": {"type": "MultiPolygon", "coordinates": [[[(1, 1), (3, 1), (2, 3), (1, 1)]]]},
155+
"properties": {"id": 2},
156+
},
157+
],
158+
},
159+
[
160+
DictSubSet({
161+
"type": "Feature",
162+
"geometry": {"type": "Polygon", "coordinates": (((1, 1), (3, 1), (2, 3), (1, 1),),)},
163+
"properties": {"id": 1},
164+
}),
165+
DictSubSet({
166+
"type": "Feature",
167+
"geometry": {"type": "MultiPolygon", "coordinates": [(((1, 1), (3, 1), (2, 3), (1, 1),),)]},
168+
"properties": {"id": 2},
169+
}),
170+
],
171+
),
172+
])
173+
def test_from_geojson(self, geojson, expected):
174+
vc = DriverVectorCube.from_geojson(geojson)
175+
assert vc.to_geojson() == DictSubSet({
176+
"type": "FeatureCollection",
177+
"features": expected,
178+
})

0 commit comments

Comments
 (0)