use of org.apache.sis.referencing.operation.matrix.MatrixSIS in project sis by apache.
the class BursaWolfParametersTest method getPositionVectorTransformation.
/**
* Invokes {@link BursaWolfParameters#getPositionVectorTransformation(Date)}
* and compares with our own matrix calculated using double arithmetic.
*/
private static MatrixSIS getPositionVectorTransformation(final BursaWolfParameters p) {
final double S = 1 + p.dS / BursaWolfParameters.PPM;
final double RS = TO_RADIANS * S;
final Matrix4 expected = new Matrix4(S, -p.rZ * RS, +p.rY * RS, p.tX, +p.rZ * RS, S, -p.rX * RS, p.tY, -p.rY * RS, +p.rX * RS, S, p.tZ, 0, 0, 0, 1);
final MatrixSIS matrix = MatrixSIS.castOrCopy(p.getPositionVectorTransformation(null));
assertMatrixEquals("getPositionVectorTransformation", expected, matrix, p.isTranslation() ? 0 : 1E-14);
return matrix;
}
use of org.apache.sis.referencing.operation.matrix.MatrixSIS in project sis by apache.
the class ContextualParameters method denormalizeGeographicOutputs.
/**
* Appends a denormalization step after the non-linear kernel, which will convert input ordinates
* in the two first dimensions from radians to degrees. After this conversion, the denormalization
* can optionally add the given λ₀ value (in degrees) to the longitude.
*
* <p>Invoking this method is equivalent to {@linkplain java.awt.geom.AffineTransform#concatenate concatenating}
* the denormalization matrix with the following matrix. This will have the effect of applying the conversion
* described above after the non-linear kernel operation:</p>
*
* <center>{@include formulas.html#DenormalizeGeographic}</center>
*
* @param λ0 longitude of the central meridian, in degrees.
* @return the denormalization affine transform as a matrix.
* Callers can change that matrix directly if they want to apply additional denormalization operations.
* @throws IllegalStateException if this {@code ContextualParameter} has been made unmodifiable.
*/
public synchronized MatrixSIS denormalizeGeographicOutputs(final double λ0) {
ensureModifiable();
final DoubleDouble toDegrees = DoubleDouble.createRadiansToDegrees();
// Must be the same instance, not a copy.
final MatrixSIS denormalize = (MatrixSIS) this.denormalize;
denormalize.convertAfter(0, toDegrees, (λ0 != 0) ? λ0 : null);
denormalize.convertAfter(1, toDegrees, null);
return denormalize;
}
use of org.apache.sis.referencing.operation.matrix.MatrixSIS in project sis by apache.
the class CopyTransform method inverse.
/**
* Creates the inverse transform of this object.
*/
@Override
// Okay since 'inverse' is volatile.
@SuppressWarnings("DoubleCheckedLocking")
public LinearTransform inverse() throws NoninvertibleTransformException {
LinearTransform inv = inverse;
if (inv == null) {
synchronized (this) {
inv = inverse;
if (inv == null) {
/*
* Note: no need to perform the following check at this point because MathTransforms.linear(…)
* should never instantiate this class in the identity case and because we perform an
* equivalent check later anyway.
*
* if (isIdentity()) {
* inverse = this;
* } else { ... }
*/
final int srcDim = this.srcDim;
final int dstDim = indices.length;
final int[] reverse = new int[srcDim];
Arrays.fill(reverse, -1);
for (int i = dstDim; --i >= 0; ) {
reverse[indices[i]] = i;
}
/*
* Check if there is any unassigned dimension. In such case,
* delegates to the generic ProjectiveTransform with a matrix
* which set the missing values to NaN.
*/
for (int j = srcDim; --j >= 0; ) {
if (reverse[j] < 0) {
final MatrixSIS matrix = Matrices.createZero(srcDim + 1, dstDim + 1);
for (j = 0; j < srcDim; j++) {
// Okay to reuse 'j' since the outer loop will not continue.
final int i = reverse[j];
if (i >= 0) {
matrix.setElement(j, i, 1);
} else {
matrix.setElement(j, dstDim, Double.NaN);
}
}
matrix.setElement(srcDim, dstDim, 1);
inv = MathTransforms.linear(matrix);
if (inv instanceof AbstractLinearTransform) {
((AbstractLinearTransform) inv).inverse = this;
}
inverse = inv;
return inv;
}
}
/*
* At this point, we know that we can create the inverse transform.
* If this transform is the identity transform or an anti-diagonal matrix except last row
* (e.g. matrix used for swapping axis order), then the old and new arrays would be equal.
*/
CopyTransform copyInverse = this;
if (!Arrays.equals(reverse, indices)) {
copyInverse = new CopyTransform(indices.length, reverse);
copyInverse.inverse = this;
}
inverse = inv = copyInverse;
}
}
}
return inv;
}
use of org.apache.sis.referencing.operation.matrix.MatrixSIS in project sis by apache.
the class EllipsoidToCentricTransform method createGeodeticConversion.
/**
* Creates a transform from geographic to geocentric coordinates. This factory method combines the
* {@code EllipsoidToCentricTransform} instance with the steps needed for converting degrees to
* radians and expressing the results in units of the given ellipsoid.
*
* <p>Input coordinates are expected to contain:</p>
* <ol>
* <li>longitudes in <strong>degrees</strong> relative to the prime meridian (usually Greenwich),</li>
* <li>latitudes in <strong>degrees</strong>,</li>
* <li>optionally heights above the ellipsoid, in units of the ellipsoid axis (usually metres).</li>
* </ol>
*
* Output coordinates are as below, in units of the ellipsoid axis (usually metres):
* <ol>
* <li>distance from Earth center on the X axis (toward the intersection of prime meridian and equator),</li>
* <li>distance from Earth center on the Y axis (toward the intersection of 90°E meridian and equator),</li>
* <li>distance from Earth center on the Z axis (toward North pole).</li>
* </ol>
*
* @param factory the factory to use for creating and concatenating the affine transforms.
* @param semiMajor the semi-major axis length.
* @param semiMinor the semi-minor axis length.
* @param unit the unit of measurement for the semi-axes and the ellipsoidal height.
* @param withHeight {@code true} if source geographic coordinates include an ellipsoidal height
* (i.e. are 3-D), or {@code false} if they are only 2-D.
* @param target whether the target coordinate shall be Cartesian or Spherical.
* @return the conversion from geographic to geocentric coordinates.
* @throws FactoryException if an error occurred while creating a transform.
*/
public static MathTransform createGeodeticConversion(final MathTransformFactory factory, final double semiMajor, final double semiMinor, final Unit<Length> unit, final boolean withHeight, final TargetType target) throws FactoryException {
if (Math.abs(semiMajor - semiMinor) <= semiMajor * (Formulas.LINEAR_TOLERANCE / ReferencingServices.AUTHALIC_RADIUS)) {
/*
* If semi-major axis length is almost equal to semi-minor axis length, uses spherical equations instead.
* We need to add the sphere radius to the elevation before to perform spherical to Cartesian conversion.
*/
final MatrixSIS translate = Matrices.createDiagonal(4, withHeight ? 4 : 3);
translate.setElement(2, withHeight ? 3 : 2, semiMajor);
if (!withHeight) {
translate.setElement(3, 2, 1);
}
final MathTransform tr = SphericalToCartesian.INSTANCE.completeTransform(factory);
return factory.createConcatenatedTransform(factory.createAffineTransform(translate), tr);
}
EllipsoidToCentricTransform tr = new EllipsoidToCentricTransform(semiMajor, semiMinor, unit, withHeight, target);
return tr.context.completeTransform(factory, tr);
}
use of org.apache.sis.referencing.operation.matrix.MatrixSIS in project sis by apache.
the class ProjectiveTransform method derivative.
/**
* Gets the derivative of this transform at a point.
* For a matrix transform, the derivative is the same everywhere.
*
* @param point ignored (can be {@code null}).
*/
@Override
public final Matrix derivative(final DirectPosition point) {
final int srcDim = numCol - 1;
final int dstDim = numRow - 1;
final MatrixSIS matrix = Matrices.createZero(dstDim, srcDim);
int mix = 0;
for (int j = 0; j < dstDim; j++) {
for (int i = 0; i < srcDim; i++) {
matrix.setElement(j, i, elt[mix++]);
}
// Skip translation column.
mix++;
}
return matrix;
}
Aggregations