This is an automated email from the ASF dual-hosted git repository.
jiayu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sedona.git
The following commit(s) were added to refs/heads/master by this push:
new be4884a242 [GH-2406] Make ST_Distance return null instead of 0.0 when
arg is empty geom (#2447)
be4884a242 is described below
commit be4884a242ce6957f26ae0f0aea53de662217f63
Author: Peter Nguyen <[email protected]>
AuthorDate: Sat Oct 25 02:32:57 2025 -0700
[GH-2406] Make ST_Distance return null instead of 0.0 when arg is empty
geom (#2447)
---
.../src/main/java/org/apache/sedona/common/Functions.java | 5 ++++-
.../test/java/org/apache/sedona/common/FunctionsTest.java | 13 +++++++++++++
python/tests/geopandas/test_match_geopandas_series.py | 5 -----
.../test/scala/org/apache/sedona/sql/SpatialJoinSuite.scala | 12 ++++++++++++
4 files changed, 29 insertions(+), 6 deletions(-)
diff --git a/common/src/main/java/org/apache/sedona/common/Functions.java
b/common/src/main/java/org/apache/sedona/common/Functions.java
index eb67674510..a9d59b28ff 100644
--- a/common/src/main/java/org/apache/sedona/common/Functions.java
+++ b/common/src/main/java/org/apache/sedona/common/Functions.java
@@ -575,7 +575,10 @@ public class Functions {
return geometry.getEnvelope();
}
- public static double distance(Geometry left, Geometry right) {
+ public static Double distance(Geometry left, Geometry right) {
+ if (left.isEmpty() || right.isEmpty()) {
+ return null;
+ }
return left.distance(right);
}
diff --git a/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
b/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
index cdf1e5d97b..15bff34e23 100644
--- a/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
+++ b/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
@@ -1472,6 +1472,19 @@ public class FunctionsTest extends TestBase {
assertEquals(123, actual2.getSRID());
}
+ @Test
+ public void distance_empty_geometries() throws ParseException {
+ Point point = GEOMETRY_FACTORY.createPoint(new Coordinate(90, 0));
+ LineString lineString = GEOMETRY_FACTORY.createLineString(coordArray(0, 0,
0, 90));
+
+ // Ensure operations involving empty geometries return null
+ Geometry emptyGeom1 = GEOMETRY_FACTORY.createPoint();
+ Geometry emptyGeom2 = GEOMETRY_FACTORY.createGeometryCollection();
+ assertNull(Functions.distance(emptyGeom1, emptyGeom2));
+ assertNull(Functions.distance(point, emptyGeom1));
+ assertNull(Functions.distance(emptyGeom1, lineString));
+ }
+
@Test
public void haversineDistance() {
// Basic check
diff --git a/python/tests/geopandas/test_match_geopandas_series.py
b/python/tests/geopandas/test_match_geopandas_series.py
index e1be0cf237..e0f713c167 100644
--- a/python/tests/geopandas/test_match_geopandas_series.py
+++ b/python/tests/geopandas/test_match_geopandas_series.py
@@ -1044,11 +1044,6 @@ class TestMatchGeopandasSeries(TestGeopandasBase):
def test_distance(self):
for geom, geom2 in self.pairs:
- if geom[0].is_empty or geom2[0].is_empty:
- # Sedona's ST_Distance returns 0.0 instead of null
- # when an empty geometry is involved
- # https://github.com/apache/sedona/issues/2406
- continue
sgpd_result = GeoSeries(geom).distance(GeoSeries(geom2),
align=True)
gpd_result = gpd.GeoSeries(geom).distance(gpd.GeoSeries(geom2),
align=True)
self.check_pd_series_equal(sgpd_result, gpd_result)
diff --git
a/spark/common/src/test/scala/org/apache/sedona/sql/SpatialJoinSuite.scala
b/spark/common/src/test/scala/org/apache/sedona/sql/SpatialJoinSuite.scala
index 543cf5e911..9f4fd30f95 100644
--- a/spark/common/src/test/scala/org/apache/sedona/sql/SpatialJoinSuite.scala
+++ b/spark/common/src/test/scala/org/apache/sedona/sql/SpatialJoinSuite.scala
@@ -268,6 +268,18 @@ class SpatialJoinSuite extends TestBaseScala with
TableDrivenPropertyChecks {
assert(resultRows.isEmpty)
}
}
+
+ it("ST_Distance involving empty geometries should work as a predicate") {
+ // ST_Distance returns null when either arg is an empty geometry,
+ // while this test doesn't involve an actual spatial join, it tests that
+ // a distance-based spatial join doesn't fail due to this edge case.
+ val result1 = sparkSession.sql(
+ "SELECT * FROM df1 WHERE ST_Distance(df1.geom, ST_GeomFromText('POINT
EMPTY')) < 1")
+ assert(result1.count() == 0)
+ val result2 = sparkSession.sql(
+ "SELECT * FROM df2 WHERE ST_Distance(df2.geom, ST_GeomFromText('POINT
EMPTY')) < 1")
+ assert(result2.count() == 0)
+ }
}
private def withOptimizationMode(mode: String)(body: => Unit): Unit = {