From 9a6767703dcbd9eefc6ca12319e3d6b40b22c3f2 Mon Sep 17 00:00:00 2001 From: kcj-coding Date: Tue, 3 Nov 2026 12:53:04 +0000 Subject: [PATCH 01/18] test new multipolygon geometry --- digital_land/datatype/wkt.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/digital_land/datatype/wkt.py b/digital_land/datatype/wkt.py index 398b8c3a..50d7833b 100644 --- a/digital_land/datatype/wkt.py +++ b/digital_land/datatype/wkt.py @@ -4,7 +4,7 @@ import logging from shapely.geometry import shape, Point from shapely.errors import ShapelyError -from shapely.ops import transform +from shapely.ops import transform, unary_union from shapely.geometry import MultiPolygon from shapely.geometry.polygon import orient from shapely.validation import explain_validity, make_valid @@ -227,7 +227,10 @@ def normalise_geometry(geometry, simplification=0.000001): issue = None if not geometry.is_valid: issue = explain_validity(geometry) - geometry = make_valid(geometry) + if geometry.geom_type == "MultiPolygon": + geometry = unary_union([make_valid(part) for part in geometry.geoms]) + else: + geometry = make_valid(geometry) # ensure geometry is a MultiPolygon geometry = make_multipolygon(geometry) From aedee6a8edd651de0f1b343c06da01f3e8a4850c Mon Sep 17 00:00:00 2001 From: kcj-coding Date: Tue, 3 Nov 2026 14:28:01 +0000 Subject: [PATCH 02/18] updated unit tests --- tests/unit/datatype/test_wkt.py | 70 ++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/tests/unit/datatype/test_wkt.py b/tests/unit/datatype/test_wkt.py index ba226981..ff8dffc9 100644 --- a/tests/unit/datatype/test_wkt.py +++ b/tests/unit/datatype/test_wkt.py @@ -3,11 +3,18 @@ from shapely.validation import explain_validity, make_valid import pytest -from digital_land.datatype.wkt import WktDataType, parse_wkt, flip, metres_like +from digital_land.datatype.wkt import ( + WktDataType, + parse_wkt, + flip, + metres_like, + normalise_geometry, +) from digital_land.datatype.wkt import DEFAULT_BOUNDARY from digital_land.datatype.multipolygon import MultiPolygonDataType from digital_land.log import IssueLog from shapely.geometry import MultiPolygon +from shapely.ops import unary_union def test_normalise_returns_valid_shape_and_record_issue(): @@ -637,3 +644,64 @@ def test_metres_like_checks_both_axes(): assert metres_like(-14245.78, 6711600.07) assert not metres_like(30000000.0, 6711600.07) assert not metres_like(-30000000.0, 6711600.07) + + +# tests to check the unary_union function of shapely +def test_normalise_geometry_hole_outside_shell(): + input_wkt = "MULTIPOLYGON (" + "((0 0, 10 0, 10 10, 0 10, 0 0)), " # Part 1 (Solid large square) + "((20 20, 21 20, 21 21, 20 21, 20 20), (2 2, 2 3, 3 3, 3 2, 2 2))" # Part 2 with stray hole + ")" + output_wkt = shapely.wkt.loads(input_wkt) + assert not output_wkt.is_valid # Verify baseline invalidity + + fixed_geom = unary_union([make_valid(part) for part in output_wkt.geoms]) + + assert fixed_geom.is_valid + # The large square (0,0 to 10,10) should have an area of 100, + # plus 1 from the tiny square. Total area should be 101, NOT ~98. + assert pytest.approx(fixed_geom.area) == 101.0 + + +def test_normalise_geometry_overlapping_parts(): + input_wkt = "MULTIPOLYGON (" + "((0 0, 2 0, 2 2, 0 2, 0 0)), " + "((1 0, 3 0, 3 2, 1 2, 1 0))" + ")" + output_wkt = shapely.wkt.loads(input_wkt) + + fixed_geom = unary_union([make_valid(part) for part in output_wkt.geoms]) + + assert fixed_geom.is_valid + # Two 2x2 squares overlapping by 1 unit + assert pytest.approx(fixed_geom.area) == 7.0 + + +def test_normalise_geometry_bowtie_unchanged(): + input_wkt = "POLYGON ((0 0, 0 2, 2 0, 2 2, 0 0))" + output_wkt = shapely.wkt.loads(input_wkt) + + assert not output_wkt.is_valid + exp_geom = make_valid(output_wkt) + if output_wkt.geom_type == "Multipolygon": + fixed_geom = unary_union([make_valid(part) for part in output_wkt.geoms]) + else: + fixed_geom = make_valid(output_wkt) + + assert fixed_geom.is_valid + assert fixed_geom.equals(exp_geom) + + +def test_normalise_geometry_valid_unchanged(): + input_wkt = "MULTIPOLYGON (" + "((0 0, 2 0, 2 2, 0 2, 0 0)), " + "((4 4, 6 4, 6 6, 4 6, 4 4))" + ")" + output_wkt = shapely.wkt.loads(input_wkt) + + fixed_geom = normalise_geometry( + output_wkt + ) # normalise_geometry function from wkt.py + + assert fixed_geom.is_valid + assert fixed_geom.wkt == output_wkt.wkt From a9582441cb1ef948904b81d19d01e1fb0b1e58be Mon Sep 17 00:00:00 2001 From: kcj-coding Date: Tue, 3 Nov 2026 15:03:21 +0000 Subject: [PATCH 03/18] updated unit tests --- tests/unit/datatype/test_wkt.py | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/tests/unit/datatype/test_wkt.py b/tests/unit/datatype/test_wkt.py index ff8dffc9..419c8297 100644 --- a/tests/unit/datatype/test_wkt.py +++ b/tests/unit/datatype/test_wkt.py @@ -648,10 +648,7 @@ def test_metres_like_checks_both_axes(): # tests to check the unary_union function of shapely def test_normalise_geometry_hole_outside_shell(): - input_wkt = "MULTIPOLYGON (" - "((0 0, 10 0, 10 10, 0 10, 0 0)), " # Part 1 (Solid large square) - "((20 20, 21 20, 21 21, 20 21, 20 20), (2 2, 2 3, 3 3, 3 2, 2 2))" # Part 2 with stray hole - ")" + input_wkt = "MULTIPOLYGON (((0 0, 10 0, 10 10, 0 10, 0 0)),((20 20, 21 20, 21 21, 20 21, 20 20), (2 2, 2 3, 3 3, 3 2, 2 2))" output_wkt = shapely.wkt.loads(input_wkt) assert not output_wkt.is_valid # Verify baseline invalidity @@ -664,10 +661,7 @@ def test_normalise_geometry_hole_outside_shell(): def test_normalise_geometry_overlapping_parts(): - input_wkt = "MULTIPOLYGON (" - "((0 0, 2 0, 2 2, 0 2, 0 0)), " - "((1 0, 3 0, 3 2, 1 2, 1 0))" - ")" + input_wkt = "MULTIPOLYGON (((0 0, 2 0, 2 2, 0 2, 0 0)), ((1 0, 3 0, 3 2, 1 2, 1 0)))" output_wkt = shapely.wkt.loads(input_wkt) fixed_geom = unary_union([make_valid(part) for part in output_wkt.geoms]) @@ -693,10 +687,7 @@ def test_normalise_geometry_bowtie_unchanged(): def test_normalise_geometry_valid_unchanged(): - input_wkt = "MULTIPOLYGON (" - "((0 0, 2 0, 2 2, 0 2, 0 0)), " - "((4 4, 6 4, 6 6, 4 6, 4 4))" - ")" + input_wkt = "MULTIPOLYGON (((0 0, 2 0, 2 2, 0 2, 0 0)), ((4 4, 6 4, 6 6, 4 6, 4 4)))" output_wkt = shapely.wkt.loads(input_wkt) fixed_geom = normalise_geometry( From 727c3cfe13241b7808ecfea7ff1642d2cc368982 Mon Sep 17 00:00:00 2001 From: kcj-coding Date: Tue, 3 Nov 2026 15:09:23 +0000 Subject: [PATCH 04/18] updated unit tests --- tests/unit/datatype/test_wkt.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/unit/datatype/test_wkt.py b/tests/unit/datatype/test_wkt.py index 419c8297..f60115bf 100644 --- a/tests/unit/datatype/test_wkt.py +++ b/tests/unit/datatype/test_wkt.py @@ -661,7 +661,9 @@ def test_normalise_geometry_hole_outside_shell(): def test_normalise_geometry_overlapping_parts(): - input_wkt = "MULTIPOLYGON (((0 0, 2 0, 2 2, 0 2, 0 0)), ((1 0, 3 0, 3 2, 1 2, 1 0)))" + input_wkt = ( + "MULTIPOLYGON (((0 0, 2 0, 2 2, 0 2, 0 0)), ((1 0, 3 0, 3 2, 1 2, 1 0)))" + ) output_wkt = shapely.wkt.loads(input_wkt) fixed_geom = unary_union([make_valid(part) for part in output_wkt.geoms]) @@ -687,7 +689,9 @@ def test_normalise_geometry_bowtie_unchanged(): def test_normalise_geometry_valid_unchanged(): - input_wkt = "MULTIPOLYGON (((0 0, 2 0, 2 2, 0 2, 0 0)), ((4 4, 6 4, 6 6, 4 6, 4 4)))" + input_wkt = ( + "MULTIPOLYGON (((0 0, 2 0, 2 2, 0 2, 0 0)), ((4 4, 6 4, 6 6, 4 6, 4 4)))" + ) output_wkt = shapely.wkt.loads(input_wkt) fixed_geom = normalise_geometry( From 404e7bba98a3a5e2ad82ecca125f2eafe3dcd62e Mon Sep 17 00:00:00 2001 From: kcj-coding Date: Tue, 3 Nov 2026 15:16:59 +0000 Subject: [PATCH 05/18] updated unit tests --- tests/unit/datatype/test_wkt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/datatype/test_wkt.py b/tests/unit/datatype/test_wkt.py index f60115bf..559f2fd1 100644 --- a/tests/unit/datatype/test_wkt.py +++ b/tests/unit/datatype/test_wkt.py @@ -648,7 +648,7 @@ def test_metres_like_checks_both_axes(): # tests to check the unary_union function of shapely def test_normalise_geometry_hole_outside_shell(): - input_wkt = "MULTIPOLYGON (((0 0, 10 0, 10 10, 0 10, 0 0)),((20 20, 21 20, 21 21, 20 21, 20 20), (2 2, 2 3, 3 3, 3 2, 2 2))" + input_wkt = "MULTIPOLYGON (((0 0, 10 0, 10 10, 0 10, 0 0)),((20 20, 21 20, 21 21, 20 21, 20 20), (2 2, 2 3, 3 3, 3 2, 2 2)))" output_wkt = shapely.wkt.loads(input_wkt) assert not output_wkt.is_valid # Verify baseline invalidity From f68728ce49e5a57fec5cdc9f32d6d5235da36fa2 Mon Sep 17 00:00:00 2001 From: kcj-coding Date: Tue, 3 Nov 2026 15:27:05 +0000 Subject: [PATCH 06/18] updated unit tests --- tests/unit/datatype/test_wkt.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/unit/datatype/test_wkt.py b/tests/unit/datatype/test_wkt.py index 559f2fd1..9b32346e 100644 --- a/tests/unit/datatype/test_wkt.py +++ b/tests/unit/datatype/test_wkt.py @@ -666,7 +666,7 @@ def test_normalise_geometry_overlapping_parts(): ) output_wkt = shapely.wkt.loads(input_wkt) - fixed_geom = unary_union([make_valid(part) for part in output_wkt.geoms]) + fixed_geom = normalise_geometry(input_wkt)#unary_union([make_valid(part) for part in output_wkt.geoms]) assert fixed_geom.is_valid # Two 2x2 squares overlapping by 1 unit @@ -694,9 +694,11 @@ def test_normalise_geometry_valid_unchanged(): ) output_wkt = shapely.wkt.loads(input_wkt) - fixed_geom = normalise_geometry( + result = normalise_geometry( output_wkt ) # normalise_geometry function from wkt.py + fixed_geom = result[0] if isinstance(result, tuple) else result + assert fixed_geom.is_valid assert fixed_geom.wkt == output_wkt.wkt From 23da563efc39dcb9965bd9ed39052d74655861b2 Mon Sep 17 00:00:00 2001 From: kcj-coding Date: Tue, 3 Nov 2026 16:02:15 +0000 Subject: [PATCH 07/18] updated unit tests --- tests/unit/datatype/test_wkt.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/tests/unit/datatype/test_wkt.py b/tests/unit/datatype/test_wkt.py index 9b32346e..62f0fd03 100644 --- a/tests/unit/datatype/test_wkt.py +++ b/tests/unit/datatype/test_wkt.py @@ -652,7 +652,9 @@ def test_normalise_geometry_hole_outside_shell(): output_wkt = shapely.wkt.loads(input_wkt) assert not output_wkt.is_valid # Verify baseline invalidity - fixed_geom = unary_union([make_valid(part) for part in output_wkt.geoms]) + fixed_geom = normalise_geometry( + output_wkt + ) # unary_union([make_valid(part) for part in output_wkt.geoms]) assert fixed_geom.is_valid # The large square (0,0 to 10,10) should have an area of 100, @@ -666,7 +668,9 @@ def test_normalise_geometry_overlapping_parts(): ) output_wkt = shapely.wkt.loads(input_wkt) - fixed_geom = normalise_geometry(input_wkt)#unary_union([make_valid(part) for part in output_wkt.geoms]) + fixed_geom = normalise_geometry( + input_wkt + ) # unary_union([make_valid(part) for part in output_wkt.geoms]) assert fixed_geom.is_valid # Two 2x2 squares overlapping by 1 unit @@ -680,7 +684,9 @@ def test_normalise_geometry_bowtie_unchanged(): assert not output_wkt.is_valid exp_geom = make_valid(output_wkt) if output_wkt.geom_type == "Multipolygon": - fixed_geom = unary_union([make_valid(part) for part in output_wkt.geoms]) + fixed_geom = normalise_geometry( + input_wkt + ) # unary_union([make_valid(part) for part in output_wkt.geoms]) else: fixed_geom = make_valid(output_wkt) @@ -694,9 +700,7 @@ def test_normalise_geometry_valid_unchanged(): ) output_wkt = shapely.wkt.loads(input_wkt) - result = normalise_geometry( - output_wkt - ) # normalise_geometry function from wkt.py + result = normalise_geometry(output_wkt) # normalise_geometry function from wkt.py fixed_geom = result[0] if isinstance(result, tuple) else result From 0edf8e9306592065bd5ac4762e4eb82b0872a691 Mon Sep 17 00:00:00 2001 From: kcj-coding Date: Tue, 3 Nov 2026 16:12:35 +0000 Subject: [PATCH 08/18] updated unit tests --- tests/unit/datatype/test_wkt.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/datatype/test_wkt.py b/tests/unit/datatype/test_wkt.py index 62f0fd03..a5d29ab0 100644 --- a/tests/unit/datatype/test_wkt.py +++ b/tests/unit/datatype/test_wkt.py @@ -669,7 +669,7 @@ def test_normalise_geometry_overlapping_parts(): output_wkt = shapely.wkt.loads(input_wkt) fixed_geom = normalise_geometry( - input_wkt + output_wkt ) # unary_union([make_valid(part) for part in output_wkt.geoms]) assert fixed_geom.is_valid @@ -685,7 +685,7 @@ def test_normalise_geometry_bowtie_unchanged(): exp_geom = make_valid(output_wkt) if output_wkt.geom_type == "Multipolygon": fixed_geom = normalise_geometry( - input_wkt + output_wkt ) # unary_union([make_valid(part) for part in output_wkt.geoms]) else: fixed_geom = make_valid(output_wkt) From c06bf02059f718dba9de302d263ccc47d4148987 Mon Sep 17 00:00:00 2001 From: kcj-coding Date: Tue, 3 Nov 2026 16:17:09 +0000 Subject: [PATCH 09/18] updated unit tests --- tests/unit/datatype/test_wkt.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/unit/datatype/test_wkt.py b/tests/unit/datatype/test_wkt.py index a5d29ab0..a47d54fc 100644 --- a/tests/unit/datatype/test_wkt.py +++ b/tests/unit/datatype/test_wkt.py @@ -653,8 +653,8 @@ def test_normalise_geometry_hole_outside_shell(): assert not output_wkt.is_valid # Verify baseline invalidity fixed_geom = normalise_geometry( - output_wkt - ) # unary_union([make_valid(part) for part in output_wkt.geoms]) + output_wkt + ) # unary_union([make_valid(part) for part in output_wkt.geoms]) assert fixed_geom.is_valid # The large square (0,0 to 10,10) should have an area of 100, @@ -685,8 +685,8 @@ def test_normalise_geometry_bowtie_unchanged(): exp_geom = make_valid(output_wkt) if output_wkt.geom_type == "Multipolygon": fixed_geom = normalise_geometry( - output_wkt - ) # unary_union([make_valid(part) for part in output_wkt.geoms]) + output_wkt + ) # unary_union([make_valid(part) for part in output_wkt.geoms]) else: fixed_geom = make_valid(output_wkt) From cfac17c22bdb4b4dda8a3d2ef2e39819c30f6249 Mon Sep 17 00:00:00 2001 From: kcj-coding Date: Tue, 3 Nov 2026 16:38:46 +0000 Subject: [PATCH 10/18] updated unit tests --- tests/unit/datatype/test_wkt.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit/datatype/test_wkt.py b/tests/unit/datatype/test_wkt.py index a47d54fc..87ddd6be 100644 --- a/tests/unit/datatype/test_wkt.py +++ b/tests/unit/datatype/test_wkt.py @@ -14,7 +14,6 @@ from digital_land.datatype.multipolygon import MultiPolygonDataType from digital_land.log import IssueLog from shapely.geometry import MultiPolygon -from shapely.ops import unary_union def test_normalise_returns_valid_shape_and_record_issue(): From 723ec73c323a178d515968b3d73dc0f9794342ce Mon Sep 17 00:00:00 2001 From: kcj-coding Date: Tue, 3 Nov 2026 16:46:59 +0000 Subject: [PATCH 11/18] updated unit tests --- tests/unit/datatype/test_wkt.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tests/unit/datatype/test_wkt.py b/tests/unit/datatype/test_wkt.py index 87ddd6be..5d9ffedd 100644 --- a/tests/unit/datatype/test_wkt.py +++ b/tests/unit/datatype/test_wkt.py @@ -651,10 +651,12 @@ def test_normalise_geometry_hole_outside_shell(): output_wkt = shapely.wkt.loads(input_wkt) assert not output_wkt.is_valid # Verify baseline invalidity - fixed_geom = normalise_geometry( + result= normalise_geometry( output_wkt ) # unary_union([make_valid(part) for part in output_wkt.geoms]) + fixed_geom = result[0] if isinstance(result, tuple) else result + assert fixed_geom.is_valid # The large square (0,0 to 10,10) should have an area of 100, # plus 1 from the tiny square. Total area should be 101, NOT ~98. @@ -667,10 +669,12 @@ def test_normalise_geometry_overlapping_parts(): ) output_wkt = shapely.wkt.loads(input_wkt) - fixed_geom = normalise_geometry( + result = normalise_geometry( output_wkt ) # unary_union([make_valid(part) for part in output_wkt.geoms]) + fixed_geom = result[0] if isinstance(result, tuple) else result + assert fixed_geom.is_valid # Two 2x2 squares overlapping by 1 unit assert pytest.approx(fixed_geom.area) == 7.0 @@ -683,11 +687,13 @@ def test_normalise_geometry_bowtie_unchanged(): assert not output_wkt.is_valid exp_geom = make_valid(output_wkt) if output_wkt.geom_type == "Multipolygon": - fixed_geom = normalise_geometry( + result = normalise_geometry( output_wkt ) # unary_union([make_valid(part) for part in output_wkt.geoms]) else: - fixed_geom = make_valid(output_wkt) + result = make_valid(output_wkt) + + fixed_geom = result[0] if isinstance(result, tuple) else result assert fixed_geom.is_valid assert fixed_geom.equals(exp_geom) From 1630bddc0a7e8cbb02097674300d0a71793555d6 Mon Sep 17 00:00:00 2001 From: kcj-coding Date: Tue, 3 Nov 2026 16:51:28 +0000 Subject: [PATCH 12/18] updated unit tests --- tests/unit/datatype/test_wkt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/datatype/test_wkt.py b/tests/unit/datatype/test_wkt.py index 5d9ffedd..87676ce1 100644 --- a/tests/unit/datatype/test_wkt.py +++ b/tests/unit/datatype/test_wkt.py @@ -651,7 +651,7 @@ def test_normalise_geometry_hole_outside_shell(): output_wkt = shapely.wkt.loads(input_wkt) assert not output_wkt.is_valid # Verify baseline invalidity - result= normalise_geometry( + result = normalise_geometry( output_wkt ) # unary_union([make_valid(part) for part in output_wkt.geoms]) From eb4dc9283b18c77141c9118eb6e2798d62e09e98 Mon Sep 17 00:00:00 2001 From: kcj-coding Date: Tue, 3 Nov 2026 16:58:58 +0000 Subject: [PATCH 13/18] updated unit tests --- tests/unit/datatype/test_wkt.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/datatype/test_wkt.py b/tests/unit/datatype/test_wkt.py index 87676ce1..aca889bb 100644 --- a/tests/unit/datatype/test_wkt.py +++ b/tests/unit/datatype/test_wkt.py @@ -660,7 +660,7 @@ def test_normalise_geometry_hole_outside_shell(): assert fixed_geom.is_valid # The large square (0,0 to 10,10) should have an area of 100, # plus 1 from the tiny square. Total area should be 101, NOT ~98. - assert pytest.approx(fixed_geom.area) == 101.0 + assert fixed_geom.area == pytest.approx(101.0) def test_normalise_geometry_overlapping_parts(): @@ -677,7 +677,7 @@ def test_normalise_geometry_overlapping_parts(): assert fixed_geom.is_valid # Two 2x2 squares overlapping by 1 unit - assert pytest.approx(fixed_geom.area) == 7.0 + assert fixed_geom.area == pytest.approx(7.0) def test_normalise_geometry_bowtie_unchanged(): From 63ad3696ccc4dc9704e2a9cd103a2fda97a4e620 Mon Sep 17 00:00:00 2001 From: kcj-coding Date: Tue, 3 Nov 2026 17:04:45 +0000 Subject: [PATCH 14/18] updated unit tests --- tests/unit/datatype/test_wkt.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/unit/datatype/test_wkt.py b/tests/unit/datatype/test_wkt.py index aca889bb..767b3af7 100644 --- a/tests/unit/datatype/test_wkt.py +++ b/tests/unit/datatype/test_wkt.py @@ -652,7 +652,7 @@ def test_normalise_geometry_hole_outside_shell(): assert not output_wkt.is_valid # Verify baseline invalidity result = normalise_geometry( - output_wkt + input_wkt ) # unary_union([make_valid(part) for part in output_wkt.geoms]) fixed_geom = result[0] if isinstance(result, tuple) else result @@ -670,7 +670,7 @@ def test_normalise_geometry_overlapping_parts(): output_wkt = shapely.wkt.loads(input_wkt) result = normalise_geometry( - output_wkt + input_wkt ) # unary_union([make_valid(part) for part in output_wkt.geoms]) fixed_geom = result[0] if isinstance(result, tuple) else result @@ -688,7 +688,7 @@ def test_normalise_geometry_bowtie_unchanged(): exp_geom = make_valid(output_wkt) if output_wkt.geom_type == "Multipolygon": result = normalise_geometry( - output_wkt + input_wkt ) # unary_union([make_valid(part) for part in output_wkt.geoms]) else: result = make_valid(output_wkt) @@ -705,7 +705,7 @@ def test_normalise_geometry_valid_unchanged(): ) output_wkt = shapely.wkt.loads(input_wkt) - result = normalise_geometry(output_wkt) # normalise_geometry function from wkt.py + result = normalise_geometry(input_wkt) # normalise_geometry function from wkt.py fixed_geom = result[0] if isinstance(result, tuple) else result From f972a3af5a27a13bac17717218303d67b2ce330f Mon Sep 17 00:00:00 2001 From: kcj-coding Date: Tue, 3 Nov 2026 17:08:55 +0000 Subject: [PATCH 15/18] updated unit tests --- tests/unit/datatype/test_wkt.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/unit/datatype/test_wkt.py b/tests/unit/datatype/test_wkt.py index 767b3af7..ec32e6af 100644 --- a/tests/unit/datatype/test_wkt.py +++ b/tests/unit/datatype/test_wkt.py @@ -667,7 +667,7 @@ def test_normalise_geometry_overlapping_parts(): input_wkt = ( "MULTIPOLYGON (((0 0, 2 0, 2 2, 0 2, 0 0)), ((1 0, 3 0, 3 2, 1 2, 1 0)))" ) - output_wkt = shapely.wkt.loads(input_wkt) + result = normalise_geometry( input_wkt @@ -703,7 +703,6 @@ def test_normalise_geometry_valid_unchanged(): input_wkt = ( "MULTIPOLYGON (((0 0, 2 0, 2 2, 0 2, 0 0)), ((4 4, 6 4, 6 6, 4 6, 4 4)))" ) - output_wkt = shapely.wkt.loads(input_wkt) result = normalise_geometry(input_wkt) # normalise_geometry function from wkt.py From 300bccb30a10c7d449a9a35d0904537e370d39ad Mon Sep 17 00:00:00 2001 From: kcj-coding Date: Tue, 3 Nov 2026 17:14:41 +0000 Subject: [PATCH 16/18] updated unit tests --- tests/unit/datatype/test_wkt.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/unit/datatype/test_wkt.py b/tests/unit/datatype/test_wkt.py index ec32e6af..f4d10369 100644 --- a/tests/unit/datatype/test_wkt.py +++ b/tests/unit/datatype/test_wkt.py @@ -667,7 +667,6 @@ def test_normalise_geometry_overlapping_parts(): input_wkt = ( "MULTIPOLYGON (((0 0, 2 0, 2 2, 0 2, 0 0)), ((1 0, 3 0, 3 2, 1 2, 1 0)))" ) - result = normalise_geometry( input_wkt @@ -704,6 +703,8 @@ def test_normalise_geometry_valid_unchanged(): "MULTIPOLYGON (((0 0, 2 0, 2 2, 0 2, 0 0)), ((4 4, 6 4, 6 6, 4 6, 4 4)))" ) + output_wkt = shapely.wkt.loads(input_wkt) + result = normalise_geometry(input_wkt) # normalise_geometry function from wkt.py fixed_geom = result[0] if isinstance(result, tuple) else result From 45d4545122fa220302c0842895e5eec015b5bd42 Mon Sep 17 00:00:00 2001 From: kcj-coding Date: Tue, 3 Nov 2026 17:32:23 +0000 Subject: [PATCH 17/18] updated unit tests --- tests/unit/datatype/test_wkt.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/unit/datatype/test_wkt.py b/tests/unit/datatype/test_wkt.py index f4d10369..c5a67a02 100644 --- a/tests/unit/datatype/test_wkt.py +++ b/tests/unit/datatype/test_wkt.py @@ -652,7 +652,7 @@ def test_normalise_geometry_hole_outside_shell(): assert not output_wkt.is_valid # Verify baseline invalidity result = normalise_geometry( - input_wkt + output_wkt ) # unary_union([make_valid(part) for part in output_wkt.geoms]) fixed_geom = result[0] if isinstance(result, tuple) else result @@ -668,15 +668,16 @@ def test_normalise_geometry_overlapping_parts(): "MULTIPOLYGON (((0 0, 2 0, 2 2, 0 2, 0 0)), ((1 0, 3 0, 3 2, 1 2, 1 0)))" ) + output_wkt = shapely.wkt.loads(input_wkt) + result = normalise_geometry( - input_wkt + output_wkt ) # unary_union([make_valid(part) for part in output_wkt.geoms]) fixed_geom = result[0] if isinstance(result, tuple) else result assert fixed_geom.is_valid - # Two 2x2 squares overlapping by 1 unit - assert fixed_geom.area == pytest.approx(7.0) + assert fixed_geom.area == pytest.approx(6.0) def test_normalise_geometry_bowtie_unchanged(): @@ -687,7 +688,7 @@ def test_normalise_geometry_bowtie_unchanged(): exp_geom = make_valid(output_wkt) if output_wkt.geom_type == "Multipolygon": result = normalise_geometry( - input_wkt + output_wkt ) # unary_union([make_valid(part) for part in output_wkt.geoms]) else: result = make_valid(output_wkt) From 3c2ba4b7c7729cbb5df8ac0f02795b67bdd93800 Mon Sep 17 00:00:00 2001 From: kcj-coding Date: Tue, 3 Nov 2026 18:12:16 +0000 Subject: [PATCH 18/18] updated unit tests --- tests/unit/datatype/test_wkt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/datatype/test_wkt.py b/tests/unit/datatype/test_wkt.py index c5a67a02..cae94d97 100644 --- a/tests/unit/datatype/test_wkt.py +++ b/tests/unit/datatype/test_wkt.py @@ -706,7 +706,7 @@ def test_normalise_geometry_valid_unchanged(): output_wkt = shapely.wkt.loads(input_wkt) - result = normalise_geometry(input_wkt) # normalise_geometry function from wkt.py + result = normalise_geometry(output_wkt) # normalise_geometry function from wkt.py fixed_geom = result[0] if isinstance(result, tuple) else result