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 2022/09/17 00:08:48 UTC

[incubator-sedona] branch master updated: [SEDONA-168] Add ST_Normalize to Apache Sedona (#688)

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/incubator-sedona.git


The following commit(s) were added to refs/heads/master by this push:
     new 65080422 [SEDONA-168] Add ST_Normalize to Apache Sedona (#688)
65080422 is described below

commit 65080422b6256a0f12cc74347ac2ed531d26a4f6
Author: Kengo Seki <se...@apache.org>
AuthorDate: Sat Sep 17 09:08:43 2022 +0900

    [SEDONA-168] Add ST_Normalize to Apache Sedona (#688)
---
 .../java/org/apache/sedona/common/Functions.java   |  5 +++++
 docs/api/flink/Function.md                         | 26 ++++++++++++++++++++++
 docs/api/sql/Function.md                           | 26 ++++++++++++++++++++++
 .../main/java/org/apache/sedona/flink/Catalog.java |  3 ++-
 .../apache/sedona/flink/expressions/Functions.java |  8 +++++++
 .../java/org/apache/sedona/flink/FunctionTest.java |  8 +++++++
 .../scala/org/apache/sedona/sql/UDF/Catalog.scala  |  1 +
 .../sql/sedona_sql/expressions/Functions.scala     | 13 +++++++++++
 .../org/apache/sedona/sql/functionTestScala.scala  |  7 ++++++
 9 files changed, 96 insertions(+), 1 deletion(-)

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 d3e6bcc3..3a1b49cc 100644
--- a/common/src/main/java/org/apache/sedona/common/Functions.java
+++ b/common/src/main/java/org/apache/sedona/common/Functions.java
@@ -78,6 +78,11 @@ public class Functions {
         return geometry.getLength();
     }
 
+    public static Geometry normalize(Geometry geometry) {
+        geometry.normalize();
+        return geometry;
+    }
+
     public static Double x(Geometry geometry) {
         if (geometry instanceof Point) {
             return geometry.getCoordinate().x;
diff --git a/docs/api/flink/Function.md b/docs/api/flink/Function.md
index b21c0bba..defff6ea 100644
--- a/docs/api/flink/Function.md
+++ b/docs/api/flink/Function.md
@@ -431,6 +431,32 @@ SELECT ST_Length(polygondf.countyshape)
 FROM polygondf
 ```
 
+## ST_Normalize
+
+Introduction: Returns the input geometry in its normalized form.
+
+Format
+
+`ST_Normalize(geom: geometry)`
+
+Since: `v1.3.0`
+
+Example:
+
+```SQL
+SELECT ST_AsEWKT(ST_Normalize(ST_GeomFromWKT('POLYGON((0 1, 1 1, 1 0, 0 0, 0 1))'))) AS geom
+```
+
+Result:
+
+```
++-----------------------------------+
+|geom                               |
++-----------------------------------+
+|POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))|
++-----------------------------------+
+```
+
 ## ST_NPoints
 
 Introduction: Returns the number of points of the geometry
diff --git a/docs/api/sql/Function.md b/docs/api/sql/Function.md
index 426a47a3..a3331b5c 100644
--- a/docs/api/sql/Function.md
+++ b/docs/api/sql/Function.md
@@ -855,6 +855,32 @@ Result:
 +---------------------------------------------------------------+
 ```
 
+## ST_Normalize
+
+Introduction: Returns the input geometry in its normalized form.
+
+Format
+
+`ST_Normalize(geom: geometry)`
+
+Since: `v1.3.0`
+
+Example:
+
+```SQL
+SELECT ST_AsEWKT(ST_Normalize(ST_GeomFromWKT('POLYGON((0 1, 1 1, 1 0, 0 0, 0 1))'))) AS geom
+```
+
+Result:
+
+```
++-----------------------------------+
+|geom                               |
++-----------------------------------+
+|POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))|
++-----------------------------------+
+```
+
 ## ST_NPoints
 
 Introduction: Return points of the geometry
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 7b246f44..163dc0e1 100644
--- a/flink/src/main/java/org/apache/sedona/flink/Catalog.java
+++ b/flink/src/main/java/org/apache/sedona/flink/Catalog.java
@@ -76,7 +76,8 @@ public class Catalog {
                 new Functions.ST_IsClosed(),
                 new Functions.ST_IsRing(),
                 new Functions.ST_IsSimple(),
-                new Functions.ST_IsValid()
+                new Functions.ST_IsValid(),
+                new Functions.ST_Normalize()
         };
     }
 
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 a7965446..7a9c228d 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
@@ -372,4 +372,12 @@ public class Functions {
             return org.apache.sedona.common.Functions.isValid(geom);
         }
     }
+
+    public static class ST_Normalize 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.normalize(geom);
+        }
+    }
 }
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 a7f44d14..24d11dcc 100644
--- a/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
+++ b/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
@@ -422,4 +422,12 @@ public class FunctionTest extends TestBase{
         polygonTable = polygonTable.select(call(Functions.ST_IsValid.class.getSimpleName(), $(polygonColNames[0])));
         assertTrue((boolean) first(polygonTable).getField(0));
     }
+
+    @Test
+    public void testNormalize() {
+        Table polygonTable = tableEnv.sqlQuery("SELECT ST_GeomFromText('POLYGON((0 1, 1 1, 1 0, 0 0, 0 1))') AS polygon");
+        polygonTable = polygonTable.select(call(Functions.ST_Normalize.class.getSimpleName(), $("polygon")));
+        Geometry result = (Geometry) first(polygonTable).getField(0);
+        assertEquals("POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))", result.toString());
+    }
 }
diff --git a/sql/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala b/sql/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala
index 3437c45b..735a71e9 100644
--- a/sql/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala
+++ b/sql/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala
@@ -120,6 +120,7 @@ object Catalog {
     ST_BuildArea,
     ST_OrderingEquals,
     ST_CollectionExtract,
+    ST_Normalize,
     // Expression for rasters
     RS_NormalizedDifference,
     RS_Mean,
diff --git a/sql/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala b/sql/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala
index 9d7da6d8..aec70692 100644
--- a/sql/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala
+++ b/sql/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala
@@ -1305,3 +1305,16 @@ case class ST_BuildArea(inputExpressions: Seq[Expression])
     copy(inputExpressions = newChildren)
   }
 }
+
+/**
+ * Returns the input geometry in its normalized form.
+ *
+ * @param inputExpressions
+ */
+case class ST_Normalize(inputExpressions: Seq[Expression])
+  extends InferredUnaryExpression(Functions.normalize) {
+
+  protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]): Expression = {
+    copy(inputExpressions = newChildren)
+  }
+}
diff --git a/sql/src/test/scala/org/apache/sedona/sql/functionTestScala.scala b/sql/src/test/scala/org/apache/sedona/sql/functionTestScala.scala
index 42389c70..ea2fcc07 100644
--- a/sql/src/test/scala/org/apache/sedona/sql/functionTestScala.scala
+++ b/sql/src/test/scala/org/apache/sedona/sql/functionTestScala.scala
@@ -1601,6 +1601,8 @@ class functionTestScala extends TestBaseScala with Matchers with GeometrySample
     assert(functionDf.first().get(0) == null)
     functionDf = sparkSession.sql("select ST_BuildArea(null)")
     assert(functionDf.first().get(0) == null)
+    functionDf = sparkSession.sql("select ST_Normalize(null)")
+    assert(functionDf.first().get(0) == null)
   }
 
   it ("Should pass St_CollectionExtract") {
@@ -1615,4 +1617,9 @@ class functionTestScala extends TestBaseScala with Matchers with GeometrySample
     assert(df.selectExpr("ST_AsText(ST_CollectionExtract(geom, 2))").collect().head.get(0) == "MULTILINESTRING EMPTY")
     assert(df.selectExpr("ST_AsText(ST_CollectionExtract(geom))").collect().head.get(0) == "MULTIPOINT ((40 10), (40 10))")
   }
+
+  it("Should pass ST_Normalize") {
+    val df = sparkSession.sql("SELECT ST_AsEWKT(ST_Normalize(ST_GeomFromWKT('POLYGON((0 1, 1 1, 1 0, 0 0, 0 1))')))")
+    assert(df.first().get(0).asInstanceOf[String] == "POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))")
+  }
 }
\ No newline at end of file