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 d71b5604 [SEDONA-116] Add ST_YMax and ST_YMin function (#620)
d71b5604 is described below

commit d71b5604b0e6e9f91be6ec342e4cfe13bdd548ed
Author: naharon2210 <[email protected]>
AuthorDate: Sat Apr 23 01:22:20 2022 -0700

    [SEDONA-116] Add ST_YMax and ST_YMin function (#620)
---
 docs/api/flink/Function.md                         | 28 +++++++++++++
 docs/api/sql/Function.md                           | 31 +++++++++++++++
 .../main/java/org/apache/sedona/flink/Catalog.java |  4 +-
 .../apache/sedona/flink/expressions/Functions.java | 28 +++++++++++++
 .../java/org/apache/sedona/flink/FunctionTest.java | 19 +++++++++
 .../scala/org/apache/sedona/sql/UDF/Catalog.scala  |  4 +-
 .../sql/sedona_sql/expressions/Functions.scala     | 46 ++++++++++++++++++++++
 .../org/apache/sedona/sql/functionTestScala.scala  | 10 +++++
 8 files changed, 168 insertions(+), 2 deletions(-)

diff --git a/docs/api/flink/Function.md b/docs/api/flink/Function.md
index 8c613c1a..8d2ba930 100644
--- a/docs/api/flink/Function.md
+++ b/docs/api/flink/Function.md
@@ -56,7 +56,35 @@ Spark SQL example:
 SELECT ST_Buffer(polygondf.countyshape, 1)
 FROM polygondf
 ```
+## ST_YMin
 
+Introduction: Return the minimum Y coordinate of A
+
+Format: `ST_Y_Min (A:geometry)`
+
+Since: `v1.2.1`
+
+Spark SQL example:
+```SQL
+SELECT ST_YMin(ST_GeomFromText('POLYGON((0 0 1, 1 1 1, 1 2 1, 1 1 1, 0 0 1))'))
+```
+
+Output : 0
+
+## ST_YMax
+
+Introduction: Return the minimum Y coordinate of A
+
+Format: `ST_YMax (A:geometry)`
+
+Since: `v1.2.1`
+
+Spark SQL example:
+```SQL
+SELECT ST_YMax(ST_GeomFromText('POLYGON((0 0 1, 1 1 1, 1 2 1, 1 1 1, 0 0 1))'))
+```
+
+Output : 2
 ## ST_FlipCoordinates
 
 Introduction: Returns a version of the given geometry with X and Y axis 
flipped.
diff --git a/docs/api/sql/Function.md b/docs/api/sql/Function.md
index 1adfa515..1080f1d7 100644
--- a/docs/api/sql/Function.md
+++ b/docs/api/sql/Function.md
@@ -12,6 +12,37 @@ SELECT ST_Distance(polygondf.countyshape, 
polygondf.countyshape)
 FROM polygondf
 ```
 
+## ST_YMin
+
+Introduction: Return the minimum Y coordinate of A
+
+Format: `ST_Y_Min (A:geometry)`
+
+Since: `v1.2.1`
+
+Spark SQL example:
+```SQL
+SELECT ST_YMin(ST_GeomFromText('POLYGON((0 0 1, 1 1 1, 1 2 1, 1 1 1, 0 0 1))'))
+```
+
+Output : 0
+
+## ST_YMax
+
+Introduction: Return the minimum Y coordinate of A
+
+Format: `ST_YMax (A:geometry)`
+
+Since: `v1.2.1`
+
+Spark SQL example:
+```SQL
+SELECT ST_YMax(ST_GeomFromText('POLYGON((0 0 1, 1 1 1, 1 2 1, 1 1 1, 0 0 1))'))
+```
+
+Output: 2
+
+
 ## ST_3DDistance
 
 Introduction: Return the 3-dimensional minimum cartesian distance between A 
and B
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 d0c207ea..6fe3ab43 100644
--- a/flink/src/main/java/org/apache/sedona/flink/Catalog.java
+++ b/flink/src/main/java/org/apache/sedona/flink/Catalog.java
@@ -35,7 +35,9 @@ public class Catalog {
                 new Functions.ST_Reverse(),
                 new Functions.ST_AsEWKT(),
                 new Functions.ST_Force_2D(),
-                new Functions.ST_IsEmpty()
+                new Functions.ST_IsEmpty(),
+                new Functions.ST_YMax(),
+                new Functions.ST_YMin()
         };
     }
 
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 9dd46016..46b4c713 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
@@ -25,6 +25,7 @@ import org.locationtech.jts.geom.Coordinate;
 import org.locationtech.jts.geom.CoordinateSequence;
 import org.locationtech.jts.geom.Geometry;
 import org.locationtech.jts.geom.GeometryFactory;
+import org.locationtech.jts.geom.Coordinate;
 import org.opengis.referencing.FactoryException;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.operation.MathTransform;
@@ -54,6 +55,33 @@ public class Functions {
         }
     }
 
+    public static class ST_YMin extends ScalarFunction {
+        @DataTypeHint("Double")
+        public Double eval(@DataTypeHint(value = "RAW", bridgedTo = 
org.locationtech.jts.geom.Geometry.class) Object o){
+            Geometry geom = (Geometry) o;
+            Coordinate[] points= geom.getCoordinates();
+            double min=Double.MAX_VALUE;
+            for(int i=0;i<points.length;i++){
+                min=Math.min(points[i].getY(),min);
+            }
+            return min;
+        }
+    }
+
+    public static class ST_YMax extends ScalarFunction {
+        @DataTypeHint("Double")
+        public Double eval(@DataTypeHint(value = "RAW", bridgedTo = 
org.locationtech.jts.geom.Geometry.class) Object o){
+            Geometry geom = (Geometry) o;
+            Coordinate[] points= geom.getCoordinates();
+            double max=Double.MIN_VALUE;
+            for(int i=0;i<points.length;i++){
+                max=Math.max(points[i].getY(),max);
+            }
+            return max;
+        }
+    }
+
+
     public static class ST_Transform 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("String") 
String sourceCRS, @DataTypeHint("String") String targetCRS) {
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 0a1cc84b..f4901e69 100644
--- a/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
+++ b/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
@@ -61,6 +61,25 @@ public class FunctionTest extends TestBase{
         assertEquals(0.0, first(pointTable).getField(0));
     }
 
+    @Test
+    public void testYMax() {
+        Table polygonTable = createPolygonTable(1);
+        Table ResultTable = 
polygonTable.select(call(Functions.ST_YMax.class.getSimpleName(), 
$(polygonColNames[0])));
+        assert(first(ResultTable).getField(0)!=null);
+        double result = (double) first(ResultTable).getField(0);
+        assertEquals(0.5, result,0);
+    }
+
+    @Test
+    public void testYMin() {
+        Table polygonTable = createPolygonTable(1);
+        Table ResultTable = 
polygonTable.select(call(Functions.ST_YMin.class.getSimpleName(), 
$(polygonColNames[0])));
+        assert(first(ResultTable).getField(0)!=null);
+        double result = (double) first(ResultTable).getField(0);
+        assertEquals(-0.5, result, 0);
+    }
+
+
     @Test
     public void testGeomToGeoHash() {
         Table pointTable = createPointTable(testDataSize);
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 df9d7c0b..882ed307 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
@@ -20,7 +20,7 @@ package org.apache.sedona.sql.UDF
 
 import org.apache.spark.sql.catalyst.analysis.FunctionRegistry.FunctionBuilder
 import org.apache.spark.sql.expressions.{Aggregator, 
UserDefinedAggregateFunction}
-import org.apache.spark.sql.sedona_sql.expressions._
+import org.apache.spark.sql.sedona_sql.expressions.{ST_YMax, ST_YMin, _}
 import org.apache.spark.sql.sedona_sql.expressions.collect.ST_Collect
 import org.apache.spark.sql.sedona_sql.expressions.raster.{RS_Add, RS_Append, 
RS_Array, RS_Base64, RS_BitwiseAnd, RS_BitwiseOr, RS_Count, RS_Divide, 
RS_FetchRegion, RS_GetBand, RS_GreaterThan, RS_GreaterThanEqual, RS_HTML, 
RS_LessThan, RS_LessThanEqual, RS_LogicalDifference, RS_LogicalOver, RS_Mean, 
RS_Mode, RS_Modulo, RS_Multiply, RS_MultiplyFactor, RS_Normalize, 
RS_NormalizedDifference, RS_SquareRoot, RS_Subtract}
 import org.locationtech.jts.geom.Geometry
@@ -108,6 +108,8 @@ object Catalog {
     ST_Reverse,
     ST_AsEWKT,
     ST_Force_2D,
+    ST_YMax,
+    ST_YMin,
     // 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 a24a549e..ffc33275 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
@@ -49,6 +49,8 @@ import org.locationtech.jts.precision.GeometryPrecisionReducer
 import org.locationtech.jts.simplify.TopologyPreservingSimplifier
 import org.opengis.referencing.operation.MathTransform
 import org.wololo.jts2geojson.GeoJSONWriter
+import org.locationtech.jts.geom.Geometry
+import org.locationtech.jts.geom.Coordinate
 
 import java.nio.ByteOrder
 import scala.util.{Failure, Success, Try}
@@ -77,6 +79,50 @@ case class ST_Distance(inputExpressions: Seq[Expression])
   }
 }
 
+
+case class ST_YMax(inputExpressions: Seq[Expression])
+  extends UnaryGeometryExpression with CodegenFallback {
+  assert(inputExpressions.length == 1)
+
+  override protected def nullSafeEval(geometry: Geometry): Any = {
+    val seqRev : Array[Coordinate] = geometry.getCoordinates()
+    var maxVal:Double = Double.MinValue
+    for(x <- seqRev ){
+      maxVal=Math.max(maxVal,x.getY())
+    }
+    maxVal
+  }
+
+  override def dataType: DataType = DoubleType
+
+  override def children: Seq[Expression] = inputExpressions
+
+  protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]) = 
{
+    copy(inputExpressions = newChildren)
+  }
+}
+
+case class ST_YMin(inputExpressions: Seq[Expression])
+  extends UnaryGeometryExpression with CodegenFallback {
+  assert(inputExpressions.length == 1)
+
+  override protected def nullSafeEval(geometry: Geometry): Any = {
+    val seqRev : Array[Coordinate] = geometry.getCoordinates()
+    var minVal:Double = Double.MaxValue
+    for(x <- seqRev){
+      minVal=Math.min(minVal,x.getY())
+    }
+    minVal
+  }
+
+  override def dataType: DataType = DoubleType
+
+  override def children: Seq[Expression] = inputExpressions
+
+  protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]) = 
{
+    copy(inputExpressions = newChildren)
+  }
+}
 case class ST_3DDistance(inputExpressions: Seq[Expression])
   extends BinaryGeometryExpression with CodegenFallback {
   assert(inputExpressions.length == 2)
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 71411cc0..ff6bce37 100644
--- a/sql/src/test/scala/org/apache/sedona/sql/functionTestScala.scala
+++ b/sql/src/test/scala/org/apache/sedona/sql/functionTestScala.scala
@@ -65,6 +65,16 @@ class functionTestScala extends TestBaseScala with Matchers 
with GeometrySample
       assert(functionDf.count() > 0);
     }
 
+    it("Passed ST_YMax") {
+      var test = sparkSession.sql("SELECT ST_YMax(ST_GeomFromWKT('POLYGON ((-3 
-3, 3 -3, 3 3, -3 3, -3 -3))'))")
+      assert(test.take(1)(0).get(0).asInstanceOf[Double] == 3.0)
+    }
+
+    it("Passed ST_YMin") {
+      var test = sparkSession.sql("SELECT ST_YMin(ST_GeomFromWKT('POLYGON ((-3 
-3, 3 -3, 3 3, -3 3, -3 -3))'))")
+      assert(test.take(1)(0).get(0).asInstanceOf[Double] == -3.0)
+    }
+
     it("Passed ST_Centroid") {
       var polygonWktDf = sparkSession.read.format("csv").option("delimiter", 
"\t").option("header", "false").load(mixedWktGeometryInputLocation)
       polygonWktDf.createOrReplaceTempView("polygontable")

Reply via email to