blob: bd86e1ca5ac680fd24cd902c6e2688441b44f01d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.sis.referencing.operation.transform;
import org.opengis.referencing.operation.Matrix;
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.apache.sis.referencing.operation.matrix.Matrices;
import org.apache.sis.referencing.operation.matrix.MatrixSIS;
import org.apache.sis.internal.referencing.provider.Affine;
import org.apache.sis.parameter.Parameterized;
// Test imports
import org.opengis.test.Validators;
import org.apache.sis.test.TestRunner;
import org.apache.sis.test.DependsOn;
import org.junit.runner.RunWith;
import org.junit.After;
import org.junit.Test;
import static org.opengis.test.Assert.*;
// Branch-dependent imports
import org.opengis.test.referencing.AffineTransformTest;
/**
* Tests the {@link ProjectiveTransform} class by inheriting the tests defined in GeoAPI conformance module.
* We use the {@link java.awt.geom.AffineTransform} class as a reference, so we need to avoid NaN values.
* Note that {@link CopyTransformTest} will use {@code ProjectiveTransform} as a reference,
* this time with NaN values.
*
* @author Martin Desruisseaux (Geomatys)
* @version 0.7
* @since 0.5
* @module
*/
@RunWith(TestRunner.class)
@DependsOn({AbstractMathTransformTest.class, ScaleTransformTest.class})
public strictfp class ProjectiveTransformTest extends AffineTransformTest {
/**
* For {@link LinearTransformTest} constructor only.
*/
ProjectiveTransformTest(final MathTransformFactory factory) {
super(factory);
}
/**
* Creates a new test suite.
*/
public ProjectiveTransformTest() {
super(new MathTransformFactoryBase() {
@Override
public MathTransform createAffineTransform(final Matrix matrix) {
final ProjectiveTransform pt;
if (matrix.getNumRow() == 3 && matrix.getNumCol() == 3) {
pt = new ProjectiveTransform2D(matrix);
} else {
pt = new ProjectiveTransform(matrix);
}
MathTransform tr = pt.optimize();
if (tr != pt) {
/*
* Opportunistically tests ScaledTransform together with ProjectiveTransform.
* We takes ScaledTransform as a reference implementation since it is simpler.
*/
tr = new TransformResultComparator(tr, pt, 0);
}
return tr;
}
});
}
/*
* Inherit all the tests from GeoAPI:
* - testIdentity1D()
* - testIdentity2D()
* - testIdentity3D()
* - testAxisSwapping2D()
* - testSouthOrientated2D()
* - testTranslatation2D()
* - testUniformScale2D()
* - testGenericScale2D()
* - testRotation2D()
* - testGeneral()
* - testDimensionReduction()
*/
/**
* Tests {@link ProjectiveTransform#optimize()}. In particular this method verifies that a non-square matrix
* that looks like diagonal is not confused with a real diagonal matrix.
*
* @throws TransformException if a coordinate conversion failed.
*
* @since 0.7
*/
@Test
public void testOptimize() throws TransformException {
matrix = Matrices.create(5, 4, new double[] {
2, 0, 0, 0,
0, 3, 0, 0,
0, 0, 4, 0,
0, 0, 0, 5,
0, 0, 0, 1
});
transform = new ProjectiveTransform(matrix).optimize();
assertInstanceOf("Non-diagonal matrix shall not be handled by ScaleTransform.", ProjectiveTransform.class, transform);
verifyConsistency(1, 2, 3, -3, -2, -1);
/*
* Remove the "problematic" row. The new transform should now be optimizable.
*/
matrix = ((MatrixSIS) matrix).removeRows(3, 4);
transform = new ProjectiveTransform(matrix).optimize();
assertInstanceOf("Diagonal matrix should be handled by a specialized class.", ScaleTransform.class, transform);
verifyConsistency(1, 2, 3, -3, -2, -1);
}
/**
* {@code true} if {@link #ensureImplementRightInterface()} should skip its check for a transform
* of the given dimension. {@code ProjectiveTransformTest} needs to skip the case for dimension 1
* because there is no {@code ProjectiveTransform1D} class. However {@link LinearTransformTest}
* can check for all dimensions.
*/
boolean skipInterfaceCheckForDimension(final int dimension) {
return dimension == 1;
}
/**
* Executed after every test in order to ensure that the {@linkplain #transform transform}
* implements the {@link MathTransform1D} or {@link MathTransform2D} interface as needed.
* In addition, all Apache SIS classes for linear transforms shall implement
* {@link LinearTransform} and {@link Parameterized} interfaces.
*/
@After
public final void ensureImplementRightInterface() {
if (transform instanceof TransformResultComparator) {
transform = ((TransformResultComparator) transform).tested;
}
/*
* Below is a copy of MathTransformTestCase.validate(), with minor modifications
* due to the fact that this class does not extend MathTransformTestCase.
*/
assertNotNull("The 'transform' field shall be assigned a value.", transform);
Validators.validate(transform);
final int dimension = transform.getSourceDimensions();
if (transform.getTargetDimensions() == dimension && !skipInterfaceCheckForDimension(dimension)) {
assertEquals("MathTransform1D", dimension == 1, (transform instanceof MathTransform1D));
assertEquals("MathTransform2D", dimension == 2, (transform instanceof MathTransform2D));
} else {
assertFalse("MathTransform1D", transform instanceof MathTransform1D);
assertFalse("MathTransform2D", transform instanceof MathTransform2D);
}
assertInstanceOf("Parameterized", Parameterized.class, transform);
/*
* End of MathTransformTestCase.validate(). Remaining is specific to LinearTransform implementations.
*/
assertInstanceOf("Not a LinearTransform.", LinearTransform.class, transform);
final Matrix tm = ((LinearTransform) transform).getMatrix();
assertTrue("The matrix declared by the MathTransform is not equal to the one given at creation time.",
Matrices.equals(matrix, tm, tolerance, false));
assertSame("ParameterDescriptor",
Affine.getProvider(transform.getSourceDimensions(), transform.getTargetDimensions(), true).getParameters(),
((Parameterized) transform).getParameterDescriptors());
}
}