sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1718274 - in /sis/branches/JDK8: core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ core/sis-referencing/src/main/resources/ME...
Date Mon, 07 Dec 2015 09:58:55 GMT
Author: desruisseaux
Date: Mon Dec  7 09:58:55 2015
New Revision: 1718274

URL: http://svn.apache.org/viewvc?rev=1718274&view=rev
Log:
Add support for NADCON datum shift grid files.

Added:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/DatumShiftGridLoader.java   (with props)
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/NADCON.java   (with props)
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/NADCONTest.java   (with props)
    sis/branches/JDK8/core/sis-referencing/src/test/resources/org/apache/sis/internal/referencing/provider/conus-extract.laa   (with props)
    sis/branches/JDK8/core/sis-referencing/src/test/resources/org/apache/sis/internal/referencing/provider/conus-extract.loa   (with props)
Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/DatumShiftGridFile.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/FranceGeocentricInterpolation.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/NTv2.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedGeocentricTransform.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedTransform.java
    sis/branches/JDK8/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/AllProvidersTest.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/NTv2Test.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/InterpolatedTransformTest.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
    sis/branches/JDK8/ide-project/NetBeans/build.xml

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/DatumShiftGridFile.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/DatumShiftGridFile.java?rev=1718274&r1=1718273&r2=1718274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/DatumShiftGridFile.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/DatumShiftGridFile.java [UTF-8] Mon Dec  7 09:58:55 2015
@@ -20,13 +20,17 @@ import java.util.Arrays;
 import java.lang.reflect.Array;
 import javax.measure.unit.Unit;
 import javax.measure.quantity.Quantity;
+import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.parameter.ParameterDescriptorGroup;
+import org.opengis.parameter.GeneralParameterDescriptor;
 import org.opengis.referencing.operation.NoninvertibleTransformException;
 import org.apache.sis.math.DecimalFunctions;
 import org.apache.sis.util.collection.Cache;
+import org.apache.sis.util.Debug;
+import org.apache.sis.parameter.Parameters;
 import org.apache.sis.referencing.datum.DatumShiftGrid;
-import org.apache.sis.internal.referencing.j2d.AffineTransform2D;
 import org.apache.sis.referencing.operation.transform.LinearTransform;
+import org.apache.sis.internal.referencing.j2d.AffineTransform2D;
 
 // Branch-specific imports
 import java.nio.file.Path;
@@ -81,11 +85,11 @@ public abstract class DatumShiftGridFile
     public final ParameterDescriptorGroup descriptor;
 
     /**
-     * The file from which the grid has been loaded. This is not used directly by this class
+     * The files from which the grid has been loaded. This is not used directly by this class
      * (except for {@link #equals(Object)} and {@link #hashCode()}), but can be used by math
      * transform for setting the parameter values.
      */
-    public final Path file;
+    private final Path[] files;
 
     /**
      * Number of grid cells along the <var>x</var> axis.
@@ -120,14 +124,17 @@ public abstract class DatumShiftGridFile
                        final double Δx, final double Δy,
                        final int    nx, final int    ny,
                        final ParameterDescriptorGroup descriptor,
-                       final Path file) throws NoninvertibleTransformException
+                       final Path... files) throws NoninvertibleTransformException
     {
         super(coordinateUnit, (LinearTransform) new AffineTransform2D(Δx, 0, 0, Δy, x0, y0).inverse(),
                 new int[] {nx, ny}, isCellValueRatio, translationUnit);
         this.descriptor = descriptor;
-        this.file       = file;
+        this.files      = files;
         this.nx         = nx;
         this.accuracy   = Double.NaN;
+        if (files.length == 0) {
+            throw new IllegalArgumentException();
+        }
     }
 
     /**
@@ -138,7 +145,7 @@ public abstract class DatumShiftGridFile
     DatumShiftGridFile(final DatumShiftGridFile<C,T> other) {
         super(other);
         descriptor = other.descriptor;
-        file       = other.file;
+        files      = other.files;
         nx         = other.nx;
         accuracy   = other.accuracy;
     }
@@ -184,6 +191,24 @@ public abstract class DatumShiftGridFile
     abstract Object[] getData();
 
     /**
+     * Sets all parameters for a value of type {@link Path} to the values given to th constructor.
+     *
+     * @param parameters The parameter group where to set the values.
+     */
+    public final void setFileParameters(final Parameters parameters) {
+        int i = 0;  // The 'files' array should always contains at least one element.
+        for (final GeneralParameterDescriptor gd : descriptor.descriptors()) {
+            if (gd instanceof ParameterDescriptor<?>) {
+                final ParameterDescriptor<?> d = (ParameterDescriptor<?>) gd;
+                if (Path.class.isAssignableFrom(d.getValueClass())) {
+                    parameters.getOrCreate(d).setValue(files[i]);
+                    if (++i == files.length) break;
+                }
+            }
+        }
+    }
+
+    /**
      * Returns {@code this} casted to the given type, after verification that those types are valid.
      */
     @SuppressWarnings("unchecked")
@@ -209,7 +234,7 @@ public abstract class DatumShiftGridFile
         }
         if (super.equals(other)) {
             final DatumShiftGridFile<?,?> that = (DatumShiftGridFile<?,?>) other;
-            return file.equals(that.file) && Arrays.deepEquals(getData(), that.getData());
+            return Arrays.equals(files, that.files) && Arrays.deepEquals(getData(), that.getData());
         }
         return false;
     }
@@ -221,7 +246,7 @@ public abstract class DatumShiftGridFile
      */
     @Override
     public int hashCode() {
-        return super.hashCode() + file.hashCode();
+        return super.hashCode() + Arrays.hashCode(files);
     }
 
     /**
@@ -229,9 +254,10 @@ public abstract class DatumShiftGridFile
      *
      * @return A string representation for debugging purpose.
      */
+    @Debug
     @Override
     public String toString() {
-        return "DatumShiftGrid[\"" + file.getFileName() + "\"]";
+        return "DatumShiftGrid[\"" + files[0].getFileName() + "\"]";
     }
 
 
@@ -260,16 +286,17 @@ public abstract class DatumShiftGridFile
          * Creates a new datum shift grid with the given grid geometry, filename and number of shift dimensions.
          * All {@code double} values given to this constructor will be converted from degrees to radians.
          */
-        Float(final Unit<C> coordinateUnit,
+        Float(final int dim,
+              final Unit<C> coordinateUnit,
               final Unit<T> translationUnit,
               final boolean isCellValueRatio,
               final double x0, final double y0,
               final double Δx, final double Δy,
               final int    nx, final int    ny,
               final ParameterDescriptorGroup descriptor,
-              final Path file, final int dim) throws NoninvertibleTransformException
+              final Path... files) throws NoninvertibleTransformException
         {
-            super(coordinateUnit, translationUnit, isCellValueRatio, x0, y0, Δx, Δy, nx, ny, descriptor, file);
+            super(coordinateUnit, translationUnit, isCellValueRatio, x0, y0, Δx, Δy, nx, ny, descriptor, files);
             offsets = new float[dim][];
             final int size = Math.multiplyExact(nx, ny);
             for (int i=0; i<dim; i++) {

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/DatumShiftGridLoader.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/DatumShiftGridLoader.java?rev=1718274&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/DatumShiftGridLoader.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/DatumShiftGridLoader.java [UTF-8] Mon Dec  7 09:58:55 2015
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.referencing.provider;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ReadableByteChannel;
+import org.apache.sis.util.resources.Errors;
+
+// Branch-dependent imports
+import java.nio.file.Path;
+
+
+/**
+ * Base class of datum shift grid loaders.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.7
+ * @version 0.7
+ * @module
+ */
+class DatumShiftGridLoader {
+    /**
+     * Conversion factor from degrees to seconds.
+     */
+    static final double DEGREES_TO_SECONDS = 3600;
+
+    /**
+     * Possible precision for offset values in seconds of angle. This value is used only as a hint
+     * when attempting to compress the grid in arrays of {@code short} values. It does not hurt if
+     * this value is wrong, as it will only cause the grid to not be compressed.
+     *
+     * <p>Some interesting values:</p>
+     * <ul>
+     *   <li>1E-4 is about 3 millimetres on Earth.</li>
+     *   <li>1E-6 matches the precision found in ASCII outputs of NADCON grids.</li>
+     *   <li>1E-7 is about 1 ULP of 1 second of angle.</li>
+     * </ul>
+     *
+     * We use a value of 1E-4 because more accurate values tend to cause overflows in the compression algorithm,
+     * in which case the compression fails. With a more reasonable value, we have better chances of success.
+     */
+    static final double SECOND_PRECISION = 1E-4;
+
+    /**
+     * The file to load, used only if we have errors to report.
+     */
+    final Path file;
+
+    /**
+     * The channel opened on the file.
+     */
+    private final ReadableByteChannel channel;
+
+    /**
+     * The buffer to use for transferring data from the channel.
+     */
+    final ByteBuffer buffer;
+
+    /**
+     * Creates a new loader for the given channel and an existing buffer.
+     *
+     * @param  channel Where to read data from.
+     * @param  buffer  The buffer to use.
+     * @param  file    Path to the longitude or latitude difference file. Used only for error reporting.
+     */
+    DatumShiftGridLoader(final ReadableByteChannel channel, final ByteBuffer buffer, final Path file) throws IOException {
+        this.file    = file;
+        this.buffer  = buffer;
+        this.channel = channel;
+        channel.read(buffer);
+        buffer.flip();
+    }
+
+    /**
+     * Makes sure that the buffer contains at least <var>n</var> remaining bytes.
+     * It is caller's responsibility to ensure that the given number of bytes is
+     * not greater than the {@linkplain ByteBuffer#capacity() buffer capacity}.
+     *
+     * @param  n The minimal number of bytes needed in the {@linkplain #buffer}.
+     * @throws EOFException If the channel has reached the end of stream.
+     * @throws IOException If an other kind of error occurred while reading.
+     */
+    final void ensureBufferContains(int n) throws IOException {
+        assert n >= 0 && n <= buffer.capacity() : n;
+        n -= buffer.remaining();
+        if (n > 0) {
+            buffer.compact();
+            do {
+                final int c = channel.read(buffer);
+                if (c <= 0) {
+                    if (c != 0) {
+                        throw new EOFException(Errors.format(Errors.Keys.UnexpectedEndOfFile_1, file));
+                    } else {
+                        throw new IOException(Errors.format(Errors.Keys.CanNotRead_1, file));
+                    }
+                }
+                n -= c;
+            } while (n > 0);
+            buffer.flip();
+        }
+    }
+
+    /**
+     * Skips exactly <var>n</var> bytes.
+     */
+    final void skip(int n) throws IOException {
+        int p;
+        while ((p = buffer.position() + n) > buffer.limit()) {
+            n -= buffer.remaining();
+            buffer.clear();
+            ensureBufferContains(Math.min(n, buffer.capacity()));
+        }
+        buffer.position(p);
+    }
+}

Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/DatumShiftGridLoader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/DatumShiftGridLoader.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/FranceGeocentricInterpolation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/FranceGeocentricInterpolation.java?rev=1718274&r1=1718273&r2=1718274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/FranceGeocentricInterpolation.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/FranceGeocentricInterpolation.java [UTF-8] Mon Dec  7 09:58:55 2015
@@ -424,9 +424,9 @@ public final class FranceGeocentricInter
                             Δy = gridGeometry[5];
                             nx = Math.toIntExact(Math.round((xf - x0) / Δx + 1));
                             ny = Math.toIntExact(Math.round((yf - y0) / Δy + 1));
-                            grid = new DatumShiftGridFile.Float<>(
+                            grid = new DatumShiftGridFile.Float<>(3,
                                     NonSI.DEGREE_ANGLE, SI.METRE, false,
-                                    x0, y0, Δx, Δy, nx, ny, PARAMETERS, file, 3);
+                                    x0, y0, Δx, Δy, nx, ny, PARAMETERS, file);
                         }
                         break;
                     }

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/NADCON.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/NADCON.java?rev=1718274&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/NADCON.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/NADCON.java [UTF-8] Mon Dec  7 09:58:55 2015
@@ -0,0 +1,453 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.referencing.provider;
+
+import java.io.IOException;
+import java.nio.ByteOrder;
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
+import java.nio.channels.ReadableByteChannel;
+import javax.xml.bind.annotation.XmlTransient;
+import javax.measure.quantity.Angle;
+import javax.measure.unit.NonSI;
+import org.opengis.util.FactoryException;
+import org.opengis.parameter.ParameterDescriptor;
+import org.opengis.parameter.ParameterDescriptorGroup;
+import org.opengis.parameter.ParameterNotFoundException;
+import org.opengis.parameter.ParameterValueGroup;
+import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.MathTransformFactory;
+import org.opengis.referencing.operation.Transformation;
+import org.opengis.referencing.operation.NoninvertibleTransformException;
+import org.apache.sis.referencing.operation.transform.InterpolatedTransform;
+import org.apache.sis.parameter.ParameterBuilder;
+import org.apache.sis.parameter.Parameters;
+import org.apache.sis.util.collection.Cache;
+import org.apache.sis.util.resources.Errors;
+
+// Branch-dependent imports
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.Files;
+
+
+/**
+ * The provider for <cite>"North American Datum Conversion"</cite> (EPSG:9613).
+ * This transform requires data that are not bundled by default with Apache SIS.
+ *
+ * <p>The files given in parameters are theoretically binary files. However this provider accepts also ASCII files.
+ * Those two kinds of files are recognized automatically; there is no need to specify whether the files are ASCII
+ * or binary.</p>
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @author  Rueben Schulz (UBC)
+ * @since   0.7
+ * @version 0.7
+ * @module
+ *
+ * @see <a href="http://www.ngs.noaa.gov/cgi-bin/nadcon.prl">NADCON on-line computation</a>
+ */
+@XmlTransient
+public final class NADCON extends AbstractProvider {
+    /**
+     * Serial number for inter-operability with different versions.
+     */
+    private static final long serialVersionUID = -4707304160205218546L;
+
+    /**
+     * The operation parameter descriptor for the <cite>"Latitude difference file"</cite> parameter value.
+     * The default value is {@code "conus.las"}.
+     */
+    private static final ParameterDescriptor<Path> LATITUDE;
+
+    /**
+     * The operation parameter descriptor for the <cite>"Longitude difference file"</cite> parameter value.
+     * The default value is {@code "conus.los"}.
+     */
+    private static final ParameterDescriptor<Path> LONGITUDE;
+
+    /**
+     * The group of all parameters expected by this coordinate operation.
+     */
+    public static final ParameterDescriptorGroup PARAMETERS;
+    static {
+        final ParameterBuilder builder = builder();
+        LATITUDE = builder
+                .addIdentifier("8657")
+                .addName("Latitude difference file")
+                .create(Path.class, Paths.get("conus.las"));
+        LONGITUDE = builder
+                .addIdentifier("8658")
+                .addName("Longitude difference file")
+                .create(Path.class, Paths.get("conus.los"));
+        PARAMETERS = builder
+                .addIdentifier("9613")
+                .addName("NADCON")
+                .createGroup(LATITUDE, LONGITUDE);
+    }
+
+    /**
+     * Creates a new provider.
+     */
+    public NADCON() {
+        super(2, 2, PARAMETERS);
+    }
+
+    /**
+     * Returns the base interface of the {@code CoordinateOperation} instances that use this method.
+     *
+     * @return Fixed to {@link Transformation}.
+     */
+    @Override
+    public Class<Transformation> getOperationType() {
+        return Transformation.class;
+    }
+
+    /**
+     * Creates a transform from the specified group of parameter values.
+     *
+     * @param  factory The factory to use if this constructor needs to create other math transforms.
+     * @param  values The group of parameter values.
+     * @return The created math transform.
+     * @throws ParameterNotFoundException if a required parameter was not found.
+     * @throws FactoryException if an error occurred while loading the grid.
+     */
+    @Override
+    public MathTransform createMathTransform(final MathTransformFactory factory, final ParameterValueGroup values)
+            throws ParameterNotFoundException, FactoryException
+    {
+        final Parameters pg  = Parameters.castOrWrap(values);
+        return InterpolatedTransform.createGeodeticTransformation(factory,
+                getOrLoad(pg.getValue(LATITUDE), pg.getValue(LONGITUDE)));
+    }
+
+    /**
+     * Returns the grid of the given name. This method returns the cached instance if it still exists,
+     * or load the grid otherwise.
+     *
+     * @param latitude   Name of the grid file for latitude shifts.
+     * @param longitude  Name of the grid file for longitude shifts.
+     */
+    static DatumShiftGridFile<Angle,Angle> getOrLoad(final Path latitude, final Path longitude)
+            throws FactoryException
+    {
+        DatumShiftGridFile<?,?> grid = DatumShiftGridFile.CACHE.peek(latitude);
+        if (grid == null) {
+            final Cache.Handler<DatumShiftGridFile<?,?>> handler = DatumShiftGridFile.CACHE.lock(latitude);
+            try {
+                grid = handler.peek();
+                if (grid == null) {
+                    final Loader loader;
+                    Path file = null;
+                    try {
+                        // Note: buffer size must be divisible by the size of 'float' data type.
+                        final ByteBuffer buffer = ByteBuffer.allocate(4096).order(ByteOrder.LITTLE_ENDIAN);
+                        final FloatBuffer fb = buffer.asFloatBuffer();
+                        try (final ReadableByteChannel in = Files.newByteChannel(file = latitude)) {
+                            loader = new Loader(in, buffer, file);
+                            loader.readGrid(fb, null, longitude);
+                        }
+                        buffer.clear();
+                        try (final ReadableByteChannel in = Files.newByteChannel(file = longitude)) {
+                            new Loader(in, buffer, file).readGrid(fb, loader, null);
+                        }
+                    } catch (IOException | NoninvertibleTransformException | RuntimeException e) {
+                        throw new FactoryException(Errors.format(Errors.Keys.CanNotParseFile_2, "NADCON", file), e);
+                    }
+                    grid = DatumShiftGridCompressed.compress(loader.grid, null, loader.grid.accuracy);
+                    grid = grid.useSharedData();
+                }
+            } finally {
+                handler.putAndUnlock(grid);
+            }
+        }
+        return grid.castTo(Angle.class, Angle.class);
+    }
+
+
+
+
+    /**
+     * Loaders of NADCON data. Instances of this class exist only at loading time.
+     * This class can read both binary and ASCII grid files.
+     *
+     * <div class="section">Binary format</div>
+     * NADCON binary files ({@code "*.las"} and {@code "*.los"}) are organized into records
+     * with the first record containing the header information, followed by the shift data.
+     * The length of each record (including header) depends on the number of columns.
+     *
+     * <p>Records are ordered from South to North. Each record (except the header) is an entire row of grid points,
+     * with values ordered from West to East. Each value is a {@code float} encoded in little endian byte order.
+     * Each record ends with a 4 byte separator.</p>
+     *
+     * @author  Martin Desruisseaux (Geomatys)
+     * @author  Rueben Schulz (UBC)
+     * @since   0.7
+     * @version 0.7
+     * @module
+     */
+    private static final class Loader extends DatumShiftGridLoader {
+        /**
+         * The length of the description in the header, in bytes.
+         * <ul>
+         *   <li>56 bytes of NADCON's identification: {@code "NADCON EXTRACTED REGION"}.</li>
+         *   <li>8 bytes of "PGM" (unknown meaning).</li>
+         * </ul>
+         */
+        private static final int DESCRIPTION_LENGTH = 64;
+
+        /**
+         * The first bytes that we expect to find the header (both binary and ASCII files).
+         * We use that as the format signature.
+         */
+        private static final String NADCON = "NADCON";
+
+        /**
+         * Longitude and latitude of of the first value in the first record, in degrees.
+         */
+        private final float x0, y0;
+
+        /**
+         * The difference between longitude (<var>Δx</var>) and latitude (<var>Δy</var>) cells, in degrees.
+         */
+        private final float Δx, Δy;
+
+        /**
+         * Number of longitude (<var>nx</var>) and latitude (<var>ny</var>) values.
+         */
+        private final int nx, ny, nz;
+
+        /**
+         * Temporary buffer for ASCII characters, or {@code null} if the file is a binary file.
+         */
+        private final StringBuilder ascii;
+
+        /**
+         * The grid created by {@link #readGrid(Loader)}.
+         */
+        DatumShiftGridFile.Float<Angle,Angle> grid;
+
+        /**
+         * Creates a new reader for the given channel. The file can be binary or ASCII.
+         * This constructor parses the header immediately, but does not read any grid.
+         *
+         * @param  channel Where to read data from.
+         * @param  buffer  The buffer to use. That buffer must use little endian byte order
+         *                 and have a capacity divisible by the size of the {@code float} type.
+         * @param  file    Path to the longitude or latitude difference file. Used only for error reporting.
+         */
+        Loader(final ReadableByteChannel channel, final ByteBuffer buffer, final Path file)
+                throws IOException, FactoryException
+        {
+            super(channel, buffer, file);
+            // After the description we need (3 int + 5 float) = 32 bytes
+            // for a binary header, or 74 characters for an ASCII header.
+            ensureBufferContains(DESCRIPTION_LENGTH + 80);
+            for (int i=0; i<NADCON.length(); i++) {
+                if (buffer.get() != NADCON.charAt(i)) {
+                    throw unexpectedFormat();
+                }
+            }
+            if (isASCII(buffer)) {
+                ascii = new StringBuilder();
+                nx = Integer.parseInt(nextWord());
+                ny = Integer.parseInt(nextWord());
+                nz = Integer.parseInt(nextWord());
+                x0 = Float.parseFloat(nextWord());
+                Δx = Float.parseFloat(nextWord());
+                y0 = Float.parseFloat(nextWord());
+                Δy = Float.parseFloat(nextWord());
+                     Float.parseFloat(nextWord());
+            } else {
+                ascii = null;
+                buffer.position(DESCRIPTION_LENGTH);
+                nx = buffer.getInt();     // Number of data elements in each record.
+                ny = buffer.getInt();     // Number of records in the file.
+                nz = buffer.getInt();     // Not used.
+                x0 = buffer.getFloat();   // Longitude of first record (westmost).
+                Δx = buffer.getFloat();   // Cell size in degrees of longitude.
+                y0 = buffer.getFloat();   // Latitude of first record (southmost).
+                Δy = buffer.getFloat();   // Cell size in degrees of latitude.
+                                          // One more float at this position, which we ignore.
+            }
+            if (nx < 8 || ny < 1 || nz < 1 || !(Δx > 0) || !(Δy > 0) || Float.isNaN(x0) || Float.isNaN(y0)) {
+                throw unexpectedFormat();
+            }
+            if (ascii == null) {
+                skip((nx + 1) * Float.BYTES - buffer.position());
+            }
+        }
+
+        /**
+         * Returns {@code true} if all remaining characters in the buffer are US-ASCII characters for real numbers,
+         * except the characters on the first line which may be any printable US-ASCII characters. If the content is
+         * assumed ASCII, then the buffer position is set to the first EOL character.
+         *
+         * @return {@code true} if the file seems to be an ASCII one.
+         */
+        private static boolean isASCII(final ByteBuffer buffer) {
+            int newLine = 0;
+            while (buffer.hasRemaining()) {
+                final char c = (char) buffer.get();
+                if (c != ' ' && !(c >= '+' && c <= '9' && c != ',' && c != '/')) {  // (space) + - . [0-9]
+                    if (c == '\r' || c == '\n') {
+                        if (newLine == 0) {
+                            newLine = buffer.position();
+                        }
+                    } else {
+                        if (newLine == 0 && c >= 32 & c <= 126) {
+                            continue;   // Accept other US-ASCII characters ony on the first line.
+                        }
+                        return false;
+                    }
+                }
+            }
+            if (newLine == 0) {
+                return false;   // If it was an ASCII file, we would have found at least one EOL character.
+            }
+            buffer.position(newLine);
+            return true;
+        }
+
+        /**
+         * Returns the next word from an ASCII file. This method is invoked only for parsing ASCII files,
+         * in which case the {@link #ascii} string builder is non-null.
+         */
+        private String nextWord() throws IOException {
+            char c;
+            do {
+                ensureBufferContains(1);
+                c = (char) buffer.get();
+            } while (Character.isWhitespace(c));
+            ascii.setLength(0);
+            do {
+                ascii.append(c);
+                ensureBufferContains(1);
+                c = (char) buffer.get();
+            } while (!Character.isWhitespace(c));
+            return ascii.toString();
+        }
+
+        /**
+         * Returns the exception to thrown in the file does not seems to be a NADCON format.
+         */
+        private FactoryException unexpectedFormat() {
+            return new FactoryException(Errors.format(Errors.Keys.UnexpectedFileFormat_2, NADCON, file));
+        }
+
+        /**
+         * Loads latitude or longitude shifts data. This method should be invoked twice:
+         *
+         * <ol>
+         *   <li>On an instance created for the latitude shifts file with a {@code latitude} argument set to null.</li>
+         *   <li>On an instance created for the longitude shifts file with a {@code latitude} argument set to the
+         *       instance created in the previous step.</li>
+         * </ol>
+         *
+         * The result is stored in the {@link #grid} field.
+         *
+         * @param fb        A {@code FloatBuffer} view over the full {@link #buffer} range.
+         * @param latitude  The previously loaded latitude shifts, or {@code null} if not yet loaded.
+         * @param longitude The file for the longitude grid, or {@code null} if identical to {@link #file}.
+         */
+        final void readGrid(final FloatBuffer fb, final Loader latitude, final Path longitude)
+                throws IOException, FactoryException, NoninvertibleTransformException
+        {
+            final int dim;
+            final double scale;
+            if (latitude == null) {
+                dim   = 1;                          // Dimension of latitudes.
+                scale = DEGREES_TO_SECONDS * Δy;    // NADCON shifts are positive north.
+                grid  = new DatumShiftGridFile.Float<>(2, NonSI.DEGREE_ANGLE, NonSI.DEGREE_ANGLE,
+                        true, x0, y0, Δx, Δy, nx, ny, PARAMETERS, file, longitude);
+                grid.accuracy = SECOND_PRECISION / DEGREES_TO_SECONDS;
+            } else {
+                if (x0 != latitude.x0 || Δx != latitude.Δx || nx != latitude.nx ||
+                    y0 != latitude.y0 || Δy != latitude.Δy || ny != latitude.ny || nz != latitude.nz)
+                {
+                    throw new FactoryException(Errors.format(Errors.Keys.MismatchedGridGeometry_2,
+                            latitude.file.getFileName(), file.getFileName()));
+                }
+                dim   = 0;                          // Dimension of longitudes
+                scale = -DEGREES_TO_SECONDS * Δx;   // NADCON shifts are positive west.
+                grid  = latitude.grid;              // Continue writing in existing grid.
+            }
+            final float[] array = grid.offsets[dim];
+            if (ascii != null) {
+                for (int i=0; i<array.length; i++) {
+                    array[i] = (float) (Double.parseDouble(nextWord()) / scale);
+                }
+            } else {
+                /*
+                 * Transfer all data from the FloatBuffer to the float[] array, except one float at the beginning
+                 * of every row which must be skipped. That skipped float value is not a translation value and is
+                 * expected to be always zero.
+                 */
+                syncView(fb);
+                int forCurrentRow = 0;
+                for (int i=0; i<array.length;) {
+                    if (forCurrentRow == 0) {
+                        if (!fb.hasRemaining()) {
+                            fillBuffer(fb);
+                        }
+                        if (fb.get() != 0) {
+                            throw unexpectedFormat();
+                        }
+                        forCurrentRow = nx;
+                    }
+                    int remaining = fb.remaining();
+                    if (remaining == 0) {
+                        fillBuffer(fb);
+                        remaining = fb.remaining();
+                    }
+                    final int n = Math.min(forCurrentRow, remaining);
+                    fb.get(array, i, n);
+                    forCurrentRow -= n;
+                    i += n;
+                }
+                /*
+                 * Convert seconds to degrees for consistency with the unit declared at the beginning of this method,
+                 * then divide by cell size for consistency with the 'isCellRatio = true' configuration.
+                 */
+                for (int i=0; i<array.length; i++) {
+                    array[i] /= scale;
+                }
+            }
+        }
+
+        /**
+         * Invoked when the given {@code FloatBuffer} buffer is empty. This method requests one {@code float}
+         * from the channel, but the channel will usually give us as many data as the buffer can contain.
+         */
+        private void fillBuffer(final FloatBuffer fb) throws IOException {
+            buffer.position(fb.position() * Float.BYTES).limit(fb.limit() * Float.BYTES);
+            ensureBufferContains(Float.BYTES);  // Require at least one float, but usually get many.
+            syncView(fb);
+        }
+
+        /**
+         * Sets the position and limit of the given {@code FloatBuffer} to the same position and limit
+         * than the underlying {@code ByteBuffer}, converted to units of {@code float} data type.
+         */
+        private void syncView(final FloatBuffer fb) {
+            if ((buffer.position() % Float.BYTES) != 0) {
+                buffer.compact();   // For bytes alignment with FloatBuffer.
+            }
+            fb.limit(buffer.limit() / Float.BYTES).position(buffer.position() / Float.BYTES);
+        }
+    }
+}

Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/NADCON.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/NADCON.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/NTv2.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/NTv2.java?rev=1718274&r1=1718273&r2=1718274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/NTv2.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/NTv2.java [UTF-8] Mon Dec  7 09:58:55 2015
@@ -23,7 +23,6 @@ import java.util.Arrays;
 import java.util.Locale;
 import java.util.logging.Level;
 import java.util.logging.LogRecord;
-import java.io.EOFException;
 import java.io.IOException;
 import java.nio.ByteOrder;
 import java.nio.ByteBuffer;
@@ -170,7 +169,7 @@ public final class NTv2 extends Abstract
      * @version 0.7
      * @module
      */
-    private static final class Loader {
+    private static final class Loader extends DatumShiftGridLoader {
         /**
          * Size of a record. This value applies to both the header records and the data records.
          * In the case of header records, this is the size of the key plus the size of the value.
@@ -222,21 +221,6 @@ public final class NTv2 extends Abstract
         }
 
         /**
-         * The file to load, used only if we have errors to report.
-         */
-        private final Path file;
-
-        /**
-         * The channel opened on the file.
-         */
-        private final ReadableByteChannel channel;
-
-        /**
-         * The buffer to use for transferring data from the channel.
-         */
-        private final ByteBuffer buffer;
-
-        /**
          * The header content. Keys are strings like {@code "VERSION"}, {@code "SYSTEM_F"},
          * <var>etc.</var>. Values are {@link String}, {@link Integer} or {@link Double}.
          * If some keys are unrecognized, they will be put in this map with the {@code null} value
@@ -264,12 +248,8 @@ public final class NTv2 extends Abstract
          * @throws FactoryException if a data record can not be parsed.
          */
         Loader(final ReadableByteChannel channel, final Path file) throws IOException, FactoryException {
-            this.file    = file;
-            this.channel = channel;
-            this.header  = new LinkedHashMap<>();
-            this.buffer  = ByteBuffer.allocate(4096);
-            channel.read(buffer);
-            buffer.flip();
+            super(channel, ByteBuffer.allocate(4096), file);
+            this.header = new LinkedHashMap<>();
             ensureBufferContains(RECORD_LENGTH);
             if (isLittleEndian(buffer.getInt(KEY_LENGTH))) {
                 buffer.order(ByteOrder.LITTLE_ENDIAN);
@@ -315,13 +295,13 @@ public final class NTv2 extends Abstract
             final String name = (String) get("GS_TYPE");
             if (name.equalsIgnoreCase("SECONDS")) {         // Most common value
                 unit = NonSI.SECOND_ANGLE;
-                precision = 1;
+                precision = SECOND_PRECISION;                       // Used only as a hint; will not hurt if wrong.
             } else if (name.equalsIgnoreCase("MINUTES")) {
                 unit = NonSI.MINUTE_ANGLE;
-                precision = 0.001;                          // Used only as a hint; will not hurt if wrong.
+                precision = SECOND_PRECISION / 60;                  // Used only as a hint; will not hurt if wrong.
             } else if (name.equalsIgnoreCase("DEGREES")) {
                 unit = NonSI.DEGREE_ANGLE;
-                precision = 0.00001;                        // Used only as a hint; will not hurt if wrong.
+                precision = SECOND_PRECISION / DEGREES_TO_SECONDS;  // Used only as a hint; will not hurt if wrong.
             } else {
                 throw new FactoryException(Errors.format(Errors.Keys.UnexpectedValueInElement_2, "GS_TYPE", name));
             }
@@ -346,8 +326,8 @@ public final class NTv2 extends Abstract
              * sign of longitude translations; instead, this reversal will be handled by grid.coordinateToGrid
              * MathTransform and its inverse.
              */
-            final DatumShiftGridFile.Float<Angle,Angle> grid = new DatumShiftGridFile.Float<>(
-                    unit, unit, true, -xmin, ymin, -dx, dy, width, height, PARAMETERS, file, 2);
+            final DatumShiftGridFile.Float<Angle,Angle> grid = new DatumShiftGridFile.Float<>(2,
+                    unit, unit, true, -xmin, ymin, -dx, dy, width, height, PARAMETERS, file);
             @SuppressWarnings("MismatchedReadAndWriteOfArray") final float[] tx = grid.offsets[0];
             @SuppressWarnings("MismatchedReadAndWriteOfArray") final float[] ty = grid.offsets[1];
             for (int i=0; i<count; i++) {
@@ -371,31 +351,6 @@ public final class NTv2 extends Abstract
         }
 
         /**
-         * Makes sure that the buffer contains at least <var>n</var> remaining bytes.
-         * It is caller's responsibility to ensure that the given number of bytes is
-         * not greater than the {@linkplain ByteBuffer#capacity() buffer capacity}.
-         *
-         * @param  n The minimal number of bytes needed in the {@linkplain #buffer}.
-         * @throws EOFException If the channel has reached the end of stream.
-         * @throws IOException If an other kind of error occurred while reading.
-         */
-        private void ensureBufferContains(int n) throws IOException {
-            assert n >= 0 && n <= buffer.capacity() : n;
-            n -= buffer.remaining();
-            if (n > 0) {
-                buffer.compact();
-                do {
-                    final int c = channel.read(buffer);
-                    if (c < 0) {
-                        throw new EOFException(Errors.format(Errors.Keys.UnexpectedEndOfFile_1, file));
-                    }
-                    n -= c;
-                } while (n > 0);
-                buffer.flip();
-            }
-        }
-
-        /**
          * Reads a string at the given position in the buffer.
          */
         private String readString(final int position, int length) {

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedGeocentricTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedGeocentricTransform.java?rev=1718274&r1=1718273&r2=1718274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedGeocentricTransform.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedGeocentricTransform.java [UTF-8] Mon Dec  7 09:58:55 2015
@@ -268,7 +268,7 @@ public class InterpolatedGeocentricTrans
             pg.getOrCreate(Molodensky.FLATTENING_DIFFERENCE) .setValue(Δf, Unit.ONE);
         }
         if (grid instanceof DatumShiftGridFile<?,?>) {
-            pg.getOrCreate(FranceGeocentricInterpolation.FILE).setValue(((DatumShiftGridFile<?,?>) grid).file);
+            ((DatumShiftGridFile<?,?>) grid).setFileParameters(pg);
         }
     }
 

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedTransform.java?rev=1718274&r1=1718273&r2=1718274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedTransform.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedTransform.java [UTF-8] Mon Dec  7 09:58:55 2015
@@ -25,8 +25,6 @@ import javax.measure.converter.UnitConve
 import javax.measure.converter.LinearConverter;
 import org.opengis.util.FactoryException;
 import org.opengis.parameter.ParameterValueGroup;
-import org.opengis.parameter.ParameterDescriptor;
-import org.opengis.parameter.GeneralParameterDescriptor;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.MathTransformFactory;
@@ -46,7 +44,6 @@ import org.apache.sis.internal.referenci
 
 // Branch-specific imports
 import java.util.Objects;
-import java.nio.file.Path;
 
 
 /**
@@ -166,20 +163,10 @@ public class InterpolatedTransform exten
          * Create the contextual parameters using the descriptor of the provider that created the datum shift grid.
          * If that provider is unknown, default (for now) to NTv2. This default may change in any future SIS version.
          */
+        context = new ContextualParameters((grid instanceof DatumShiftGridFile<?,?>)
+                ? ((DatumShiftGridFile<?,?>) grid).descriptor : NTv2.PARAMETERS, dimension + 1, dimension + 1);
         if (grid instanceof DatumShiftGridFile<?,?>) {
-            final DatumShiftGridFile<?,?> gridFile = (DatumShiftGridFile<?,?>) grid;
-            context = new ContextualParameters(gridFile.descriptor, dimension + 1, dimension + 1);
-            for (final GeneralParameterDescriptor gd : gridFile.descriptor.descriptors()) {
-                if (gd instanceof ParameterDescriptor<?>) {
-                    final ParameterDescriptor<?> d = (ParameterDescriptor<?>) gd;
-                    if (Path.class.isAssignableFrom(d.getValueClass())) {
-                        context.getOrCreate(d).setValue(gridFile.file);
-                        break;
-                    }
-                }
-            }
-        } else {
-            context = new ContextualParameters(NTv2.PARAMETERS, dimension + 1, dimension + 1);
+            ((DatumShiftGridFile<?,?>) grid).setFileParameters(context);
         }
         /*
          * Set the normalization matrix to the conversion from grid coordinates (e.g. seconds of angle)

Modified: sis/branches/JDK8/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod?rev=1718274&r1=1718273&r2=1718274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod [UTF-8] Mon Dec  7 09:58:55 2015
@@ -40,4 +40,5 @@ org.apache.sis.internal.referencing.prov
 org.apache.sis.internal.referencing.provider.PolarStereographicSouth
 org.apache.sis.internal.referencing.provider.ObliqueStereographic
 org.apache.sis.internal.referencing.provider.NTv2
+org.apache.sis.internal.referencing.provider.NADCON
 org.apache.sis.internal.referencing.provider.FranceGeocentricInterpolation

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/AllProvidersTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/AllProvidersTest.java?rev=1718274&r1=1718273&r2=1718274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/AllProvidersTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/AllProvidersTest.java [UTF-8] Mon Dec  7 09:58:55 2015
@@ -91,6 +91,7 @@ public final strictfp class AllProviders
             PolarStereographicSouth.class,
             ObliqueStereographic.class,
             NTv2.class,
+            NADCON.class,
             FranceGeocentricInterpolation.class
         };
     }

Added: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/NADCONTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/NADCONTest.java?rev=1718274&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/NADCONTest.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/NADCONTest.java [UTF-8] Mon Dec  7 09:58:55 2015
@@ -0,0 +1,252 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.referencing.provider;
+
+import java.util.Locale;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URISyntaxException;
+import javax.measure.unit.NonSI;
+import javax.measure.quantity.Angle;
+import org.opengis.geometry.Envelope;
+import org.opengis.util.FactoryException;
+import org.opengis.referencing.operation.TransformException;
+import org.apache.sis.referencing.operation.transform.LinearTransform;
+import org.apache.sis.referencing.operation.matrix.Matrix3;
+import org.apache.sis.geometry.Envelope2D;
+import org.apache.sis.geometry.Envelopes;
+import org.apache.sis.test.TestCase;
+import org.junit.Test;
+
+import static org.opengis.test.Assert.*;
+
+// Branch-dependent imports
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.Files;
+
+
+/**
+ * Tests the {@link NADCON} grid loader.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @author  Simon Reynard (Geomatys)
+ * @since   0.7
+ * @version 0.7
+ * @module
+ */
+public final strictfp class NADCONTest extends TestCase {
+    /**
+     * Returns the sample point for a step in the transformation from NAD27 to NAD83.
+     * The sample point is the coordinate of Meades Ranch station, which was the point
+     * relative to which all land measurements in USA were made for NAD27.
+     * Its position was officially set as 39°13′26.686″N, 98°32′30.506″W.
+     * Precision is given by {@link #ANGULAR_TOLERANCE}.
+     *
+     * <p>The coordinate in NAD83 has been computed with the
+     * <a href="http://www.ngs.noaa.gov/cgi-bin/nadcon.prl">NADCON tools on NOAA website.</a></p>
+     *
+     * @param  step The step as a value from 1 to 3 inclusive.
+     * @return The sample point at the given step.
+     */
+    public static double[] samplePoint(final int step) {
+        switch (step) {
+            case 1: return new double[] {               // NAD27 coordinate
+                      -(98 + (32 + 30.506/60)/60),      // 98°32′30.506″
+                        39 + (13 + 26.686/60)/60        // 39°13′26.686″
+                    };
+            case 2: return new double[] {               // Shift in seconds of angle
+                       -1.24121,                        // 1.24121″ (positive west in NADCON)
+                        0.03498                         // 0.03498″
+                    };
+            case 3: return new double[] {               // NAD83 coordinate
+                      -(98 + (32 + 31.74721/60)/60),    // 98°32′31.74721″
+                        39 + (13 + 26.72098/60)/60      // 39°13′26.72098″
+                    };
+            default: throw new AssertionError(step);
+        }
+    }
+
+    /**
+     * The tolerance when comparing coordinates in degrees.
+     * This tolerance is determined by the precision of the tools used for computing NAD83 coordinates.
+     */
+    public static final double ANGULAR_TOLERANCE = 0.5E-5 / DatumShiftGridLoader.DEGREES_TO_SECONDS;
+
+    /**
+     * Name of the file without extension containing a small extract of the NADCON grid.
+     * The {@code ".laa"} and {@code ".loa"} extension must be added to that name.
+     */
+    public static final String TEST_FILE = "conus-extract";
+
+    /**
+     * Tests loading a grid file and interpolating a sample point.
+     * The point used for this test is given by {@link #samplePoint(int)}.
+     *
+     * @throws URISyntaxException if the URL to the test file can not be converted to a path.
+     * @throws IOException if an error occurred while loading the grid.
+     * @throws FactoryException if an error occurred while computing the grid.
+     * @throws TransformException if an error occurred while computing the envelope.
+     */
+    @Test
+    public void testLoader() throws URISyntaxException, IOException, FactoryException, TransformException {
+        final URL latitudeShifts  = NADCONTest.class.getResource(TEST_FILE + ".laa");
+        final URL longitudeShifts = NADCONTest.class.getResource(TEST_FILE + ".loa");
+        assertNotNull("Test file \"" + TEST_FILE + ".laa\" not found.", latitudeShifts);
+        assertNotNull("Test file \"" + TEST_FILE + ".loa\" not found.", longitudeShifts);
+        testNADCON(Paths.get(latitudeShifts.toURI()),
+                   Paths.get(longitudeShifts.toURI()),
+                   -99.75, -98.0, 37.5, 39.75);
+    }
+
+    /**
+     * Tests loading an official {@code "conus.las"} and {@code "conus.los"} datum shift grid files and interpolating
+     * the sample point given by {@link #samplePoint(int)}. This test is normally not executed because Apache SIS does
+     * not redistribute the datum shift grid files. But developers can invoke this method explicitely if they can
+     * provide a path to those files.
+     *
+     * @param  latitudeShifts  Path to the official {@code "conus.las"} file.
+     * @param  longitudeShifts Path to the official {@code "conus.los"} file.
+     * @throws IOException if an error occurred while loading the grid.
+     * @throws FactoryException if an error occurred while computing the grid.
+     * @throws TransformException if an error occurred while computing the envelope.
+     */
+    public static void testNADCON(final Path latitudeShifts, final Path longitudeShifts)
+            throws IOException, FactoryException, TransformException
+    {
+        testNADCON(latitudeShifts, longitudeShifts, -131, -63, 20, 50);
+    }
+
+    /**
+     * Implementation of {@link #testLoader()} and {@link #testNADCON(Path)}.
+     *
+     * @param xmin Westmost longitude.
+     * @param xmax Eastmost longitude.
+     * @param ymin Southmost latitude.
+     * @param ymax Northmost latitude.
+     */
+    private static void testNADCON(final Path latitudeShifts, final Path longitudeShifts,
+            final double xmin, final double xmax, final double ymin, final double ymax)
+            throws IOException, FactoryException, TransformException
+    {
+        final DatumShiftGridFile<Angle,Angle> grid = NADCON.getOrLoad(latitudeShifts, longitudeShifts);
+        assertInstanceOf("Should not be compressed.", DatumShiftGridFile.Float.class, grid);
+        assertEquals("coordinateUnit",  NonSI.DEGREE_ANGLE, grid.getCoordinateUnit());
+        assertEquals("translationUnit", NonSI.DEGREE_ANGLE, grid.getTranslationUnit());
+        assertEquals("translationDimensions", 2, grid.getTranslationDimensions());
+        assertTrue  ("isCellValueRatio", grid.isCellValueRatio());
+        assertTrue  ("cellPrecision", grid.getCellPrecision() > 0);
+        /*
+         * Verify the envelope and the conversion between geographic coordinates and grid indices.
+         * The cells are expected to have the same size (0.25°) in longitudes and latitudes.
+         */
+        final double cellSize = 0.25;
+        final Envelope envelope = grid.getDomainOfValidity();
+        assertEquals("xmin", xmin - cellSize/2, envelope.getMinimum(0), STRICT);
+        assertEquals("xmax", xmax + cellSize/2, envelope.getMaximum(0), STRICT);
+        assertEquals("ymin", ymin - cellSize/2, envelope.getMinimum(1), STRICT);
+        assertEquals("ymax", ymax + cellSize/2, envelope.getMaximum(1), STRICT);
+        assertMatrixEquals("coordinateToGrid",
+                new Matrix3(cellSize,  0,  xmin,
+                            0,  cellSize,  ymin,
+                            0,         0,    1),
+                ((LinearTransform) grid.getCoordinateToGrid().inverse()).getMatrix(), STRICT);
+        /*
+         * Test the Meades Ranch station. If we were using the complete Conus files, we would obtain
+         * after conversion the grid indices listed on the left side. But since we are using a sub-set
+         * of the grid, we rather obtain the grid indices on the right side.
+         *
+         *   gridX ≈ 129.83277 in official file,   ≈ 4.83277 in the test file.
+         *   gridY ≈  76.89632 in official file,   ≈ 6.89632 in the test file.
+         */
+        final double[] position = samplePoint(1);
+        final double[] expected = samplePoint(2);
+        final double[] indices  = new double[position.length];
+        final double[] vector   = new double[2];
+        grid.getCoordinateToGrid().transform(position, 0, indices, 0, 1);
+        grid.interpolateInCell(indices[0], indices[1], vector);
+        vector[0] *= cellSize * DatumShiftGridLoader.DEGREES_TO_SECONDS;
+        vector[1] *= cellSize * DatumShiftGridLoader.DEGREES_TO_SECONDS;
+        assertArrayEquals("interpolateInCell", expected, vector, 0.5E-5);
+
+        // Same test than above, but let DatumShiftGrid do the conversions for us.
+        expected[0] /= DatumShiftGridLoader.DEGREES_TO_SECONDS;
+        expected[1] /= DatumShiftGridLoader.DEGREES_TO_SECONDS;
+        assertArrayEquals("interpolateAt", expected, grid.interpolateAt(position), ANGULAR_TOLERANCE);
+        assertSame("Grid should be cached.", grid, NADCON.getOrLoad(latitudeShifts, longitudeShifts));
+    }
+
+
+
+
+    //////////////////////////////////////////////////
+    ////////                                  ////////
+    ////////        TEST FILE CREATION        ////////
+    ////////                                  ////////
+    //////////////////////////////////////////////////
+
+    /**
+     * Writes a sub-grid of the given grid in pseudo-NADCON ASCII format.
+     * This method is used only for creating the test file, and the output is not fully NADCON compliant.
+     * We take this opportunity for testing the parser capability to be lenient.
+     *
+     * <p>This method has been executed once for creating the {@code "conus-extract.laa"} and
+     * {@code "conus-extract.loa"} test files and should not be needed anymore, but we keep it
+     * around in case we have new test files to generate. The parameter used for creating the
+     * test file are:</p>
+     *
+     * <ul>
+     *   <li>{@code gridX} = 125</li>
+     *   <li>{@code gridY} =  70</li>
+     *   <li>{@code nx}    =   8</li>
+     *   <li>{@code ny}    =  10</li>
+     * </ul>
+     *
+     * This ensure that the grid indices (129.83277, 76.89632) is included in the test file.
+     * Those grid indices is the location of the (39°13′26.71″N, 98°32′31.75″W) test point to interpolate.
+     *
+     * @param grid   The full grid from which to extract a few values.
+     * @param file   Where to write the test file.
+     * @param dim    0 for writing longitudes, or 1 for writing latitudes.
+     * @param gridX  Index along the longitude axis of the first cell to write.
+     * @param gridY  Index along the latitude axis of the first cell to write.
+     * @param nx     Number of cells to write along the longitude axis.
+     * @param ny     Number of cells to write along the latitude axis.
+     * @throws TransformException if an error occurred while computing the envelope.
+     * @throws IOException if an error occurred while writing the test file.
+     */
+    public static void writeSubGrid(final DatumShiftGridFile<Angle,Angle> grid, final Path file, final int dim,
+            final int gridX, final int gridY, final int nx, final int ny) throws IOException, TransformException
+    {
+        Envelope envelope = new Envelope2D(null, gridX, gridY, nx - 1, ny - 1);
+        envelope = Envelopes.transform(grid.getCoordinateToGrid().inverse(), envelope);
+        try (final BufferedWriter out = Files.newBufferedWriter(file)) {
+            out.write("NADCON EXTRACTED REGION\n");
+            out.write(String.format(Locale.US, "%4d %3d %3d %11.5f %11.5f %11.5f %11.5f %11.5f\n", nx, ny, 1,
+                    envelope.getMinimum(0), envelope.getSpan(0) / (nx - 1),
+                    envelope.getMinimum(1), envelope.getSpan(1) / (ny - 1),
+                    0.0));
+            for (int y=0; y<ny; y++) {
+                for (int x=0; x<nx; x++) {
+                    out.write(String.format(Locale.US, " %11.6f", grid.getCellValue(dim, gridX + x, gridY + y)));
+                }
+                out.write('\n');
+            }
+        }
+    }
+}

Propchange: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/NADCONTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/NADCONTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/NTv2Test.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/NTv2Test.java?rev=1718274&r1=1718273&r2=1718274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/NTv2Test.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/NTv2Test.java [UTF-8] Mon Dec  7 09:58:55 2015
@@ -63,11 +63,6 @@ public final strictfp class NTv2Test ext
     public static final String TEST_FILE = "NTF_R93-extract.gsb";
 
     /**
-     * Conversion factor from degrees to seconds.
-     */
-    private static final double DEGREES_TO_SECONDS = 3600;
-
-    /**
      * Best accuracy found in the "{@code NTF_R93.gsb}" file.
      */
     private static final float ACCURACY = 0.001618f;
@@ -154,8 +149,8 @@ public final strictfp class NTv2Test ext
         final double[] indices  = new double[position.length];
         final double[] vector   = new double[2];
         for (int i=0; i<expected.length; i++) {
-            position[i] *= DEGREES_TO_SECONDS;
-            expected[i] *= DEGREES_TO_SECONDS;
+            position[i] *= DatumShiftGridLoader.DEGREES_TO_SECONDS;
+            expected[i] *= DatumShiftGridLoader.DEGREES_TO_SECONDS;
             expected[i] -= position[i];  // We will test the interpolated shifts rather than final coordinates.
         }
         grid.getCoordinateToGrid().transform(position, 0, indices, 0, 1);
@@ -163,11 +158,11 @@ public final strictfp class NTv2Test ext
         vector[0] *= -cellSize;   // Was positive toward west.
         vector[1] *= +cellSize;
         assertArrayEquals("interpolateInCell", expected, vector,
-                FranceGeocentricInterpolationTest.ANGULAR_TOLERANCE * DEGREES_TO_SECONDS);
+                FranceGeocentricInterpolationTest.ANGULAR_TOLERANCE * DatumShiftGridLoader.DEGREES_TO_SECONDS);
 
         // Same test than above, but let DatumShiftGrid do the conversions for us.
         assertArrayEquals("interpolateAt", expected, grid.interpolateAt(position),
-                FranceGeocentricInterpolationTest.ANGULAR_TOLERANCE * DEGREES_TO_SECONDS);
+                FranceGeocentricInterpolationTest.ANGULAR_TOLERANCE * DatumShiftGridLoader.DEGREES_TO_SECONDS);
         assertSame("Grid should be cached.", grid, NTv2.getOrLoad(file));
     }
 
@@ -262,6 +257,6 @@ public final strictfp class NTv2Test ext
      * Moves the buffer position to the next record.
      */
     private static void nextRecord(final ByteBuffer buffer) {
-        buffer.position(((buffer.position() / 16) + 1) * 16);
+        buffer.position(((buffer.position() / 16) + 1) * 16);   // "16" is the length of records in NTv2 format.
     }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/InterpolatedTransformTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/InterpolatedTransformTest.java?rev=1718274&r1=1718273&r2=1718274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/InterpolatedTransformTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/InterpolatedTransformTest.java [UTF-8] Mon Dec  7 09:58:55 2015
@@ -21,12 +21,14 @@ import org.opengis.util.FactoryException
 import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.referencing.operation.MathTransformFactory;
 import org.opengis.referencing.operation.TransformException;
+import org.apache.sis.internal.referencing.provider.NADCON;
 import org.apache.sis.internal.referencing.provider.NTv2;
 import org.apache.sis.internal.referencing.Formulas;
 import org.apache.sis.internal.system.DefaultFactories;
 
 // Test dependencies
 import org.apache.sis.internal.referencing.provider.FranceGeocentricInterpolationTest;
+import org.apache.sis.internal.referencing.provider.NADCONTest;
 import org.apache.sis.internal.referencing.provider.NTv2Test;
 import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.DependsOn;
@@ -44,7 +46,8 @@ import static org.junit.Assert.assertNot
  * @module
  */
 @DependsOn({
-    NTv2Test.class
+    NTv2Test.class,
+    NADCONTest.class
 })
 public final strictfp class InterpolatedTransformTest extends MathTransformTestCase {
     /**
@@ -53,7 +56,7 @@ public final strictfp class Interpolated
      *
      * @throws FactoryException if an error occurred while loading the grid.
      */
-    private void createGeodeticTransformation() throws FactoryException {
+    private void createRGF93() throws FactoryException {
         final URL file = NTv2Test.class.getResource(NTv2Test.TEST_FILE);
         assertNotNull("Test file \"" + NTv2Test.TEST_FILE + "\" not found.", file);
         final NTv2 provider = new NTv2();
@@ -61,42 +64,73 @@ public final strictfp class Interpolated
         values.parameter("Latitude and longitude difference file").setValue(file);    // Automatic conversion from URL to Path.
         transform = provider.createMathTransform(DefaultFactories.forBuildin(MathTransformFactory.class), values);
         tolerance = Formulas.ANGULAR_TOLERANCE;
+        validate();
     }
 
     /**
-     * Tests transformation of sample point from NTF to RGF93.
+     * Creates a transformation from NAD27 to NAD93
      *
      * @throws FactoryException if an error occurred while loading the grid.
-     * @throws TransformException if an error occurred while transforming the coordinate.
+     */
+    private void createNADCON() throws FactoryException {
+        final URL latitudeShifts  = NADCONTest.class.getResource(NADCONTest.TEST_FILE + ".laa");
+        final URL longitudeShifts = NADCONTest.class.getResource(NADCONTest.TEST_FILE + ".loa");
+        assertNotNull("Test file \"" + NADCONTest.TEST_FILE + ".laa\" not found.", latitudeShifts);
+        assertNotNull("Test file \"" + NADCONTest.TEST_FILE + ".loa\" not found.", longitudeShifts);
+        final NADCON provider = new NADCON();
+        final ParameterValueGroup values = provider.getParameters().createValue();
+        values.parameter("Latitude difference file").setValue(latitudeShifts);
+        values.parameter("Longitude difference file").setValue(longitudeShifts);
+        transform = provider.createMathTransform(DefaultFactories.forBuildin(MathTransformFactory.class), values);
+        tolerance = NADCONTest.ANGULAR_TOLERANCE;
+        validate();
+    }
+
+    /**
+     * Tests forward transformation of sample points. Tested transformations are:
+     * <ul>
+     *   <li>From NTF to RGF93 using a NTv2 grid.</li>
+     *   <li>From NAD27 to NAD83 using a NADCON grid.</li>
+     * </ul>
+     *
+     * @throws FactoryException if an error occurred while loading a grid.
+     * @throws TransformException if an error occurred while transforming a coordinate.
      *
      * @see InterpolatedGeocentricTransformTest#testInverseTransform()
      */
     @Test
     public void testForwardTransform() throws FactoryException, TransformException {
-        createGeodeticTransformation();
         isInverseTransformSupported = false;
+        createRGF93();
         verifyTransform(FranceGeocentricInterpolationTest.samplePoint(1),
                         FranceGeocentricInterpolationTest.samplePoint(3));
-        validate();
+        createNADCON();
+        verifyTransform(NADCONTest.samplePoint(1),
+                        NADCONTest.samplePoint(3));
     }
 
     /**
-     * Tests transformation of sample point from RGF93 to NTF.
+     * Tests inverse transformation of sample points. Tested transformations are:
+     * <ul>
+     *   <li>From RGF93 to NTF using a NTv2 grid.</li>
+     *   <li>From NAD83 to NAD27 using a NADCON grid.</li>
+     * </ul>
      *
-     * @throws FactoryException if an error occurred while loading the grid.
-     * @throws TransformException if an error occurred while transforming the coordinate.
-     *
-     * @see InterpolatedGeocentricTransformTest#testForwardTransform()
+     * @throws FactoryException if an error occurred while loading a grid.
+     * @throws TransformException if an error occurred while transforming a coordinate.
      */
     @Test
     @DependsOnMethod("testForwardTransform")
     public void testInverseTransform() throws FactoryException, TransformException {
-        createGeodeticTransformation();
-        transform = transform.inverse();
         isInverseTransformSupported = false;
+        createRGF93();
+        transform = transform.inverse();
         verifyTransform(FranceGeocentricInterpolationTest.samplePoint(3),
                         FranceGeocentricInterpolationTest.samplePoint(1));
-        validate();
+        createNADCON();
+        transform = transform.inverse();
+        verifyTransform(NADCONTest.samplePoint(3),
+                        NADCONTest.samplePoint(1));
     }
 
     /**
@@ -109,7 +143,7 @@ public final strictfp class Interpolated
     @Test
     @DependsOnMethod("testForwardTransform")
     public void testDerivative() throws FactoryException, TransformException {
-        createGeodeticTransformation();
+        createRGF93();
         final double delta = 0.2;
         derivativeDeltas = new double[] {delta, delta};
         tolerance = 5E-6;   // Empirical value.
@@ -125,7 +159,7 @@ public final strictfp class Interpolated
      */
     @Test
     public void testWKT() throws FactoryException, TransformException {
-        createGeodeticTransformation();
+        createRGF93();
         assertWktEqualsRegex("(?m)\\Q" +
                 "PARAM_MT[“NTv2”,\n" +
                 "  PARAMETER[“Latitude and longitude difference file”, “\\E.*\\W\\Q" +
@@ -137,5 +171,12 @@ public final strictfp class Interpolated
                 "  PARAM_MT[“NTv2”,\n" +
                 "    PARAMETER[“Latitude and longitude difference file”, “\\E.*\\W\\Q" +
                              NTv2Test.TEST_FILE + "”]]]\\E");
+
+        createNADCON();
+        assertWktEqualsRegex("(?m)\\Q" +
+                "PARAM_MT[“NADCON”,\n" +
+                "  PARAMETER[“Latitude difference file”, “\\E.*\\W\\Q"  + NADCONTest.TEST_FILE + ".laa”],\n" +
+                "  PARAMETER[“Longitude difference file”, “\\E.*\\W\\Q" + NADCONTest.TEST_FILE + ".loa”]]\\E");
+
     }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java?rev=1718274&r1=1718273&r2=1718274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] Mon Dec  7 09:58:55 2015
@@ -134,6 +134,7 @@ import org.junit.BeforeClass;
     org.apache.sis.internal.referencing.provider.MolodenskyTest.class,
     org.apache.sis.internal.referencing.provider.FranceGeocentricInterpolationTest.class,
     org.apache.sis.internal.referencing.provider.NTv2Test.class,
+    org.apache.sis.internal.referencing.provider.NADCONTest.class,
     org.apache.sis.internal.referencing.provider.MapProjectionTest.class,
     org.apache.sis.internal.referencing.provider.AllProvidersTest.class,
     org.apache.sis.referencing.operation.transform.InterpolatedTransformTest.class,

Added: sis/branches/JDK8/core/sis-referencing/src/test/resources/org/apache/sis/internal/referencing/provider/conus-extract.laa
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/resources/org/apache/sis/internal/referencing/provider/conus-extract.laa?rev=1718274&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/resources/org/apache/sis/internal/referencing/provider/conus-extract.laa (added)
+++ sis/branches/JDK8/core/sis-referencing/src/test/resources/org/apache/sis/internal/referencing/provider/conus-extract.laa [UTF-8] Mon Dec  7 09:58:55 2015
@@ -0,0 +1,12 @@
+NADCON EXTRACTED REGION
+   8  10   1   -99.75000     0.25000    37.50000     0.25000     0.00000
+    0.077689    0.074266    0.070703    0.071796    0.070248    0.069115    0.064058    0.059599
+    0.069975    0.064358    0.058726    0.059876    0.061814    0.062557    0.058803    0.048981
+    0.066956    0.062076    0.055701    0.054326    0.053513    0.051978    0.048575    0.042574
+    0.059772    0.053575    0.046033    0.048322    0.046101    0.044316    0.039337    0.035972
+    0.053544    0.050689    0.047679    0.045635    0.041370    0.039626    0.035610    0.033370
+    0.047759    0.045335    0.044390    0.043067    0.039976    0.038340    0.033538    0.024895
+    0.031871    0.036976    0.039935    0.041266    0.041244    0.040254    0.026152    0.018048
+    0.024633    0.031051    0.037431    0.038427    0.037895    0.033644    0.026022    0.014731
+    0.022734    0.030217    0.036062    0.037343    0.038205    0.037451    0.036149    0.017196
+    0.021666    0.031176    0.036000    0.041596    0.041818    0.041529    0.043860    0.033428

Propchange: sis/branches/JDK8/core/sis-referencing/src/test/resources/org/apache/sis/internal/referencing/provider/conus-extract.laa
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/core/sis-referencing/src/test/resources/org/apache/sis/internal/referencing/provider/conus-extract.laa
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Added: sis/branches/JDK8/core/sis-referencing/src/test/resources/org/apache/sis/internal/referencing/provider/conus-extract.loa
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/resources/org/apache/sis/internal/referencing/provider/conus-extract.loa?rev=1718274&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/resources/org/apache/sis/internal/referencing/provider/conus-extract.loa (added)
+++ sis/branches/JDK8/core/sis-referencing/src/test/resources/org/apache/sis/internal/referencing/provider/conus-extract.loa [UTF-8] Mon Dec  7 09:58:55 2015
@@ -0,0 +1,12 @@
+NADCON EXTRACTED REGION
+   8  10   1   -99.75000     0.25000    37.50000     0.25000     0.00000
+    1.457859    1.428933    1.401735    1.369558    1.330359    1.293002    1.250290    1.211417
+    1.456447    1.429075    1.404004    1.368848    1.329687    1.288261    1.243118    1.203158
+    1.452812    1.428737    1.398337    1.359529    1.317925    1.276657    1.233545    1.195242
+    1.442025    1.419372    1.386526    1.348886    1.309127    1.270386    1.226583    1.189869
+    1.430085    1.403484    1.367832    1.337503    1.298278    1.259007    1.218430    1.183218
+    1.422020    1.396543    1.363757    1.328373    1.287291    1.243412    1.207282    1.175327
+    1.422024    1.393362    1.362306    1.323786    1.280760    1.235031    1.201412    1.171734
+    1.423097    1.386720    1.353197    1.316248    1.276787    1.233865    1.197748    1.160423
+    1.417811    1.378398    1.344091    1.306630    1.269470    1.228051    1.191465    1.160763
+    1.416746    1.374435    1.336000    1.297365    1.265631    1.225836    1.191175    1.163249

Propchange: sis/branches/JDK8/core/sis-referencing/src/test/resources/org/apache/sis/internal/referencing/provider/conus-extract.loa
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/core/sis-referencing/src/test/resources/org/apache/sis/internal/referencing/provider/conus-extract.loa
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1718274&r1=1718273&r2=1718274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] Mon Dec  7 09:58:55 2015
@@ -524,6 +524,11 @@ public final class Errors extends Indexe
         public static final short MismatchedDimension_3 = 59;
 
         /**
+         * The grid geometry must be the same for “{0}” and “{1}”.
+         */
+        public static final short MismatchedGridGeometry_2 = 203;
+
+        /**
          * Mismatched matrix sizes: expected {0}×{1} but got {2}×{3}.
          */
         public static final short MismatchedMatrixSize_4 = 60;

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1718274&r1=1718273&r2=1718274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] Mon Dec  7 09:58:55 2015
@@ -115,6 +115,7 @@ MismatchedArrayLengths            = Mism
 MismatchedCRS                     = The coordinate reference system must be the same for all objects.
 MismatchedDimension_2             = Mismatched object dimensions: {0}D and {1}D.
 MismatchedDimension_3             = Argument \u2018{0}\u2019 has {2} dimension{2,choice,1#|2#s}, while {1} was expected.
+MismatchedGridGeometry_2          = The grid geometry must be the same for \u201c{0}\u201d and \u201c{1}\u201d.
 MismatchedMatrixSize_4            = Mismatched matrix sizes: expected {0}\u00d7{1} but got {2}\u00d7{3}.
 MismatchedParameterDescriptor_1   = Mismatched descriptor for \u201c{0}\u201d parameter.
 MismatchedPropertyType_1          = Mismatched type for \u201c{0}\u201d property.

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties?rev=1718274&r1=1718273&r2=1718274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties [ISO-8859-1] Mon Dec  7 09:58:55 2015
@@ -112,6 +112,7 @@ MismatchedArrayLengths            = Les
 MismatchedCRS                     = Le syst\u00e8me de r\u00e9f\u00e9rence des coordonn\u00e9es doit \u00eatre le m\u00eame pour tous les objets.
 MismatchedDimension_2             = Les dimensions des objets ({0}D et {1}D) ne concordent pas.
 MismatchedDimension_3             = L\u2019argument \u2018{0}\u2019 a {2} dimension{2,choice,1#|2#s}, alors qu\u2019on en attendait {1}.
+MismatchedGridGeometry_2          = La g\u00e9om\u00e9trie de la grille doit \u00eatre la m\u00eame pour \u00ab\u202f{0}\u202f\u00bb et \u00ab\u202f{1}\u202f\u00bb.
 MismatchedMatrixSize_4            = Une matrice de taille de {0}\u00d7{1} \u00e9tait attendue mais la matrice donn\u00e9e est de taille {2}\u00d7{3}.
 MismatchedParameterDescriptor_1   = Le descripteur du param\u00e8tre \u00ab\u202f{0}\u202f\u00bb ne correspond pas.
 MismatchedPropertyType_1          = Le type de la propri\u00e9t\u00e9 \u00ab\u202f{0}\u202f\u00bb ne correspond pas.

Modified: sis/branches/JDK8/ide-project/NetBeans/build.xml
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/ide-project/NetBeans/build.xml?rev=1718274&r1=1718273&r2=1718274&view=diff
==============================================================================
--- sis/branches/JDK8/ide-project/NetBeans/build.xml (original)
+++ sis/branches/JDK8/ide-project/NetBeans/build.xml Mon Dec  7 09:58:55 2015
@@ -166,6 +166,8 @@
         <include name="**/*.xml"/>
         <include name="**/*.txt"/>
         <include name="**/*.gsb"/>
+        <include name="**/*.laa"/>
+        <include name="**/*.loa"/>
       </fileset>
     </copy>
     <copy todir="${build.test.classes.dir}">



Mime
View raw message