sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1600540 [1/2] - in /sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis: internal/referencing/j2d/ referencing/operation/provider/ referencing/operation/transform/
Date Wed, 04 Jun 2014 23:34:39 GMT
Author: desruisseaux
Date: Wed Jun  4 23:34:38 2014
New Revision: 1600540

URL: http://svn.apache.org/r1600540
Log:
Initial port of ProjectiveTransform and its dependencies.

Added:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/ImmutableAffineTransform.java   (with props)
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/provider/
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/provider/Affine.java   (with props)
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AffineTransform2D.java   (with props)
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConstantTransform1D.java   (with props)
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java   (with props)
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/IdentityTransform.java   (with props)
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/IdentityTransform1D.java   (with props)
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/LinearTransform1D.java   (with props)
Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform2D.java
    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/ProjectiveTransform.java

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/ImmutableAffineTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/ImmutableAffineTransform.java?rev=1600540&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/ImmutableAffineTransform.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/ImmutableAffineTransform.java [UTF-8] Wed Jun  4 23:34:38 2014
@@ -0,0 +1,304 @@
+/*
+ * 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.j2d;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
+import org.apache.sis.util.resources.Errors;
+
+
+/**
+ * Overrides all mutable {@link AffineTransform} methods in order to check for permission
+ * before changing the transform state. If {@link #checkPermission()} is defined to always
+ * throw an exception (which is the default), then {@code AffineTransform} is immutable.
+ *
+ * @author  Martin Desruisseaux (IRD, Geomatys)
+ * @since   0.5 (derived from geotk-1.2)
+ * @version 0.5
+ * @module
+ */
+public class ImmutableAffineTransform extends AffineTransform {
+    /**
+     * Serial number for inter-operability with different versions.
+     */
+    private static final long serialVersionUID = 5215291166450556451L;
+
+    /**
+     * Constructs an identity affine transform. This is for subclasses usage only,
+     * for subclasses that override the {@link #checkPermission()} method.
+     */
+    protected ImmutableAffineTransform() {
+        super();
+    }
+
+    /**
+     * Constructs a new transform that is a copy of the specified {@code AffineTransform} object.
+     *
+     * @param tr The affine transform to copy.
+     */
+    public ImmutableAffineTransform(final AffineTransform tr) {
+        super(tr);
+    }
+
+    /**
+     * Constructs a new transform from 6 values representing the 6 specifiable
+     * entries of the 3×3 transformation matrix. Those values are given unchanged to the
+     * {@linkplain AffineTransform#AffineTransform(double,double,double,double,double,double) super class constructor}.
+     *
+     * @param m00 the X coordinate scaling.
+     * @param m10 the Y coordinate shearing.
+     * @param m01 the X coordinate shearing.
+     * @param m11 the Y coordinate scaling.
+     * @param m02 the X coordinate translation.
+     * @param m12 the Y coordinate translation.
+     */
+    public ImmutableAffineTransform(double m00, double m10, double m01, double m11, double m02, double m12) {
+        super(m00, m10, m01, m11, m02, m12);
+    }
+
+    /**
+     * Checks if the caller is allowed to change this {@code AffineTransform} state.
+     * If this method is defined to thrown an exception in all case (which is the default),
+     * then this {@code AffineTransform} is immutable.
+     *
+     * <p>An {@code ImmutableAffineTransform} may be temporary mutable at construction time,
+     * but shall be back to immutable state before the instance is given to the user.</p>
+     *
+     * @throws UnsupportedOperationException if this affine transform is immutable.
+     */
+    protected void checkPermission() throws UnsupportedOperationException {
+        throw new UnsupportedOperationException(Errors.format(Errors.Keys.UnmodifiableAffineTransform));
+    }
+
+    /**
+     * Checks for {@linkplain #checkPermission() permission} before translating this transform.
+     */
+    @Override
+    public final void translate(double tx, double ty) {
+        checkPermission();
+        super.translate(tx, ty);
+    }
+
+    /**
+     * Checks for {@linkplain #checkPermission() permission} before rotating this transform.
+     */
+    @Override
+    public final void rotate(double theta) {
+        checkPermission();
+        super.rotate(theta);
+    }
+
+    /**
+     * Checks for {@linkplain #checkPermission() permission} before rotating this transform.
+     */
+    @Override
+    public final void rotate(double theta, double anchorx, double anchory) {
+        checkPermission();
+        super.rotate(theta, anchorx, anchory);
+    }
+
+    /**
+     * Checks for {@linkplain #checkPermission() permission} before rotating this transform.
+     */
+    @Override
+    public final void rotate(double vecx, double vecy) {
+        checkPermission();
+        super.rotate(vecx, vecy);
+    }
+
+    /**
+     * Checks for {@linkplain #checkPermission() permission} before rotating this transform.
+     */
+    @Override
+    public final void rotate(double vecx, double vecy, double anchorx, double anchory) {
+        checkPermission();
+        super.rotate(vecx, vecy, anchorx, anchory);
+    }
+
+    /**
+     * Checks for {@linkplain #checkPermission() permission} before rotating this transform.
+     */
+    @Override
+    public final void quadrantRotate(int numquadrants) {
+        checkPermission();
+        super.quadrantRotate(numquadrants);
+    }
+
+    /**
+     * Checks for {@linkplain #checkPermission() permission} before rotating this transform.
+     */
+    @Override
+    public final void quadrantRotate(int numquadrants, double anchorx, double anchory) {
+        checkPermission();
+        super.quadrantRotate(numquadrants, anchorx, anchory);
+    }
+
+    /**
+     * Checks for {@linkplain #checkPermission() permission} before scaling this transform.
+     */
+    @Override
+    public final void scale(double sx, double sy) {
+        checkPermission();
+        super.scale(sx, sy);
+    }
+
+    /**
+     * Checks for {@linkplain #checkPermission() permission} before shearing this transform.
+     */
+    @Override
+    public final void shear(double shx, double shy) {
+        checkPermission();
+        super.shear(shx, shy);
+    }
+
+    /**
+     * Checks for {@linkplain #checkPermission() permission} before setting this transform.
+     */
+    @Override
+    public final void setToIdentity() {
+        checkPermission();
+        super.setToIdentity();
+    }
+
+    /**
+     * Checks for {@linkplain #checkPermission() permission} before setting this transform.
+     */
+    @Override
+    public final void setToTranslation(double tx, double ty) {
+        checkPermission();
+        super.setToTranslation(tx, ty);
+    }
+
+    /**
+     * Checks for {@linkplain #checkPermission() permission} before setting this transform.
+     */
+    @Override
+    public final void setToRotation(double theta) {
+        checkPermission();
+        super.setToRotation(theta);
+    }
+
+    /**
+     * Checks for {@linkplain #checkPermission() permission} before setting this transform.
+     */
+    @Override
+    public final void setToRotation(double theta, double anchorx, double anchory) {
+        checkPermission();
+        super.setToRotation(theta, anchorx, anchory);
+    }
+
+    /**
+     * Checks for {@linkplain #checkPermission() permission} before setting this transform.
+     */
+    @Override
+    public final void setToRotation(double vecx, double vecy) {
+        checkPermission();
+        super.setToRotation(vecx, vecy);
+    }
+
+    /**
+     * Checks for {@linkplain #checkPermission() permission} before setting this transform.
+     */
+    @Override
+    public final void setToRotation(double vecx, double vecy, double anchorx, double anchory) {
+        checkPermission();
+        super.setToRotation(vecx, vecy, anchorx, anchory);
+    }
+
+    /**
+     * Checks for {@linkplain #checkPermission() permission} before setting this transform.
+     */
+    @Override
+    public final void setToQuadrantRotation(int numquadrants) {
+        checkPermission();
+        super.setToQuadrantRotation(numquadrants);
+    }
+
+    /**
+     * Checks for {@linkplain #checkPermission() permission} before setting this transform.
+     */
+    @Override
+    public final void setToQuadrantRotation(int numquadrants, double anchorx, double anchory) {
+        checkPermission();
+        super.setToQuadrantRotation(numquadrants, anchorx, anchory);
+    }
+
+    /**
+     * Checks for {@linkplain #checkPermission() permission} before setting this transform.
+     */
+    @Override
+    public final void setToScale(double sx, double sy) {
+        checkPermission();
+        super.setToScale(sx, sy);
+    }
+
+    /**
+     * Checks for {@linkplain #checkPermission() permission} before setting this transform.
+     */
+    @Override
+    public final void setToShear(double shx, double shy) {
+        checkPermission();
+        super.setToShear(shx, shy);
+    }
+
+    /**
+     * Checks for {@linkplain #checkPermission() permission} before setting this transform.
+     */
+    @Override
+    public final void setTransform(AffineTransform Tx) {
+        checkPermission();
+        super.setTransform(Tx);
+    }
+
+    /**
+     * Checks for {@linkplain #checkPermission() permission} before setting this transform.
+     */
+    @Override
+    public final void setTransform(double m00, double m10,
+                             double m01, double m11,
+                             double m02, double m12) {
+        checkPermission();
+        super.setTransform(m00, m10, m01, m11, m02, m12);
+    }
+
+    /**
+     * Checks for {@linkplain #checkPermission() permission} before concatenating this transform.
+     */
+    @Override
+    public final void concatenate(AffineTransform Tx) {
+        checkPermission();
+        super.concatenate(Tx);
+    }
+
+    /**
+     * Checks for {@linkplain #checkPermission() permission} before concatenating this transform.
+     */
+    @Override
+    public final void preConcatenate(AffineTransform Tx) {
+        checkPermission();
+        super.preConcatenate(Tx);
+    }
+
+    /**
+     * Checks for {@linkplain #checkPermission() permission} before inverting this transform.
+     */
+    @Override
+    public final void invert() throws NoninvertibleTransformException {
+        checkPermission();
+        super.invert();
+    }
+}

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

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

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/provider/Affine.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/provider/Affine.java?rev=1600540&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/provider/Affine.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/provider/Affine.java Wed Jun  4 23:34:38 2014
@@ -0,0 +1,23 @@
+/*
+ * 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.provider;
+
+import org.opengis.parameter.ParameterDescriptorGroup;
+
+public class Affine {
+    public static ParameterDescriptorGroup PARAMETERS; // TODO
+}

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

Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/provider/Affine.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java?rev=1600540&r1=1600539&r2=1600540&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java [UTF-8] Wed Jun  4 23:34:38 2014
@@ -908,8 +908,8 @@ public abstract class AbstractMathTransf
             final Matrix m1 = t1.getMatrix();
             if (m1 != null) {
                 final Matrix m2 = ((LinearTransform) t2).getMatrix();
-                if (m1 instanceof org.apache.sis.util.LenientComparable) {
-                    return ((org.apache.sis.util.LenientComparable) m1).equals(m2, mode);
+                if (m1 instanceof LenientComparable) {
+                    return ((LenientComparable) m1).equals(m2, mode);
                 }
                 return Matrices.equals(m1, m2, mode);
             }

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AffineTransform2D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AffineTransform2D.java?rev=1600540&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AffineTransform2D.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AffineTransform2D.java [UTF-8] Wed Jun  4 23:34:38 2014
@@ -0,0 +1,390 @@
+/*
+ * 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.awt.Shape;
+import java.awt.geom.Point2D;
+import java.awt.geom.AffineTransform;
+import org.opengis.geometry.DirectPosition;
+import org.opengis.parameter.ParameterValueGroup;
+import org.opengis.parameter.ParameterDescriptorGroup;
+import org.opengis.referencing.operation.Matrix;
+import org.opengis.referencing.operation.MathTransform2D;
+import org.opengis.referencing.operation.NoninvertibleTransformException;
+import org.apache.sis.geometry.DirectPosition2D;
+import org.apache.sis.parameter.Parameterized;
+import org.apache.sis.referencing.operation.matrix.Matrix2;
+import org.apache.sis.referencing.operation.matrix.AffineTransforms2D;
+import org.apache.sis.referencing.operation.provider.Affine;
+import org.apache.sis.io.wkt.Formatter;
+import org.apache.sis.internal.referencing.j2d.ImmutableAffineTransform;
+import org.apache.sis.util.LenientComparable;
+import org.apache.sis.util.ComparisonMode;
+import org.apache.sis.util.Workaround;
+
+import static org.apache.sis.util.ArgumentChecks.ensureDimensionMatches;
+
+
+/**
+ * Transforms two-dimensional coordinate points using an affine transform. This class both extends
+ * {@link AffineTransform} and implements {@link MathTransform2D}, so it can be used as a bridge
+ * between Java2D and the referencing module. Note that this bridge role involve a tricky issue with
+ * the {@link #equals(Object) equals} method, hopefully to occur only in exceptional corner cases.
+ *
+ * @author  Martin Desruisseaux (IRD, Geomatys)
+ * @since   0.5 (derived from geotk-1.2)
+ * @version 0.5
+ * @module
+ *
+ * @see ProjectiveTransform
+ */
+final class AffineTransform2D extends ImmutableAffineTransform implements MathTransform2D, LinearTransform,
+        LenientComparable, Parameterized, Cloneable
+{
+    /**
+     * Serial number for inter-operability with different versions.
+     */
+    private static final long serialVersionUID = -5299837898367149069L;
+
+    /**
+     * The inverse transform. This field will be computed only when needed.
+     */
+    private transient volatile AffineTransform2D inverse;
+
+    /**
+     * {@code true} if this transform is mutable. This field may be temporarily set
+     * to {@code true} during construction, but <strong>must</strong> be reset to
+     * {@code false} before a reference to {@link AffineTransform2D} is made public.
+     */
+    transient boolean mutable;
+
+    /**
+     * Constructs an identity affine transform.  This constructor is reserved to code that
+     * temporarily set the {@linkplain #mutable} flag to {@code true} for initializing the
+     * affine transform.
+     */
+    AffineTransform2D() {
+        super();
+    }
+
+    /**
+     * Constructs a new affine transform with the same coefficient than the specified transform.
+     *
+     * @param transform The affine transform to copy.
+     */
+    public AffineTransform2D(final AffineTransform transform) {
+        super(transform);
+        mutable = true;
+        forcePositiveZeros();
+        mutable = false;
+    }
+
+    /**
+     * Constructs a new {@code AffineTransform2D} from 6 values representing the 6 specifiable
+     * entries of the 3×3 transformation matrix. Those values are given unchanged to the
+     * {@link AffineTransform#AffineTransform(double,double,double,double,double,double) super
+     * class constructor}.
+     *
+     * @param m00 the X coordinate scaling.
+     * @param m10 the Y coordinate shearing.
+     * @param m01 the X coordinate shearing.
+     * @param m11 the Y coordinate scaling.
+     * @param m02 the X coordinate translation.
+     * @param m12 the Y coordinate translation.
+     */
+    public AffineTransform2D(double m00, double m10, double m01, double m11, double m02, double m12) {
+        super(pz(m00), pz(m10), pz(m01), pz(m11), pz(m02), pz(m12));
+    }
+
+    /**
+     * Makes sure that the zero is positive. We do that in order to workaround a JDK 6 bug,
+     * where AffineTransform.hashCode() is inconsistent with AffineTransform.equals(Object)
+     * if there is zeros of opposite sign.
+     */
+    @Workaround(library="JDK", version="6")
+    private static double pz(final double value) {
+        return (value != 0) ? value : 0;
+    }
+
+    /**
+     * Ensures that this transform contains only positive zeros.
+     */
+    final void forcePositiveZeros() {
+        super.setTransform(pz(super.getScaleX()),     pz(super.getShearY()),
+                           pz(super.getShearX()),     pz(super.getScaleY()),
+                           pz(super.getTranslateX()), pz(super.getTranslateY()));
+    }
+
+    /**
+     * Throws an {@link UnsupportedOperationException} when a mutable method
+     * is invoked, since {@code AffineTransform2D} must be immutable.
+     *
+     * @throws UnsupportedOperationException Always thrown.
+     */
+    @Override
+    protected final void checkPermission() throws UnsupportedOperationException {
+        if (!mutable) {
+            super.checkPermission();
+        }
+    }
+
+    /**
+     * Returns the parameter descriptors for this math transform.
+     */
+    @Override
+    public ParameterDescriptorGroup getParameterDescriptors() {
+        return Affine.PARAMETERS;
+    }
+
+    /**
+     * Returns the matrix elements as a group of parameters values. The number of parameters
+     * depends on the matrix size. Only matrix elements different from their default value
+     * will be included in this group.
+     */
+    @Override
+    public ParameterValueGroup getParameterValues() {
+        return ProjectiveTransform.getParameterValues(getMatrix());
+    }
+
+    /**
+     * Gets the dimension of input points, which is fixed to 2.
+     */
+    @Override
+    public final int getSourceDimensions() {
+        return 2;
+    }
+
+    /**
+     * Gets the dimension of output points, which is fixed to 2.
+     */
+    @Override
+    public final int getTargetDimensions() {
+        return 2;
+    }
+
+    /**
+     * Transforms the specified {@code ptSrc} and stores the result in {@code ptDst}.
+     */
+    @Override
+    public DirectPosition transform(final DirectPosition ptSrc, DirectPosition ptDst) {
+        ensureDimensionMatches("ptSrc", 2, ptSrc);
+        /*
+         * Try to write directly in the destination point if possible. Following
+         * code avoid the creation of temporary objects (except if ptDst is null).
+         */
+        if (ptDst == ptSrc) {
+            if (ptSrc instanceof Point2D) {
+                final Point2D point = (Point2D) ptSrc;
+                super.transform(point, point);
+                return ptSrc;
+            }
+        } else {
+            if (ptDst == null) {
+                final DirectPosition2D point = new DirectPosition2D(ptSrc.getOrdinate(0), ptSrc.getOrdinate(1));
+                super.transform(point, point);
+                return point;
+            }
+            ensureDimensionMatches("ptDst", 2, ptDst);
+            if (ptDst instanceof Point2D) {
+                final Point2D point = (Point2D) ptDst;
+                point.setLocation(ptSrc.getOrdinate(0), ptSrc.getOrdinate(1));
+                super.transform(point, point);
+                return ptDst;
+            }
+        }
+        /*
+         * At this point, we have no choice to create a temporary Point2D.
+         */
+        final Point2D.Double point = new Point2D.Double(ptSrc.getOrdinate(0), ptSrc.getOrdinate(1));
+        super.transform(point, point);
+        ptDst.setOrdinate(0, point.x);
+        ptDst.setOrdinate(1, point.y);
+        return ptDst;
+    }
+
+    /**
+     * Transforms the specified shape. This method creates a simpler shape then the default
+     * {@linkplain AffineTransform#createTransformedShape(Shape) super-class implementation}.
+     * For example if the given shape is a rectangle and this affine transform has no scale or
+     * shear, then the returned shape will be an instance of {@link java.awt.geom.Rectangle2D}.
+     *
+     * @param  shape Shape to transform.
+     * @return Transformed shape, or {@code shape} if this transform is the identity transform.
+     */
+    @Override
+    public Shape createTransformedShape(final Shape shape) {
+        return AffineTransforms2D.transform(this, shape, false);
+    }
+
+    /**
+     * Returns this transform as an affine transform matrix.
+     */
+    @Override
+    public Matrix getMatrix() {
+        return AffineTransforms2D.toMatrix(this);
+    }
+
+    /**
+     * Gets the derivative of this transform at a point.
+     * For an affine transform, the derivative is the same everywhere.
+     */
+    @Override
+    public Matrix derivative(final Point2D point) {
+        return new Matrix2(getScaleX(), getShearX(),
+                           getShearY(), getScaleY());
+    }
+
+    /**
+     * Gets the derivative of this transform at a point.
+     * For an affine transform, the derivative is the same everywhere.
+     */
+    @Override
+    public Matrix derivative(final DirectPosition point) {
+        return derivative((Point2D) null);
+    }
+
+    /**
+     * Creates the inverse transform of this object.
+     *
+     * @throws NoninvertibleTransformException if this transform can not be inverted.
+     */
+    @Override
+    public MathTransform2D inverse() throws NoninvertibleTransformException {
+        if (inverse == null) {
+            if (super.isIdentity()) {
+                inverse = this;
+            } else synchronized (this) {
+                /*
+                 * Double check idiom. Was deprecated before Java 5 (couldn't work reliably).
+                 * Is okay with the new memory model since Java 5 provided that the field is
+                 * declared volatile (Joshua Bloch, "Effective Java" second edition).
+                 */
+                if (inverse == null) try {
+                    final AffineTransform2D work = new AffineTransform2D(this);
+                    work.mutable = true;
+                    work.invert();
+                    work.forcePositiveZeros();
+                    work.mutable = false;
+                    work.inverse = this;
+                    inverse = work; // Set only on success.
+                } catch (java.awt.geom.NoninvertibleTransformException exception) {
+                    throw new NoninvertibleTransformException(exception.getLocalizedMessage(), exception);
+                }
+            }
+        }
+        return inverse;
+    }
+
+    /**
+     * Compares this affine transform with the given object for equality. This method behaves as documented
+     * in the {@link LinearTransform#equals(Object, ComparisonMode) LinearTransform} interface, except for
+     * the following case: if the given mode is {@link ComparisonMode#STRICT}, then this method delegates
+     * to {@link #equals(Object)}. The later method has different rules than the ones documented in the
+     * {@code LinearTransform} interface, because of the {@code AffineTransform} inheritance.
+     *
+     * @param  object The object to compare to {@code this}.
+     * @param  mode The strictness level of the comparison.
+     * @return {@code true} if both objects are equal.
+     */
+    @Override
+    public boolean equals(final Object object, final ComparisonMode mode) {
+        if (mode == ComparisonMode.STRICT) {
+            return equals(object);
+        }
+        return (object == this) || AbstractMathTransform.equals(this, object, mode);
+    }
+
+    /**
+     * Compares this affine transform with the given object for equality. The comparison is performed in the same way
+     * than {@link AffineTransform#equals(Object)} with one additional rule: if the other object is also an instance
+     * of {@code AffineTransform2D}, then the two objects must be of the exact same class.
+     *
+     * <p>Most SIS implementations require that the objects being compared are unconditionally of the same class in
+     * order to be considered equal. However many JDK implementations, including {@link AffineTransform}, do not have
+     * this requirement. Consequently the above condition (i.e. require the same class only if the given object is an
+     * {@code AffineTransform2D} or a subclass) is necessary in order to preserve the <cite>symmetricity</cite> contract
+     * of {@link Object#equals(Object)}.</p>
+     *
+     * <p>A side-effect of this implementation is that the <cite>transitivity</cite> contract of
+     * {@code Object.equals(Object)} may be broken is some corner cases. This contract said:</p>
+     *
+     * <blockquote>
+     * <code>a.equals(b)</code> and <code>b.equals(c)</code> implies <code>a.equals(c)</code>
+     * </blockquote>
+     *
+     * Assuming that <var>a</var>, <var>b</var> and <var>c</var> are instances of {@code AffineTransform}
+     * (where "instance of <var>T</var>" means <var>T</var> or any subclass of <var>T</var>), then the transitivity
+     * contract is broken if and only if exactly two of those objects are instance of {@code AffineTransform2D} and
+     * those two objects are not of the same class. Note that this implies that at least one subclass of
+     * {@code AffineTransform2D} is used.
+     *
+     * <p>In the vast majority of cases, the transitivity contract is <strong>not</strong> broken and the users can
+     * ignore this documentation. The transitivity contract is typically not broken either because we usually don't
+     * subclass {@code AffineTransform2D}, or because we don't mix {@code AffineTransform} with {@code AffineTransform2D}
+     * subclasses in the same collection.</p>
+     *
+     * <p>This special case exists in order to allow developers to attach additional information to their own subclass
+     * of {@code AffineTransform2D}, and still distinguish their specialized subclass from ordinary affine transforms
+     * in a pool of {@code MathTransform} instances. The main application is the
+     * {@linkplain org.apache.sis.referencing.operation.projection.Equirectangular} map projection,
+     * which can be simplified to an affine transform but still needs to remember the projection parameters.</p>
+     *
+     * @param  object The object to compare with this affine transform for equality.
+     * @return {@code true} if the given object is of appropriate class (as explained in the
+     *         above documentation) and the affine transform coefficients are the same.
+     */
+    @Override
+    public boolean equals(final Object object) {
+        if (object != this) {
+            if (!super.equals(object)) {
+                return false;
+            }
+            if (object instanceof AffineTransform2D) {
+                return object.getClass() == getClass();
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Returns a new affine transform which is a modifiable copy of this transform. This implementation always
+     * returns an instance of {@link AffineTransform}, <strong>not</strong> {@code AffineTransform2D}, because
+     * the later is unmodifiable and cloning it make little sense.
+     */
+    @Override
+    public AffineTransform clone() {
+        return new AffineTransform(this);
+    }
+
+    /**
+     * Returns the WKT for this transform.
+     */
+    @Override
+    public String toWKT() {
+        final Formatter formatter = new Formatter();
+        formatter.append(this);
+        return formatter.toWKT();
+    }
+
+    /**
+     * Returns the WKT representation of this transform.
+     */
+    @Override
+    public String toString() {
+        return toWKT();
+    }
+}

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

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

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java?rev=1600540&r1=1600539&r2=1600540&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java [UTF-8] Wed Jun  4 23:34:38 2014
@@ -236,7 +236,7 @@ class ConcatenatedTransform extends Abst
                  * Apache SIS performs matrix operations using double-double arithmetic in the hope to get exact
                  * results at the 'double' accuracy, which avoid the need for a tolerance threshold.
                  */
-                return ProjectiveTransform.create(matrix);
+                return MathTransforms.linear(matrix);
             }
             /*
              * If the second transform is a passthrough transform and all passthrough ordinates
@@ -247,7 +247,7 @@ class ConcatenatedTransform extends Abst
                 final Matrix sub = candidate.toSubMatrix(matrix1);
                 if (sub != null) {
                     return PassThroughTransform.create(candidate.firstAffectedOrdinate,
-                            create(ProjectiveTransform.create(sub), candidate.subTransform),
+                            create(MathTransforms.linear(sub), candidate.subTransform),
                             candidate.numTrailingOrdinates);
                 }
             }
@@ -259,7 +259,7 @@ class ConcatenatedTransform extends Abst
         if (areInverse(tr1, tr2) || areInverse(tr2, tr1)) {
             assert tr1.getSourceDimensions() == tr2.getTargetDimensions();
             assert tr1.getTargetDimensions() == tr2.getSourceDimensions();
-            return ProjectiveTransform.identity(tr1.getSourceDimensions());
+            return MathTransforms.identity(tr1.getSourceDimensions());
         }
         /*
          * Gives a chance to AbstractMathTransform to returns an optimized object.

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform2D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform2D.java?rev=1600540&r1=1600539&r2=1600540&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform2D.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform2D.java [UTF-8] Wed Jun  4 23:34:38 2014
@@ -91,7 +91,7 @@ final class ConcatenatedTransform2D exte
      * {@link #transform1} and {@link #transform2} may not be instances of {@link MathTransform2D}.
      *
      * @param  point The coordinate point where to evaluate the derivative.
-     * @return The derivative at the specified point as a 2&times;2 matrix.
+     * @return The derivative at the specified point as a 2×2 matrix.
      * @throws TransformException if the derivative can't be evaluated at the specified point.
      */
     @Override

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConstantTransform1D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConstantTransform1D.java?rev=1600540&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConstantTransform1D.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConstantTransform1D.java [UTF-8] Wed Jun  4 23:34:38 2014
@@ -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.referencing.operation.transform;
+
+import java.util.Arrays;
+
+
+/**
+ * A one dimensional, constant transform. Output values are set to a constant value regardless of input values.
+ * This class is a special case of {@link LinearTransform1D} in which <code>{@linkplain #scale} = 0</code> and
+ * <code>{@linkplain #offset} = constant</code>. However, this specialized {@code ConstantTransform1D} class is
+ * faster.
+ *
+ * @author  Martin Desruisseaux (IRD, Geomatys)
+ * @since   0.5 (derived from geotk-2.0)
+ * @version 0.5
+ * @module
+ */
+final class ConstantTransform1D extends LinearTransform1D {
+    /**
+     * Serial number for inter-operability with different versions.
+     */
+    private static final long serialVersionUID = -1583675681650985947L;
+
+    /**
+     * Constructs a new constant transform.
+     *
+     * @param offset The {@code offset} term in the linear equation.
+     */
+    ConstantTransform1D(final double offset) {
+        super(0, offset);
+    }
+
+    /**
+     * Transforms the specified value.
+     */
+    @Override
+    public double transform(double value) {
+        return offset;
+    }
+
+    /**
+     * Transforms many coordinates in a list of ordinal values.
+     */
+    @Override
+    public void transform(final double[] srcPts, int srcOff,
+                          final double[] dstPts, int dstOff, int numPts)
+    {
+        Arrays.fill(dstPts, dstOff, dstOff + numPts, offset);
+    }
+
+    /**
+     * Transforms many coordinates in a list of ordinal values.
+     */
+    @Override
+    public void transform(final float[] srcPts, int srcOff,
+                          final float[] dstPts, int dstOff, int numPts)
+    {
+        Arrays.fill(dstPts, dstOff, dstOff + numPts, (float) offset);
+    }
+
+    /**
+     * Transforms many coordinates in a list of ordinal values.
+     */
+    @Override
+    public void transform(final double[] srcPts, int srcOff,
+                          final float [] dstPts, int dstOff, int numPts)
+    {
+        Arrays.fill(dstPts, dstOff, dstOff + numPts, (float) offset);
+    }
+
+    /**
+     * Transforms many coordinates in a list of ordinal values.
+     */
+    @Override
+    public void transform(final float [] srcPts, int srcOff,
+                          final double[] dstPts, int dstOff, int numPts)
+    {
+        Arrays.fill(dstPts, dstOff, dstOff + numPts, offset);
+    }
+}

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

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

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java?rev=1600540&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java [UTF-8] Wed Jun  4 23:34:38 2014
@@ -0,0 +1,425 @@
+/*
+ * 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.Arrays;
+import java.io.Serializable;
+import org.opengis.geometry.DirectPosition;
+import org.opengis.referencing.operation.Matrix;
+import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.NoninvertibleTransformException;
+import org.opengis.parameter.ParameterValueGroup;
+import org.opengis.parameter.ParameterDescriptorGroup;
+import org.apache.sis.referencing.operation.provider.Affine;
+import org.apache.sis.referencing.operation.matrix.MatrixSIS;
+import org.apache.sis.referencing.operation.matrix.Matrices;
+import org.apache.sis.util.ComparisonMode;
+
+
+
+/**
+ * A transform which copy the ordinates in the source array to different locations in the target array.
+ * This is a special case of {@link ProjectiveTransform} where the matrix coefficients are zero everywhere,
+ * except one value by row which is set to 1 and is not the translation term. Those transforms are used for
+ * swapping axis order, or selecting the dimension to retain when converting from a large dimension to a smaller one.
+ * This transform has the particularity to involve no floating point operation - just copy of values with no change -
+ * and consequently works well with NaN ordinate values.
+ *
+ * <p>We do not provide a subclass for the 2D case because our policy is to use
+ * an {@link java.awt.geom.AffineTransform} for every 2D affine conversions.</p>
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.5 (derived from geotk-3.08)
+ * @version 0.5
+ * @module
+ */
+final class CopyTransform extends AbstractMathTransform implements LinearTransform, Serializable {
+    /**
+     * Serial number for inter-operability with different versions.
+     */
+    private static final long serialVersionUID = 5457032501070947956L;
+
+    /**
+     * The dimension of source coordinates.
+     * Must be greater than the highest value in {@link #indices}.
+     */
+    private final int srcDim;
+
+    /**
+     * The indices of ordinates to copy in the source array.
+     * The length of this array is the target dimension.
+     */
+    private final int[] indices;
+
+    /**
+     * The inverse transform. Will be created only when first needed.
+     */
+    private transient MathTransform inverse;
+
+    /**
+     * Creates a new transform.
+     *
+     * @param srcDim The dimension of source coordinates.
+     *        Must be greater than the highest value in {@code indices}.
+     * @param indices The indices of ordinates to copy in the source array.
+     *        The length of this array is the target dimension.
+     */
+    CopyTransform(final int srcDim, final int... indices) {
+        this.srcDim  = srcDim;
+        this.indices = indices;
+    }
+
+    /**
+     * If a transform can be created from the given matrix, returns it.
+     * Otherwise returns {@code null}.
+     */
+    static CopyTransform create(final Matrix matrix) {
+        final int srcDim = matrix.getNumCol() - 1;
+        final int dstDim = matrix.getNumRow() - 1;
+        for (int i=0; i<=srcDim; i++) {
+            if (matrix.getElement(dstDim, i) != (i == srcDim ? 1 : 0)) {
+                // Not an affine transform.
+                return null;
+            }
+        }
+        final int[] indices = new int[dstDim];
+        for (int j=0; j<dstDim; j++) {
+            if (matrix.getElement(j, srcDim) != 0) {
+                // The matrix has translation terms.
+                return null;
+            }
+            boolean found = false;
+            for (int i=0; i<srcDim; i++) {
+                final double elt = matrix.getElement(j, i);
+                if (elt != 0) {
+                    if (elt != 1 || found) {
+                        // Not a simple copy operation.
+                        return null;
+                    }
+                    indices[j] = i;
+                    found = true;
+                }
+            }
+            if (!found) {
+                // Target ordinate unconditionally set to 0 (not a copy).
+                return null;
+            }
+        }
+        return new CopyTransform(srcDim, indices);
+    }
+
+    /**
+     * Gets the dimension of input points.
+     */
+    @Override
+    public int getSourceDimensions() {
+        return srcDim;
+    }
+
+    /**
+     * Gets the dimension of output points.
+     */
+    @Override
+    public int getTargetDimensions() {
+        return indices.length;
+    }
+
+    /**
+     * Tests whether this transform does not move any points.
+     */
+    @Override
+    public boolean isIdentity() {
+        if (srcDim != indices.length) {
+            return false;
+        }
+        for (int i=indices.length; --i>=0;) {
+            if (indices[i] != i) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Transforms a single coordinate in a list of ordinal values, and optionally returns
+     * the derivative at that location.
+     */
+    @Override
+    public Matrix transform(final double[] srcPts, final int srcOff,
+                            final double[] dstPts, final int dstOff,
+                            final boolean derivate)
+    {
+        transform(srcPts, srcOff, dstPts, dstOff, 1);
+        return derivate ? derivative((DirectPosition) null) : null;
+    }
+
+    /**
+     * Transforms an array of floating point coordinates by this matrix.
+     */
+    @Override
+    public void transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts) {
+        final int srcDim, dstDim;
+        final int[] indices = this.indices;
+        int srcInc = srcDim = this.srcDim;
+        int dstInc = dstDim = indices.length;
+        if (srcPts == dstPts) {
+            switch (IterationStrategy.suggest(srcOff, srcDim, dstOff, dstDim, numPts)) {
+                case ASCENDING: {
+                    break;
+                }
+                case DESCENDING: {
+                    srcOff += (numPts-1) * srcDim;
+                    dstOff += (numPts-1) * dstDim;
+                    srcInc = -srcInc;
+                    dstInc = -dstInc;
+                    break;
+                }
+                default: {
+                    srcPts = Arrays.copyOfRange(srcPts, srcOff, srcOff + numPts*srcDim);
+                    srcOff = 0;
+                    break;
+                }
+            }
+        }
+        if (srcPts != dstPts) {
+            // Optimisation for a common case.
+            while (--numPts >= 0) {
+                for (int i=0; i<dstDim; i++) {
+                    dstPts[dstOff++] = srcPts[srcOff + indices[i]];
+                }
+                srcOff += srcDim;
+            }
+        } else {
+            // General case: there is a risk that two coordinates overlap.
+            final double[] buffer = new double[dstDim];
+            while (--numPts >= 0) {
+                for (int i=0; i<dstDim; i++) {
+                    buffer[i] = srcPts[srcOff + indices[i]];
+                }
+                System.arraycopy(buffer, 0, dstPts, dstOff, dstDim);
+                srcOff += srcInc;
+                dstOff += dstInc;
+            }
+        }
+    }
+
+    /**
+     * Transforms an array of floating point coordinates by this matrix.
+     */
+    @Override
+    public void transform(float[] srcPts, int srcOff, float[] dstPts, int dstOff, int numPts) {
+        final int srcDim, dstDim;
+        final int[] indices = this.indices;
+        int srcInc = srcDim = this.srcDim;
+        int dstInc = dstDim = indices.length;
+        if (srcPts == dstPts) {
+            switch (IterationStrategy.suggest(srcOff, srcDim, dstOff, dstDim, numPts)) {
+                case ASCENDING: {
+                    break;
+                }
+                case DESCENDING: {
+                    srcOff += (numPts-1) * srcDim;
+                    dstOff += (numPts-1) * dstDim;
+                    srcInc = -srcInc;
+                    dstInc = -dstInc;
+                    break;
+                }
+                default: {
+                    srcPts = Arrays.copyOfRange(srcPts, srcOff, srcOff + numPts*srcDim);
+                    srcOff = 0;
+                    break;
+                }
+            }
+        }
+        if (srcPts != dstPts) {
+            // Optimisation for a common case.
+            while (--numPts >= 0) {
+                for (int i=0; i<dstDim; i++) {
+                    dstPts[dstOff++] = srcPts[srcOff + indices[i]];
+                }
+                srcOff += srcDim;
+            }
+        } else {
+            // General case: there is a risk that two coordinates overlap.
+            final float[] buffer = new float[dstDim];
+            while (--numPts >= 0) {
+                for (int i=0; i<dstDim; i++) {
+                    buffer[i] = srcPts[srcOff + indices[i]];
+                }
+                System.arraycopy(buffer, 0, dstPts, dstOff, dstDim);
+                srcOff += srcInc;
+                dstOff += dstInc;
+            }
+        }
+    }
+
+    /**
+     * Transforms an array of floating point coordinates by this matrix.
+     */
+    @Override
+    public void transform(double[] srcPts, int srcOff, float[] dstPts, int dstOff, int numPts) {
+        final int[] indices = this.indices;
+        final int srcDim = this.srcDim;
+        final int dstDim = indices.length;
+        while (--numPts >= 0) {
+            for (int i=0; i<dstDim; i++) {
+                dstPts[dstOff++] = (float) srcPts[srcOff + indices[i]];
+            }
+            srcOff += srcDim;
+        }
+    }
+
+    /**
+     * Transforms an array of floating point coordinates by this matrix.
+     */
+    @Override
+    public void transform(float[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts) {
+        final int[] indices = this.indices;
+        final int srcDim = this.srcDim;
+        final int dstDim = indices.length;
+        while (--numPts >= 0) {
+            for (int i=0; i<dstDim; i++) {
+                dstPts[dstOff++] = srcPts[srcOff + indices[i]];
+            }
+            srcOff += srcDim;
+        }
+    }
+
+    /**
+     * Returns the parameter descriptors for this math transform.
+     */
+    @Override
+    public ParameterDescriptorGroup getParameterDescriptors() {
+        return Affine.PARAMETERS;
+    }
+
+    /**
+     * Returns the matrix elements as a group of parameters values.
+     */
+    @Override
+    public ParameterValueGroup getParameterValues() {
+        return ProjectiveTransform.getParameterValues(getMatrix());
+    }
+
+    /**
+     * Returns the matrix.
+     */
+    @Override
+    public Matrix getMatrix() {
+        final int dstDim = indices.length;
+        final MatrixSIS matrix = Matrices.createZero(dstDim + 1, srcDim + 1);
+        for (int j=0; j<dstDim; j++) {
+            matrix.setElement(j, indices[j], 1);
+        }
+        matrix.setElement(dstDim, srcDim, 1);
+        assert equals(create(matrix)) : matrix;
+        return matrix;
+    }
+
+    /**
+     * Gets the derivative of this transform at a point.
+     * For a matrix transform, the derivative is the same everywhere.
+     *
+     * @param point Ignored (can be {@code null}).
+     */
+    @Override
+    public Matrix derivative(final DirectPosition point) {
+        final MatrixSIS matrix = Matrices.createZero(indices.length, srcDim);
+        for (int j=0; j<indices.length; j++) {
+            matrix.setElement(j, indices[j], 1);
+        }
+        return matrix;
+    }
+
+    /**
+     * Creates the inverse transform of this object.
+     */
+    @Override
+    public synchronized MathTransform inverse() throws NoninvertibleTransformException {
+        if (inverse == null) {
+            CopyTransform copyInverse = this;
+            if (!isIdentity()) {
+                final int srcDim = this.srcDim;
+                final int dstDim = indices.length;
+                final int[] reverse = new int[srcDim];
+                Arrays.fill(reverse, -1);
+                for (int i=dstDim; --i>=0;) {
+                    reverse[indices[i]] = i;
+                }
+                /*
+                 * Check if there is any unassigned dimension. In such case,
+                 * delegates to the generic ProjectiveTransform with a matrix
+                 * which set the missing values to NaN.
+                 */
+                for (int j=srcDim; --j>=0;) {
+                    if (reverse[j] < 0) {
+                        final MatrixSIS matrix = Matrices.createZero(srcDim + 1, dstDim + 1);
+                        for (j=0; j<srcDim; j++) { // NOSONAR: the outer loop will not continue.
+                            final int i = reverse[j];
+                            if (i >= 0) {
+                                matrix.setElement(j, i, 1);
+                            } else {
+                                matrix.setElement(j, dstDim, Double.NaN);
+                            }
+                        }
+                        matrix.setElement(srcDim, dstDim, 1);
+                        inverse = MathTransforms.linear(matrix);
+                        if (inverse instanceof ProjectiveTransform) {
+                            ((ProjectiveTransform) inverse).inverse = this;
+                        }
+                        return inverse;
+                    }
+                }
+                /*
+                 * At this point, we known that we can create the inverse transform.
+                 */
+                if (!Arrays.equals(reverse, indices)) {
+                    copyInverse = new CopyTransform(indices.length, reverse);
+                    copyInverse.inverse = this;
+                }
+            }
+            inverse = copyInverse;
+        }
+        return inverse;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected int computeHashCode() {
+        return Arrays.hashCode(indices) + 31 * super.computeHashCode();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean equals(final Object object, final ComparisonMode mode) {
+        if (object == this) { // Slight optimization
+            return true;
+        }
+        if (mode != ComparisonMode.STRICT) {
+            return equals(this, object, mode);
+        }
+        if (super.equals(object, mode)) {
+            final CopyTransform that = (CopyTransform) object;
+            return srcDim == that.srcDim && Arrays.equals(indices, that.indices);
+        }
+        return false;
+    }
+}

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

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

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/IdentityTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/IdentityTransform.java?rev=1600540&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/IdentityTransform.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/IdentityTransform.java [UTF-8] Wed Jun  4 23:34:38 2014
@@ -0,0 +1,266 @@
+/*
+ * 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.io.Serializable;
+import org.opengis.geometry.DirectPosition;
+import org.opengis.parameter.ParameterValueGroup;
+import org.opengis.parameter.ParameterDescriptorGroup;
+import org.opengis.referencing.operation.Matrix;
+import org.opengis.referencing.operation.MathTransform;
+import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.ComparisonMode;
+import org.apache.sis.geometry.GeneralDirectPosition;
+import org.apache.sis.referencing.operation.provider.Affine;
+import org.apache.sis.referencing.operation.matrix.Matrices;
+
+
+/**
+ * The identity transform. The data are only copied without any transformation. Instance of this
+ * class are created for identity transform of dimension greater than 2. For 1D and 2D identity
+ * transforms, {@link LinearTransform1D} and {@link AffineTransform2D} already provide their own
+ * optimizations.
+ *
+ * @author  Martin Desruisseaux (IRD, Geomatys)
+ * @since   0.5 (derived from geotk-2.0)
+ * @version 0.5
+ * @module
+ */
+final class IdentityTransform extends AbstractMathTransform implements LinearTransform, Serializable {
+    /**
+     * Serial number for inter-operability with different versions.
+     */
+    private static final long serialVersionUID = -5339040282922138164L;
+
+    /**
+     * Identity transforms for dimensions ranging from to 0 to 7.
+     * Elements in this array will be created only when first requested.
+     *
+     * @see #identity(int)
+     */
+    private static final LinearTransform[] IDENTITIES = new LinearTransform[8];
+
+    /**
+     * The input and output dimension.
+     */
+    private final int dimension;
+
+    /**
+     * Constructs an identity transform of the specified dimension.
+     *
+     * @param dimension The dimension of the transform to be created.
+     *
+     * @see MathTransforms#identity(int)
+     */
+    private IdentityTransform(final int dimension) {
+        this.dimension = dimension;
+    }
+
+    /**
+     * Returns an identity transform of the specified dimension. In the special case of
+     * dimension 1 and 2, this method returns instances of {@link LinearTransform1D} or
+     * {@link AffineTransform2D} respectively.
+     *
+     * @param dimension The dimension of the transform to be returned.
+     * @return An identity transform of the specified dimension.
+     *
+     * @see MathTransforms#identity(int)
+     */
+    public static LinearTransform create(final int dimension) {
+        LinearTransform candidate;
+        synchronized (IDENTITIES) {
+            if (dimension < IDENTITIES.length) {
+                candidate = IDENTITIES[dimension];
+                if (candidate != null) {
+                    return candidate;
+                }
+            }
+            switch (dimension) {
+                case 1:  candidate = IdentityTransform1D.INSTANCE;     break;
+                case 2:  candidate = new AffineTransform2D();          break;
+                default: candidate = new IdentityTransform(dimension); break;
+            }
+            if (dimension < IDENTITIES.length) {
+                IDENTITIES[dimension] = candidate;
+            }
+        }
+        return candidate;
+    }
+
+    /**
+     * Returns {@code true} since this transform does not move any points.
+     */
+    @Override
+    public boolean isIdentity() {
+        return true;
+    }
+
+    /**
+     * Gets the dimension of input points.
+     */
+    @Override
+    public int getSourceDimensions() {
+        return dimension;
+    }
+
+    /**
+     * Gets the dimension of output points.
+     */
+    @Override
+    public int getTargetDimensions() {
+        return dimension;
+    }
+
+    /**
+     * Returns the parameter descriptors for this math transform.
+     */
+    @Override
+    public ParameterDescriptorGroup getParameterDescriptors() {
+        return Affine.PARAMETERS;
+    }
+
+    /**
+     * Returns the matrix elements as a group of parameters values.
+     *
+     * @return A copy of the parameter values for this math transform.
+     */
+    @Override
+    public ParameterValueGroup getParameterValues() {
+        return ProjectiveTransform.getParameterValues(getMatrix());
+    }
+
+    /**
+     * Returns a copy of the identity matrix.
+     */
+    @Override
+    public Matrix getMatrix() {
+        return Matrices.createIdentity(dimension + 1);
+    }
+
+    /**
+     * Gets the derivative of this transform at a point. For an identity transform,
+     * the derivative is the same everywhere.
+     */
+    @Override
+    public Matrix derivative(final DirectPosition point) {
+        return Matrices.createIdentity(dimension);
+    }
+
+    /**
+     * Copies the values from {@code ptSrc} to {@code ptDst}.
+     * Overrides the super-class method for performance reason.
+     */
+    @Override
+    public DirectPosition transform(final DirectPosition ptSrc, final DirectPosition ptDst) {
+        ArgumentChecks.ensureDimensionMatches("ptSrc", dimension, ptSrc);
+        if (ptDst == null) {
+            return new GeneralDirectPosition(ptSrc);
+        }
+        ArgumentChecks.ensureDimensionMatches("ptDst", dimension, ptDst);
+        for (int i=0; i<dimension; i++) {
+            ptDst.setOrdinate(i, ptSrc.getOrdinate(i));
+        }
+        return ptDst;
+    }
+
+    /**
+     * Transforms a single coordinate in a list of ordinal values,
+     * and optionally returns the derivative at that location.
+     */
+    @Override
+    public Matrix transform(final double[] srcPts, final int srcOff,
+                            final double[] dstPts, final int dstOff,
+                            final boolean derivate)
+    {
+        if (dstPts != null) {
+            System.arraycopy(srcPts, srcOff, dstPts, dstOff, dimension);
+        }
+        return derivate ? derivative((DirectPosition) null) : null;
+    }
+
+    /**
+     * Transforms many coordinates in a list of ordinal values.
+     */
+    @Override
+    public void transform(final double[] srcPts, int srcOff,
+                          final double[] dstPts, int dstOff, int numPts)
+    {
+        System.arraycopy(srcPts, srcOff, dstPts, dstOff, numPts * dimension);
+    }
+
+    /**
+     * Transforms many coordinates in a list of ordinal values.
+     */
+    @Override
+    public void transform(final float[] srcPts, int srcOff,
+                          final float[] dstPts, int dstOff, int numPts)
+    {
+        System.arraycopy(srcPts, srcOff, dstPts, dstOff, numPts * dimension);
+    }
+
+    /**
+     * Transforms many coordinates in a list of ordinal values.
+     */
+    @Override
+    public void transform(final double[] srcPts, int srcOff,
+                          final float [] dstPts, int dstOff, int numPts)
+    {
+        numPts *= dimension;
+        while (--numPts >= 0) {
+            dstPts[dstOff++] = (float) srcPts[srcOff++];
+        }
+    }
+
+    /**
+     * Transforms many coordinates in a list of ordinal values.
+     */
+    @Override
+    public void transform(final float [] srcPts, int srcOff,
+                          final double[] dstPts, int dstOff, int numPts)
+    {
+        numPts *= dimension;
+        while (--numPts >= 0) {
+            dstPts[dstOff++] = srcPts[srcOff++];
+        }
+    }
+
+    /**
+     * Returns the inverse transform of this object, which is this transform itself
+     */
+    @Override
+    public MathTransform inverse() {
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean equals(final Object object, final ComparisonMode mode) {
+        if (object == this) { // Slight optimization
+            return true;
+        }
+        if (mode != ComparisonMode.STRICT) {
+            return equals(this, object, mode);
+        }
+        if (super.equals(object, mode)) {
+            final IdentityTransform that = (IdentityTransform) object;
+            return this.dimension == that.dimension;
+        }
+        return false;
+    }
+}

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

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

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/IdentityTransform1D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/IdentityTransform1D.java?rev=1600540&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/IdentityTransform1D.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/IdentityTransform1D.java [UTF-8] Wed Jun  4 23:34:38 2014
@@ -0,0 +1,98 @@
+/*
+ * 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;
+
+
+/**
+ * A one dimensional, identity transform. Output values are identical to input values.
+ * This class is a special case of {@link LinearTransform1D} optimized for speed.
+ *
+ * @author  Martin Desruisseaux (IRD, Geomatys)
+ * @since   0.5 (derived from geotk-2.0)
+ * @version 0.5
+ * @module
+ */
+final class IdentityTransform1D extends LinearTransform1D {
+    /**
+     * Serial number for inter-operability with different versions.
+     */
+    private static final long serialVersionUID = -7378774584053573789L;
+
+    /**
+     * The unique instance.
+     */
+    public static final LinearTransform1D INSTANCE = new IdentityTransform1D();
+
+    /**
+     * Constructs a new identity transform.
+     */
+    private IdentityTransform1D() {
+        super(1, 0);
+    }
+
+    /**
+     * Transforms the specified value.
+     */
+    @Override
+    public double transform(final double value) {
+        return value;
+    }
+
+    /**
+     * Transforms many coordinates in a list of ordinal values.
+     */
+    @Override
+    public void transform(final double[] srcPts, int srcOff,
+                          final double[] dstPts, int dstOff, int numPts)
+    {
+        System.arraycopy(srcPts, srcOff, dstPts, dstOff, numPts);
+    }
+
+    /**
+     * Transforms many coordinates in a list of ordinal values.
+     */
+    @Override
+    public void transform(final float[] srcPts, int srcOff,
+                          final float[] dstPts, int dstOff, int numPts)
+    {
+        System.arraycopy(srcPts, srcOff, dstPts, dstOff, numPts);
+    }
+
+    /**
+     * Transforms many coordinates in a list of ordinal values.
+     */
+    @Override
+    public void transform(final double[] srcPts, int srcOff,
+                          final float [] dstPts, int dstOff, int numPts)
+    {
+        while (--numPts >= 0) {
+            dstPts[dstOff++] = (float) srcPts[srcOff++];
+        }
+    }
+
+    /**
+     * Transforms many coordinates in a list of ordinal values.
+     */
+    @Override
+    public void transform(final float [] srcPts, int srcOff,
+                          final double[] dstPts, int dstOff, int numPts)
+    {
+        while (--numPts >= 0) {
+            dstPts[dstOff++] = srcPts[srcOff++];
+        }
+    }
+}

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

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

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/LinearTransform1D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/LinearTransform1D.java?rev=1600540&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/LinearTransform1D.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/LinearTransform1D.java [UTF-8] Wed Jun  4 23:34:38 2014
@@ -0,0 +1,316 @@
+/*
+ * 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.io.Serializable;
+import org.opengis.geometry.DirectPosition;
+import org.opengis.parameter.ParameterValueGroup;
+import org.opengis.parameter.ParameterDescriptorGroup;
+import org.opengis.referencing.operation.Matrix;
+import org.opengis.referencing.operation.MathTransform1D;
+import org.opengis.referencing.operation.TransformException;
+import org.opengis.referencing.operation.NoninvertibleTransformException;
+import org.apache.sis.referencing.operation.matrix.Matrix1;
+import org.apache.sis.referencing.operation.matrix.Matrix2;
+import org.apache.sis.referencing.operation.provider.Affine;
+import org.apache.sis.internal.util.Numerics;
+import org.apache.sis.util.ComparisonMode;
+
+// We really want to use doubleToRawLongBits, not doubleToLongBits, because the
+// coverage module needs the raw bits for differentiating various NaN values.
+import static java.lang.Double.doubleToRawLongBits;
+
+
+/**
+ * A one dimensional, linear transform.
+ * Input values <var>x</var> are converted into output values <var>y</var> using the following equation:
+ *
+ * <blockquote><var>y</var>  =  <var>x</var> × {@linkplain #scale} + {@linkplain #offset}</blockquote>
+ *
+ * This class is the same as a 2×2 affine transform. However, this specialized {@code LinearTransform1D} class
+ * is faster. This kind of transform is extensively used by {@link org.apache.sis.coverage.grid.GridCoverage2D}.
+ *
+ * @author  Martin Desruisseaux (IRD, Geomatys)
+ * @since   0.5 (derived from geotk-2.0)
+ * @version 0.5
+ * @module
+ *
+ * @see LogarithmicTransform1D
+ * @see ExponentialTransform1D
+ */
+class LinearTransform1D extends AbstractMathTransform1D implements LinearTransform, Serializable {
+    /**
+     * Serial number for inter-operability with different versions.
+     */
+    private static final long serialVersionUID = -7595037195668813000L;
+
+    /**
+     * The value which is multiplied to input values.
+     */
+    final double scale;
+
+    /**
+     * The value to add to input values.
+     */
+    final double offset;
+
+    /**
+     * The inverse of this transform. Created only when first needed.
+     */
+    private transient MathTransform1D inverse;
+
+    /**
+     * Constructs a new linear transform. This constructor is provided for subclasses only.
+     * Instances should be created using the {@linkplain #create(double, double) factory method},
+     * which may returns optimized implementations for some particular argument values.
+     *
+     * @param scale  The {@code scale}  term in the linear equation.
+     * @param offset The {@code offset} term in the linear equation.
+     *
+     * @see #create(double, double)
+     */
+    protected LinearTransform1D(final double scale, final double offset) {
+        this.scale  = scale;
+        this.offset = offset;
+    }
+
+    /**
+     * Constructs a new linear transform.
+     *
+     * @param  scale  The {@code scale}  term in the linear equation.
+     * @param  offset The {@code offset} term in the linear equation.
+     * @return The linear transform for the given scale and offset.
+     *
+     * @see MathTransforms#linear(double, double)
+     */
+    public static LinearTransform1D create(final double scale, final double offset) {
+        if (offset == 0 && scale == 1) {
+            return IdentityTransform1D.INSTANCE;
+        }
+        if (scale == 0) {
+            return new ConstantTransform1D(offset);
+        }
+        return new LinearTransform1D(scale, offset);
+    }
+
+    /**
+     * Returns the parameter descriptors for this math transform.
+     */
+    @Override
+    public ParameterDescriptorGroup getParameterDescriptors() {
+        return Affine.PARAMETERS;
+    }
+
+    /**
+     * Returns the matrix elements as a group of parameters values. The number of parameters
+     * depends on the matrix size. Only matrix elements different from their default value
+     * will be included in this group.
+     *
+     * @return A copy of the parameter values for this math transform.
+     */
+    @Override
+    public ParameterValueGroup getParameterValues() {
+        return ProjectiveTransform.getParameterValues(getMatrix());
+    }
+
+    /**
+     * Returns this transform as an affine transform matrix.
+     */
+    @Override
+    public Matrix getMatrix() {
+        return new Matrix2(scale, offset, 0, 1);
+    }
+
+    /**
+     * Creates the inverse transform of this object.
+     */
+    @Override
+    public MathTransform1D inverse() throws NoninvertibleTransformException {
+        if (inverse == null) {
+            if (isIdentity()) {
+                inverse = this;
+            } else if (scale != 0) {
+                final LinearTransform1D inverse;
+                inverse = create(1/scale, -offset/scale);
+                inverse.inverse = this;
+                this.inverse = inverse;
+            } else {
+                inverse = super.inverse();
+            }
+        }
+        return inverse;
+    }
+
+    /**
+     * Tests whether this transform does not move any points.
+     */
+    @Override
+    public boolean isIdentity() {
+       return offset == 0 && scale == 1;
+    }
+
+    /**
+     * Gets the derivative of this transform at a point.
+     *
+     * @param point Ignored for a linear transform. Can be null.
+     * @return The derivative at the given point.
+     */
+    @Override
+    public Matrix derivative(final DirectPosition point) throws TransformException {
+        return new Matrix1(scale);
+    }
+
+    /**
+     * Gets the derivative of this function at a value.
+     *
+     * @param  value Ignored for a linear transform. Can be {@link Double#NaN NaN}.
+     * @return The derivative at the given point.
+     */
+    @Override
+    public double derivative(final double value) {
+        return scale;
+    }
+
+    /**
+     * Transforms the specified value.
+     */
+    @Override
+    public double transform(double value) {
+        return offset + scale * value;
+    }
+
+    /**
+     * Transforms a single point in the given array and opportunistically computes its derivative
+     * if requested. The default implementation computes all those values from the {@link #scale}
+     * and {@link #offset} coefficients.
+     */
+    @Override
+    public Matrix transform(final double[] srcPts, final int srcOff,
+                            final double[] dstPts, final int dstOff,
+                            final boolean derivate)
+    {
+        if (dstPts != null) {
+            dstPts[dstOff] = offset + scale*srcPts[srcOff];
+        }
+        return derivate ? new Matrix1(scale) : null;
+    }
+
+    /**
+     * Transforms many coordinates in a list of ordinal values. The default implementation
+     * computes the values from the {@link #scale} and {@link #offset} coefficients.
+     */
+    @Override
+    public void transform(final double[] srcPts, int srcOff,
+                          final double[] dstPts, int dstOff, int numPts)
+    {
+        if (srcPts!=dstPts || srcOff>=dstOff) {
+            while (--numPts >= 0) {
+                dstPts[dstOff++] = offset + scale * srcPts[srcOff++];
+            }
+        } else {
+            srcOff += numPts;
+            dstOff += numPts;
+            while (--numPts >= 0) {
+                dstPts[--dstOff] = offset + scale * srcPts[--srcOff];
+            }
+        }
+    }
+
+    /**
+     * Transforms many coordinates in a list of ordinal values. The default implementation
+     * computes the values from the {@link #scale} and {@link #offset} coefficients using
+     * the {@code double} precision, then casts the result to the {@code float} type.
+     */
+    @Override
+    public void transform(final float[] srcPts, int srcOff,
+                          final float[] dstPts, int dstOff, int numPts)
+    {
+        if (srcPts!=dstPts || srcOff>=dstOff) {
+            while (--numPts >= 0) {
+                dstPts[dstOff++] = (float) (offset + scale * srcPts[srcOff++]);
+            }
+        } else {
+            srcOff += numPts;
+            dstOff += numPts;
+            while (--numPts >= 0) {
+                dstPts[--dstOff] = (float) (offset + scale * srcPts[--srcOff]);
+            }
+        }
+    }
+
+    /**
+     * Transforms many coordinates in a list of ordinal values. The default implementation
+     * computes the values from the {@link #scale} and {@link #offset} coefficients using
+     * the {@code double} precision, then casts the result to the {@code float} type.
+     */
+    @Override
+    public void transform(final double[] srcPts, int srcOff,
+                          final float [] dstPts, int dstOff, int numPts)
+    {
+        while (--numPts >= 0) {
+            dstPts[dstOff++] = (float) (offset + scale * srcPts[srcOff++]);
+        }
+    }
+
+    /**
+     * Transforms many coordinates in a list of ordinal values. The default implementation
+     * computes the values from the {@link #scale} and {@link #offset} coefficients.
+     */
+    @Override
+    public void transform(final float [] srcPts, int srcOff,
+                          final double[] dstPts, int dstOff, int numPts)
+    {
+        while (--numPts >= 0) {
+            dstPts[dstOff++] = offset + scale * srcPts[srcOff++];
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected int computeHashCode() {
+        return Numerics.hashCode(doubleToRawLongBits(offset) + 31*doubleToRawLongBits(scale)) ^ super.computeHashCode();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean equals(final Object object, final ComparisonMode mode) {
+        if (object == this) { // Slight optimization
+            return true;
+        }
+        if (mode != ComparisonMode.STRICT) {
+            return equals(this, object, mode);
+        }
+        if (super.equals(object, mode)) {
+            final LinearTransform1D that = (LinearTransform1D) object;
+            return doubleToRawLongBits(this.scale)  == doubleToRawLongBits(that.scale) &&
+                   doubleToRawLongBits(this.offset) == doubleToRawLongBits(that.offset);
+            /*
+             * NOTE: 'LinearTransform1D' and 'ConstantTransform1D' are heavily used by 'Category'
+             * from 'org.apache.sis.coverage' package. It is essential for Cateory to differenciate
+             * various NaN values. Because 'equals' is used by WeakHashSet.unique(Object) (which
+             * is used by 'DefaultMathTransformFactory'), test for equality can't use the non-raw
+             * doubleToLongBits method because it collapse all NaN into a single canonical value.
+             * The 'doubleToRawLongBits' method instead provides the needed functionality.
+             */
+        }
+        return false;
+    }
+}

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

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



Mime
View raw message