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 07e4987  [SEDONA-90] Create ST_Union function (#592)
07e4987 is described below

commit 07e4987f0ac9aad6a0bbf77098e6539b8872ce02
Author: Magdalena <[email protected]>
AuthorDate: Mon Mar 14 07:40:30 2022 +0100

    [SEDONA-90] Create ST_Union function (#592)
---
 docs/api/sql/Function.md                           | 21 +++++++++++++++++
 python/tests/sql/test_function.py                  | 12 ++++++++++
 .../scala/org/apache/sedona/sql/UDF/Catalog.scala  |  1 +
 .../sql/sedona_sql/expressions/Functions.scala     | 22 ++++++++++++++++++
 .../org/apache/sedona/sql/functionTestScala.scala  | 27 ++++++++++++++++++++++
 5 files changed, 83 insertions(+)

diff --git a/docs/api/sql/Function.md b/docs/api/sql/Function.md
index a9bb5ae..7922fdb 100644
--- a/docs/api/sql/Function.md
+++ b/docs/api/sql/Function.md
@@ -963,4 +963,25 @@ Result:
 
 ```
 MULTIPOLYGON (((-2 -3, -3 -3, -3 3, -2 3, -2 -3)), ((3 -3, 3 3, 4 3, 4 -3, 3 
-3)))
+```
+
+## ST_Union
+
+Introduction: Return the union of geometry A and B
+
+
+Format: `ST_Union (A:geometry, B:geometry)`
+
+Since: `v1.2.0`
+
+Example:
+
+```SQL
+SELECT ST_Union(ST_GeomFromWKT('POLYGON ((-3 -3, 3 -3, 3 3, -3 3, -3 -3))'), 
ST_GeomFromWKT('POLYGON ((1 -2, 5 0, 1 2, 1 -2))'))
+```
+
+Result:
+
+```
+POLYGON ((3 -1, 3 -3, -3 -3, -3 3, 3 3, 3 1, 5 0, 3 -1))
 ```
\ No newline at end of file
diff --git a/python/tests/sql/test_function.py 
b/python/tests/sql/test_function.py
index 83bb2c7..b7ea160 100644
--- a/python/tests/sql/test_function.py
+++ b/python/tests/sql/test_function.py
@@ -318,6 +318,18 @@ class TestPredicateJoin(TestBase):
         diff = self.spark.sql("select ST_SymDifference(a,b) from 
test_sym_diff")
         assert diff.take(1)[0][0].wkt == "POLYGON ((-3 -3, -3 3, 3 3, 3 -3, -3 
-3), (-1 -1, 1 -1, 1 1, -1 1, -1 -1))"
 
+    def test_st_union_part_of_right_overlaps_left(self):
+        test_table = self.spark.sql("select ST_GeomFromWKT('POLYGON ((-3 -3, 3 
-3, 3 3, -3 3, -3 -3))') as a, ST_GeomFromWKT('POLYGON ((-2 1, 2 1, 2 4, -2 4, 
-2 1))') as b")
+        test_table.createOrReplaceTempView("test_union")
+        union = self.spark.sql("select ST_Union(a,b) from test_union")
+        assert union.take(1)[0][0].wkt == "POLYGON ((2 3, 3 3, 3 -3, -3 -3, -3 
3, -2 3, -2 4, 2 4, 2 3))"
+
+    def test_st_union_not_overlaps_left(self):
+        test_table = self.spark.sql("select ST_GeomFromWKT('POLYGON ((-3 -3, 3 
-3, 3 3, -3 3, -3 -3))') as a,ST_GeomFromWKT('POLYGON ((5 -3, 7 -3, 7 -1, 5 -1, 
5 -3))') as b")
+        test_table.createOrReplaceTempView("test_union")
+        union = self.spark.sql("select ST_Union(a,b) from test_union")
+        assert union.take(1)[0][0].wkt == "MULTIPOLYGON (((-3 -3, -3 3, 3 3, 3 
-3, -3 -3)), ((5 -3, 5 -1, 7 -1, 7 -3, 5 -3)))"
+
     def test_st_azimuth(self):
         sample_points = create_sample_points(20)
         sample_pair_points = [[el, sample_points[1]] for el in sample_points]
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 a6926ff..56c38c5 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
@@ -53,6 +53,7 @@ object Catalog {
     ST_Intersection,
     ST_Difference,
     ST_SymDifference,
+    ST_Union,
     ST_IsValid,
     ST_PrecisionReduce,
     ST_Equals,
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 0270016..35309c6 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
@@ -1500,4 +1500,26 @@ case class ST_SymDifference(inputExpressions: 
Seq[Expression])
   protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]) = 
{
     copy(inputExpressions = newChildren)
   }
+}
+
+/**
+ * Return the union of geometry A and B
+ *
+ * @param inputExpressions
+ */
+case class ST_Union(inputExpressions: Seq[Expression])
+  extends BinaryGeometryExpression with CodegenFallback {
+  assert(inputExpressions.length == 2)
+
+  override protected def nullSafeEval(leftGeometry: Geometry, rightGeometry: 
Geometry): Any = {
+    new 
GenericArrayData(GeometrySerializer.serialize(leftGeometry.union(rightGeometry)))
+  }
+
+  override def dataType: DataType = GeometryUDT
+
+  override def children: Seq[Expression] = inputExpressions
+
+  protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]) = 
{
+    copy(inputExpressions = newChildren)
+  }
 }
\ No newline at end of file
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 8d1d8b2..422afcf 100644
--- a/sql/src/test/scala/org/apache/sedona/sql/functionTestScala.scala
+++ b/sql/src/test/scala/org/apache/sedona/sql/functionTestScala.scala
@@ -431,6 +431,31 @@ class functionTestScala extends TestBaseScala with 
Matchers with GeometrySample
       assert(symDiff.first().get(0) == null)
     }
 
+    it("Passed ST_Union - part of right overlaps left") {
+
+      val testtable = sparkSession.sql("select ST_GeomFromWKT('POLYGON ((-3 
-3, 3 -3, 3 3, -3 3, -3 -3))') as a, ST_GeomFromWKT('POLYGON ((-2 1, 2 1, 2 4, 
-2 4, -2 1))') as b")
+      testtable.createOrReplaceTempView("union_table")
+      val union = sparkSession.sql("select ST_Union(a,b) from union_table")
+      
assert(union.take(1)(0).get(0).asInstanceOf[Geometry].toText.equals("POLYGON 
((2 3, 3 3, 3 -3, -3 -3, -3 3, -2 3, -2 4, 2 4, 2 3))"))
+    }
+
+    it("Passed ST_Union - right not overlaps left") {
+
+      val testtable = sparkSession.sql("select ST_GeomFromWKT('POLYGON ((-3 
-3, 3 -3, 3 3, -3 3, -3 -3))') as a,ST_GeomFromWKT('POLYGON ((5 -3, 7 -3, 7 -1, 
5 -1, 5 -3))') as b")
+      testtable.createOrReplaceTempView("union_table")
+      val union = sparkSession.sql("select ST_Union(a,b) from union_table")
+      println(union.take(1)(0).get(0).asInstanceOf[Geometry].toText)
+      
assert(union.take(1)(0).get(0).asInstanceOf[Geometry].toText.equals("MULTIPOLYGON
 (((-3 -3, -3 3, 3 3, 3 -3, -3 -3)), ((5 -3, 5 -1, 7 -1, 7 -3, 5 -3)))"))
+    }
+
+    it("Passed ST_Union - one null") {
+
+      val testtable = sparkSession.sql("select ST_GeomFromWKT('POLYGON ((-3 
-3, 3 -3, 3 3, -3 3, -3 -3))') as a")
+      testtable.createOrReplaceTempView("union_table")
+      val union = sparkSession.sql("select ST_Union(a,null) from union_table")
+      assert(union.first().get(0) == null)
+    }
+
     it("Passed ST_Azimuth") {
 
       val pointDataFrame = samplePoints
@@ -1358,5 +1383,7 @@ class functionTestScala extends TestBaseScala with 
Matchers with GeometrySample
     assert(functionDf.first().get(0) == null)
     functionDf = sparkSession.sql("select ST_SymDifference(null, null)")
     assert(functionDf.first().get(0) == null)
+    functionDf = sparkSession.sql("select ST_Union(null, null)")
+    assert(functionDf.first().get(0) == null)
   }
 }

Reply via email to