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/05 18:34:04 UTC
[incubator-sedona] branch master updated: [SEDONA-159] Add Nth accessor functions to the Flink API (#679)
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 0083d2c3 [SEDONA-159] Add Nth accessor functions to the Flink API (#679)
0083d2c3 is described below
commit 0083d2c3a9c3443013c9de0dca1e6e368196294f
Author: Kengo Seki <se...@apache.org>
AuthorDate: Tue Sep 6 03:33:59 2022 +0900
[SEDONA-159] Add Nth accessor functions to the Flink API (#679)
---
.../java/org/apache/sedona/common/Functions.java | 17 ++++++++
docs/api/flink/Function.md | 30 ++++++++++++++
.../main/java/org/apache/sedona/flink/Catalog.java | 2 +
.../apache/sedona/flink/expressions/Functions.java | 16 ++++++++
.../java/org/apache/sedona/flink/FunctionTest.java | 16 ++++++++
.../sql/sedona_sql/expressions/Functions.scala | 48 +---------------------
6 files changed, 83 insertions(+), 46 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 c6714c75..11498f99 100644
--- a/common/src/main/java/org/apache/sedona/common/Functions.java
+++ b/common/src/main/java/org/apache/sedona/common/Functions.java
@@ -157,6 +157,23 @@ public class Functions {
return geometry.reverse();
}
+ public static Geometry geometryN(Geometry geometry, int n) {
+ if (n < geometry.getNumGeometries()) {
+ return geometry.getGeometryN(n);
+ }
+ return null;
+ }
+
+ public static Geometry interiorRingN(Geometry geometry, int n) {
+ if (geometry instanceof Polygon) {
+ Polygon polygon = (Polygon) geometry;
+ if (n < polygon.getNumInteriorRing()) {
+ return polygon.getInteriorRingN(n);
+ }
+ }
+ return null;
+ }
+
public static Geometry pointN(Geometry geometry, int n) {
if(!(geometry instanceof LineString)) {
return null;
diff --git a/docs/api/flink/Function.md b/docs/api/flink/Function.md
index 53b4925c..760721cc 100644
--- a/docs/api/flink/Function.md
+++ b/docs/api/flink/Function.md
@@ -281,6 +281,36 @@ Result:
+-----------------------------+
```
+## ST_GeometryN
+
+Introduction: Return the 0-based Nth geometry if the geometry is a GEOMETRYCOLLECTION, (MULTI)POINT, (MULTI)LINESTRING, MULTICURVE or (MULTI)POLYGON. Otherwise, return null
+
+Format: `ST_GeometryN(geom: geometry, n: Int)`
+
+Since: `v1.3.0`
+
+Example:
+```SQL
+SELECT ST_GeometryN(ST_GeomFromText('MULTIPOINT((1 2), (3 4), (5 6), (8 9))'), 1)
+```
+
+Output: `POINT (3 4)`
+
+## ST_InteriorRingN
+
+Introduction: Returns the Nth interior linestring ring of the polygon geometry. Returns NULL if the geometry is not a polygon or the given N is out of range
+
+Format: `ST_InteriorRingN(geom: geometry, n: Int)`
+
+Since: `v1.3.0`
+
+Example:
+```SQL
+SELECT ST_InteriorRingN(ST_GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0), (1 1, 2 1, 2 2, 1 2, 1 1), (1 3, 2 3, 2 4, 1 4, 1 3), (3 3, 4 3, 4 4, 3 4, 3 3))'), 0)
+```
+
+Output: `LINEARRING (1 1, 2 1, 2 2, 1 2, 1 1)`
+
## ST_IsClosed
Introduction: RETURNS true if the LINESTRING start and end point are the same.
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 f4787411..97244865 100644
--- a/flink/src/main/java/org/apache/sedona/flink/Catalog.java
+++ b/flink/src/main/java/org/apache/sedona/flink/Catalog.java
@@ -45,6 +45,8 @@ public class Catalog {
new Functions.ST_GeoHash(),
new Functions.ST_PointOnSurface(),
new Functions.ST_Reverse(),
+ new Functions.ST_GeometryN(),
+ new Functions.ST_InteriorRingN(),
new Functions.ST_PointN(),
new Functions.ST_ExteriorRing(),
new Functions.ST_AsEWKT(),
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 33f890d4..e11ba35e 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
@@ -133,6 +133,22 @@ public class Functions {
}
}
+ public static class ST_GeometryN 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, int n) {
+ Geometry geom = (Geometry) o;
+ return org.apache.sedona.common.Functions.geometryN(geom, n);
+ }
+ }
+
+ public static class ST_InteriorRingN 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, int n) {
+ Geometry geom = (Geometry) o;
+ return org.apache.sedona.common.Functions.interiorRingN(geom, n);
+ }
+ }
+
public static class ST_PointN 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, int n) {
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 a5994e5f..bd3a8d24 100644
--- a/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
+++ b/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
@@ -144,6 +144,22 @@ public class FunctionTest extends TestBase{
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 testGeometryN() {
+ Table collectionTable = tableEnv.sqlQuery("SELECT ST_GeomFromWKT('GEOMETRYCOLLECTION(POINT(10 10), POINT(30 30), LINESTRING(15 15, 20 20))') AS collection");
+ Table resultTable = collectionTable.select(call(Functions.ST_GeometryN.class.getSimpleName(), $("collection"), 1));
+ Point point = (Point) first(resultTable).getField(0);
+ assertEquals("POINT (30 30)", point.toString());
+ }
+
+ @Test
+ public void testInteriorRingN() {
+ Table polygonTable = tableEnv.sqlQuery("SELECT ST_GeomFromText('POLYGON((7 9,8 7,11 6,15 8,16 6,17 7,17 10,18 12,17 14,15 15,11 15,10 13,9 12,7 9),(9 9,10 10,11 11,11 10,10 8,9 9),(12 14,15 14,13 11,12 14))') AS polygon");
+ Table resultTable = polygonTable.select(call(Functions.ST_InteriorRingN.class.getSimpleName(), $("polygon"), 1));
+ LinearRing linearRing = (LinearRing) first(resultTable).getField(0);
+ assertEquals("LINEARRING (12 14, 15 14, 13 11, 12 14)", linearRing.toString());
+ }
+
@Test
public void testPointN_positiveN() {
int n = 1;
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 5b742429..73b351f7 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
@@ -20,7 +20,6 @@ package org.apache.spark.sql.sedona_sql.expressions
import org.apache.sedona.common.Functions
import org.apache.sedona.sql.utils.GeometrySerializer
-import org.apache.spark.internal.Logging
import org.apache.spark.sql.catalyst.InternalRow
import org.apache.spark.sql.catalyst.expressions.codegen.CodegenFallback
import org.apache.spark.sql.catalyst.expressions._
@@ -793,33 +792,7 @@ case class ST_ExteriorRing(inputExpressions: Seq[Expression])
case class ST_GeometryN(inputExpressions: Seq[Expression])
- extends Expression with CodegenFallback with Logging {
- assert(inputExpressions.length == 2)
-
- override def nullable: Boolean = true
-
- override def eval(input: InternalRow): Any = {
- val geometry = inputExpressions(0).toGeometry(input)
- val n = inputExpressions(1).toInt(input)
- geometry match {
- case geom: Geometry => getNthGeom(geom, n)
- case _ => null
- }
- }
-
- private def getNthGeom(geom: Geometry, index: Int): GenericArrayData = {
- val nthGeom = Try(geom.getGeometryN(index))
- nthGeom match {
- case Failure(exception) =>
- logWarning(s"Geometry ${geom.toString}, Out Of index")
- null
- case Success(geom) => geom.toGenericArrayData
- }
- }
-
- override def dataType: DataType = GeometryUDT
-
- override def children: Seq[Expression] = inputExpressions
+ extends InferredBinaryExpression(Functions.geometryN) {
protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]) = {
copy(inputExpressions = newChildren)
@@ -827,24 +800,7 @@ case class ST_GeometryN(inputExpressions: Seq[Expression])
}
case class ST_InteriorRingN(inputExpressions: Seq[Expression])
- extends Expression with CodegenFallback {
- assert(inputExpressions.length == 2)
-
- override def nullable: Boolean = true
-
- override def eval(input: InternalRow): Any = {
- val geometry = inputExpressions(0).toGeometry(input)
- val n = inputExpressions(1).toInt(input)
- geometry match {
- case geom: Polygon => geom.getInteriorRingN(n)
- .toGenericArrayData
- case _ => null
- }
- }
-
- override def dataType: DataType = GeometryUDT
-
- override def children: Seq[Expression] = inputExpressions
+ extends InferredBinaryExpression(Functions.interiorRingN) {
protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]) = {
copy(inputExpressions = newChildren)