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 2023/08/17 09:10:07 UTC

[sedona] branch master updated: [SEDONA-367] Add RS_PixelAsCentroid (#977)

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 23b9f2947 [SEDONA-367] Add RS_PixelAsCentroid (#977)
23b9f2947 is described below

commit 23b9f294763df7ad3a52ed240502949f1c6661ba
Author: Furqaanahmed Khan <46...@users.noreply.github.com>
AuthorDate: Thu Aug 17 05:10:01 2023 -0400

    [SEDONA-367] Add RS_PixelAsCentroid (#977)
---
 .../sedona/common/raster/PixelFunctions.java       |  5 +++++
 .../apache/sedona/common/raster/FunctionsTest.java | 14 +++++++++++++
 docs/api/sql/Raster-operators.md                   | 24 +++++++++++++++++++++-
 .../scala/org/apache/sedona/sql/UDF/Catalog.scala  |  1 +
 .../expressions/raster/PixelFunctions.scala        |  6 ++++++
 .../org/apache/sedona/sql/rasteralgebraTest.scala  | 12 +++++++++++
 6 files changed, 61 insertions(+), 1 deletion(-)

diff --git a/common/src/main/java/org/apache/sedona/common/raster/PixelFunctions.java b/common/src/main/java/org/apache/sedona/common/raster/PixelFunctions.java
index da78d4a54..ce231037c 100644
--- a/common/src/main/java/org/apache/sedona/common/raster/PixelFunctions.java
+++ b/common/src/main/java/org/apache/sedona/common/raster/PixelFunctions.java
@@ -62,6 +62,11 @@ public class PixelFunctions
         return GEOMETRY_FACTORY.createPolygon(coordinateArray);
     }
 
+    public static Geometry getPixelAsCentroid(GridCoverage2D raster, int colX, int rowY) throws FactoryException, TransformException {
+        Geometry polygon = PixelFunctions.getPixelAsPolygon(raster, colX, rowY);
+        return  polygon.getCentroid();
+    }
+
     public static Geometry getPixelAsPoint(GridCoverage2D raster, int colX, int rowY) throws TransformException, FactoryException {
         int srid = RasterAccessors.srid(raster);
         Point2D point2D = RasterUtils.getWorldCornerCoordinatesWithRangeCheck(raster, colX, rowY);
diff --git a/common/src/test/java/org/apache/sedona/common/raster/FunctionsTest.java b/common/src/test/java/org/apache/sedona/common/raster/FunctionsTest.java
index 093b20185..521557976 100644
--- a/common/src/test/java/org/apache/sedona/common/raster/FunctionsTest.java
+++ b/common/src/test/java/org/apache/sedona/common/raster/FunctionsTest.java
@@ -91,6 +91,20 @@ public class FunctionsTest extends RasterTestBase {
         assertEquals(expected,actual);
     }
 
+    @Test
+    public void testPixelAsCentroid() throws FactoryException, TransformException {
+        GridCoverage2D emptyRaster = RasterConstructors.makeEmptyRaster(1, 12, 13, 134, -53, 9);
+        String actual = Functions.asWKT(PixelFunctions.getPixelAsCentroid(emptyRaster, 3, 3));
+        String expected = "POINT (156.5 -75.5)";
+        assertEquals(expected, actual);
+
+        // Testing with skewed raster
+        emptyRaster = RasterConstructors.makeEmptyRaster(1, 12, 13, 240, -193, 2, 1.5, 3, 2, 0);
+        actual = Functions.asWKT(PixelFunctions.getPixelAsCentroid(emptyRaster, 3, 3));
+        expected = "POINT (252.5 -184.25)";
+        assertEquals(expected, actual);
+    }
+
     @Test
     public void testPixelAsPointUpperLeft() throws FactoryException, TransformException {
         GridCoverage2D emptyRaster = RasterConstructors.makeEmptyRaster(1, 5, 10, 123, -230, 8);
diff --git a/docs/api/sql/Raster-operators.md b/docs/api/sql/Raster-operators.md
index 03d94635a..a58278a4f 100644
--- a/docs/api/sql/Raster-operators.md
+++ b/docs/api/sql/Raster-operators.md
@@ -1,5 +1,27 @@
 ## Pixel Functions
 
+### RS_PixelAsCentroid
+
+Introduction: Returns the centroid (point geometry) of the specified pixel's area.
+The pixel coordinates specified are 1-indexed.
+If `colX` and `rowY` are out of bounds for the raster, they are interpolated assuming the same skew and translate values.
+
+Format: `RS_PixelAsCentroid(raster: Raster, colX: int, rowY: int)`
+
+Since: `v1.5.0`
+
+Spark SQL Example:
+
+```sql
+SELECT ST_AsText(RS_PixelAsPolygon(RS_MakeEmptyRaster(1, 12, 13, 134, -53, 9), 3, 3))
+```
+
+Output:
+
+```
+POINT (156.5 -75.5)
+```
+
 ### RS_PixelAsPoint
 
 Introduction: Returns a point geometry of the specified pixel's upper-left corner. The pixel coordinates specified are 1-indexed.
@@ -45,7 +67,7 @@ Since: `v1.5.0`
 Spark SQL Example:
 
 ```sql
-SELECT ST_AsText(RS_PixelAsPolygon(RS_MakeEmptyRaster(1, 5, 10, 123, -230, 8), 2, 3)) FROM rasters
+SELECT ST_AsText(RS_PixelAsPolygon(RS_MakeEmptyRaster(1, 5, 10, 123, -230, 8), 2, 3))
 ```
 
 Output:
diff --git a/sql/common/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala b/sql/common/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala
index d059539e2..91ce8d840 100644
--- a/sql/common/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala
+++ b/sql/common/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala
@@ -221,6 +221,7 @@ object Catalog {
     function[RS_GeoReference](),
     function[RS_PixelAsPoint](),
     function[RS_PixelAsPolygon](),
+    function[RS_PixelAsCentroid](),
     function[RS_Count](),
     function[RS_ConvexHull](),
     function[RS_RasterToWorldCoordX](),
diff --git a/sql/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/raster/PixelFunctions.scala b/sql/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/raster/PixelFunctions.scala
index 461065781..df89f572c 100644
--- a/sql/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/raster/PixelFunctions.scala
+++ b/sql/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/raster/PixelFunctions.scala
@@ -48,6 +48,12 @@ case class RS_PixelAsPolygon(inputExpressions: Seq[Expression]) extends Inferred
   }
 }
 
+case class RS_PixelAsCentroid(inputExpressions: Seq[Expression]) extends InferredExpression(PixelFunctions.getPixelAsCentroid _) {
+  protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]) = {
+    copy(inputExpressions = newChildren)
+  }
+}
+
 case class RS_Values(inputExpressions: Seq[Expression]) extends Expression with CodegenFallback with ExpectsInputTypes {
 
   override def nullable: Boolean = true
diff --git a/sql/common/src/test/scala/org/apache/sedona/sql/rasteralgebraTest.scala b/sql/common/src/test/scala/org/apache/sedona/sql/rasteralgebraTest.scala
index 3be27bb6b..63b9b6615 100644
--- a/sql/common/src/test/scala/org/apache/sedona/sql/rasteralgebraTest.scala
+++ b/sql/common/src/test/scala/org/apache/sedona/sql/rasteralgebraTest.scala
@@ -669,6 +669,18 @@ class rasteralgebraTest extends TestBaseScala with BeforeAndAfter with GivenWhen
       assertEquals(expected, result)
     }
 
+    it("Passed RS_PixelAsCentroid with raster") {
+      val widthInPixel = 12
+      val heightInPixel = 13
+      val upperLeftX = 240
+      val upperLeftY = -193
+      val cellSize = 9
+      val numBands = 2
+      val result = sparkSession.sql(s"SELECT ST_AsText(RS_PixelAsCentroid(RS_MakeEmptyRaster($numBands, $widthInPixel, $heightInPixel, $upperLeftX, $upperLeftY, $cellSize), 2, 3))").first().getString(0);
+      val expected = "POINT (253.5 -215.5)"
+      assertEquals(expected, result)
+    }
+
     it("Passed RS_RasterToWorldCoordX with raster") {
       var df = sparkSession.read.format("binaryFile").load(resourceFolder + "raster/test1.tiff")
       df = df.selectExpr("RS_FromGeoTiff(content) as raster")