use of org.apache.sis.referencing.operation.matrix.Matrix4 in project sis by apache.
the class DefaultConversionTest method testWithInterpolationCRS.
/**
* Tests {@link DefaultConversion#specialize DefaultConversion.specialize(…)} with an interpolation CRS.
* In this test, we invent an imaginary scenario where the longitude rotation to apply varies with time
* (a "moving prime meridian").
*
* <div class="note"><b>Note:</b>
* from some point of view, this scenario is not as weird as it may look like. The Greenwich prime meridian
* was initially the meridian passing through the telescope of the Greenwich observatory. But when a new
* more powerful telescopes was built, is was installed a few metres far from the old one. So if we were
* staying to a strict interpretation like "the meridian passing through the main telescope",
* that meridian would indeed more with time.</div>
*
* @throws FactoryException if an error occurred while creating the conversion.
*/
@Test
@DependsOnMethod("testDefiningConversion")
public void testWithInterpolationCRS() throws FactoryException {
DefaultConversion op = createLongitudeRotation(HardCodedCRS.NTF_NORMALIZED_AXES, createParisCRS(false, HardCodedCS.GEODETIC_2D, true), HardCodedCRS.TIME);
assertMatrixEquals("Longitude rotation of a time-varying CRS", new Matrix4(1, 0, 0, 0, 0, 1, 0, OFFSET, 0, 0, 1, 0, 0, 0, 0, 1), MathTransforms.getMatrix(op.getMathTransform()), STRICT);
op = op.specialize(// In normal use, this would be 'Conversion.class'.
DefaultConversion.class, // Keep the same source CRS.
op.getSourceCRS(), // Swap axis order.
changeCS(op.getTargetCRS(), HardCodedCS.GEODETIC_φλ), DefaultFactories.forBuildin(MathTransformFactory.class));
assertMatrixEquals("Longitude rotation of a time-varying CRS", new Matrix4(1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, OFFSET, 0, 0, 0, 1), MathTransforms.getMatrix(op.getMathTransform()), STRICT);
}
use of org.apache.sis.referencing.operation.matrix.Matrix4 in project sis by apache.
the class DefaultConversionTest method testSpecialize.
/**
* Tests {@link DefaultConversion#specialize DefaultConversion.specialize(…)} with new source and target CRS.
* This test attempts to swap axis order and change the number of dimensions of the <em>target</em> CRS.
*
* <div class="note"><b>Note:</b>
* By contrast, {@link #testDefiningConversion()} tested swapping axis order in the <em>source</em> CRS.</div>
*
* @throws FactoryException if an error occurred while creating the conversion.
*/
@Test
@DependsOnMethod("testDefiningConversion")
public void testSpecialize() throws FactoryException {
final MathTransformFactory factory = DefaultFactories.forBuildin(MathTransformFactory.class);
DefaultConversion op = createLongitudeRotation(createParisCRS(true, HardCodedCS.GEODETIC_3D, false), createParisCRS(false, HardCodedCS.GEODETIC_3D, true), null);
assertMatrixEquals("Longitude rotation of a three-dimensional CRS", new Matrix4(1, 0, 0, OFFSET, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1), MathTransforms.getMatrix(op.getMathTransform()), STRICT);
/*
* When asking for a "specialization" with the same properties,
* we should get the existing instance since no change is needed.
*/
assertSame(op, op.specialize(Conversion.class, op.getSourceCRS(), op.getTargetCRS(), factory));
/*
* Reducing the number of dimensions to 2 and swapping (latitude, longitude) axes.
*/
op = op.specialize(DefaultConversion.class, op.getSourceCRS(), changeCS(op.getTargetCRS(), HardCodedCS.GEODETIC_φλ), factory);
assertMatrixEquals("Longitude rotation of a two-dimensional CRS", Matrices.create(3, 4, new double[] { 0, 1, 0, 0, 1, 0, 0, OFFSET, 0, 0, 0, 1 }), MathTransforms.getMatrix(op.getMathTransform()), STRICT);
}
use of org.apache.sis.referencing.operation.matrix.Matrix4 in project sis by apache.
the class ConcatenatedTransformTest method testPassthrough.
/**
* Tests the concatenation of a 3D affine transform with a pass-through transform.
* The {@link ConcatenatedTransform#create(MathTransform, MathTransform, MathTransformFactory)}
* method should optimize this case.
*
* @throws FactoryException if an error occurred while creating the math transform to test.
*/
@Test
public void testPassthrough() throws FactoryException {
// Any non-linear transform.
final MathTransform kernel = new PseudoTransform(2, 3);
final MathTransform passth = PassThroughTransform.create(0, kernel, 1);
final Matrix4 matrix = new Matrix4();
transform = ConcatenatedTransform.create(MathTransforms.linear(matrix), passth, null);
assertSame("Identity transform should be ignored.", passth, transform);
assertEquals("Source dimensions", 3, transform.getSourceDimensions());
assertEquals("Target dimensions", 4, transform.getTargetDimensions());
/*
* Put scale or offset factors only in the dimension to be processed by the sub-transform.
* The matrix should be concatenated to the sub-transform rather than to the passthrough
* transform.
*/
matrix.m00 = 3;
matrix.m13 = 2;
transform = ConcatenatedTransform.create(MathTransforms.linear(matrix), passth, null);
assertInstanceOf("Expected a new passthrough transform.", PassThroughTransform.class, transform);
final MathTransform subTransform = ((PassThroughTransform) transform).subTransform;
assertInstanceOf("Expected a new concatenated transform.", ConcatenatedTransform.class, subTransform);
assertSame(kernel, ((ConcatenatedTransform) subTransform).transform2);
assertEquals("Source dimensions", 3, transform.getSourceDimensions());
assertEquals("Target dimensions", 4, transform.getTargetDimensions());
/*
* Put scale or offset factors is a passthrough dimension. Now, the affine transform
* can not anymore be concatenated with the sub-transform.
*/
matrix.m22 = 4;
transform = ConcatenatedTransform.create(MathTransforms.linear(matrix), passth, null);
assertInstanceOf("Expected a new concatenated transform.", ConcatenatedTransform.class, transform);
assertSame(passth, ((ConcatenatedTransform) transform).transform2);
assertEquals("Source dimensions", 3, transform.getSourceDimensions());
assertEquals("Target dimensions", 4, transform.getTargetDimensions());
}
use of org.apache.sis.referencing.operation.matrix.Matrix4 in project sis by apache.
the class MathTransformsTest method testGetSteps.
/**
* Tests {@link MathTransforms#getSteps(MathTransform)}.
*/
@Test
public void testGetSteps() {
// Scales a value.
final Matrix4 scale = new Matrix4();
// Swaps two dimensions.
final Matrix4 swap = new Matrix4();
final List<MathTransform> steps = MathTransforms.getSteps(createConcatenateAndPassThrough(scale, swap));
assertEquals(3, steps.size());
assertMatrixEquals("Step 1", scale, MathTransforms.getMatrix(steps.get(0)), STRICT);
assertMatrixEquals("Step 3", swap, MathTransforms.getMatrix(steps.get(2)), STRICT);
assertInstanceOf("Step 2", PassThroughTransform.class, steps.get(1));
}
use of org.apache.sis.referencing.operation.matrix.Matrix4 in project sis by apache.
the class MathTransformContext method getMatrix.
/**
* Returns the normalization or denormalization matrix.
*/
@Override
@SuppressWarnings("fallthrough")
public Matrix getMatrix(final MatrixRole role) throws FactoryException {
final CoordinateSystem cs;
boolean inverse = false;
double rotation;
switch(role) {
default:
throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalArgumentValue_2, "role", role));
// Fall through
case INVERSE_NORMALIZATION:
inverse = true;
case NORMALIZATION:
rotation = sourceMeridian;
cs = getSourceCS();
break;
// Fall through
case INVERSE_DENORMALIZATION:
inverse = true;
case DENORMALIZATION:
inverse = !inverse;
rotation = targetMeridian;
cs = getTargetCS();
break;
}
Matrix matrix = super.getMatrix(role);
if (rotation != 0) {
if (inverse)
rotation = -rotation;
MatrixSIS cm = MatrixSIS.castOrCopy(matrix);
if (cs instanceof CartesianCS) {
rotation = Math.toRadians(rotation);
final Matrix4 rot = new Matrix4();
rot.m00 = rot.m11 = Math.cos(rotation);
rot.m01 = -(rot.m10 = Math.sin(rotation));
if (inverse) {
// Apply the rotation after denormalization.
matrix = Matrices.multiply(rot, cm);
} else {
// Apply the rotation before normalization.
matrix = cm.multiply(rot);
}
} else if (cs == null || cs instanceof EllipsoidalCS || cs instanceof SphericalCS) {
final Double value = rotation;
if (inverse) {
// Longitude is the first axis in normalized CS.
cm.convertBefore(0, null, value);
} else {
cm.convertAfter(0, null, value);
}
matrix = cm;
} else {
throw new FactoryException(Errors.format(Errors.Keys.UnsupportedCoordinateSystem_1, cs.getName()));
}
}
return matrix;
}
Aggregations