/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2004-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 javax.measure.unit.SI;
import javax.measure.unit.Unit;
import javax.measure.quantity.Length;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.cs.AxisDirection;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.MathTransformFactory;
import org.opengis.referencing.operation.Matrix;
import org.geotools.referencing.crs.DefaultProjectedCRS;
import org.geotools.referencing.cs.AbstractCS;
import org.geotools.referencing.cs.DefaultCartesianCS;
import org.geotools.referencing.cs.DefaultCoordinateSystemAxis;
import org.geotools.referencing.datum.DefaultEllipsoid;
import org.geotools.referencing.operation.matrix.Matrix2;
import org.geotools.referencing.operation.matrix.Matrix3;
import org.geotools.referencing.operation.matrix.GeneralMatrix;
import static org.geotools.referencing.crs.DefaultGeographicCRS.WGS84;
import static org.geotools.referencing.cs.DefaultCartesianCS.PROJECTED;
import static org.opengis.referencing.cs.AxisDirection.*;
import org.junit.*;
import static org.junit.Assert.*;
/**
* Tests some operation steps involved in coordinate operation creation.
*
* @source $URL$
* @version $Id$
* @author Martin Desruisseaux (IRD)
*/
public final class LinearConversionTest {
/**
* Tests matrix inversion and multiplication using {@link Matrix2}.
*/
@Test
public void testMatrix2() {
final Matrix2 m = new Matrix2();
assertTrue(m.isAffine());
assertTrue(m.isIdentity());
final Random random = new Random(8447482612423035360L);
final GeneralMatrix identity = new GeneralMatrix(2);
for (int i=0; i<100; i++) {
m.setElement(0,0, 100*random.nextDouble());
m.setElement(0,1, 100*random.nextDouble());
m.setElement(1,0, 100*random.nextDouble());
m.setElement(1,1, 100*random.nextDouble());
final Matrix2 original = m.clone();
final GeneralMatrix check = new GeneralMatrix(m);
m.invert();
check.invert();
assertTrue(check.equals(m, 1E-9));
m.multiply(original);
assertTrue(identity.equals(m, 1E-9));
}
}
/**
* Tests axis swapping using {@link GeneralMatrix}.
*/
@Test
public void testAxisSwapping() {
AxisDirection[] srcAxis = {NORTH, EAST, UP};
AxisDirection[] dstAxis = {NORTH, EAST, UP};
GeneralMatrix matrix = new GeneralMatrix(srcAxis, dstAxis);
assertTrue(matrix.isAffine ());
assertTrue(matrix.isIdentity());
dstAxis = new AxisDirection[] {WEST, UP, SOUTH};
matrix = new GeneralMatrix(srcAxis, dstAxis);
assertTrue (matrix.isAffine ());
assertFalse(matrix.isIdentity());
assertEquals(new GeneralMatrix(new double[][] {
{ 0,-1, 0, 0},
{ 0, 0, 1, 0},
{-1, 0, 0, 0},
{ 0, 0, 0, 1}
}), matrix);
dstAxis = new AxisDirection[] {DOWN, NORTH};
matrix = new GeneralMatrix(srcAxis, dstAxis);
assertFalse(matrix.isIdentity());
assertEquals(new GeneralMatrix(new double[][] {
{0, 0,-1, 0},
{1, 0, 0, 0},
{0, 0, 0, 1}
}), matrix);
dstAxis = new AxisDirection[] {DOWN, DOWN};
matrix = new GeneralMatrix(srcAxis, dstAxis);
assertFalse(matrix.isIdentity());
assertEquals(new GeneralMatrix(new double[][] {
{0, 0,-1, 0},
{0, 0,-1, 0},
{0, 0, 0, 1}
}), matrix);
dstAxis = new AxisDirection[] {DOWN, GEOCENTRIC_X};
try {
matrix = new GeneralMatrix(srcAxis, dstAxis);
fail();
} catch (IllegalArgumentException exception) {
// This is the expected exception (axis not in source).
}
srcAxis = dstAxis;
dstAxis = new AxisDirection[] {NORTH, EAST, UP, WEST};
try {
matrix = new GeneralMatrix(srcAxis, dstAxis);
fail();
} catch (IllegalArgumentException exception) {
// This is the expected exception (colinear axis).
}
}
/**
* Tests an example similar to the one provided in the
* {@link AbstractCS#testScaleAndSwapAxis} javadoc.
*/
@Test
public void testScaleAndSwapAxis() {
final Unit<Length> cm = SI.CENTI(SI.METER);
final Unit<Length> mm = SI.MILLI(SI.METER);
final AbstractCS cs = new DefaultCartesianCS("Test",
new DefaultCoordinateSystemAxis("y", SOUTH, cm),
new DefaultCoordinateSystemAxis("x", EAST, mm));
Matrix matrix;
matrix = AbstractCS.swapAndScaleAxis(DefaultCartesianCS.GENERIC_2D, cs);
assertEquals(new GeneralMatrix(new double[][] {
{0, -100, 0},
{1000, 0, 0},
{0, 0, 1}
}), matrix);
matrix = AbstractCS.swapAndScaleAxis(DefaultCartesianCS.GENERIC_3D, cs);
assertEquals(new GeneralMatrix(new double[][] {
{0, -100, 0, 0},
{1000, 0, 0, 0},
{0, 0, 0, 1}
}), matrix);
}
/**
* Test the {@link DefaultProjectedCRS#createLinearConversion} method.
* Note: this requires a working {@link MathTransformFactory}.
*
* @throws FactoryException If the conversion can't be created.
*/
@Test
public void testCreateLinearConversion() throws FactoryException {
final double EPS = 1E-12;
final MathTransformFactory factory = new DefaultMathTransformFactory();
final ParameterValueGroup parameters = factory.getDefaultParameters("Mercator_1SP");
DefaultProjectedCRS sourceCRS, targetCRS;
MathTransform transform;
Matrix conversion;
parameters.parameter("semi_major").setValue(DefaultEllipsoid.WGS84.getSemiMajorAxis());
parameters.parameter("semi_minor").setValue(DefaultEllipsoid.WGS84.getSemiMinorAxis());
transform = factory.createParameterizedTransform(parameters);
sourceCRS = new DefaultProjectedCRS("source", WGS84, transform, PROJECTED);
parameters.parameter("false_easting" ).setValue(1000);
parameters.parameter("false_northing").setValue(2000);
transform = factory.createParameterizedTransform(parameters);
targetCRS = new DefaultProjectedCRS("source", WGS84, transform, PROJECTED);
conversion = ProjectionAnalyzer.createLinearConversion(sourceCRS, targetCRS, EPS);
assertEquals(new Matrix3(
1, 0, 1000,
0, 1, 2000,
0, 0, 1
), conversion);
parameters.parameter("scale_factor").setValue(2);
transform = factory.createParameterizedTransform(parameters);
targetCRS = new DefaultProjectedCRS("source", WGS84, transform, PROJECTED);
conversion = ProjectionAnalyzer.createLinearConversion(sourceCRS, targetCRS, EPS);
assertEquals(new Matrix3(
2, 0, 1000,
0, 2, 2000,
0, 0, 1
), conversion);
parameters.parameter("semi_minor").setValue(DefaultEllipsoid.WGS84.getSemiMajorAxis());
transform = factory.createParameterizedTransform(parameters);
targetCRS = new DefaultProjectedCRS("source", WGS84, transform, PROJECTED);
conversion = ProjectionAnalyzer.createLinearConversion(sourceCRS, targetCRS, EPS);
assertNull(conversion);
}
}