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 1ba1ab4  Calculation of GridExtent from an Envelope resulting from an 
intersection shall support the case where the envelope as infinite bounds.
1ba1ab4 is described below

commit 1ba1ab4b0ef7ea006b46e7cb5c01886ee45a4a0c
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Fri Jan 11 11:51:48 2019 +0100

    Calculation of GridExtent from an Envelope resulting from an intersection 
shall support the case where the envelope as infinite bounds.
---
 .../org/apache/sis/coverage/grid/GridExtent.java   | 149 +++++++++++----------
 1 file changed, 80 insertions(+), 69 deletions(-)

diff --git 
a/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridExtent.java 
b/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridExtent.java
index ae35569..046662a 100644
--- a/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridExtent.java
+++ b/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridExtent.java
@@ -317,80 +317,91 @@ public class GridExtent implements Serializable {
         final int dimension = envelope.getDimension();
         coordinates = (enclosing != null) ? enclosing.coordinates.clone() : 
allocate(dimension);
         for (int i=0; i<dimension; i++) {
-            final double min = envelope.getLower(i);
-            final double max = envelope.getUpper(i);
-            if (min >= Long.MIN_VALUE && max <= Long.MAX_VALUE && min <= max) {
-                long lower, upper;
-                switch (rounding) {
-                    default: {
-                        throw new AssertionError(rounding);
-                    }
-                    case ENCLOSING: {
-                        lower = (long) Math.floor(min);
-                        upper = (long) Math.ceil (max);
-                        if (lower != upper) upper--;                           
     // For making the coordinate inclusive.
-                        break;
-                    }
-                    case NEAREST: {
-                        lower = Math.round(min);
-                        upper = Math.round(max);
-                        if (lower != upper) upper--;                           
     // For making the coordinate inclusive.
-                        /*
-                         * The [lower … upper] range may be slightly larger 
than desired in some rounding error situations.
-                         * For example if 'min' was 1.49999 and 'max' was 
2.50001,  the rounding will create a [1…3] range
-                         * while there is actually only 2 pixels. We detect 
those rounding problems by comparing the spans
-                         * before and after rounding.  We attempt an 
adjustment only if the span mismatch is ±1, otherwise
-                         * the difference is assumed to be caused by overflow. 
On the three values that can be affected by
-                         * the adjustment (min, max and span), we change only 
the number which is farthest from an integer
-                         * value.
-                         */
-                        long error = (upper - lower) + 1;                      
     // Negative number if overflow.
-                        if (error >= 0) {
-                            final double span = envelope.getSpan(i);
-                            final long extent = Math.round(span);
-                            if (extent != 0 && Math.abs(error -= extent) == 1) 
{
-                                final double dmin = Math.abs(min - 
Math.rint(min));
-                                final double dmax = Math.abs(max - 
Math.rint(max));
-                                final boolean adjustMax = (dmax >= dmin);
-                                if (Math.abs(span - extent) < (adjustMax ? 
dmax : dmin)) {
-                                    if (adjustMax) upper = 
Math.subtractExact(upper, error);
-                                    else lower = Math.addExact(lower, error);
-                                }
-                            }
-                        }
-                    }
-                }
+            double min = envelope.getLower(i);
+            double max = envelope.getUpper(i);
+            final boolean isMinValid = (min >= Long.MIN_VALUE);
+            final boolean isMaxValid = (max <= Long.MAX_VALUE);
+            if (min > max || (!(isMinValid & isMaxValid) & enclosing == null)) 
{
                 /*
-                 * If the user specified a margin, add it now. The margin 
dimension indices follow the envelope
-                 * dimension indices.  Note that the resulting extent will be 
intersected with enclosing extent
-                 * at the next step, which may cancel the margin effect.
+                 * We do not throw an exception if 'enclosing' is non-null and 
envelope bounds are NaN
+                 * because this case occurs when the gridToCRS transform has a 
NaN scale factor.  Such
+                 * scale factor may occur with ranges like [0 … 0]. With a 
non-null 'enclosing' extent,
+                 * we can still have grid coordinates: they are inherited from 
'enclosing'. We require
+                 * the two bounds to be NaN, otherwise the reason for those 
NaN envelope bounds is not
+                 * a NaN scale factor.
                  */
-                if (margin != null && i < margin.length) {
-                    final int m = margin[i];
-                    lower = Math.subtractExact(lower, m);
-                    upper = Math.addExact(upper, m);
+                throw new IllegalArgumentException(Resources.format(
+                        Resources.Keys.IllegalGridEnvelope_3, 
getAxisIdentification(i,i), min, max));
+            }
+            if (!isMinValid) min = Long.MIN_VALUE;
+            if (!isMaxValid) max = Long.MAX_VALUE;
+            long lower, upper;
+            switch (rounding) {
+                default: {
+                    throw new AssertionError(rounding);
                 }
-                if (lower > upper) {
-                    upper += (lower - upper) >>> 1;         // (upper - lower) 
as unsigned integer: overflow-safe.
-                    lower = upper;
+                case ENCLOSING: {
+                    lower = (long) Math.floor(min);
+                    upper = (long) Math.ceil (max);
+                    if (lower != upper) upper--;                               
 // For making the coordinate inclusive.
+                    break;
                 }
-                /*
-                 * At this point the grid range has been computed (lower to 
upper).
-                 * Update the coordinates accordingly.
-                 */
-                final int m = getDimension();
-                if (enclosing != null) {
-                    final int lo = (modifiedDimensions != null) ? 
modifiedDimensions[i] : i;
-                    final int hi = lo + m;
-                    if (lower > coordinates[lo]) coordinates[lo] = 
Math.min(coordinates[hi], lower);
-                    if (upper < coordinates[hi]) coordinates[hi] = 
Math.max(coordinates[lo], upper);
-                } else {
-                    coordinates[i]   = lower;
-                    coordinates[i+m] = upper;
+                case NEAREST: {
+                    lower = Math.round(min);
+                    upper = Math.round(max);
+                    if (lower != upper) upper--;                               
 // For making the coordinate inclusive.
+                    /*
+                     * The [lower … upper] range may be slightly larger than 
desired in some rounding error situations.
+                     * For example if 'min' was 1.49999 and 'max' was 2.50001, 
 the rounding will create a [1…3] range
+                     * while there is actually only 2 pixels. We detect those 
rounding problems by comparing the spans
+                     * before and after rounding.  We attempt an adjustment 
only if the span mismatch is ±1, otherwise
+                     * the difference is assumed to be caused by overflow. On 
the three values that can be affected by
+                     * the adjustment (min, max and span), we change only the 
number which is farthest from an integer
+                     * value.
+                     */
+                    long error = (upper - lower) + 1;                          
 // Negative number if overflow.
+                    if (error >= 0) {
+                        final double span = envelope.getSpan(i);
+                        final long extent = Math.round(span);
+                        if (extent != 0 && Math.abs(error -= extent) == 1) {
+                            final double dmin = Math.abs(min - Math.rint(min));
+                            final double dmax = Math.abs(max - Math.rint(max));
+                            final boolean adjustMax = (dmax >= dmin);
+                            if (Math.abs(span - extent) < (adjustMax ? dmax : 
dmin)) {
+                                if (adjustMax) upper = 
Math.subtractExact(upper, error);
+                                else lower = Math.addExact(lower, error);
+                            }
+                        }
+                    }
                 }
-            } else if (enclosing == null || !Double.isNaN(min) || 
!Double.isNaN(max)) {
-                throw new IllegalArgumentException(Resources.format(
-                        Resources.Keys.IllegalGridEnvelope_3, 
getAxisIdentification(i,i), min, max));
+            }
+            /*
+             * If the user specified a margin, add it now. The margin 
dimension indices follow the envelope
+             * dimension indices.  Note that the resulting extent will be 
intersected with enclosing extent
+             * at the next step, which may cancel the margin effect.
+             */
+            if (margin != null && i < margin.length) {
+                final int m = margin[i];
+                lower = Math.subtractExact(lower, m);
+                upper = Math.addExact(upper, m);
+            }
+            if (lower > upper) {
+                upper += (lower - upper) >>> 1;         // (upper - lower) as 
unsigned integer: overflow-safe.
+                lower = upper;
+            }
+            /*
+             * At this point the grid range has been computed (lower to upper).
+             * Update the coordinates accordingly.
+             */
+            final int m = getDimension();
+            if (enclosing != null) {
+                final int lo = (modifiedDimensions != null) ? 
modifiedDimensions[i] : i;
+                final int hi = lo + m;
+                if (lower > coordinates[lo]) coordinates[lo] = 
Math.min(coordinates[hi], lower);
+                if (upper < coordinates[hi]) coordinates[hi] = 
Math.max(coordinates[lo], upper);
+            } else {
+                coordinates[i]   = lower;
+                coordinates[i+m] = upper;
             }
             /*
              * We do not throw an exception if 'enclosing' is non-null and 
envelope bounds are NaN

Reply via email to