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 7fe698362e [SEDONA-679] Fix ST_LengthSpheroid behavior (#1691)
7fe698362e is described below

commit 7fe698362ed552b82a2cf834d91b418399672fa4
Author: Furqaan Khan <[email protected]>
AuthorDate: Sat Nov 23 00:59:09 2024 -0500

    [SEDONA-679] Fix ST_LengthSpheroid behavior (#1691)
    
    * feat: remove support for polygonal geometry in ST_LengthSpheroid
    
    * lint fix
---
 .../java/org/apache/sedona/common/Functions.java   |  2 +-
 .../org/apache/sedona/common/sphere/Spheroid.java  | 37 +++++++++++++++++++---
 .../org/apache/sedona/common/FunctionsTest.java    | 33 +++++++++++++++++--
 docs/api/flink/Function.md                         |  7 ++--
 docs/api/snowflake/vector-data/Function.md         | 11 +++++--
 docs/api/sql/Function.md                           |  7 ++--
 .../java/org/apache/sedona/flink/FunctionTest.java |  4 +--
 .../sedona/snowflake/snowsql/TestFunctions.java    |  4 +--
 .../sedona/snowflake/snowsql/TestFunctionsV2.java  |  3 +-
 .../org/apache/sedona/sql/functionTestScala.scala  |  2 +-
 10 files changed, 88 insertions(+), 22 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 8502c241bd..5a35d10d98 100644
--- a/common/src/main/java/org/apache/sedona/common/Functions.java
+++ b/common/src/main/java/org/apache/sedona/common/Functions.java
@@ -1120,7 +1120,7 @@ public class Functions {
 
   private static double calculateLength(Geometry geometry, boolean 
use_spheroid) {
     if (use_spheroid) {
-      return Spheroid.length(geometry);
+      return Spheroid.baseLength(geometry);
     } else {
       return length(geometry);
     }
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 50a3beb77b..546fec4f84 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
@@ -72,13 +72,40 @@ public class Spheroid {
   }
 
   /**
-   * Calculate the length of a geometry using the Spheroid formula. Equivalent 
to PostGIS
+   * Calculates length just for linear geometries or geometry collection 
containing linear
+   * geometries.
+   *
+   * @param geometry
+   * @return
+   */
+  public static double length(Geometry geometry) {
+    String geomType = geometry.getGeometryType();
+    if (geomType.equalsIgnoreCase(Geometry.TYPENAME_LINESTRING)
+        || geomType.equalsIgnoreCase(Geometry.TYPENAME_POINT)
+        || geomType.equalsIgnoreCase(Geometry.TYPENAME_MULTIPOINT)
+        || geomType.equalsIgnoreCase(Geometry.TYPENAME_MULTILINESTRING)) {
+      return baseLength(geometry);
+    } else if 
(geomType.equalsIgnoreCase(Geometry.TYPENAME_GEOMETRYCOLLECTION)) {
+      double length = 0;
+      for (int i = 0; i < geometry.getNumGeometries(); i++) {
+        length += length(geometry.getGeometryN(i));
+      }
+      return length;
+    } else {
+      return 0;
+    }
+  }
+
+  /**
+   * Base function to calculate the spheroid length/perimeter
+   *
+   * <p>Calculate the length of a geometry using the Spheroid formula. 
Equivalent to PostGIS
    * ST_LengthSpheroid and PostGIS ST_Length(useSpheroid=true) WGS84 ellipsoid 
is used.
    *
    * @param geom
    * @return
    */
-  public static double length(Geometry geom) {
+  public static double baseLength(Geometry geom) {
     String geomType = geom.getGeometryType();
     if (geomType.equals(Geometry.TYPENAME_LINEARRING)
         || geomType.equals(Geometry.TYPENAME_LINESTRING)) {
@@ -93,11 +120,11 @@ public class Spheroid {
       return compute.perimeter;
     } else if (geomType.equals(Geometry.TYPENAME_POLYGON)) {
       Polygon poly = (Polygon) geom;
-      double length = length(poly.getExteriorRing());
+      double length = baseLength(poly.getExteriorRing());
 
       if (poly.getNumInteriorRing() > 0) {
         for (int i = 0; i < poly.getNumInteriorRing(); i++) {
-          length += length(poly.getInteriorRingN(i));
+          length += baseLength(poly.getInteriorRingN(i));
         }
       }
 
@@ -107,7 +134,7 @@ public class Spheroid {
         || geomType.equals(Geometry.TYPENAME_GEOMETRYCOLLECTION)) {
       double length = 0.0;
       for (int i = 0; i < geom.getNumGeometries(); i++) {
-        length += length(geom.getGeometryN(i));
+        length += baseLength(geom.getGeometryN(i));
       }
       return length;
     } else {
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 72b850b900..208b9268d7 100644
--- a/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
+++ b/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
@@ -1695,7 +1695,7 @@ public class FunctionsTest extends TestBase {
     assertEquals(1.0018754171394622E7, Spheroid.length(line), FP_TOLERANCE2);
 
     Polygon polygon = GEOMETRY_FACTORY.createPolygon(coordArray(0, 0, 90, 0, 
0, 0));
-    assertEquals(2.0037508342789244E7, Spheroid.length(polygon), 
FP_TOLERANCE2);
+    assertEquals(0.0, Spheroid.length(polygon), FP_TOLERANCE2);
 
     MultiPoint multiPoint = GEOMETRY_FACTORY.createMultiPoint(new Point[] 
{point, point});
     assertEquals(0, Spheroid.length(multiPoint), FP_TOLERANCE2);
@@ -1706,17 +1706,44 @@ public class FunctionsTest extends TestBase {
 
     MultiPolygon multiPolygon =
         GEOMETRY_FACTORY.createMultiPolygon(new Polygon[] {polygon, polygon});
-    assertEquals(4.007501668557849E7, Spheroid.length(multiPolygon), 
FP_TOLERANCE2);
+    assertEquals(0.0, Spheroid.length(multiPolygon), FP_TOLERANCE2);
 
     GeometryCollection geometryCollection =
         GEOMETRY_FACTORY.createGeometryCollection(new Geometry[] {point, line, 
multiLineString});
     assertEquals(3.0056262514183864E7, Spheroid.length(geometryCollection), 
FP_TOLERANCE2);
+  }
+
+  @Test
+  public void spheroidBaseLength() throws ParseException {
+    Point point = GEOMETRY_FACTORY.createPoint(new Coordinate(90, 0));
+    assertEquals(0, Spheroid.baseLength(point), FP_TOLERANCE2);
+
+    LineString line = GEOMETRY_FACTORY.createLineString(coordArray(0, 0, 90, 
0));
+    assertEquals(1.0018754171394622E7, Spheroid.baseLength(line), 
FP_TOLERANCE2);
+
+    Polygon polygon = GEOMETRY_FACTORY.createPolygon(coordArray(0, 0, 90, 0, 
0, 0));
+    assertEquals(2.0037508342789244E7, Spheroid.baseLength(polygon), 
FP_TOLERANCE2);
+
+    MultiPoint multiPoint = GEOMETRY_FACTORY.createMultiPoint(new Point[] 
{point, point});
+    assertEquals(0, Spheroid.baseLength(multiPoint), FP_TOLERANCE2);
+
+    MultiLineString multiLineString =
+        GEOMETRY_FACTORY.createMultiLineString(new LineString[] {line, line});
+    assertEquals(2.0037508342789244E7, Spheroid.baseLength(multiLineString), 
FP_TOLERANCE2);
+
+    MultiPolygon multiPolygon =
+        GEOMETRY_FACTORY.createMultiPolygon(new Polygon[] {polygon, polygon});
+    assertEquals(4.007501668557849E7, Spheroid.baseLength(multiPolygon), 
FP_TOLERANCE2);
+
+    GeometryCollection geometryCollection =
+        GEOMETRY_FACTORY.createGeometryCollection(new Geometry[] {point, line, 
multiLineString});
+    assertEquals(3.0056262514183864E7, 
Spheroid.baseLength(geometryCollection), FP_TOLERANCE2);
 
     Geometry polygonWithHole =
         Constructors.geomFromWKT(
             "POLYGON((-122.33 47.61, -122.32 47.62, -122.31 47.61, -122.30 
47.62, -122.29 47.61, -122.30 47.60, -122.31 47.59, -122.32 47.60, -122.33 
47.61), (-122.315 47.605, -122.305 47.615, -122.295 47.605, -122.305 47.595, 
-122.315 47.605))",
             4326);
-    assertEquals(16106.506409488933, Spheroid.length(polygonWithHole), 
FP_TOLERANCE2);
+    assertEquals(16106.506409488933, Spheroid.baseLength(polygonWithHole), 
FP_TOLERANCE2);
   }
 
   @Test
diff --git a/docs/api/flink/Function.md b/docs/api/flink/Function.md
index 8bcaa9e41d..62cb86685f 100644
--- a/docs/api/flink/Function.md
+++ b/docs/api/flink/Function.md
@@ -2389,6 +2389,9 @@ Geometry must be in EPSG:4326 (WGS84) projection and must 
be in ==lon/lat== orde
 !!!note
     By default, this function uses lon/lat order since `v1.5.0`. Before, it 
used lat/lon order.
 
+!!!Warning
+    Since `v1.7.0`, this function only supports LineString, MultiLineString, 
and GeometryCollections containing linear geometries. Use 
[ST_Perimeter](#st_perimeter) for polygons.
+
 Format: `ST_LengthSpheroid (A: Geometry)`
 
 Since: `v1.4.1`
@@ -2396,13 +2399,13 @@ Since: `v1.4.1`
 Example:
 
 ```sql
-SELECT ST_LengthSpheroid(ST_GeomFromWKT('Polygon ((0 0, 90 0, 0 0))'))
+SELECT ST_LengthSpheroid(ST_GeomFromWKT('LINESTRING (0 0, 2 0)'))
 ```
 
 Output:
 
 ```
-20037508.342789244
+222638.98158654713
 ```
 
 ## ST_LineFromMultiPoint
diff --git a/docs/api/snowflake/vector-data/Function.md 
b/docs/api/snowflake/vector-data/Function.md
index 7d0e6e408d..ef7f4f778a 100644
--- a/docs/api/snowflake/vector-data/Function.md
+++ b/docs/api/snowflake/vector-data/Function.md
@@ -1734,15 +1734,22 @@ Introduction: Return the geodesic perimeter of A using 
WGS84 spheroid. Unit is m
 
 Geometry must be in EPSG:4326 (WGS84) projection and must be in ==lat/lon== 
order. You can use ==ST_FlipCoordinates== to swap lat and lon.
 
+!!!Warning
+    This function only supports LineString, MultiLineString, and 
GeometryCollections containing linear geometries. Use 
[ST_Perimeter](#st_perimeter) for polygons.
+
 Format: `ST_LengthSpheroid (A:geometry)`
 
 SQL example:
 
 ```sql
-SELECT ST_LengthSpheroid(ST_GeomFromWKT('Polygon ((0 0, 0 90, 0 0))'))
+SELECT ST_LengthSpheroid(ST_GeomFromWKT('LINESTRING (0 0, 2 0)'))
 ```
 
-Output: `20037508.342789244`
+Output:
+
+```
+222638.98158654713
+```
 
 ## ST_LineFromMultiPoint
 
diff --git a/docs/api/sql/Function.md b/docs/api/sql/Function.md
index ac63ca7cf9..a42dc9e466 100644
--- a/docs/api/sql/Function.md
+++ b/docs/api/sql/Function.md
@@ -2434,6 +2434,9 @@ Geometry must be in EPSG:4326 (WGS84) projection and must 
be in ==lon/lat== orde
 !!!note
     By default, this function uses lon/lat order since `v1.5.0`. Before, it 
used lat/lon order.
 
+!!!Warning
+    Since `v1.7.0`, this function only supports LineString, MultiLineString, 
and GeometryCollections containing linear geometries. Use 
[ST_Perimeter](#st_perimeter) for polygons.
+
 Format: `ST_LengthSpheroid (A: Geometry)`
 
 Since: `v1.4.1`
@@ -2441,13 +2444,13 @@ Since: `v1.4.1`
 SQL Example
 
 ```sql
-SELECT ST_LengthSpheroid(ST_GeomFromWKT('Polygon ((0 0, 90 0, 0 0))'))
+SELECT ST_LengthSpheroid(ST_GeomFromWKT('LINESTRING (0 0, 2 0)'))
 ```
 
 Output:
 
 ```
-20037508.342789244
+222638.98158654713
 ```
 
 ## ST_LineFromMultiPoint
diff --git a/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java 
b/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
index cbb9fec605..6ee9160c4a 100644
--- a/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
+++ b/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
@@ -654,8 +654,8 @@ public class FunctionTest extends TestBase {
   @Test
   public void testLengthSpheroid() {
     Table tbl =
-        tableEnv.sqlQuery("SELECT ST_LengthSpheroid(ST_GeomFromWKT('Polygon 
((0 0, 90 0, 0 0))'))");
-    Double expected = 20037508.342789244;
+        tableEnv.sqlQuery("SELECT ST_LengthSpheroid(ST_GeomFromWKT('LINESTRING 
(0 0, 2 0)'))");
+    Double expected = 222638.98158654713;
     Double actual = (Double) first(tbl).getField(0);
     assertEquals(expected, actual, 0.1);
   }
diff --git 
a/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctions.java
 
b/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctions.java
index c3fdd3160a..ed319f92bc 100644
--- 
a/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctions.java
+++ 
b/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctions.java
@@ -1190,8 +1190,8 @@ public class TestFunctions extends TestBase {
   public void test_ST_LengthSpheroid() {
     registerUDF("ST_LengthSpheroid", byte[].class);
     verifySqlSingleRes(
-        "select sedona.ST_LengthSpheroid(sedona.ST_GeomFromWKT('Polygon ((0 0, 
90 0, 0 0))'))",
-        20037508.342789244);
+        "select 
CEIL(sedona.ST_LengthSpheroid(sedona.ST_GeomFromWKT('LINESTRING (0 0, 2 0)')))",
+        222639.0);
   }
 
   @Test
diff --git 
a/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctionsV2.java
 
b/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctionsV2.java
index e1b9ccc7de..cfcdddcd20 100644
--- 
a/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctionsV2.java
+++ 
b/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctionsV2.java
@@ -1142,8 +1142,7 @@ public class TestFunctionsV2 extends TestBase {
   public void test_ST_LengthSpheroid() {
     registerUDFV2("ST_LengthSpheroid", String.class);
     verifySqlSingleRes(
-        "select sedona.ST_LengthSpheroid(ST_GeomFromWKT('Polygon ((0 0, 90 0, 
90 90, 0 90, 0 0))'))",
-        30022685.630020067);
+        "select CEIL(sedona.ST_LengthSpheroid(ST_GeomFromWKT('LINESTRING (0 0, 
2 0)')))", 222639.0);
   }
 
   @Test
diff --git 
a/spark/common/src/test/scala/org/apache/sedona/sql/functionTestScala.scala 
b/spark/common/src/test/scala/org/apache/sedona/sql/functionTestScala.scala
index 9bda2da441..82dbff82c1 100644
--- a/spark/common/src/test/scala/org/apache/sedona/sql/functionTestScala.scala
+++ b/spark/common/src/test/scala/org/apache/sedona/sql/functionTestScala.scala
@@ -2891,7 +2891,7 @@ class functionTestScala
     val geomTestCases = Map(
       ("'POINT (-0.56 51.3168)'") -> "0.0",
       ("'LineString (0 0, 90 0)'") -> "10018754.17139462",
-      ("'Polygon ((0 0, 90 0, 0 0))'") -> "20037508.34278924")
+      ("'Polygon ((0 0, 90 0, 0 0))'") -> "0.0")
     for (((geom1), expectedResult) <- geomTestCases) {
       val df = sparkSession.sql(
         s"SELECT ST_LengthSpheroid(ST_GeomFromWKT($geom1)), " +

Reply via email to