Search in sources :

Example 56 with Matrix

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);
}
Also used : NoninvertibleTransformException(org.opengis.referencing.operation.NoninvertibleTransformException) Matrix(org.opengis.referencing.operation.Matrix)

Example 57 with Matrix

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);
}
Also used : Matrix(org.opengis.referencing.operation.Matrix)

Example 58 with Matrix

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;
}
Also used : Matrix(org.opengis.referencing.operation.Matrix) ArrayList(java.util.ArrayList) FormattableObject(org.apache.sis.io.wkt.FormattableObject)

Example 59 with Matrix

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;
    }
}
Also used : Matrix(org.opengis.referencing.operation.Matrix)

Example 60 with Matrix

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);
}
Also used : Matrix(org.opengis.referencing.operation.Matrix) DirectPosition1D(org.apache.sis.geometry.DirectPosition1D)

Aggregations

Matrix (org.opengis.referencing.operation.Matrix)63 Test (org.junit.Test)20 DependsOnMethod (org.apache.sis.test.DependsOnMethod)11 MathTransform (org.opengis.referencing.operation.MathTransform)8 HashMap (java.util.HashMap)6 ParameterValueGroup (org.opengis.parameter.ParameterValueGroup)6 NoninvertibleTransformException (org.opengis.referencing.operation.NoninvertibleTransformException)5 TransformException (org.opengis.referencing.operation.TransformException)5 FormattableObject (org.apache.sis.io.wkt.FormattableObject)4 DirectPosition1D (org.apache.sis.geometry.DirectPosition1D)3 ExtendedPrecisionMatrix (org.apache.sis.internal.referencing.ExtendedPrecisionMatrix)3 Matrix3 (org.apache.sis.referencing.operation.matrix.Matrix3)3 CoordinateSystem (org.opengis.referencing.cs.CoordinateSystem)3 FactoryException (org.opengis.util.FactoryException)3 DirectPosition2D (org.apache.sis.geometry.DirectPosition2D)2 DirectPositionView (org.apache.sis.internal.referencing.DirectPositionView)2 Parameterized (org.apache.sis.parameter.Parameterized)2 MatrixSIS (org.apache.sis.referencing.operation.matrix.MatrixSIS)2 GeneralParameterValue (org.opengis.parameter.GeneralParameterValue)2 ParameterValue (org.opengis.parameter.ParameterValue)2