From 352cdbfecc1b44a096c29f1650eb7149936b54cd Mon Sep 17 00:00:00 2001 From: Furqaanahmed Khan <46216254+furqaankhan@users.noreply.github.com> Date: Tue, 1 Aug 2023 14:16:52 -0400 Subject: [PATCH] [SEDONA-336] Add RS_UpperLeftX and RS_UpperLeftY (#935) --- .../sedona/common/raster/RasterAccessors.java | 10 ++++- .../common/raster/RasterAccessorsTest.java | 22 ++++++++++ docs/api/sql/Raster-operators.md | 40 +++++++++++++++++++ .../org/apache/sedona/sql/UDF/Catalog.scala | 2 + .../expressions/raster/RasterAccessors.scala | 12 ++++++ .../apache/sedona/sql/rasteralgebraTest.scala | 14 +++++++ 6 files changed, 99 insertions(+), 1 deletion(-) 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 32c33bdf01..a0dc07fbbc 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 @@ -64,6 +64,15 @@ public static int getHeight(GridCoverage2D raster) { return raster.getGridGeometry().getGridRange().getSpan(1); } + public static double getUpperLeftX(GridCoverage2D raster) { + Envelope2D envelope2D = raster.getEnvelope2D(); + return envelope2D.getMinX(); + } + + public static double getUpperLeftY(GridCoverage2D raster) { + Envelope2D envelope2D = raster.getEnvelope2D(); + return envelope2D.getMaxY(); + } public static double getScaleX(GridCoverage2D raster) { return getAffineTransform(raster).getScaleX(); @@ -82,7 +91,6 @@ private static AffineTransform2D getAffineTransform(GridCoverage2D raster) throw 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 60ab834616..d70ad0f8f4 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,28 @@ public void testSrid() throws FactoryException { assertEquals(4326, RasterAccessors.srid(multiBandRaster)); } + @Test + public void testUpperLeftX() throws FactoryException { + GridCoverage2D gridCoverage2D = RasterConstructors.makeEmptyRaster(1, 3, 4, 1,2, 5); + double upperLeftX = RasterAccessors.getUpperLeftX(gridCoverage2D); + assertEquals(1, upperLeftX, 0.1d); + + gridCoverage2D = RasterConstructors.makeEmptyRaster(10, 7, 8, 5, 6, 9); + upperLeftX = RasterAccessors.getUpperLeftX(gridCoverage2D); + assertEquals(5, upperLeftX, 0.1d); + } + + @Test + public void testUpperLeftY() throws FactoryException { + GridCoverage2D gridCoverage2D = RasterConstructors.makeEmptyRaster(1, 3, 4, 1,2, 5); + double upperLeftY = RasterAccessors.getUpperLeftY(gridCoverage2D); + assertEquals(2, upperLeftY, 0.1d); + + gridCoverage2D = RasterConstructors.makeEmptyRaster(10, 7, 8, 5, 6, 9); + upperLeftY = RasterAccessors.getUpperLeftY(gridCoverage2D); + assertEquals(6, upperLeftY, 0.1d); + } + @Test public void testScaleX() throws UnsupportedOperationException, FactoryException { GridCoverage2D emptyRaster = RasterConstructors.makeEmptyRaster(2, 10, 15, 0, 0, 1, 2, 0, 0, 0); diff --git a/docs/api/sql/Raster-operators.md b/docs/api/sql/Raster-operators.md index c89324d3b8..465488d858 100644 --- a/docs/api/sql/Raster-operators.md +++ b/docs/api/sql/Raster-operators.md @@ -83,6 +83,46 @@ Output: -2 ``` +### RS_UpperLeftX + +Introduction: Returns the X coordinate of the upper-left corner of the raster. + +Format: `RS_UpperLeftX(raster: Raster)` + +Since: `v1.5.0` + +Spark SQL Example: + +```sql +SELECT RS_UpperLeftX(raster) FROM rasters +``` + +Output: + +``` +5 +``` + +### RS_UpperLeftY + +Introduction: Returns the Y coordinate of the upper-left corner of the raster. + +Format: `RS_UpperLeftY(raster: Raster)` + +Since: `v1.5.0` + +Spark SQL Example: + +```sql +SELECT RS_UpperLeftY(raster) FROM rasters +``` + +Output: + +``` +6 +``` + ### 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 8c329b5319..ab588102d8 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 @@ -211,6 +211,8 @@ object Catalog { function[RS_AsArcGrid](), function[RS_Width](), function[RS_Height](), + function[RS_UpperLeftX](), + function[RS_UpperLeftY](), function[RS_ScaleX](), function[RS_ScaleY](), function[RS_BandPath]() 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 b518190882..dc96fb9f23 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 @@ -53,6 +53,18 @@ case class RS_Width(inputExpressions: Seq[Expression]) extends InferredExpressio } } +case class RS_UpperLeftX(inputExpressions: Seq[Expression]) extends InferredExpression(RasterAccessors.getUpperLeftX _) { + protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]) = { + copy(inputExpressions = newChildren) + } +} + +case class RS_UpperLeftY(inputExpressions: Seq[Expression]) extends InferredExpression(RasterAccessors.getUpperLeftY _) { + protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]) = { + copy(inputExpressions = newChildren) + } +} + case class RS_Height(inputExpressions: Seq[Expression]) extends InferredExpression(RasterAccessors.getHeight _) { 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 09fc5bae6a..b9309efc00 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 @@ -451,6 +451,20 @@ class rasteralgebraTest extends TestBaseScala with BeforeAndAfter with GivenWhen assertEquals(rasterDf.count(), binaryDf.count()) } + it("Passed RS_UpperLeftX"){ + val df = sparkSession.read.format("binaryFile").load(resourceFolder + "raster/test1.tiff") + val result = df.selectExpr("RS_UpperLeftX(RS_FromGeoTiff(content))").first().getDouble(0) + val expected: Double = -1.3095817809482181E7 + assertEquals(expected, result, 1e-12) + } + + it("Passed RS_UpperLeftY") { + val df = sparkSession.read.format("binaryFile").load(resourceFolder + "raster/test1.tiff") + val result = df.selectExpr("RS_UpperLeftY(RS_FromGeoTiff(content))").first().getDouble(0) + val expected: Double = 4021262.7487925636 + assertEquals(expected, result, 1e-8) + } + it("Passed RS_Metadata") { val df = sparkSession.read.format("binaryFile").load(resourceFolder + "raster/test1.tiff") val result = df.selectExpr("RS_Metadata(RS_FromGeoTiff(content))").first().getSeq(0)