diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 84431ce..7ba82e1 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -18,7 +18,17 @@ jobs: with: flake8_version: 6.0.0 max_line_length: 120 - plugins: flake8-isort==6.1.2 flake8-quotes==3.4.0 flake8-commas==4.0.0 + plugins: flake8-isort==6.1.2 flake8-quotes==3.4.0 + + ruff-format: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: astral-sh/ruff-action@v3 + with: + version: "~=0.13.3" + args: format --check --diff --output-format=github mypy: runs-on: ubuntu-latest diff --git a/geo_extensions/transformations/cartesian.py b/geo_extensions/transformations/cartesian.py index 416abd0..29c24ca 100644 --- a/geo_extensions/transformations/cartesian.py +++ b/geo_extensions/transformations/cartesian.py @@ -104,20 +104,26 @@ def split(polygon: Polygon) -> TransformationResult: def _shift_polygon(polygon: Polygon) -> Polygon: """Shift into [0, 360) range.""" - return Polygon([ - ((360.0 + lon) % 360, lat) - for lon, lat in polygon.exterior.coords - ]) + return Polygon( + [ + # ruff hint + ((360.0 + lon) % 360, lat) + for lon, lat in polygon.exterior.coords + ] + ) def _shift_polygon_back(polygon: Polygon) -> Polygon: """Shift back to [-180, 180] range.""" _, _, max_lon, _ = polygon.bounds - return Polygon([ - (_adjust_lon(lon, max_lon), lat) - for lon, lat in polygon.exterior.coords - ]) + return Polygon( + [ + # ruff hint + (_adjust_lon(lon, max_lon), lat) + for lon, lat in polygon.exterior.coords + ] + ) def _adjust_lon(lon: float, max_lon: float) -> float: @@ -136,6 +142,7 @@ def _split_polygon( split_collection = shapely.ops.split(polygon, line) return [ + # ruff hint orient(geom) for geom in split_collection.geoms if isinstance(geom, Polygon) and not _ignore_polygon(geom) diff --git a/geo_extensions/transformations/general.py b/geo_extensions/transformations/general.py index e01eb73..be5ee7a 100644 --- a/geo_extensions/transformations/general.py +++ b/geo_extensions/transformations/general.py @@ -17,6 +17,7 @@ def drop_z_coordinate(polygon: Polygon) -> TransformationResult: yield Polygon( shell=((x, y) for x, y, *_ in polygon.exterior.coords), holes=[ + # ruff hint ((x, y) for x, y, *_ in interior.coords) for interior in polygon.interiors ], diff --git a/geo_extensions/transformations/geodetic.py b/geo_extensions/transformations/geodetic.py index d2aaf7f..131dc1c 100644 --- a/geo_extensions/transformations/geodetic.py +++ b/geo_extensions/transformations/geodetic.py @@ -49,6 +49,7 @@ def densify(polygon: Polygon) -> TransformationResult: yield Polygon( shell=_densify_ring(polygon.exterior.coords, tolerance_meters), holes=[ + # ruff hint _densify_ring(interior.coords, tolerance_meters) for interior in polygon.interiors ], diff --git a/pyproject.toml b/pyproject.toml index 137bb1a..00cb931 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,3 +27,10 @@ types-shapely = "^2.0.3" [tool.isort] profile = "black" + +[tool.ruff] +line-length = 120 + +[tool.ruff.lint] +# Add the `line-too-long` rule to the enforced rule set. +extend-select = ["E501"] diff --git a/tests/conftest.py b/tests/conftest.py index 1adcbc7..7a8ac4b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -12,10 +12,15 @@ def data_path(): @pytest.fixture def rectangle(): """A rectanglular polygon""" - polygon = Polygon([ - (160., 60.), (170., 60.), - (170., 70.), (160., 70.), (160., 60.), - ]) + polygon = Polygon( + [ + (160.0, 60.0), + (170.0, 60.0), + (170.0, 70.0), + (160.0, 70.0), + (160.0, 60.0), + ] + ) assert polygon.exterior.is_ccw assert polygon.exterior.is_valid @@ -25,10 +30,15 @@ def rectangle(): @pytest.fixture def centered_rectangle(): """A rectanglular polygon centered at 0, 0""" - polygon = Polygon([ - (-30., 10.), (-30., -10.), - (30., -10.), (30., 10.), (-30., 10.), - ]) + polygon = Polygon( + [ + (-30.0, 10.0), + (-30.0, -10.0), + (30.0, -10.0), + (30.0, 10.0), + (-30.0, 10.0), + ] + ) assert polygon.exterior.is_ccw assert polygon.exterior.is_valid @@ -38,10 +48,15 @@ def centered_rectangle(): @pytest.fixture def antimeridian_centered_rectangle(): """A rectanglular polygon centered over the antimeridian""" - polygon = Polygon([ - (150., 10.), (150., -10.), - (-150., -10.), (-150., 10.), (150., 10.), - ]) + polygon = Polygon( + [ + (150.0, 10.0), + (150.0, -10.0), + (-150.0, -10.0), + (-150.0, 10.0), + (150.0, 10.0), + ] + ) assert not polygon.exterior.is_ccw assert polygon.exterior.is_valid @@ -57,10 +72,16 @@ def multi_crossing_polygon(): | \ -------- """ - polygon = Polygon([ - (150., -10.), (-150., -10.), (160., 0.), - (-150., 10.), (150., 10.), (150., -10.), - ]) + polygon = Polygon( + [ + (150.0, -10.0), + (-150.0, -10.0), + (160.0, 0.0), + (-150.0, 10.0), + (150.0, 10.0), + (150.0, -10.0), + ] + ) assert not polygon.exterior.is_ccw assert not polygon.exterior.is_valid diff --git a/tests/test_checks.py b/tests/test_checks.py index aafd308..0756eba 100644 --- a/tests/test_checks.py +++ b/tests/test_checks.py @@ -17,10 +17,17 @@ def test_polygon_crosses_antimeridian_ccw_tricky(): / \ -------- """ - polygon = Polygon([ - (-30., 10.), (-10., 0.), (-30., -10.), - (30., -10.), (10., 0.), (30., 10.), (-30., 10.), - ]) + polygon = Polygon( + [ + (-30.0, 10.0), + (-10.0, 0.0), + (-30.0, -10.0), + (30.0, -10.0), + (10.0, 0.0), + (30.0, 10.0), + (-30.0, 10.0), + ] + ) assert polygon_crosses_antimeridian_ccw(polygon) is False @@ -31,10 +38,17 @@ def test_polygon_crosses_antimeridian_ccw_tricky_crosses(): / \ -------- """ - polygon = Polygon([ - (150., 10.), (170., 0.), (150., -10.), - (-150., 10.), (-170., 0.), (-150., -10.), (150., 10.), - ]) + polygon = Polygon( + [ + (150.0, 10.0), + (170.0, 0.0), + (150.0, -10.0), + (-150.0, 10.0), + (-170.0, 0.0), + (-150.0, -10.0), + (150.0, 10.0), + ] + ) assert polygon_crosses_antimeridian_ccw(polygon) is True @@ -50,12 +64,14 @@ def test_polygon_crosses_antimeridian_ccw_alos2_antarctica(): ALOS2 granule: ALOS2075945400-151019-WBDR1.1__D """ - polygon = Polygon([ - (-178.328, -79.438), - (179.625, -76.163), - (166.084, -76.163), - (164.037, -79.438), - ]) + polygon = Polygon( + [ + (-178.328, -79.438), + (179.625, -76.163), + (166.084, -76.163), + (164.037, -79.438), + ] + ) assert polygon_crosses_antimeridian_ccw(polygon) is True @@ -72,10 +88,17 @@ def test_polygon_crosses_antimeridian_fixed_size_tricky_crosses(): / \ -------- """ - polygon = Polygon([ - (150., 10.), (170., 0.), (150., -10.), - (-150., 10.), (-170., 0.), (-150., -10.), (150., 10.), - ]) + polygon = Polygon( + [ + (150.0, 10.0), + (170.0, 0.0), + (150.0, -10.0), + (-150.0, 10.0), + (-170.0, 0.0), + (-150.0, -10.0), + (150.0, 10.0), + ] + ) assert polygon_crosses_antimeridian_fixed_size(polygon, 30) is True @@ -83,8 +106,13 @@ def test_polygon_crosses_antimeridian_fixed_size_antarctica(): r"""A real polygon from ALOS2 granule ALOS2014555550-140830 which is located close to the south pole, and also crosses the antimeridian """ - polygon = Polygon([ - (-164.198, -82.125), (172.437, -83.885), (165.618, -80.869), - (-176.331, -79.578), (-164.198, -82.125), - ]) + polygon = Polygon( + [ + (-164.198, -82.125), + (172.437, -83.885), + (165.618, -80.869), + (-176.331, -79.578), + (-164.198, -82.125), + ] + ) assert polygon_crosses_antimeridian_fixed_size(polygon, 40) is True diff --git a/tests/test_geo_extensions.py b/tests/test_geo_extensions.py index 90bca8e..52c3f1f 100644 --- a/tests/test_geo_extensions.py +++ b/tests/test_geo_extensions.py @@ -10,18 +10,22 @@ def test_default_transformer(data_path): wkt_path = data_path / "OPERA_L2_RTC-S1_T114-243299-IW1_20230722T122534Z_20230818T184635Z_S1A_30_v0.4.wkt" - transformer = Transformer([ - split_polygon_on_antimeridian_ccw, - simplify_polygon(0.1), - ]) + transformer = Transformer( + [ + split_polygon_on_antimeridian_ccw, + simplify_polygon(0.1), + ] + ) polygons = transformer.from_wkt(wkt_path.read_text()) assert polygons == [ - Polygon([ - (-64.18242781701073, 80.92318071697005), - (-68.40445755029818, 81.31609026531473), - (-68.93161319601728, 81.16999707795055), - (-64.74688665108201, 80.78217738556877), - (-64.18242781701073, 80.92318071697005), - ]), + Polygon( + [ + (-64.18242781701073, 80.92318071697005), + (-68.40445755029818, 81.31609026531473), + (-68.93161319601728, 81.16999707795055), + (-64.74688665108201, 80.78217738556877), + (-64.18242781701073, 80.92318071697005), + ] + ), ] diff --git a/tests/test_transformations.py b/tests/test_transformations.py index 5afc007..99f211c 100644 --- a/tests/test_transformations.py +++ b/tests/test_transformations.py @@ -15,40 +15,48 @@ def test_simplify(): - polygon = Polygon([ - (20, 0), - (20, 0), - (20, 10), - (0, 10), - (0, 0), - (20, 0), - ]) - assert list(simplify_polygon(0.01)(polygon)) == [ - Polygon([ + polygon = Polygon( + [ + (20, 0), (20, 0), (20, 10), (0, 10), (0, 0), (20, 0), - ]), + ] + ) + assert list(simplify_polygon(0.01)(polygon)) == [ + Polygon( + [ + (20, 0), + (20, 10), + (0, 10), + (0, 0), + (20, 0), + ] + ), ] def test_simplify_line(): - polygon = Polygon([ - (20, 0), - (20, 10), - (20, 10), - (20, 0), - (20, 0), - ]) - assert list(simplify_polygon(0.01)(polygon)) == [ - Polygon([ + polygon = Polygon( + [ (20, 0), (20, 10), (20, 10), (20, 0), - ]), + (20, 0), + ] + ) + assert list(simplify_polygon(0.01)(polygon)) == [ + Polygon( + [ + (20, 0), + (20, 10), + (20, 10), + (20, 0), + ] + ), ] assert list(simplify_polygon(0.01, preserve_topology=False)(polygon)) == [ @@ -57,24 +65,28 @@ def test_simplify_line(): def test_densify(): - polygon = Polygon([ - (50, 75), - (10, 80), - (0, 77), - (40, 70), - (50, 75), - ]) - - assert list(densify_polygon(50_000)(polygon)) == [ - Polygon([ + polygon = Polygon( + [ (50, 75), - (34.100003241169595, 78.2028289318241), (10, 80), (0, 77), - (24.297878219303588, 74.40374356383884), (40, 70), (50, 75), - ]), + ] + ) + + assert list(densify_polygon(50_000)(polygon)) == [ + Polygon( + [ + (50, 75), + (34.100003241169595, 78.2028289318241), + (10, 80), + (0, 77), + (24.297878219303588, 74.40374356383884), + (40, 70), + (50, 75), + ] + ), ] @@ -125,18 +137,21 @@ def test_densify_with_holes(): def test_densify_idempotent(): - polygon = Polygon([ - (50, 75), - (10, 80), - (0, 77), - (40, 70), - (50, 75), - ]) + polygon = Polygon( + [ + (50, 75), + (10, 80), + (0, 77), + (40, 70), + (50, 75), + ] + ) transformation = densify_polygon(50_000) densified_polygons = list(transformation(polygon)) double_densified_polygons = [ + # ruff hint poly for densified_polygon in densified_polygons for poly in transformation(densified_polygon) @@ -155,32 +170,38 @@ def test_densify_error(): def test_drop_z_coordinate(): - polygon = Polygon([ - (180, 1, 10), - (180, 0, 10), - (-179.999, 0, 10), - (-179.999, 1, 10), - (180, 1, 10), - ]) + polygon = Polygon( + [ + (180, 1, 10), + (180, 0, 10), + (-179.999, 0, 10), + (-179.999, 1, 10), + (180, 1, 10), + ] + ) assert list(drop_z_coordinate(polygon)) == [ - Polygon([ + Polygon( + [ + (180, 1), + (180, 0), + (-179.999, 0), + (-179.999, 1), + (180, 1), + ] + ), + ] + + +def test_drop_z_coordinate_noop(): + polygon = Polygon( + [ (180, 1), (180, 0), (-179.999, 0), (-179.999, 1), (180, 1), - ]), - ] - - -def test_drop_z_coordinate_noop(): - polygon = Polygon([ - (180, 1), - (180, 0), - (-179.999, 0), - (-179.999, 1), - (180, 1), - ]) + ] + ) assert list(drop_z_coordinate(polygon)) == [polygon] @@ -237,9 +258,15 @@ def test_split_polygon_on_antimeridian_ccw_returns_non_empty_list(polygon): def test_split_polygon_on_antimeridian_ccw_returns_empty_list(): # There is a case where the input polygon is really small, and both split # parts are culled. - polygon = Polygon([ - (180, 1), (180, 0), (-179.999, 0), (-179.999, 1), (180, 1), - ]) + polygon = Polygon( + [ + (180, 1), + (180, 0), + (-179.999, 0), + (-179.999, 1), + (180, 1), + ] + ) assert list(split_polygon_on_antimeridian_ccw(polygon)) == [] @@ -264,20 +291,24 @@ def test_split_polygon_on_antimeridian_ccw_centered(antimeridian_centered_rectan assert poly.exterior.is_valid assert polygons == [ - Polygon([ - (180., -10), - (180., 10.), - (150., 10.), - (150., -10), - (180., -10), - ]), - Polygon([ - (-180., 10), - (-180., -10.), - (-150., -10.), - (-150., 10), - (-180., 10), - ]), + Polygon( + [ + (180.0, -10), + (180.0, 10.0), + (150.0, 10.0), + (150.0, -10), + (180.0, -10), + ] + ), + Polygon( + [ + (-180.0, 10), + (-180.0, -10.0), + (-150.0, -10.0), + (-150.0, 10), + (-180.0, 10), + ] + ), ] @@ -293,26 +324,33 @@ def test_split_polygon_on_antimeridian_ccw_crosses_multiple_times( assert poly.exterior.is_valid assert polygons == [ - Polygon([ - (180., -10), - (180., -4), - (160., 0), - (180., 4), - (180., 10), - (150., 10), - (150., -10), - ]), - Polygon([(-180., -4), (-180., -10), (-150., -10), (-180., -4)]), - Polygon([(-180., 10), (-180., 4), (-150., 10), (-180., 10)]), + Polygon( + [ + (180.0, -10), + (180.0, -4), + (160.0, 0), + (180.0, 4), + (180.0, 10), + (150.0, 10), + (150.0, -10), + ] + ), + Polygon([(-180.0, -4), (-180.0, -10), (-150.0, -10), (-180.0, -4)]), + Polygon([(-180.0, 10), (-180.0, 4), (-150.0, 10), (-180.0, 10)]), ] def test_split_polygon_on_antimeridian_ccw_west(): """Polygon is mostly west of the IDL""" - polygon = Polygon([ - (170., 70.), (170., 60.), (-179., 60.), - (-179., 70.), (170., 70.), - ]) + polygon = Polygon( + [ + (170.0, 70.0), + (170.0, 60.0), + (-179.0, 60.0), + (-179.0, 70.0), + (170.0, 70.0), + ] + ) assert not polygon.exterior.is_ccw polygons = list(split_polygon_on_antimeridian_ccw(polygon)) @@ -321,29 +359,38 @@ def test_split_polygon_on_antimeridian_ccw_west(): assert poly.exterior.is_valid assert polygons == [ - Polygon([ - (180., 60.), - (180., 70.), - (170., 70.), - (170., 60.), - (180., 60.), - ]), - Polygon([ - (-180., 70.), - (-180., 60.), - (-179., 60.), - (-179., 70.), - (-180., 70.), - ]), + Polygon( + [ + (180.0, 60.0), + (180.0, 70.0), + (170.0, 70.0), + (170.0, 60.0), + (180.0, 60.0), + ] + ), + Polygon( + [ + (-180.0, 70.0), + (-180.0, 60.0), + (-179.0, 60.0), + (-179.0, 70.0), + (-180.0, 70.0), + ] + ), ] def test_split_polygon_on_antimeridian_ccw_east(): """Polygon is mostly east of the IDL""" - polygon = Polygon([ - (179., 70.), (179., 60.), (-170., 60.), - (-170., 70.), (179., 70.), - ]) + polygon = Polygon( + [ + (179.0, 70.0), + (179.0, 60.0), + (-170.0, 60.0), + (-170.0, 70.0), + (179.0, 70.0), + ] + ) assert not polygon.exterior.is_ccw polygons = list(split_polygon_on_antimeridian_ccw(polygon)) @@ -352,30 +399,38 @@ def test_split_polygon_on_antimeridian_ccw_east(): assert poly.exterior.is_valid assert polygons == [ - Polygon([ - (180., 60.), - (180., 70.), - (179., 70.), - (179., 60.), - (180., 60.), - ]), - Polygon([ - (-180., 70.), - (-180., 60.), - (-170., 60.), - (-170., 70.), - (-180., 70.), - ]), + Polygon( + [ + (180.0, 60.0), + (180.0, 70.0), + (179.0, 70.0), + (179.0, 60.0), + (180.0, 60.0), + ] + ), + Polygon( + [ + (-180.0, 70.0), + (-180.0, 60.0), + (-170.0, 60.0), + (-170.0, 70.0), + (-180.0, 70.0), + ] + ), ] def test_split_polygon_on_antimeridian_ccw_close_point(): """Polygon has a point that is extremely close to the antimeridian""" - polygon = Polygon([ - (179.999999, 70.), - (179., 60.), (-170., 60.), - (-170., 70.), (179., 70.), - ]) + polygon = Polygon( + [ + (179.999999, 70.0), + (179.0, 60.0), + (-170.0, 60.0), + (-170.0, 70.0), + (179.0, 70.0), + ] + ) assert not polygon.exterior.is_ccw polygons = list(split_polygon_on_antimeridian_ccw(polygon)) @@ -387,31 +442,33 @@ def test_split_polygon_on_antimeridian_ccw_close_point(): coords = [list(poly.boundary.coords) for poly in polygons] assert coords == [ [ - (180., 60.), - (180., 70.), - (179.999999, 70.), - (179., 60.), - (180., 60.), + (180.0, 60.0), + (180.0, 70.0), + (179.999999, 70.0), + (179.0, 60.0), + (180.0, 60.0), ], [ - (-180., 70.), - (-180., 60.), - (-170., 60.), - (-170., 70.), - (-180., 70.), + (-180.0, 70.0), + (-180.0, 60.0), + (-170.0, 60.0), + (-170.0, 70.0), + (-180.0, 70.0), ], ] def test_split_polygon_on_antimeridian_ccw_alos_example(): """Example from ALOS mission: ALPSRP237090990-L1.1""" - polygon = Polygon([ - (179.648, 50.172), - (179.794, 49.658), - (-179.255, 49.766), - (-179.392, 50.281), - (179.648, 50.172), - ]) + polygon = Polygon( + [ + (179.648, 50.172), + (179.794, 49.658), + (-179.255, 49.766), + (-179.392, 50.281), + (179.648, 50.172), + ] + ) polygons = list(split_polygon_on_antimeridian_ccw(polygon)) for poly in polygons: @@ -422,30 +479,32 @@ def test_split_polygon_on_antimeridian_ccw_alos_example(): coords = [list(poly.boundary.coords) for poly in polygons] assert coords == [ [ - (180., 49.68139432176656), - (180., 50.21196666666666), + (180.0, 49.68139432176656), + (180.0, 50.21196666666666), (179.64800000000002, 50.172), (179.79399999999998, 49.658), - (180., 49.68139432176656), + (180.0, 49.68139432176656), ], [ - (-180., 50.21196666666666), - (-180., 49.68139432176656), + (-180.0, 50.21196666666666), + (-180.0, 49.68139432176656), (-179.255, 49.766), (-179.392, 50.281), - (-180., 50.21196666666666), + (-180.0, 50.21196666666666), ], ] def test_split_polygon_on_antimeridian_ccw_alos2_example(): """ALOS2 granule: ALOS2075945400-151019-WBDR1.1__D""" - polygon = Polygon([ - (-178.328, -79.438), - (179.625, -76.163), - (166.084, -76.163), - (164.037, -79.438), - ]) + polygon = Polygon( + [ + (-178.328, -79.438), + (179.625, -76.163), + (166.084, -76.163), + (164.037, -79.438), + ] + ) polygons = list(split_polygon_on_antimeridian_ccw(polygon)) for poly in polygons: @@ -456,18 +515,18 @@ def test_split_polygon_on_antimeridian_ccw_alos2_example(): coords = [list(poly.boundary.coords) for poly in polygons] assert coords == [ [ - (-180., -76.76296336101612), - (-180., -79.438), + (-180.0, -76.76296336101612), + (-180.0, -79.438), (-178.328, -79.438), - (-180., -76.76296336101612), + (-180.0, -76.76296336101612), ], [ - (180., -79.438), - (180., -76.76296336101612), + (180.0, -79.438), + (180.0, -76.76296336101612), (179.625, -76.163), (166.08400000000006, -76.163), (164.03700000000003, -79.438), - (180., -79.438), + (180.0, -79.438), ], ] @@ -494,18 +553,18 @@ def test_split_polygon_on_antimeridian_ccw_opera_example(): coords = [list(poly.boundary.coords) for poly in polygons] assert coords == [ [ - (180., 66.140), - (180., 66.663), + (180.0, 66.140), + (180.0, 66.663), (178.83400000000006, 66.663), (178.83400000000006, 66.140), - (180., 66.140), + (180.0, 66.140), ], [ - (-180., 66.663), - (-180., 66.140), + (-180.0, 66.663), + (-180.0, 66.140), (-178.918, 66.140), (-178.918, 66.663), - (-180., 66.663), + (-180.0, 66.663), ], ] @@ -515,14 +574,16 @@ def test_split_polygon_on_antimeridian_ccw_opera_example_pre_split(): OPERA_L2_CSLC-S1_T001-000688-IW1_20250504T183220Z_20250505T112029Z_S1A_VV_v1.1 """ - polygon = Polygon([ - (180, 64.67712437067621), - (180, 64.50629047887854), - (179.9988239237079, 64.50640025835617), - (179.9167734717595, 64.51400884003007), - (179.999315144991, 64.6771877237759), - (180, 64.67712437067621), - ]) + polygon = Polygon( + [ + (180, 64.67712437067621), + (180, 64.50629047887854), + (179.9988239237079, 64.50640025835617), + (179.9167734717595, 64.51400884003007), + (179.999315144991, 64.6771877237759), + (180, 64.67712437067621), + ] + ) assert not polygon.exterior.is_ccw polygons = list(split_polygon_on_antimeridian_ccw(polygon)) @@ -546,65 +607,67 @@ def test_split_polygon_on_antimeridian_ccw_opera_example_pre_split(): def test_split_polygon_on_antimeridian_ccw_sentinel_ocn_example(): """Sentinel-1 granule: S1A_WV_OCN__2SSV_20250417T170934_20250417T172302_058799_07490A_662C""" - polygon = Polygon([ - (-173.31352985574108, -23.14698567224461), - (-173.77162229214494, -24.907619019866505), - (-174.2415526063507, -26.665847671745183), - (-174.735358150903, -28.420448333916106), - (-175.23380277184344, -30.175206972263744), - (-175.74843654546004, -31.927869767925337), - (-176.2807594129271, -33.67798464336149), - (-176.84487055921355, -35.423184310947256), - (-177.41910677624742, -37.16801395691638), - (-178.0174237891529, -38.90994274849644), - (-178.6424368542418, -40.64852489269256), - (-179.29727678081028, -42.38361736393), - (-179.99919575326913, -44.11165778890455), - (179.27499973531806, -45.83867913785123), - (178.50719394616408, -47.561023088516535), - (177.69231780926836, -49.27817128078806), - (176.80904931895057, -50.986415957829536), - (175.87985821681252, -52.69120887337212), - (174.8814954194563, -54.38819050545594), - (173.80356416208477, -56.07742986626234), - (172.6342022987177, -57.75707684914518), - (171.3430337906186, -59.42214751260288), - (169.94378551545861, -61.077752113025916), - (168.3999709466183, -62.71805533391731), - (166.6843566389666, -64.34111371291355), - (164.74985524368935, -65.9397497607168), - (162.5883735575569, -67.5152692747083), - (160.1325459675333, -69.06048810117184), - (154.88126113623596, -68.86722808467104), - (157.66232733899088, -67.40109715863518), - (160.11788634153672, -65.89157783252615), - (162.30350978708452, -64.34830642665239), - (164.26115705334965, -62.776359315577984), - (166.0243795283944, -61.18062028554268), - (167.62930602018182, -59.5668614442984), - (169.08373088867933, -57.93420475768521), - (170.41560899457167, -56.28647419580335), - (171.64130903910598, -54.625361215229724), - (172.78119311087207, -52.95574121072587), - (173.83243861741815, -51.273905612708624), - (174.81205988512076, -49.58367135376619), - (175.72884840278266, -47.885484758555855), - (176.58940809511245, -46.18095578091026), - (177.407673659417, -44.471546605796334), - (178.17413248284223, -42.75510333566816), - (178.90089160626385, -41.03375212942789), - (179.59202341272197, -39.307739657248156), - (-179.74246296618378, -37.57885571562622), - (-179.11269276255436, -35.84470103625437), - (-178.50911206250385, -34.10700088461006), - (-177.92939864490123, -32.366184612752285), - (-177.3711810617254, -30.622149243259848), - (-176.8274107386524, -28.87700042708585), - (-176.30710772502422, -27.127570832268837), - (-175.8034798185683, -25.37659855071509), - (-175.3146666830624, -23.622777737104464), - (-173.31352985574108, -23.14698567224461), - ]) + polygon = Polygon( + [ + (-173.31352985574108, -23.14698567224461), + (-173.77162229214494, -24.907619019866505), + (-174.2415526063507, -26.665847671745183), + (-174.735358150903, -28.420448333916106), + (-175.23380277184344, -30.175206972263744), + (-175.74843654546004, -31.927869767925337), + (-176.2807594129271, -33.67798464336149), + (-176.84487055921355, -35.423184310947256), + (-177.41910677624742, -37.16801395691638), + (-178.0174237891529, -38.90994274849644), + (-178.6424368542418, -40.64852489269256), + (-179.29727678081028, -42.38361736393), + (-179.99919575326913, -44.11165778890455), + (179.27499973531806, -45.83867913785123), + (178.50719394616408, -47.561023088516535), + (177.69231780926836, -49.27817128078806), + (176.80904931895057, -50.986415957829536), + (175.87985821681252, -52.69120887337212), + (174.8814954194563, -54.38819050545594), + (173.80356416208477, -56.07742986626234), + (172.6342022987177, -57.75707684914518), + (171.3430337906186, -59.42214751260288), + (169.94378551545861, -61.077752113025916), + (168.3999709466183, -62.71805533391731), + (166.6843566389666, -64.34111371291355), + (164.74985524368935, -65.9397497607168), + (162.5883735575569, -67.5152692747083), + (160.1325459675333, -69.06048810117184), + (154.88126113623596, -68.86722808467104), + (157.66232733899088, -67.40109715863518), + (160.11788634153672, -65.89157783252615), + (162.30350978708452, -64.34830642665239), + (164.26115705334965, -62.776359315577984), + (166.0243795283944, -61.18062028554268), + (167.62930602018182, -59.5668614442984), + (169.08373088867933, -57.93420475768521), + (170.41560899457167, -56.28647419580335), + (171.64130903910598, -54.625361215229724), + (172.78119311087207, -52.95574121072587), + (173.83243861741815, -51.273905612708624), + (174.81205988512076, -49.58367135376619), + (175.72884840278266, -47.885484758555855), + (176.58940809511245, -46.18095578091026), + (177.407673659417, -44.471546605796334), + (178.17413248284223, -42.75510333566816), + (178.90089160626385, -41.03375212942789), + (179.59202341272197, -39.307739657248156), + (-179.74246296618378, -37.57885571562622), + (-179.11269276255436, -35.84470103625437), + (-178.50911206250385, -34.10700088461006), + (-177.92939864490123, -32.366184612752285), + (-177.3711810617254, -30.622149243259848), + (-176.8274107386524, -28.87700042708585), + (-176.30710772502422, -27.127570832268837), + (-175.8034798185683, -25.37659855071509), + (-175.3146666830624, -23.622777737104464), + (-173.31352985574108, -23.14698567224461), + ] + ) polygons = list(split_polygon_on_antimeridian_ccw(polygon)) for poly in polygons: @@ -685,10 +748,15 @@ def test_split_polygon_on_antimeridian_ccw_sentinel_ocn_example(): def test_split_polygon_on_antimeridian_fixed_size_alos2_example(): """Example from ALOS2: ALOS2014555550-140830""" - polygon = Polygon([ - (-164.198, -82.125), (172.437, -83.885), (165.618, -80.869), - (-176.331, -79.578), (-164.198, -82.125), - ]) + polygon = Polygon( + [ + (-164.198, -82.125), + (172.437, -83.885), + (165.618, -80.869), + (-176.331, -79.578), + (-164.198, -82.125), + ] + ) polygons = list(split_polygon_on_antimeridian_fixed_size(40)(polygon)) for poly in polygons: @@ -701,15 +769,15 @@ def test_split_polygon_on_antimeridian_fixed_size_alos2_example(): [ (-164.198, -82.125), (-176.331, -79.578), - (-180., -79.84040535150407), - (-180., -83.31530686924889), + (-180.0, -79.84040535150407), + (-180.0, -83.31530686924889), (-164.198, -82.125), ], [ - (180., -83.31530686924889), - (180., -79.84040535150407), + (180.0, -83.31530686924889), + (180.0, -79.84040535150407), (165.61799999999994, -80.869), (172.437, -83.885), - (180., -83.31530686924889), + (180.0, -83.31530686924889), ], ] diff --git a/tests/test_transformer.py b/tests/test_transformer.py index 9f559f3..8b4b4f8 100644 --- a/tests/test_transformer.py +++ b/tests/test_transformer.py @@ -8,9 +8,11 @@ @pytest.fixture def simplify_transformer(): - return Transformer([ - simplify_polygon(0.1), - ]) + return Transformer( + [ + simplify_polygon(0.1), + ] + ) def test_from_wkt(simplify_transformer): @@ -18,113 +20,132 @@ def test_from_wkt(simplify_transformer): assert simplify_transformer.from_wkt( "POLYGON ((50 20, 50 21, 51 21, 51 20, 50 20))", ) == [ - Polygon([ - (50.0, 20.0), - (50.0, 21.0), - (51.0, 21.0), - (51.0, 20.0), - (50.0, 20.0), - ]), + Polygon( + [ + (50.0, 20.0), + (50.0, 21.0), + (51.0, 21.0), + (51.0, 20.0), + (50.0, 20.0), + ] + ), ] assert simplify_transformer.from_wkt( "POLYGON(( 1 1, 2 1, 1 2, 1 1))", ) == [ - Polygon([ - (1, 1), - (2, 1), - (1, 2), - (1, 1), - ]), + Polygon( + [ + (1, 1), + (2, 1), + (1, 2), + (1, 1), + ] + ), ] # Duplicate point is removed assert simplify_transformer.from_wkt( "POLYGON ((50 20, 50 21, 51 21, 51 20, 50 20, 50 20))", ) == [ - Polygon([ - (50.0, 20.0), - (50.0, 21.0), - (51.0, 21.0), - (51.0, 20.0), - (50.0, 20.0), - ]), + Polygon( + [ + (50.0, 20.0), + (50.0, 21.0), + (51.0, 21.0), + (51.0, 20.0), + (50.0, 20.0), + ] + ), ] def test_from_wkt_multipolygon(simplify_transformer): assert simplify_transformer.from_wkt( - "MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20))," - "((15 5, 40 10, 10 20, 5 10, 15 5)))", + "MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)),((15 5, 40 10, 10 20, 5 10, 15 5)))", ) == [ - Polygon([ - (30.0, 20.0), - (45.0, 40.0), - (10.0, 40.0), - (30.0, 20.0), - ]), - Polygon([ - (15.0, 5.0), - (40.0, 10.0), - (10.0, 20.0), - (5.0, 10.0), - (15.0, 5.0), - ]), + Polygon( + [ + (30.0, 20.0), + (45.0, 40.0), + (10.0, 40.0), + (30.0, 20.0), + ] + ), + Polygon( + [ + (15.0, 5.0), + (40.0, 10.0), + (10.0, 20.0), + (5.0, 10.0), + (15.0, 5.0), + ] + ), ] def test_from_geo_json(simplify_transformer): # Clockwise polygon remains clockwise - assert simplify_transformer.from_geo_json({ - "type": "Polygon", - "coordinates": [ - [ - [50, 20], - [50, 21], - [51, 21], - [51, 20], - [50, 20], + assert simplify_transformer.from_geo_json( + { + "type": "Polygon", + "coordinates": [ + [ + [50, 20], + [50, 21], + [51, 21], + [51, 20], + [50, 20], + ], ], - ], - }) == [ - Polygon([ - (50.0, 20.0), - (50.0, 21.0), - (51.0, 21.0), - (51.0, 20.0), - (50.0, 20.0), - ]), - ] - assert simplify_transformer.from_geo_json({ - "type": "Polygon", - "coordinates": [ + } + ) == [ + Polygon( [ - [1, 1], - [2, 1], - [1, 2], - [1, 1], + (50.0, 20.0), + (50.0, 21.0), + (51.0, 21.0), + (51.0, 20.0), + (50.0, 20.0), + ] + ), + ] + assert simplify_transformer.from_geo_json( + { + "type": "Polygon", + "coordinates": [ + [ + [1, 1], + [2, 1], + [1, 2], + [1, 1], + ], ], - ], - }) == [ - Polygon([ - (1, 1), - (2, 1), - (1, 2), - (1, 1), - ]), + } + ) == [ + Polygon( + [ + (1, 1), + (2, 1), + (1, 2), + (1, 1), + ] + ), ] # Duplicate point is removed - assert simplify_transformer.from_geo_json({ - "type": "Polygon", - "coordinates": [ - [ - [50.0, 20.0], - [50.0, 21.0], - [51.0, 21.0], - [51.0, 20.0], - [50.0, 20.0], - [50.0, 20.0], + assert simplify_transformer.from_geo_json( + { + "type": "Polygon", + "coordinates": [ + [ + [50.0, 20.0], + [50.0, 21.0], + [51.0, 21.0], + [51.0, 20.0], + [50.0, 20.0], + [50.0, 20.0], + ], ], - ], - }) == [ + } + ) == [ Polygon( [ (50.0, 20.0), @@ -198,10 +219,12 @@ def test_from_geo_json_bad_points(simplify_transformer): Exception, match=r"'POINT \(30 10\)' is not a Polygon or MultiPolygon", ): - simplify_transformer.from_geo_json({ - "type": "Point", - "coordinates": [[30, 10]], - }) + simplify_transformer.from_geo_json( + { + "type": "Point", + "coordinates": [[30, 10]], + } + ) with pytest.raises(AttributeError): simplify_transformer.from_geo_json({})