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

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

commit 8e1d7dc0d1c6cf2f305ef7ff11f86c834ece83de
Author: Furqaan Khan <[email protected]>
AuthorDate: Tue May 7 02:11:59 2024 -0400

    [TASK-77] Add ST_SimplifyVW (#185)
    
    * feat: Add ST_SimplifyVW
    
    * fix: snowflake test wrong argument
    
    * fix: snowflake test
---
 .../java/org/apache/sedona/common/Functions.java   |  8 ++++++++
 .../org/apache/sedona/common/FunctionsTest.java    | 21 ++++++++++++++++++++
 docs/api/flink/Function.md                         | 23 ++++++++++++++++++++++
 docs/api/snowflake/vector-data/Function.md         | 21 ++++++++++++++++++++
 docs/api/sql/Function.md                           | 23 ++++++++++++++++++++++
 .../main/java/org/apache/sedona/flink/Catalog.java |  1 +
 .../apache/sedona/flink/expressions/Functions.java |  9 +++++++++
 .../java/org/apache/sedona/flink/FunctionTest.java |  8 ++++++++
 python/sedona/sql/st_functions.py                  | 13 ++++++++++++
 python/tests/sql/test_dataframe_api.py             |  3 +++
 python/tests/sql/test_function.py                  |  7 +++++++
 .../sedona/snowflake/snowsql/TestFunctions.java    | 10 ++++++++++
 .../sedona/snowflake/snowsql/TestFunctionsV2.java  | 10 ++++++++++
 .../org/apache/sedona/snowflake/snowsql/UDFs.java  | 10 ++++++++++
 .../apache/sedona/snowflake/snowsql/UDFsV2.java    | 10 ++++++++++
 .../scala/org/apache/sedona/sql/UDF/Catalog.scala  |  1 +
 .../sql/sedona_sql/expressions/Functions.scala     |  8 ++++++++
 .../sql/sedona_sql/expressions/st_functions.scala  |  4 ++++
 .../apache/sedona/sql/dataFrameAPITestScala.scala  |  7 +++++++
 .../org/apache/sedona/sql/functionTestScala.scala  |  8 ++++++++
 20 files changed, 205 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 dcd5fbf6a..c8895442e 100644
--- a/common/src/main/java/org/apache/sedona/common/Functions.java
+++ b/common/src/main/java/org/apache/sedona/common/Functions.java
@@ -44,6 +44,7 @@ import org.locationtech.jts.operation.valid.IsValidOp;
 import org.locationtech.jts.operation.valid.TopologyValidationError;
 import org.locationtech.jts.precision.GeometryPrecisionReducer;
 import org.locationtech.jts.simplify.TopologyPreservingSimplifier;
+import org.locationtech.jts.simplify.VWSimplifier;
 import 
org.locationtech.jts.triangulate.polygon.ConstrainedDelaunayTriangulator;
 import org.wololo.jts2geojson.GeoJSONWriter;
 
@@ -1243,6 +1244,13 @@ public class Functions {
         return TopologyPreservingSimplifier.simplify(geometry, 
distanceTolerance);
     }
 
+    public static Geometry simplifyVW(Geometry geometry, double tolerance) {
+        // JTS squares the tolerance in its implementation, inorder to keep it 
consistent square rooting the input tolerance
+        // source: 
https://github.com/locationtech/jts/blob/7ef2b9d2e6f36ce5e7a787cff57bd18281e50826/modules/core/src/main/java/org/locationtech/jts/simplify/VWLineSimplifier.java#L41
+        tolerance = Math.sqrt(tolerance);
+        return VWSimplifier.simplify(geometry, tolerance);
+    }
+
     public static String geometryType(Geometry geometry) {
         return "ST_" + geometry.getGeometryType();
     }
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 3456fef9e..99e93f151 100644
--- a/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
+++ b/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
@@ -1310,6 +1310,27 @@ public class FunctionsTest extends TestBase {
         assertEquals(expected, e.getMessage());
     }
 
+    @Test
+    public void simplifyVW() throws ParseException {
+        Geometry geom = Constructors.geomFromEWKT("LINESTRING(5 2, 3 8, 6 20, 
7 25, 10 10)");
+        String actual = Functions.simplifyVW(geom, 30).toString();
+        String expected = "LINESTRING (5 2, 7 25, 10 10)";
+        assertEquals(expected, actual);
+
+        actual = Functions.simplifyVW(geom, 10).toString();
+        expected = "LINESTRING (5 2, 3 8, 7 25, 10 10)";
+        assertEquals(expected, actual);
+
+        geom = Constructors.geomFromEWKT("POLYGON((8 25, 28 22, 28 20, 15 11, 
33 3, 56 30, 46 33,46 34, 47 44, 35 36, 45 33, 43 19, 29 21, 29 22,35 26, 24 
39, 8 25))");
+        actual = Functions.simplifyVW(geom, 10).toString();
+        expected = "POLYGON ((8 25, 28 22, 28 20, 15 11, 33 3, 56 30, 46 33, 
47 44, 35 36, 45 33, 43 19, 29 21, 35 26, 24 39, 8 25))";
+        assertEquals(expected, actual);
+
+        actual = Functions.simplifyVW(geom, 80).toString();
+        expected = "POLYGON ((8 25, 28 22, 15 11, 33 3, 56 30, 47 44, 43 19, 
24 39, 8 25))";
+        assertEquals(expected, actual);
+    }
+
     @Test
     public void force3DObject2D() {
         int expectedDims = 3;
diff --git a/docs/api/flink/Function.md b/docs/api/flink/Function.md
index b3ea497ab..c3bcce190 100644
--- a/docs/api/flink/Function.md
+++ b/docs/api/flink/Function.md
@@ -3063,6 +3063,29 @@ Output:
 POLYGON ((8 25, 28 22, 15 11, 33 3, 56 30, 47 44, 35 36, 43 19, 24 39, 8 25))
 ```
 
+## ST_SimplifyVW
+
+Introduction: This function simplifies the input geometry by applying the 
Visvalingam-Whyatt algorithm.
+
+!!!Note
+    The simplification may not preserve topology, potentially producing 
invalid geometries. Use 
[ST_SimplifyPreserveTopology](#st_simplifypreservetopology) to retain valid 
topology after simplification.
+
+Format: `ST_SimplifyVW(geom: Geometry, tolerance: Double)`
+
+Since: `vTBD`
+
+SQL Example
+
+```sql
+SELECT ST_SimplifyVW(ST_GeomFromWKT('POLYGON((8 25, 28 22, 28 20, 15 11, 33 3, 
56 30, 46 33,46 34, 47 44, 35 36, 45 33, 43 19, 29 21, 29 22,35 26, 24 39, 8 
25))'), 80)
+```
+
+Output:
+
+```
+POLYGON ((8 25, 28 22, 15 11, 33 3, 56 30, 47 44, 43 19, 24 39, 8 25))
+```
+
 ## ST_Snap
 
 Introduction: Snaps the vertices and segments of the `input` geometry to 
`reference` geometry within the specified `tolerance` distance. The `tolerance` 
parameter controls the maximum snap distance.
diff --git a/docs/api/snowflake/vector-data/Function.md 
b/docs/api/snowflake/vector-data/Function.md
index 3674661cc..419a1a907 100644
--- a/docs/api/snowflake/vector-data/Function.md
+++ b/docs/api/snowflake/vector-data/Function.md
@@ -2266,6 +2266,27 @@ SELECT 
ST_SimplifyPreserveTopology(polygondf.countyshape, 10.0)
 FROM polygondf
 ```
 
+## ST_SimplifyVW
+
+Introduction: This function simplifies the input geometry by applying the 
Visvalingam-Whyatt algorithm.
+
+!!!Note
+    The simplification may not preserve topology, potentially producing 
invalid geometries. Use 
[ST_SimplifyPreserveTopology](#st_simplifypreservetopology) to retain valid 
topology after simplification.
+
+Format: `ST_SimplifyVW(geom: Geometry, tolerance: Double)`
+
+SQL Example
+
+```sql
+SELECT ST_SimplifyVW(ST_GeomFromWKT('POLYGON((8 25, 28 22, 28 20, 15 11, 33 3, 
56 30, 46 33,46 34, 47 44, 35 36, 45 33, 43 19, 29 21, 29 22,35 26, 24 39, 8 
25))'), 80)
+```
+
+Output:
+
+```
+POLYGON ((8 25, 28 22, 15 11, 33 3, 56 30, 47 44, 43 19, 24 39, 8 25))
+```
+
 ## ST_Snap
 
 Introduction: Snaps the vertices and segments of the `input` geometry to 
`reference` geometry within the specified `tolerance` distance. The `tolerance` 
parameter controls the maximum snap distance.
diff --git a/docs/api/sql/Function.md b/docs/api/sql/Function.md
index 0c5dcf31d..49e88276c 100644
--- a/docs/api/sql/Function.md
+++ b/docs/api/sql/Function.md
@@ -3052,6 +3052,29 @@ Output:
 POLYGON ((8 25, 28 22, 15 11, 33 3, 56 30, 47 44, 35 36, 43 19, 24 39, 8 25))
 ```
 
+## ST_SimplifyVW
+
+Introduction: This function simplifies the input geometry by applying the 
Visvalingam-Whyatt algorithm.
+
+!!!Note
+    The simplification may not preserve topology, potentially producing 
invalid geometries. Use 
[ST_SimplifyPreserveTopology](#st_simplifypreservetopology) to retain valid 
topology after simplification.
+
+Format: `ST_SimplifyVW(geom: Geometry, tolerance: Double)`
+
+Since: `vTBD`
+
+SQL Example
+
+```sql
+SELECT ST_SimplifyVW(ST_GeomFromWKT('POLYGON((8 25, 28 22, 28 20, 15 11, 33 3, 
56 30, 46 33,46 34, 47 44, 35 36, 45 33, 43 19, 29 21, 29 22,35 26, 24 39, 8 
25))'), 80)
+```
+
+Output:
+
+```
+POLYGON ((8 25, 28 22, 15 11, 33 3, 56 30, 47 44, 43 19, 24 39, 8 25))
+```
+
 ## ST_Snap
 
 Introduction: Snaps the vertices and segments of the `input` geometry to 
`reference` geometry within the specified `tolerance` distance. The `tolerance` 
parameter controls the maximum snap distance.
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 8e60a8483..d9f05ef1f 100644
--- a/flink/src/main/java/org/apache/sedona/flink/Catalog.java
+++ b/flink/src/main/java/org/apache/sedona/flink/Catalog.java
@@ -153,6 +153,7 @@ public class Catalog {
                 new Functions.ST_StartPoint(),
                 new Functions.ST_ShiftLongitude(),
                 new Functions.ST_SimplifyPreserveTopology(),
+                new Functions.ST_SimplifyVW(),
                 new Functions.ST_Split(),
                 new Functions.ST_Subdivide(),
                 new Functions.ST_SymDifference(),
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 cad1be4bc..86feb05f5 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
@@ -1037,6 +1037,15 @@ public class Functions {
         }
     }
 
+    public static class ST_SimplifyVW 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,
+                             @DataTypeHint("Double") Double distanceTolerance) 
{
+            Geometry geom = (Geometry) o;
+            return org.apache.sedona.common.Functions.simplifyVW(geom, 
distanceTolerance);
+        }
+    }
+
     public static class ST_Subdivide 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 8afd16012..c19e8177e 100644
--- a/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
+++ b/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
@@ -1152,6 +1152,14 @@ public class FunctionTest extends TestBase{
         assertEquals("POLYGON ((0 0, 1 0, 1 1, 0 0))", result.toString());
     }
 
+    @Test
+    public void testSimplifyVW() {
+        Table table = tableEnv.sqlQuery("SELECT ST_GeomFromWKT('POLYGON ((0 0, 
1 0, 1 0.9, 1 1, 0 0))') AS geom");
+        table = 
table.select(call(Functions.ST_SimplifyPreserveTopology.class.getSimpleName(), 
$("geom"), 2));
+        Geometry result = (Geometry) first(table).getField(0);
+        assertEquals("POLYGON ((0 0, 1 0, 1 1, 0 0))", result.toString());
+    }
+
     @Test
     public void testSplit() {
         Table pointTable = tableEnv.sqlQuery("SELECT 
ST_Split(ST_GeomFromWKT('LINESTRING (0 0, 1.5 1.5, 2 2)'), 
ST_GeomFromWKT('MULTIPOINT (0.5 0.5, 1 1)'))");
diff --git a/python/sedona/sql/st_functions.py 
b/python/sedona/sql/st_functions.py
index f12d6a9f2..33470ef41 100644
--- a/python/sedona/sql/st_functions.py
+++ b/python/sedona/sql/st_functions.py
@@ -1373,6 +1373,19 @@ def ST_SimplifyPreserveTopology(geometry: ColumnOrName, 
distance_tolerance: Colu
     """
     return _call_st_function("ST_SimplifyPreserveTopology", (geometry, 
distance_tolerance))
 
+@validate_argument_types
+def ST_SimplifyVW(geometry: ColumnOrName, distance_tolerance: 
ColumnOrNameOrNumber) -> Column:
+    """Simplify a geometry using Visvalingam-Whyatt algorithm within a 
specified tolerance while preserving topological relationships.
+
+    :param geometry: Geometry column to simplify.
+    :type geometry: ColumnOrName
+    :param distance_tolerance: Tolerance for merging points together to 
simplify the geometry as either a number or numeric column.
+    :type distance_tolerance: ColumnOrNameOrNumber
+    :return: Simplified geometry as a geometry column.
+    :rtype: Column
+    """
+    return _call_st_function("ST_SimplifyVW", (geometry, distance_tolerance))
+
 
 @validate_argument_types
 def ST_Split(input: ColumnOrName, blade: ColumnOrName) -> Column:
diff --git a/python/tests/sql/test_dataframe_api.py 
b/python/tests/sql/test_dataframe_api.py
index 6de3a7699..a76cd3885 100644
--- a/python/tests/sql/test_dataframe_api.py
+++ b/python/tests/sql/test_dataframe_api.py
@@ -191,6 +191,7 @@ test_configurations = [
     (stf.ST_SetSRID, ("point", 3021), "point_geom", "ST_SRID(geom)", 3021),
     (stf.ST_ShiftLongitude, ("geom",), "triangle_geom", "", "POLYGON ((0 0, 1 
0, 1 1, 0 0))"),
     (stf.ST_SimplifyPreserveTopology, ("geom", 0.2), "0.9_poly", "", "POLYGON 
((0 0, 1 0, 1 1, 0 0))"),
+    (stf.ST_SimplifyVW, ("geom", 0.1), "0.9_poly", "", "POLYGON ((0 0, 1 0, 1 
1, 0 0))"),
     (stf.ST_Snap, ("poly", "line", 2.525), "poly_and_line", "" ,"POLYGON ((2.6 
12.5, 2.6 20, 12.6 20, 12.6 12.5, 10.1 10, 2.6 12.5))"),
     (stf.ST_Split, ("line", "points"), "multipoint_splitting_line", "", 
"MULTILINESTRING ((0 0, 0.5 0.5), (0.5 0.5, 1 1), (1 1, 1.5 1.5, 2 2))"),
     (stf.ST_SRID, ("point",), "point_geom", "", 0),
@@ -392,6 +393,8 @@ wrong_type_configurations = [
     (stf.ST_ShiftLongitude, (None,)),
     (stf.ST_SimplifyPreserveTopology, (None, 0.2)),
     (stf.ST_SimplifyPreserveTopology, ("", None)),
+    (stf.ST_SimplifyVW, (None, 2)),
+    (stf.ST_SimplifyVW, ("", None)),
     (stf.ST_Snap, (None, None, 12)),
     (stf.ST_SRID, (None,)),
     (stf.ST_StartPoint, (None,)),
diff --git a/python/tests/sql/test_function.py 
b/python/tests/sql/test_function.py
index 5d08c5de4..bbc7d19cc 100644
--- a/python/tests/sql/test_function.py
+++ b/python/tests/sql/test_function.py
@@ -896,6 +896,13 @@ class TestPredicateJoin(TestBase):
         actual = self.spark.sql("SELECT ST_IsPolygonCW(ST_GeomFromWKT('POLYGON 
((20 35, 45 20, 30 5, 10 10, 10 30, 20 35), (30 20, 20 25, 20 15, 30 
20))'))").take(1)[0][0]
         assert actual
 
+    def test_st_simplify_vw(self):
+        basedf = self.spark.sql("SELECT ST_GeomFromWKT('LINESTRING(5 2, 3 8, 6 
20, 7 25, 10 10)') as geom")
+        actual = basedf.selectExpr("ST_SimplifyVW(geom, 30)").take(1)[0][0].wkt
+        expected = "LINESTRING (5 2, 7 25, 10 10)"
+        assert expected == actual
+
+
     def test_st_is_ring(self):
         result_and_expected = [
             [self.calculate_st_is_ring("LINESTRING(0 0, 0 1, 1 0, 1 1, 0 0)"), 
False],
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 94d8ac97a..04dea7d12 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
@@ -864,6 +864,16 @@ public class TestFunctions extends TestBase {
                 "POLYGON ((8 25, 28 22, 15 11, 33 3, 56 30, 47 44, 35 36, 43 
19, 24 39, 8 25))"
         );
     }
+
+    @Test
+    public void test_ST_SimplifyVW() {
+        registerUDF("ST_SimplifyVW", byte[].class, double.class);
+        verifySqlSingleRes(
+                "select 
sedona.ST_AsText(sedona.ST_SimplifyVW(sedona.ST_GeomFromText('POLYGON((8 25, 28 
22, 28 20, 15 11, 33 3, 56 30, 46 33,46 34, 47 44, 35 36, 45 33, 43 19, 29 21, 
29 22,35 26, 24 39, 8 25))'), 10))",
+                "POLYGON ((8 25, 28 22, 28 20, 15 11, 33 3, 56 30, 46 33, 47 
44, 35 36, 45 33, 43 19, 29 21, 35 26, 24 39, 8 25))"
+        );
+    }
+
     @Test
     public void test_ST_Split() {
         registerUDF("ST_Split", byte[].class, 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 cc998e835..bb58dc103 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
@@ -827,6 +827,16 @@ public class TestFunctionsV2
                 "POLYGON((8 25,28 22,15 11,33 3,56 30,47 44,35 36,43 19,24 
39,8 25))"
         );
     }
+
+    @Test
+    public void test_ST_SimplifyVW() {
+        registerUDFV2("ST_SimplifyVW", String.class, double.class);
+        verifySqlSingleRes(
+                "select 
ST_AsText(sedona.ST_SimplifyVW(ST_GeometryFromWKT('POLYGON((8 25, 28 22, 28 20, 
15 11, 33 3, 56 30, 46 33,46 34, 47 44, 35 36, 45 33, 43 19, 29 21, 29 22,35 
26, 24 39, 8 25))'), 10))",
+                "POLYGON((8 25,28 22,28 20,15 11,33 3,56 30,46 33,47 44,35 
36,45 33,43 19,29 21,35 26,24 39,8 25))"
+        );
+    }
+
     @Test
     public void test_ST_Split() {
         registerUDFV2("ST_Split", String.class, 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 ff044c546..f8e8194b5 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
@@ -1226,6 +1226,16 @@ public class UDFs {
         );
     }
 
+    @UDFAnnotations.ParamMeta(argNames = {"geometry", "distanceTolerance"})
+    public static byte[] ST_SimplifyVW(byte[] geometry, double 
distanceTolerance) {
+        return GeometrySerde.serialize(
+                Functions.simplifyVW(
+                        GeometrySerde.deserialize(geometry),
+                        distanceTolerance
+                )
+        );
+    }
+
     @UDFAnnotations.ParamMeta(argNames = {"input", "blade"})
     public static byte[] ST_Split(byte[] input, byte[] blade) {
         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 fbb4d2879..faa075f95 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
@@ -984,6 +984,16 @@ public class UDFsV2
         );
     }
 
+    @UDFAnnotations.ParamMeta(argNames = {"geometry", "distanceTolerance"}, 
argTypes = {"Geometry", "double"}, returnTypes = "Geometry")
+    public static String ST_SimplifyVW(String geometry, double 
distanceTolerance) {
+        return GeometrySerde.serGeoJson(
+                Functions.simplifyVW(
+                        GeometrySerde.deserGeoJson(geometry),
+                        distanceTolerance
+                )
+        );
+    }
+
     @UDFAnnotations.ParamMeta(argNames = {"input", "blade"}, argTypes = 
{"Geometry", "Geometry"}, returnTypes = "Geometry")
     public static String ST_Split(String input, String blade) {
         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 bbf06b75e..8ef7ea486 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
@@ -106,6 +106,7 @@ object Catalog {
     function[ST_AsHEXEWKB](),
     function[ST_AsGML](),
     function[ST_AsKML](),
+    function[ST_SimplifyVW](),
     function[ST_SRID](),
     function[ST_SetSRID](),
     function[ST_GeometryType](),
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 8d5b67bdf..708edd538 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
@@ -346,6 +346,14 @@ case class ST_ReducePrecision(inputExpressions: 
Seq[Expression])
   }
 }
 
+case class ST_SimplifyVW(inputExpressions: Seq[Expression])
+  extends InferredExpression(Functions.simplifyVW _) {
+
+  protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]) = 
{
+    copy(inputExpressions = newChildren)
+  }
+}
+
 case class ST_AsText(inputExpressions: Seq[Expression])
   extends InferredExpression(Functions.asWKT _) {
 
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 6550fe575..67b342162 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
@@ -360,6 +360,10 @@ object st_functions extends DataFrameAPI {
   def ST_Transform(geometry: String, targetCRS: String): Column = 
wrapExpression[ST_Transform](geometry, targetCRS)
   def ST_Transform(geometry: Column, targetCRS: Column): Column = 
wrapExpression[ST_Transform](geometry, targetCRS)
 
+  def ST_SimplifyVW(geometry: Column, distanceTolerance: Column): Column = 
wrapExpression[ST_SimplifyVW](geometry, distanceTolerance)
+  def ST_SimplifyVW(geometry: String, distanceTolerance: Double): Column = 
wrapExpression[ST_SimplifyVW](geometry, distanceTolerance)
+
+
   def ST_Union(a: Column, b: Column): Column = wrapExpression[ST_Union](a, b)
   def ST_Union(a: String, b: String): Column = wrapExpression[ST_Union](a, b)
   def ST_Union(geoms: Column): Column = wrapExpression[ST_Union](geoms)
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 08e0a6d0e..a62b13ea7 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
@@ -696,6 +696,13 @@ class dataFrameAPITestScala extends TestBaseScala {
       assert(actualResult == expectedResult)
     }
 
+    it("Passed ST_SimplifyVW") {
+      val baseDf = sparkSession.sql("SELECT ST_GeomFromWKT('LINESTRING(5 2, 3 
8, 6 20, 7 25, 10 10)') AS geom")
+      val actual = baseDf.select(ST_SimplifyVW("geom", 
30)).first().get(0).asInstanceOf[Geometry].toText
+      val expected = "LINESTRING (5 2, 7 25, 10 10)"
+      assertEquals(expected, actual)
+    }
+
     it("Passed ST_GeometryType") {
       val pointDf = sparkSession.sql("SELECT ST_Point(0.0, 0.0) AS geom")
       val df = pointDf.select(ST_GeometryType("geom"))
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 174af005d..cb1082b02 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
@@ -655,6 +655,14 @@ class functionTestScala extends TestBaseScala with 
Matchers with GeometrySample
       assert(Hex.encodeHexString(df.first().get(0).asInstanceOf[Array[Byte]]) 
== s)
     }
 
+    it("Passed ST_SimplifyVW") {
+      val baseDf = sparkSession.sql("SELECT ST_GeomFromWKT('LINESTRING(5 2, 3 
8, 6 20, 7 25, 10 10)') AS geom")
+      val actual = baseDf.selectExpr("ST_SimplifyVW(geom, 
30)").first().get(0).asInstanceOf[Geometry].toText
+      val expected = "LINESTRING (5 2, 7 25, 10 10)"
+      assertEquals(expected, actual)
+    }
+
+
     it("Passed ST_NPoints") {
       var test = sparkSession.sql("SELECT 
ST_NPoints(ST_GeomFromText('LINESTRING(77.29 29.07,77.42 29.26,77.27 
29.31,77.29 29.07)'))")
       assert(test.take(1)(0).get(0).asInstanceOf[Int] == 4)

Reply via email to