Skip to content

Commit 59093c6

Browse files
committed
Simplify get_geojson_bounds and add examples to doctring
Fixes #115
1 parent 38e0d14 commit 59093c6

File tree

2 files changed

+76
-13
lines changed

2 files changed

+76
-13
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
3232
interpolation, such that the response status is 400, not 500
3333
([#122](https://github.com/developmentseed/titiler-cmr/issues/122))
3434

35+
### Changed
36+
37+
- Simplify function `get_geojson_bounds` and add illustrative examples to its
38+
docstring ([#115](https://github.com/developmentseed/titiler-cmr/issues/115))
39+
3540
## [v0.3.0]
3641

3742
### Added

titiler/cmr/utils.py

Lines changed: 71 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
from typing import TYPE_CHECKING, Any
1212

1313
import earthaccess
14+
import rasterio.features
1415
from geojson_pydantic import Feature, FeatureCollection
1516
from isodate import parse_datetime as _parse_datetime
16-
from rasterio.features import bounds
1717
from rasterio.warp import transform_bounds
1818
from urllib3.response import HTTPException # type: ignore
1919

@@ -212,18 +212,76 @@ def calculate_time_series_request_size(
212212
def get_geojson_bounds(
213213
geojson: Feature | FeatureCollection,
214214
) -> tuple[float, float, float, float]:
215-
"""Get the global bounding box for a geojson Feature or FeatureCollection"""
216-
fc = geojson
217-
if isinstance(fc, Feature):
218-
fc = FeatureCollection(type="FeatureCollection", features=[geojson])
215+
"""Get the global bounding box for a GeoJSON Feature or FeatureCollection.
219216
220-
all_bounds = [
221-
bounds(feature.model_dump(exclude_none=True)) for feature in fc.features
222-
]
217+
Parameters
218+
----------
219+
geojson
220+
A GeoJSON Feature or FeatureCollection whose coordinates are expressed
221+
in WGS84 longitude/latitude.
223222
224-
minx = min(bound[0] for bound in all_bounds)
225-
miny = min(bound[1] for bound in all_bounds)
226-
maxx = max(bound[2] for bound in all_bounds)
227-
maxy = max(bound[3] for bound in all_bounds)
223+
Returns
224+
-------
225+
tuple[float, float, float, float]
226+
A tuple of `(minx, miny, maxx, maxy)` representing the bounding box in
227+
WGS84 degrees.
228228
229-
return (minx, miny, maxx, maxy)
229+
Examples
230+
--------
231+
The bounding box for a point is simply the same point at both corners of the
232+
box:
233+
234+
>>> point = Feature(
235+
... **{
236+
... "type": "Feature",
237+
... "geometry": {
238+
... "type": "Point",
239+
... "coordinates": [12.38272, 53.46385],
240+
... },
241+
... "properties": None,
242+
... }
243+
... )
244+
>>> get_geojson_bounds(point)
245+
(12.38272, 53.46385, 12.38272, 53.46385)
246+
247+
For a polygon, the bounds are simply the smallest and largest coordinates
248+
in both the x and y directions amongst all points of the polygon:
249+
250+
>>> polygon = Feature(
251+
... **{
252+
... "type": "Feature",
253+
... "geometry": {
254+
... "type": "Polygon",
255+
... "coordinates": [
256+
... [
257+
... [13.38272, 52.46385],
258+
... [13.42786, 52.46385],
259+
... [13.42786, 52.48445],
260+
... [13.38272, 52.48445],
261+
... [13.38272, 52.46385],
262+
... ]
263+
... ],
264+
... },
265+
... "properties": None,
266+
... }
267+
... )
268+
>>> get_geojson_bounds(polygon)
269+
(13.38272, 52.46385, 13.42786, 52.48445)
270+
271+
For a feature collection, the bounds are the smallest and largest
272+
coordinates across all points of all geometries in the collection, as if a
273+
single feature with all points from all geometries were supplied instead:
274+
275+
>>> fc = FeatureCollection(type="FeatureCollection", features=[point, polygon])
276+
>>> get_geojson_bounds(fc)
277+
(12.38272, 52.46385, 13.42786, 53.46385)
278+
279+
Notice that in the result above, the `minx` (first) and `maxy` (last)
280+
coordinates come from the point, because it sits to the west and north of
281+
the polygon, while the others (`maxx` and `miny`) come from the polygon.
282+
"""
283+
return rasterio.features.bounds(
284+
FeatureCollection(type="FeatureCollection", features=[geojson])
285+
if isinstance(geojson, Feature)
286+
else geojson
287+
)

0 commit comments

Comments
 (0)