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 2024/06/07 21:46:52 UTC
(sedona) branch SEDONA-599 created (now 6b712b6e9)
This is an automated email from the ASF dual-hosted git repository.
jiayu pushed a change to branch SEDONA-599
in repository https://gitbox.apache.org/repos/asf/sedona.git
at 6b712b6e9 Update versions
This branch includes the following new commits:
new 36ec0ce34 [TASK-253] Add ST_MinimumClearance (#194)
new 96326d9ab [TASK-209] Add ST_MinimumClearanceLine (#196)
new 6b712b6e9 Update versions
The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(sedona) 03/03: Update versions
Posted by ji...@apache.org.
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 6b712b6e96e4b4d5ba29ba4de76e72ff3312a5eb
Author: Jia Yu <ji...@gmail.com>
AuthorDate: Fri Jun 7 14:46:39 2024 -0700
Update versions
---
docs/api/flink/Function.md | 4 ++--
docs/api/sql/Function.md | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/docs/api/flink/Function.md b/docs/api/flink/Function.md
index c55320a13..8d346e6a8 100644
--- a/docs/api/flink/Function.md
+++ b/docs/api/flink/Function.md
@@ -2485,7 +2485,7 @@ For geometries with no definable minimum clearance, such as single Point geometr
Format: `ST_MinimumClearance(geometry: Geometry)`
-Since: `vTBD`
+Since: `v1.6.1`
SQL Example
@@ -2507,7 +2507,7 @@ Introduction: This function returns a two-point LineString geometry representing
Format: `ST_MinimumClearanceLine(geometry: Geometry)`
-Since: `vTBD`
+Since: `v1.6.1`
SQL Example:
diff --git a/docs/api/sql/Function.md b/docs/api/sql/Function.md
index 78587f204..513379ad8 100644
--- a/docs/api/sql/Function.md
+++ b/docs/api/sql/Function.md
@@ -2497,7 +2497,7 @@ For geometries with no definable minimum clearance, such as single Point geometr
Format: `ST_MinimumClearance(geometry: Geometry)`
-Since: `vTBD`
+Since: `v1.6.1`
SQL Example
@@ -2519,7 +2519,7 @@ Introduction: This function returns a two-point LineString geometry representing
Format: `ST_MinimumClearanceLine(geometry: Geometry)`
-Since: `vTBD`
+Since: `v1.6.1`
SQL Example:
(sedona) 02/03: [TASK-209] Add ST_MinimumClearanceLine (#196)
Posted by ji...@apache.org.
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 <46...@users.noreply.github.com>
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(
(sedona) 01/03: [TASK-253] Add ST_MinimumClearance (#194)
Posted by ji...@apache.org.
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 36ec0ce34b7f3b277184d40d56d430eb75928cbf
Author: Furqaan Khan <46...@users.noreply.github.com>
AuthorDate: Mon May 13 17:47:06 2024 -0400
[TASK-253] Add ST_MinimumClearance (#194)
---
.../java/org/apache/sedona/common/Functions.java | 5 ++++
.../org/apache/sedona/common/FunctionsTest.java | 33 ++++++++++++++++++++++
docs/api/flink/Function.md | 29 +++++++++++++++++++
docs/api/snowflake/vector-data/Function.md | 27 ++++++++++++++++++
docs/api/sql/Function.md | 29 +++++++++++++++++++
.../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 | 10 +++++++
python/tests/sql/test_dataframe_api.py | 2 ++
python/tests/sql/test_function.py | 5 ++++
.../sedona/snowflake/snowsql/TestFunctions.java | 10 +++++++
.../sedona/snowflake/snowsql/TestFunctionsV2.java | 9 ++++++
.../org/apache/sedona/snowflake/snowsql/UDFs.java | 7 +++++
.../apache/sedona/snowflake/snowsql/UDFsV2.java | 7 +++++
.../scala/org/apache/sedona/sql/UDF/Catalog.scala | 1 +
.../sql/sedona_sql/expressions/Functions.scala | 7 +++++
.../sql/sedona_sql/expressions/st_functions.scala | 3 ++
.../apache/sedona/sql/dataFrameAPITestScala.scala | 7 +++++
.../org/apache/sedona/sql/functionTestScala.scala | 7 +++++
20 files changed, 215 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 161d862db..594976cb9 100644
--- a/common/src/main/java/org/apache/sedona/common/Functions.java
+++ b/common/src/main/java/org/apache/sedona/common/Functions.java
@@ -43,6 +43,7 @@ import org.locationtech.jts.operation.valid.IsSimpleOp;
import org.locationtech.jts.operation.valid.IsValidOp;
import org.locationtech.jts.operation.valid.TopologyValidationError;
import org.locationtech.jts.precision.GeometryPrecisionReducer;
+import org.locationtech.jts.precision.MinimumClearance;
import org.locationtech.jts.simplify.PolygonHullSimplifier;
import org.locationtech.jts.simplify.TopologyPreservingSimplifier;
import org.locationtech.jts.simplify.VWSimplifier;
@@ -863,6 +864,10 @@ public class Functions {
return Pair.of(centre, radius);
}
+ public static double minimumClearance(Geometry geometry) {
+ return MinimumClearance.getDistance(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 8915c2cab..4b37b1d61 100644
--- a/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
+++ b/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
@@ -1663,6 +1663,39 @@ public class FunctionsTest extends TestBase {
assertEquals(7.071067, Functions.minimumBoundingRadius(polygon).getRight(), 1e-6);
}
+ @Test
+ public void minimumClearance() throws ParseException {
+ Geometry geometry = Constructors.geomFromEWKT("POLYGON ((0 0, 1 0, 1 1, 0.5 3.2e-4, 0 0))");
+ double actual = Functions.minimumClearance(geometry);
+ double expected = 0.00032;
+ assertEquals(expected, actual, FP_TOLERANCE);
+
+ 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.minimumClearance(geometry);
+ expected = 0.14142135623731153;
+ assertEquals(expected, actual, FP_TOLERANCE);
+
+ geometry = Constructors.geomFromEWKT("POLYGON ((65 18, 62 16, 64.5 16, 62 14, 65 14, 65 18))");
+ actual = Functions.minimumClearance(geometry);
+ expected = 0.5;
+ assertEquals(expected, actual, FP_TOLERANCE2);
+
+ 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.minimumClearance(geometry);
+ expected = 0.4407369162202361;
+ assertEquals(expected, actual, FP_TOLERANCE);
+
+ geometry = Constructors.geomFromEWKT("MULTIPOINT(10 10, 20 20)");
+ actual = Functions.minimumClearance(geometry);
+ expected = 14.142135623730951;
+ assertEquals(expected, actual, FP_TOLERANCE);
+
+ geometry = Constructors.geomFromEWKT("POINT(10 10)");
+ actual = Functions.minimumClearance(geometry);
+ expected = Double.MAX_VALUE;
+ assertEquals(expected, actual, FP_TOLERANCE2);
+ }
+
@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 660658491..81bc961b6 100644
--- a/docs/api/flink/Function.md
+++ b/docs/api/flink/Function.md
@@ -2472,6 +2472,35 @@ Output:
36.05551275463989
```
+## ST_MinimumClearance
+
+Introduction: The minimum clearance is a metric that quantifies a geometry's tolerance to changes in coordinate precision or vertex positions. It represents the maximum distance by which vertices can be adjusted without introducing invalidity to the geometry's structure. A larger minimum clearance value indicates greater robustness against such perturbations.
+
+For a geometry with a minimum clearance of `x`, the following conditions hold:
+
+- No two distinct vertices are separated by a distance less than `x`.
+- No vertex lies within a distance `x` from any line segment it is not an endpoint of.
+
+For geometries with no definable minimum clearance, such as single Point geometries or MultiPoint geometries where all points occupy the same location, the function returns `Double.MAX_VALUE`.
+
+Format: `ST_MinimumClearance(geometry: Geometry)`
+
+Since: `vTBD`
+
+SQL Example
+
+```sql
+SELECT ST_MinimumClearance(
+ ST_GeomFromWKT('POLYGON ((65 18, 62 16, 64.5 16, 62 14, 65 14, 65 18))')
+)
+```
+
+Output:
+
+```
+0.5
+```
+
## 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 5f862e767..e274f435d 100644
--- a/docs/api/snowflake/vector-data/Function.md
+++ b/docs/api/snowflake/vector-data/Function.md
@@ -1786,6 +1786,33 @@ Output:
36.05551275463989
```
+## ST_MinimumClearance
+
+Introduction: The minimum clearance is a metric that quantifies a geometry's tolerance to changes in coordinate precision or vertex positions. It represents the maximum distance by which vertices can be adjusted without introducing invalidity to the geometry's structure. A larger minimum clearance value indicates greater robustness against such perturbations.
+
+For a geometry with a minimum clearance of `x`, the following conditions hold:
+
+- No two distinct vertices are separated by a distance less than `x`.
+- No vertex lies within a distance `x` from any line segment it is not an endpoint of.
+
+For geometries with no definable minimum clearance, such as single Point geometries or MultiPoint geometries where all points occupy the same location, the function returns `Double.MAX_VALUE`.
+
+Format: `ST_MinimumClearance(geometry: Geometry)`
+
+SQL Example
+
+```sql
+SELECT ST_MinimumClearance(
+ ST_GeomFromWKT('POLYGON ((65 18, 62 16, 64.5 16, 62 14, 65 14, 65 18))')
+)
+```
+
+Output:
+
+```
+0.5
+```
+
## 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 ff0a58fbe..d6318eba0 100644
--- a/docs/api/sql/Function.md
+++ b/docs/api/sql/Function.md
@@ -2484,6 +2484,35 @@ Output:
36.05551275463989
```
+## ST_MinimumClearance
+
+Introduction: The minimum clearance is a metric that quantifies a geometry's tolerance to changes in coordinate precision or vertex positions. It represents the maximum distance by which vertices can be adjusted without introducing invalidity to the geometry's structure. A larger minimum clearance value indicates greater robustness against such perturbations.
+
+For a geometry with a minimum clearance of `x`, the following conditions hold:
+
+- No two distinct vertices are separated by a distance less than `x`.
+- No vertex lies within a distance `x` from any line segment it is not an endpoint of.
+
+For geometries with no definable minimum clearance, such as single Point geometries or MultiPoint geometries where all points occupy the same location, the function returns `Double.MAX_VALUE`.
+
+Format: `ST_MinimumClearance(geometry: Geometry)`
+
+Since: `vTBD`
+
+SQL Example
+
+```sql
+SELECT ST_MinimumClearance(
+ ST_GeomFromWKT('POLYGON ((65 18, 62 16, 64.5 16, 62 14, 65 14, 65 18))')
+)
+```
+
+Output:
+
+```
+0.5
+```
+
## 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 91eebd9c4..9ae235a9a 100644
--- a/flink/src/main/java/org/apache/sedona/flink/Catalog.java
+++ b/flink/src/main/java/org/apache/sedona/flink/Catalog.java
@@ -149,6 +149,7 @@ public class Catalog {
new Functions.ST_MakePolygon(),
new Functions.ST_MakeValid(),
new Functions.ST_MaxDistance(),
+ new Functions.ST_MinimumClearance(),
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 79d1a8b26..6b1e38958 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
@@ -912,6 +912,14 @@ public class Functions {
}
}
+ public static class ST_MinimumClearance extends ScalarFunction {
+ @DataTypeHint(value = "Double")
+ public Double eval(@DataTypeHint(value = "RAW", bridgedTo = org.locationtech.jts.geom.Geometry.class) Object o) {
+ Geometry geometry = (Geometry) o;
+ return org.apache.sedona.common.Functions.minimumClearance(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 f128b31d2..4c4d68f92 100644
--- a/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
+++ b/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
@@ -1085,6 +1085,14 @@ public class FunctionTest extends TestBase{
assertEquals(expected, actual);
}
+ @Test
+ public void testMinimumClearance() {
+ Table table = tableEnv.sqlQuery("SELECT ST_GeomFromWKT('POLYGON ((65 18, 62 16, 64.5 16, 62 14, 65 14, 65 18))') as geom");
+ Double actual = (Double) first(table.select(call(Functions.ST_MinimumClearance.class.getSimpleName(), $("geom")))).getField(0);
+ Double expected = 0.5;
+ 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 1a3dd9809..7b468b904 100644
--- a/python/sedona/sql/st_functions.py
+++ b/python/sedona/sql/st_functions.py
@@ -1042,6 +1042,16 @@ def ST_MaxDistance(geom1: ColumnOrName, geom2: ColumnOrName) -> Column:
"""
return _call_st_function("ST_MaxDistance", (geom1, geom2))
+@validate_argument_types
+def ST_MinimumClearance(geometry: ColumnOrName) -> Column:
+ """Calculate the minimum clearance between two vertices
+
+ :param geometry: Geometry column
+ :type geometry: ColumnOrName
+ :return: Minimum Clearance between the geometries
+ :rtype: Column
+ """
+ return _call_st_function("ST_MinimumClearance", geometry)
@validate_argument_types
def ST_MinimumBoundingCircle(geometry: ColumnOrName, quadrant_segments: Optional[Union[ColumnOrName, int]] = None) -> Column:
diff --git a/python/tests/sql/test_dataframe_api.py b/python/tests/sql/test_dataframe_api.py
index 2e201e538..588fa3140 100644
--- a/python/tests/sql/test_dataframe_api.py
+++ b/python/tests/sql/test_dataframe_api.py
@@ -171,6 +171,7 @@ test_configurations = [
(stf.ST_Polygon, ("geom", 4236), "closed_linestring_geom", "", "POLYGON ((0 0, 1 0, 1 1, 0 0))"),
(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_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}),
@@ -370,6 +371,7 @@ wrong_type_configurations = [
(stf.ST_MaxDistance, (None, None)),
(stf.ST_MaxDistance, (None, "")),
(stf.ST_MaxDistance, ("", None)),
+ (stf.ST_MinimumClearance, (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 fcedfb794..d3ca954fa 100644
--- a/python/tests/sql/test_function.py
+++ b/python/tests/sql/test_function.py
@@ -642,6 +642,11 @@ class TestPredicateJoin(TestBase):
assert (empty_dataframe.count() == 0)
+ def test_st_minimum_clearance(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_MinimumClearance(geom)").take(1)[0][0]
+ assert actual == 0.5
+
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 8a39b3f01..dc392b6eb 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
@@ -673,6 +673,16 @@ public class TestFunctions extends TestBase {
"MULTIPOLYGON (((1 5, 3 3, 1 1, 1 5)), ((5 3, 7 5, 7 1, 5 3)))"
);
}
+
+ @Test
+ public void test_ST_MinimumClearance() {
+ registerUDF("ST_MinimumClearance", byte[].class);
+ verifySqlSingleRes(
+ "select sedona.ST_MinimumClearance(sedona.ST_GeomFromText('POLYGON ((65 18, 62 16, 64.5 16, 62 14, 65 14, 65 18))'))",
+ 0.5
+ );
+ }
+
@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 6f9448783..c2fd8693e 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
@@ -628,6 +628,15 @@ public class TestFunctionsV2
);
}
+ @Test
+ public void test_ST_MinimumClearance() {
+ registerUDFV2("ST_MinimumClearance", String.class);
+ verifySqlSingleRes(
+ "select sedona.ST_MinimumClearance(ST_GeomFromText('POLYGON ((65 18, 62 16, 64.5 16, 62 14, 65 14, 65 18))'))",
+ 0.5
+ );
+ }
+
@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 db4d394e1..bdf987d89 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
@@ -914,6 +914,13 @@ public class UDFs {
);
}
+ @UDFAnnotations.ParamMeta(argNames = {"geometry"})
+ public static double ST_MinimumClearance(byte[] geometry) throws IOException {
+ return Functions.minimumClearance(
+ 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 e2e0acdc5..94e716fd6 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
@@ -756,6 +756,13 @@ public class UDFsV2
);
}
+ @UDFAnnotations.ParamMeta(argNames = {"geometry"}, argTypes = {"Geometry"})
+ public static Double ST_MinimumClearance(String geometry) throws IOException {
+ return Functions.minimumClearance(
+ 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 6d16bc9be..ebe266ed4 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
@@ -129,6 +129,7 @@ object Catalog {
function[ST_M](),
function[ST_MMin](),
function[ST_MMax](),
+ function[ST_MinimumClearance](),
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 ded1e31f7..c3d740917 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
@@ -506,6 +506,13 @@ case class ST_Boundary(inputExpressions: Seq[Expression])
}
}
+case class ST_MinimumClearance(inputExpressions: Seq[Expression])
+ extends InferredExpression(Functions.minimumClearance _) {
+
+ 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 9bb23391d..b31d9adff 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
@@ -266,6 +266,9 @@ object st_functions extends DataFrameAPI {
def ST_MaxDistance(geom1: Column, geom2: Column): Column = wrapExpression[ST_MaxDistance](geom1, geom2)
def ST_MaxDistance(geom1: String, geom2: String): Column = wrapExpression[ST_MaxDistance](geom1, geom2)
+ def ST_MinimumClearance(geometry: Column): Column = wrapExpression[ST_MinimumClearance](geometry)
+ def ST_MinimumClearance(geometry: String): Column = wrapExpression[ST_MinimumClearance](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 4a1bf9f98..f62cbc4ff 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
@@ -1014,6 +1014,13 @@ class dataFrameAPITestScala extends TestBaseScala {
assert(actualResult == expectedResult)
}
+ it("Passed ST_MinimumClearance") {
+ 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_MinimumClearance("geom")).first().get(0)
+ val expected = 0.5
+ 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 1b81fb909..3d43006a8 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
@@ -1669,6 +1669,13 @@ class functionTestScala extends TestBaseScala with Matchers with GeometrySample
assert(newY == oldX)
}
+ it("Should pass ST_MinimumClearance") {
+ 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_MinimumClearance(geom)").first().get(0)
+ val expected = 0.5
+ assertEquals(expected, actual)
+ }
+
it("Should pass ST_MinimumBoundingCircle") {
Given("Sample geometry data frame")
val geometryTable = Seq(