use of org.opengis.referencing.operation.Matrix in project sis by apache.
the class AbstractLinearTransform method equals.
/**
* Compares the specified object with this linear transform for equality.
* This implementation returns {@code true} if the following conditions are meet:
* <ul>
* <li>In {@code STRICT} mode, the objects are of the same class and {@link #equalsSameClass(Object)}
* returns {@code true}.</li>
* <li>In other modes, the matrix are equals or approximatively equals (depending on the mode).</li>
* </ul>
*
* @param object the object to compare with this transform.
* @param mode the strictness level of the comparison. Default to {@link ComparisonMode#STRICT STRICT}.
* @return {@code true} if the given object is considered equals to this math transform.
*/
@Override
public final boolean equals(final Object object, final ComparisonMode mode) {
if (object == this) {
// Slight optimization
return true;
}
if (object == null) {
return false;
}
final boolean isApproximative = mode.isApproximative();
if (!isApproximative && getClass() == object.getClass()) {
if (!equalsSameClass(object)) {
return false;
}
} else if (mode == ComparisonMode.STRICT) {
return false;
} else {
final Matrix m;
if (object instanceof LinearTransform) {
m = ((LinearTransform) object).getMatrix();
} else if (object instanceof Matrix) {
m = (Matrix) object;
} else {
return false;
}
if (!Matrices.equals(this, m, mode)) {
return false;
}
}
/*
* At this point the transforms are considered equal. In theory we would not need to check
* the inverse transforms since if A and B are equal, then A⁻¹ and B⁻¹ should be equal too.
* However in Apache SIS this is not exactly true because computation of inverse transforms
* avoid NaN values in some circumstances. For example the inverse of a 2×3 matrix normally
* sets the "new" dimensions to NaN, but in the particular case where the transform is used
* for a "Geographic 2D to 3D" conversion it will rather set the new dimensions to zero. So
* A⁻¹ and B⁻¹ may differ in their "NaN versus 0" values even if A and B are equal.
*
* Opportunistically, the comparison of inverse transforms in approximative mode also ensures
* that we are below the tolerance threshold not only for this matrix, but for the inverse one
* as well.
*/
if (object instanceof AbstractLinearTransform) {
/*
* If the 'inverse' matrix was not computed in any of the transforms being compared
* (i.e. if 'this.inverse' and 'object.inverse' are both null), then assume that the
* two transforms will compute their inverse in the same way. The intent is to avoid
* to trig the inverse transform computation.
*
* Note that this code requires the 'inverse' fields to be volatile
* (otherwise we would need to synchronize).
*/
if (inverse == ((AbstractLinearTransform) object).inverse) {
return true;
}
}
/*
* Get the matrices of inverse transforms. In the following code 'null' is really the intended
* value for non-invertible matrices because the Matrices.equals(…) methods accept null values,
* so we are okay to ignore NoninvertibleTransformException in this particular case.
*/
Matrix mt = null, mo = null;
try {
mt = inverse().getMatrix();
} catch (NoninvertibleTransformException e) {
// Leave 'mt' to null.
}
try {
if (object instanceof LinearTransform) {
mo = ((LinearTransform) object).inverse().getMatrix();
} else if (object instanceof Matrix) {
mo = Matrices.inverse((Matrix) object);
}
} catch (NoninvertibleTransformException e) {
// Leave 'mo' to null.
}
return Matrices.equals(mt, mo, isApproximative ? Numerics.COMPARISON_THRESHOLD : 0, isApproximative);
}
use of org.opengis.referencing.operation.Matrix in project sis by apache.
the class ConcatenatedTransform method derivative.
/**
* Gets the derivative of this transform at a point.
*
* @param point the coordinate point where to evaluate the derivative.
* @return the derivative at the specified point (never {@code null}).
* @throws TransformException if the derivative can't be evaluated at the specified point.
*/
@Override
public Matrix derivative(final DirectPosition point) throws TransformException {
final Matrix matrix1 = transform1.derivative(point);
final Matrix matrix2 = transform2.derivative(transform1.transform(point, null));
return Matrices.multiply(matrix2, matrix1);
}
use of org.opengis.referencing.operation.Matrix in project sis by apache.
the class ConcatenatedTransform method getPseudoSteps.
/**
* Returns all concatenated transforms, modified with the pre- and post-processing required for WKT formating.
* More specifically, if there is any Apache SIS implementation of Map Projection in the chain, then the
* (<var>normalize</var>, <var>normalized projection</var>, <var>denormalize</var>) tuples are replaced by single
* (<var>projection</var>) elements, which does not need to be instances of {@link MathTransform}.
*/
private List<Object> getPseudoSteps() {
final List<Object> transforms = new ArrayList<>();
getSteps(transforms);
/*
* Pre-process the transforms before to format. Some steps may be merged, or new
* steps may be created. Do not move size() out of the loop, because it may change.
*/
for (int i = 0; i < transforms.size(); i++) {
final Object step = transforms.get(i);
if (step instanceof AbstractMathTransform) {
i = ((AbstractMathTransform) step).beforeFormat(transforms, i, false);
}
}
/*
* Merge consecutive affine transforms. The transforms list should never contain consecutive instances
* of LinearTransform because the ConcatenatedTransform.create(…) method already merged them (this is
* verified by assertions in MathTransforms). However the above loop may have created synthetic affine
* transforms for WKT formatting purpose. Those synthetic affine transforms are actually represented by
* Matrix objects (rather than full MathTransform objects), and two matrices may have been generated
* consecutively.
*/
Matrix after = null;
for (int i = transforms.size(); --i >= 0; ) {
final Object step = transforms.get(i);
if (step instanceof Matrix) {
if (after != null) {
final Matrix merged = Matrices.multiply(after, (Matrix) step);
if (merged.isIdentity()) {
transforms.subList(i, i + 2).clear();
after = null;
} else {
transforms.set(i, MathTransforms.linear(merged));
transforms.remove(i + 1);
after = merged;
}
} else {
after = (Matrix) step;
}
} else {
after = null;
}
}
/*
* Special case for datum shifts. Need to be done only after we processed
* 'beforeFormat(…)' for all objects and concatenated the affine transforms.
*/
GeocentricAffine.asDatumShift(transforms);
return transforms;
}
use of org.opengis.referencing.operation.Matrix in project sis by apache.
the class ConcatenatedTransform method transform.
/**
* Transforms a single coordinate in a list of ordinal values,
* and optionally returns the derivative at that location.
*
* @throws TransformException if {@link #transform1} or {@link #transform2} failed.
*/
@Override
public Matrix transform(final double[] srcPts, final int srcOff, final double[] dstPts, final int dstOff, final boolean derivate) throws TransformException {
assert isValid();
final int bufferDim = transform2.getSourceDimensions();
final int targetDim = transform2.getTargetDimensions();
final double[] buffer;
final int offset;
if (bufferDim > targetDim) {
buffer = new double[bufferDim];
offset = 0;
} else {
buffer = dstPts;
offset = dstOff;
}
if (derivate) {
final Matrix matrix1 = MathTransforms.derivativeAndTransform(transform1, srcPts, srcOff, buffer, offset);
final Matrix matrix2 = MathTransforms.derivativeAndTransform(transform2, buffer, offset, dstPts, dstOff);
return Matrices.multiply(matrix2, matrix1);
} else {
transform1.transform(srcPts, srcOff, buffer, offset, 1);
transform2.transform(buffer, offset, dstPts, dstOff, 1);
return null;
}
}
use of org.opengis.referencing.operation.Matrix in project sis by apache.
the class ConcatenatedTransform1D method derivative.
/**
* Gets the derivative of this function at a value.
*/
@Override
public double derivative(final double value) throws TransformException {
final DirectPosition1D p = new DirectPosition1D(value);
final Matrix m = super.derivative(p);
assert (m.getNumRow() == 1) && (m.getNumCol() == 1);
return m.getElement(0, 0);
}
Aggregations