sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] branch geoapi-4.0 updated: GridDerivation.subgrid(GridGeometry) should modify the resolution to match the given `gridOfInterest`.
Date Fri, 05 Jul 2019 10:59:40 GMT
This is an automated email from the ASF dual-hosted git repository.

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


The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
     new 6371286  GridDerivation.subgrid(GridGeometry) should modify the resolution to match
the given `gridOfInterest`.
6371286 is described below

commit 6371286bfafe474ad1fa2ced8232289cba83c217
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Fri Jul 5 12:59:04 2019 +0200

    GridDerivation.subgrid(GridGeometry) should modify the resolution to match the given `gridOfInterest`.
---
 .../apache/sis/coverage/grid/GridDerivation.java   | 70 ++++++++++++----------
 .../org/apache/sis/coverage/grid/GridGeometry.java |  4 ++
 .../sis/coverage/grid/GridDerivationTest.java      | 30 +++++-----
 .../java/org/apache/sis/math/MathFunctions.java    |  6 +-
 .../apache/sis/internal/netcdf/RasterResource.java |  8 +--
 5 files changed, 63 insertions(+), 55 deletions(-)

diff --git a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridDerivation.java
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridDerivation.java
index ac9cdc1..7831d6f 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridDerivation.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridDerivation.java
@@ -145,9 +145,9 @@ public class GridDerivation {
     private int[] modifiedDimensions;
 
     /**
-     * An estimation of the multiplication factors when converting cell coordinates from
{@code gridOfInterest} to {@link #base}
-     * grid. Those factors appear in the order of <em>base</em> grid axes. May
be {@code null} if the conversion is identity.
-     * This is sometime redundant with {@link #toBase} but not always.
+     * An estimation of the multiplication factors when converting cell coordinates from
{@code gridOfInterest} to {@link #base} grid.
+     * Those factors appear in the order of <em>base</em> grid axes. May be {@code
null} if the conversion is identity.
+     * This is sometime redundant with {@link #toBase} but not always. All values are positives
or NaN.
      *
      * @see #getSubsamplings()
      */
@@ -334,11 +334,9 @@ public class GridDerivation {
 
     /**
      * Adapts the base grid for the geographic area and resolution of the given grid geometry.
-     * After this method invocation, {@code GridDerivation} will hold information about conversion
-     * from the given {@code gridOfInterest} to the {@link #base} grid geometry.
-     * Those information include the {@link MathTransform}s converting cell coordinates
-     * from the {@code gridOfInterest} to cell coordinates in the {@code base} grid,
-     * together with the grid extent that results from this conversion.
+     * The new grid geometry will cover the spatiotemporal region given by {@code gridOfInterest}
envelope
+     * (coordinate operations are applied as needed if the Coordinate Reference Systems are
not the same).
+     * The the new grid geometry resolution will be integer multiples of the {@link #base}
grid geometry resolution.
      *
      * <div class="note"><b>Usage:</b>
      * This method can be helpful for implementation of
@@ -425,6 +423,7 @@ public class GridDerivation {
              * call to `resolution(…)`, the domain must be the source of the `mapCenters`
transform.
              */
             scales = GridGeometry.resolution(mapCenters, domain);
+            subsample(getSubsamplings());
         }
         return this;
     }
@@ -691,36 +690,34 @@ public class GridDerivation {
         if (toBase != null) {
             throw new IllegalStateException(Errors.format(Errors.Keys.ValueAlreadyDefined_1,
"subsamplings"));
         }
+        // Validity of the subsamplings values will be verified by GridExtent.subsample(…)
invoked below.
         final GridExtent extent = (baseExtent != null) ? baseExtent : base.getExtent();
         Matrix affine = null;
-        scales = null;
-        if (subsamplings != null) {
-            // Validity of the subsamplings values will be verified by GridExtent.subsample(…)
invoked below.
-            final int dimension = extent.getDimension();
-            for (int i = Math.min(dimension, subsamplings.length); --i >= 0;) {
-                final int s = subsamplings[i];
-                if (s != 1) {
-                    if (scales == null) {
-                        scaledExtent = extent.subsample(subsamplings);
-                        scales = new double[dimension];
-                        Arrays.fill(scales, 1);
-                        if (!scaledExtent.startsAtZero()) {
-                            affine = Matrices.createIdentity(dimension + 1);
-                        }
-                    }
-                    final double sd = s;
-                    scales[i] = sd;
-                    if (affine != null) {
-                        affine.setElement(i, i, sd);
-                        affine.setElement(i, dimension, extent.getLow(i) - scaledExtent.getLow(i)
* sd);
-                    }
+        final int dimension = extent.getDimension();
+        for (int i = Math.min(dimension, subsamplings.length); --i >= 0;) {
+            final int s = subsamplings[i];
+            if (s != 1) {
+                if (affine == null) {
+                    affine = Matrices.createIdentity(dimension + 1);
+                    scaledExtent = extent.subsample(subsamplings);
                 }
+                final double sd = s;
+                affine.setElement(i, i, sd);
+                affine.setElement(i, dimension, extent.getLow(i) - scaledExtent.getLow(i)
* sd);
             }
         }
         if (affine != null) {
             toBase = MathTransforms.linear(affine);
-        } else if (scales != null) {
-            toBase = MathTransforms.scale(scales);
+            /*
+             * Take the matrix scale factors as the resolutions, unless the scale factors
were already computed
+             * by subgrid(GridGeometry). In the later case the scales may have fractional
values, which we keep.
+             */
+            if (scales == null) {
+                scales = new double[dimension];
+                for (int i=0; i<dimension; i++) {
+                    scales[i] = affine.getElement(i,i);
+                }
+            }
         }
         return this;
     }
@@ -932,7 +929,8 @@ public class GridDerivation {
      *   <li><var>z′</var> = s₂⋅<var>z</var></li>
      * </ul>
      *
-     * Then this method returns {|s₀|, |s₁|, |s₂|} rounded toward zero and clamped
to 1
+     * Then this method returns {|s₀|, |s₁|, |s₂|} rounded toward zero or nearest integer
+     * (depending on the {@linkplain GridRoundingMode grid rounding mode}) and clamped to
1
      * (i.e. all values in the returned array are strictly positive, no zero values).
      * It means that an iteration over {@code gridOfInterest} grid coordinates with a step
Δ<var>x</var>=1
      * corresponds approximately to an iteration in {@link #base} grid coordinates with a
step of Δ<var>x′</var>=s₀,
@@ -954,7 +952,13 @@ public class GridDerivation {
         } else {
             subsamplings = new int[scales.length];
             for (int i=0; i<subsamplings.length; i++) {
-                subsamplings[i] = Math.max(1, (int) Math.nextUp(scales[i]));    // Really
want rounding toward 0.
+                final int s;
+                switch (rounding) {
+                    default:        throw new AssertionError(rounding);
+                    case NEAREST:   s = (int) Math.min(Math.round(scales[i]), Integer.MAX_VALUE);
break;
+                    case ENCLOSING: s = (int) Math.nextUp(scales[i]); break;
+                }
+                subsamplings[i] = Math.max(1, s);
             }
         }
         return subsamplings;
diff --git a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
index d5dd976..12169c1 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
@@ -931,6 +931,7 @@ public class GridGeometry implements Serializable {
 
     /**
      * Computes the resolution for the given grid extent and transform, or returns {@code
null} if unknown.
+     * Resolutions are given in order of target axes and give a scale factor from source
to target coordinates.
      * If the {@code gridToCRS} transform is linear, we do not even need to check the grid
extent; it can be null.
      * Otherwise (if the transform is non-linear) the extent is necessary. The easiest way
to estimate a resolution
      * is then to ask for the derivative at some arbitrary point (the point of interest).
@@ -941,6 +942,7 @@ public class GridGeometry implements Serializable {
      * @param  gridToCRS  a transform for which to compute the resolution, or {@code null}
if none.
      * @param  domain     the domain for which to get a resolution, or {@code null} if none.
      *                    If non-null, must be the source of {@code gridToCRS}.
+     * @return the resolutions as positive numbers. May contain NaN values.
      */
     static double[] resolution(final MathTransform gridToCRS, final GridExtent domain) {
         final Matrix matrix = MathTransforms.getMatrix(gridToCRS);
@@ -956,11 +958,13 @@ public class GridGeometry implements Serializable {
 
     /**
      * Computes the resolutions from the given matrix. This is the magnitude of each row
vector.
+     * Resolutions are given in order of target axes.
      *
      * @param  gridToCRS    Jacobian matrix or affine transform for which to compute the
resolution.
      * @param  numToIgnore  number of rows and columns to ignore at the end of the matrix.
      *         This is 0 if the matrix is a derivative (i.e. we ignore nothing), or 1 if
the matrix
      *         is an affine transform (i.e. we ignore the translation column and the [0 0
… 1] row).
+     * @return the resolutions as positive numbers. May contain NaN values.
      */
     private static double[] resolution(final Matrix gridToCRS, final int numToIgnore) {
         final double[] resolution = new double[gridToCRS.getNumRow() - numToIgnore];
diff --git a/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/GridDerivationTest.java
b/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/GridDerivationTest.java
index 290c260..fc0e164 100644
--- a/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/GridDerivationTest.java
+++ b/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/GridDerivationTest.java
@@ -115,27 +115,25 @@ public final strictfp class GridDerivationTest extends TestCase {
         GridExtentTest.assertExtentEquals(extent, 1, -1000, 8000);
         assertArrayEquals("subsamplings", new int[] {50, 300}, change.getSubsamplings());
      // s = scaleSource / scaleTarget
         /*
-         * If we do not ask for subsamplings, the 'gridToCRS' transforms shall be the same
than the 'target' geometry.
-         * The envelope is the intersection of the envelopes of 'source' and 'target' geometries,
documented above.
+         * Above (50, 300) subsampling shall be applied and the `gridToCRS` transform adjusted
consequently.
          */
-        GridGeometry tg = change.build();
-        assertSame("extent",      extent, tg.getExtent());
-        assertSame("CELL_CORNER", target.getGridToCRS(PixelInCell.CELL_CORNER), tg.getGridToCRS(PixelInCell.CELL_CORNER));
-        assertSame("CELL_CENTER", target.getGridToCRS(PixelInCell.CELL_CENTER), tg.getGridToCRS(PixelInCell.CELL_CENTER));
-        GeneralEnvelope expected = new GeneralEnvelope(2);
-        expected.setRange(0,  4200, 11300);
-        expected.setRange(1, -7501,  1500);
-        assertEnvelopeEquals(expected, tg.getEnvelope(), STRICT);
-        /*
-         * If we ask for subsamplings, then the envelope should be approximately the same
or smaller. Note that without
-         * the clipping documented in GridExtent(GridExtent, int...) constructor, the envelope
could be larger.
-         */
-        tg = change.subsample(50, 300).build();
-        assertEnvelopeEquals(expected, tg.getEnvelope(), STRICT);
+        final GridGeometry tg = change.build();
+        extent = tg.getExtent();
+        GridExtentTest.assertExtentEquals(extent, 0,  40, 110);
+        GridExtentTest.assertExtentEquals(extent, 1,  -3,  27);               // NEAREST
grid rounding mode.
         assertMatrixEquals("gridToCRS", new Matrix3(
                 100,    0, 200,
                   0, -300, 600,
                   0,    0,   1), MathTransforms.getMatrix(tg.getGridToCRS(PixelInCell.CELL_CORNER)),
STRICT);
+        /*
+         * The envelope is the intersection of the envelopes of `source` and `target` grid
geometries, documented above.
+         * That intersection should be approximately the same or smaller. Note that without
the clipping documented in
+         * `GridExtent(GridExtent, int...)` constructor, the envelope would have been larger.
+         */
+        GeneralEnvelope expected = new GeneralEnvelope(2);
+        expected.setRange(0,  4200, 11300);
+        expected.setRange(1, -7501,  1500);
+        assertEnvelopeEquals(expected, tg.getEnvelope(), STRICT);
     }
 
     /**
diff --git a/core/sis-utility/src/main/java/org/apache/sis/math/MathFunctions.java b/core/sis-utility/src/main/java/org/apache/sis/math/MathFunctions.java
index 79ff346..f0ee80c 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/math/MathFunctions.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/math/MathFunctions.java
@@ -197,6 +197,8 @@ public final class MathFunctions extends Static {
      *     sqrt(vector[0]² + vector[1]² + … + vector[length-1]²)
      * }
      *
+     * If the given vector contains a NaN value, then the result is NaN.
+     *
      * <div class="section">Implementation note</div>
      * In the special case where only one element is different than zero, this method
      * returns directly the {@linkplain Math#abs(double) absolute value} of that element
@@ -207,7 +209,7 @@ public final class MathFunctions extends Static {
      * Cartesian coordinate system}.
      *
      * @param  vector  the vector for which to compute the magnitude.
-     * @return the magnitude of the given vector.
+     * @return the magnitude of the given vector as a positive number, of NaN.
      *
      * @see Math#hypot(double, double)
      */
@@ -219,7 +221,7 @@ public final class MathFunctions extends Static {
         do if (i == 0) return 0;
         while ((v1 = vector[--i]) == 0);
 
-        // We have found a non-zero element. If it is the only one, returns it directly.
+        // We have found a non-zero element. If it is the only one, returns its absolute
value.
         double v2;
         do if (i == 0) return Math.abs(v1);
         while ((v2 = vector[--i]) == 0);
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/RasterResource.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/RasterResource.java
index 8dc07c0..908f8dc 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/RasterResource.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/RasterResource.java
@@ -564,12 +564,12 @@ public final class RasterResource extends AbstractGridResource implements
Resour
         final SampleDimension[] bands = new SampleDimension[rangeIndices.getNumBands()];
         int[] bandOffsets = null;                                                   // By
default, all bands start at index 0.
         try {
-            GridDerivation targetGeometry = gridGeometry.derive()
+            final GridDerivation targetGeometry = gridGeometry.derive()
                     .rounding(GridRoundingMode.ENCLOSING)
                     .subgrid(domain);
-            GridExtent     areaOfInterest = targetGeometry.getIntersection();       // Pixel
indices of data to read.
-            int[]          subsamplings   = targetGeometry.getSubsamplings();       // Slice
to read or subsampling to apply.
-            int            numBuffers     = bands.length;                           // By
default, one variable per band.
+            GridExtent areaOfInterest = targetGeometry.getIntersection();           // Pixel
indices of data to read.
+            int[]      subsamplings   = targetGeometry.getSubsamplings();           // Slice
to read or subsampling to apply.
+            int        numBuffers     = bands.length;                               // By
default, one variable per band.
             domain = targetGeometry.subsample(subsamplings).build();                // Adjust
user-specified domain to data geometry.
             if (bandDimension >= 0) {
                 areaOfInterest = rangeIndices.insertBandDimension(areaOfInterest, bandDimension);


Mime
View raw message