You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sedona.apache.org by ji...@apache.org on 2026/05/06 04:36:06 UTC

(sedona) branch master updated: [GH-2901]: Fix ST_BestSRID logic for Geometries near the poles (#2902)

This is an automated email from the ASF dual-hosted git repository.

jiayuasu 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 d451b6b1fc [GH-2901]: Fix ST_BestSRID logic for Geometries near the poles (#2902)
d451b6b1fc is described below

commit d451b6b1fc893c4cb40bf753b2d2ad3d89245ccc
Author: Thomas Dekeyser <th...@gmail.com>
AuthorDate: Wed May 6 06:36:00 2026 +0200

    [GH-2901]: Fix ST_BestSRID logic for Geometries near the poles (#2902)
    
    Co-authored-by: Thomas Dekeyser <th...@noreply.com>
---
 .../org/apache/sedona/common/sphere/Spheroid.java  |  6 +--
 .../org/apache/sedona/common/FunctionsTest.java    | 16 +++++-
 .../apache/sedona/common/sphere/SpheroidTest.java  | 57 ++++++++++++++++++++++
 python/tests/sql/test_dataframe_api.py             |  2 +-
 python/tests/sql/test_function.py                  |  2 +-
 5 files changed, 75 insertions(+), 8 deletions(-)

diff --git a/common/src/main/java/org/apache/sedona/common/sphere/Spheroid.java b/common/src/main/java/org/apache/sedona/common/sphere/Spheroid.java
index 758670c06f..557921da28 100644
--- a/common/src/main/java/org/apache/sedona/common/sphere/Spheroid.java
+++ b/common/src/main/java/org/apache/sedona/common/sphere/Spheroid.java
@@ -196,8 +196,7 @@ public class Spheroid {
     double distance = g.s12; // Distance in meters
 
     // Convert distance to angular width in degrees
-    Double angularWidth =
-        Math.toDegrees(distance / (Geodesic.WGS84.EquatorialRadius() * Math.PI / 180));
+    Double angularWidth = distance / (Geodesic.WGS84.EquatorialRadius() * Math.PI / 180);
 
     return angularWidth;
   }
@@ -213,8 +212,7 @@ public class Spheroid {
     double distance = g.s12; // Distance in meters
 
     // Convert distance to angular height in degrees
-    Double angularHeight =
-        Math.toDegrees(distance / (Geodesic.WGS84.EquatorialRadius() * Math.PI / 180));
+    Double angularHeight = distance / (Geodesic.WGS84.EquatorialRadius() * Math.PI / 180);
 
     return angularHeight;
   }
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 be21a0d9ff..1f869ec29a 100644
--- a/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
+++ b/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
@@ -3401,10 +3401,10 @@ public class FunctionsTest extends TestBase {
             "POLYGON ((-179.908607846266 24.025403116254306, -177.99876698499668 23.825660822056278, -176.1851748144233 23.267372220454533, -174.54862792786022 22.380090414241554, -173.15522797402008 21.20765453023379, -172.05367901642606 19.803908497939666, -171.27542809803106 18.22850022788734, -170.83670228698406 16.543486102335997, -170.7412636921777 14.811036901560918, -170.9829095910743 13.092142713348924, -171.5471495735382 11.445952123266512, -172.41190582467604 9.929276420592164 [...]
     Geometry expected8 =
         geomFromEWKT(
-            "POLYGON ((179 -15.000873160293315, 178.999824747382 -15.000856382797105, 178.99965622962375 -15.000806695050459, 178.9995009227683 -15.000726006503347, 178.999364795171 -15.000617417938033, 178.99925307813902 -15.000485102312915, 178.9991700648953 -15.000334144403906, 178.99911894559222 -15.00017034540551, 178.9991016847159 -14.999999999999092, 178.9991016847159 14.99999999999908, 178.99911894559222 15.00017034540551, 178.9991700648953 15.000334144403906, 178.99925307813902  [...]
+            "POLYGON ((178.9999957907089 -15.000903596473622, 178.99981605472888 -15.000885740363822, 178.9996432665321 -15.000834429161598, 178.99948395250945 -15.000751600936063, 178.99934413010374 -15.000640384187193, 178.999229080519 -15.000504979676391, 178.99914314924223 -15.00035050175554, 178.99908958191227 -15.000182785188626, 178.99907040173593 -15.000008164763253, 178.99907040173593 15.000008164763253, 178.99908958191227 15.000182785188626, 178.99914314924223 15.00035050175554 [...]
     Geometry expected9 =
         geomFromEWKT(
-            "POLYGON ((178 -18.747248844374, 176.24747381949112 -18.582729101204464, 174.5622962372712 -18.0945531116537, 173.0092276827665 -17.29887379200776, 171.64795170955566 -16.222572896097414, 170.53078138987692 -14.903037762363958, 169.70064895259912 -13.387566659631126, 169.18945592174327 -11.73221950803158, 169.01684715880478 -9.999999999999265, 169.01684715880478 9.999999999999238, 169.18945592174327 11.73221950803157, 169.70064895259912 13.387566659631101, 170.53078138987692  [...]
+            "POLYGON ((177.9549995416554 -19.040094935317835, 176.11434781653608 -18.85284309323023, 174.35693335915332 -18.312833546632955, 172.75892069701706 -17.445729285603573, 171.38477758716215 -16.29151182562638, 170.28436137749944 -14.900872725390832, 169.49233786416985 -13.331457888391856, 169.02929359537578 -11.64464082255408, 168.9036172802648 -9.903154239380708, 168.9036172802648 9.903154239380708, 169.02929359537578 11.644640822554088, 169.49233786416985 13.331457888391858,  [...]
 
     Geometry postgis_result1 =
         geomFromEWKT(
@@ -3577,6 +3577,18 @@ public class FunctionsTest extends TestBase {
         "Expected World Mercator projection for wide range geometry", expectedEPSG, actualEPSG);
   }
 
+  @Test
+  public void testBestSRIDNearSouthPole() throws ParseException {
+    int actualEPSG =
+        Functions.bestSRID(
+            geomFromWKT("LINESTRING (-179.9999994 -82.42408, -157.330902 -85.0511284)", 4326));
+
+    assertEquals(
+        "Expected South Pole Lambert Azimuthal Equal Area projection near the south pole",
+        Spheroid.EPSG_SOUTH_LAMBERT,
+        actualEPSG);
+  }
+
   @Test
   public void nRingsUnsupported() {
     LineString lineString =
diff --git a/common/src/test/java/org/apache/sedona/common/sphere/SpheroidTest.java b/common/src/test/java/org/apache/sedona/common/sphere/SpheroidTest.java
new file mode 100644
index 0000000000..9d390561b5
--- /dev/null
+++ b/common/src/test/java/org/apache/sedona/common/sphere/SpheroidTest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sedona.common.sphere;
+
+import static org.apache.sedona.common.Constructors.geomFromWKT;
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.locationtech.jts.geom.Envelope;
+import org.locationtech.jts.io.ParseException;
+
+public class SpheroidTest {
+
+  @Test
+  public void testAngularHeight() throws ParseException {
+    Double actual =
+        Spheroid.angularHeight(geomFromWKT("LINESTRING (0 90, 0 -90)", 4326).getEnvelopeInternal());
+
+    assertEquals(180.0, actual, 0.5);
+  }
+
+  @Test
+  public void testAngularWidth() throws ParseException {
+    Double actual =
+        Spheroid.angularWidth(geomFromWKT("LINESTRING (-90 0, 90 0)", 4326).getEnvelopeInternal());
+
+    assertEquals(180.0, actual, 0.5);
+  }
+
+  @Test
+  public void testAngularWidthAndHeightNearPolesAndAntiMeridian() throws ParseException {
+    Envelope env =
+        geomFromWKT("LINESTRING (-179.9999994 -82.42408, -157.330902 -85.0511284)", 4326)
+            .getEnvelopeInternal();
+    Double actualAngularHeight = Spheroid.angularHeight(env);
+    Double actualAngularWidth = Spheroid.angularWidth(env);
+
+    assertEquals(2.63, actualAngularHeight, 0.01);
+    assertEquals(2.46, actualAngularWidth, 0.01);
+  }
+}
diff --git a/python/tests/sql/test_dataframe_api.py b/python/tests/sql/test_dataframe_api.py
index 9156b1d48f..72c28eede5 100644
--- a/python/tests/sql/test_dataframe_api.py
+++ b/python/tests/sql/test_dataframe_api.py
@@ -383,7 +383,7 @@ test_configurations = [
     ),
     (stf.ST_AsText, ("point",), "point_geom", "", "POINT (0 1)"),
     (stf.ST_Azimuth, ("a", "b"), "two_points", "geom * 180.0 / pi()", 90.0),
-    (stf.ST_BestSRID, ("geom",), "triangle_geom", "", 3395),
+    (stf.ST_BestSRID, ("geom",), "triangle_geom", "", 32631),
     (
         stf.ST_Boundary,
         ("geom",),
diff --git a/python/tests/sql/test_function.py b/python/tests/sql/test_function.py
index ad7cabe739..75db8398c3 100644
--- a/python/tests/sql/test_function.py
+++ b/python/tests/sql/test_function.py
@@ -164,7 +164,7 @@ class TestPredicateJoin(TestBase):
         )
         function_df.show()
         actual = function_df.take(1)[0][0]
-        assert actual == 3395
+        assert actual == 32614
 
     def test_st_shiftlongitude(self):
         function_df = self.spark.sql(