/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotools.referencing.operation;
import java.util.Random;
import org.opengis.referencing.crs.CRSFactory;
import org.opengis.referencing.datum.DatumFactory;
import org.opengis.referencing.operation.CoordinateOperationFactory;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.MathTransform1D;
import org.opengis.referencing.operation.MathTransform2D;
import org.opengis.referencing.operation.MathTransformFactory;
import org.opengis.referencing.operation.TransformException;
import org.geotools.factory.Hints;
import org.geotools.geometry.DirectPosition2D;
import org.geotools.geometry.GeneralDirectPosition;
import org.geotools.referencing.ReferencingFactoryFinder;
import org.junit.*;
import static org.junit.Assert.*;
/**
* Base class for transform test cases. This class is not a test in itself;
* only subclasses will be.
*
*
* @source $URL$
* @version $Id$
* @author Martin Desruisseaux (IRD)
*/
public abstract class TransformTestBase {
/**
* Small values for comparaisons of floating point numbers after transformations.
*/
private static final double EPS = 1E-6;
/**
* The default datum factory.
*/
protected DatumFactory datumFactory;
/**
* The default coordinate reference system factory.
*/
protected CRSFactory crsFactory;
/**
* The default math transform factory.
*/
protected MathTransformFactory mtFactory;
/**
* The default transformations factory.
*/
protected CoordinateOperationFactory opFactory;
/**
* Random numbers generator.
*/
protected static final Random random = new Random(-3531834320875149028L);
/**
* Setup the factories using the hints provided by {@link #getHintsForTesting}.
*/
@Before
public final void setUpFactories() {
Hints hints = getHintsForTesting();
datumFactory = ReferencingFactoryFinder.getDatumFactory(hints);
crsFactory = ReferencingFactoryFinder.getCRSFactory(hints);
mtFactory = ReferencingFactoryFinder.getMathTransformFactory(hints);
opFactory = ReferencingFactoryFinder.getCoordinateOperationFactory(hints);
}
/**
* Returns the hints to be used by {@link #setUp} in order to fetch the factories.
* The default implementation returns {@code null}. Subclasses can override.
*/
protected Hints getHintsForTesting() {
return null;
}
/**
* Returns <code>true</code> if the specified number is real
* (neither NaN or infinite).
*/
public static boolean isReal(final double value) {
return !Double.isNaN(value) && !Double.isInfinite(value);
}
/**
* Verify that the specified transform implements {@link MathTransform1D}
* or {@link MathTransform2D} as needed.
*
* @param transform The transform to test.
*/
public static void assertInterfaced(final MathTransform transform) {
int dim = transform.getSourceDimensions();
if (transform.getTargetDimensions() != dim) {
dim = 0;
}
assertTrue("MathTransform1D", (dim==1) == (transform instanceof MathTransform1D));
assertTrue("MathTransform2D", (dim==2) == (transform instanceof MathTransform2D));
}
/**
* Transforms a two-dimensional point and compare the result with the expected value.
*
* @param transform The transform to test.
* @param x The x value to transform.
* @param y The y value to transform.
* @param ex The expected x value.
* @param ey The expected y value.
*/
public static void assertTransformEquals2_2(final MathTransform transform,
final double x, final double y,
final double ex, final double ey)
throws TransformException
{
final DirectPosition2D source = new DirectPosition2D(x,y);
final DirectPosition2D target = new DirectPosition2D();
assertSame(target, transform.transform(source, target));
final String message = "Expected ("+ex+", "+ey+"), "+
"transformed=("+target.x+", "+target.y+")";
assertEquals(message, ex, target.x, EPS);
assertEquals(message, ey, target.y, EPS);
}
/**
* Transforms a three-dimensional point and compare the result with the expected value.
*
* @param transform The transform to test.
* @param x The x value to transform.
* @param y The y value to transform.
* @param z The z value to transform.
* @param ex The expected x value.
* @param ey The expected y value.
* @param ez The expected z value.
*/
public static void assertTransformEquals3_3(final MathTransform transform,
final double x, final double y, final double z,
final double ex, final double ey, final double ez)
throws TransformException
{
final GeneralDirectPosition source = new GeneralDirectPosition(x,y,z);
final GeneralDirectPosition target = new GeneralDirectPosition(3);
assertSame(target, transform.transform(source, target));
final String message = "Expected ("+ex+", "+ey+", "+ez+"), "+
"transformed=("+target.ordinates[0]+", "+target.ordinates[1]+", "+target.ordinates[2]+")";
assertEquals(message, ex, target.ordinates[0], EPS);
assertEquals(message, ey, target.ordinates[1], EPS);
assertEquals(message, ez, target.ordinates[2], 1E-2); // Greater tolerance level for Z.
}
/**
* Transforms a two-dimensional point and compare the result with the expected
* three-dimensional value.
*
* @param transform The transform to test.
* @param x The x value to transform.
* @param y The y value to transform.
* @param ex The expected x value.
* @param ey The expected y value.
* @param ez The expected z value.
*/
public static void assertTransformEquals2_3(final MathTransform transform,
final double x, final double y,
final double ex, final double ey, final double ez)
throws TransformException
{
final GeneralDirectPosition source = new GeneralDirectPosition(x,y);
final GeneralDirectPosition target = new GeneralDirectPosition(3);
assertSame(target, transform.transform(source, target));
final String message = "Expected ("+ex+", "+ey+", "+ez+"), "+
"transformed=("+target.ordinates[0]+", "+target.ordinates[1]+", "+target.ordinates[2]+")";
assertEquals(message, ex, target.ordinates[0], EPS);
assertEquals(message, ey, target.ordinates[1], EPS);
assertEquals(message, ez, target.ordinates[2], 1E-2); // Greater tolerance level for Z.
}
/**
* Transforms a three-dimensional point and compare the result with the expected
* two-dimensional value.
*
* @param transform The transform to test.
* @param x The x value to transform.
* @param y The y value to transform.
* @param z The z value to transform.
* @param ex The expected x value.
* @param ey The expected y value.
*/
public static void assertTransformEquals3_2(final MathTransform transform,
final double x, final double y, final double z,
final double ex, final double ey)
throws TransformException
{
final GeneralDirectPosition source = new GeneralDirectPosition(x,y,z);
final GeneralDirectPosition target = new GeneralDirectPosition(2);
assertSame(target, transform.transform(source, target));
final String message = "Expected ("+ex+", "+ey+"), "+
"transformed=("+target.ordinates[0]+", "+target.ordinates[1]+")";
assertEquals(message, ex, target.ordinates[0], EPS);
assertEquals(message, ey, target.ordinates[1], EPS);
}
/**
* Transforms a three-dimensional point and compare the result with the expected
* one-dimensional value.
*
* @param transform The transform to test.
* @param x The x value to transform.
* @param y The y value to transform.
* @param z The z value to transform.
* @param ez The expected z value.
*/
public static void assertTransformEquals3_1(final MathTransform transform,
final double x, final double y, final double z,
final double ez)
throws TransformException
{
final GeneralDirectPosition source = new GeneralDirectPosition(x,y,z);
final GeneralDirectPosition target = new GeneralDirectPosition(1);
assertSame(target, transform.transform(source, target));
final String message = "Expected ("+ez+"), "+
"transformed=("+target.ordinates[0]+")";
assertEquals(message, ez, target.ordinates[0], 1E-2); // Greater tolerance level for Z.
}
/**
* Compare two arrays of points.
*
* @param name The name of the comparaison to be performed.
* @param expected The expected array of points.
* @param actual The actual array of points.
* @param delta The maximal difference tolerated in comparaisons for each dimension.
* This array length must be equal to coordinate dimension (usually 1, 2 or 3).
*/
public static void assertPointsEqual(final String name,
final double[] expected,
final double[] actual,
final double[] delta)
{
final int dimension = delta.length;
final int stop = Math.min(expected.length, actual.length)/dimension * dimension;
assertEquals("Array length for expected points", stop, expected.length);
assertEquals("Array length for actual points", stop, actual.length);
final StringBuilder buffer = new StringBuilder(name);
buffer.append(": point[");
final int start = buffer.length();
for (int i=0; i<stop; i++) {
buffer.setLength(start);
buffer.append(i / dimension).append(", dimension ")
.append(i % dimension).append(" of ")
.append( dimension).append(']');
if (isReal(expected[i])) {
// The "two steps" method in ConcatenatedTransformTest sometime produces
// random NaN numbers. This "two steps" is used only for comparaison purpose;
// the "real" (tested) method work better.
assertEquals(buffer.toString(), expected[i], actual[i], delta[i % dimension]);
}
}
}
/**
* Quick self test, in part to give this test suite a test
* and also to test the internal method.
*/
@Test
public void testAssertPointsEqual(){
String name = "self test";
double a[] = {10, 10 };
double b[] = {10.1, 10.1};
double delta[] = { 0.2, 0.2};
assertPointsEqual(name, a, b, delta);
}
}