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 c33b457c83 [SEDONA-726] Fix ST_Force_2D and add ST_Force2D (#1876)
c33b457c83 is described below
commit c33b457c83f60445895c47cd622966e879f7a415
Author: Furqaan Khan <[email protected]>
AuthorDate: Tue Mar 25 15:04:46 2025 -0400
[SEDONA-726] Fix ST_Force_2D and add ST_Force2D (#1876)
---
.../java/org/apache/sedona/common/Functions.java | 2 +-
.../common/utils/GeometryForce2DTransformer.java | 44 +++++++++++++
.../org/apache/sedona/common/FunctionsTest.java | 75 ++++++++++++++++++++++
docs/api/flink/Function.md | 22 ++++++-
docs/api/snowflake/vector-data/Function.md | 26 +++++++-
docs/api/sql/Function.md | 22 ++++++-
.../main/java/org/apache/sedona/flink/Catalog.java | 1 +
.../apache/sedona/flink/expressions/Functions.java | 10 +++
.../java/org/apache/sedona/flink/FunctionTest.java | 13 +++-
python/sedona/sql/st_functions.py | 12 ++++
python/tests/sql/test_dataframe_api.py | 2 +
python/tests/sql/test_function.py | 15 ++++-
.../scala/org/apache/sedona/sql/UDF/Catalog.scala | 1 +
.../sql/sedona_sql/expressions/Functions.scala | 13 ++++
.../sql/sedona_sql/expressions/st_functions.scala | 3 +
15 files changed, 255 insertions(+), 6 deletions(-)
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 c4bcb67086..97e08b7b0f 100644
--- a/common/src/main/java/org/apache/sedona/common/Functions.java
+++ b/common/src/main/java/org/apache/sedona/common/Functions.java
@@ -885,7 +885,7 @@ public class Functions {
}
public static Geometry force2D(Geometry geometry) {
- return GeomUtils.get2dGeom(geometry);
+ return GeometryForce2DTransformer.transform2D(geometry);
}
public static boolean isEmpty(Geometry geometry) {
diff --git
a/common/src/main/java/org/apache/sedona/common/utils/GeometryForce2DTransformer.java
b/common/src/main/java/org/apache/sedona/common/utils/GeometryForce2DTransformer.java
new file mode 100644
index 0000000000..78bc16fa51
--- /dev/null
+++
b/common/src/main/java/org/apache/sedona/common/utils/GeometryForce2DTransformer.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sedona.common.utils;
+
+import org.locationtech.jts.geom.Coordinate;
+import org.locationtech.jts.geom.CoordinateSequence;
+import org.locationtech.jts.geom.Geometry;
+import org.locationtech.jts.geom.util.GeometryTransformer;
+
+public class GeometryForce2DTransformer extends GeometryTransformer {
+
+ @Override
+ protected CoordinateSequence transformCoordinates(CoordinateSequence coords,
Geometry parent) {
+ Coordinate[] newCoords = new Coordinate[coords.size()];
+ for (int i = 0; i < coords.size(); i++) {
+ Coordinate coordinate = coords.getCoordinate(i);
+ newCoords[i] = new Coordinate(coordinate.getX(), coordinate.getY());
+ }
+
+ return createCoordinateSequence(newCoords);
+ }
+
+ public static Geometry transform2D(Geometry geometry) {
+ if (geometry.getCoordinates().length == 0) return geometry;
+ GeometryForce2DTransformer transformer = new GeometryForce2DTransformer();
+ return transformer.transform(geometry);
+ }
+}
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 642efe0216..4819384e70 100644
--- a/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
+++ b/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
@@ -2133,6 +2133,81 @@ public class FunctionsTest extends TestBase {
assertEquals(expectedWKT, actualWKT);
}
+ @Test
+ public void force2D() throws ParseException {
+ Geometry geom =
+ Constructors.geomFromWKT(
+ "POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (3 5, 5 7, 5 3, 3 5), (5
7, 11 5, 5 3, 5 7))",
+ 0);
+ byte[] polyBinary = Functions.asEWKB(geom);
+ Geometry polyFromBinary = Constructors.geomFromWKB(polyBinary);
+ Geometry forcedPoly =
Functions.force2D(Functions.makeValid(polyFromBinary, false));
+ String actual = Functions.asWKT(forcedPoly);
+ String expected =
+ "POLYGON ((0 10, 10 10, 10 5.333333333333333, 5 7, 3 5, 5 3, 10
4.666666666666667, 10 0, 0 0, 0 10))";
+ assertEquals(expected, actual);
+
+ geom = Constructors.geomFromWKT("POINT ZM(1 2 2 5)", 0);
+ actual = Functions.asWKT(Functions.force2D(geom));
+ expected = "POINT (1 2)";
+ assertEquals(expected, actual);
+
+ geom = Constructors.geomFromWKT("MULTIPOINT ZM((1 2 2 5), (2 3 2 5))", 0);
+ actual = Functions.asWKT(Functions.force2D(geom));
+ expected = "MULTIPOINT ((1 2), (2 3))";
+ assertEquals(expected, actual);
+
+ geom = Constructors.geomFromWKT("LINESTRING (1 2 5, 2 3 5, 3 4 5)", 0);
+ actual = Functions.asWKT(Functions.force2D(geom));
+ expected = "LINESTRING (1 2, 2 3, 3 4)";
+ assertEquals(expected, actual);
+
+ // return 2D as is
+ geom =
+ Constructors.geomFromWKT(
+ "MULTILINESTRING ((10 10, 20 20, 30 30), (15 15, 25 25, 35 35))",
0);
+ Geometry actualGeom = Functions.force2D(geom);
+ assertTrue(Predicates.equals(actualGeom, geom));
+
+ geom = Constructors.geomFromWKT("LINEARRING M(30 10 5, 40 40 5, 20 40 5,
10 20 5, 30 10 5)", 0);
+ actual = Functions.asWKT(Functions.force2D(geom));
+ expected = "LINEARRING (30 10, 40 40, 20 40, 10 20, 30 10)";
+ assertEquals(expected, actual);
+
+ geom =
+ Constructors.geomFromWKT(
+ "POLYGON ZM((0 0 0 0, 10 0 0 0, 10 10 0 0, 0 10 0 0, 0 0 0 0), (4
4 0 0, 4 6 0 0, 6 6 0 0, 6 4 0 0, 4 4 0 0))",
+ 0);
+ actual = Functions.asWKT(Functions.force2D(geom));
+ expected = "POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (4 4, 4 6, 6 6, 6 4, 4
4))";
+ assertEquals(expected, actual);
+
+ geom =
+ Constructors.geomFromWKT(
+ "POLYGON ZM((0 0 0 0, 10 0 0 0, 10 10 0 0, 0 0 0 0), (4 4 0 0, 4 6
0 0, 6 6 0 0, 4 4 0 0))",
+ 0);
+ actual = Functions.asWKT(Functions.force2D(geom));
+ expected = "POLYGON ((0 0, 10 0, 10 10, 0 0), (4 4, 4 6, 6 6, 4 4))";
+ assertEquals(expected, actual);
+
+ geom =
+ Constructors.geomFromWKT(
+ "MULTIPOLYGON M(((30 10 5, 40 40 5, 20 40 5, 10 20 5, 30 10 5)),
((15 5 5, 10 20 5, 20 30 5, 15 5 5)))",
+ 0);
+ actual = Functions.asWKT(Functions.force2D(geom));
+ expected = "MULTIPOLYGON (((30 10, 40 40, 20 40, 10 20, 30 10)), ((15 5,
10 20, 20 30, 15 5)))";
+ assertEquals(expected, actual);
+
+ geom =
+ Constructors.geomFromWKT(
+ "GEOMETRYCOLLECTION ZM(POINT ZM(10 10 2 5), LINESTRING ZM(15 15 2
5, 25 25 2 5, 35 35 2 5), POLYGON ZM((30 10 2 5, 40 40 2 5, 20 40 2 5, 10 20 2
5, 30 10 2 5)))",
+ 0);
+ actual = Functions.asWKT(Functions.force2D(geom));
+ expected =
+ "GEOMETRYCOLLECTION (POINT (10 10), LINESTRING (15 15, 25 25, 35 35),
POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10)))";
+ assertEquals(expected, actual);
+ }
+
@Test
public void testForce3DM() throws ParseException {
Geometry geom = Constructors.geomFromWKT("POINT (1 2)", 0);
diff --git a/docs/api/flink/Function.md b/docs/api/flink/Function.md
index 8446bc5a69..d5960a2284 100644
--- a/docs/api/flink/Function.md
+++ b/docs/api/flink/Function.md
@@ -1439,7 +1439,7 @@ POINT (2 1)
## ST_Force_2D
-Introduction: Forces the geometries into a "2-dimensional mode" so that all
output representations will only have the X and Y coordinates
+Introduction: Forces the geometries into a "2-dimensional mode" so that all
output representations will only have the X and Y coordinates. This function is
an alias of [ST_Force2D](#st_force2d).
Format: `ST_Force_2D (A: Geometry)`
@@ -1457,6 +1457,26 @@ Output:
POLYGON((0 0,0 5,5 0,0 0),(1 1,3 1,1 3,1 1))
```
+## ST_Force2D
+
+Introduction: Forces the geometries into a "2-dimensional mode" so that all
output representations will only have the X and Y coordinates. This function is
an alias of [ST_Force_2D](#st_force_2d).
+
+Format: `ST_Force2D (A: Geometry)`
+
+Since: `v1.8.0`
+
+Example:
+
+```sql
+SELECT ST_Force2D(ST_GeomFromText('POLYGON((0 0 2,0 5 2,5 0 2,0 0 2),(1 1 2,3
1 2,1 3 2,1 1 2))'))
+```
+
+Output:
+
+```
+POLYGON((0 0,0 5,5 0,0 0),(1 1,3 1,1 3,1 1))
+```
+
## ST_Force3D
Introduction: Forces the geometry into a 3-dimensional model so that all
output representations will have X, Y and Z coordinates.
diff --git a/docs/api/snowflake/vector-data/Function.md
b/docs/api/snowflake/vector-data/Function.md
index f6b8c447f2..08bfb3b30a 100644
--- a/docs/api/snowflake/vector-data/Function.md
+++ b/docs/api/snowflake/vector-data/Function.md
@@ -1162,7 +1162,7 @@ Output: `POINT (2 1)`
## ST_Force_2D
-Introduction: Forces the geometries into a "2-dimensional mode" so that all
output representations will only have the X and Y coordinates
+Introduction: Forces the geometries into a "2-dimensional mode" so that all
output representations will only have the X and Y coordinates. This function is
an alias of [ST_Force2D](#st_force2d).
Format: `ST_Force_2D (A:geometry)`
@@ -1184,6 +1184,30 @@ Result:
+---------------------------------------------------------------+
```
+## ST_Force2D
+
+Introduction: Forces the geometries into a "2-dimensional mode" so that all
output representations will only have the X and Y coordinates. This function is
an alias of [ST_Force_2D](#st_force_2d).
+
+Format: `ST_Force2D (A:geometry)`
+
+Example:
+
+```sql
+SELECT ST_AsText(
+ ST_Force2D(ST_GeomFromText('POLYGON((0 0 2,0 5 2,5 0 2,0 0 2),(1 1 2,3 1
2,1 3 2,1 1 2))'))
+) AS geom
+```
+
+Result:
+
+```
++---------------------------------------------------------------+
+|geom |
++---------------------------------------------------------------+
+|POLYGON((0 0,0 5,5 0,0 0),(1 1,3 1,1 3,1 1)) |
++---------------------------------------------------------------+
+```
+
## ST_Force3D
Introduction: Forces the geometry into a 3-dimensional model so that all
output representations will have X, Y and Z coordinates.
diff --git a/docs/api/sql/Function.md b/docs/api/sql/Function.md
index d4bda5c44a..0cf40f4f2a 100644
--- a/docs/api/sql/Function.md
+++ b/docs/api/sql/Function.md
@@ -1495,7 +1495,7 @@ POINT (2 1)
## ST_Force_2D
-Introduction: Forces the geometries into a "2-dimensional mode" so that all
output representations will only have the X and Y coordinates
+Introduction: Forces the geometries into a "2-dimensional mode" so that all
output representations will only have the X and Y coordinates. This function is
an alias of [ST_Force2D](#st_force2d).
Format: `ST_Force_2D (A: Geometry)`
@@ -1513,6 +1513,26 @@ Output:
POLYGON((0 0,0 5,5 0,0 0),(1 1,3 1,1 3,1 1))
```
+## ST_Force2D
+
+Introduction: Forces the geometries into a "2-dimensional mode" so that all
output representations will only have the X and Y coordinates. This function is
an alias of [ST_Force_2D](#st_force_2d).
+
+Format: `ST_Force2D (A: Geometry)`
+
+Since: `v1.8.0`
+
+SQL Example
+
+```sql
+SELECT ST_Force2D(ST_GeomFromText('POLYGON((0 0 2,0 5 2,5 0 2,0 0 2),(1 1 2,3
1 2,1 3 2,1 1 2))'))
+```
+
+Output:
+
+```
+POLYGON((0 0,0 5,5 0,0 0),(1 1,3 1,1 3,1 1))
+```
+
## ST_Force3D
Introduction: Forces the geometry into a 3-dimensional model so that all
output representations will have X, Y and Z coordinates.
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 497aaa5fe6..8654e3bf2a 100644
--- a/flink/src/main/java/org/apache/sedona/flink/Catalog.java
+++ b/flink/src/main/java/org/apache/sedona/flink/Catalog.java
@@ -128,6 +128,7 @@ public class Catalog {
new Functions.ST_AsGML(),
new Functions.ST_AsKML(),
new Functions.ST_Force_2D(),
+ new Functions.ST_Force2D(),
new Functions.ST_IsEmpty(),
new Functions.ST_X(),
new Functions.ST_Y(),
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 86562860fe..af90fabbe6 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
@@ -865,6 +865,16 @@ public class Functions {
}
}
+ public static class ST_Force2D extends ScalarFunction {
+ @DataTypeHint(value = "RAW", bridgedTo =
org.locationtech.jts.geom.Geometry.class)
+ public Geometry eval(
+ @DataTypeHint(value = "RAW", bridgedTo =
org.locationtech.jts.geom.Geometry.class)
+ Object o) {
+ Geometry geom = (Geometry) o;
+ return org.apache.sedona.common.Functions.force2D(geom);
+ }
+ }
+
public static class ST_IsEmpty extends ScalarFunction {
@DataTypeHint("Boolean")
public boolean 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 838f39db26..b85a9f0ae5 100644
--- a/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
+++ b/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
@@ -1126,7 +1126,7 @@ public class FunctionTest extends TestBase {
}
@Test
- public void testForce2D() {
+ public void testForce_2D() {
Table polygonTable = createPolygonTable(1);
Table Forced2DTable =
polygonTable.select(
@@ -1136,6 +1136,17 @@ public class FunctionTest extends TestBase {
"POLYGON ((-0.5 -0.5, -0.5 0.5, 0.5 0.5, 0.5 -0.5, -0.5 -0.5))",
result.toString());
}
+ @Test
+ public void testForce2D() {
+ Table polygonTable = createPolygonTable(1);
+ Table Forced2DTable =
+ polygonTable.select(
+ call(Functions.ST_Force2D.class.getSimpleName(),
$(polygonColNames[0])));
+ Geometry result = (Geometry) first(Forced2DTable).getField(0);
+ assertEquals(
+ "POLYGON ((-0.5 -0.5, -0.5 0.5, 0.5 0.5, 0.5 -0.5, -0.5 -0.5))",
result.toString());
+ }
+
@Test
public void testIsEmpty() {
Table polygonTable = createPolygonTable(testDataSize);
diff --git a/python/sedona/sql/st_functions.py
b/python/sedona/sql/st_functions.py
index 684ffa8e93..82bead1db2 100644
--- a/python/sedona/sql/st_functions.py
+++ b/python/sedona/sql/st_functions.py
@@ -654,6 +654,18 @@ def ST_Force_2D(geometry: ColumnOrName) -> Column:
return _call_st_function("ST_Force_2D", geometry)
+@validate_argument_types
+def ST_Force2D(geometry: ColumnOrName) -> Column:
+ """Force the geometry column to only output two dimensional
representations.
+
+ :param geometry: Geometry column to force to be 2D.
+ :type geometry: ColumnOrName
+ :return: Geometry column identical to geometry except with only X and Y
coordinates.
+ :rtype: Column
+ """
+ return _call_st_function("ST_Force2D", geometry)
+
+
@validate_argument_types
def ST_GeneratePoints(
geometry: ColumnOrName,
diff --git a/python/tests/sql/test_dataframe_api.py
b/python/tests/sql/test_dataframe_api.py
index 99d1f17754..22ee40c799 100644
--- a/python/tests/sql/test_dataframe_api.py
+++ b/python/tests/sql/test_dataframe_api.py
@@ -543,6 +543,7 @@ test_configurations = [
),
(stf.ST_FlipCoordinates, ("point",), "point_geom", "", "POINT (1 0)"),
(stf.ST_Force_2D, ("point",), "point_geom", "", "POINT (0 1)"),
+ (stf.ST_Force2D, ("point",), "point_geom", "", "POINT (0 1)"),
(stf.ST_Force3D, ("point", 1.0), "point_geom", "", "POINT Z (0 1 1)"),
(
stf.ST_Force3DM,
@@ -1304,6 +1305,7 @@ wrong_type_configurations = [
(stf.ST_ExteriorRing, (None,)),
(stf.ST_FlipCoordinates, (None,)),
(stf.ST_Force_2D, (None,)),
+ (stf.ST_Force2D, (None,)),
(stf.ST_Force3DM, (None,)),
(stf.ST_Force3DZ, (None,)),
(stf.ST_Force4D, (None,)),
diff --git a/python/tests/sql/test_function.py
b/python/tests/sql/test_function.py
index 96f31e4d94..da9f2bc253 100644
--- a/python/tests/sql/test_function.py
+++ b/python/tests/sql/test_function.py
@@ -2125,7 +2125,7 @@ class TestPredicateJoin(TestBase):
)
assert point.take(1)[0][0] == test[2]
- def test_st_force2d(self):
+ def test_st_force_2d(self):
tests1 = {
"'POINT(0 5)'": "POINT (0 5)",
"'POLYGON((0 0 2, 0 5 2, 5 0 2, 0 0 2), (1 1 2, 3 1 2, 1 3 2, 1 1
2))'": "POLYGON ((0 0, 0 5, 5 0, 0 0), (1 1, 3 1, 1 3, 1 1))",
@@ -2138,6 +2138,19 @@ class TestPredicateJoin(TestBase):
)
assert geom_2d.take(1)[0][0] == expected_geom
+ def test_st_force2d(self):
+ tests1 = {
+ "'POINT(0 5)'": "POINT (0 5)",
+ "'POLYGON((0 0 2, 0 5 2, 5 0 2, 0 0 2), (1 1 2, 3 1 2, 1 3 2, 1 1
2))'": "POLYGON ((0 0, 0 5, 5 0, 0 0), (1 1, 3 1, 1 3, 1 1))",
+ "'LINESTRING(0 5 1, 0 0 1, 0 10 2)'": "LINESTRING (0 5, 0 0, 0
10)",
+ }
+
+ for input_geom, expected_geom in tests1.items():
+ geom_2d = self.spark.sql(
+ "select
ST_AsText(ST_Force2D(ST_GeomFromText({})))".format(input_geom)
+ )
+ assert geom_2d.take(1)[0][0] == expected_geom
+
def test_st_buildarea(self):
tests = {
"'MULTILINESTRING((0 0, 10 0, 10 10, 0 10, 0 0),(10 10, 20 10, 20
20, 10 20, 10 10))'": "MULTIPOLYGON (((0 0, 0 10, 10 10, 10 0, 0 0)), ((10 10,
10 20, 20 20, 20 10, 10 10)))",
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 57fe3893e0..e0e3503012 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
@@ -187,6 +187,7 @@ object Catalog extends AbstractCatalog {
function[ST_PointN](),
function[ST_AsEWKT](),
function[ST_Force_2D](),
+ function[ST_Force2D](),
function[ST_ForcePolygonCW](),
function[ST_ForceRHR](),
function[ST_ZMax](),
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 8fb84b3b61..b594d8a43d 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
@@ -1241,6 +1241,19 @@ case class ST_Force_2D(inputExpressions: Seq[Expression])
}
}
+/*
+ * Forces the geometries into a "2-dimensional mode" so that all output
representations will only have the X and Y coordinates.
+ *
+ * @param inputExpressions
+ */
+case class ST_Force2D(inputExpressions: Seq[Expression])
+ extends InferredExpression(Functions.force2D _) {
+
+ protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]) =
{
+ copy(inputExpressions = newChildren)
+ }
+}
+
/**
* Returns the geometry in EWKT format
*
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 84d555ff64..637579e8c2 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
@@ -218,6 +218,9 @@ object st_functions extends DataFrameAPI {
def ST_Force_2D(geometry: Column): Column =
wrapExpression[ST_Force_2D](geometry)
def ST_Force_2D(geometry: String): Column =
wrapExpression[ST_Force_2D](geometry)
+ def ST_Force2D(geometry: Column): Column =
wrapExpression[ST_Force2D](geometry)
+ def ST_Force2D(geometry: String): Column =
wrapExpression[ST_Force2D](geometry)
+
def ST_GeoHash(geometry: Column, precision: Column): Column =
wrapExpression[ST_GeoHash](geometry, precision)
def ST_GeoHash(geometry: String, precision: Int): Column =