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 ab5f1106 [SEDONA-334] Add RS_ScaleX and RS_ScaleY (#932)
ab5f1106 is described below

commit ab5f11061b495a6e5c77e9236c1e495c0bf962fa
Author: Nilesh Gajwani <[email protected]>
AuthorDate: Fri Jul 28 14:15:43 2023 -0700

    [SEDONA-334] Add RS_ScaleX and RS_ScaleY (#932)
---
 .../sedona/common/raster/RasterAccessors.java      | 19 +++++++++
 .../sedona/common/raster/RasterAccessorsTest.java  | 12 ++++++
 docs/api/sql/Raster-operators.md                   | 46 ++++++++++++++++++++++
 .../scala/org/apache/sedona/sql/UDF/Catalog.scala  |  4 +-
 .../expressions/raster/RasterAccessors.scala       | 16 +++++++-
 .../org/apache/sedona/sql/rasteralgebraTest.scala  | 14 +++++++
 6 files changed, 109 insertions(+), 2 deletions(-)

diff --git 
a/common/src/main/java/org/apache/sedona/common/raster/RasterAccessors.java 
b/common/src/main/java/org/apache/sedona/common/raster/RasterAccessors.java
index 2794f93a..9d232d1f 100644
--- a/common/src/main/java/org/apache/sedona/common/raster/RasterAccessors.java
+++ b/common/src/main/java/org/apache/sedona/common/raster/RasterAccessors.java
@@ -19,6 +19,8 @@
 package org.apache.sedona.common.raster;
 
 import org.geotools.coverage.grid.GridCoverage2D;
+import org.geotools.coverage.grid.GridGeometry2D;
+import org.geotools.coverage.processing.operation.Affine;
 import org.geotools.geometry.Envelope2D;
 import org.geotools.referencing.CRS;
 import org.geotools.referencing.crs.DefaultEngineeringCRS;
@@ -62,6 +64,23 @@ public class RasterAccessors
     }
 
 
+    public static double getScaleX(GridCoverage2D raster) {
+        return getAffineTransform(raster).getScaleX();
+    }
+
+    public static double getScaleY(GridCoverage2D raster) {
+        return getAffineTransform(raster).getScaleY();
+    }
+
+    private static AffineTransform2D getAffineTransform(GridCoverage2D raster) 
throws UnsupportedOperationException {
+        GridGeometry2D gridGeometry2D = raster.getGridGeometry();
+        MathTransform crsTransform = gridGeometry2D.getGridToCRS2D();
+        if (!(crsTransform instanceof AffineTransform2D)) {
+            throw new UnsupportedOperationException("Only AffineTransform2D is 
supported");
+        }
+        return (AffineTransform2D) crsTransform;
+    }
+
 
     public static Geometry envelope(GridCoverage2D raster) throws 
FactoryException {
         Envelope2D envelope2D = raster.getEnvelope2D();
diff --git 
a/common/src/test/java/org/apache/sedona/common/raster/RasterAccessorsTest.java 
b/common/src/test/java/org/apache/sedona/common/raster/RasterAccessorsTest.java
index c47570c0..60ab8346 100644
--- 
a/common/src/test/java/org/apache/sedona/common/raster/RasterAccessorsTest.java
+++ 
b/common/src/test/java/org/apache/sedona/common/raster/RasterAccessorsTest.java
@@ -56,6 +56,18 @@ public class RasterAccessorsTest extends RasterTestBase
         assertEquals(4326, RasterAccessors.srid(multiBandRaster));
     }
 
+    @Test
+    public void testScaleX() throws UnsupportedOperationException, 
FactoryException {
+        GridCoverage2D emptyRaster = RasterConstructors.makeEmptyRaster(2, 10, 
15, 0, 0, 1, 2, 0, 0, 0);
+        assertEquals(1, RasterAccessors.getScaleX(emptyRaster), 1e-9);
+    }
+
+    @Test
+    public void testScaleY() throws UnsupportedOperationException, 
FactoryException {
+        GridCoverage2D emptyRaster = RasterConstructors.makeEmptyRaster(2, 10, 
15, 0, 0, 1, 2, 0, 0, 0);
+        assertEquals(-2, RasterAccessors.getScaleY(emptyRaster), 1e-9);
+    }
+
     @Test
     public void testMetaData()
             throws FactoryException
diff --git a/docs/api/sql/Raster-operators.md b/docs/api/sql/Raster-operators.md
index 9157ccf8..25cca45b 100644
--- a/docs/api/sql/Raster-operators.md
+++ b/docs/api/sql/Raster-operators.md
@@ -18,6 +18,52 @@ Output:
 512
 ```
 
+### RS_ScaleX
+
+Introduction: Returns the pixel width of the raster in CRS units.
+!!!Note
+    RS_ScaleX attempts to get an Affine transform on the grid in order to 
return scaleX (See [World File](https://en.wikipedia.org/wiki/World_file) for 
more details). If the transform on the geometry is not an Affine transform, 
RS_ScaleX will throw an UnsupportedException:
+    ```
+    UnsupportedOperationException("Only AffineTransform2D is supported")
+    ```
+
+Format: `RS_ScaleX(raster: Raster)`
+
+Since: `1.5.0`
+
+Spark SQL example:
+```sql
+SELECT RS_ScaleX(raster) FROM rasters
+```
+
+Output:
+```
+1
+```
+
+### RS_ScaleY
+
+Introduction: Returns the pixel height of the raster in CRS units.
+!!!Note
+    RS_ScaleY attempts to get an Affine transform on the grid in order to 
return scaleX (See [World File](https://en.wikipedia.org/wiki/World_file) for 
more details). If the transform on the geometry is not an Affine transform, 
RS_ScaleY will throw an UnsupportedException:
+    ```
+    UnsupportedOperationException("Only AffineTransform2D is supported")
+    ```
+
+Format: `RS_ScaleY(raster: Raster)`
+
+Since: `1.5.0`
+
+Spark SQL example:
+```sql
+SELECT RS_ScaleY(raster) FROM rasters
+```
+
+Output:
+```
+-2
+```
+
 ### RS_Width
 
 Introduction: Returns the width of the raster.
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 95473c05..8ed7d61c 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
@@ -205,7 +205,9 @@ object Catalog {
     function[RS_AsGeoTiff](),
     function[RS_AsArcGrid](),
     function[RS_Width](),
-    function[RS_Height]()
+    function[RS_Height](),
+    function[RS_ScaleX](),
+    function[RS_ScaleY]()
   )
 
   val aggregateExpressions: Seq[Aggregator[Geometry, Geometry, Geometry]] = 
Seq(
diff --git 
a/sql/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/raster/RasterAccessors.scala
 
b/sql/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/raster/RasterAccessors.scala
index 13b47724..284ec3fc 100644
--- 
a/sql/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/raster/RasterAccessors.scala
+++ 
b/sql/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/raster/RasterAccessors.scala
@@ -57,4 +57,18 @@ case class RS_Height(inputExpressions: Seq[Expression]) 
extends InferredExpressi
   protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]) = 
{
     copy(inputExpressions = newChildren)
   }
-}
\ No newline at end of file
+}
+
+
+case class RS_ScaleX(inputExpressions: Seq[Expression]) extends 
InferredExpression(RasterAccessors.getScaleX _) {
+  protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]) = 
{
+    copy(inputExpressions = newChildren)
+  }
+}
+
+case class RS_ScaleY(inputExpressions: Seq[Expression]) extends 
InferredExpression(RasterAccessors.getScaleY _) {
+  protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]) = 
{
+    copy(inputExpressions = newChildren)
+  }
+}
+
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 11e75e6d..1689099d 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
@@ -488,5 +488,19 @@ class rasteralgebraTest extends TestBaseScala with 
BeforeAndAfter with GivenWhen
       raster = df.collect().head.getAs[GridCoverage2D](0)
       assert(raster.getNumSampleDimensions == 2)
     }
+
+    it("Passed RS_ScaleX with raster") {
+      val df = sparkSession.read.format("binaryFile").load(resourceFolder + 
"raster/test1.tiff")
+      val result = 
df.selectExpr("RS_ScaleX(RS_FromGeoTiff(content))").first().getDouble(0)
+      val expected: Double = 72.32861272132695
+      assertEquals(expected, result, 1e-9)
+    }
+
+    it("Passed RS_ScaleY with raster") {
+      val df = sparkSession.read.format("binaryFile").load(resourceFolder + 
"raster/test1.tiff")
+      val result = 
df.selectExpr("RS_ScaleY(RS_FromGeoTiff(content))").first().getDouble(0)
+      val expected: Double = -72.32861272132695
+      assertEquals(expected, result, 1e-9)
+    }
   }
 }

Reply via email to