sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1800513 - in /sis/branches/JDK8: core/sis-feature/src/main/java/org/apache/sis/internal/feature/ core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ core/sis-referencing/src/main/java/org/apache/sis/referencing/operatio...
Date Sat, 01 Jul 2017 15:49:54 GMT
Author: desruisseaux
Date: Sat Jul  1 15:49:53 2017
New Revision: 1800513

URL: http://svn.apache.org/viewvc?rev=1800513&view=rev
Log:
Store GeolocationInformation metadata built from the ModelTiePoints found in GeoTIFF file.

Added:
    sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GridGeometry.java
  (with props)
Modified:
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/DateList.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LocalizationGridBuilder.java
    sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CRSBuilder.java
    sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/ImageFileDirectory.java
    sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/Tags.java
    sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/package-info.java
    sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java

Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/DateList.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/DateList.java?rev=1800513&r1=1800512&r2=1800513&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/DateList.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/internal/feature/DateList.java
[UTF-8] Sat Jul  1 15:49:53 2017
@@ -64,11 +64,14 @@ final class DateList extends AbstractLis
         }
         long inc = max;
         for (long t : millis) {
-            if ((t % inc) != 0) do {
-                final long r = (inc % t);       // Search for greatest common divisor with
Euclid's algorithm.
-                inc = t;
-                t = r;
-            } while (t != 0);
+            if ((t % inc) != 0) {
+                do {
+                    final long r = (inc % t);       // Search for greatest common divisor
with Euclid's algorithm.
+                    inc = t;
+                    t = r;
+                } while (t != 0);
+                if (inc == 1) break;                // No need to check other values.
+            }
         }
         epoch = min;
         increment = inc;

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java?rev=1800513&r1=1800512&r2=1800513&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java
[UTF-8] Sat Jul  1 15:49:53 2017
@@ -83,6 +83,11 @@ public final class Resources extends Ind
         public static final short CanNotCreateObjectAsInstanceOf_2 = 4;
 
         /**
+         * Can not infer a grid size from the given values in {0} range.
+         */
+        public static final short CanNotInferGridSizeFromValues_1 = 75;
+
+        /**
          * Can not instantiate geodetic object for “{0}”.
          */
         public static final short CanNotInstantiateGeodeticObject_1 = 5;

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties?rev=1800513&r1=1800512&r2=1800513&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties
[ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties
[ISO-8859-1] Sat Jul  1 15:49:53 2017
@@ -45,6 +45,7 @@ NonConformCRS_3                   = The
 CanNotConcatenateTransforms_2     = Can not concatenate transforms \u201c{0}\u201d and \u201c{1}\u201d.
 CanNotComputeDerivative           = Can not compute the coordinate operation derivative.
 CanNotCreateObjectAsInstanceOf_2  = Can not create an object of group \u201c{1}\u201d as
an instance of class \u2018{0}\u2019.
+CanNotInferGridSizeFromValues_1   = Can not infer a grid size from the given values in {0}
range.
 CanNotInstantiateGeodeticObject_1 = Can not instantiate geodetic object for \u201c{0}\u201d.
 CanNotMapAxisToDirection_1        = Can not map an axis from the specified coordinate system
to the \u201c{0}\u201d direction.
 CanNotSeparateTargetDimension_1   = Target dimension {0} depends on excluded source dimensions.

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties?rev=1800513&r1=1800512&r2=1800513&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties
[ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties
[ISO-8859-1] Sat Jul  1 15:49:53 2017
@@ -50,6 +50,7 @@ NonConformCRS_3                   = La d
 CanNotConcatenateTransforms_2     = Les transformations \u00ab\u202f{0}\u202f\u00bb et \u00ab\u202f{1}\u202f\u00bb
ne peuvent pas \u00eatre combin\u00e9es.
 CanNotComputeDerivative           = La d\u00e9riv\u00e9 de l\u2019op\u00e9ration sur les
coordonn\u00e9es ne peut pas \u00eatre calcul\u00e9e.
 CanNotCreateObjectAsInstanceOf_2  = Ne peut pas cr\u00e9er un objet du groupe \u00ab\u202f{1}\u202f\u00bb
comme une instance de la classe \u2018{0}\u2019.
+CanNotInferGridSizeFromValues_1   = Ne peut pas inf\u00e9rer une taille de grille \u00e0
partir des valeurs donn\u00e9es dans la plage {0}.
 CanNotInstantiateGeodeticObject_1 = Ne peut pas cr\u00e9er l\u2019objet g\u00e9od\u00e9tique
pour \u00ab\u202f{0}\u202f\u00bb.
 CanNotMapAxisToDirection_1        = Aucun axe du syst\u00e8me de coordonn\u00e9es sp\u00e9cifi\u00e9
n\u2019a pu \u00eatre associ\u00e9 \u00e0 la direction \u00ab\u202f{0}\u202f\u00bb.
 CanNotSeparateTargetDimension_1   = La dimension de destination {0} d\u00e9pend de dimensions
sources qui ont \u00e9t\u00e9 exclues.

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LocalizationGridBuilder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LocalizationGridBuilder.java?rev=1800513&r1=1800512&r2=1800513&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LocalizationGridBuilder.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LocalizationGridBuilder.java
[UTF-8] Sat Jul  1 15:49:53 2017
@@ -18,18 +18,24 @@ package org.apache.sis.referencing.opera
 
 import org.opengis.util.FactoryException;
 import org.opengis.geometry.MismatchedDimensionException;
+import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.MathTransformFactory;
 import org.opengis.referencing.operation.TransformException;
+import org.opengis.referencing.operation.NoninvertibleTransformException;
 import org.apache.sis.referencing.operation.transform.InterpolatedTransform;
 import org.apache.sis.referencing.operation.transform.LinearTransform;
 import org.apache.sis.referencing.operation.transform.MathTransforms;
 import org.apache.sis.referencing.operation.matrix.MatrixSIS;
+import org.apache.sis.referencing.operation.matrix.Matrices;
 import org.apache.sis.referencing.datum.DatumShiftGrid;
 import org.apache.sis.internal.referencing.Resources;
 import org.apache.sis.geometry.DirectPosition2D;
+import org.apache.sis.internal.util.Numerics;
 import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.measure.NumberRange;
 import org.apache.sis.math.MathFunctions;
+import org.apache.sis.math.Vector;
 
 
 /**
@@ -63,6 +69,11 @@ import org.apache.sis.math.MathFunctions
  */
 public class LocalizationGridBuilder extends TransformBuilder {
     /**
+     * Tolerance threshold for comparing pixel coordinates relative to integer values.
+     */
+    private static final double EPS = Numerics.COMPARISON_THRESHOLD;
+
+    /**
      * The transform for the linear part.
      */
     private final LinearTransformBuilder linear;
@@ -71,7 +82,7 @@ public class LocalizationGridBuilder ext
      * A temporary array for two-dimensional source coordinates.
      * Used for reducing object allocations.
      */
-    private final int[] tmp;
+    private final int[] tmp = new int[2];
 
     /**
      * Conversions from source real-world coordinates to grid indices before interpolation.
@@ -90,18 +101,86 @@ public class LocalizationGridBuilder ext
     static final double DEFAULT_PRECISION = 1E-7;
 
     /**
-     * Creates a new, initially empty, builder.
+     * Creates a new, initially empty, builder for a localization grid of the given size.
      *
      * @param width   the number of columns in the grid of target positions.
      * @param height  the number of rows in the grid of target positions.
      */
     public LocalizationGridBuilder(final int width, final int height) {
         linear       = new LinearTransformBuilder(width, height);
-        tmp          = new int[2];
         sourceToGrid = MathTransforms.identity(2);
     }
 
     /**
+     * Creates a new, initially empty, builder for a localization grid of a size inferred
from the given points.
+     * This constructor uses the given vectors for computing a grid size and the following
initial conversion:
+     *
+     * <blockquote>({@code sourceX}, {@code sourceY}) → ({@code gridX}, {@code gridY})</blockquote>
+     *
+     * Above conversion can be obtained by {@link #getSourceToGrid()}.
+     *
+     * <p>Values in the given vectors should be integers, but this constructor is tolerant
to non-integer values
+     * if they have a constant offset (typically 0.5) relative to integer values. The two
vectors do not need to
+     * have the same length (i.e. {@code sourceX[i]} are not necessarily related to {@code
sourceY[i]}).</p>
+     *
+     * @param  sourceX  all possible <var>x</var> inputs before conversion to
grid coordinates.
+     * @param  sourceY  all possible <var>y</var> inputs before conversion to
grid coordinates.
+     * @throws ArithmeticException if this constructor can not infer a reasonable grid size
from the given vectors.
+     */
+    public LocalizationGridBuilder(final Vector sourceX, final Vector sourceY) {
+        final Matrix fromGrid = Matrices.createDiagonal(3,3);
+        linear = new LinearTransformBuilder(infer(sourceX, fromGrid, 0), infer(sourceY, fromGrid,
1));
+        try {
+            sourceToGrid = MathTransforms.linear(fromGrid).inverse();
+        } catch (NoninvertibleTransformException e) {
+            // Should not happen because infer(…) verified that the coefficients are okay.
+            throw (ArithmeticException) new ArithmeticException(e.getLocalizedMessage()).initCause(e);
+        }
+    }
+
+    /**
+     * Infers a grid size by searching for the greatest common divisor (GCD) for values in
the given vector.
+     * The vector values should be integers, but this method is tolerant to constant offsets
(typically 0.5).
+     * The GCD is taken as a "grid to source" scale factor and the minimal value as the translation
term.
+     * Those two values are stored in the {@code dim} row of the given matrix.
+     *
+     * @param  source    the vector of values for which to get the GCD and minimum value.
+     * @param  fromGrid  matrix where to store the minimum value and the GCD.
+     * @param  dim       index of the matrix row to update.
+     * @return grid size.
+     */
+    private static int infer(final Vector source, final Matrix fromGrid, final int dim) {
+        final NumberRange<?> range = source.range();
+        final double min  = range.getMinDouble(true);
+        final double span = range.getMaxDouble(true) - min;
+        final Number increment = source.increment(EPS * span);
+        double inc;
+        if (increment != null) {
+            inc = increment.doubleValue();
+        } else {
+            inc = span;
+            final int size = source.size();
+            for (int i=0; i<size; i++) {
+                double v = source.doubleValue(i) - min;
+                if (Math.abs(v % inc) > EPS) {
+                    do {
+                        final double r = (inc % v);     // Both 'inc' and 'v' are positive,
so 'r' will be positive too.
+                        inc = v;
+                        v = r;
+                    } while (Math.abs(v) > EPS);
+                }
+            }
+        }
+        fromGrid.setElement(dim, dim, inc);
+        fromGrid.setElement(dim,   2, min);
+        final double n = span / inc;
+        if (n > 0.5 && n < 0.5 + Short.MAX_VALUE) {
+            return ((int) Math.round(n)) + 1;
+        }
+        throw new ArithmeticException(Resources.format(Resources.Keys.CanNotInferGridSizeFromValues_1,
range));
+    }
+
+    /**
      * Sets the desired precision of <em>inverse</em> transformations, in units
of source coordinates.
      * If a conversion from "real world" to grid coordinates {@linkplain #setSourceToGrid
has been specified},
      * then the given precision is in "real world" units. Otherwise the precision is in units
of grid cells.
@@ -122,6 +201,16 @@ public class LocalizationGridBuilder ext
     }
 
     /**
+     * Returns the desired precision of <em>inverse</em> transformations, in
units of source coordinates.
+     * This is the precision sets by the last call to {@link #setDesiredPrecision(double)}.
+     *
+     * @return desired precision of the results of inverse transformations.
+     */
+    public double getDesiredPrecision() {
+        return precision;
+    }
+
+    /**
      * Defines relationship between "real-world" source coordinates and grid coordinates.
      * The given transform is usually two-dimensional, in which case conversions from (<var>x</var>,<var>y</var>)
      * source coordinates to ({@code gridX}, {@code gridY}) indices can be done with the
following formulas:
@@ -173,9 +262,25 @@ public class LocalizationGridBuilder ext
     }
 
     /**
+     * Returns the current relationship between "real-world" source coordinates and grid
coordinates.
+     * This is the value set by the last call to {@link #setSourceToGrid(LinearTransform)}.
+     * If that setter method has never been invoked, then this is an automatically computed
transform
+     * if the grid coordinates {@linkplain #LocalizationGridBuilder(Vector, Vector) have
been specified
+     * to the constructor}, or the identity transform {@linkplain #LocalizationGridBuilder(int,
int) otherwise}.
+     *
+     * @return the current relationship between "real-world" source coordinates and grid
coordinates.
+     */
+    public LinearTransform getSourceToGrid() {
+        return sourceToGrid;
+    }
+
+    /**
      * Sets a single matching control point pair. Source position is assumed precise and
target position is assumed uncertain.
      * If the given source position was already associated with another target position,
then the old target position is discarded.
      *
+     * <p>If a {@linkplain #getSourceToGrid() source to grid} conversion exists, it
shall have been applied
+     * by the caller for computing the ({@code gridX}, {@code gridY}) coordinates given to
this method.</p>
+     *
      * @param  gridX   the column index in the grid where to store the given target position.
      * @param  gridY   the row index in the grid where to store the given target position.
      * @param  target  the target coordinates, assumed uncertain.

Modified: sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CRSBuilder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CRSBuilder.java?rev=1800513&r1=1800512&r2=1800513&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CRSBuilder.java
[UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CRSBuilder.java
[UTF-8] Sat Jul  1 15:49:53 2017
@@ -740,6 +740,8 @@ final class CRSBuilder {
      * <ul>
      *   <li>{@link #build(Vector, Vector, String)} must have been invoked before this
method.</li>
      *   <li>{@link ImageFileDirectory} must have filled its part of metadata before
to invoke this method.</li>
+     *   <li>{@link MetadataBuilder#newGridRepresentation(MetadataBuilder.GridType)}
should have been invoked
+     *       with the appropriate {@code GEORECTIFIED} or {@code GEOREFERENCEABLE} type.</li>
      * </ul>
      *
      * After execution, this method emits a warning for unprocessed GeoTIFF tags.
@@ -748,7 +750,6 @@ final class CRSBuilder {
      * @throws NumberFormatException if a numeric value was stored as a string and can not
be parsed.
      */
     final void complete(final MetadataBuilder metadata) {
-        metadata.newGridRepresentation(MetadataBuilder.GridType.GEORECTIFIED);
         /*
          * ASCII reference to published documentation on the overall configuration of the
GeoTIFF file.
          * Often the projected CRS name, despite GeoKeys.PCSCitation being already for that
purpose.

Added: sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GridGeometry.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GridGeometry.java?rev=1800513&view=auto
==============================================================================
--- sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GridGeometry.java
(added)
+++ sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GridGeometry.java
[UTF-8] Sat Jul  1 15:49:53 2017
@@ -0,0 +1,95 @@
+/*
+ * 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.storage.geotiff;
+
+import java.util.Collection;
+import java.util.Collections;
+import org.opengis.util.FactoryException;
+import org.opengis.metadata.quality.DataQuality;
+import org.opengis.metadata.spatial.GeolocationInformation;
+import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.TransformException;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.apache.sis.referencing.operation.transform.LinearTransform;
+import org.apache.sis.referencing.operation.builder.LocalizationGridBuilder;
+import org.apache.sis.referencing.operation.AbstractCoordinateOperation;
+import org.apache.sis.math.Vector;
+
+
+/**
+ * The conversion or transformation from pixel coordinates to model coordinates.
+ * The target CRS may be the image CRS if the image is "georeferenceable" instead of georeferenced.
+ *
+ * This is a placeholder before a real {@code GridGeometry} class is ported to Apache SIS.
+ * We implement {@code CoordinateOperation} for now for allowing access to the math transform
from
+ * outside this package, but we will probably not keep this class hierarchy in a future version.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 0.8
+ * @since   0.8
+ * @module
+ */
+@SuppressWarnings("serial")
+final class GridGeometry extends AbstractCoordinateOperation implements GeolocationInformation
{
+    /**
+     * Number of floating point values in each (I,J,K,X,Y,Z) record.
+     */
+    private static final int RECORD_LENGTH = 6;
+
+    /**
+     * Creates a new transformation from the information found by {@link ImageFileDirectory}.
+     */
+    GridGeometry(final String name, final CoordinateReferenceSystem crs, final Vector modelTiePoints)
+            throws FactoryException, TransformException
+    {
+        super(Collections.singletonMap(NAME_KEY, name), null, crs, null, localizationGrid(modelTiePoints));
+    }
+
+    /**
+     * Builds a localization grid from the given GeoTIFF tie points.
+     * This is a workaround for RFE #4093999 in Sun's bug database
+     * ("Relax constraint on placement of this()/super() call in constructors").
+     */
+    private static MathTransform localizationGrid(final Vector modelTiePoints) throws FactoryException,
TransformException {
+        final int size = modelTiePoints.size();
+        final int n = size / RECORD_LENGTH;
+        final LocalizationGridBuilder grid = new LocalizationGridBuilder(
+                modelTiePoints.subSampling(0, RECORD_LENGTH, n),
+                modelTiePoints.subSampling(1, RECORD_LENGTH, n));
+
+        final LinearTransform sourceToGrid = grid.getSourceToGrid();
+        final double[] ordinates = new double[2];
+        for (int i=0; i<size; i += RECORD_LENGTH) {
+            ordinates[0] = modelTiePoints.doubleValue(i);
+            ordinates[1] = modelTiePoints.doubleValue(i+1);
+            sourceToGrid.transform(ordinates, 0, ordinates, 0, 1);
+            grid.setControlPoint((int) Math.round(ordinates[0]),
+                                 (int) Math.round(ordinates[1]),
+                                 modelTiePoints.doubleValue(i+3),
+                                 modelTiePoints.doubleValue(i+4));
+        }
+        return grid.create(null);
+    }
+
+    /**
+     * Provides an overall assessment of quality of geolocation information.
+     */
+    @Override
+    public Collection<DataQuality> getQualityInfo() {
+        return Collections.emptyList();
+    }
+}

Propchange: sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GridGeometry.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GridGeometry.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/ImageFileDirectory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/ImageFileDirectory.java?rev=1800513&r1=1800512&r2=1800513&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/ImageFileDirectory.java
[UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/ImageFileDirectory.java
[UTF-8] Sat Jul  1 15:49:53 2017
@@ -31,11 +31,15 @@ import org.opengis.util.FactoryException
 import org.opengis.util.NoSuchIdentifierException;
 import org.opengis.parameter.ParameterNotFoundException;
 import org.opengis.referencing.NoSuchAuthorityCodeException;
+import org.opengis.referencing.operation.TransformException;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.apache.sis.referencing.operation.matrix.Matrices;
+import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 import org.apache.sis.internal.geotiff.Resources;
+import org.apache.sis.internal.storage.MetadataBuilder;
 import org.apache.sis.internal.storage.io.ChannelDataInput;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.DataStoreContentException;
-import org.apache.sis.internal.storage.MetadataBuilder;
 import org.apache.sis.math.Vector;
 import org.apache.sis.measure.Units;
 
@@ -311,18 +315,32 @@ final class ImageFileDirectory {
     private String asciiGeoParameters;
 
     /**
-     * Originally part of Intergraph's GeoTIFF tags, but now used in interchangeable GeoTIFF
files.
-     *
-     * This tag is also known as <strong>'GeoreferenceTag'</strong>.
-     * This tag stores raster model tiepoint pairs into the following order
-     * ModelTiepointTag = (...,I,J,K, X,Y,Z...)
-     * where (I,J,K) is the point at location (I,J) in raster space with pixel-value K, and
(X,Y,Z) is a vector in model space.
-     * In most cases the model space is only two-dimensional, in which case both K and Z
should be set to zero;
-     * this third dimension is provided in anticipation of future support for 3D digital
elevation models and vertical coordinate systems.
+     * Raster model tie points. This vector contains ordinate values structured as (I,J,K,
X,Y,Z) records.
+     * The (I,J,K) ordinate values specify the point at location (I,J) in raster space with
pixel-value K,
+     * and (X,Y,Z) ordinate values specify the point in the Coordinate Reference System.
In most cases the
+     * coordinate system is only two-dimensional, in which case both K and Z should be set
to zero.
      */
     private Vector modelTiePoints;
 
     /**
+     * The conversion from grid coordinates to CRS coordinates. It can be determined in different
ways,
+     * from simpler to more complex:
+     *
+     * <ul>
+     *   <li>By a combination of a single {@link #modelTiePoints} with the 3 values
given in
+     *       {@link Tags#ModelPixelScaleTag} as documented in the Javadoc of that tag.</li>
+     *   <li>By a {@link Tags#ModelTransformation} giving all coefficients of the 4×4
matrix}.
+     *       Note that the third row and the third column have all their value set to 0 if
the
+     *       space model (or the coordinate reference system) should be two-dimensional.</li>
+     *   <li>By building a non-linear transformation from all {@link #modelTiePoints}.
+     *       Such transformation can not be stored in a matrix, so will leave this field
{@code null}.</li>
+     * </ul>
+     *
+     * By convention, the translation column is set to NaN values if it needs to be computed
from the tie point.
+     */
+    private MatrixSIS gridToCRS;
+
+    /**
      * Creates a new image file directory.
      *
      * @param reader  information about the input stream to read, the metadata and the character
encoding.
@@ -660,13 +678,51 @@ final class ImageFileDirectory {
                 // TODO
                 break;
             }
-
             /*
-             * This tag stores raster->model tiepoint pairs in the order
-             * ModelTiepointTag = (...,I,J,K, X,Y,Z...).
+             * The "grid to CRS" conversion as a 4×4 matrix in row-major fashion. The third
matrix row and
+             * the third matrix column may contain only zero values; this block does not
reduce the number
+             * of dimensions from 3 to 2.
+             */
+            case Tags.ModelTransformation: {
+                final Vector m = type.readVector(input(), count);
+                final int size = m.size();
+                final int n;
+                switch (size) {
+                    case  6:                    // Assume 2D model with implicit [0 0 1]
last row.
+                    case  9: n = 3; break;      // Assume 2D model with full 3×3 matrix.
+                    case 12:                    // Assume 3D model with implicit [0 0 0 1]
last row.
+                    case 16: n = 4; break;      // 3D model with full 4×4 matrix, as required
by GeoTIFF spec.
+                    default: return m;
+                }
+                gridToCRS = Matrices.createZero(n, n);
+                gridToCRS.setElement(n-1, n-1, 1);
+                for (int i=0; i<size; i++) {
+                    gridToCRS.setElement(i / n, i % n, m.doubleValue(i));
+                }
+                break;
+            }
+            /*
+             * The "grid to CRS" conversion with only the scale factor specified. This block
sets the
+             * translation column to NaN, meaning that it will need to be computed from the
tie point.
              */
-            case Tags.ModelTiePointTag: {
-                //-- TODO : store into ISO19115 metadata object
+            case Tags.ModelPixelScaleTag: {
+                final Vector m = type.readVector(input(), count);
+                final int size = m.size();
+                if (size < 2 || size > 3) {     // Length should be exactly 3, but
we make this reader tolerant.
+                    return m;
+                }
+                gridToCRS = Matrices.createZero(size+1, size+1);
+                gridToCRS.setElement(size, size, 1);
+                for (int i=0; i<size; i++) {
+                    gridToCRS.setElement(i, i, m.doubleValue(i));
+                    gridToCRS.setElement(i, size, Double.NaN);
+                }
+                break;
+            }
+            /*
+             * The mapping from pixel coordinates to CRS coordinates as a sequence of (I,J,K,
X,Y,Z) records.
+             */
+            case Tags.ModelTiePoints: {
                 modelTiePoints = type.readVector(input(), count);
                 break;
             }
@@ -1062,10 +1118,15 @@ final class ImageFileDirectory {
          * in which case the CRS builder returns null. This is safe since all MetadataBuilder
methods
          * ignore null values (a design choice because this pattern come very often).
          */
+        final boolean isGeorectified = (modelTiePoints == null) || (gridToCRS != null);
+        metadata.newGridRepresentation(isGeorectified ? MetadataBuilder.GridType.GEORECTIFIED
+                                                      : MetadataBuilder.GridType.GEOREFERENCEABLE);
+        CoordinateReferenceSystem crs = null;
         if (geoKeyDirectory != null) {
             final CRSBuilder helper = new CRSBuilder(reader);
             try {
-                metadata.addReferenceSystem(helper.build(geoKeyDirectory, numericGeoParameters,
asciiGeoParameters));
+                crs = helper.build(geoKeyDirectory, numericGeoParameters, asciiGeoParameters);
+                metadata.addReferenceSystem(crs);
                 helper.complete(metadata);
             } catch (NoSuchIdentifierException | ParameterNotFoundException e) {
                 short key = Resources.Keys.UnsupportedProjectionMethod_1;
@@ -1078,10 +1139,16 @@ final class ImageFileDirectory {
                     reader.owner.warning(null, e);
                 }
             }
-            geoKeyDirectory      = null;            // Not needed anymore, so let GC do its
work.
-            numericGeoParameters = null;
-            asciiGeoParameters   = null;
         }
+        if (!isGeorectified) try {
+            metadata.addGeolocation(new GridGeometry(input().filename, crs, modelTiePoints));
+        } catch (TransformException e) {
+            reader.owner.warning(null, e);
+        }
+        geoKeyDirectory      = null;            // Not needed anymore, so let GC do its work.
+        numericGeoParameters = null;
+        asciiGeoParameters   = null;
+        modelTiePoints       = null;
     }
 
     /**

Modified: sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/Tags.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/Tags.java?rev=1800513&r1=1800512&r2=1800513&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/Tags.java
[UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/Tags.java
[UTF-8] Sat Jul  1 15:49:53 2017
@@ -114,7 +114,6 @@ final class Tags {
     public static final short YCbCrPositioning            = 0x0213;
     public static final short ReferenceBlackWhite         = 0x0214;
     public static final short Copyright           = (short) 0x8298;
-    public static final short ModelTiePointTag    = (short) 0x8482;
 
 
     /////////////////////////////////////////////////////////
@@ -162,6 +161,35 @@ final class Tags {
     public static final short GeoAsciiParams = (short) 0x87B1;            // 34737
 
     /**
+     * The tie points as (I,J,K,X,Y,Z) records in an array of floating-point numbers.
+     * This tag is also known as {@code Georeference}.
+     */
+    public static final short ModelTiePoints = (short) 0x8482;            // 33922
+
+    /**
+     * A vector of 3 floating-point values defining the "grid to CRS" conversion without
rotation.
+     * The conversion is defined as below, when (I,J,K,X,Y,Z) is the tie point singleton
record:
+     *
+     * ┌                       ┐
+     * │   Sx   0    0    Tx   │       Tx = X - I/Sx
+     * │   0   -Sy   0    Ty   │       Ty = Y + J/Sy
+     * │   0    0    Sz   Tz   │       Tz = Z - K/Sz  (if not 0)
+     * │   0    0    0    1    │
+     * └                       ┘
+     *
+     * Only one of {@code ModelPixelScaleTag} and {@link #ModelTransformation} should be
used.
+     */
+    public static final short ModelPixelScaleTag = (short) 0x830E;        // 33550
+
+    /**
+     * Specifies the "grid to CRS" conversion (the transformation matrix between the raster
space and the model space).
+     * If specified, the tag shall have the 16 values of a 4×4 matrix in row-major fashion.
The last matrix row (i.e.
+     * the last 4 values) should be [0 0 0 1]. The row before should be [0 0 0 0] if the
conversion is two-dimensional.
+     * Only one of {@link #ModelPixelScaleTag} and {@code ModelTransformation} should be
used.
+     */
+    public static final short ModelTransformation = (short) 0x85D8;       // 34264
+
+    /**
      * Do not allow instantiation of this class.
      */
     private Tags() {

Modified: sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/package-info.java?rev=1800513&r1=1800512&r2=1800513&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/package-info.java
[UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/package-info.java
[UTF-8] Sat Jul  1 15:49:53 2017
@@ -23,7 +23,7 @@
  *   <li><a href="http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf">TIFF
specification</a>: baseline</li>
  *   <li><a href="http://partners.adobe.com/public/developer/en/tiff/TIFFphotoshop.pdf">TIFF
Tecnical Notes</a>: add new compressions</li>
  *   <li><a href="http://www.awaresystems.be/imaging/tiff/tifftags.html">TIFF
Tag Reference</a></li>
- *   <li><a href="http://www.remotesensing.org/geotiff/spec/contents.html">GeoTIFF
specification</a></li>
+ *   <li><a href="http://download.osgeo.org/geotiff/spec/geotiff.rtf">GeoTIFF
specification</a></li>
  * </ul>
  *
  * @author  Rémi Maréchal (Geomatys)

Modified: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java?rev=1800513&r1=1800512&r2=1800513&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java
[UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java
[UTF-8] Sat Jul  1 15:49:53 2017
@@ -38,6 +38,7 @@ import org.opengis.metadata.spatial.Dime
 import org.opengis.metadata.spatial.DimensionNameType;
 import org.opengis.metadata.spatial.CellGeometry;
 import org.opengis.metadata.spatial.PixelOrientation;
+import org.opengis.metadata.spatial.GeolocationInformation;
 import org.opengis.metadata.spatial.SpatialRepresentationType;
 import org.opengis.metadata.constraint.Restriction;
 import org.opengis.metadata.content.TransferFunctionType;
@@ -1790,7 +1791,10 @@ parse:      for (int i = 0; i < length;)
      */
     public final void setPointInPixel(final PixelOrientation value) {
         if (value != null) {
-            ((DefaultGeorectified) gridRepresentation()).setPointInPixel(value);
+            final DefaultGridSpatialRepresentation gridRepresentation = gridRepresentation();
+            if (gridRepresentation instanceof DefaultGeorectified) {
+                ((DefaultGeorectified) gridRepresentation).setPointInPixel(value);
+            }
         }
     }
 
@@ -1807,7 +1811,29 @@ parse:      for (int i = 0; i < length;)
     public final void setGridToCRS(final CharSequence value) {
         final InternationalString i18n = trim(value);
         if (i18n != null) {
-            ((DefaultGeorectified) gridRepresentation()).setTransformationDimensionDescription(i18n);
+            final DefaultGridSpatialRepresentation gridRepresentation = gridRepresentation();
+            if (gridRepresentation instanceof DefaultGeorectified) {
+                ((DefaultGeorectified) gridRepresentation).setTransformationDimensionDescription(i18n);
+            }
+        }
+    }
+
+    /**
+     * Adds information about the geolocation of an image.
+     * Storage location is:
+     *
+     * <ul>
+     *   <li>{@code metadata/spatialRepresentationInfo/geolocationInformation}</li>
+     * </ul>
+     *
+     * @param  info  the geolocation information to add, or {@code null} if none.
+     */
+    public final void addGeolocation(final GeolocationInformation info) {
+        if (info != null) {
+            final DefaultGridSpatialRepresentation gridRepresentation = gridRepresentation();
+            if (gridRepresentation instanceof DefaultGeoreferenceable) {
+                addIfNotPresent(((DefaultGeoreferenceable) gridRepresentation).getGeolocationInformation(),
info);
+            }
         }
     }
 



Mime
View raw message