use of org.opengis.referencing.operation.Matrix in project sis by apache.
the class EllipsoidToCentricTransform method tryConcatenate.
/**
* If this transform expects three-dimensional inputs, and if the transform just before this one
* unconditionally sets the height to zero, then replaces this transform by a two-dimensional one.
* The intent is to handle the following sequence of operations defined in the EPSG database:
*
* <ol>
* <li>Inverse of <cite>Geographic 3D to 2D conversion</cite> (EPSG:9659)</li>
* <li><cite>Geographic/geocentric conversions</cite> (EPSG:9602)</li>
* </ol>
*
* Replacing the above sequence by a two-dimensional {@code EllipsoidToCentricTransform} instance
* allow the following optimizations:
*
* <ul>
* <li>Avoid computation of <var>h</var> value.</li>
* <li>Allow use of the more efficient {@link java.awt.geom.AffineTransform} before this transform
* instead than a transform based on a matrix of size 4×3.</li>
* </ul>
*
* @return the combined math transform, or {@code null} if no optimized combined transform is available.
* @throws FactoryException if an error occurred while combining the transforms.
*/
@Override
protected MathTransform tryConcatenate(final boolean applyOtherFirst, final MathTransform other, final MathTransformFactory factory) throws FactoryException {
if (applyOtherFirst && withHeight && other instanceof LinearTransform && other.getSourceDimensions() == 2) {
/*
* Found a 4×3 matrix before this transform. We can reduce to a 3×3 matrix only if the row that we are
* about to drop unconditionnaly set the height to zero (i.e. all coefficients in that row are zero).
*/
Matrix matrix = ((LinearTransform) other).getMatrix();
if (matrix.getElement(2, 0) == 0 && matrix.getElement(2, 1) == 0 && matrix.getElement(2, 2) == 0) {
matrix = MatrixSIS.castOrCopy(matrix).removeRows(2, 3);
final MathTransform tr2D = create2D();
if (factory != null) {
return factory.createConcatenatedTransform(factory.createAffineTransform(matrix), tr2D);
} else {
return ConcatenatedTransform.create(MathTransforms.linear(matrix), tr2D, factory);
}
}
}
return super.tryConcatenate(applyOtherFirst, other, factory);
}
use of org.opengis.referencing.operation.Matrix in project sis by apache.
the class InterpolatedGeocentricTransform method transform.
/**
* Transforms the (λ,φ) or (λ,φ,<var>h</var>) coordinates between two geographic CRS,
* and optionally returns the derivative at that location.
*
* @return {@inheritDoc}
* @throws TransformException if the point can not be transformed or
* if a problem occurred while calculating the derivative.
*/
@Override
public Matrix transform(final double[] srcPts, final int srcOff, final double[] dstPts, final int dstOff, final boolean derivate) throws TransformException {
/*
* Interpolate the geocentric translation (ΔX,ΔY,ΔZ) for the source coordinate (λ,φ).
* The translation that we got is in metres, which we convert into normalized units.
*/
final double[] vector = new double[3];
// In radians
grid.interpolateInCell(// In radians
grid.normalizedToGridX(srcPts[srcOff]), grid.normalizedToGridY(srcPts[srcOff + 1]), vector);
final double tX = vector[0] / semiMajor;
final double tY = vector[1] / semiMajor;
final double tZ = vector[2] / semiMajor;
/*
* Geographic → Geocentric conversion. Result stored in a temporary array
* because we do not check if the target points are two or three dimensional.
*/
final Matrix m1 = ellipsoidToCentric.transform(srcPts, srcOff, vector, 0, derivate);
/*
* Apply the geocentric translation on the geocentric coordinates. If the coordinates were in metres,
* we would have only additions. But since we use normalized units, we also need to convert from the
* normalization relative to the source ellipsoid to normalization relative to the target ellipsoid.
* This is the purpose of the scale factor.
*/
vector[0] = (vector[0] + tX) * scale;
vector[1] = (vector[1] + tY) * scale;
vector[2] = (vector[2] + tZ) * scale;
/*
* Final Geocentric → Geographic conversion, and compute the derivative matrix if the user asked for it.
*/
final Matrix m2 = centricToEllipsoid.transform(vector, 0, dstPts, dstOff, derivate);
if (m1 == null || m2 == null) {
return null;
}
return concatenate(m1, m2);
}
use of org.opengis.referencing.operation.Matrix in project sis by apache.
the class PassThroughTransform method create.
/**
* Creates a transform which passes through a subset of ordinates to another transform.
* This method returns a transform having the following dimensions:
*
* {@preformat java
* Source: firstAffectedOrdinate + subTransform.getSourceDimensions() + numTrailingOrdinates
* Target: firstAffectedOrdinate + subTransform.getTargetDimensions() + numTrailingOrdinates
* }
*
* Affected ordinates will range from {@code firstAffectedOrdinate} inclusive to
* {@code dimTarget - numTrailingOrdinates} exclusive.
*
* @param firstAffectedOrdinate index of the first affected ordinate.
* @param subTransform the sub-transform to apply on modified coordinates.
* @param numTrailingOrdinates number of trailing ordinates to pass through.
* @return a pass-through transform, not necessarily a {@code PassThroughTransform} instance.
*/
public static MathTransform create(final int firstAffectedOrdinate, final MathTransform subTransform, final int numTrailingOrdinates) {
ensureNonNull("subTransform", subTransform);
ensurePositive("firstAffectedOrdinate", firstAffectedOrdinate);
ensurePositive("numTrailingOrdinates", numTrailingOrdinates);
if (firstAffectedOrdinate == 0 && numTrailingOrdinates == 0) {
return subTransform;
}
/*
* Optimizes the "Identity transform" case.
*/
if (subTransform.isIdentity()) {
final int dimension = subTransform.getSourceDimensions();
if (dimension == subTransform.getTargetDimensions()) {
return IdentityTransform.create(firstAffectedOrdinate + dimension + numTrailingOrdinates);
}
}
/*
* Special case for transformation backed by a matrix. Is is possible to use a
* new matrix for such transform, instead of wrapping the sub-transform into a
* PassThroughTransform object. It is faster and easier to concatenate.
*/
Matrix matrix = MathTransforms.getMatrix(subTransform);
if (matrix != null) {
matrix = expand(MatrixSIS.castOrCopy(matrix), firstAffectedOrdinate, numTrailingOrdinates, 1);
return MathTransforms.linear(matrix);
}
/*
* Constructs the general PassThroughTransform object. An optimization is done right in
* the constructor for the case where the sub-transform is already a PassThroughTransform.
*/
int dim = subTransform.getSourceDimensions();
if (subTransform.getTargetDimensions() == dim) {
dim += firstAffectedOrdinate + numTrailingOrdinates;
if (dim == 2) {
return new PassThroughTransform2D(firstAffectedOrdinate, subTransform, numTrailingOrdinates);
}
}
return new PassThroughTransform(firstAffectedOrdinate, subTransform, numTrailingOrdinates);
}
Aggregations