use of org.opengis.referencing.operation.Matrix in project sis by apache.
the class LinearTransformBuilderTest method testMinimalist1D.
/**
* Tests a very simple case where an exact answer is expected.
*
* @throws FactoryException if the transform can not be created.
*/
@Test
public void testMinimalist1D() throws FactoryException {
final LinearTransformBuilder builder = new LinearTransformBuilder();
final Map<DirectPosition1D, DirectPosition1D> pos = new HashMap<>(4);
assertNull(pos.put(new DirectPosition1D(1), new DirectPosition1D(1)));
assertNull(pos.put(new DirectPosition1D(2), new DirectPosition1D(3)));
builder.setControlPoints(pos);
assertArrayEquals(new double[] { 1 }, builder.getControlPoint(new int[] { 1 }), STRICT);
assertArrayEquals(new double[] { 3 }, builder.getControlPoint(new int[] { 2 }), STRICT);
assertNull(builder.getControlPoint(new int[] { 3 }));
final Matrix m = builder.create(null).getMatrix();
assertEquals("m₀₀", 2, m.getElement(0, 0), STRICT);
assertEquals("m₀₁", -1, m.getElement(0, 1), STRICT);
assertArrayEquals("correlation", new double[] { 1 }, builder.correlation(), STRICT);
}
use of org.opengis.referencing.operation.Matrix in project sis by apache.
the class LinearTransformBuilderTest method test1D.
/**
* Implementation of {@link #testExact1D()} and {@link #testNonExact1D()}.
*
* @param rd the random number generator to use.
* @param numPts the number of points to generate.
* @param addErrors {@code true} for adding a random error in the target points.
* @param scaleTolerance tolerance threshold for floating point comparisons.
*/
private static void test1D(final Random rd, final int numPts, final boolean addErrors, final double scaleTolerance, final double translationTolerance) throws FactoryException {
final double scale = rd.nextDouble() * 30 - 12;
final double offset = rd.nextDouble() * 10 - 4;
final Map<DirectPosition1D, DirectPosition1D> pos = new HashMap<>(numPts);
for (int i = 0; i < numPts; i++) {
final DirectPosition1D src = new DirectPosition1D(rd.nextDouble() * 100 - 50);
final DirectPosition1D tgt = new DirectPosition1D(src.ordinate * scale + offset);
if (addErrors) {
tgt.ordinate += rd.nextDouble() * 10 - 5;
}
assertNull(pos.put(src, tgt));
}
/*
* Create the fitted transform to test.
*/
final LinearTransformBuilder builder = new LinearTransformBuilder();
builder.setControlPoints(pos);
final Matrix m = builder.create(null).getMatrix();
assertEquals("m₀₀", scale, m.getElement(0, 0), scaleTolerance);
assertEquals("m₀₁", offset, m.getElement(0, 1), translationTolerance);
assertEquals("correlation", 1, StrictMath.abs(builder.correlation()[0]), scaleTolerance);
}
use of org.opengis.referencing.operation.Matrix in project sis by apache.
the class CoordinateSystemsTest method testSwapAndScaleAxes3D.
/**
* Tests {@link CoordinateSystems#swapAndScaleAxes(CoordinateSystem, CoordinateSystem)} for (λ,φ,h) ↔ (φ,λ,h).
* This very common conversion is of critical importance to Apache SIS.
*
* @throws IncommensurableException if a conversion between incompatible units was attempted.
*/
@Test
@DependsOnMethod("testSwapAndScaleAxes2D")
public void testSwapAndScaleAxes3D() throws IncommensurableException {
final CoordinateSystem λφh = new DefaultEllipsoidalCS(singletonMap(NAME_KEY, "(λ,φ,h)"), HardCodedAxes.GEODETIC_LONGITUDE, HardCodedAxes.GEODETIC_LATITUDE, HardCodedAxes.ELLIPSOIDAL_HEIGHT);
final CoordinateSystem φλh = new DefaultEllipsoidalCS(singletonMap(NAME_KEY, "(φ,λ,h)"), HardCodedAxes.GEODETIC_LATITUDE, HardCodedAxes.GEODETIC_LONGITUDE, HardCodedAxes.ELLIPSOIDAL_HEIGHT);
final Matrix expected = Matrices.create(4, 4, new double[] { 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 });
assertTrue(swapAndScaleAxes(λφh, λφh).isIdentity());
assertTrue(swapAndScaleAxes(φλh, φλh).isIdentity());
assertMatrixEquals("(λ,φ,h) → (φ,λ,h)", expected, swapAndScaleAxes(λφh, φλh), STRICT);
assertMatrixEquals("(φ,λ,h) → (λ,φ,h)", expected, swapAndScaleAxes(φλh, λφh), STRICT);
}
use of org.opengis.referencing.operation.Matrix in project sis by apache.
the class ContextualParameters method completeTransform.
/**
* Marks this {@code ContextualParameter} as unmodifiable and creates the
* <cite>normalize</cite> → {@code kernel} → <cite>denormalize</cite> transforms chain.
* This method shall be invoked only after the {@linkplain #getMatrix(MatrixRole) (de)normalization}
* matrices have been set to their final values.
*
* <p>The transforms chain created by this method does not include any step for
* {@linkplain org.apache.sis.referencing.cs.CoordinateSystems#swapAndScaleAxes changing axis order}
* or for converting to units other than degrees or metres. Such steps, if desired, should be defined
* outside {@code ContextualParameters}. Efficient concatenation of those steps will happen "under
* the hood".</p>
*
* @param factory the factory to use for creating math transform instances.
* @param kernel the (usually non-linear) kernel.
* This is often a {@link org.apache.sis.referencing.operation.projection.NormalizedProjection}.
* @return the concatenation of <cite>normalize</cite> → <cite>the given kernel</cite> → <cite>denormalize</cite>
* transforms.
* @throws FactoryException if an error occurred while creating a math transform instance.
*
* @see org.apache.sis.referencing.operation.projection.NormalizedProjection#createMapProjection(MathTransformFactory)
*/
public MathTransform completeTransform(final MathTransformFactory factory, final MathTransform kernel) throws FactoryException {
final MathTransform n, d;
synchronized (this) {
if (!isFrozen) {
freeze();
}
/*
* Creates the ConcatenatedTransform, letting the factory returns the cached instance
* if the caller already invoked this method previously (which usually do not happen).
*/
n = factory.createAffineTransform(normalize);
d = factory.createAffineTransform(denormalize);
Matrix m;
if ((m = MathTransforms.getMatrix(n)) != null)
normalize = m;
if ((m = MathTransforms.getMatrix(d)) != null)
denormalize = m;
}
if (kernel == null) {
// Undocumented feature useful for MolodenskyTransform constructor.
return null;
}
/*
* Following call must be outside the synchronized block for avoiding dead-lock. This is because the
* factory typically contains a WeakHashSet, which invoke in turn the 'equals' methods in this class
* (indirectly, through 'kernel' comparison). We need to be outside the synchronized block for having
* the locks taken in same order (WeakHashSet lock before the ContextualParameters lock).
*/
return factory.createConcatenatedTransform(factory.createConcatenatedTransform(n, kernel), d);
}
use of org.opengis.referencing.operation.Matrix in project sis by apache.
the class ZonedGridSystem method transform.
/**
* Converts the specified (λ,φ) coordinate and stores the result in {@code dstPts}.
* In addition, opportunistically computes the projection derivative if {@code derivate} is {@code true}.
* Note that the derivative does not contain zone prefix.
*
* @return the matrix of the projection derivative at the given source position,
* or {@code null} if the {@code derivate} argument is {@code false}.
* @throws TransformException if the coordinate can not be converted.
*/
@Override
public Matrix transform(final double[] srcPts, final int srcOff, final double[] dstPts, final int dstOff, final boolean derivate) throws TransformException {
double λ = srcPts[srcOff] - initialLongitude;
double φ = srcPts[srcOff + 1];
λ -= RANGE * floor(λ / RANGE);
final double zone = floor(λ / zoneWidth);
λ -= (zone * zoneWidth);
dstPts[dstOff] = λ;
dstPts[dstOff + 1] = φ;
final Matrix derivative = projection.transform(dstPts, dstOff, dstPts, dstOff, derivate);
dstPts[dstOff] += (zone + 1) * ZONE_SCALE;
return derivative;
}
Aggregations