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 <[email protected]> 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(
