use of org.opengis.referencing.operation.NoninvertibleTransformException in project sis by apache.
the class Geographic3Dto2DTest method createDatumShiftForGeographic2D.
/**
* Creates a "Geographic 2D to 3D → Geocentric → Affine → Geographic → Geographic 3D to 2D" chain.
* This method is used for integration tests.
*
* @param factory the math transform factory to use for creating and concatenating the transform.
* @param affine the math transform for the operation in geocentric Cartesian domain.
* @param pv the parameters for the operation in geographic coordinates.
* @return the chain of transforms.
* @throws FactoryException if an error occurred while creating a transform.
*
* @see GeocentricTranslationTest#createDatumShiftForGeographic2D(MathTransformFactory)
*/
static MathTransform createDatumShiftForGeographic2D(final MathTransformFactory factory, final MathTransform affine, final Parameters pv) throws FactoryException {
assertEquals("sourceDimensions", 3, affine.getSourceDimensions());
assertEquals("targetDimensions", 3, affine.getTargetDimensions());
/*
* Create a "Geographic to Geocentric" conversion with ellipsoid axis length units converted to metres
* (the unit implied by SRC_SEMI_MAJOR) because it is the unit of Bursa-Wolf parameters that we created above.
*/
Parameters step = Parameters.castOrWrap(factory.getDefaultParameters(GeographicToGeocentric.NAME));
step.getOrCreate(MapProjection.SEMI_MAJOR).setValue(pv.doubleValue(GeocentricAffineBetweenGeographic.SRC_SEMI_MAJOR));
step.getOrCreate(MapProjection.SEMI_MINOR).setValue(pv.doubleValue(GeocentricAffineBetweenGeographic.SRC_SEMI_MINOR));
MathTransform toGeocentric = factory.createParameterizedTransform(step);
assertEquals("sourceDimensions", 3, toGeocentric.getSourceDimensions());
assertEquals("targetDimensions", 3, toGeocentric.getTargetDimensions());
final MathTransform reduce = factory.createParameterizedTransform(factory.getDefaultParameters("Geographic3D to 2D conversion"));
assertEquals("sourceDimensions", 3, reduce.getSourceDimensions());
assertEquals("targetDimensions", 2, reduce.getTargetDimensions());
try {
toGeocentric = factory.createConcatenatedTransform(reduce.inverse(), toGeocentric);
} catch (NoninvertibleTransformException e) {
throw new FactoryException(e);
}
assertEquals("sourceDimensions", 2, toGeocentric.getSourceDimensions());
assertEquals("targetDimensions", 3, toGeocentric.getTargetDimensions());
/*
* Create a "Geocentric to Geographic" conversion with ellipsoid axis length units converted to metres
* because this is the unit of the Geocentric CRS used above.
*/
step = Parameters.castOrWrap(factory.getDefaultParameters(GeocentricToGeographic.NAME));
step.getOrCreate(MapProjection.SEMI_MAJOR).setValue(pv.doubleValue(GeocentricAffineBetweenGeographic.TGT_SEMI_MAJOR));
step.getOrCreate(MapProjection.SEMI_MINOR).setValue(pv.doubleValue(GeocentricAffineBetweenGeographic.TGT_SEMI_MINOR));
MathTransform toGeographic = factory.createParameterizedTransform(step);
assertEquals("sourceDimensions", 3, toGeographic.getSourceDimensions());
assertEquals("targetDimensions", 3, toGeographic.getTargetDimensions());
toGeographic = factory.createConcatenatedTransform(toGeographic, reduce);
assertEquals("sourceDimensions", 3, toGeographic.getSourceDimensions());
assertEquals("targetDimensions", 2, toGeographic.getTargetDimensions());
/*
* The Geocentric → Affine → Geographic chain.
*/
return factory.createConcatenatedTransform(toGeocentric, factory.createConcatenatedTransform(affine, toGeographic));
}
use of org.opengis.referencing.operation.NoninvertibleTransformException 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.NoninvertibleTransformException in project sis by apache.
the class LinearInterpolator1D method create.
/**
* Creates a <i>y=f(x)</i> transform for the given preimage (<var>x</var>) and values (<var>y</var>).
* See {@link MathTransforms#interpolate(double[], double[])} javadoc for more information.
*/
static MathTransform1D create(final double[] preimage, final double[] values) {
final int length;
if (preimage == null) {
if (values == null) {
return IdentityTransform1D.INSTANCE;
}
length = values.length;
} else {
length = preimage.length;
if (values != null && values.length != length) {
throw new IllegalArgumentException(Errors.format(Errors.Keys.MismatchedArrayLengths));
}
}
switch(length) {
case 0:
throw new IllegalArgumentException(Errors.format(Errors.Keys.EmptyArgument_1, (preimage != null) ? "preimage" : "values"));
case 1:
return LinearTransform1D.constant((preimage != null) ? preimage[0] : Double.NaN, (values != null) ? values[0] : Double.NaN);
}
/*
* A common usage of this 'create' method is for creating a "gridToCRS" transform from grid coordinates
* to something else, in which case the preimage array is null. In the less frequent case where preimage
* is non-null, we first convert from preimage to indices, then from indices to y values.
*/
MathTransform1D tr = null;
if (values != null) {
tr = create(values.clone());
}
if (preimage != null) {
final MathTransform1D indexToValues = tr;
try {
// preimageToIndex transform.
tr = create(preimage.clone()).inverse();
} catch (NoninvertibleTransformException e) {
throw new IllegalArgumentException(Resources.format(Resources.Keys.NonMonotonicSequence_1, "preimage"), e);
}
if (indexToValues != null) {
tr = MathTransforms.concatenate(tr, indexToValues);
}
}
return tr;
}
Aggregations