sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jso...@apache.org
Subject [sis] 01/02: Coverage : first implementation of evaluate method for GridCoverage2D
Date Fri, 15 Nov 2019 08:25:40 GMT
This is an automated email from the ASF dual-hosted git repository.

jsorel pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git

commit 5c209b019ae4dbf2442ded906ea087cf1e35a324
Author: jsorel <johann.sorel@geomatys.com>
AuthorDate: Thu Nov 14 15:07:46 2019 +0100

    Coverage : first implementation of evaluate method for GridCoverage2D
---
 .../sis/internal/coverage/GridCoverage2D.java      | 135 +++++++++++++++++++--
 .../sis/internal/coverage/GridCoverage2DTest.java  |   3 +-
 2 files changed, 129 insertions(+), 9 deletions(-)

diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/GridCoverage2D.java
b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/GridCoverage2D.java
index 842ca9d..5f8d76f 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/GridCoverage2D.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/GridCoverage2D.java
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.internal.coverage;
 
+import java.awt.Rectangle;
 import java.awt.image.BufferedImage;
 import java.awt.image.ColorModel;
 import java.awt.image.RenderedImage;
@@ -25,8 +26,17 @@ import org.apache.sis.coverage.SampleDimension;
 import org.apache.sis.coverage.grid.GridCoverage;
 import org.apache.sis.coverage.grid.GridExtent;
 import org.apache.sis.coverage.grid.GridGeometry;
+import org.apache.sis.referencing.CRS;
+import org.apache.sis.referencing.operation.transform.MathTransforms;
 import org.apache.sis.util.ArgumentChecks;
 import org.opengis.coverage.CannotEvaluateException;
+import org.opengis.coverage.PointOutsideCoverageException;
+import org.opengis.geometry.DirectPosition;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.datum.PixelInCell;
+import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.TransformException;
+import org.opengis.util.FactoryException;
 
 /**
  * A {@link GridCoverage} with data stored in a {@link RenderedImage}.
@@ -36,11 +46,13 @@ import org.opengis.coverage.CannotEvaluateException;
  * @since   2.0
  * @module
  */
-public class GridCoverage2D extends GridCoverage {
+public final class GridCoverage2D extends GridCoverage {
     /**
      * The sample values, stored as a RenderedImage.
      */
-    protected final RenderedImage image;
+    private final RenderedImage image;
+    private final int[] imageAxes;
+    private final CoordinateReferenceSystem crs2d;
 
     /**
      * Result of the call to {@link #forConvertedValues(boolean)}, created when first needed.
@@ -48,15 +60,32 @@ public class GridCoverage2D extends GridCoverage {
     private GridCoverage converted;
 
     /**
+     * The given RenderedImage may not start at 0,0, so does the gridExtent of the grid geometry.
+     * Image minX/MinY coordinate is expected to be located grid extent lower corner.
+     *
      *
      * @param grid  the grid extent, CRS and conversion from cell indices to CRS.
      * @param bands sample dimensions for each image band.
      * @param image the sample values as a RenderedImage, potentially multi-banded in packed
view.
      */
-    public GridCoverage2D(final GridGeometry grid, final Collection<? extends SampleDimension>
bands, final RenderedImage image) {
+    public GridCoverage2D(final GridGeometry grid, final Collection<? extends SampleDimension>
bands, final RenderedImage image) throws FactoryException {
         super(grid, bands);
         this.image = image;
         ArgumentChecks.ensureNonNull("image", image);
+
+        //extract the 2D Coordinater
+        GridExtent extent = grid.getExtent();
+        imageAxes = extent.getSubspaceDimensions(2);
+        crs2d = CRS.reduce(grid.getCoordinateReferenceSystem(), imageAxes);
+
+        //check image is coherent with grid geometry
+        if (image.getWidth() != extent.getSize(imageAxes[0])) {
+            throw new IllegalArgumentException("Image width " + image.getWidth() + "does
not match grid extent width "+ extent.getSize(imageAxes[0]));
+        }
+        if (image.getHeight()!= extent.getSize(imageAxes[1])) {
+            throw new IllegalArgumentException("Image height " + image.getHeight()+ "does
not match grid extent height "+ extent.getSize(imageAxes[1]));
+        }
+
     }
 
     /**
@@ -94,11 +123,10 @@ public class GridCoverage2D extends GridCoverage {
         if (sliceExtent == null || sliceExtent.equals(getGridGeometry().getExtent())) {
             return image;
         } else {
-            final int[] imgAxes = sliceExtent.getSubspaceDimensions(2);
-            final int subX = Math.toIntExact(sliceExtent.getLow(imgAxes[0]));
-            final int subY = Math.toIntExact(sliceExtent.getLow(imgAxes[1]));
-            final int subWidth = Math.toIntExact(Math.round(sliceExtent.getSize(imgAxes[0])));
-            final int subHeight = Math.toIntExact(Math.round(sliceExtent.getSize(imgAxes[1])));
+            final int subX = Math.toIntExact(sliceExtent.getLow(imageAxes[0]));
+            final int subY = Math.toIntExact(sliceExtent.getLow(imageAxes[1]));
+            final int subWidth = Math.toIntExact(Math.round(sliceExtent.getSize(imageAxes[0])));
+            final int subHeight = Math.toIntExact(Math.round(sliceExtent.getSize(imageAxes[1])));
 
             if (image instanceof BufferedImage) {
                 final BufferedImage bi = (BufferedImage) image;
@@ -114,4 +142,95 @@ public class GridCoverage2D extends GridCoverage {
         }
     }
 
+    public double[] evaluate(DirectPosition position, double[] pixel) throws CannotEvaluateException
{
+
+        try {
+            position = toGridCoord(position);
+
+            int x = 0;
+            int y = 0;
+            for (int i = 0, n = position.getDimension(); i < n; i++) {
+                final double dv = position.getOrdinate(i);
+                if (Double.isFinite(dv)) {
+                    throw new PointOutsideCoverageException("Position outside coverage, axis
" + i + " value " + dv);
+                }
+
+                final int v = Math.toIntExact(Math.round(dv));
+                if (i == imageAxes[0]) {
+                    x = v;
+                } else if (i == imageAxes[1]) {
+                    y = v;
+                } else if (v != 0) {
+                    //coverage is a slice, all other indices must be zero, otherwise we are
outside coverage
+                    throw new PointOutsideCoverageException("Position outside coverage, axis
" + i + " value " + v);
+                }
+            }
+
+            if (getBounds().contains(x,y)) {
+                return image.getTile(XToTileX(x), YToTileY(y)).getPixel(x, y, pixel);
+            }
+            throw new PointOutsideCoverageException("");
+        } catch (FactoryException | TransformException ex) {
+            throw new CannotEvaluateException(ex.getMessage(), ex);
+        }
+    }
+
+    /**
+     * Converts the specified point to grid coordinate.
+     * @param point point to transform to grid coordinate
+     * @return point in grid coordinate
+     * @throws org.opengis.util.FactoryException if creating transformation fails
+     * @throws org.opengis.referencing.operation.TransformException if transformation fails
+     */
+    protected DirectPosition toGridCoord(final DirectPosition point)
+            throws FactoryException, TransformException
+    {
+        final CoordinateReferenceSystem sourceCRS = point.getCoordinateReferenceSystem();
+        final MathTransform trs;
+        if (sourceCRS != null) {
+            MathTransform toCrs = CRS.findOperation(sourceCRS, getCoordinateReferenceSystem(),
null).getMathTransform();
+            trs = MathTransforms.concatenate(toCrs, getGridGeometry().getGridToCRS(PixelInCell.CELL_CENTER).inverse());
+        } else {
+            trs = getGridGeometry().getGridToCRS(PixelInCell.CELL_CENTER);
+        }
+
+        return trs.transform(point, null);
+    }
+
+    /**
+     * Utility method to convert image bounds as {@link java.awt.Rectangle}.
+     * @return {@link java.awt.Rectangle} bounds.
+     */
+    private Rectangle getBounds() {
+        return new Rectangle(image.getMinX(), image.getMinY(), image.getWidth(), image.getHeight());
+    }
+
+    /**
+     * Converts a pixel's X coordinate into a horizontal tile index.
+     * @param x pixel x coordinate
+     * @return tile x coordinate
+     */
+    private int XToTileX(int x) {
+        int tileWidth = image.getTileWidth();
+        x -= image.getTileGridXOffset();
+        if (x < 0) {
+            x += 1 - tileWidth;
+        }
+        return x/tileWidth;
+    }
+
+    /**
+     * Converts a pixel's Y coordinate into a vertical tile index.
+     * @param y pixel x coordinate
+     * @return tile y coordinate
+     */
+    private int YToTileY(int y) {
+        int tileHeight = image.getTileHeight();
+        y -= image.getTileGridYOffset();
+        if (y < 0) {
+            y += 1 - tileHeight;
+        }
+        return y/tileHeight;
+    }
+
 }
diff --git a/core/sis-feature/src/test/java/org/apache/sis/internal/coverage/GridCoverage2DTest.java
b/core/sis-feature/src/test/java/org/apache/sis/internal/coverage/GridCoverage2DTest.java
index ed6d759..d1de1eb 100644
--- a/core/sis-feature/src/test/java/org/apache/sis/internal/coverage/GridCoverage2DTest.java
+++ b/core/sis-feature/src/test/java/org/apache/sis/internal/coverage/GridCoverage2DTest.java
@@ -40,6 +40,7 @@ import org.junit.Assert;
 import org.junit.Test;
 import org.opengis.referencing.datum.PixelInCell;
 import org.opengis.referencing.operation.MathTransform1D;
+import org.opengis.util.FactoryException;
 
 
 /**
@@ -55,7 +56,7 @@ public class GridCoverage2DTest extends TestCase {
      * Tests with a two-dimensional coverage.
      */
     @Test
-    public void testCoverage2D() {
+    public void testCoverage2D() throws FactoryException {
         /*
          * Create coverage of 2×2 pixels with an identity "grid to CRS" transform.
          * The range of sample values will be [-10 … +10]°C.


Mime
View raw message