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 b533404 If correction for ±180° meridian crossing results in a
GridGeometry well outside its original longitude range, apply a 360°
translation on the whole grid.
b533404 is described below
commit b5334040c030c76548d72c75d9d7654e45eab0f1
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Mon Apr 8 14:21:08 2019 +0200
If correction for ±180° meridian crossing results in a GridGeometry well
outside its original longitude range, apply a 360° translation on the whole
grid.
---
.../internal/referencing/WraparoundAdjustment.java | 2 +-
.../operation/builder/LinearTransformBuilder.java | 36 +++++++++++++++++++++-
.../operation/builder/LocalizationGridBuilder.java | 2 +-
.../java/org/apache/sis/internal/netcdf/Axis.java | 2 +-
4 files changed, 38 insertions(+), 4 deletions(-)
diff --git
a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/WraparoundAdjustment.java
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/WraparoundAdjustment.java
index a18fa73..b9e9da5 100644
---
a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/WraparoundAdjustment.java
+++
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/WraparoundAdjustment.java
@@ -309,7 +309,7 @@ public final class WraparoundAdjustment {
final double lowerToValidStart = ((validStart - lower) /
period) - lowerCycles; // In number of periods.
final double upperToValidEnd = ((validEnd - upper) /
period) - upperCycles;
final boolean lowerIsBefore = (lowerToValidStart > 0);
- final boolean upperIsAfter = (upperToValidEnd < 0);
+ final boolean upperIsAfter = (upperToValidEnd < 0);
if (lowerIsBefore != upperIsAfter) {
final double upperToValidStart = ((validStart - upper)
/ period) - upperCycles;
final double lowerToValidEnd = ((validEnd - lower)
/ period) - lowerCycles;
diff --git
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java
index ac05e77..eceb47a 100644
---
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java
+++
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java
@@ -1071,7 +1071,7 @@ search: for (int j=domain(); --j >= 0;) {
* @param direction the direction to walk through: 0 for columns or 1
for rows (higher dimensions are also possible).
* Value can be from 0 inclusive to {@link
#getSourceDimensions()} exclusive.
* The recommended direction is the direction of most
stable values, typically 1 (rows) for longitudes.
- * @param period that wraparound range (typically 360° for
longitudes).
+ * @param period that wraparound range (typically 360° for
longitudes). Must be strictly positive.
* @throws IllegalStateException if {@link #create(MathTransformFactory)
create(…)} has already been invoked.
*/
final void resolveWraparoundAxis(final int dimension, final int direction,
final double period) {
@@ -1083,12 +1083,18 @@ search: for (int j=domain(); --j >= 0;) {
}
final int page = stride * gridSize[direction]; // Index
offset for moving to next row or whatever is the next dimension.
final double threshold = period / 2;
+ double minValue = Double.POSITIVE_INFINITY;
+ double maxValue = Double.NEGATIVE_INFINITY;
+ double minAfter = Double.POSITIVE_INFINITY;
+ double maxAfter = Double.NEGATIVE_INFINITY;
double previous = coordinates[0];
for (int x=0; x<stride; x++) { // For
iterating over dimensions lower than 'dimension'.
for (int y=0; y<gridLength; y += page) { // For
iterating over dimensions greater than 'dimension'.
final int stop = y + page;
for (int i = x+y; i<stop; i += stride) {
double value = coordinates[i];
+ if (value < minValue) minValue = value;
+ if (value > maxValue) maxValue = value;
double delta = value - previous;
if (Math.abs(delta) > threshold) {
delta = Math.rint(delta / period) * period;
@@ -1096,6 +1102,8 @@ search: for (int j=domain(); --j >= 0;) {
coordinates[i] = value;
}
previous = value;
+ if (value < minAfter) minAfter = value;
+ if (value > maxAfter) maxAfter = value;
}
/*
* For the next scan, use as a reference the first value of
this scan. If our scan direction is 0
@@ -1115,6 +1123,32 @@ search: for (int j=domain(); --j >= 0;) {
previous = coordinates[x];
}
}
+ /*
+ * If some coordinates have been shifted, the range may become
unreasonable. For example we may get a
+ * range of [-440 … -160]° of longitude. Shift again in the direction
that provide the best intersection
+ * with original range.
+ */
+ final double Δmin = minValue - minAfter;
+ final double Δmax = maxValue - maxAfter;
+ if (Δmin != 0 || Δmax != 0) {
+ double shift = 0;
+ double intersection = 0;
+ final double minCycles = Math.floor(Math.min(Δmin, Δmax) / period);
+ final double maxCycles = Math.ceil (Math.max(Δmin, Δmax) / period);
+ for (double cycles = minCycles; cycles <= maxCycles; cycles++) {
+ final double s = cycles * period;
+ final double p = Math.min(maxValue, maxAfter + s) -
Math.max(minValue, minAfter + s);
+ if (p > intersection) {
+ intersection = p;
+ shift = s;
+ }
+ }
+ if (shift != 0) {
+ for (int i=0; i<coordinates.length; i++) {
+ coordinates[i] += shift;
+ }
+ }
+ }
}
/**
diff --git
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LocalizationGridBuilder.java
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LocalizationGridBuilder.java
index ad9f013..e115b41 100644
---
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LocalizationGridBuilder.java
+++
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LocalizationGridBuilder.java
@@ -515,7 +515,7 @@ public class LocalizationGridBuilder extends
TransformBuilder {
* This is 0 for longitude dimension in a
(<var>longitudes</var>, <var>latitudes</var>) grid.
* @param direction the direction to walk through: 0 for columns or 1
for rows.
* The recommended direction is the direction of most
stable values, typically 1 (rows) for longitudes.
- * @param period that wraparound range (typically 360° for
longitudes).
+ * @param period that wraparound range (typically 360° for
longitudes). Must be strictly positive.
* @throws IllegalStateException if {@link #create(MathTransformFactory)
create(…)} has already been invoked.
*
* @since 1.0
diff --git
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Axis.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Axis.java
index 67e602b..2b8438a 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Axis.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Axis.java
@@ -412,7 +412,7 @@ public final class Axis extends NamedElement {
@SuppressWarnings("fallthrough")
private double wraparoundRange() {
if (isWraparound()) {
- double period = 360;
+ double period = Longitude.MAX_VALUE - Longitude.MIN_VALUE;
final Unit<?> unit = getUnit();
if (unit != null) try {
period = unit.getConverterToAny(Units.DEGREE).convert(period);