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)
+ }
}
}