use of org.apache.sis.internal.util.DoubleDouble in project sis by apache.
the class MatrixSIS method normalizeColumns.
/**
* Normalizes all columns in-place. Each columns in this matrix is considered as a vector.
* For each column (vector), this method computes the magnitude (vector length) as the square
* root of the sum of all square values. Then, all values in the column are divided by that
* magnitude.
*
* <p>This method is useful when the matrix is a
* {@linkplain org.opengis.referencing.operation.MathTransform#derivative transform derivative}.
* In such matrix, each column is a vector representing the displacement in target space when an
* ordinate in the source space is increased by one. Invoking this method turns those vectors
* into unitary vectors, which is useful for forming the basis of a new coordinate system.</p>
*
* @throws UnsupportedOperationException if this matrix is unmodifiable.
*/
public void normalizeColumns() {
final int numRow = getNumRow();
final int numCol = getNumCol();
final DoubleDouble sum = new DoubleDouble();
final DoubleDouble dot = new DoubleDouble();
final DoubleDouble tmp = new DoubleDouble();
for (int i = 0; i < numCol; i++) {
sum.clear();
for (int j = 0; j < numRow; j++) {
get(j, i, dot);
dot.square();
sum.add(dot);
}
sum.sqrt();
for (int j = 0; j < numRow; j++) {
get(j, i, tmp);
dot.setFrom(sum);
dot.inverseDivide(tmp);
set(j, i, dot);
}
}
}
use of org.apache.sis.internal.util.DoubleDouble in project sis by apache.
the class MatrixSIS method convertBefore.
/**
* Assuming that this matrix represents an affine transform, concatenates a scale and a translation on the
* given dimension. Converting a point with the resulting matrix is equivalent to first convert the point
* with {@code ordinates[srcDim] = ordinates[srcDim] * scale + offset}, then apply the original matrix.
*
* <div class="section">Equivalence between this method and Java2D {@code AffineTransform} methods</div>
* If this matrix was an instance of Java2D {@link AffineTransform}, then invoking this method would
* be equivalent to invoke the following {@code AffineTransform} methods in the order shown below:
*
* <table class="sis" summary="Equivalence between this method and AffineTransform methods">
* <tr>
* <th>{@code MatrixSIS} method</th>
* <th class="sep">{@code AffineTransform} methods</th>
* </tr><tr>
* <td>{@code concatenate(0, scale, offset)}</td>
* <td class="sep"><code>at.{@linkplain AffineTransform#translate(double, double) translate}(offset, 0);
* at.{@linkplain AffineTransform#scale(double, double) scale}(scale, 1);</code></td>
* </tr><tr>
* <td class="hsep">{@code concatenate(1, scale, offset)}</td>
* <td class="hsep sep"><code>at.{@linkplain AffineTransform#translate(double, double) translate}(0, offset);
* at.{@linkplain AffineTransform#scale(double, double) scale}(1, scale);</code></td>
* </tr>
* </table>
*
* @param srcDim the dimension of the ordinate to rescale in the source coordinates.
* @param scale the amount by which to multiply the source ordinate value before to apply the transform, or {@code null} if none.
* @param offset the amount by which to translate the source ordinate value before to apply the transform, or {@code null} if none.
* @throws UnsupportedOperationException if this matrix is unmodifiable.
*
* @see AffineTransform#concatenate(AffineTransform)
*
* @since 0.6
*/
public void convertBefore(final int srcDim, final Number scale, final Number offset) {
final int lastCol = getNumCol() - 1;
ArgumentChecks.ensureValidIndex(lastCol, srcDim);
final DoubleDouble s = new DoubleDouble();
final DoubleDouble t = new DoubleDouble();
for (int j = getNumRow(); --j >= 0; ) {
if (offset != null) {
// Scale factor
get(j, srcDim, s);
// Translation factor
get(j, lastCol, t);
s.multiply(offset);
t.add(s);
set(j, lastCol, t);
}
if (scale != null) {
// Scale factor
get(j, srcDim, s);
s.multiply(scale);
set(j, srcDim, s);
}
}
}
use of org.apache.sis.internal.util.DoubleDouble in project sis by apache.
the class MatrixSIS method convertAfter.
/**
* Assuming that this matrix represents an affine transform, pre-concatenates a scale and a translation on the
* given dimension. Converting a point with the resulting matrix is equivalent to first convert the point with
* the original matrix, then convert the result with {@code ordinates[tgtDim] = ordinates[tgtDim] * scale + offset}.
*
* @param tgtDim the dimension of the ordinate to rescale in the target coordinates.
* @param scale the amount by which to multiply the target ordinate value after this transform, or {@code null} if none.
* @param offset the amount by which to translate the target ordinate value after this transform, or {@code null} if none.
* @throws UnsupportedOperationException if this matrix is unmodifiable.
*
* @see AffineTransform#preConcatenate(AffineTransform)
*
* @since 0.6
*/
public void convertAfter(final int tgtDim, final Number scale, final Number offset) {
final int lastRow = getNumRow() - 1;
final int lastCol = getNumCol() - 1;
ArgumentChecks.ensureValidIndex(lastRow, tgtDim);
final DoubleDouble s = new DoubleDouble();
if (scale != null) {
for (int i = lastCol; i >= 0; i--) {
get(tgtDim, i, s);
s.multiply(scale);
set(tgtDim, i, s);
}
}
if (offset != null) {
get(tgtDim, lastCol, s);
s.add(offset);
set(tgtDim, lastCol, s);
}
}
use of org.apache.sis.internal.util.DoubleDouble in project sis by apache.
the class GridGeometry method setTranslationTerms.
/**
* Computes translation terms in the given matrix from the (usually singleton) tie point.
* This method is invoked when the GeoTIFF file has a {@link Tags#ModelPixelScaleTag} and
* {@link Tags#ModelTiePoints}. The later should have a single record.
*
* @param gridToCRS the matrix to update. That matrix shall contain the scale factors before to invoke this method.
* @param modelTiePoints the vector of model tie points. Only the first point will be used.
* @return {@code true} if the given vector is non-null and contains at least one complete record.
*/
static boolean setTranslationTerms(final MatrixSIS gridToCRS, final Vector modelTiePoints) {
if (modelTiePoints != null) {
/*
* The GeoTIFF specification recommends that the first point is located at grid indices (0,0).
* But as a safety, we will nevertheless search in the grid for the point closest to origin.
* If the grid is affine, using the corner closest to (0,0) reduces rounding errors compared
* to using another corner. If the grid is not affine, then ModelPixelScaleTag should not have
* been defined for that fileā¦
*/
// Index of the record nearest to origin.
int nearest = 0;
// Distance squared of the nearest record.
double distance = Double.POSITIVE_INFINITY;
final int size = modelTiePoints.size();
for (int i = 0; i < size; i += RECORD_LENGTH) {
double t;
final double d = (t = modelTiePoints.doubleValue(i)) * t + (t = modelTiePoints.doubleValue(i + 1)) * t + (t = modelTiePoints.doubleValue(i + 2)) * t;
if (d < distance) {
distance = d;
nearest = i;
// Optimization for the standard case.
if (d == 0)
break;
}
}
if (distance != Double.POSITIVE_INFINITY) {
final DoubleDouble t = new DoubleDouble();
final int numDim = gridToCRS.getNumRow() - 1;
final int trCol = gridToCRS.getNumCol() - 1;
for (int j = 0; j < numDim; j++) {
t.value = -modelTiePoints.doubleValue(nearest + j);
t.error = DoubleDouble.errorForWellKnownValue(t.value);
t.divide(gridToCRS.getNumber(j, j));
t.add(modelTiePoints.doubleValue(nearest + j + RECORD_LENGTH / 2));
gridToCRS.setNumber(j, trCol, t);
}
return true;
}
}
return false;
}
Aggregations