2828SPARK_REMOTE = os .getenv ("SPARK_REMOTE" )
2929EXTRA_JARS = os .getenv ("SEDONA_PYTHON_EXTRA_JARS" )
3030
31+ import shapely
3132from shapely import wkt
3233from shapely .geometry .base import BaseGeometry
3334
35+ SHAPELY_GE_210 = shapely .__version__ >= "2.1.0"
36+
3437
3538class TestBase :
3639
@@ -122,14 +125,31 @@ def assert_geometry_almost_equal(
122125 right_geom : Union [str , BaseGeometry ],
123126 tolerance = 1e-6 ,
124127 ):
128+ """
129+ Assert that two geometries are almost equal.
130+
131+ Note: this function will only check Z and M dimensions for shapely >= 2.1.0 (python >= 3.10)
132+
133+ When comparing geometries with Z or M dimensions, this function will ignore `tolerance` and check for exact equality.
134+ """
125135 expected_geom = (
126136 wkt .loads (left_geom ) if isinstance (left_geom , str ) else left_geom
127137 )
128138 actual_geom = (
129139 wkt .loads (right_geom ) if isinstance (right_geom , str ) else right_geom
130140 )
131141
132- if not actual_geom .equals_exact (expected_geom , tolerance = tolerance ):
142+ # Note: only shapely >= 2.1.0 supports Z and M dimensions
143+ # If has Z or M dimension, use equals_identical to check the equality
144+ if SHAPELY_GE_210 and (has_zm (actual_geom ) or has_zm (expected_geom )):
145+ if not shapely .equals_identical (actual_geom , expected_geom ):
146+ raise ValueError (
147+ f"Geometry equality check failed for { left_geom } and { right_geom } "
148+ )
149+
150+ # Comparison for XY geometries
151+ # Note: equals_exact doesn't check for Z or M dimensions
152+ elif not actual_geom .equals_exact (expected_geom , tolerance = tolerance ):
133153 # If the exact equals check fails, perform a buffer check with tolerance
134154 if (
135155 actual_geom .is_valid
@@ -143,3 +163,66 @@ def assert_geometry_almost_equal(
143163 raise ValueError (
144164 f"Geometry equality check failed for { left_geom } and { right_geom } "
145165 )
166+
167+
168+ def has_zm (geom : BaseGeometry ):
169+ return geom .has_z or geom .has_m
170+
171+
172+ def test_assert_geometry_almost_equal ():
173+ import pytest
174+
175+ TestBase .assert_geometry_almost_equal ("POINT (1 1)" , "POINT (1 1)" )
176+ TestBase .assert_geometry_almost_equal ("POINT (1 1)" , "POINT (1.000001 1)" )
177+ TestBase .assert_geometry_almost_equal ("POINT (1 1)" , "POINT (1.000001 1)" )
178+
179+ with pytest .raises (ValueError ):
180+ TestBase .assert_geometry_almost_equal ("POINT (1 1)" , "POINT (2 2)" )
181+
182+ with pytest .raises (ValueError ):
183+ TestBase .assert_geometry_almost_equal ("POINT (1 1)" , "POINT (2 2)" )
184+
185+ # Check Z and M dimension compatibility (requires shapely >= 2.1.0)
186+ if SHAPELY_GE_210 :
187+ # 2D vs 3D should fail
188+ with pytest .raises (ValueError ):
189+ TestBase .assert_geometry_almost_equal ("POINT (1 1)" , "POINT (1 1 0)" )
190+
191+ with pytest .raises (ValueError ):
192+ TestBase .assert_geometry_almost_equal ("POINT (1 1 0)" , "POINT (1 1)" )
193+
194+ # Different 3D should fail
195+ with pytest .raises (ValueError ):
196+ TestBase .assert_geometry_almost_equal ("POINT (1 1 1)" , "POINT (1 1 2)" )
197+
198+ with pytest .raises (ValueError ):
199+ TestBase .assert_geometry_almost_equal ("POINT (1 1 2)" , "POINT (1 1 1)" )
200+
201+ # Z vs M dimension should fail
202+ with pytest .raises (ValueError ):
203+ TestBase .assert_geometry_almost_equal ("POINT Z (1 1 1)" , "POINT M (1 1 1)" )
204+
205+ with pytest .raises (ValueError ):
206+ TestBase .assert_geometry_almost_equal ("POINT M (1 1 1)" , "POINT Z (1 1 1)" )
207+
208+ # 3D vs 4D should fail
209+ with pytest .raises (ValueError ):
210+ TestBase .assert_geometry_almost_equal (
211+ "POINT Z (1 1 1)" , "POINT ZM (1 1 1 1)"
212+ )
213+
214+ with pytest .raises (ValueError ):
215+ TestBase .assert_geometry_almost_equal (
216+ "POINT ZM (1 1 1 1)" , "POINT Z (1 1 1)"
217+ )
218+
219+ # Different 4D should fail
220+ with pytest .raises (ValueError ):
221+ TestBase .assert_geometry_almost_equal (
222+ "POINT ZM (1 1 1 1)" , "POINT ZM (1 1 1 2)"
223+ )
224+
225+ with pytest .raises (ValueError ):
226+ TestBase .assert_geometry_almost_equal (
227+ "POINT ZM (1 1 1 2)" , "POINT ZM (1 1 1 1)"
228+ )
0 commit comments