You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@sedona.apache.org by "jiayuasu (via GitHub)" <gi...@apache.org> on 2023/09/08 02:17:39 UTC

[GitHub] [sedona] jiayuasu commented on a diff in pull request #1011: [SEDONA-388] Add RS_AsRaster

jiayuasu commented on code in PR #1011:
URL: https://github.com/apache/sedona/pull/1011#discussion_r1319265665


##########
common/src/main/java/org/apache/sedona/common/raster/RasterConstructors.java:
##########
@@ -45,6 +55,94 @@ public static GridCoverage2D fromGeoTiff(byte[] bytes) throws IOException {
         return geoTiffReader.read(null);
     }
 
+    /**
+    * Returns a raster that is converted from the geometry provided.
+     * @param geom The geometry to convert
+     * @param raster The reference raster
+     * @param pixelType The data type of pixel/cell of resultant raster
+     * @param value The value of the pixel of the resultant raster
+     * @param noDataValue The noDataValue of the resultant raster
+     *
+     * @return Rasterized Geometry
+     * @throws FactoryException
+    */
+    public static GridCoverage2D asRaster(Geometry geom, GridCoverage2D raster, String pixelType, double value, Double noDataValue) throws FactoryException {
+
+        DefaultFeatureCollection featureCollection = getFeatureCollection(geom, raster.getCoordinateReferenceSystem());
+
+
+        double[] metadata = RasterAccessors.metadata(raster);
+        // The current implementation doesn't support rasters with properties below
+        // It is not a problem as most rasters don't have these properties
+        // ScaleX < 0
+        if (metadata[4] < 0) {
+            throw new IllegalArgumentException(String.format("ScaleX %f of the raster is negative, it should be positive", metadata[4]));
+        }
+        // ScaleY > 0
+        if (metadata[5] > 0) {

Review Comment:
   Why cannot ScaleY >0?



##########
spark/common/pom.xml:
##########
@@ -122,6 +122,10 @@
             <groupId>org.geotools</groupId>
             <artifactId>gt-geotiff</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.geotools</groupId>
+            <artifactId>gt-process-feature</artifactId>

Review Comment:
   This needs to put in the spark-shaded pom.xml as well.



##########
common/src/main/java/org/apache/sedona/common/raster/RasterConstructors.java:
##########
@@ -45,6 +55,94 @@ public static GridCoverage2D fromGeoTiff(byte[] bytes) throws IOException {
         return geoTiffReader.read(null);
     }
 
+    /**
+    * Returns a raster that is converted from the geometry provided.
+     * @param geom The geometry to convert
+     * @param raster The reference raster
+     * @param pixelType The data type of pixel/cell of resultant raster
+     * @param value The value of the pixel of the resultant raster
+     * @param noDataValue The noDataValue of the resultant raster
+     *
+     * @return Rasterized Geometry
+     * @throws FactoryException
+    */
+    public static GridCoverage2D asRaster(Geometry geom, GridCoverage2D raster, String pixelType, double value, Double noDataValue) throws FactoryException {
+
+        DefaultFeatureCollection featureCollection = getFeatureCollection(geom, raster.getCoordinateReferenceSystem());
+
+
+        double[] metadata = RasterAccessors.metadata(raster);
+        // The current implementation doesn't support rasters with properties below
+        // It is not a problem as most rasters don't have these properties
+        // ScaleX < 0
+        if (metadata[4] < 0) {
+            throw new IllegalArgumentException(String.format("ScaleX %f of the raster is negative, it should be positive", metadata[4]));
+        }
+        // ScaleY > 0
+        if (metadata[5] > 0) {
+            throw new IllegalArgumentException(String.format("ScaleY %f of the raster is positive. It should be negative.", metadata[5]));
+        }
+        // SkewX should be zero
+        if (metadata[6] != 0) {
+            throw new IllegalArgumentException(String.format("SkewX %d of the raster is not zero.", metadata[6]));
+        }
+        // SkewY should be zero
+        if (metadata[7] != 0) {
+            throw new IllegalArgumentException(String.format("SkewY %d of the raster is not zero.", metadata[7]));
+        }
+
+        Envelope2D bound = JTS.getEnvelope2D(geom.getEnvelopeInternal(), raster.getCoordinateReferenceSystem2D());
+
+        double scaleX = Math.abs(metadata[4]), scaleY = Math.abs(metadata[5]);
+
+        int width = (int) bound.getWidth(), height = (int) bound.getHeight();
+
+        // To preserve scale of reference raster
+        width = (int) (width / scaleX);
+        height = (int) (height / scaleY);
+
+        VectorToRasterProcess rasterProcess = new VectorToRasterProcess();
+        GridCoverage2D rasterized = rasterProcess.execute(featureCollection, width, height, "value", Double.toString(value), bound, null);
+        if (noDataValue != null) {
+            rasterized = RasterBandEditors.setBandNoDataValue(rasterized, 1, noDataValue);
+        }
+        WritableRaster writableRaster = RasterFactory.createBandedRaster(RasterUtils.getDataTypeCode(pixelType), width, height, 1, null);
+        double [] samples = rasterized.getRenderedImage().getData().getSamples(0, 0, width, height, 0, (double[]) null);

Review Comment:
   Please use `RasterUtils.getRaster` function to replace rasterized.getRenderImage().getData



##########
common/src/main/java/org/apache/sedona/common/raster/RasterOutputs.java:
##########
@@ -74,6 +76,26 @@ public static byte[] asGeoTiff(GridCoverage2D raster) {
         return asGeoTiff(raster, null, -1);
     }
 
+    /**
+    * Creates a GeoTiff file with the provided raster. Primarily used for testing.
+     * @param raster The raster to be stored as .tiff
+     * @param filePath The path where the .tiff should be stored.
+     *
+     * @return true if file is created, otherwise throws IOException
+     * @throws IOException
+     * */
+    public static boolean toGeoTiff(GridCoverage2D raster, String filePath) {
+        File outputFile = new File(filePath);
+        GeoTiffFormat format = new GeoTiffFormat();

Review Comment:
   And this function is not tested. Please add a test.



##########
common/src/main/java/org/apache/sedona/common/raster/RasterOutputs.java:
##########
@@ -74,6 +76,26 @@ public static byte[] asGeoTiff(GridCoverage2D raster) {
         return asGeoTiff(raster, null, -1);
     }
 
+    /**
+    * Creates a GeoTiff file with the provided raster. Primarily used for testing.
+     * @param raster The raster to be stored as .tiff
+     * @param filePath The path where the .tiff should be stored.
+     *
+     * @return true if file is created, otherwise throws IOException
+     * @throws IOException
+     * */
+    public static boolean toGeoTiff(GridCoverage2D raster, String filePath) {
+        File outputFile = new File(filePath);
+        GeoTiffFormat format = new GeoTiffFormat();

Review Comment:
   Please do not use the GeoTiff format here. Use the `asGeoTiff` function to get the bytes and directly write the bytes to the disk file.



##########
common/src/main/java/org/apache/sedona/common/raster/RasterConstructors.java:
##########
@@ -45,6 +55,94 @@ public static GridCoverage2D fromGeoTiff(byte[] bytes) throws IOException {
         return geoTiffReader.read(null);
     }
 
+    /**
+    * Returns a raster that is converted from the geometry provided.
+     * @param geom The geometry to convert
+     * @param raster The reference raster
+     * @param pixelType The data type of pixel/cell of resultant raster
+     * @param value The value of the pixel of the resultant raster
+     * @param noDataValue The noDataValue of the resultant raster
+     *
+     * @return Rasterized Geometry
+     * @throws FactoryException
+    */
+    public static GridCoverage2D asRaster(Geometry geom, GridCoverage2D raster, String pixelType, double value, Double noDataValue) throws FactoryException {
+
+        DefaultFeatureCollection featureCollection = getFeatureCollection(geom, raster.getCoordinateReferenceSystem());
+
+
+        double[] metadata = RasterAccessors.metadata(raster);
+        // The current implementation doesn't support rasters with properties below
+        // It is not a problem as most rasters don't have these properties
+        // ScaleX < 0
+        if (metadata[4] < 0) {
+            throw new IllegalArgumentException(String.format("ScaleX %f of the raster is negative, it should be positive", metadata[4]));
+        }
+        // ScaleY > 0
+        if (metadata[5] > 0) {
+            throw new IllegalArgumentException(String.format("ScaleY %f of the raster is positive. It should be negative.", metadata[5]));
+        }
+        // SkewX should be zero
+        if (metadata[6] != 0) {
+            throw new IllegalArgumentException(String.format("SkewX %d of the raster is not zero.", metadata[6]));
+        }
+        // SkewY should be zero
+        if (metadata[7] != 0) {
+            throw new IllegalArgumentException(String.format("SkewY %d of the raster is not zero.", metadata[7]));
+        }
+
+        Envelope2D bound = JTS.getEnvelope2D(geom.getEnvelopeInternal(), raster.getCoordinateReferenceSystem2D());
+
+        double scaleX = Math.abs(metadata[4]), scaleY = Math.abs(metadata[5]);
+
+        int width = (int) bound.getWidth(), height = (int) bound.getHeight();
+
+        // To preserve scale of reference raster
+        width = (int) (width / scaleX);
+        height = (int) (height / scaleY);
+
+        VectorToRasterProcess rasterProcess = new VectorToRasterProcess();
+        GridCoverage2D rasterized = rasterProcess.execute(featureCollection, width, height, "value", Double.toString(value), bound, null);
+        if (noDataValue != null) {
+            rasterized = RasterBandEditors.setBandNoDataValue(rasterized, 1, noDataValue);
+        }
+        WritableRaster writableRaster = RasterFactory.createBandedRaster(RasterUtils.getDataTypeCode(pixelType), width, height, 1, null);

Review Comment:
   Why does this call `RasterFactory.createBandedRaster` to get the GridCoverage2D? Is it because the original GridCoverage2D object is not banded?



##########
common/src/test/java/org/apache/sedona/common/raster/RasterConstructorsTest.java:
##########
@@ -55,6 +58,22 @@ public void fromGeoTiff() throws IOException, FactoryException {
         assertEquals(4, gridCoverage2D.getNumSampleDimensions());
     }
 
+    @Test
+    public void testAsRasterWithEmptyRaster() throws FactoryException, ParseException {

Review Comment:
   Please add a few more tests using the real test geotiff images



##########
docs/api/sql/Raster-writer.md:
##########
@@ -183,3 +183,59 @@ sparkSession.read.format("binaryFile").load("my_raster_file/*")
 Then you can create Raster type in Sedona like this `RS_FromGeoTiff(content)` (if the written data was in GeoTiff format).
 
 The newly created DataFrame can be written to disk again but must be under a different name such as `my_raster_file_modified`
+
+### Write Geometry to Raster dataframe
+
+#### RS_AsRaster
+
+Introduction: Converts a Geometry to a Raster dataset. Defaults to using `1.0` for cell `value` and `null` for `noDataValue` if not provided. Supports all geometry types. 

Review Comment:
   Please explain the possible values for pixel type



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@sedona.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org