sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1825945 - in /sis/branches/JDK8/core/sis-referencing/src: main/java/org/apache/sis/referencing/operation/transform/ test/java/org/apache/sis/referencing/operation/transform/
Date Mon, 05 Mar 2018 22:13:04 GMT
Author: desruisseaux
Date: Mon Mar  5 22:13:04 2018
New Revision: 1825945

URL: http://svn.apache.org/viewvc?rev=1825945&view=rev
Log:
Addition of SpecializationTransform2D and public API for making those transforms accessible.
This complete https://issues.apache.org/jira/browse/SIS-408

Added:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform1D.txt
  (with props)
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform2D.java
  (with props)
Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/SpecializableTransformTest.java

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java?rev=1825945&r1=1825944&r2=1825945&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java
[UTF-8] Mon Mar  5 22:13:04 2018
@@ -16,10 +16,12 @@
  */
 package org.apache.sis.referencing.operation.transform;
 
+import java.util.Map;
 import java.util.List;
 import java.util.Collections;
 import java.awt.geom.AffineTransform;
 import org.opengis.util.FactoryException;
+import org.opengis.geometry.Envelope;
 import org.opengis.geometry.MismatchedDimensionException;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.MathTransform;
@@ -51,7 +53,7 @@ import org.apache.sis.util.Static;
  * GeoAPI factory interfaces instead.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.7
+ * @version 1.0
  *
  * @see MathTransformFactory
  *
@@ -179,6 +181,45 @@ public final class MathTransforms extend
     }
 
     /**
+     * Creates a transform defined as one transform applied globally except in sub-areas
where more accurate
+     * transforms are available. Such constructs appear in some datum shift files. The result
of transforming
+     * a point by the returned {@code MathTransform} is as if iterating over all given {@link
Envelope}s in
+     * no particular order, find the smallest one containing the point to transform, then
use the associated
+     * {@link MathTransform} for transforming the point. If the point is not found in any
envelope,
+     * then the global transform is applied.
+     *
+     * <p>The following constraints apply:</p>
+     * <ul>
+     *   <li>The global transform must be a reasonable approximation of the specialized
transforms
+     *       (this is required for calculating the inverse transform).</li>
+     *   <li>All transforms in the {@code specializations} map must have the same number
of source and target
+     *       dimensions than the {@code global} transform.</li>
+     *   <li>All envelopes in the {@code specializations} map must have the same number
of dimensions
+     *       than the global transform <em>source</em> dimensions.</li>
+     *   <li>In current implementation, each envelope must either be fully included
in another envelope,
+     *       or not overlap any other envelope.</li>
+     * </ul>
+     *
+     * @param  global  the transform to use globally where there is no suitable specialization.
+     * @param  specializations  more accurate transforms available in some sub-areas.
+     * @return a transform applying the given global transform except in sub-areas where
specializations are available.
+     * @throws IllegalArgumentException if a constraint is not meet.
+     *
+     * @since 1.0
+     */
+    public static MathTransform specialize(final MathTransform global, final Map<Envelope,MathTransform>
specializations) {
+        ArgumentChecks.ensureNonNull("generic", global);
+        ArgumentChecks.ensureNonNull("specializations", specializations);
+        if (specializations.isEmpty()) {
+            return global;
+        } else if (global.getSourceDimensions() == 2 && global.getTargetDimensions()
== 2) {
+            return new SpecializableTransform2D(global, specializations);
+        } else {
+            return new SpecializableTransform(global, specializations);
+        }
+    }
+
+    /**
      * Puts together a list of independent math transforms, each of them operating on a subset
of ordinate values.
      * This method is often used for defining 4-dimensional (<var>x</var>,<var>y</var>,<var>z</var>,<var>t</var>)
      * transform as an aggregation of 3 simpler transforms operating on (<var>x</var>,<var>y</var>),
(<var>z</var>)

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform.java?rev=1825945&r1=1825944&r2=1825945&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform.java
[UTF-8] Mon Mar  5 22:13:04 2018
@@ -22,12 +22,13 @@ import java.util.Objects;
 import java.io.Serializable;
 import org.opengis.geometry.Envelope;
 import org.opengis.geometry.DirectPosition;
+import org.opengis.geometry.MismatchedDimensionException;
+import org.opengis.geometry.MismatchedReferenceSystemException;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.TransformException;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.operation.NoninvertibleTransformException;
-import org.apache.sis.referencing.factory.InvalidGeodeticParameterException;
 import org.apache.sis.internal.referencing.DirectPositionView;
 import org.apache.sis.internal.referencing.Resources;
 import org.apache.sis.geometry.GeneralEnvelope;
@@ -40,18 +41,26 @@ import org.apache.sis.util.ArraysExt;
 
 /**
  * A transform having sub-areas where more accurate transforms can be used.
- * The general transform must be a reasonable approximation of the specialized transforms.
+ * The global transform must be a reasonable approximation of the specialized transforms.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @version 1.0
- * @since   1.0
+ *
+ * @see MathTransforms#specialize(MathTransform, Map)
+ *
+ * @since 1.0
  * @module
  */
 class SpecializableTransform extends AbstractMathTransform implements Serializable {
     /**
-     * The generic transform to use if there is no suitable specialization.
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -7379277748632094312L;
+
+    /**
+     * The global transform to use if there is no suitable specialization.
      */
-    private final MathTransform generic;
+    private final MathTransform global;
 
     /**
      * The region where a transform is valid, together with the transform.
@@ -118,7 +127,7 @@ class SpecializableTransform extends Abs
          * Sets the CRS of all given ares to a common value. An exception is thrown if incompatible
CRS are found.
          * This method does not verify the number of dimensions; this check should have been
done by the caller.
          */
-        static void uniformize(final SubArea[] domains) throws InvalidGeodeticParameterException
{
+        static void uniformize(final SubArea[] domains) {
             CoordinateReferenceSystem common = null;
             for (SubArea area : domains) {
                 do {
@@ -126,7 +135,7 @@ class SpecializableTransform extends Abs
                     if (common == null) {
                         common = crs;
                     } else if (crs != null && !Utilities.equalsIgnoreMetadata(common,
crs)) {
-                        throw new InvalidGeodeticParameterException(Errors.format(Errors.Keys.MismatchedCRS));
+                        throw new MismatchedReferenceSystemException(Errors.format(Errors.Keys.MismatchedCRS));
                     }
                 } while ((area = area.specialization) != null);
             }
@@ -242,17 +251,15 @@ class SpecializableTransform extends Abs
     private MathTransform inverse;
 
     /**
-     * Creates a new transform with the given generic transform and some amount of specializations.
+     * Creates a new transform with the given global transform and some amount of specializations.
      *
-     * @param  generic  the generic transform to use if there is no suitable specialization.
+     * @param  global  the transform to use globally where there is no suitable specialization.
      * @param  specializations  more accurate transforms available in sub-areas.
      */
-    SpecializableTransform(final MathTransform generic, final Map<Envelope,MathTransform>
specializations)
-            throws InvalidGeodeticParameterException
-    {
-        this.generic = generic;
-        final int sourceDim = generic.getSourceDimensions();
-        final int targetDim = generic.getTargetDimensions();
+    SpecializableTransform(final MathTransform global, final Map<Envelope,MathTransform>
specializations) {
+        this.global = global;
+        final int sourceDim = global.getSourceDimensions();
+        final int targetDim = global.getTargetDimensions();
         int n = 0;
         final SubArea[] areas = new SubArea[specializations.size()];
 next:   for (final Map.Entry<Envelope,MathTransform> e : specializations.entrySet())
{
@@ -261,7 +268,7 @@ next:   for (final Map.Entry<Envelope,Ma
             ensureDimensionMatches(1, targetDim, tr.getTargetDimensions());
             final SubArea area = new SubArea(e.getKey(), tr);
             if (area.getDimension() != sourceDim) {
-                throw new InvalidGeodeticParameterException(Errors.format(Errors.Keys.MismatchedDimension_3,
+                throw new MismatchedDimensionException(Errors.format(Errors.Keys.MismatchedDimension_3,
                             "envelope", sourceDim, area.getDimension()));
             }
             for (int i=0; i<n; i++) {
@@ -272,7 +279,7 @@ next:   for (final Map.Entry<Envelope,Ma
             for (int i=0; i<n; i++) {
                 if (area.intersects(areas[n])) {
                     // Pending implementation of R-Tree in Apache SIS.
-                    throw new InvalidGeodeticParameterException("Current implementation does
not accept overlapping envelopes.");
+                    throw new IllegalArgumentException("Current implementation does not accept
overlapping envelopes.");
                 }
             }
             areas[n++] = area;
@@ -286,11 +293,9 @@ next:   for (final Map.Entry<Envelope,Ma
      *
      * @param  type  0 if verifying source dimension, or 1 if verifying target dimension.
      */
-    private static void ensureDimensionMatches(final int type, final int expected, final
int actual)
-            throws InvalidGeodeticParameterException
-    {
+    private static void ensureDimensionMatches(final int type, final int expected, final
int actual) {
         if (expected != actual) {
-            throw new InvalidGeodeticParameterException(Resources.format(
+            throw new MismatchedDimensionException(Resources.format(
                     Resources.Keys.MismatchedTransformDimension_3, type, expected, actual));
         }
     }
@@ -300,7 +305,7 @@ next:   for (final Map.Entry<Envelope,Ma
      */
     @Override
     public final int getSourceDimensions() {
-        return generic.getSourceDimensions();
+        return global.getSourceDimensions();
     }
 
     /**
@@ -308,14 +313,14 @@ next:   for (final Map.Entry<Envelope,Ma
      */
     @Override
     public final int getTargetDimensions() {
-        return generic.getTargetDimensions();
+        return global.getTargetDimensions();
     }
 
     /**
      * Returns the transform to use for the given domain.
      */
     private MathTransform forDomain(final SubArea domain) {
-        return (domain != null) ? domain.transform : generic;
+        return (domain != null) ? domain.transform : global;
     }
 
     /**
@@ -345,13 +350,15 @@ next:   for (final Map.Entry<Envelope,Ma
                                   final double[] dstPts, final int dstOff,
                                   boolean derivate) throws TransformException
     {
-        final DirectPositionView pos = new DirectPositionView.Double(srcPts, srcOff, generic.getSourceDimensions());
+        final DirectPositionView pos = new DirectPositionView.Double(srcPts, srcOff, global.getSourceDimensions());
         final MathTransform tr = forDomain(SubArea.find(domains, pos));
         if (tr instanceof AbstractMathTransform) {
             return ((AbstractMathTransform) tr).transform(srcPts, srcOff, dstPts, dstOff,
derivate);
         } else {
             Matrix derivative = derivate ? tr.derivative(pos) : null;       // Must be before
transform(srcPts, …).
-            tr.transform(srcPts, srcOff, dstPts, dstOff, 1);
+            if (dstPts != null) {
+                tr.transform(srcPts, srcOff, dstPts, dstOff, 1);
+            }
             return derivative;
         }
     }
@@ -387,7 +394,7 @@ next:   for (final Map.Entry<Envelope,Ma
             int srcOff = src.offset;
             final MathTransform tr;
             if (domain == null) {
-                tr = generic;                               // The transform to apply when
no specialization is found.
+                tr = global;                               // The transform to apply when
no specialization is found.
                 do {                                        // Count how many points will
use that transform.
                     src.offset += srcInc;
                     if (--numPts <= 0) break;
@@ -520,7 +527,7 @@ next:   for (final Map.Entry<Envelope,Ma
      */
     @Override
     protected final int computeHashCode() {
-        return super.computeHashCode() + 7*generic.hashCode() ^ Arrays.hashCode(domains);
+        return super.computeHashCode() + 7*global.hashCode() ^ Arrays.hashCode(domains);
     }
 
     /**
@@ -530,7 +537,7 @@ next:   for (final Map.Entry<Envelope,Ma
     public final boolean equals(final Object object, final ComparisonMode mode) {
         if (super.equals(object, mode)) {
             final SpecializableTransform other = (SpecializableTransform) object;
-            return Utilities.deepEquals(generic, other.generic, mode) &&
+            return Utilities.deepEquals(global, other.global, mode) &&
                    Utilities.deepEquals(domains, other.domains, mode);
         }
         return false;
@@ -548,7 +555,7 @@ next:   for (final Map.Entry<Envelope,Ma
     @Override
     protected final String formatTo(final Formatter formatter) {
         formatter.newLine();
-        formatter.append(generic);
+        formatter.append(global);
         for (SubArea domain : domains) {
             SubArea.format(domain, formatter);
         }
@@ -560,17 +567,25 @@ next:   for (final Map.Entry<Envelope,Ma
      * Returns the inverse of this transform.
      */
     @Override
-    public final synchronized MathTransform inverse() throws NoninvertibleTransformException
{
+    public synchronized MathTransform inverse() throws NoninvertibleTransformException {
         if (inverse == null) {
-            inverse = new Inverse(this);
+            inverse = createInverse();
         }
         return inverse;
     }
 
     /**
+     * Invoked at construction time for creating the inverse transform.
+     * Overridden by {@link SpecializableTransform2D} for the two-dimensional variant.
+     */
+    Inverse createInverse() throws NoninvertibleTransformException {
+        return new Inverse(this);
+    }
+
+    /**
      * The inverse of {@link SpecializableTransform}.
      */
-    private static final class Inverse extends AbstractMathTransform.Inverse implements Serializable
{
+    static class Inverse extends AbstractMathTransform.Inverse implements Serializable {
         /**
          * For cross-version compatibility.
          */
@@ -582,16 +597,16 @@ next:   for (final Map.Entry<Envelope,Ma
         private final SpecializableTransform forward;
 
         /**
-         * The inverse of {@link SpecializableTransform#generic}.
+         * The inverse of {@link SpecializableTransform#global}.
          */
-        private final MathTransform generic;
+        private final MathTransform global;
 
         /**
          * Creates the inverse of a specialized transform having the given properties.
          */
         Inverse(final SpecializableTransform forward) throws NoninvertibleTransformException
{
             this.forward = forward;
-            this.generic = forward.generic.inverse();
+            this.global = forward.global.inverse();
             for (final SubArea domain : forward.domains) {
                 SubArea.createInverse(domain);
             }
@@ -611,7 +626,7 @@ next:   for (final Map.Entry<Envelope,Ma
         @Override
         public final DirectPosition transform(final DirectPosition ptSrc, DirectPosition
ptDst) throws TransformException {
             final double[] source = ptSrc.getCoordinate();      // Needs to be first in case
ptDst overwrites ptSrc.
-            ptDst = generic.transform(ptSrc, ptDst);
+            ptDst = global.transform(ptSrc, ptDst);
             final SubArea domain = SubArea.find(forward.domains, ptDst);
             if (domain != null) {
                 ptDst = domain.inverse.transform(new DirectPositionView.Double(source, 0,
source.length), ptDst);
@@ -636,8 +651,8 @@ next:   for (final Map.Entry<Envelope,Ma
         public final Matrix transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff,
final boolean derivate)
                 throws TransformException
         {
-            final int srcInc = generic.getSourceDimensions();
-            final int dstInc = generic.getTargetDimensions();
+            final int srcInc = global.getSourceDimensions();
+            final int dstInc = global.getTargetDimensions();
             if (dstPts == null) {
                 dstPts = new double[dstInc];                    // Needed for checking if
inside a sub-area.
                 dstOff = 0;
@@ -650,7 +665,7 @@ next:   for (final Map.Entry<Envelope,Ma
              * given in arguments overlap.  We need this stability because the source coordinates
may be used
              * twice, if 'secondTry' become true.
              */
-            MathTransform tr = generic;
+            MathTransform tr = global;
             boolean secondTry = false;
             Matrix derivative;
             do {
@@ -679,7 +694,7 @@ next:   for (final Map.Entry<Envelope,Ma
                 int srcOff, int dstOff, int srcInc, int dstInc, int numPts) throws TransformException
         {
             final SubArea[] domains = forward.domains;
-            transform.apply(generic, srcOff, dstOff, numPts);
+            transform.apply(global, srcOff, dstOff, numPts);
             final DirectPositionView dst = new DirectPositionView.Double(dstPts, dstOff,
dstInc);
             while (numPts > 0) {
                 SubArea domain = SubArea.find(domains, dst);
@@ -718,8 +733,8 @@ next:   for (final Map.Entry<Envelope,Ma
                 throws TransformException
         {
             if (numPts <= 0) return;
-            final int srcInc = generic.getSourceDimensions();
-            final int dstInc = generic.getTargetDimensions();
+            final int srcInc = global.getSourceDimensions();
+            final int dstInc = global.getTargetDimensions();
             if (srcPts == dstPts) {
                 final int srcEnd = srcOff + numPts*srcInc;
                 if (srcEnd > dstOff || dstOff + numPts*dstInc > srcOff) {
@@ -742,8 +757,8 @@ next:   for (final Map.Entry<Envelope,Ma
                 throws TransformException
         {
             if (numPts <= 0) return;
-            final int srcInc = generic.getSourceDimensions();
-            final int dstInc = generic.getTargetDimensions();
+            final int srcInc = global.getSourceDimensions();
+            final int dstInc = global.getTargetDimensions();
             final double[] buffer = new double[numPts * dstInc];
             transform((tr, src, dst, num) -> tr.transform(srcPts, src, buffer, dst, num),
                       buffer, srcOff, 0, srcInc, dstInc, numPts);
@@ -763,8 +778,8 @@ next:   for (final Map.Entry<Envelope,Ma
                               final float [] dstPts, int dstOff, int numPts) throws TransformException
         {
             if (numPts <= 0) return;
-            final int srcInc = generic.getSourceDimensions();
-            final int dstInc = generic.getTargetDimensions();
+            final int srcInc = global.getSourceDimensions();
+            final int dstInc = global.getTargetDimensions();
             final double[] buffer = new double[numPts * dstInc];
             transform((tr, src, dst, num) -> tr.transform(srcPts, src, buffer, dst, num),
                       buffer, srcOff, 0, srcInc, dstInc, numPts);
@@ -784,8 +799,8 @@ next:   for (final Map.Entry<Envelope,Ma
                               final double[] dstPts, int dstOff, int numPts) throws TransformException
         {
             if (numPts <= 0) return;
-            final int srcInc = generic.getSourceDimensions();
-            final int dstInc = generic.getTargetDimensions();
+            final int srcInc = global.getSourceDimensions();
+            final int dstInc = global.getTargetDimensions();
             transform((tr, src, dst, num) -> tr.transform(srcPts, src, dstPts, dst, num),
                       dstPts, srcOff, dstOff, srcInc, dstInc, numPts);
         }

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform1D.txt
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform1D.txt?rev=1825945&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform1D.txt
(added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform1D.txt
[UTF-8] Mon Mar  5 22:13:04 2018
@@ -0,0 +1,3 @@
+There is no SpecializableTransform1D implementation yet because
+a more specific implementation will be needed for grid Coverage.
+It may look like the SampleDimension class in Geotk.

Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform1D.txt
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform1D.txt
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform2D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform2D.java?rev=1825945&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform2D.java
(added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform2D.java
[UTF-8] Mon Mar  5 22:13:04 2018
@@ -0,0 +1,139 @@
+/*
+ * 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.referencing.operation.transform;
+
+import java.util.Map;
+import java.awt.Shape;
+import java.awt.geom.Point2D;
+import org.opengis.geometry.Envelope;
+import org.opengis.referencing.operation.Matrix;
+import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.MathTransform2D;
+import org.opengis.referencing.operation.TransformException;
+import org.opengis.referencing.operation.NoninvertibleTransformException;
+
+
+/**
+ * A specializable transform in the two-dimensional case.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.0
+ * @since   1.0
+ * @module
+ */
+final class SpecializableTransform2D extends SpecializableTransform implements MathTransform2D
{
+    /**
+     * Serial number for inter-operability with different versions.
+     */
+    private static final long serialVersionUID = 2924682501896480813L;
+
+    /**
+     * Creates a new transform.
+     */
+    SpecializableTransform2D(MathTransform global, Map<Envelope,MathTransform> specializations)
{
+        super(global, specializations);
+    }
+
+    /**
+     * Transforms the specified {@code ptSrc} and stores the result in {@code ptDst}.
+     */
+    @Override
+    public Point2D transform(final Point2D ptSrc, final Point2D ptDst) throws TransformException
{
+        return AbstractMathTransform2D.transform(this, ptSrc, ptDst);
+    }
+
+    /**
+     * Transforms the specified shape.
+     */
+    @Override
+    public Shape createTransformedShape(final Shape shape) throws TransformException {
+        return AbstractMathTransform2D.createTransformedShape(this, shape, null, null, false);
+    }
+
+    /**
+     * Gets the derivative of this transform at a point.
+     */
+    @Override
+    public Matrix derivative(final Point2D point) throws TransformException {
+        return AbstractMathTransform2D.derivative(this, point);
+    }
+
+    /**
+     * Returns the inverse transform of this object.
+     */
+    @Override
+    public MathTransform2D inverse() throws NoninvertibleTransformException {
+        return (MathTransform2D) super.inverse();
+    }
+
+    /**
+     * Invoked at construction time for creating the two-dimensional inverse transform.
+     */
+    @Override
+    Inverse createInverse() throws NoninvertibleTransformException {
+        return new Inverse(this);
+    }
+
+    /**
+     * The inverse of {@link SpecializableTransform2D}.
+     */
+    static final class Inverse extends SpecializableTransform.Inverse implements MathTransform2D
{
+        /**
+         * Serial number for inter-operability with different versions.
+         */
+        private static final long serialVersionUID = 366420739633368389L;
+
+        /**
+         * Creates a new inverse transform.
+         */
+        Inverse(SpecializableTransform2D forward) throws NoninvertibleTransformException
{
+            super(forward);
+        }
+
+        /**
+         * Transforms the specified {@code ptSrc} and stores the result in {@code ptDst}.
+         */
+        @Override
+        public Point2D transform(final Point2D ptSrc, final Point2D ptDst) throws TransformException
{
+            return AbstractMathTransform2D.transform(this, ptSrc, ptDst);
+        }
+
+        /**
+         * Transforms the specified shape.
+         */
+        @Override
+        public Shape createTransformedShape(final Shape shape) throws TransformException
{
+            return AbstractMathTransform2D.createTransformedShape(this, shape, null, null,
false);
+        }
+
+        /**
+         * Gets the derivative of this transform at a point.
+         */
+        @Override
+        public Matrix derivative(final Point2D point) throws TransformException {
+            return AbstractMathTransform2D.derivative(this, point);
+        }
+
+        /**
+         * Returns the inverse transform of this object.
+         */
+        @Override
+        public MathTransform2D inverse() {
+            return (MathTransform2D) super.inverse();
+        }
+    }
+}

Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform2D.java
------------------------------------------------------------------------------
    svn:eol-style = native

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

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/SpecializableTransformTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/SpecializableTransformTest.java?rev=1825945&r1=1825944&r2=1825945&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/SpecializableTransformTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/SpecializableTransformTest.java
[UTF-8] Mon Mar  5 22:13:04 2018
@@ -21,9 +21,9 @@ import java.util.HashMap;
 import org.opengis.geometry.Envelope;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.TransformException;
-import org.apache.sis.referencing.factory.InvalidGeodeticParameterException;
 import org.apache.sis.internal.referencing.j2d.AffineTransform2D;
 import org.apache.sis.geometry.Envelope2D;
+import org.apache.sis.test.DependsOnMethod;
 import org.junit.Test;
 
 import static org.junit.Assert.*;
@@ -49,13 +49,17 @@ public final strictfp class Specializabl
     /**
      * Creates a transform to test.
      *
-     * @throws InvalidGeodeticParameterException if {@link SpecializableTransform} constructor
reject a parameter.
+     * @throws IllegalArgumentException if {@link SpecializableTransform} constructor rejects
a parameter.
      */
-    private static SpecializableTransform create() throws InvalidGeodeticParameterException
{
+    private static SpecializableTransform create(final boolean is2D) {
         final Map<Envelope,MathTransform> specializations = new HashMap<>(4);
         assertNull(specializations.put(new Envelope2D(null, -5, -4, 10, 7), translation(0.1)));
         assertNull(specializations.put(new Envelope2D(null, -3, -1,  5, 2), translation(0.2)));
-        return new SpecializableTransform(translation(0), specializations);
+        final MathTransform global = translation(0);
+        if (is2D) {
+            return new SpecializableTransform2D(global, specializations);
+        }
+        return new SpecializableTransform(global, specializations);
     }
 
     /**
@@ -76,17 +80,36 @@ public final strictfp class Specializabl
      * situations where two transforms could calculate the same point (because of the way
we created
      * our test transform).
      *
-     * @throws InvalidGeodeticParameterException if {@link SpecializableTransform} constructor
reject a parameter.
+     * @throws IllegalArgumentException if {@link SpecializableTransform} constructor rejects
a parameter.
+     * @throws TransformException if a transformation failed.
+     */
+    @Test
+    public void testTransform() throws TransformException {
+        verifyNonAmbiguousPoints(false);
+    }
+
+    /**
+     * Verifies the transformation using two-dimensional variant.
+     *
+     * @throws IllegalArgumentException if {@link SpecializableTransform} constructor rejects
a parameter.
      * @throws TransformException if a transformation failed.
      */
     @Test
-    public void testTransform() throws InvalidGeodeticParameterException, TransformException
{
-        //                      ┌─── generic ───┐┌───── Special.
1 ──────┐┌──── Special. 2 ─────┐
-        final double[] source = {8,  2,  4,  5,   3,    2,    2,    -2,    -2,    0,   1,
   0,   8,  3};
-        final double[] target = {80, 20, 40, 50,  30.1, 20.1, 20.1, -19.9, -19.8, 0.2, 10.2,
0.2, 80, 30};
+    @DependsOnMethod("testTransform")
+    public void testTransform2D() throws TransformException {
+        verifyNonAmbiguousPoints(true);
+    }
+
+    /**
+     * Implementation of {@link #testTransform()} and {@link #testTransform2D()}.
+     */
+    private void verifyNonAmbiguousPoints(final boolean is2D) throws TransformException {
+        //                      ┌─── global ───┐┌───── Special.
1 ──────┐┌──── Special. 2 ─────┐
+        final double[] source = {8,  2,  4,  5,  3,    2,    2,    -2,    -2,    0,   1,
   0,   8,  3};
+        final double[] target = {80, 20, 40, 50, 30.1, 20.1, 20.1, -19.9, -19.8, 0.2, 10.2,
0.2, 80, 30};
 
         tolerance = 1E-14;
-        transform = create();
+        transform = create(is2D);
         verifyTransform(source, target);
         verifyDerivatives(source);
 
@@ -103,12 +126,12 @@ public final strictfp class Specializabl
      * some target coordinates can be created from more than one source coordinates. We need
to be
      * "lucky" enough for not testing a point in this case, otherwise the result is undetermined.
      *
-     * @throws InvalidGeodeticParameterException if {@link SpecializableTransform} constructor
reject a parameter.
+     * @throws IllegalArgumentException if {@link SpecializableTransform} constructor rejects
a parameter.
      * @throws TransformException if a transformation failed.
      */
     @Test
-    public void testForwardConsistency() throws InvalidGeodeticParameterException, TransformException
{
-        transform = create();
+    public void testForwardConsistency() throws TransformException {
+        transform = create(false);
         tolerance = 1E-14;
         isDerivativeSupported = false;          // Actually supported, but our test transform
has discontinuities.
         verifyInDomain(CoordinateDomain.RANGE_10, -672445632505596619L);
@@ -120,12 +143,12 @@ public final strictfp class Specializabl
      * used in this test is {@linkplain org.apache.sis.math.FunctionProperty#SURJECTIVE surjective}.
      * See {@link #testForwardConsistency()}.
      *
-     * @throws InvalidGeodeticParameterException if {@link SpecializableTransform} constructor
reject a parameter.
+     * @throws IllegalArgumentException if {@link SpecializableTransform} constructor rejects
a parameter.
      * @throws TransformException if a transformation failed.
      */
     @Test
-    public void testInverseConsistency() throws InvalidGeodeticParameterException, TransformException
{
-        transform = create().inverse();
+    public void testInverseConsistency() throws TransformException {
+        transform = create(false).inverse();
         tolerance = 1E-12;
         isDerivativeSupported = false;          // Actually supported, but our test transform
has discontinuities.
         verifyInDomain(CoordinateDomain.RANGE_100, 4308397764777385180L);
@@ -135,11 +158,11 @@ public final strictfp class Specializabl
      * Tests the pseudo Well-Known Text formatting.
      * The format used by this transform is non-standard and may change in any future Apache
SIS version.
      *
-     * @throws InvalidGeodeticParameterException if {@link SpecializableTransform} constructor
reject a parameter.
+     * @throws IllegalArgumentException if {@link SpecializableTransform} constructor rejects
a parameter.
      */
     @Test
-    public void testWKT() throws InvalidGeodeticParameterException {
-        transform = create();
+    public void testWKT() {
+        transform = create(false);
         assertWktEquals(
                 "SPECIALIZABLE_MT[\n" +
                 "  PARAM_MT[“Affine”,\n" +



Mime
View raw message