Skip to content

Commit b6ed855

Browse files
committed
aggregate_spatial with points: more robust buffering approach
1 parent 005e8c8 commit b6ed855

File tree

2 files changed

+32
-21
lines changed

2 files changed

+32
-21
lines changed

openeo_driver/dry_run.py

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -561,10 +561,12 @@ def filter_bbox(
561561

562562
def filter_spatial(self, geometries):
563563
crs = None
564+
resolution = None
564565
if len(self.metadata.spatial_dimensions) > 0:
565566
spatial_dim = self.metadata.spatial_dimensions[0]
566567
crs = spatial_dim.crs
567-
geometries, bbox = self._normalize_geometry(geometries, target_crs=crs)
568+
resolution = spatial_dim.step
569+
geometries, bbox = self._normalize_geometry(geometries, target_crs=crs, target_resolution=resolution)
568570
cube = self.filter_bbox(**bbox, operation="weak_spatial_extent")
569571
return cube._process(operation="filter_spatial", arguments={"geometries": geometries})
570572

@@ -622,19 +624,25 @@ def aggregate_spatial(
622624
cube = self
623625
if not geoms_is_empty:
624626
crs = None
627+
resolution = None
625628
if len(self.metadata.spatial_dimensions) > 0:
626629
spatial_dim = self.metadata.spatial_dimensions[0]
630+
resolution = spatial_dim.step
627631
crs = spatial_dim.crs
628-
geometries, bbox = self._normalize_geometry(geometries, target_crs=crs)
632+
geometries, bbox = self._normalize_geometry(geometries, target_crs=crs, target_resolution=resolution)
629633
cube = self.filter_bbox(**bbox, operation="weak_spatial_extent")
630634
return cube._process(operation="aggregate_spatial", arguments={"geometries": geometries})
631635

632636
def _normalize_geometry(
633-
self, geometries, target_crs=None
637+
self, geometries, target_crs=None, target_resolution = None
634638
) -> Tuple[Union[DriverVectorCube, DelayedVector, BaseGeometry], dict]:
635639
"""
636640
Helper to preprocess geometries (as used in aggregate_spatial and mask_polygon)
637641
and extract bbox (e.g. for filter_bbox)
642+
643+
:param geometries: geometries as BaseGeometry, GeoJSON dict, DelayedVector or DriverVectorCube
644+
:param target_crs: target CRS to reproject geometries to
645+
:param target_resolution: target resolution for geometries, in units of the target CRS, None by default which will use 10m
638646
"""
639647
_log.debug(f"_normalize_geometry with {type(geometries)}")
640648
# TODO #71 #114 EP-3981 normalize to vector cube instead of GeometryCollection
@@ -660,21 +668,25 @@ def _normalize_geometry(
660668

661669
if len(points) > 0:
662670
point_hull = reproject_geometry(shapely.geometry.MultiPoint(points).envelope,geometries.get_crs(),CRS.from_user_input(target_crs))
663-
loi_point = point_hull.representative_point()
664-
bufferer = GeometryBufferer.from_meter_for_crs(
665-
distance=10, crs=target_crs, loi=(loi_point.x,loi_point.y), loi_crs=target_crs
666-
)
667-
buffered_points = bufferer.buffer(point_hull)
671+
buffered_points = None
672+
if target_resolution == None:
673+
loi_point = point_hull.representative_point()
674+
bufferer = GeometryBufferer.from_meter_for_crs(
675+
distance=10, crs=target_crs, loi=(loi_point.x,loi_point.y), loi_crs=target_crs
676+
)
677+
buffered_points = bufferer.buffer(point_hull)
678+
else:
679+
buffered_points = point_hull.buffer(distance=target_resolution)
668680
other_hull = other_hull.union(buffered_points)
669681
bbox = other_hull.bounds
670682
crs = target_crs
671683
else:
672684
bbox = geometries.buffer_points(distance=10).get_bounding_box()
673685
crs = geometries.get_crs_str()
674686
elif isinstance(geometries, dict):
675-
return self._normalize_geometry(geojson_to_geometry(geometries))
687+
return self._normalize_geometry(geojson_to_geometry(geometries),target_crs, target_resolution)
676688
elif isinstance(geometries, str):
677-
return self._normalize_geometry(DelayedVector(geometries))
689+
return self._normalize_geometry(DelayedVector(geometries),target_crs, target_resolution)
678690
elif isinstance(geometries, DelayedVector):
679691
bbox = geometries.bounds
680692
elif isinstance(geometries, shapely.geometry.base.BaseGeometry):

tests/test_dry_run.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -652,10 +652,10 @@ def test_aggregate_spatial_only(dry_run_env, dry_run_tracer):
652652
approxify(
653653
{
654654
"crs": "EPSG:32631",
655-
"east": 610869.8770073673,
656-
"north": 552758.5425218772,
657-
"south": 331634.0169357686,
658-
"west": 388860.8935124034,
655+
"east": 611139.132350062,
656+
"north": 552758.6209151235,
657+
"south": 331633.9380733739,
658+
"west": 388860.86764994,
659659
}
660660
),
661661
),
@@ -2376,7 +2376,7 @@ def test_complex_extract_load_stac(dry_run_env, dry_run_tracer):
23762376
loadparams = _extract_load_parameters(dry_run_env, source_id_bands)
23772377

23782378
print(loadparams)
2379-
expected_extent = {"crs": "EPSG:32633", "east": 400380, "north": 4700400, "south": 4679610, "west": 380120}
2379+
expected_extent = {'west': 379840, 'south': 4679580, 'east': 400460, 'north': 4700510, 'crs': 'EPSG:32633'}
23802380
assert loadparams.global_extent == expected_extent
23812381
assert loadparams.bands == ["B02", "B03", "B04", "B05", "B06", "B07", "B08", "B8A", "B11", "B12"]
23822382
assert loadparams.pixel_buffer == None
@@ -2441,12 +2441,11 @@ def test_normalize_geometries(dry_run_env, dry_run_tracer):
24412441

24422442
# print(json.dumps(dict(type="FeatureCollection",features=[dict(type="Feature",geometry=mapping(e),properties={}) for e in extents])))
24432443

2444-
assert params[0].global_extent == {
2445-
"crs": "EPSG:32632",
2446-
"east": 636980,
2447-
"north": 5729350,
2448-
"south": 5654910,
2449-
"west": 89920,
2444+
assert params[0].global_extent == {'crs': 'EPSG:32632',
2445+
'east': 638890,
2446+
'north': 5736520,
2447+
'south': 5642750,
2448+
'west': 84850
24502449
}
24512450

24522451

0 commit comments

Comments
 (0)