From 3ce197967eee9c40af370f1a2779c2c7ddbdbd43 Mon Sep 17 00:00:00 2001 From: Ivor Bosloper Date: Sun, 27 Sep 2026 23:52:27 +0200 Subject: [PATCH 1/2] create-stac-collection: the bbox is the extent of the geometries Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 4 ++++ tests/test_create_stac.py | 25 +++++++++++++++++++++++++ vecorel_cli/create_stac.py | 11 ++++++++--- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 776a999..7ca37f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +- Fix: `create-stac-collection` takes the bbox from the geometries in EPSG:4326. It + transformed the corners of the source bbox, which in a projected CRS reach beyond + the data. + ## [v0.3.1] - 2026-09-24 - Fix: ZIP archives compressed with Deflate64 are extracted through `inflate64` (a diff --git a/tests/test_create_stac.py b/tests/test_create_stac.py index 42d4909..2254ea8 100644 --- a/tests/test_create_stac.py +++ b/tests/test_create_stac.py @@ -55,3 +55,28 @@ def test_create_stac_collection(tmp_folder: Path, file: str, expected_file: str) del expected["assets"]["data"]["processing:software"]["vecorel-cli"] assert created_file == expected + + +def test_bbox_is_the_extent_of_the_geometries(): + """In a projected CRS, the corners of the source bbox reach beyond the data.""" + import geopandas as gpd + import pytest as _pytest + from shapely.geometry import Polygon + + from vecorel_cli.vecorel.collection import Collection + + # a parcel in Saxony, in ETRS89 / UTM zone 33N + field = Polygon([(300000, 5600000), (500000, 5650000), (450000, 5700000), (320000, 5680000)]) + gdf = gpd.GeoDataFrame({"id": ["1"]}, geometry=[field], crs="EPSG:25833") + collection = Collection( + { + "schemas": {"c": ["https://vecorel.org/specification/v0.1.0/schema.yaml"]}, + "title": "t", + "description": "d", + } + ) + + stac = CreateStacCollection().create(collection, gdf, "x.parquet") + + expected = gdf.to_crs(epsg=4326).total_bounds + assert stac["extent"]["spatial"]["bbox"][0] == _pytest.approx(list(expected)) diff --git a/vecorel_cli/create_stac.py b/vecorel_cli/create_stac.py index 970a596..d6a4a04 100644 --- a/vecorel_cli/create_stac.py +++ b/vecorel_cli/create_stac.py @@ -4,8 +4,7 @@ import click import pandas as pd -from geopandas import GeoDataFrame, GeoSeries -from shapely.geometry import box +from geopandas import GeoDataFrame from yarl import URL from .basecommand import BaseCommand, runnable @@ -142,7 +141,13 @@ def create( if len(description) == 0: raise Exception("Description is not found in collection.") - bbox = list(GeoSeries([box(*gdf.total_bounds)], crs=gdf.crs).to_crs(epsg=4326).total_bounds) + # the extent of the geometries themselves: in a projected CRS the corners of its bbox reach beyond the data + geometry = ( + gdf.geometry + if gdf.crs and gdf.crs.to_epsg() == 4326 + else gdf.geometry.to_crs(epsg=4326) + ) + bbox = list(geometry.total_bounds) if isinstance(data_url, Path): href = "file://" + str(data_url.resolve()).replace("\\", "/") From bec773db75ba8abf1637822f7d84cee10479722d Mon Sep 17 00:00:00 2001 From: Ivor Bosloper Date: Thu, 1 Oct 2026 09:25:22 +0200 Subject: [PATCH 2/2] Trim the bbox comment and import the test dependencies at module level Co-Authored-By: Claude Opus 5.5 --- tests/test_create_stac.py | 11 ++++------- vecorel_cli/create_stac.py | 2 +- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/tests/test_create_stac.py b/tests/test_create_stac.py index 2254ea8..4e080e7 100644 --- a/tests/test_create_stac.py +++ b/tests/test_create_stac.py @@ -1,9 +1,12 @@ from pathlib import Path +import geopandas as gpd import pytest +from shapely.geometry import Polygon from vecorel_cli.create_stac import CreateStacCollection from vecorel_cli.registry import Registry +from vecorel_cli.vecorel.collection import Collection from vecorel_cli.vecorel.util import load_file files = [ @@ -59,12 +62,6 @@ def test_create_stac_collection(tmp_folder: Path, file: str, expected_file: str) def test_bbox_is_the_extent_of_the_geometries(): """In a projected CRS, the corners of the source bbox reach beyond the data.""" - import geopandas as gpd - import pytest as _pytest - from shapely.geometry import Polygon - - from vecorel_cli.vecorel.collection import Collection - # a parcel in Saxony, in ETRS89 / UTM zone 33N field = Polygon([(300000, 5600000), (500000, 5650000), (450000, 5700000), (320000, 5680000)]) gdf = gpd.GeoDataFrame({"id": ["1"]}, geometry=[field], crs="EPSG:25833") @@ -79,4 +76,4 @@ def test_bbox_is_the_extent_of_the_geometries(): stac = CreateStacCollection().create(collection, gdf, "x.parquet") expected = gdf.to_crs(epsg=4326).total_bounds - assert stac["extent"]["spatial"]["bbox"][0] == _pytest.approx(list(expected)) + assert stac["extent"]["spatial"]["bbox"][0] == pytest.approx(list(expected)) diff --git a/vecorel_cli/create_stac.py b/vecorel_cli/create_stac.py index d6a4a04..6442de7 100644 --- a/vecorel_cli/create_stac.py +++ b/vecorel_cli/create_stac.py @@ -141,7 +141,7 @@ def create( if len(description) == 0: raise Exception("Description is not found in collection.") - # the extent of the geometries themselves: in a projected CRS the corners of its bbox reach beyond the data + # in a projected CRS, the transformed corners of the bbox reach beyond the data geometry = ( gdf.geometry if gdf.crs and gdf.crs.to_epsg() == 4326