/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2015, 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.matrix;
import org.junit.Test;
import java.awt.geom.AffineTransform;
import static org.junit.Assert.*;
/**
* Test functionality GeneralMatrix
* Tests {@link org.geotools.referencing.operation.matrix.GeneralMatrix}.
*
*
*
* @source $URL$
* @version $Id$
* @author James Hughes
*/
public class GeneralMatrixTest {
private static double EPSILON_TOLERANCE = 0.000001;
private static double[][] zero2 = new double[][] {
{0.0, 0.0},
{0.0, 0.0}
};
private static double[][] id2 = new double[][] {
{1.0, 0.0},
{0.0, 1.0}
};
private static double[][] id4 = new double[][]{
{1.0, 0.0, 0.0, 0.0},
{0.0, 1.0, 0.0, 0.0},
{0.0, 0.0, 1.0, 0.0},
{0.0, 0.0, 0.0, 1.0}
};
private static double[][] id23 = new double[][] {
{1.0, 0.0, 0.0},
{0.0, 1.0, 0.0}
};
private static double[][] id32 = new double[][] {
{1.0, 0.0},
{0.0, 1.0},
{0.0, 0.0}
};
private static double[][] array1 = new double[][] {
{1.2, -3.4},
{-5.6, 7.8},
{9.0, -1.0}
};
private static double[][] negativeArray1 = new double[][] {
{-1.2, 3.4},
{5.6, -7.8},
{-9.0, 1.0}
};
private static double[] array1flatten = new double[] {
1.2, -3.4, -5.6, 7.8, 9.0, -1.0
};
private static AffineTransform affineTransform = new AffineTransform(1.2, 3.4, 5.6, 7.8, 9.0, 1.0);
private static double[][] affineMatrix = new double[][] {
{1.2, 5.6, 9.0},
{3.4, 7.8, 1.0},
{0.0, 0.0, 1.0}
};
private static double[][] matrix33 = new double[][] {
{1.2, 5.6, 9.0},
{3.4, 7.8, 1.0},
{-2.3, 4.6, 1.0}
};
private static double[][] sub32 = new double[][] {
{1.2, 5.6},
{3.4, 7.8},
{-2.3, 4.6}
};
private static double[][] sub22 = new double[][] {
{1.2, 5.6},
{3.4, 7.8}
};
private static double [][] arrayA = new double[][] {
{2, 6},
{4, 7}
};
private static double [][] arrayAInverse = new double[][] {
{-0.7, 0.6},
{0.4, -0.2}
};
private static GeneralMatrix generalAffineMatrix = new GeneralMatrix(affineMatrix);
private static GeneralMatrix matrix1 = new GeneralMatrix(array1);
AffineTransform2D affineTransform2D = new AffineTransform2D(affineTransform);
@Test
public void constructorTests() {
GeneralMatrix squareId2 = new GeneralMatrix(2);
double[][] array2 = squareId2.getElements();
assertArrayEquals(array2, id2);
GeneralMatrix squareId = new GeneralMatrix(4);
double[][] array = squareId.getElements();
assertArrayEquals(array, id4);
GeneralMatrix squareId23 = new GeneralMatrix(2, 3);
double[][] array23 = squareId23.getElements();
assertArrayEquals(array23, id23);
GeneralMatrix squareId32 = new GeneralMatrix(3, 2);
double[][] array32 = squareId32.getElements();
assertArrayEquals(array32, id32);
GeneralMatrix matrix1 = new GeneralMatrix(3, 2, array1flatten);
double[][] matrix1array = matrix1.getElements();
assertArrayEquals(array1, matrix1array);
GeneralMatrix matrix2 = new GeneralMatrix(array1);
double [][] matrix2array = matrix2.getElements();
assertArrayEquals(array1, matrix2array);
Matrix2 matrix2zero = new Matrix2(0, 0, 0, 0);
GeneralMatrix gm2zero = new GeneralMatrix(matrix2zero);
assertArrayEquals(gm2zero.getElements(), zero2);
matrix2zero.setIdentity();
GeneralMatrix gm2id = new GeneralMatrix(matrix2zero);
assertArrayEquals(gm2id.getElements(), id2);
GeneralMatrix gmsid2 = new GeneralMatrix(squareId2);
double [][] gmsid2array = gmsid2.getElements();
assertArrayEquals(gmsid2array, id2);
GeneralMatrix affineGeneralMatrix = new GeneralMatrix(affineTransform);
double [][] affineMatrixarray = affineGeneralMatrix.getElements();
assertArrayEquals(affineMatrixarray, affineMatrix);
}
@Test
public void getElementsTest() {
double [][] affineTransformElements = GeneralMatrix.getElements(affineTransform2D);
assertArrayEquals(affineTransformElements, affineMatrix);
double [][] generalAffineMatrixElements = GeneralMatrix.getElements(generalAffineMatrix);
assertArrayEquals(generalAffineMatrixElements, affineMatrix);
}
@Test(expected = IllegalStateException.class)
public void affineTest() {
assertTrue(generalAffineMatrix.isAffine());
assertFalse(matrix1.isAffine());
AffineTransform affineTransform1 = generalAffineMatrix.toAffineTransform2D();
assertNotNull(affineTransform1);
//TODO add test for toAffineTransform2d
matrix1.toAffineTransform2D();
}
@Test
public void negateTest() {
GeneralMatrix gm = new GeneralMatrix(array1);
gm.negate();
assertArrayEquals(gm.getElements(), negativeArray1);
gm.negate();
assertArrayEquals(gm.getElements(), array1);
}
@Test
public void invertTest() {
GeneralMatrix gm = new GeneralMatrix(id4);
gm.invert();
GeneralMatrix gm2 = new GeneralMatrix(id4);
GeneralMatrix.epsilonEquals(gm, gm2, EPSILON_TOLERANCE);
GeneralMatrix gma = new GeneralMatrix(arrayA);
gma.invert();
GeneralMatrix gmaInverse = new GeneralMatrix(arrayAInverse);
GeneralMatrix.epsilonEquals(gma, gmaInverse, EPSILON_TOLERANCE);
gma.invert();
GeneralMatrix gma2 = new GeneralMatrix(arrayA);
GeneralMatrix.epsilonEquals(gma, gma2, EPSILON_TOLERANCE);
}
public void invertAccuracyTest(){
// the following is a regression noticed during change to EJML
// OrderedAxisAuthorityFactoryTest relies on DefaultCoordinateOperationFactory checking inverse
// accuracy to 1E-9, previously vecmath accomplished 1E-10
GeneralMatrix matrix = new GeneralMatrix(
new double[][]{
{1.0000000000000002, 0.0, -1.1641532182693481E-10},
{0.0, 1.0000000000000002, 0.0},
{0.0, 0.0, 1.0}});
GeneralMatrix inverse = matrix.clone();
inverse.invert();
matrix.mul( inverse );
GeneralMatrix sourceScale = new GeneralMatrix( new double[][]{
{0.9996, 0.0, 500000.0},
{0.0, 0.9996, 0.0},
{0.0, 0.0, 1.0}});
GeneralMatrix targetScale = new GeneralMatrix( new double[][]{
{0.9996, 0.0, 500000.0},
{0.0, 0.9996, 0.0},
{0.0, 0.0, 1.0}});
sourceScale.invert();
targetScale.multiply(sourceScale);
assertFalse("inverse exact", targetScale.isIdentity());
assertFalse("inverse 1E-10", targetScale.isIdentity(1E-10));
assertTrue("inverse 1E-9", targetScale.isIdentity(1E-9));
}
@Test
public void sizeTests() {
GeneralMatrix gm = new GeneralMatrix(id32);
assertEquals(gm.getNumRow(), 3);
assertEquals(gm.getNumCol(), 2);
}
@Test
public void getSetElementTest() {
GeneralMatrix gm = new GeneralMatrix(id2);
assertEquals(gm.getElement(0, 0), 1.0, EPSILON_TOLERANCE);
double [] newRow = {10.11, 12.23};
gm.setRow(0, newRow);
assertEquals(gm.getElement(0, 0), 10.11, EPSILON_TOLERANCE);
gm.setElement(0, 0, 12.23);
assertEquals(gm.getElement(0, 0), 12.23, EPSILON_TOLERANCE);
gm.setZero();
assertEquals(gm.getElement(0, 0), 0.0, EPSILON_TOLERANCE);
}
@Test
public void identityTest() {
GeneralMatrix id = new GeneralMatrix(id4);
assertTrue(id.isIdentity());
id.setElement(0, 0, 1.0001);
assertFalse(id.isIdentity());
assertTrue(GeneralMatrix.isIdentity(id, 0.01));
id.setIdentity();
assertTrue(id.isIdentity());
}
@Test
public void equalsHashcodeTest() {
GeneralMatrix gm1 = new GeneralMatrix(affineMatrix);
GeneralMatrix gm2 = new GeneralMatrix(affineMatrix);
assertTrue(gm1.equals(gm2));
gm2.setElement(2, 2, gm2.getElement(2, 2) + 0.0001);
assertTrue(gm1.equals(gm2, 0.001));
assertTrue(GeneralMatrix.epsilonEquals(gm1, gm2, 0.001));
assertFalse(gm1.equals(gm2));
}
@Test
public void copySubMatrixTest() {
GeneralMatrix big = new GeneralMatrix(matrix33);
GeneralMatrix m32 = new GeneralMatrix(3, 2);
GeneralMatrix m22 = new GeneralMatrix(2, 2);
GeneralMatrix second = new GeneralMatrix(2, 2);
big.copySubMatrix(0, 0, 3, 2, 0, 0, m32);
assertArrayEquals(m32.getElements(), sub32);
m32.copySubMatrix(0, 0, 2, 2, 0, 0, m22);
assertArrayEquals(m22.getElements(), sub22);
big.copySubMatrix(0, 0, 2, 2, 0, 0, second);
assertTrue(m22.equals(second));
}
}