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: Calculation of GridExtent from an Envelope resulting from an intersection shall support the case where the envelope as infinite bounds.
Date Fri, 11 Jan 2019 10:52:38 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 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 <martin.desruisseaux@geomatys.com>
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


Mime
View raw message