sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1654267 - in /sis/branches/JDK8/core: sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/ sis-referencing/src/test/java/org/apache/sis/referencing/operation/builder/ sis-utility/src/main/java/org/apache/sis/math/
Date Fri, 23 Jan 2015 16:55:44 GMT
Author: desruisseaux
Date: Fri Jan 23 16:55:44 2015
New Revision: 1654267

URL: http://svn.apache.org/r1654267
Log:
Added tests.

Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilderTest.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/Plane.java

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java?rev=1654267&r1=1654266&r2=1654267&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java
[UTF-8] Fri Jan 23 16:55:44 2015
@@ -23,8 +23,10 @@ import org.apache.sis.referencing.operat
 import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 import org.apache.sis.referencing.operation.transform.LinearTransform;
 import org.apache.sis.referencing.operation.transform.MathTransforms;
-import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.Classes;
+import org.apache.sis.util.Debug;
 
 
 /**
@@ -47,7 +49,7 @@ import org.apache.sis.util.resources.Err
  */
 public class LinearTransformBuilder {
     /**
-     * The arrays of source ordinate values, for example (x[], y[], z[]).
+     * The arrays of source ordinate values, for example (x[], y[]).
      * This is {@code null} if not yet specified.
      */
     private double[][] sources;
@@ -126,6 +128,11 @@ public class LinearTransformBuilder {
         correlation = null;
     }
 
+    /*
+     * No getters yet because we did not determined what they should return.
+     * Array? Collection? Map<source,target>?
+     */
+
     /**
      * Creates a linear transform approximation from the source points to the target points.
      * This method assumes that source points are precise and all uncertainty is in the target
points.
@@ -153,4 +160,37 @@ public class LinearTransformBuilder {
         matrix.setElement(targetDim, sourceDim, 1);
         return MathTransforms.linear(matrix);
     }
+
+    /**
+     * Returns the correlation coefficients of the last transform created by {@link #create()},
+     * or {@code null} if none. If non-null, the array length is equals to the number of
target
+     * dimensions.
+     *
+     * @return Estimation of correlation coefficients for each target dimension, or {@code
null}.
+     */
+    public double[] correlation() {
+        return (correlation != null) ? correlation.clone() : null;
+    }
+
+    /**
+     * Returns a string representation of this builder for debugging purpose.
+     *
+     * @return A string representation of this builder.
+     */
+    @Debug
+    @Override
+    public String toString() {
+        final StringBuilder buffer = new StringBuilder(Classes.getShortClassName(this)).append('[');
+        if (sources != null) {
+            buffer.append(sources[0].length).append(" points");
+            if (correlation != null) {
+                String separator = ", correlation is ";
+                for (final double c : correlation) {
+                    buffer.append(separator).append((float) c);
+                    separator = ", ";
+                }
+            }
+        }
+        return buffer.append(']').toString();
+    }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilderTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilderTest.java?rev=1654267&r1=1654266&r2=1654267&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilderTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilderTest.java
[UTF-8] Fri Jan 23 16:55:44 2015
@@ -16,8 +16,12 @@
  */
 package org.apache.sis.referencing.operation.builder;
 
+import java.util.Random;
+import java.awt.geom.AffineTransform;
 import org.opengis.referencing.operation.Matrix;
 import org.apache.sis.geometry.DirectPosition2D;
+import org.apache.sis.test.DependsOnMethod;
+import org.apache.sis.test.TestUtilities;
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
@@ -34,10 +38,17 @@ import static org.junit.Assert.*;
  */
 public final strictfp class LinearTransformBuilderTest extends TestCase {
     /**
+     * Tolerance threshold for strict floating point comparisons. This is used when the math
transform has
+     * been built from exactly 3 points, in which case we expect an exact solution without
rounding errors
+     * at the scale of {@code double} type since the implementation use double-double arithmetic.
+     */
+    private static final double STRICT = 0;
+
+    /**
      * Tests a very simple case where an exact answer is expected.
      */
     @Test
-    public void testExact() {
+    public void testMinimalist() {
         final LinearTransformBuilder builder = new LinearTransformBuilder();
         builder.setSourcePoints(
                 new DirectPosition2D(1, 1),
@@ -50,13 +61,100 @@ public final strictfp class LinearTransf
         final Matrix m = builder.create().getMatrix();
 
         // First row (x)
-        assertEquals( 2, m.getElement(0, 0), 0);
-        assertEquals( 0, m.getElement(0, 1), 0);
-        assertEquals( 1, m.getElement(0, 2), 0);
+        assertEquals("m₀₀",  2, m.getElement(0, 0), STRICT);
+        assertEquals("m₀₁",  0, m.getElement(0, 1), STRICT);
+        assertEquals("m₀₂",  1, m.getElement(0, 2), STRICT);
 
         // Second row (y)
-        assertEquals( 0, m.getElement(1, 0), 0);
-        assertEquals( 3, m.getElement(1, 1), 0);
-        assertEquals(-1, m.getElement(1, 2), 0);
+        assertEquals("m₁₀",  0, m.getElement(1, 0), STRICT);
+        assertEquals("m₁₁",  3, m.getElement(1, 1), STRICT);
+        assertEquals("m₁₂", -1, m.getElement(1, 2), STRICT);
+
+        assertArrayEquals("correlation", new double[] {1, 1}, builder.correlation(), STRICT);
+    }
+
+    /**
+     * Tests with a random number of points with an exact solution expected.
+     *
+     * <p><b>Note:</b> this test can pass with a random seed most of the
time. But we fix the seed anyway
+     * because there is always a small probability that truly random points are all colinear,
in which case
+     * the test would fail. Even if the probability is low, we do not take the risk of random
build failures.</p>
+     */
+    @Test
+    @DependsOnMethod("testMinimalist")
+    public void testExact() {
+        final Random rd = TestUtilities.createRandomNumberGenerator(41632405806929L);
+        for (int i=0; i<10; i++) {
+            test(rd, rd.nextInt(900) + 100, false, 1E-14, 1E-12);
+        }
+    }
+
+    /**
+     * Tests with a random number of points and a random errors in target points.
+     *
+     * <p><b>Note:</b> this test can pass with a random seed most of the
time. But we fix the seed anyway
+     * because there is always a small probability that truly random points are all colinear,
or that lot
+     * of errors are in the same directions (thus introducing a larger bias than expected),
in which case
+     * the test would fail. Even if the probability is low, we do not take the risk of such
random build
+     * failures.</p>
+     */
+    @Test
+    @DependsOnMethod("testExact")
+    public void testNonExact() {
+        final Random rd = TestUtilities.createRandomNumberGenerator(270575025643864L);
+        for (int i=0; i<4; i++) {
+            test(rd, rd.nextInt(900) + 100, true, 0.02, 0.5);
+        }
+    }
+
+    /**
+     * Implementation of {@link #testExact()} and {@link #testNonExact()}.
+     *
+     * @param rd        The random number generator to use.
+     * @param numPts    The number of points to generate.
+     * @param addErrors {@code true} for adding a random error in the target points.
+     * @param scaleTolerance Tolerance threshold for floating point comparisons.
+     */
+    private static void test(final Random rd, final int numPts, final boolean addErrors,
+            final double scaleTolerance, final double translationTolerance)
+    {
+        /*
+         * Create an AffineTransform to use as the reference implementation.
+         */
+        final AffineTransform ref = AffineTransform.getRotateInstance(
+                rd.nextDouble() * (2 * Math.PI),    // Rotation angle
+                rd.nextDouble() * 30 - 12,          // Center X
+                rd.nextDouble() * 10 - 8);          // Center Y
+        final DirectPosition2D[] sources = new DirectPosition2D[numPts];
+        final DirectPosition2D[] targets = new DirectPosition2D[numPts];
+        for (int i=0; i<numPts; i++) {
+            final DirectPosition2D src = new DirectPosition2D(rd.nextDouble() * 100 - 50,
rd.nextDouble() * 200 - 75);
+            final DirectPosition2D tgt = new DirectPosition2D();
+            assertSame(tgt, ref.transform(src, tgt));
+            if (addErrors) {
+                tgt.x += rd.nextDouble() * 10 - 5;
+                tgt.y += rd.nextDouble() * 10 - 5;
+            }
+            sources[i] = src;
+            targets[i] = tgt;
+        }
+        /*
+         * Create the fitted transform to test.
+         */
+        final LinearTransformBuilder builder = new LinearTransformBuilder();
+        builder.setSourcePoints(sources);
+        builder.setTargetPoints(targets);
+        final Matrix m = builder.create().getMatrix();
+        /*
+         * Compare the coefficients with the reference implementation.
+         */
+        double r;
+        assertEquals("m₀₀", ref.getScaleX(),     m.getElement(0, 0), scaleTolerance);
+        assertEquals("m₀₁", ref.getShearX(),     m.getElement(0, 1), scaleTolerance);
+        assertEquals("m₀₂", ref.getTranslateX(), m.getElement(0, 2), translationTolerance);
+        assertEquals("m₁₀", ref.getShearY(),     m.getElement(1, 0), scaleTolerance);
+        assertEquals("m₁₁", ref.getScaleY(),     m.getElement(1, 1), scaleTolerance);
+        assertEquals("m₁₂", ref.getTranslateY(), m.getElement(1, 2), translationTolerance);
+        assertArrayEquals("correlation", new double[] {1, 1}, builder.correlation(), scaleTolerance);
     }
 }

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/Plane.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/Plane.java?rev=1654267&r1=1654266&r2=1654267&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/Plane.java [UTF-8]
(original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/Plane.java [UTF-8]
Fri Jan 23 16:55:44 2015
@@ -267,7 +267,7 @@ public class Plane implements Cloneable,
         final double mean_x = sum_x.value / n;
         final double mean_y = sum_y.value / n;
         final double mean_z = sum_z.value / n;
-        final double offset = (this.cx * mean_x + this.cy * mean_y) + this.c; // Offsetted
c - see comment before usage.
+        final double offset = Math.abs((this.cx * mean_x + this.cy * mean_y) + this.c); //
Offsetted c - see comment before usage.
         double sum_ds2 = 0, sum_dz2 = 0, sum_dsz = 0;
         for (final DirectPosition p : points) {
             final double x = (p.getOrdinate(0) - mean_x) * cx.value;



Mime
View raw message