Author: rmarechal
Date: Tue Apr 19 15:58:49 2016
New Revision: 1739949
URL: http://svn.apache.org/viewvc?rev=1739949&view=rev
Log:
LinearTransformBuilder: add tests
Modified:
sis/branches/ImageDatum/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java
sis/branches/ImageDatum/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilderTest.java
Modified:
sis/branches/ImageDatum/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java
URL:
http://svn.apache.org/viewvc/sis/branches/ImageDatum/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java?rev=1739949&r1=1739948&r2=1739949&view=diff
==============================================================================
---
sis/branches/ImageDatum/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java
[UTF-8] (original)
+++
sis/branches/ImageDatum/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java
[UTF-8] Tue Apr 19 15:58:49 2016
@@ -59,13 +59,28 @@ import org.apache.sis.util.NullArgumentE
*/
public class LinearTransformBuilder {
+ /**
+ * Tolerance use to define if points coordinates are considered as regular
or not.
+ * A coordinate is define as regular if between its value and the integer
troncated
+ * coordinate value is lesser than tolerance.
+ */
private static double COORDS_TOLERANCE = 1E-12;
-
+ /**
+ * Define grid size for each dimension.
+ */
private int[] gridSize;
+ /**
+ * Define number of expected points exprimate by {@link #gridSize}.
+ * @see #getLength(int, int, int[])
+ */
private int gridLength;
+ /**
+ * Define the current index of inserted source and target points.
+ * @see #addNoRegularPoints(double[], double[])
+ */
private int noneRegularPointPosition = 0;
/**
@@ -206,10 +221,12 @@ public class LinearTransformBuilder {
}
/**
+ * Increase the length of the array on the 2nd array dimension.<br>
+ * Stored datas from given array are copied into new array.
*
- * @param array
- * @param newNumberPoints
- * @return
+ * @param array reference array.
+ * @param newNumberPoints new array length.
+ * @return array with increased length.
*/
private static double[][] increasePointLength(final double[][] array,
final int newNumberPoints) {
final double[][] result = new double[array.length][];
@@ -228,7 +245,7 @@ public class LinearTransformBuilder {
* @param sourceCoords coordinates from sources point.
* @return index position into source points array.
* @throws NullArgumentException if <var>sourceCoords</var> is {@code
null}.
- * @throws IllegalArgumentException if <var>sourceCoords</var> do not
contains only intergers values.
+ * @throws IllegalArgumentException if <var>sourceCoords</var> do not
contains only integers values.
*/
private int getRegularArrayPosition(final double... sourceCoords) {
ArgumentChecks.ensureNonNull("sourceCoords", sourceCoords);
@@ -267,8 +284,8 @@ public class LinearTransformBuilder {
/**
* Add couple of points into none regular grid.
*
- * @param sourceCoords
- * @param targetCoords
+ * @param sourceCoords grid point source coordinates.
+ * @param targetCoords target point coordinates.
*/
private void addNoRegularPoints(final double[] sourceCoords, final
double[] targetCoords) {
assert targets != null && targets.length == targetCoords.length;
@@ -440,7 +457,70 @@ public class LinearTransformBuilder {
}
- //------------------------------- public --------------------------------//
+ //-------------------------- package protected
---------------------------//
+
+ /**
+ * Returns {@code true} if this class is considered as valid.
+ * This object is valid if its attributs are consistent into regular grid
+ * mode or consistent into none regular grid mode.
+ * @return {@code true} if all attributs are consistent else {@code false}.
+ */
+ boolean isValid() {
+
+ if (sources == null
+ && targets == null
+ && gridSize == null)
+ return true;
+
+ //-- sources
+ if (sources == null) {
+ if (gridSize == null)
+ throw new AssertionError("Impossible to have null sources
points and grid size not defined.");
+ if (noneRegularPointPosition != 0)
+ throw new AssertionError("With grid define as regular
noneRegularPointPosition attribut should be 0. Found :
"+noneRegularPointPosition);
+ if (gridLength == 0)
+ throw new AssertionError("With grid define as regular
gridLength should be equals to gridsize length. "
+ + "Expected : "+getLength(0, gridSize.length,
gridSize)+", found : "+gridLength);
+ } else {
+ if (gridSize != null)
+ throw new AssertionError("Impossible to have defined sources
points and grid size defined.");
+ if (gridLength != 0)
+ throw new AssertionError("With grid define as none regular
gridLength should be equals to 0. Found : "+gridLength);
+ if (targets == null)
+ throw new AssertionError("Target points should never be null");
+ if (targets[0].length != sources[0].length)
+ throw new AssertionError("With grid defined as none regular,
sources points and targets points "
+ + "should own same points number. Sources points
length : "+sources[0].length+", targets points length : "+targets[0].length);
+ if (sources[0].length != noneRegularPointPosition)
+ throw new AssertionError("With grid define as none regular
sources points length and noneRegularPointPosition should be equals. "
+ + "Sources points length : "+sources[0].length+",
noneRegularPointPosition : "+noneRegularPointPosition);
+ }
+
+ //-- targets
+ if (targets != null) {
+ if (sources == null) {
+ if (gridSize != null) {
+ if (gridLength != targets[0].length)
+ throw new AssertionError("Target number points do not
match with expected stipulate regular grid size."
+ + " Grid size :
("+Arrays.toString(gridSize)+"), expected target points numbers : "
+ +gridLength+", target points found :
"+targets[0].length);
+ } else {
+ throw new AssertionError("Only targets points are defined,
please set grid size or set source points.");
+ }
+ } else {
+ if (sources[0].length != targets[0].length)
+ throw new AssertionError("Target number points do not
match with expected sources number points."
+ + " Sources points number found :
"+sources[0].length+", target points number found : "+targets[0].length);
+ if (gridSize != null)
+ throw new AssertionError("With grid define as none regular
gridSize should be null. Found : "+Arrays.toString(gridSize));
+ if (gridLength != 0)
+ throw new AssertionError("With grid define as none regular
gridLength should be equals to 0. Found : "+gridLength);
+ }
+ }
+ return true;
+ }
+
+ //------------------------------- public
---------------------------------//
/**
* Set all source and target points from an array which contain all of
them.
@@ -478,8 +558,8 @@ public class LinearTransformBuilder {
final int tiePointLength, final double[]
tiePoints)
{
ArgumentChecks.ensurePositive("sourceOffset", sourceOffset);
- ArgumentChecks.ensurePositive("sourceDimension", sourceDimension);
- ArgumentChecks.ensurePositive("targetOffset", targetOffset);
+ ArgumentChecks.ensureStrictlyPositive("sourceDimension",
sourceDimension);
+ ArgumentChecks.ensureStrictlyPositive("targetOffset", targetOffset);
ArgumentChecks.ensureStrictlyPositive("targetdimension",
targetdimension);
ArgumentChecks.ensureStrictlyPositive("tiePointLength",
tiePointLength);
ArgumentChecks.ensureNonNull("tiePoints", tiePoints);
@@ -489,26 +569,48 @@ public class LinearTransformBuilder {
throw new IllegalArgumentException("tiePoint array should have
array length multiple of tiePointLenth."
+ " Array length : "+tiePointsLen+" One point length =
"+tiePointLength);
+ //-- verify source and targets offsets
+ final int min = Math.max(sourceOffset, targetOffset);
+ final int max = Math.min(sourceOffset + sourceDimension, targetOffset
+ targetdimension);
+
+ if (min < max)
+ throw new MismatchedDimensionException("Source offset, dimension
indexes overlaps target offset, dimension indexes."
+ + "Source offset : "+sourceOffset
+ + ", Source dimension : "+sourceDimension
+ + ", Target offset : "+targetOffset
+ + ", Target dimension : "+targetdimension);
+
final int nbTiePoints = tiePointsLen / tiePointLength;
- sources = (sourceDimension > 0) ? new
double[sourceDimension][nbTiePoints] : null;
- targets = new double[targetdimension][nbTiePoints];
- for (int pt = 0; pt < nbTiePoints; pt ++) {
+ if (gridSize == null) {
+ //-- maybe its not efficient
+ if (sources == null)
+ sources = createArray(sourceDimension, nbTiePoints);
+ else
+ sources = increasePointLength(sources, sources[0].length +
nbTiePoints);
+
+ if (targets == null)
+ targets = createArray(targetdimension, nbTiePoints);
+ else
+ targets = increasePointLength(targets, targets[0].length +
nbTiePoints);
+ }
- final int originPt = pt * tiePointLength;
+ final double[] srcPt = new double[sourceDimension];
+ final double[] targetPt = new double[targetdimension];
+
+ for (int pt = 0; pt < nbTiePoints; pt ++) {
+ final int originPt = pt * tiePointLength;
//-- source
final int srcOffset = originPt + sourceOffset;
- for (int srcDim = 0; srcDim < sourceDimension; srcDim++) {
- sources[srcDim][pt] = tiePoints[srcOffset + srcDim];
- }
-
+ System.arraycopy(tiePoints, srcOffset, srcPt, 0, sourceDimension);
//-- target
final int tarOffset = originPt + targetOffset;
- for (int tarDim = 0; tarDim < targetdimension; tarDim++) {
- targets[tarDim][pt] = tiePoints[tarOffset + tarDim];
- }
+ System.arraycopy(tiePoints, tarOffset, targetPt, 0,
targetdimension);
+
+ setPoints(srcPt, targetPt);
}
+ assert isValid();
notifyChanges();
}
@@ -634,13 +736,18 @@ public class LinearTransformBuilder {
* @param points The source points, assumed precise.
* @throws MismatchedDimensionException if at least one point does not
have the expected number of dimensions.
*/
- public void setSourcePoints(final DirectPosition... points) throws
MismatchedDimensionException {
+ public void setSourcePoints(final DirectPosition... points)
+ throws MismatchedDimensionException
+ {
ArgumentChecks.ensureNonNull("points", points);
if (points.length != 0) {
sources = toArrays(points, points[0].getDimension() == 1 ? 1 : 2);
} else {
sources = null;
}
+ //-- when this setter is used, mandatory pass into no regular grid.
+ gridSize = null;
+ gridLength = 0;
noneRegularPointPosition = points.length;
transform = null;
correlation = null;
@@ -654,13 +761,19 @@ public class LinearTransformBuilder {
* @param points The target points, assumed uncertain.
* @throws MismatchedDimensionException if not all points have the same
number of dimensions.
*/
- public void setTargetPoints(final DirectPosition... points) throws
MismatchedDimensionException {
+ public void setTargetPoints(final DirectPosition... points)
+ throws MismatchedDimensionException
+ {
ArgumentChecks.ensureNonNull("points", points);
if (points.length != 0) {
targets = toArrays(points, points[0].getDimension());
} else {
targets = null;
}
+ //-- when this setter is used, mandatory pass into no regular grid.
+ gridSize = null;
+ gridLength = 0;
+ noneRegularPointPosition = points.length;
transform = null;
correlation = null;
}
@@ -678,6 +791,7 @@ public class LinearTransformBuilder {
*/
public LinearTransform create() {
if (transform == null) {
+ isValid();
final double[][] sources = this.sources; // Protect from changes.
final double[][] targets = this.targets;
@@ -719,7 +833,6 @@ public class LinearTransformBuilder {
matrix.setElement(j, 2, plan.z0());
}
}
-
break;
}
default: throw new AssertionError(sourceDim); // Should have
been verified by setSourcePoints(…) method.
Modified:
sis/branches/ImageDatum/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilderTest.java
URL:
http://svn.apache.org/viewvc/sis/branches/ImageDatum/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilderTest.java?rev=1739949&r1=1739948&r2=1739949&view=diff
==============================================================================
---
sis/branches/ImageDatum/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilderTest.java
[UTF-8] (original)
+++
sis/branches/ImageDatum/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/builder/LinearTransformBuilderTest.java
[UTF-8] Tue Apr 19 15:58:49 2016
@@ -18,6 +18,7 @@ package org.apache.sis.referencing.opera
import java.util.Random;
import java.awt.geom.AffineTransform;
+import java.util.Arrays;
import org.opengis.referencing.operation.Matrix;
import org.apache.sis.geometry.DirectPosition1D;
import org.apache.sis.geometry.DirectPosition2D;
@@ -91,8 +92,8 @@ public final strictfp class LinearTransf
}
/**
- * Tests a very simple case where an exact answer is expected.
- * Tolerance threshold is set to zero because the math transform has been
built from exactly 3 points,
+ * Tests a very simple on regular grid, case where an exact answer is
expected.
+ * Tolerance threshold is set to zero because the math transform has been
built from exactly 4 points,
* in which case we expect an exact solution without rounding errors at
the scale of the {@code double}
* type. This is possible because SIS implementation uses double-double
arithmetic.
*/
@@ -110,6 +111,7 @@ public final strictfp class LinearTransf
new
DirectPosition2D(1, 2)};
builder.setPoints(sourcePoints, targetPoints);
+ assertTrue(builder.isValid());
final Matrix m = builder.create().getMatrix();
// First row (x)
@@ -126,6 +128,132 @@ public final strictfp class LinearTransf
}
/**
+ * Test different kind of insertions.
+ */
+ @Test
+ public void testValidity() {
+
+ //-- test insertion in many times
+ final LinearTransformBuilder builder = new LinearTransformBuilder();
+ final DirectPosition2D[] sourcePoints = new DirectPosition2D[]{new
DirectPosition2D(0, 0),
+ new
DirectPosition2D(1, 0),
+ new
DirectPosition2D(1, 1),
+ new
DirectPosition2D(0, 1)};
+
+ final DirectPosition2D[] targetPoints = new DirectPosition2D[]{new
DirectPosition2D(1, -1),
+ new
DirectPosition2D(3, -1),
+ new
DirectPosition2D(3, 2),
+ new
DirectPosition2D(1, 2)};
+
+ builder.setPoints(Arrays.copyOfRange(sourcePoints, 0, 2),
Arrays.copyOfRange(targetPoints, 0, 2));
+ assertTrue(builder.isValid());
+ builder.setPoints(Arrays.copyOfRange(sourcePoints, 2, 4),
Arrays.copyOfRange(targetPoints, 2, 4));
+ assertTrue(builder.isValid());
+
+ final Matrix m = builder.create().getMatrix();
+
+ // First row (x)
+ 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("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);
+
+ //--------------//
+
+
+ //-- Test switch from regular grid to no regular
+ //-- begin insertion with integer coordinates points and switch with
floating coordinates points.
+ final LinearTransformBuilder regBuilder = new
LinearTransformBuilder();
+ final DirectPosition2D[] noRegSourcePoints = new
DirectPosition2D[]{new DirectPosition2D(1+1E-12, 1),
+ new
DirectPosition2D(0, 1+1E-12)};
+
+ //-- set 2 pts as regular grid.
+ regBuilder.setPoints(Arrays.copyOfRange(sourcePoints, 0, 2),
Arrays.copyOfRange(targetPoints, 0, 2));
+ assertTrue(regBuilder.isValid());
+
+ //-- set 2 no regular points and verify that switch between regular to
none regular grid is controled
+ regBuilder.setPoints(noRegSourcePoints,
Arrays.copyOfRange(targetPoints, 2, 4));
+ assertTrue(regBuilder.isValid());
+
+ //--------------//
+
+
+ //-- test insert source points and targets points separately
+ LinearTransformBuilder builderTest = new LinearTransformBuilder();
+ builderTest.setSourcePoints(sourcePoints);
+ builderTest.setTargetPoints(targetPoints);
+ assertTrue(builderTest.isValid());
+
+ //--------------//
+
+ //-- test validity at origin
+ builderTest = new LinearTransformBuilder();
+ assertTrue(builderTest.isValid());
+ }
+
+ /**
+ * Test method {@link LinearTransformBuilder#setModelTiePoints(int, int,
int, int, int, double[]) .
+ */
+ @Test
+ public void setTiePointTest() {
+
+ final double[] points = new double[]{
+ //-- [Empty][x source][y source][Empty][Empty][x dest][y dest]
+ Double.NaN, 0, 0, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY,
1, -1,//-- pt 0
+ Double.NaN, 1, 0, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY,
3, -1,//-- pt 1
+ Double.NaN, 1, 1, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY,
3, 2,//-- pt 2
+ Double.NaN, 0, 1, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY,
1, 2,//-- pt 3
+ };
+
+ //-- No regular
+ LinearTransformBuilder builder = new LinearTransformBuilder();
+
+ builder.setModelTiePoints(1, 2, 5, 2, 7, points);
+ assertTrue(builder.isValid());
+
+ Matrix m = builder.create().getMatrix();
+
+ // First row (x)
+ 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("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);
+
+ //-- regular
+ builder = new LinearTransformBuilder(2, 2);
+
+ builder.setModelTiePoints(1, 2, 5, 2, 7, points);
+ assertTrue(builder.isValid());
+
+ m = builder.create().getMatrix();
+
+ // First row (x)
+ 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("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);
+ }
+
+
+ /**
* Test comportements which should fail.
*/
@Test
@@ -157,52 +285,58 @@ public final strictfp class LinearTransf
//-- do nothing test validate
}
+ final DirectPosition2D[] sourcePoints = new DirectPosition2D[]{new
DirectPosition2D(0, 0),
+ new
DirectPosition2D(1, 0),
+ new
DirectPosition2D(1, 1),
+ new
DirectPosition2D(0, 1)};
+
+ final DirectPosition2D[] targetPoints = new DirectPosition2D[]{new
DirectPosition2D(1, -1),
+ new
DirectPosition2D(3, -1),
+ new
DirectPosition2D(3, 2),
+ new
DirectPosition2D(1, 2)};
+
+
//-- try to build a regular grid with a missing point
try {
final LinearTransformBuilder builder = new
LinearTransformBuilder(2, 2);
- final DirectPosition2D[] sourcePoints = new DirectPosition2D[]{new
DirectPosition2D(0, 0),
-
//--new DirectPosition2D(1, 0), volontary miss a grid point
- new
DirectPosition2D(1, 1),
- new
DirectPosition2D(0, 1)};
-
- final DirectPosition2D[] targetPoints = new DirectPosition2D[]{new
DirectPosition2D(1, -1),
-
//--new DirectPosition2D(3, -1),
- new
DirectPosition2D(3, 2),
- new
DirectPosition2D(1, 2)};
-
- builder.setPoints(sourcePoints, targetPoints);
+ //-- missing one point
+ builder.setPoints(Arrays.copyOfRange(sourcePoints, 0, 3),
Arrays.copyOfRange(targetPoints, 0, 3));
final Matrix m = builder.create().getMatrix();
Assert.fail("Test should thrown an exception it is normaly
impossible to build a transformation with missing grid point.");
} catch (IllegalStateException ex) {
- //-- do nothing
+ //-- test with missing points from expected defined grid.
}
-
-
try {
+ final LinearTransformBuilder builder = new
LinearTransformBuilder();
- } catch (Exception ex) {
-
+ builder.setSourcePoints(Arrays.copyOfRange(sourcePoints, 0, 3));
+ builder.setTargetPoints(targetPoints);
+ final Matrix m = builder.create().getMatrix();
+ Assert.fail("Test should thrown an exception it is normaly
impossible to build a transformation with missing grid point.");
+ } catch (AssertionError ex) {
+ //-- define grid with missing source points.
}
- try {
-
- } catch (Exception ex) {
- }
try {
-
- } catch (Exception ex) {
-
+ //-- test define builder as regular grid and only set targets
points
+ final LinearTransformBuilder builderTest = new
LinearTransformBuilder(2, 2);
+ assertTrue(builderTest.isValid());
+ builderTest.setTargetPoints(targetPoints);
+ builderTest.isValid();
+ } catch (AssertionError ex) {
+ //-- only setted target points + grid is not enought to build
transform
}
- try {
- } catch (Exception ex) {
- }
try {
-
- } catch (Exception ex) {
-
+ //-- test define builder as regular grid and only set targets
points
+ final LinearTransformBuilder builderTest = new
LinearTransformBuilder(2, 2);
+ assertTrue(builderTest.isValid());
+ builderTest.setSourcePoints(sourcePoints);
+ builderTest.isValid();
+ } catch (AssertionError ex) {
+ //-- only setted source points + grid is not enought to build
transform
}
}