diff --git a/scripts/stac/imagery/capture_area.py b/scripts/stac/imagery/capture_area.py index 510c5281..7e13b143 100644 --- a/scripts/stac/imagery/capture_area.py +++ b/scripts/stac/imagery/capture_area.py @@ -3,7 +3,7 @@ from typing import Any, Sequence from linz_logger import get_log -from shapely import BufferCapStyle, BufferJoinStyle, to_geojson, union_all +from shapely import BufferCapStyle, BufferJoinStyle, to_geojson, union_all, wkt from shapely.geometry.base import BaseGeometry from shapely.ops import orient @@ -62,9 +62,10 @@ def merge_polygons(polygons: Sequence[BaseGeometry], buffer_distance: float) -> # Negative buffer back in the polygons union_unbuffered = union_buffered.buffer(-buffer_distance, cap_style=BufferCapStyle.flat, join_style=BufferJoinStyle.mitre) union_simplified = union_unbuffered.simplify(buffer_distance) + union_rounded = wkt.loads(wkt.dumps(union_simplified, rounding_precision=8)) # Apply right-hand rule winding order (exterior rings should be counter-clockwise) to the geometry # Ref: https://datatracker.ietf.org/doc/html/rfc7946#section-3.1.6 - oriented_union_simplified = orient(union_simplified, sign=1.0) + oriented_union_simplified = orient(union_rounded, sign=1.0) return oriented_union_simplified diff --git a/scripts/stac/imagery/tests/capture_area_test.py b/scripts/stac/imagery/tests/capture_area_test.py index 01021873..4a96bd24 100644 --- a/scripts/stac/imagery/tests/capture_area_test.py +++ b/scripts/stac/imagery/tests/capture_area_test.py @@ -58,11 +58,11 @@ def test_merge_polygons_with_rounding_margin_too_big() -> None: (1.0, 1.0), (0.0, 1.0), (0.0, 0.0), - (1.9999999999999998, 0.0), - (1.9999999999999998, 1.0), + (2.0, 0.0), + (2.0, 1.0), (1.1, 1.0), - (1.015018629811984, 0.1501862981198402), - (1.0, 0.15093536161009757), + (1.01501863, 0.1501863), + (1.0, 0.15093536), (1.0, 1.0), ] ) @@ -190,3 +190,42 @@ def test_capture_area_orientation_multipolygon() -> None: capture_area = generate_capture_area(polygons, Decimal("0.05")) mp_geom = cast(MultiPolygon, shape(capture_area["geometry"])) assert is_ccw(get_exterior_ring(mp_geom.geoms[0])) + + +def test_capture_area_rounding_decimal_places() -> None: + # Test that the capture area is rounded to 8 decimal places + polygons = [] + polygons.append( + shape( + { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [174.673418475601466, -37.051277768264598], + [174.673425023818197, -37.051550327851878], + [174.673479898051271, -37.051280958541774], + [174.673418475601466, -37.051277768264598], + ] + ] + ], + } + ) + ) + capture_area_expected = { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [174.67342502, -37.05155033], + [174.6734799, -37.05128096], + [174.67341848, -37.05127777], + [174.67342502, -37.05155033], + ] + ], + }, + "type": "Feature", + "properties": {}, + } + capture_area = generate_capture_area(polygons, Decimal("1")) + assert capture_area == capture_area_expected diff --git a/scripts/stac/imagery/tests/collection_test.py b/scripts/stac/imagery/tests/collection_test.py index 4982d0c2..b6915c75 100644 --- a/scripts/stac/imagery/tests/collection_test.py +++ b/scripts/stac/imagery/tests/collection_test.py @@ -310,17 +310,14 @@ def test_capture_area_added(fake_collection_metadata: CollectionMetadata, subtes with subtests.test(): assert collection.stac["assets"]["capture_area"]["file:checksum"] in ( - "1220369cd5d4179f5f68ca0fd9be70b9f66033fcc6bb2f3305c0ad977adc79d7ad53", # geos 3.11 - geos 3.12 as yet untested + "1220ba57cd77defc7fa72e140f4faa0846e8905ae443de04aef99bf381d4650c17a0", # geos 3.11 - geos 3.12 as yet untested ) with subtests.test(): assert "file:size" in collection.stac["assets"]["capture_area"] with subtests.test(): - assert collection.stac["assets"]["capture_area"]["file:size"] in ( - 339, # geos 3.11 - 299, # geos 3.12 - ) + assert collection.stac["assets"]["capture_area"]["file:size"] in (269,) # geos 3.11 - geos 3.12 as yet untested def test_event_name_is_present(fake_collection_metadata: CollectionMetadata) -> None: