use of org.opengis.referencing.operation.MathTransform1D in project sis by apache.
the class DefaultVerticalExtent method intersect.
/**
* Sets this vertical extent to the intersection of this extent with the specified one.
* The {@linkplain org.apache.sis.referencing.crs.DefaultVerticalCRS#getDatum() vertical datum}
* must be the same (ignoring metadata) for both extents; this method does not perform datum shift.
* However this method can perform unit conversions.
*
* <p>If there is no intersection between the two extents, then this method sets both minimum and
* maximum values to {@linkplain Double#NaN}. If either this extent or the specified extent has NaN
* bounds, then the corresponding bounds of the intersection result will also be NaN.</p>
*
* @param other the vertical extent to intersect with this extent.
* @throws IllegalArgumentException if the two extents do not use the same datum, ignoring metadata.
*
* @see Extents#intersection(VerticalExtent, VerticalExtent)
* @see org.apache.sis.geometry.GeneralEnvelope#intersect(Envelope)
*
* @since 0.8
*/
public void intersect(final VerticalExtent other) throws IllegalArgumentException {
checkWritePermission();
ArgumentChecks.ensureNonNull("other", other);
Double min = other.getMinimumValue();
Double max = other.getMaximumValue();
try {
final MathTransform1D cv = getConversionFrom(other.getVerticalCRS());
if (isReversing(cv, min, max)) {
Double tmp = min;
min = max;
max = tmp;
}
/*
* If minimumValue is NaN, keep it unchanged (because x > minimumValue is false)
* in order to preserve the NilReason. Conversely if min is NaN, then we want to
* take it without conversion for preserving its NilReason.
*/
if (min != null) {
if (minimumValue == null || min.isNaN() || (min = convert(cv, min)) > minimumValue) {
minimumValue = min;
}
}
if (max != null) {
if (maximumValue == null || max.isNaN() || (max = convert(cv, max)) < maximumValue) {
maximumValue = max;
}
}
} catch (UnsupportedOperationException | FactoryException | ClassCastException | TransformException e) {
throw new IllegalArgumentException(Errors.format(Errors.Keys.IncompatiblePropertyValue_1, "verticalCRS"), e);
}
if (minimumValue != null && maximumValue != null && minimumValue > maximumValue) {
minimumValue = maximumValue = NilReason.MISSING.createNilObject(Double.class);
}
}
use of org.opengis.referencing.operation.MathTransform1D in project sis by apache.
the class ConcatenatedTransform method create.
/**
* Concatenates the two given transforms.
* If the concatenation result works with two-dimensional input and output points,
* then the returned transform will implement {@link MathTransform2D}.
* Likewise if the concatenation result works with one-dimensional input and output points,
* then the returned transform will implement {@link MathTransform1D}.
*
* <div class="note"><b>Implementation note:</b>
* {@code ConcatenatedTransform} implementations are available in two versions: direct and non-direct.
* The "non-direct" versions use an intermediate buffer when performing transformations; they are slower
* and consume more memory. They are used only as a fallback when a "direct" version can not be created.</div>
*
* @param tr1 the first math transform.
* @param tr2 the second math transform.
* @param factory the factory which is (indirectly) invoking this method, or {@code null} if none.
* @return the concatenated transform.
*
* @see MathTransforms#concatenate(MathTransform, MathTransform)
*/
public static MathTransform create(MathTransform tr1, MathTransform tr2, final MathTransformFactory factory) throws FactoryException, MismatchedDimensionException {
final int dim1 = tr1.getTargetDimensions();
final int dim2 = tr2.getSourceDimensions();
if (dim1 != dim2) {
throw new MismatchedDimensionException(Resources.format(Resources.Keys.CanNotConcatenateTransforms_2, getName(tr1), getName(tr2)) + ' ' + Errors.format(Errors.Keys.MismatchedDimension_2, dim1, dim2));
}
MathTransform mt = createOptimized(tr1, tr2, factory);
if (mt != null) {
return mt;
}
/*
* If at least one math transform is an instance of ConcatenatedTransform and assuming
* that MathTransforms are associatives, tries the following arrangements and select
* the one with the fewest amount of steps:
*
* Assuming : tr1 = (A * B)
* tr2 = (C * D)
*
* Current : (A * B) * (C * D) Will be the selected one if nothing better.
* Try k=0 : A * (B * (C * D)) Implies A * ((B * C) * D) through recursivity.
* Try k=1 : ((A * B) * C) * D Implies (A * (B * C)) * D through recursivity.
* Try k=2 : Tried only if try k=1 changed something.
*
* TODO: The same combination may be computed more than once (e.g. (B * C) above).
* Should not be a big deal if there is not two many steps. In the even where
* it would appears a performance issue, we could maintain a Map of combinations
* already computed. The map would be local to a "create" method execution.
*/
int stepCount = getStepCount(tr1) + getStepCount(tr2);
// Really 'true' because we want at least 2 iterations.
boolean tryAgain = true;
for (int k = 0; ; k++) {
MathTransform c1 = tr1;
MathTransform c2 = tr2;
final boolean first = (k & 1) == 0;
MathTransform candidate = first ? c1 : c2;
while (candidate instanceof ConcatenatedTransform) {
final ConcatenatedTransform ctr = (ConcatenatedTransform) candidate;
if (first) {
c1 = candidate = ctr.transform1;
c2 = create(ctr.transform2, c2, factory);
} else {
c1 = create(c1, ctr.transform1, factory);
c2 = candidate = ctr.transform2;
}
final int c = getStepCount(c1) + getStepCount(c2);
if (c < stepCount) {
tr1 = c1;
tr2 = c2;
stepCount = c;
tryAgain = true;
}
}
if (!tryAgain)
break;
tryAgain = false;
}
/*
* Tries again the check for optimized cases (identity, etc.), because a
* transform may have been simplified to identity as a result of the above.
*/
mt = createOptimized(tr1, tr2, factory);
if (mt != null) {
return mt;
}
/*
* Can not avoid the creation of a ConcatenatedTransform object.
* Check for the type to create (1D, 2D, general case...)
*/
final int dimSource = tr1.getSourceDimensions();
final int dimTarget = tr2.getTargetDimensions();
if (dimSource == 1 && dimTarget == 1) {
/*
* Result needs to be a MathTransform1D.
*/
if (tr1 instanceof MathTransform1D && tr2 instanceof MathTransform1D) {
return new ConcatenatedTransformDirect1D((MathTransform1D) tr1, (MathTransform1D) tr2);
} else {
return new ConcatenatedTransform1D(tr1, tr2);
}
} else if (dimSource == 2 && dimTarget == 2) {
/*
* Result needs to be a MathTransform2D.
*/
if (tr1 instanceof MathTransform2D && tr2 instanceof MathTransform2D) {
return new ConcatenatedTransformDirect2D((MathTransform2D) tr1, (MathTransform2D) tr2);
} else {
return new ConcatenatedTransform2D(tr1, tr2);
}
} else if (// dim1 = tr1.getTargetDimensions() and
dimSource == tr1.getTargetDimensions() && // dim2 = tr2.getSourceDimensions() may not be true anymore.
dimTarget == tr2.getSourceDimensions()) {
return new ConcatenatedTransformDirect(tr1, tr2);
} else {
return new ConcatenatedTransform(tr1, tr2);
}
}
use of org.opengis.referencing.operation.MathTransform1D 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