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

jiayu pushed a commit to branch SEDONA-599
in repository https://gitbox.apache.org/repos/asf/sedona.git

commit 96326d9ab2ccf823012c6d1d83a3044f441c2b77
Author: Furqaan Khan <[email protected]>
AuthorDate: Thu May 16 00:26:35 2024 -0400

    [TASK-209] Add ST_MinimumClearanceLine (#196)
---
 .../java/org/apache/sedona/common/Functions.java   |  4 +++
 .../org/apache/sedona/common/FunctionsTest.java    | 33 ++++++++++++++++++++++
 docs/api/flink/Function.md                         | 22 +++++++++++++++
 docs/api/snowflake/vector-data/Function.md         | 20 +++++++++++++
 docs/api/sql/Function.md                           | 22 +++++++++++++++
 .../main/java/org/apache/sedona/flink/Catalog.java |  1 +
 .../apache/sedona/flink/expressions/Functions.java |  8 ++++++
 .../java/org/apache/sedona/flink/FunctionTest.java |  8 ++++++
 python/sedona/sql/st_functions.py                  | 11 ++++++++
 python/tests/sql/test_dataframe_api.py             |  2 ++
 python/tests/sql/test_function.py                  |  5 ++++
 .../sedona/snowflake/snowsql/TestFunctions.java    |  8 ++++++
 .../sedona/snowflake/snowsql/TestFunctionsV2.java  |  9 ++++++
 .../org/apache/sedona/snowflake/snowsql/UDFs.java  |  9 ++++++
 .../apache/sedona/snowflake/snowsql/UDFsV2.java    |  9 ++++++
 .../scala/org/apache/sedona/sql/UDF/Catalog.scala  |  1 +
 .../sql/sedona_sql/expressions/Functions.scala     |  8 ++++++
 .../sql/sedona_sql/expressions/st_functions.scala  |  3 ++
 .../apache/sedona/sql/dataFrameAPITestScala.scala  |  7 +++++
 .../org/apache/sedona/sql/functionTestScala.scala  |  7 +++++
 20 files changed, 197 insertions(+)

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 594976cb9..b93151cf6 100644
--- a/common/src/main/java/org/apache/sedona/common/Functions.java
+++ b/common/src/main/java/org/apache/sedona/common/Functions.java
@@ -868,6 +868,10 @@ public class Functions {
         return MinimumClearance.getDistance(geometry);
     }
 
+    public static Geometry minimumClearanceLine(Geometry geometry) {
+        return MinimumClearance.getLine(geometry);
+    }
+
     public static Geometry lineSubString(Geometry geom, double fromFraction, 
double toFraction) {
         double length = geom.getLength();
         LengthIndexedLine indexedLine = new LengthIndexedLine(geom);
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 4b37b1d61..f51d29494 100644
--- a/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
+++ b/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
@@ -1696,6 +1696,39 @@ public class FunctionsTest extends TestBase {
         assertEquals(expected, actual, FP_TOLERANCE2);
     }
 
+    @Test
+    public void minimumClearanceLine() throws ParseException {
+        Geometry geometry = Constructors.geomFromEWKT("POLYGON ((0 0, 1 0, 1 
1, 0.5 3.2e-4, 0 0))");
+        String actual = Functions.minimumClearanceLine(geometry).toText();
+        String expected = "LINESTRING (0.5 0.00032, 0.5 0)";
+        assertEquals(expected, actual);
+
+        geometry = Constructors.geomFromEWKT("POLYGON ((10 10, 20 20, 20.1 
20.1, 30 25, 40 30, 50 40, 40 50, 30 45, 20 40, 10 30, 10 10))");
+        actual = Functions.minimumClearanceLine(geometry).toText();
+        expected = "LINESTRING (20 20, 20.1 20.1)";
+        assertEquals(expected, actual);
+
+        geometry = Constructors.geomFromEWKT("POLYGON ((65 18, 62 16, 64.5 16, 
62 14, 65 14, 65 18))");
+        actual = Functions.minimumClearanceLine(geometry).toText();
+        expected = "LINESTRING (64.5 16, 65 16)";
+        assertEquals(expected, actual);
+
+        geometry = Constructors.geomFromEWKT("POLYGON ((65.10498 18.625425, 
62.182617 16.36231, 64.863281 16.40447, 62.006836 14.157882, 65.522461 
14.008696, 65.10498 18.625425))");
+        actual = Functions.minimumClearanceLine(geometry).toText();
+        expected = "LINESTRING (64.863281 16.40447, 65.30222689577225 
16.44416294526772)";
+        assertEquals(expected, actual);
+
+        geometry = Constructors.geomFromEWKT("MULTIPOINT(10 10, 20 20)");
+        actual = Functions.minimumClearanceLine(geometry).toText();
+        expected = "LINESTRING (20 20, 10 10)";
+        assertEquals(expected, actual);
+
+        geometry = Constructors.geomFromEWKT("POINT(10 10)");
+        actual = Functions.minimumClearanceLine(geometry).toText();
+        expected = "LINESTRING EMPTY";
+        assertEquals(expected, actual);
+    }
+
     @Test
     public void nRingsPolygonOnlyExternal() throws Exception {
         Polygon polygon = GEOMETRY_FACTORY.createPolygon(coordArray(1, 0, 1, 
1, 2, 1, 2, 0, 1, 0));
diff --git a/docs/api/flink/Function.md b/docs/api/flink/Function.md
index 81bc961b6..c55320a13 100644
--- a/docs/api/flink/Function.md
+++ b/docs/api/flink/Function.md
@@ -2501,6 +2501,28 @@ Output:
 0.5
 ```
 
+## ST_MinimumClearanceLine
+
+Introduction: This function returns a two-point LineString geometry 
representing the minimum clearance distance of the input geometry. If the input 
geometry does not have a defined minimum clearance, such as for single Points 
or coincident MultiPoints, an empty LineString geometry is returned instead.
+
+Format: `ST_MinimumClearanceLine(geometry: Geometry)`
+
+Since: `vTBD`
+
+SQL Example:
+
+```sql
+SELECT ST_MinimumClearanceLine(
+        ST_GeomFromWKT('POLYGON ((65 18, 62 16, 64.5 16, 62 14, 65 14, 65 
18))')
+)
+```
+
+Output:
+
+```
+LINESTRING (64.5 16, 65 16)
+```
+
 ## ST_MinimumBoundingCircle
 
 Introduction: Returns the smallest circle polygon that contains a geometry. 
The optional quadrantSegments parameter determines how many segments to use per 
quadrant and the default number of segments is 48.
diff --git a/docs/api/snowflake/vector-data/Function.md 
b/docs/api/snowflake/vector-data/Function.md
index e274f435d..83975f118 100644
--- a/docs/api/snowflake/vector-data/Function.md
+++ b/docs/api/snowflake/vector-data/Function.md
@@ -1813,6 +1813,26 @@ Output:
 0.5
 ```
 
+## ST_MinimumClearanceLine
+
+Introduction: This function returns a two-point LineString geometry 
representing the minimum clearance distance of the input geometry. If the input 
geometry does not have a defined minimum clearance, such as for single Points 
or coincident MultiPoints, an empty LineString geometry is returned instead.
+
+Format: `ST_MinimumClearanceLine(geometry: Geometry)`
+
+SQL Example:
+
+```sql
+SELECT ST_MinimumClearanceLine(
+        ST_GeomFromWKT('POLYGON ((65 18, 62 16, 64.5 16, 62 14, 65 14, 65 
18))')
+)
+```
+
+Output:
+
+```
+LINESTRING (64.5 16, 65 16)
+```
+
 ## ST_MinimumBoundingCircle
 
 Introduction: Returns the smallest circle polygon that contains a geometry.
diff --git a/docs/api/sql/Function.md b/docs/api/sql/Function.md
index d6318eba0..78587f204 100644
--- a/docs/api/sql/Function.md
+++ b/docs/api/sql/Function.md
@@ -2513,6 +2513,28 @@ Output:
 0.5
 ```
 
+## ST_MinimumClearanceLine
+
+Introduction: This function returns a two-point LineString geometry 
representing the minimum clearance distance of the input geometry. If the input 
geometry does not have a defined minimum clearance, such as for single Points 
or coincident MultiPoints, an empty LineString geometry is returned instead.
+
+Format: `ST_MinimumClearanceLine(geometry: Geometry)`
+
+Since: `vTBD`
+
+SQL Example:
+
+```sql
+SELECT ST_MinimumClearanceLine(
+        ST_GeomFromWKT('POLYGON ((65 18, 62 16, 64.5 16, 62 14, 65 14, 65 
18))')
+)
+```
+
+Output:
+
+```
+LINESTRING (64.5 16, 65 16)
+```
+
 ## ST_MinimumBoundingCircle
 
 Introduction: Returns the smallest circle polygon that contains a geometry. 
The optional quadrantSegments parameter determines how many segments to use per 
quadrant and the default number of segments has been changed to 48 since v1.5.0.
diff --git a/flink/src/main/java/org/apache/sedona/flink/Catalog.java 
b/flink/src/main/java/org/apache/sedona/flink/Catalog.java
index 9ae235a9a..cbfcc426a 100644
--- a/flink/src/main/java/org/apache/sedona/flink/Catalog.java
+++ b/flink/src/main/java/org/apache/sedona/flink/Catalog.java
@@ -150,6 +150,7 @@ public class Catalog {
                 new Functions.ST_MakeValid(),
                 new Functions.ST_MaxDistance(),
                 new Functions.ST_MinimumClearance(),
+                new Functions.ST_MinimumClearanceLine(),
                 new Functions.ST_MinimumBoundingCircle(),
                 new Functions.ST_MinimumBoundingRadius(),
                 new Functions.ST_Multi(),
diff --git 
a/flink/src/main/java/org/apache/sedona/flink/expressions/Functions.java 
b/flink/src/main/java/org/apache/sedona/flink/expressions/Functions.java
index 6b1e38958..27d398e36 100644
--- a/flink/src/main/java/org/apache/sedona/flink/expressions/Functions.java
+++ b/flink/src/main/java/org/apache/sedona/flink/expressions/Functions.java
@@ -920,6 +920,14 @@ public class Functions {
         }
     }
 
+    public static class ST_MinimumClearanceLine extends ScalarFunction {
+        @DataTypeHint(value = "RAW", bridgedTo = 
org.locationtech.jts.geom.Geometry.class)
+        public Geometry eval(@DataTypeHint(value = "RAW", bridgedTo = 
org.locationtech.jts.geom.Geometry.class) Object o) {
+            Geometry geometry = (Geometry) o;
+            return 
org.apache.sedona.common.Functions.minimumClearanceLine(geometry);
+        }
+    }
+
     public static class ST_MinimumBoundingCircle extends ScalarFunction {
         @DataTypeHint(value = "RAW", bridgedTo = 
org.locationtech.jts.geom.Geometry.class)
         public Geometry eval(@DataTypeHint(value = "RAW", bridgedTo = 
org.locationtech.jts.geom.Geometry.class) Object o,
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 4c4d68f92..c81ee7ad5 100644
--- a/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
+++ b/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
@@ -1093,6 +1093,14 @@ public class FunctionTest extends TestBase{
         assertEquals(expected, actual);
     }
 
+    @Test
+    public void testMinimumClearanceLine() {
+        Table table = tableEnv.sqlQuery("SELECT ST_GeomFromWKT('POLYGON ((65 
18, 62 16, 64.5 16, 62 14, 65 14, 65 18))') as geom");
+        String actual = ((Geometry) 
first(table.select(call(Functions.ST_MinimumClearanceLine.class.getSimpleName(),
 $("geom")))).getField(0)).toText();
+        String expected = "LINESTRING (64.5 16, 65 16)";
+        assertEquals(expected, actual);
+    }
+
     @Test
     public void testMinimumBoundingCircle() {
         Table table = tableEnv.sqlQuery("SELECT ST_GeomFromWKT('LINESTRING (0 
0, 1 0)') AS geom");
diff --git a/python/sedona/sql/st_functions.py 
b/python/sedona/sql/st_functions.py
index 7b468b904..27c1dc2a8 100644
--- a/python/sedona/sql/st_functions.py
+++ b/python/sedona/sql/st_functions.py
@@ -1053,6 +1053,17 @@ def ST_MinimumClearance(geometry: ColumnOrName) -> 
Column:
     """
     return _call_st_function("ST_MinimumClearance", geometry)
 
+@validate_argument_types
+def ST_MinimumClearanceLine(geometry: ColumnOrName) -> Column:
+    """Calculate the minimum clearance Linestring between two vertices
+
+    :param geometry: Geometry column
+    :type geometry: ColumnOrName
+    :return: Minimum Clearance Linestring between the geometries
+    :rtype: Column
+    """
+    return _call_st_function("ST_MinimumClearanceLine", geometry)
+
 @validate_argument_types
 def ST_MinimumBoundingCircle(geometry: ColumnOrName, quadrant_segments: 
Optional[Union[ColumnOrName, int]] = None) -> Column:
     """Generate the minimum bounding circle that contains a geometry.
diff --git a/python/tests/sql/test_dataframe_api.py 
b/python/tests/sql/test_dataframe_api.py
index 588fa3140..bc08ce265 100644
--- a/python/tests/sql/test_dataframe_api.py
+++ b/python/tests/sql/test_dataframe_api.py
@@ -172,6 +172,7 @@ test_configurations = [
     (stf.ST_Polygonize, ("geom",), "noded_linework", "ST_Normalize(geom)", 
"GEOMETRYCOLLECTION (POLYGON ((0 2, 1 3, 2 4, 2 3, 2 2, 1 2, 0 2)), POLYGON ((2 
2, 2 3, 2 4, 3 3, 4 2, 3 2, 2 2)))"),
     (stf.ST_MakePolygon, ("geom",), "closed_linestring_geom", "", "POLYGON ((0 
0, 1 0, 1 1, 0 0))"),
     (stf.ST_MinimumClearance, ("geom",), "invalid_geom", "", 2.0),
+    (stf.ST_MinimumClearanceLine, ("geom",), "invalid_geom", "", "LINESTRING 
(5 3, 3 3)"),
     (stf.ST_MinimumBoundingCircle, ("line", 8), "linestring_geom", 
"ST_ReducePrecision(geom, 2)", "POLYGON ((4.95 -0.49, 4.81 -0.96, 4.58 -1.39, 
4.27 -1.77, 3.89 -2.08, 3.46 -2.31, 2.99 -2.45, 2.5 -2.5, 2.01 -2.45, 1.54 
-2.31, 1.11 -2.08, 0.73 -1.77, 0.42 -1.39, 0.19 -0.96, 0.05 -0.49, 0 0, 0.05 
0.49, 0.19 0.96, 0.42 1.39, 0.73 1.77, 1.11 2.08, 1.54 2.31, 2.01 2.45, 2.5 
2.5, 2.99 2.45, 3.46 2.31, 3.89 2.08, 4.27 1.77, 4.58 1.39, 4.81 0.96, 4.95 
0.49, 5 0, 4.95 -0.49))"),
     (stf.ST_MinimumBoundingCircle, ("line", 2), "linestring_geom", 
"ST_ReducePrecision(geom, 2)", "POLYGON ((4.27 -1.77, 2.5 -2.5, 0.73 -1.77, 0 
0, 0.73 1.77, 2.5 2.5, 4.27 1.77, 5 0, 4.27 -1.77))"),
     (stf.ST_MinimumBoundingRadius, ("line",), "linestring_geom", "", 
{"center": "POINT (2.5 0)", "radius": 2.5}),
@@ -372,6 +373,7 @@ wrong_type_configurations = [
     (stf.ST_MaxDistance, (None, "")),
     (stf.ST_MaxDistance, ("", None)),
     (stf.ST_MinimumClearance, (None,)),
+    (stf.ST_MinimumClearanceLine, (None,)),
     (stf.ST_MinimumBoundingCircle, (None,)),
     (stf.ST_MinimumBoundingRadius, (None,)),
     (stf.ST_Multi, (None,)),
diff --git a/python/tests/sql/test_function.py 
b/python/tests/sql/test_function.py
index d3ca954fa..20395a4cd 100644
--- a/python/tests/sql/test_function.py
+++ b/python/tests/sql/test_function.py
@@ -647,6 +647,11 @@ class TestPredicateJoin(TestBase):
         actual = baseDf.selectExpr("ST_MinimumClearance(geom)").take(1)[0][0]
         assert actual == 0.5
 
+    def test_st_minimum_clearance_line(self):
+        baseDf = self.spark.sql("SELECT ST_GeomFromWKT('POLYGON ((65 18, 62 
16, 64.5 16, 62 14, 65 14, 65 18))') as geom")
+        actual = 
baseDf.selectExpr("ST_MinimumClearanceLine(geom)").take(1)[0][0].wkt
+        assert actual == "LINESTRING (64.5 16, 65 16)"
+
     def test_st_boundary(self):
         wkt_list = [
             "LINESTRING(1 1,0 0, -1 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 dc392b6eb..77d10ce73 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
@@ -683,6 +683,14 @@ public class TestFunctions extends TestBase {
         );
     }
 
+    @Test
+    public void test_ST_MinimumClearanceLine() {
+        registerUDF("ST_MinimumClearanceLine", byte[].class);
+        verifySqlSingleRes(
+                "select 
sedona.ST_AsText(sedona.ST_MinimumClearanceLine(sedona.ST_GeomFromText('POLYGON 
((65 18, 62 16, 64.5 16, 62 14, 65 14, 65 18))')))",
+                "LINESTRING (64.5 16, 65 16)"
+        );
+    }
     @Test
     public void test_ST_MinimumBoundingCircle() {
         registerUDF("ST_MinimumBoundingCircle", byte[].class, int.class);
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 c2fd8693e..8a2b170b8 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
@@ -637,6 +637,15 @@ public class TestFunctionsV2
         );
     }
 
+    @Test
+    public void test_ST_MinimumClearanceLine() {
+        registerUDFV2("ST_MinimumClearanceLine", String.class);
+        verifySqlSingleRes(
+                "select 
ST_AsText(sedona.ST_MinimumClearanceLine(ST_GeomFromText('POLYGON ((65 18, 62 
16, 64.5 16, 62 14, 65 14, 65 18))')))",
+                "LINESTRING(64.5 16,65 16)"
+        );
+    }
+
     @Test
     public void test_ST_MinimumBoundingCircle() {
         registerUDFV2("ST_MinimumBoundingCircle", String.class, int.class);
diff --git 
a/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFs.java 
b/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFs.java
index bdf987d89..f2728fd65 100644
--- a/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFs.java
+++ b/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFs.java
@@ -921,6 +921,15 @@ public class UDFs {
         );
     }
 
+    @UDFAnnotations.ParamMeta(argNames = {"geometry"})
+    public static byte[] ST_MinimumClearanceLine(byte[] geometry) throws 
IOException {
+        return GeometrySerde.serialize(
+                Functions.minimumClearanceLine(
+                        GeometrySerde.deserialize(geometry)
+                )
+        );
+    }
+
     @UDFAnnotations.ParamMeta(argNames = {"geometry", "quadrantSegments"})
     public static byte[] ST_MinimumBoundingCircle(byte[] geometry, int 
quadrantSegments) {
         return GeometrySerde.serialize(
diff --git 
a/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFsV2.java 
b/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFsV2.java
index 94e716fd6..4e8db072f 100644
--- a/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFsV2.java
+++ b/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFsV2.java
@@ -763,6 +763,15 @@ public class UDFsV2
         );
     }
 
+    @UDFAnnotations.ParamMeta(argNames = {"geometry"}, argTypes = 
{"Geometry"}, returnTypes = "Geometry")
+    public static String ST_MinimumClearanceLine(String geometry) {
+        return GeometrySerde.serGeoJson(
+                Functions.minimumClearanceLine(
+                        GeometrySerde.deserGeoJson(geometry)
+                )
+        );
+    }
+
     @UDFAnnotations.ParamMeta(argNames = {"geometry", "quadrantSegments"}, 
argTypes = {"Geometry", "int"}, returnTypes = "Geometry")
     public static String ST_MinimumBoundingCircle(String geometry, int 
quadrantSegments) {
         return GeometrySerde.serGeoJson(
diff --git 
a/spark/common/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala 
b/spark/common/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala
index ebe266ed4..ea4889087 100644
--- a/spark/common/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala
+++ b/spark/common/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala
@@ -130,6 +130,7 @@ object Catalog {
     function[ST_MMin](),
     function[ST_MMax](),
     function[ST_MinimumClearance](),
+    function[ST_MinimumClearanceLine](),
     function[ST_MinimumBoundingRadius](),
     
function[ST_MinimumBoundingCircle](BufferParameters.DEFAULT_QUADRANT_SEGMENTS * 
6),
     function[ST_EndPoint](),
diff --git 
a/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala
 
b/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala
index c3d740917..a36a4e30d 100644
--- 
a/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala
+++ 
b/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala
@@ -514,6 +514,14 @@ case class ST_MinimumClearance(inputExpressions: 
Seq[Expression])
   }
 }
 
+case class ST_MinimumClearanceLine(inputExpressions: Seq[Expression])
+  extends InferredExpression(Functions.minimumClearanceLine _) {
+
+  protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]) = 
{
+    copy(inputExpressions = newChildren)
+  }
+}
+
 case class ST_MinimumBoundingRadius(inputExpressions: Seq[Expression])
   extends Expression with FoldableExpression with CodegenFallback {
 
diff --git 
a/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/st_functions.scala
 
b/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/st_functions.scala
index b31d9adff..28096b9a5 100644
--- 
a/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/st_functions.scala
+++ 
b/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/st_functions.scala
@@ -269,6 +269,9 @@ object st_functions extends DataFrameAPI {
   def ST_MinimumClearance(geometry: Column): Column = 
wrapExpression[ST_MinimumClearance](geometry)
   def ST_MinimumClearance(geometry: String): Column = 
wrapExpression[ST_MinimumClearance](geometry)
 
+  def ST_MinimumClearanceLine(geometry: Column): Column = 
wrapExpression[ST_MinimumClearanceLine](geometry)
+  def ST_MinimumClearanceLine(geometry: String): Column = 
wrapExpression[ST_MinimumClearanceLine](geometry)
+
   def ST_MinimumBoundingCircle(geometry: Column): Column = 
wrapExpression[ST_MinimumBoundingCircle](geometry, 
BufferParameters.DEFAULT_QUADRANT_SEGMENTS * 6)
   def ST_MinimumBoundingCircle(geometry: String): Column = 
wrapExpression[ST_MinimumBoundingCircle](geometry, 
BufferParameters.DEFAULT_QUADRANT_SEGMENTS * 6)
   def ST_MinimumBoundingCircle(geometry: Column, quadrantSegments: Column): 
Column = wrapExpression[ST_MinimumBoundingCircle](geometry, quadrantSegments)
diff --git 
a/spark/common/src/test/scala/org/apache/sedona/sql/dataFrameAPITestScala.scala 
b/spark/common/src/test/scala/org/apache/sedona/sql/dataFrameAPITestScala.scala
index f62cbc4ff..faf8d6a56 100644
--- 
a/spark/common/src/test/scala/org/apache/sedona/sql/dataFrameAPITestScala.scala
+++ 
b/spark/common/src/test/scala/org/apache/sedona/sql/dataFrameAPITestScala.scala
@@ -1021,6 +1021,13 @@ class dataFrameAPITestScala extends TestBaseScala {
       assertEquals(expected, actual)
     }
 
+    it("Passed ST_MinimumClearanceLine") {
+      val baseDf = sparkSession.sql("SELECT ST_GeomFromWKT('POLYGON ((65 18, 
62 16, 64.5 16, 62 14, 65 14, 65 18))') as geom")
+      val actual = 
baseDf.select(ST_MinimumClearanceLine("geom")).first().get(0).asInstanceOf[Geometry].toText
+      val expected = "LINESTRING (64.5 16, 65 16)"
+      assertEquals(expected, actual)
+    }
+
     it("Passed ST_MinimumBoundingCircle with default quadrantSegments") {
       val baseDf = sparkSession.sql("SELECT ST_GeomFromWKT('LINESTRING (0 0, 1 
0)') AS geom")
       val df = 
baseDf.select(ST_MinimumBoundingCircle("geom").as("geom")).selectExpr("ST_ReducePrecision(geom,
 2)")
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 3d43006a8..df90b0481 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
@@ -1676,6 +1676,13 @@ class functionTestScala extends TestBaseScala with 
Matchers with GeometrySample
     assertEquals(expected, actual)
   }
 
+  it("Should pass ST_MinimumClearanceLine") {
+    val baseDf = sparkSession.sql("SELECT ST_GeomFromWKT('POLYGON ((65 18, 62 
16, 64.5 16, 62 14, 65 14, 65 18))') as geom")
+    val actual = 
baseDf.selectExpr("ST_MinimumClearanceLine(geom)").first().get(0).asInstanceOf[Geometry].toText
+    val expected = "LINESTRING (64.5 16, 65 16)"
+    assertEquals(expected, actual)
+  }
+
   it("Should pass ST_MinimumBoundingCircle") {
     Given("Sample geometry data frame")
     val geometryTable = Seq(

Reply via email to