This is an automated email from the ASF dual-hosted git repository.
jiayu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sedona.git
The following commit(s) were added to refs/heads/master by this push:
new 52b6ae8e71 [SEDONA-693] Add ST_Perimeter2D (#1745)
52b6ae8e71 is described below
commit 52b6ae8e71601cdf36a6176198839bc3daf5547c
Author: Furqaan Khan <[email protected]>
AuthorDate: Thu Jan 9 13:37:54 2025 -0500
[SEDONA-693] Add ST_Perimeter2D (#1745)
* feat: add ST_Perimeter2D, alias of ST_Perimeter
* fix: port function to flink
* chore: change note to info in annotation
---
docs/api/flink/Function.md | 48 +++++++++++++++++
docs/api/snowflake/vector-data/Function.md | 46 +++++++++++++++++
docs/api/sql/Function.md | 60 ++++++++++++++++++++--
.../main/java/org/apache/sedona/flink/Catalog.java | 1 +
.../apache/sedona/flink/expressions/Functions.java | 27 ++++++++++
.../java/org/apache/sedona/flink/FunctionTest.java | 26 ++++++++++
python/sedona/sql/st_functions.py | 24 +++++++++
python/tests/sql/test_dataframe_api.py | 9 ++++
python/tests/sql/test_function.py | 19 +++++++
.../sedona/snowflake/snowsql/TestFunctions.java | 19 +++++++
.../sedona/snowflake/snowsql/TestFunctionsV2.java | 13 +++++
.../org/apache/sedona/snowflake/snowsql/UDFs.java | 15 ++++++
.../apache/sedona/snowflake/snowsql/UDFsV2.java | 24 +++++++++
.../scala/org/apache/sedona/sql/UDF/Catalog.scala | 1 +
.../sql/sedona_sql/expressions/Functions.scala | 11 ++++
.../sql/sedona_sql/expressions/st_functions.scala | 11 ++++
.../apache/sedona/sql/dataFrameAPITestScala.scala | 19 +++++++
.../org/apache/sedona/sql/functionTestScala.scala | 18 +++++++
18 files changed, 387 insertions(+), 4 deletions(-)
diff --git a/docs/api/flink/Function.md b/docs/api/flink/Function.md
index d735fe97b1..e2273ae885 100644
--- a/docs/api/flink/Function.md
+++ b/docs/api/flink/Function.md
@@ -3191,6 +3191,54 @@ Output:
2216860.5497177234
```
+## ST_Perimeter2D
+
+Introduction: This function calculates the 2D perimeter of a given geometry.
It supports Polygon, MultiPolygon, and GeometryCollection geometries (as long
as the GeometryCollection contains polygonal geometries). For other types, it
returns 0. To measure lines, use [ST_Length](#st_length).
+
+To get the perimeter in meters, set `use_spheroid` to `true`. This calculates
the geodesic perimeter using the WGS84 spheroid. When using `use_spheroid`, the
`lenient` parameter defaults to true, assuming the geometry uses EPSG:4326. To
throw an exception instead, set `lenient` to `false`.
+
+!!!Info
+ This function is an alias for [ST_Perimeter](#st_perimeter).
+
+Format:
+
+`ST_Perimeter2D(geom: Geometry)`
+
+`ST_Perimeter2D(geom: Geometry, use_spheroid: Boolean)`
+
+`ST_Perimeter2D(geom: Geometry, use_spheroid: Boolean, lenient: Boolean =
True)`
+
+Since: `v1.7.1`
+
+SQL Example:
+
+```sql
+SELECT ST_Perimeter2D(
+ ST_GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))')
+)
+```
+
+Output:
+
+```
+20.0
+```
+
+SQL Example:
+
+```sql
+SELECT ST_Perimeter2D(
+ ST_GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))', 4326),
+ true, false
+)
+```
+
+Output:
+
+```
+2216860.5497177234
+```
+
## ST_PointN
Introduction: Return the Nth point in a single linestring or circular
linestring in the geometry. Negative values are counted backwards from the end
of the LineString, so that -1 is the last point. Returns NULL if there is no
linestring in the geometry.
diff --git a/docs/api/snowflake/vector-data/Function.md
b/docs/api/snowflake/vector-data/Function.md
index 3fdd484283..f6b8c447f2 100644
--- a/docs/api/snowflake/vector-data/Function.md
+++ b/docs/api/snowflake/vector-data/Function.md
@@ -2425,6 +2425,52 @@ Output:
2216860.5497177234
```
+## ST_Perimeter2D
+
+Introduction: This function calculates the 2D perimeter of a given geometry.
It supports Polygon, MultiPolygon, and GeometryCollection geometries (as long
as the GeometryCollection contains polygonal geometries). For other types, it
returns 0. To measure lines, use [ST_Length](#st_length).
+
+To get the perimeter in meters, set `use_spheroid` to `true`. This calculates
the geodesic perimeter using the WGS84 spheroid. When using `use_spheroid`, the
`lenient` parameter defaults to true, assuming the geometry uses EPSG:4326. To
throw an exception instead, set `lenient` to `false`.
+
+!!!Info
+ This function is an alias for [ST_Perimeter](#st_perimeter).
+
+Format:
+
+`ST_Perimeter2D(geom: Geometry)`
+
+`ST_Perimeter2D(geom: Geometry, use_spheroid: Boolean)`
+
+`ST_Perimeter2D(geom: Geometry, use_spheroid: Boolean, lenient: Boolean =
True)`
+
+SQL Example:
+
+```sql
+SELECT ST_Perimeter2D(
+ ST_GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))')
+)
+```
+
+Output:
+
+```
+20.0
+```
+
+SQL Example:
+
+```sql
+SELECT ST_Perimeter2D(
+ ST_GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))', 4326),
+ true, false
+)
+```
+
+Output:
+
+```
+2216860.5497177234
+```
+
## ST_PointN
Introduction: Return the Nth point in a single linestring or circular
linestring in the geometry. Negative values are counted backwards from the end
of the LineString, so that -1 is the last point. Returns NULL if there is no
linestring in the geometry.
diff --git a/docs/api/sql/Function.md b/docs/api/sql/Function.md
index 8aa8aa4404..5346fb25bf 100644
--- a/docs/api/sql/Function.md
+++ b/docs/api/sql/Function.md
@@ -723,12 +723,14 @@ SQL Example
```sql
ST_BinaryDistanceBandColumn(geometry, 1.0, true, true, false, struct(id,
geometry))
-````
+```
Output:
-```
+```sql
+{% raw %}
[{{15, POINT (3 1.9)}, 1.0}, {{16, POINT (3 2)}, 1.0}, {{17, POINT (3 2.1)},
1.0}, {{18, POINT (3 2.2)}, 1.0}]
+{% endraw %}
```
## ST_Boundary
@@ -3377,6 +3379,54 @@ Output:
2216860.5497177234
```
+## ST_Perimeter2D
+
+Introduction: This function calculates the 2D perimeter of a given geometry.
It supports Polygon, MultiPolygon, and GeometryCollection geometries (as long
as the GeometryCollection contains polygonal geometries). For other types, it
returns 0. To measure lines, use [ST_Length](#st_length).
+
+To get the perimeter in meters, set `use_spheroid` to `true`. This calculates
the geodesic perimeter using the WGS84 spheroid. When using `use_spheroid`, the
`lenient` parameter defaults to true, assuming the geometry uses EPSG:4326. To
throw an exception instead, set `lenient` to `false`.
+
+!!!Info
+ This function is an alias for [ST_Perimeter](#st_perimeter).
+
+Format:
+
+`ST_Perimeter2D(geom: Geometry)`
+
+`ST_Perimeter2D(geom: Geometry, use_spheroid: Boolean)`
+
+`ST_Perimeter2D(geom: Geometry, use_spheroid: Boolean, lenient: Boolean =
True)`
+
+Since: `v1.7.1`
+
+SQL Example:
+
+```sql
+SELECT ST_Perimeter2D(
+ ST_GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))')
+)
+```
+
+Output:
+
+```
+20.0
+```
+
+SQL Example:
+
+```sql
+SELECT ST_Perimeter2D(
+ ST_GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))', 4326),
+ true, false
+)
+```
+
+Output:
+
+```
+2216860.5497177234
+```
+
## ST_PointN
Introduction: Return the Nth point in a single linestring or circular
linestring in the geometry. Negative values are counted backwards from the end
of the LineString, so that -1 is the last point. Returns NULL if there is no
linestring in the geometry.
@@ -4531,12 +4581,14 @@ SQL Example
```sql
ST_WeightedDistanceBandColumn(geometry, 1.0, -1.0, true, true, 1.0, false,
struct(id, geometry))
-````
+```
Output:
-```
+```sql
+{% raw %}
[{{15, POINT (3 1.9)}, 1.0}, {{16, POINT (3 2)}, 9.999999999999991}, {{17,
POINT (3 2.1)}, 4.999999999999996}, {{18, POINT (3 2.2)}, 3.3333333333333304}]
+{% endraw %}
```
## ST_X
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 ba42f9febe..1654bf0d28 100644
--- a/flink/src/main/java/org/apache/sedona/flink/Catalog.java
+++ b/flink/src/main/java/org/apache/sedona/flink/Catalog.java
@@ -102,6 +102,7 @@ public class Catalog {
new Functions.ST_FlipCoordinates(),
new Functions.ST_GeoHash(),
new Functions.ST_Perimeter(),
+ new Functions.ST_Perimeter2D(),
new Functions.ST_PointOnSurface(),
new Functions.ST_Scale(),
new Functions.ST_ScaleGeom(),
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 96a00f7b4d..d23adf03f5 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
@@ -622,6 +622,33 @@ public class Functions {
}
}
+ public static class ST_Perimeter2D extends ScalarFunction {
+ @DataTypeHint(value = "Double")
+ public Double eval(
+ @DataTypeHint(value = "RAW", bridgedTo =
org.locationtech.jts.geom.Geometry.class)
+ Object o) {
+ Geometry geom = (Geometry) o;
+ return org.apache.sedona.common.Functions.perimeter(geom);
+ }
+
+ @DataTypeHint(value = "Double")
+ public Double eval(
+ @DataTypeHint(value = "RAW", bridgedTo =
org.locationtech.jts.geom.Geometry.class) Object o,
+ Boolean use_spheroid) {
+ Geometry geom = (Geometry) o;
+ return org.apache.sedona.common.Functions.perimeter(geom, use_spheroid);
+ }
+
+ @DataTypeHint(value = "Double")
+ public Double eval(
+ @DataTypeHint(value = "RAW", bridgedTo =
org.locationtech.jts.geom.Geometry.class) Object o,
+ Boolean use_spheroid,
+ boolean lenient) {
+ Geometry geom = (Geometry) o;
+ return org.apache.sedona.common.Functions.perimeter(geom, use_spheroid,
lenient);
+ }
+ }
+
public static class ST_PointOnSurface extends ScalarFunction {
@DataTypeHint(value = "RAW", bridgedTo =
org.locationtech.jts.geom.Geometry.class)
public Geometry eval(
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 dc510c1935..949464b96a 100644
--- a/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
+++ b/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
@@ -821,6 +821,32 @@ public class FunctionTest extends TestBase {
assertEquals(443770.91724830196, perimeter, FP_TOLERANCE);
}
+ @Test
+ public void testPerimeter2D() {
+ Table polygonTable = createPolygonTable(testDataSize);
+ Table perimeterTable =
+ polygonTable.select(
+ call(Functions.ST_Perimeter2D.class.getSimpleName(),
$(polygonColNames[0])));
+ Double perimeter = (Double) first(perimeterTable).getField(0);
+ assertEquals(4.0, perimeter, FP_TOLERANCE);
+
+ polygonTable =
+ tableEnv.sqlQuery(
+ "SELECT ST_GeomFromWKT('POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))',
4326) AS geom");
+ perimeterTable =
+ polygonTable.select(
+ call(Functions.ST_Perimeter2D.class.getSimpleName(), $("geom"),
true, false));
+ perimeter = (Double) first(perimeterTable).getField(0);
+ assertEquals(443770.91724830196, perimeter, FP_TOLERANCE);
+
+ polygonTable =
+ tableEnv.sqlQuery("SELECT ST_GeomFromWKT('POLYGON ((0 0, 0 1, 1 1, 1
0, 0 0))') AS geom");
+ perimeterTable =
+
polygonTable.select(call(Functions.ST_Perimeter2D.class.getSimpleName(),
$("geom"), true));
+ perimeter = (Double) first(perimeterTable).getField(0);
+ assertEquals(443770.91724830196, perimeter, FP_TOLERANCE);
+ }
+
@Test
public void testPointOnSurface() {
Table pointTable = createPointTable_real(testDataSize);
diff --git a/python/sedona/sql/st_functions.py
b/python/sedona/sql/st_functions.py
index b3f67fd522..b5d4eb6dcf 100644
--- a/python/sedona/sql/st_functions.py
+++ b/python/sedona/sql/st_functions.py
@@ -1225,6 +1225,30 @@ def ST_Perimeter(
return _call_st_function("ST_Perimeter", args)
+@validate_argument_types
+def ST_Perimeter2D(
+ geom: ColumnOrName,
+ use_spheroid: Optional[Union[ColumnOrName, bool]] = None,
+ lenient: Optional[Union[ColumnOrName, bool]] = None,
+) -> Column:
+ """Returns the perimeter of a Polygon/MultiPolygon geometries. Otherwise,
returns 0
+
+ @param geom: Polygonal geometry
+ @param use_spheroid: Use Spheroid
+ @param lenient: suppresses the exception
+ @return: Perimeter of a Polygon/MultiPolygon geometries
+ """
+
+ args = (geom, use_spheroid, lenient)
+
+ if lenient is None:
+ if use_spheroid is None:
+ args = (geom,)
+ else:
+ args = (geom, use_spheroid)
+ return _call_st_function("ST_Perimeter2D", args)
+
+
@validate_argument_types
def ST_Points(geometry: ColumnOrName) -> Column:
"""Creates a MultiPoint geometry consisting of all the coordinates of the
input geometry
diff --git a/python/tests/sql/test_dataframe_api.py
b/python/tests/sql/test_dataframe_api.py
index 8299f5b45f..0c1d0bd200 100644
--- a/python/tests/sql/test_dataframe_api.py
+++ b/python/tests/sql/test_dataframe_api.py
@@ -761,6 +761,15 @@ test_configurations = [
"ceil(geom)",
378794,
),
+ (stf.ST_Perimeter2D, ("geom",), "triangle_geom", "", 3.414213562373095),
+ (stf.ST_Perimeter2D, ("geom", True), "triangle_geom", "ceil(geom)",
378794),
+ (
+ stf.ST_Perimeter2D,
+ (lambda: stf.ST_SetSRID("geom", 4326), True),
+ "triangle_geom",
+ "ceil(geom)",
+ 378794,
+ ),
(
stf.ST_Points,
("line",),
diff --git a/python/tests/sql/test_function.py
b/python/tests/sql/test_function.py
index 6c1e968c0d..0050708bd0 100644
--- a/python/tests/sql/test_function.py
+++ b/python/tests/sql/test_function.py
@@ -1685,6 +1685,25 @@ class TestPredicateJoin(TestBase):
expected = 443770.91724830196
assert expected == actual
+ def test_st_perimeter2D(self):
+ baseDf = self.spark.sql(
+ "SELECT ST_GeomFromWKT('POLYGON((743238 2967416,743238
2967450,743265 2967450,743265.625 2967416,743238 2967416))') AS geom"
+ )
+ actual = baseDf.selectExpr("ST_Perimeter2D(geom)").take(1)[0][0]
+ expected = 122.63074400009504
+ assert actual == expected
+
+ baseDf = self.spark.sql(
+ "SELECT ST_GeomFromWKT('POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))',
4326) AS geom"
+ )
+ actual = baseDf.selectExpr("ST_Perimeter2D(geom, true)").first()[0]
+ expected = 443770.91724830196
+ assert expected == actual
+
+ actual = baseDf.selectExpr("ST_Perimeter2D(geom, true,
false)").first()[0]
+ expected = 443770.91724830196
+ assert expected == actual
+
def test_st_points(self):
# Given
geometry_df = self.spark.createDataFrame(
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 916c4e3371..e4ffafab3f 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
@@ -807,6 +807,25 @@ public class TestFunctions extends TestBase {
2216861.0);
}
+ @Test
+ public void test_ST_Perimeter2D() {
+ registerUDF("ST_Perimeter2D", byte[].class);
+ verifySqlSingleRes(
+ "SELECT sedona.ST_Perimeter2D(sedona.ST_GeomFromText('POLYGON((0 0, 0
5, 5 5, 5 0, 0 0))'))",
+ 20.0);
+
+ registerUDF("ST_Perimeter2D", byte[].class, boolean.class);
+ verifySqlSingleRes(
+ "SELECT CEIL(sedona.ST_Perimeter2D(sedona.ST_GeomFromText('POLYGON((0
0, 0 5, 5 5, 5 0, 0 0))'), true))",
+ 2216861.0);
+
+ registerUDF("ST_Perimeter2D", byte[].class, boolean.class, boolean.class);
+ registerUDF("ST_GeomFromText", String.class, int.class);
+ verifySqlSingleRes(
+ "SELECT CEIL(sedona.ST_Perimeter2D(sedona.ST_GeomFromText('POLYGON((0
0, 0 5, 5 5, 5 0, 0 0))', 4326), true, false))",
+ 2216861.0);
+ }
+
@Test
public void test_ST_PointOnSurface() {
registerUDF("ST_PointOnSurface", byte[].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 25a4006690..30488f9fae 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
@@ -748,6 +748,19 @@ public class TestFunctionsV2 extends TestBase {
2216861.0);
}
+ @Test
+ public void test_ST_Perimeter2D() {
+ registerUDFV2("ST_Perimeter2D", String.class);
+ verifySqlSingleRes(
+ "SELECT sedona.ST_Perimeter2D(ST_GeomFromText('POLYGON((0 0, 0 5, 5 5,
5 0, 0 0))'))",
+ 20.0);
+
+ registerUDFV2("ST_Perimeter2D", String.class, boolean.class);
+ verifySqlSingleRes(
+ "SELECT CEIL(sedona.ST_Perimeter2D(ST_GeomFromText('POLYGON((0 0, 0 5,
5 5, 5 0, 0 0))'), true))",
+ 2216861.0);
+ }
+
@Test
public void test_ST_PointOnSurface() {
registerUDFV2("ST_PointOnSurface", String.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 485e54730b..98fdbb0608 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
@@ -839,6 +839,21 @@ public class UDFs {
return Functions.perimeter(GeometrySerde.deserialize(geometry),
use_spheroid, lenient);
}
+ @UDFAnnotations.ParamMeta(argNames = {"geometry"})
+ public static double ST_Perimeter2D(byte[] geometry) {
+ return Functions.perimeter(GeometrySerde.deserialize(geometry));
+ }
+
+ @UDFAnnotations.ParamMeta(argNames = {"geometry", "use_spheroid"})
+ public static double ST_Perimeter2D(byte[] geometry, boolean use_spheroid) {
+ return Functions.perimeter(GeometrySerde.deserialize(geometry),
use_spheroid);
+ }
+
+ @UDFAnnotations.ParamMeta(argNames = {"geometry", "use_spheroid", "lenient"})
+ public static double ST_Perimeter2D(byte[] geometry, boolean use_spheroid,
boolean lenient) {
+ return Functions.perimeter(GeometrySerde.deserialize(geometry),
use_spheroid, lenient);
+ }
+
@UDFAnnotations.ParamMeta(argNames = {"geometry"})
public static byte[] ST_PointOnSurface(byte[] geometry) {
return
GeometrySerde.serialize(Functions.pointOnSurface(GeometrySerde.deserialize(geometry)));
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 f135a51881..2d9b349b18 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
@@ -989,6 +989,30 @@ public class UDFsV2 {
return Functions.perimeter(GeometrySerde.deserGeoJson(geometry),
use_spheroid, lenient);
}
+ @UDFAnnotations.ParamMeta(
+ argNames = {"geometry"},
+ argTypes = {"Geometry"},
+ returnTypes = "double")
+ public static double ST_Perimeter2D(String geometry) {
+ return Functions.perimeter(GeometrySerde.deserGeoJson(geometry));
+ }
+
+ @UDFAnnotations.ParamMeta(
+ argNames = {"geometry", "use_spheroid"},
+ argTypes = {"Geometry", "boolean"},
+ returnTypes = "double")
+ public static double ST_Perimeter2D(String geometry, boolean use_spheroid) {
+ return Functions.perimeter(GeometrySerde.deserGeoJson(geometry),
use_spheroid);
+ }
+
+ @UDFAnnotations.ParamMeta(
+ argNames = {"geometry", "use_spheroid", "lenient"},
+ argTypes = {"Geometry", "boolean", "boolean"},
+ returnTypes = "double")
+ public static double ST_Perimeter2D(String geometry, boolean use_spheroid,
boolean lenient) {
+ return Functions.perimeter(GeometrySerde.deserGeoJson(geometry),
use_spheroid, lenient);
+ }
+
@UDFAnnotations.ParamMeta(
argNames = {"geometry"},
argTypes = {"Geometry"},
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 371fe41913..3c9fc62450 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
@@ -57,6 +57,7 @@ object Catalog {
function[ST_GeomFromKML](),
function[ST_CoordDim](),
function[ST_Perimeter](),
+ function[ST_Perimeter2D](),
function[ST_Point](),
function[ST_Points](),
function[ST_MakeEnvelope](),
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 0f2a20713f..d90ea0cfac 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
@@ -1015,6 +1015,17 @@ case class ST_Perimeter(inputExpressions:
Seq[Expression])
}
}
+case class ST_Perimeter2D(inputExpressions: Seq[Expression])
+ extends InferredExpression(
+ inferrableFunction3(Functions.perimeter),
+ inferrableFunction2(Functions.perimeter),
+ inferrableFunction1(Functions.perimeter)) {
+
+ protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]) =
{
+ copy(inputExpressions = newChildren)
+ }
+}
+
case class ST_Points(inputExpressions: Seq[Expression])
extends InferredExpression(Functions.points _) {
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 0c332b10b9..f239bacbac 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
@@ -385,6 +385,17 @@ object st_functions extends DataFrameAPI {
def ST_Perimeter(geom: String, use_spheroid: Boolean, lenient: Boolean):
Column =
wrapExpression[ST_Perimeter](geom, use_spheroid, lenient)
+ def ST_Perimeter2D(geom: Column): Column =
wrapExpression[ST_Perimeter2D](geom)
+ def ST_Perimeter2D(geom: String): Column =
wrapExpression[ST_Perimeter2D](geom)
+ def ST_Perimeter2D(geom: Column, use_spheroid: Column): Column =
+ wrapExpression[ST_Perimeter2D](geom, use_spheroid)
+ def ST_Perimeter2D(geom: String, use_spheroid: Boolean): Column =
+ wrapExpression[ST_Perimeter2D](geom, use_spheroid)
+ def ST_Perimeter2D(geom: Column, use_spheroid: Column, lenient: Column):
Column =
+ wrapExpression[ST_Perimeter2D](geom, use_spheroid, lenient)
+ def ST_Perimeter2D(geom: String, use_spheroid: Boolean, lenient: Boolean):
Column =
+ wrapExpression[ST_Perimeter2D](geom, use_spheroid, lenient)
+
def ST_Points(geom: Column): Column = wrapExpression[ST_Points](geom)
def ST_Points(geom: String): Column = wrapExpression[ST_Points](geom)
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 f1ece09481..11de675d53 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
@@ -811,6 +811,25 @@ class dataFrameAPITestScala extends TestBaseScala {
assertEquals(expected, actual)
}
+ it("Passed ST_Perimeter2D") {
+ var baseDf = sparkSession.sql(
+ "SELECT ST_GeomFromWKT('POLYGON((743238 2967416,743238 2967450,743265
2967450,743265.625 2967416,743238 2967416))') AS geom")
+ var actual = baseDf.select(ST_Perimeter2D("geom")).first().get(0)
+ var expected = 122.63074400009504
+ assertEquals(expected, actual)
+
+ baseDf = sparkSession.sql(
+ "SELECT ST_GeomFromWKT('POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))', 4326) AS
geom")
+ actual = baseDf.select(ST_Perimeter2D("geom", use_spheroid =
true)).first().get(0)
+ expected = 443770.91724830196
+ assertEquals(expected, actual)
+
+ actual =
+ baseDf.select(ST_Perimeter2D("geom", use_spheroid = true, lenient =
false)).first().get(0)
+ expected = 443770.91724830196
+ assertEquals(expected, actual)
+ }
+
it("Passed ST_Project") {
val baseDf = sparkSession.sql(
"SELECT ST_GeomFromWKT('POINT(0 0)') as point, ST_MakeEnvelope(0, 1,
2, 0) as poly")
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 90848ebf83..0e352b1e9e 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
@@ -643,6 +643,24 @@ class functionTestScala
assertEquals(expected, actual)
}
+ it("Passed ST_Perimeter2D") {
+ var baseDf = sparkSession.sql(
+ "SELECT ST_GeomFromWKT('POLYGON((743238 2967416,743238 2967450,743265
2967450,743265.625 2967416,743238 2967416))') AS geom")
+ var actual = baseDf.selectExpr("ST_Perimeter2D(geom)").first().get(0)
+ var expected = 122.63074400009504
+ assertEquals(expected, actual)
+
+ baseDf = sparkSession.sql(
+ "SELECT ST_GeomFromWKT('POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))', 4326) AS
geom")
+ actual = baseDf.selectExpr("ST_Perimeter2D(geom, true)").first().get(0)
+ expected = 443770.91724830196
+ assertEquals(expected, actual)
+
+ actual = baseDf.selectExpr("ST_Perimeter2D(geom, true,
false)").first().get(0)
+ expected = 443770.91724830196
+ assertEquals(expected, actual)
+ }
+
it("Passed ST_Points") {
val testtable = sparkSession.sql(