sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] 03/03: Make a better guess when 'gridToCRS' seems to be mapping pixel corner instead than pixel center.
Date Wed, 19 Dec 2018 18:54:51 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

commit e006851f4612ea3a90eefc6078308de3bdf21c8f
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Wed Dec 19 19:54:10 2018 +0100

    Make a better guess when 'gridToCRS' seems to be mapping pixel corner instead than pixel
center.
---
 .../java/org/apache/sis/internal/netcdf/Axis.java  | 44 ++++++++++++++++++++++
 .../java/org/apache/sis/internal/netcdf/Grid.java  | 19 +++++++++-
 .../org/apache/sis/internal/netcdf/Variable.java   | 16 +++++++-
 .../sis/internal/netcdf/ucar/VariableWrapper.java  |  4 +-
 4 files changed, 78 insertions(+), 5 deletions(-)

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 fa90581..55ca0cf 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
@@ -22,6 +22,8 @@ import java.util.Map;
 import java.util.HashMap;
 import java.io.IOException;
 import javax.measure.Unit;
+import javax.measure.UnitConverter;
+import javax.measure.IncommensurableException;
 import org.opengis.util.GenericName;
 import org.opengis.util.FactoryException;
 import org.opengis.referencing.cs.CSFactory;
@@ -34,8 +36,11 @@ import org.apache.sis.referencing.operation.transform.MathTransforms;
 import org.apache.sis.referencing.NamedIdentifier;
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.iso.Types;
 import org.apache.sis.util.ArraysExt;
+import org.apache.sis.measure.Longitude;
+import org.apache.sis.measure.Latitude;
 import org.apache.sis.measure.Units;
 import org.apache.sis.math.Vector;
 import ucar.nc2.constants.CDM;
@@ -244,6 +249,45 @@ public final class Axis extends NamedElement implements Comparable<Axis>
{
     }
 
     /**
+     * Returns {@code true} if coordinates in this axis seem to map cell corner instead than
cell center.
+     * A {@code false} value does not necessarily means that the axis maps cell center; it
can be unknown.
+     * This method assumes a geographic CRS.
+     *
+     * <p>From CF-Convention: <cite>"If bounds are not provided, an application
might reasonably assume the
+     * grid points to be at the centers of the cells, but we do not require that in this
standard."</cite>
+     * We nevertheless tries to guess by checking if the "cell center" convention would result
in coordinates
+     * outside the range of longitude or latitude values.</p>
+     */
+    final boolean isCellCorner() throws IOException, DataStoreException {
+        double min;
+        boolean wraparound;
+        switch (abbreviation) {
+            case 'λ': min = Longitude.MIN_VALUE; wraparound = true;  break;
+            case 'φ': min =  Latitude.MIN_VALUE; wraparound = false; break;
+            default: return false;
+        }
+        final Vector data = coordinates.read();
+        final int size = data.size();
+        if (size != 0) {
+            Unit<?> unit = getUnit();
+            if (unit == null) {
+                unit = Units.DEGREE;
+            }
+            try {
+                final UnitConverter uc = unit.getConverterToAny(Units.DEGREE);
+                if (wraparound && uc.convert(data.doubleValue(size - 1)) > Longitude.MAX_VALUE)
{
+                    min = 0;            // Replace [-180 … +180]° longitude range by [0
… 360]°.
+                }
+                return uc.convert(data.doubleValue(0)) == min;
+            } catch (IncommensurableException e) {
+                coordinates.error(Grid.class, "getGridGeometry", e, Errors.Keys.InconsistentUnitsForCS_1,
unit);
+
+            }
+        }
+        return false;
+    }
+
+    /**
      * Compares this axis with the given axis for ordering based on the dimensions declared
in a variable.
      * This is used for sorting axes in the same order than the dimension order on the variable
using axes.
      * This order is not necessarily the same than the order in which variables are listed
in the netCDF file.
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Grid.java b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Grid.java
index 8368e87..606ec0b 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Grid.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Grid.java
@@ -29,11 +29,13 @@ import org.opengis.referencing.operation.TransformException;
 import org.opengis.referencing.operation.MathTransformFactory;
 import org.opengis.referencing.cs.CoordinateSystem;
 import org.opengis.referencing.crs.SingleCRS;
+import org.opengis.referencing.crs.GeographicCRS;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.metadata.spatial.DimensionNameType;
 import org.apache.sis.internal.metadata.AxisDirections;
 import org.apache.sis.referencing.operation.matrix.Matrices;
 import org.apache.sis.referencing.operation.builder.LocalizationGridBuilder;
+import org.apache.sis.referencing.CRS;
 import org.apache.sis.coverage.grid.GridExtent;
 import org.apache.sis.coverage.grid.GridGeometry;
 import org.apache.sis.storage.DataStoreException;
@@ -379,7 +381,22 @@ findFree:       for (int srcDim : axis.sourceDimensions) {
                     gridToCRS = (gridToCRS == null) ? tr : factory.createConcatenatedTransform(gridToCRS,
tr);
                 }
             }
-            geometry = new GridGeometry(getExtent(axes), PixelInCell.CELL_CENTER, gridToCRS,
getCoordinateReferenceSystem(decoder));
+            /*
+             * From CF-Convention: "If bounds are not provided, an application might reasonably
assume the gridpoints
+             * to be at the centers of the cells, but we do not require that in this standard".
We nevertheless check
+             * if an axis thinks otherwise.
+             */
+            PixelInCell anchor = PixelInCell.CELL_CENTER;
+            final CoordinateReferenceSystem crs = getCoordinateReferenceSystem(decoder);
+            if (CRS.getHorizontalComponent(crs) instanceof GeographicCRS) {
+                for (final Axis axis : axes) {
+                    if (axis.isCellCorner()) {
+                        anchor = PixelInCell.CELL_CORNER;
+                        break;
+                    }
+                }
+            }
+            geometry = new GridGeometry(getExtent(axes), anchor, gridToCRS, crs);
         } catch (FactoryException | TransformException ex) {
             canNotCreate(decoder, "getGridGeometry", Resources.Keys.CanNotCreateGridGeometry_3,
ex);
         }
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java
index 985455b..e19ff21 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java
@@ -193,8 +193,7 @@ public abstract class Variable extends NamedElement {
             if (symbols != null && !symbols.isEmpty()) try {
                 unit = parseUnit(symbols);
             } catch (Exception ex) {
-                warning(listeners, Variable.class, "getUnit", ex, Errors.getResources(listeners.getLocale()),
-                        Errors.Keys.CanNotAssignUnitToVariable_2, getName(), symbols);
+                error(Variable.class, "getUnit", ex, Errors.Keys.CanNotAssignUnitToVariable_2,
getName(), symbols);
             }
         }
         return unit;
@@ -661,6 +660,19 @@ public abstract class Variable extends NamedElement {
     }
 
     /**
+     * Reports a warning to the listeners specified at construction time.
+     *
+     * @param  caller     the caller class to report, preferably a public class.
+     * @param  method     the caller method to report, preferable a public method.
+     * @param  exception  the exception that occurred, or {@code null} if none.
+     * @param  key        one or {@link Errors.Keys} constants.
+     * @param  arguments  values to be formatted in the {@link java.text.MessageFormat} pattern.
+     */
+    protected final void error(final Class<?> caller, final String method, final Exception
exception, final short key, final Object... arguments) {
+        warning(listeners, caller, method, exception, Errors.getResources(listeners.getLocale()),
key, arguments);
+    }
+
+    /**
      * Returns a string representation of this variable for debugging purpose.
      *
      * @return a string representation of this variable.
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java
index 2c081c7..b4d24cf 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java
@@ -364,7 +364,7 @@ final class VariableWrapper extends Variable {
     @Override
     public Vector read() throws IOException {
         final Array array = variable.read();                // May be cached by the UCAR
library.
-        return Vector.create(array.get1DJavaArray(array.getElementType()), variable.isUnsigned());
+        return createDecimalVector(array.get1DJavaArray(array.getElementType()), variable.isUnsigned());
     }
 
     /**
@@ -393,7 +393,7 @@ final class VariableWrapper extends Variable {
         } catch (InvalidRangeException e) {
             throw new DataStoreException(e);
         }
-        return createDecimalVector(array.get1DJavaArray(array.getElementType()), variable.isUnsigned());
+        return Vector.create(array.get1DJavaArray(array.getElementType()), variable.isUnsigned());
     }
 
     /**


Mime
View raw message