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 f8bc4d3220 [SEDONA-672] Bug fix for ST_LengthSpheroid (#1679)
f8bc4d3220 is described below

commit f8bc4d3220418a1b70396f41c793b408a04a0903
Author: Furqaan Khan <[email protected]>
AuthorDate: Thu Nov 7 21:26:02 2024 -0500

    [SEDONA-672] Bug fix for ST_LengthSpheroid (#1679)
---
 .../org/apache/sedona/common/sphere/Spheroid.java  | 21 +++++++++++++++++----
 .../org/apache/sedona/common/FunctionsTest.java    | 22 ++++++++++++++--------
 2 files changed, 31 insertions(+), 12 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 986d66a4c5..50a3beb77b 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
@@ -27,6 +27,7 @@ import net.sf.geographiclib.PolygonResult;
 import org.locationtech.jts.geom.Coordinate;
 import org.locationtech.jts.geom.Envelope;
 import org.locationtech.jts.geom.Geometry;
+import org.locationtech.jts.geom.Polygon;
 
 public class Spheroid {
   // Standard EPSG Codes
@@ -79,7 +80,8 @@ public class Spheroid {
    */
   public static double length(Geometry geom) {
     String geomType = geom.getGeometryType();
-    if (geomType.equals("Polygon") || geomType.equals("LineString")) {
+    if (geomType.equals(Geometry.TYPENAME_LINEARRING)
+        || geomType.equals(Geometry.TYPENAME_LINESTRING)) {
       PolygonArea p = new PolygonArea(Geodesic.WGS84, true);
       Coordinate[] coordinates = geom.getCoordinates();
       for (int i = 0; i < coordinates.length; i++) {
@@ -89,9 +91,20 @@ public class Spheroid {
       }
       PolygonResult compute = p.Compute();
       return compute.perimeter;
-    } else if (geomType.equals("MultiPolygon")
-        || geomType.equals("MultiLineString")
-        || geomType.equals("GeometryCollection")) {
+    } else if (geomType.equals(Geometry.TYPENAME_POLYGON)) {
+      Polygon poly = (Polygon) geom;
+      double length = length(poly.getExteriorRing());
+
+      if (poly.getNumInteriorRing() > 0) {
+        for (int i = 0; i < poly.getNumInteriorRing(); i++) {
+          length += length(poly.getInteriorRingN(i));
+        }
+      }
+
+      return length;
+    } else if (geomType.equals(Geometry.TYPENAME_MULTIPOLYGON)
+        || geomType.equals(Geometry.TYPENAME_MULTILINESTRING)
+        || geomType.equals(Geometry.TYPENAME_GEOMETRYCOLLECTION)) {
       double length = 0.0;
       for (int i = 0; i < geom.getNumGeometries(); i++) {
         length += length(geom.getGeometryN(i));
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 926aa77dcb..e9e9af6322 100644
--- a/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
+++ b/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
@@ -1614,30 +1614,36 @@ public class FunctionsTest extends TestBase {
   }
 
   @Test
-  public void spheroidLength() {
+  public void spheroidLength() throws ParseException {
     Point point = GEOMETRY_FACTORY.createPoint(new Coordinate(90, 0));
-    assertEquals(0, Spheroid.length(point), 0.1);
+    assertEquals(0, Spheroid.length(point), FP_TOLERANCE2);
 
     LineString line = GEOMETRY_FACTORY.createLineString(coordArray(0, 0, 90, 
0));
-    assertEquals(1.0018754171394622E7, Spheroid.length(line), 0.1);
+    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), 0.1);
+    assertEquals(2.0037508342789244E7, Spheroid.length(polygon), 
FP_TOLERANCE2);
 
     MultiPoint multiPoint = GEOMETRY_FACTORY.createMultiPoint(new Point[] 
{point, point});
-    assertEquals(0, Spheroid.length(multiPoint), 0.1);
+    assertEquals(0, Spheroid.length(multiPoint), FP_TOLERANCE2);
 
     MultiLineString multiLineString =
         GEOMETRY_FACTORY.createMultiLineString(new LineString[] {line, line});
-    assertEquals(2.0037508342789244E7, Spheroid.length(multiLineString), 0.1);
+    assertEquals(2.0037508342789244E7, Spheroid.length(multiLineString), 
FP_TOLERANCE2);
 
     MultiPolygon multiPolygon =
         GEOMETRY_FACTORY.createMultiPolygon(new Polygon[] {polygon, polygon});
-    assertEquals(4.007501668557849E7, Spheroid.length(multiPolygon), 0.1);
+    assertEquals(4.007501668557849E7, Spheroid.length(multiPolygon), 
FP_TOLERANCE2);
 
     GeometryCollection geometryCollection =
         GEOMETRY_FACTORY.createGeometryCollection(new Geometry[] {point, line, 
multiLineString});
-    assertEquals(3.0056262514183864E7, Spheroid.length(geometryCollection), 
0.1);
+    assertEquals(3.0056262514183864E7, Spheroid.length(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);
   }
 
   @Test

Reply via email to