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