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:21:54 UTC

(sedona) branch SEDONA-596 created (now 60c264fb7)

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

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


      at 60c264fb7 Update versions

This branch includes the following new commits:

     new 8e1d7dc0d [TASK-77] Add ST_SimplifyVW (#185)
     new 60c264fb7 Update versions

The 2 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) 02/02: 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-596
in repository https://gitbox.apache.org/repos/asf/sedona.git

commit 60c264fb742befdfd21259d241a32fc549f7bb5d
Author: Jia Yu <ji...@gmail.com>
AuthorDate: Fri Jun 7 14:21:39 2024 -0700

    Update versions
---
 docs/api/flink/Function.md | 2 +-
 docs/api/sql/Function.md   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/api/flink/Function.md b/docs/api/flink/Function.md
index c3bcce190..3f0a2e13d 100644
--- a/docs/api/flink/Function.md
+++ b/docs/api/flink/Function.md
@@ -3072,7 +3072,7 @@ Introduction: This function simplifies the input geometry by applying the Visval
 
 Format: `ST_SimplifyVW(geom: Geometry, tolerance: Double)`
 
-Since: `vTBD`
+Since: `v1.6.1`
 
 SQL Example
 
diff --git a/docs/api/sql/Function.md b/docs/api/sql/Function.md
index 49e88276c..01893a2c8 100644
--- a/docs/api/sql/Function.md
+++ b/docs/api/sql/Function.md
@@ -3061,7 +3061,7 @@ Introduction: This function simplifies the input geometry by applying the Visval
 
 Format: `ST_SimplifyVW(geom: Geometry, tolerance: Double)`
 
-Since: `vTBD`
+Since: `v1.6.1`
 
 SQL Example
 


(sedona) 01/02: [TASK-77] Add ST_SimplifyVW (#185)

Posted by ji...@apache.org.
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 <46...@users.noreply.github.com>
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)