sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1606263 - in /sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis: internal/referencing/ internal/referencing/j2d/ referencing/operation/matrix/ referencing/operation/transform/
Date Fri, 27 Jun 2014 22:55:25 GMT
Author: desruisseaux
Date: Fri Jun 27 22:55:24 2014
New Revision: 1606263

URL: http://svn.apache.org/r1606263
Log:
Store the error terms for double-double arithmetic in AffineTransform2D and ProjectiveTransform.

Added:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ExtendedPrecisionMatrix.java
  (with props)
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/AffineMatrix.java
  (with props)
Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/AffineTransform2D.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform2D.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/ExtendedPrecisionMatrix.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ExtendedPrecisionMatrix.java?rev=1606263&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ExtendedPrecisionMatrix.java
(added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ExtendedPrecisionMatrix.java
[UTF-8] Fri Jun 27 22:55:24 2014
@@ -0,0 +1,43 @@
+/*
+ * 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;
+
+import org.opengis.referencing.operation.Matrix;
+
+
+/**
+ * A matrix capable to store extended precision elements. Apache SIS uses double-double arithmetic
+ * for extended precision, but we want to hide that implementation details from public API.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.5
+ * @version 0.5
+ * @module
+ */
+public interface ExtendedPrecisionMatrix extends Matrix {
+    /**
+     * Returns a copy of all matrix elements, potentially followed by the error terms for
extended-precision arithmetic.
+     * Matrix elements are returned in a flat, row-major (column indices vary fastest) array.
+     *
+     * <p>In <cite>extended precision mode</cite>, the length of this array
is actually twice the normal length.
+     * The first half contains {@link org.apache.sis.internal.util.DoubleDouble#value}, and
the second half contains
+     * the {@link org.apache.sis.internal.util.DoubleDouble#error} for each value in the
first half.</p>
+     *
+     * @return A copy of matrix elements, potentially followed by error terms.
+     */
+    double[] getExtendedElements();
+}

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

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

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/AffineMatrix.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/AffineMatrix.java?rev=1606263&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/AffineMatrix.java
(added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/AffineMatrix.java
[UTF-8] Fri Jun 27 22:55:24 2014
@@ -0,0 +1,160 @@
+/*
+ * 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.util.Arrays;
+import java.io.Serializable;
+import java.awt.geom.AffineTransform;
+import org.opengis.referencing.operation.Matrix;
+import org.apache.sis.internal.referencing.ExtendedPrecisionMatrix;
+import org.apache.sis.referencing.operation.matrix.Matrices;
+import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.resources.Errors;
+
+
+/**
+ * The matrix of an {@link AffineTransform}, optionally with storage for the error terms
+ * used in double-double arithmetic.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.5
+ * @version 0.5
+ * @module
+ */
+final class AffineMatrix implements ExtendedPrecisionMatrix, Serializable, Cloneable {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 1605578645060388327L;
+
+    /**
+     * The transform from which to get the matrix terms.
+     */
+    private final AffineTransform transform;
+
+    /**
+     * The error terms, or {@code null} if none.
+     * If non-null, then the length of this array shall be 6.
+     */
+    private final double[] errors;
+
+    /**
+     * Creates a new matrix wrapping the given transform.
+     *
+     * @param transform The transform to wrap.
+     * @param elements The elements used for creating the matrix (optionally with error terms),
or {@code null}.
+     */
+    AffineMatrix(final AffineTransform transform, final double[] elements) {
+        this.transform = transform;
+        if (elements != null && elements.length >= 15) {
+            errors = Arrays.copyOfRange(elements, 9, 15);
+        } else {
+            errors = null;
+        }
+        assert (elements == null) || Arrays.equals(elements, getExtendedElements());
+    }
+
+    /**
+     * Gets the number of rows in the matrix.
+     */
+    @Override
+    public int getNumRow() {
+        return 3;
+    }
+
+    /**
+     * Gets the number of columns in the matrix.
+     */
+    @Override
+    public int getNumCol() {
+        return 3;
+    }
+
+    /**
+     * Returns {@code true} if the backing affine transform is the identity transform.
+     */
+    @Override
+    public boolean isIdentity() {
+        return transform.isIdentity();
+    }
+
+    /**
+     * Returns all matrix elements.
+     */
+    @Override
+    public double[] getExtendedElements() {
+        final double[] elements = new double[errors != null ? 18 : 9];
+        if (errors != null) {
+            System.arraycopy(errors, 0, elements, 9, 6);
+        }
+        elements[0] = transform.getScaleX();
+        elements[1] = transform.getShearX();
+        elements[2] = transform.getTranslateX();
+        elements[3] = transform.getShearY();
+        elements[4] = transform.getScaleY();
+        elements[5] = transform.getTranslateY();
+        elements[8] = 1;
+        return elements;
+    }
+
+    /**
+     * Returns the matrix element at the given index.
+     */
+    @Override
+    public final double getElement(final int row, final int column) {
+        ArgumentChecks.ensureBetween("row",    0, 3, row);
+        ArgumentChecks.ensureBetween("column", 0, 3, column);
+        switch (row * 3 + column) {
+            case 0: return transform.getScaleX();
+            case 1: return transform.getShearX();
+            case 2: return transform.getTranslateX();
+            case 3: return transform.getShearY();
+            case 4: return transform.getScaleY();
+            case 5: return transform.getTranslateY();
+            case 6: // Fallthrough
+            case 7: return 0;
+            case 8: return 1;
+            default: throw new AssertionError();
+        }
+    }
+
+    /**
+     * Unsupported operation, since this matrix is unmodifiable.
+     */
+    @Override
+    public final void setElement(final int row, final int column, final double value) {
+        throw new UnsupportedOperationException(Errors.format(Errors.Keys.UnmodifiableAffineTransform));
+    }
+
+    /**
+     * Returns a copy of the matrix that user can modify.
+     */
+    @Override
+    public final Matrix clone() {
+        return Matrices.copy(this);
+    }
+
+    /**
+     * Returns a string representation of this matrix.
+     *
+     * @return String representation of this matrix.
+     */
+    @Override
+    public String toString() {
+        return Matrices.toString(this);
+    }
+}

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

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

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/AffineTransform2D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/AffineTransform2D.java?rev=1606263&r1=1606262&r2=1606263&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/AffineTransform2D.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/j2d/AffineTransform2D.java
[UTF-8] Fri Jun 27 22:55:24 2014
@@ -62,18 +62,22 @@ public class AffineTransform2D extends I
     private static final long serialVersionUID = -5299837898367149069L;
 
     /**
-     * The inverse transform. This field will be computed only when needed.
+     * The matrix, or {@code null} if not yet computed.
+     *
+     * <p>This field is also used for determining if the affine transform is mutable.
+     * If this field is {@code null} (which should be a temporary state), then this means
that
+     * this affine transform is still under construction. This field <strong>must</strong>
be
+     * set to a non-null value before an {@link AffineTransform2D} instance is published.</p>
+     *
+     * @see #getMatrix()
+     * @see #freeze()
      */
-    private transient volatile AffineTransform2D inverse;
+    private AffineMatrix matrix;
 
     /**
-     * {@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 an {@link AffineTransform2D} instance is published.
-     *
-     * @see #freeze()
+     * The inverse transform. This field will be computed only when needed.
      */
-    private transient boolean mutable;
+    private transient volatile AffineTransform2D inverse;
 
     /**
      * Constructs a <strong>temporarily mutable</strong> identity affine transform.
@@ -82,7 +86,6 @@ public class AffineTransform2D extends I
      */
     public AffineTransform2D() {
         super();
-        mutable = true;
     }
 
     /**
@@ -94,7 +97,9 @@ public class AffineTransform2D extends I
      */
     public AffineTransform2D(final AffineTransform transform, final boolean mutable) {
         super(transform);
-        this.mutable = mutable;
+        if (!mutable) {
+            freeze();
+        }
     }
 
     /**
@@ -104,9 +109,22 @@ public class AffineTransform2D extends I
      */
     public AffineTransform2D(final AffineTransform transform) {
         super(transform);
-        mutable = true;
         forcePositiveZeros();
-        mutable = false;
+        freeze();
+    }
+
+    /**
+     * Constructs a new {@code AffineTransform2D} from the given 9 or 18 values.
+     *
+     * @param elements The matrix elements, optionally with error terms.
+     */
+    public AffineTransform2D(final double[] elements) {
+        super(pz(elements[0]), pz(elements[3]),
+              pz(elements[1]), pz(elements[4]),
+              pz(elements[2]), pz(elements[5]));
+        matrix = new AffineMatrix(this, elements);
+        assert elements.length == 9 || elements.length == 18;
+        assert elements[6] == 0 && elements[7] == 0 && elements[8] == 1;
     }
 
     /**
@@ -124,6 +142,7 @@ public class AffineTransform2D extends I
      */
     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));
+        freeze();
     }
 
     /**
@@ -150,9 +169,11 @@ public class AffineTransform2D extends I
 
     /**
      * Makes this {@code AffineTransform2D} immutable.
+     * This method shall be invoked exactly once.
      */
     public final void freeze() {
-        mutable = false;
+        assert matrix == null;
+        matrix = new AffineMatrix(this, null);
     }
 
     /**
@@ -163,7 +184,7 @@ public class AffineTransform2D extends I
      */
     @Override
     protected final void checkPermission() throws UnsupportedOperationException {
-        if (!mutable) {
+        if (matrix != null) {
             super.checkPermission();
         }
     }
@@ -261,7 +282,7 @@ public class AffineTransform2D extends I
      */
     @Override
     public final Matrix getMatrix() {
-        return AffineTransforms2D.toMatrix(this);
+        return matrix;
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java?rev=1606263&r1=1606262&r2=1606263&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
[UTF-8] Fri Jun 27 22:55:24 2014
@@ -22,6 +22,7 @@ import org.apache.sis.util.ArgumentCheck
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.internal.util.DoubleDouble;
+import org.apache.sis.internal.referencing.ExtendedPrecisionMatrix;
 
 
 /**
@@ -35,12 +36,12 @@ import org.apache.sis.internal.util.Doub
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4 (derived from geotk-2.2)
- * @version 0.4
+ * @version 0.5
  * @module
  *
  * @see Matrices#createDiagonal(int, int)
  */
-class GeneralMatrix extends MatrixSIS {
+class GeneralMatrix extends MatrixSIS implements ExtendedPrecisionMatrix {
     /**
      * Serial number for inter-operability with different versions.
      */
@@ -132,8 +133,13 @@ class GeneralMatrix extends MatrixSIS {
         ensureValidSize(numRow, numCol);
         this.numRow = (short) numRow;
         this.numCol = (short) numCol;
-        elements = new double[numRow * numCol];
-        getElements(matrix, numRow, numCol, elements);
+        if (matrix instanceof ExtendedPrecisionMatrix) {
+            elements = ((ExtendedPrecisionMatrix) matrix).getExtendedElements();
+            assert (elements.length % (numRow * numCol)) == 0;
+        } else {
+            elements = new double[numRow * numCol];
+            getElements(matrix, numRow, numCol, elements);
+        }
     }
 
     /**
@@ -320,6 +326,15 @@ class GeneralMatrix extends MatrixSIS {
     }
 
     /**
+     * Returns a copy of all matrix elements, potentially followed by the error terms for
extended-precision arithmetic.
+     * Matrix elements are returned in a flat, row-major (column indices vary fastest) array.
+     */
+    @Override
+    public final double[] getExtendedElements() {
+        return elements.clone();
+    }
+
+    /**
      * {@inheritDoc}
      */
     @Override

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform2D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform2D.java?rev=1606263&r1=1606262&r2=1606263&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform2D.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform2D.java
[UTF-8] Fri Jun 27 22:55:24 2014
@@ -102,8 +102,15 @@ public abstract class AbstractMathTransf
      */
     @Override
     public Point2D transform(final Point2D ptSrc, final Point2D ptDst) throws TransformException
{
+        return transform(this, ptSrc, ptDst);
+    }
+
+    /**
+     * Implementation of {@link #transform(DirectPosition, DirectPosition)} shared by the
inverse transform.
+     */
+    static Point2D transform(final AbstractMathTransform tr, final Point2D ptSrc, final Point2D
ptDst) throws TransformException {
         final double[] ord = new double[] {ptSrc.getX(), ptSrc.getY()};
-        transform(ord, 0, ord, 0, false);
+        tr.transform(ord, 0, ord, 0, false);
         if (ptDst != null) {
             ptDst.setLocation(ord[0], ord[1]);
             return ptDst;
@@ -284,8 +291,15 @@ public abstract class AbstractMathTransf
      */
     @Override
     public Matrix derivative(final Point2D point) throws TransformException {
+        return derivative(this, point);
+    }
+
+    /**
+     * Implementation of {@link #derivative(DirectPosition)} shared by the inverse transform.
+     */
+    static Matrix derivative(final AbstractMathTransform tr, final Point2D point) throws
TransformException {
         final double[] coordinate = new double[] {point.getX(), point.getY()};
-        final Matrix derivative = transform(coordinate, 0, null, 0, true);
+        final Matrix derivative = tr.transform(coordinate, 0, null, 0, true);
         if (derivative == null) {
             throw new TransformException(Errors.format(Errors.Keys.CanNotComputeDerivative));
         }
@@ -354,14 +368,7 @@ public abstract class AbstractMathTransf
          */
         @Override
         public Point2D transform(final Point2D ptSrc, final Point2D ptDst) throws TransformException
{
-            final double[] ord = new double[] {ptSrc.getX(), ptSrc.getY()};
-            transform(ord, 0, ord, 0, false);
-            if (ptDst != null) {
-                ptDst.setLocation(ord[0], ord[1]);
-                return ptDst;
-            } else {
-                return new Point2D.Double(ord[0], ord[1]);
-            }
+            return AbstractMathTransform2D.transform(this, ptSrc, ptDst);
         }
 
         /**
@@ -397,12 +404,7 @@ public abstract class AbstractMathTransf
          */
         @Override
         public Matrix derivative(final Point2D point) throws TransformException {
-            final double[] coordinate = new double[] {point.getX(), point.getY()};
-            final Matrix derivative = transform(coordinate, 0, null, 0, true);
-            if (derivative == null) {
-                throw new TransformException(Errors.format(Errors.Keys.CanNotComputeDerivative));
-            }
-            return derivative;
+            return AbstractMathTransform2D.derivative(this, point);
         }
 
         /**

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=1606263&r1=1606262&r2=1606263&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] Fri Jun 27 22:55:24 2014
@@ -27,6 +27,7 @@ import org.opengis.referencing.operation
 import org.opengis.referencing.operation.TransformException;
 import org.opengis.referencing.operation.MathTransformFactory;
 import org.apache.sis.internal.referencing.DirectPositionView;
+import org.apache.sis.internal.referencing.ExtendedPrecisionMatrix;
 import org.apache.sis.internal.referencing.j2d.AffineTransform2D;
 import org.apache.sis.referencing.operation.matrix.AffineTransforms2D;
 import org.apache.sis.referencing.operation.matrix.Matrices;
@@ -119,11 +120,19 @@ public final class MathTransforms extend
             }
             if (Matrices.isAffine(matrix)) {
                 switch (sourceDimension) {
-                    case 1: return linear(matrix.getElement(0,0), matrix.getElement(0,1));
-                    case 2: return new AffineTransform2D(
-                            matrix.getElement(0,0), matrix.getElement(1,0),
-                            matrix.getElement(0,1), matrix.getElement(1,1),
-                            matrix.getElement(0,2), matrix.getElement(1,2));
+                    case 1: {
+                        return linear(matrix.getElement(0,0), matrix.getElement(0,1));
+                    }
+                    case 2: {
+                        if (matrix instanceof ExtendedPrecisionMatrix) {
+                            return new AffineTransform2D(((ExtendedPrecisionMatrix) matrix).getExtendedElements());
+                        } else {
+                            return new AffineTransform2D(
+                                    matrix.getElement(0,0), matrix.getElement(1,0),
+                                    matrix.getElement(0,1), matrix.getElement(1,1),
+                                    matrix.getElement(0,2), matrix.getElement(1,2));
+                        }
+                    }
                 }
             } else if (sourceDimension == 2) {
                 return new ProjectiveTransform2D(matrix);

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform.java?rev=1606263&r1=1606262&r2=1606263&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform.java
[UTF-8] Fri Jun 27 22:55:24 2014
@@ -29,6 +29,9 @@ import org.apache.sis.parameter.TensorPa
 import org.apache.sis.referencing.operation.provider.Affine;
 import org.apache.sis.referencing.operation.matrix.Matrices;
 import org.apache.sis.referencing.operation.matrix.MatrixSIS;
+import org.apache.sis.internal.referencing.ExtendedPrecisionMatrix;
+import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.resources.Errors;
 
 
 /**
@@ -46,7 +49,9 @@ import org.apache.sis.referencing.operat
  *
  * @see java.awt.geom.AffineTransform
  */
-class ProjectiveTransform extends AbstractMathTransform implements LinearTransform, Serializable
{
+class ProjectiveTransform extends AbstractMathTransform implements LinearTransform, ExtendedPrecisionMatrix,
+        Serializable // Not Cloneable, despite the clone() method.
+{
     /**
      * Serial number for inter-operability with different versions.
      */
@@ -64,6 +69,9 @@ class ProjectiveTransform extends Abstra
 
     /**
      * Elements of the matrix. Column indices vary fastest.
+     *
+     * <p>This array may have twice the normal length ({@link #numRow} × {@link #numCol}),
+     * in which case the second half contains the error terms in double-double arithmetic.</p>
      */
     private final double[] elt;
 
@@ -83,11 +91,16 @@ class ProjectiveTransform extends Abstra
     protected ProjectiveTransform(final Matrix matrix) {
         numRow = matrix.getNumRow();
         numCol = matrix.getNumCol();
-        elt = new double[numRow * numCol];
-        int mix = 0;
-        for (int j=0; j<numRow; j++) {
-            for (int i=0; i<numCol; i++) {
-                elt[mix++] = matrix.getElement(j,i);
+        if (matrix instanceof ExtendedPrecisionMatrix) {
+            elt = ((ExtendedPrecisionMatrix) matrix).getExtendedElements();
+            assert (elt.length % (numRow * numCol)) == 0;
+        } else {
+            elt = new double[numRow * numCol];
+            int mix = 0;
+            for (int j=0; j<numRow; j++) {
+                for (int i=0; i<numCol; i++) {
+                    elt[mix++] = matrix.getElement(j,i);
+                }
             }
         }
     }
@@ -109,27 +122,19 @@ class ProjectiveTransform extends Abstra
     }
 
     /**
-     * Tests whether this transform does not move any points.
-     *
-     * <span class="note"><b>Note:</b> this method should always returns
{@code false}, since
-     * {@code MathTransforms.linear(…)} should have created specialized implementations
for identity cases.
-     * Nevertheless we perform the full check as a safety, in case someone instantiated this
class directly
-     * instead than using a factory method.</span>
+     * Gets the number of rows in the matrix.
      */
     @Override
-    public boolean isIdentity() {
-        if (numRow != numCol) {
-            return false;
-        }
-        int mix = 0;
-        for (int j=0; j<numRow; j++) {
-            for (int i=0; i<numCol; i++) {
-                if (elt[mix++] != (i == j ? 1 : 0)) {
-                    return false;
-                }
-            }
-        }
-        return true;
+    public final int getNumRow() {
+        return numRow;
+    }
+
+    /**
+     * Gets the number of columns in the matrix.
+     */
+    @Override
+    public final int getNumCol() {
+        return numCol;
     }
 
     /**
@@ -137,7 +142,7 @@ class ProjectiveTransform extends Abstra
      */
     @Override
     public final Matrix getMatrix() {
-        return Matrices.create(numRow, numCol, elt);
+        return this;
     }
 
     /**
@@ -162,6 +167,64 @@ class ProjectiveTransform extends Abstra
     }
 
     /**
+     * Returns a copy of matrix elements, including error terms if any.
+     */
+    @Override
+    public final double[] getExtendedElements() {
+        return elt.clone();
+    }
+
+    /**
+     * Returns the matrix element at the given index.
+     */
+    @Override
+    public final double getElement(final int row, final int column) {
+        ArgumentChecks.ensureBetween("row",    0, numRow - 1, row);
+        ArgumentChecks.ensureBetween("column", 0, numCol - 1, column);
+        return elt[row * numCol + column];
+    }
+
+    /**
+     * Unsupported operation, since this matrix is unmodifiable.
+     */
+    @Override
+    public final void setElement(final int row, final int column, final double value) {
+        throw new UnsupportedOperationException(Errors.format(Errors.Keys.UnmodifiableAffineTransform));
+    }
+
+    /**
+     * Returns a copy of the matrix that user can modify.
+     */
+    @Override
+    public final Matrix clone() {
+        return Matrices.copy(this);
+    }
+
+    /**
+     * Tests whether this transform does not move any points.
+     *
+     * <span class="note"><b>Note:</b> this method should always returns
{@code false}, since
+     * {@code MathTransforms.linear(…)} should have created specialized implementations
for identity cases.
+     * Nevertheless we perform the full check as a safety, in case someone instantiated this
class directly
+     * instead than using a factory method.</span>
+     */
+    @Override
+    public boolean isIdentity() {
+        if (numRow != numCol) {
+            return false;
+        }
+        int mix = 0;
+        for (int j=0; j<numRow; j++) {
+            for (int i=0; i<numCol; i++) {
+                if (elt[mix++] != (i == j ? 1 : 0)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
      * Converts a single coordinate point in a list of ordinal values,
      * and optionally computes the derivative at that location.
      *
@@ -415,7 +478,7 @@ class ProjectiveTransform extends Abstra
              *           inverse = this;
              *       } else { ... }
              */
-            MatrixSIS matrix = Matrices.create(numRow, numCol, elt);
+            MatrixSIS matrix = Matrices.copy(this);
             matrix = matrix.inverse();
             ProjectiveTransform inv = createInverse(matrix);
             inv.inverse = this;



Mime
View raw message