public final class Matrices extends Static
Matrix
factory methods and utilities.
This class provides the following methods:
createIdentity
,
createDiagonal
,
createZero
,
create
,
copy
.
createTransform
,
createDimensionSelect
,
createPassThrough
.
isAffine
,
isIdentity
,
equals
,
equals
,
toString
.
Defined in the sis-referencing
module
Modifier and Type | Method and Description |
---|---|
static MatrixSIS |
copy(Matrix matrix)
Creates a new matrix which is a copy of the given matrix.
|
static MatrixSIS |
create(int numRow,
int numCol,
double[] elements)
Creates a matrix of size
numRow × numCol initialized to the given elements. |
static MatrixSIS |
create(int numRow,
int numCol,
Number[] elements)
Creates a matrix of size
numRow × numCol initialized to the given numbers. |
static MatrixSIS |
createDiagonal(int numRow,
int numCol)
Creates a matrix of size
numRow × numCol . |
static MatrixSIS |
createDimensionSelect(int sourceDimensions,
int[] selectedDimensions)
Creates a matrix for a transform that keep only a subset of source ordinate values.
|
static MatrixSIS |
createIdentity(int size)
Creates a square identity matrix of size
size × size . |
static MatrixSIS |
createPassThrough(int firstAffectedOrdinate,
Matrix subMatrix,
int numTrailingOrdinates)
Creates a matrix which converts a subset of ordinates with another matrix.
|
static MatrixSIS |
createTransform(AxisDirection[] srcAxes,
AxisDirection[] dstAxes)
Creates a transform matrix changing axis order and/or direction.
|
static MatrixSIS |
createTransform(Envelope srcEnvelope,
AxisDirection[] srcAxes,
Envelope dstEnvelope,
AxisDirection[] dstAxes)
Creates a transform matrix mapping the given source envelope to the given destination envelope,
combined with changes in axis order and/or direction.
|
static MatrixSIS |
createTransform(Envelope srcEnvelope,
Envelope dstEnvelope)
Creates a transform matrix mapping the given source envelope to the given destination envelope.
|
static MatrixSIS |
createZero(int numRow,
int numCol)
Creates a matrix of size
numRow × numCol filled with zero values. |
static boolean |
equals(Matrix m1,
Matrix m2,
ComparisonMode mode)
Compares the given matrices for equality, using the given comparison strictness level.
|
static boolean |
equals(Matrix m1,
Matrix m2,
double epsilon,
boolean relative)
Compares the given matrices for equality, using the given relative or absolute tolerance threshold.
|
static boolean |
isAffine(Matrix matrix)
Returns
true if the given matrix represents an affine transform. |
static boolean |
isIdentity(Matrix matrix,
double tolerance)
Returns
true if the given matrix is close to an identity matrix, given a tolerance threshold. |
static String |
toString(Matrix matrix)
Returns a unlocalized string representation of the given matrix.
|
public static MatrixSIS createIdentity(int size)
size
× size
.
Elements on the diagonal (j == i) are set to 1.
public static MatrixSIS createDiagonal(int numRow, int numCol)
numRow
× numCol
.
Elements on the diagonal (j == i) are set to 1.
The result is an identity matrix if numRow
= numCol
.
numRow
- For a math transform, this is the number of target dimensions + 1.numCol
- For a math transform, this is the number of source dimensions + 1.public static MatrixSIS createZero(int numRow, int numCol)
numRow
× numCol
filled with zero values.
This constructor is convenient when the caller wants to initialize the matrix elements himself.
numRow
- For a math transform, this is the number of target dimensions + 1.numCol
- For a math transform, this is the number of source dimensions + 1.public static MatrixSIS create(int numRow, int numCol, double[] elements)
numRow
× numCol
initialized to the given elements.
The elements array size must be equals to numRow*numCol
. Column indices vary fastest.
numRow
- Number of rows.numCol
- Number of columns.elements
- The matrix elements in a row-major array. Column indices vary fastest.MatrixSIS.setElements(double[])
public static MatrixSIS create(int numRow, int numCol, Number[] elements)
numRow
× numCol
initialized to the given numbers.
The elements array size must be equals to numRow*numCol
. Column indices vary fastest.numRow
- Number of rows.numCol
- Number of columns.elements
- The matrix elements in a row-major array. Column indices vary fastest.public static MatrixSIS createTransform(Envelope srcEnvelope, Envelope dstEnvelope)
getSpan(int)
method
to behave as documented in the AbstractEnvelope.getSpan(int)
javadoc.
Furthermore the matrix created by this method will produce expected results only for source or destination
points before the date line, since the wrap around operation can not be represented by an affine transform.
will return the following square matrix. The transform of the lower corner is given as an example:matrix = Matrices.createTransform( new Envelope2D(null, -20, -40, 100, 200), new Envelope2D(null, -10, -25, 300, 500));
┌ ┐ ┌ ┐ ┌ ┐ │ -10 │ │ 3.0 0 50 │ │ -20 │ // 3.0 is the scale factor from width of 100 to 300 │ -25 │ = │ 0 2.5 75 │ × │ -40 │ // 2.5 is the scale factor from height of 200 to 500 │ 1 │ │ 0 0 1 │ │ 1 │ └ ┘ └ ┘ └ ┘
srcEnvelope
- The source envelope.dstEnvelope
- The destination envelope.createTransform(AxisDirection[], AxisDirection[])
,
createTransform(Envelope, AxisDirection[], Envelope, AxisDirection[])
,
CoordinateSystems.swapAndScaleAxes(CoordinateSystem, CoordinateSystem)
public static MatrixSIS createTransform(AxisDirection[] srcAxes, AxisDirection[] dstAxes)
dstAxes
direction to either an equals srcAxis
direction, or to an opposite srcAxis
direction.
srcAxes
directions can not be mapped to dstAxes
directions, then the transform
will silently drops the ordinates associated to those extra source axis directions.dstAxes
directions can not be mapped to srcAxes
directions,
then an exception will be thrown.will return the following square matrix, which can be used in coordinate conversions as below:matrix = Matrices.createTransform( new AxisDirection[] {AxisDirection.NORTH, AxisDirection.WEST}, new AxisDirection[] {AxisDirection.EAST, AxisDirection.NORTH});
┌ ┐ ┌ ┐ ┌ ┐ │ +x │ │ 0 -1 0 │ │ y │ │ y │ = │ 1 0 0 │ × │ -x │ │ 1 │ │ 0 0 1 │ │ 1 │ └ ┘ └ ┘ └ ┘
srcAxes
- The ordered sequence of axis directions for source coordinate system.dstAxes
- The ordered sequence of axis directions for destination coordinate system.IllegalArgumentException
- If dstAxes
contains at least one axis not found in srcAxes
,
or if some colinear axes were found.createTransform(Envelope, Envelope)
,
createTransform(Envelope, AxisDirection[], Envelope, AxisDirection[])
,
CoordinateSystems.swapAndScaleAxes(CoordinateSystem, CoordinateSystem)
public static MatrixSIS createTransform(Envelope srcEnvelope, AxisDirection[] srcAxes, Envelope dstEnvelope, AxisDirection[] dstAxes)
createTransform(srcEnvelope, dstEnvelope)
createTransform(srcAxes, dstAxes)
getSpan(int)
method
to behave as documented in the AbstractEnvelope.getSpan(int)
javadoc.
Furthermore the matrix created by this method will produce expected results only for source or destination
points on one side of the date line (depending on whether axis direction is reversed), since the wrap around
operation can not be represented by an affine transform.
createTransform(…)
methods, the following method call:
will return the following square matrix. The transform of a corner is given as an example. Note that the input ordinate values are swapped because of the (North, West) axis directions, and the lower-left corner of the destination envelope is the lower-right corner of the source envelope because of the opposite axis direction.matrix = Matrices.createTransform( new Envelope2D(null, -40, +20, 200, 100), new AxisDirection[] {AxisDirection.NORTH, AxisDirection.WEST}, new Envelope2D(null, -10, -25, 300, 500), new AxisDirection[] {AxisDirection.EAST, AxisDirection.NORTH});
┌ ┐ ┌ ┐ ┌ ┐ │ -10 │ │ 0 -3.0 350 │ │ -40 │ │ -25 │ = │ 2.5 0 75 │ × │ 120 │ // 120 is the westernmost source ordinate: (x=20) + (width=100) │ 1 │ │ 0 0 1 │ │ 1 │ └ ┘ └ ┘ └ ┘
srcEnvelope
- The source envelope.srcAxes
- The ordered sequence of axis directions for source coordinate system.dstEnvelope
- The destination envelope.dstAxes
- The ordered sequence of axis directions for destination coordinate system.MismatchedDimensionException
- If an envelope dimension does not
match the length of the axis directions sequence.IllegalArgumentException
- If dstAxes
contains at least one axis not found in srcAxes
,
or if some colinear axes were found.createTransform(Envelope, Envelope)
,
createTransform(AxisDirection[], AxisDirection[])
,
CoordinateSystems.swapAndScaleAxes(CoordinateSystem, CoordinateSystem)
public static MatrixSIS createDimensionSelect(int sourceDimensions, int[] selectedDimensions)
selectedDimensions.length
+1) × (sourceDimensions
+1).
The matrix will contain only zero elements, except for the following cells which will contain 1:
selectedDimensions[j]
.The above method call will create the following 4×5 matrix, which can be used for converting coordinates as below:matrix = Matrices.createDimensionSelect(4, new int[] {1, 0, 3});
┌ ┐ ┌ ┐ ┌ ┐ │ y │ │ 0 1 0 0 0 │ │ x │ │ x │ │ 1 0 0 0 0 │ │ y │ │ t │ = │ 0 0 0 1 0 │ × │ z │ │ 1 │ │ 0 0 0 0 1 │ │ t │ └ ┘ └ ┘ │ 1 │ └ ┘
sourceDimensions
- The number of dimensions in source coordinates.selectedDimensions
- The 0-based indices of source ordinate values to keep.
The length of this array will be the number of dimensions in target coordinates.IllegalArgumentException
- if a value of selectedDimensions
is lower than 0
or not smaller than sourceDimensions
.org.apache.sis.referencing.operation.transform.MathTransforms#dimensionFilter(int, int[])
public static MatrixSIS createPassThrough(int firstAffectedOrdinate, Matrix subMatrix, int numTrailingOrdinates)
The given sub-matrix shall have the following properties:
This method builds a new matrix with the following content:
firstAffectedOrdinate
rows and columns are inserted before the first
row and columns of the sub-matrix. The elements for the new rows and columns are set to 1
on the diagonal, and 0 elsewhere.firstAffectedOrdinate
, firstAffectedOrdinate
).numTrailingOrdinates
rows and columns are appended after the above sub-matrix.
Their elements are set to 1 on the pseudo-diagonal ending in the lower-right corner, and 0 elsewhere.Then a call to┌ ┐ ┌ ┐ ┌ ┐ │ z' │ = │ 0.3048 -25 │ × │ z │ │ 1 │ │ 0 1 │ │ 1 │ └ ┘ └ ┘ └ ┘
Matrices.createPassThrough(2, subMatrix, 1)
will return the following matrix,
which can be used for converting the height (z) without affecting the other ordinate values
(x,y,t):
┌ ┐ ┌ ┐ ┌ ┐ │ x │ │ 1 0 0 0 0 │ │ x │ │ y │ │ 0 1 0 0 0 │ │ y │ │ z' │ = │ 0 0 0.3048 0 -25 │ × │ z │ │ t │ │ 0 0 0 1 0 │ │ t │ │ 1 │ │ 0 0 0 0 1 │ │ 1 │ └ ┘ └ ┘ └ ┘
firstAffectedOrdinate
- The lowest index of the affected ordinates.subMatrix
- The matrix to use for affected ordinates.numTrailingOrdinates
- Number of trailing ordinates to pass through.org.apache.sis.referencing.operation.DefaultMathTransformFactory#createPassThroughTransform(int, MathTransform, int)
public static MatrixSIS copy(Matrix matrix)
matrix
- The matrix to copy, or null
.null
if the given matrix was null.MatrixSIS.clone()
,
MatrixSIS.castOrCopy(Matrix)
public static boolean isAffine(Matrix matrix)
true
if the given matrix represents an affine transform.
A transform is affine if the matrix is square and its last row contains
only zeros, except in the last column which contains 1.matrix
- The matrix to test.true
if the matrix represents an affine transform.MatrixSIS.isAffine()
,
AffineTransforms2D.castOrCopy(Matrix)
public static boolean isIdentity(Matrix matrix, double tolerance)
true
if the given matrix is close to an identity matrix, given a tolerance threshold.
This method is equivalent to computing the difference between the given matrix and an identity matrix
of identical size, and returning true
if and only if all differences are smaller than or equal
to tolerance
.
Caution: Bursa-Wolf parameters,
when represented as a matrix, are close to an identity transform and could easily be confused with rounding
errors. In case of doubt, it is often safer to use the strict MatrixSIS.isIdentity()
method instead
than this one.
matrix
- The matrix to test for identity.tolerance
- The tolerance value, or 0 for a strict comparison.true
if this matrix is close to the identity matrix given the tolerance threshold.MatrixSIS.isIdentity()
public static boolean equals(Matrix m1, Matrix m2, double epsilon, boolean relative)
Double.NaN
values are considered equals to all other NaN valuesrelative
is true
, then for any pair of values v1j,i
and v2j,i to compare, the tolerance threshold is scaled by
max(abs(v1), abs(v2))
. Otherwise the threshold is used as-is.m1
- The first matrix to compare, or null
.m2
- The second matrix to compare, or null
.epsilon
- The tolerance value.relative
- If true
, then the tolerance value is relative to the magnitude
of the matrix elements being compared.true
if the values of the two matrix do not differ by a quantity
greater than the given tolerance threshold.MatrixSIS.equals(Matrix, double)
public static boolean equals(Matrix m1, Matrix m2, ComparisonMode mode)
mode
argument:
STRICT
:
the two matrices must be of the same class, have the same size and the same element values.BY_CONTRACT
:
the two matrices must have the same size and the same element values,
but are not required to be the same implementation class (any Matrix
is okay).IGNORE_METADATA
: same as BY_CONTRACT
,
since matrices have no metadata.APPROXIMATIVE
:
the two matrices must have the same size, but the element values can differ up to some threshold.
The threshold value is determined empirically and may change in any future SIS versions.
For more control, use equals(Matrix, Matrix, double, boolean)
instead.m1
- The first matrix to compare, or null
.m2
- The second matrix to compare, or null
.mode
- The strictness level of the comparison.true
if both matrices are equal.MatrixSIS.equals(Object, ComparisonMode)
public static String toString(Matrix matrix)
The current implementation formats ±0 and ±1 without trailing ".0"
, and all other values with
a per-column uniform number of fraction digits. The ±0 and ±1 values are treated especially because they
usually imply a "no scale", "no translation" or "orthogonal axes"
meaning. A matrix in SIS is often populated mostly by ±0 and ±1 values, with a few "interesting" values.
The simpler ±0 and ±1 formatting makes easier to spot the "interesting" values.
The following example shows the string representation of an affine transform which swap (latitude, longitude) axes, converts degrees to radians and converts height values from feet to metres:
┌ ┐ │ 0 0.017453292519943295 0 0 │ │ 0.017453292519943295 0 0 0 │ │ 0 0 0.3048 0 │ │ 0 0 0 1 │ └ ┘
matrix
- The matrix for which to get a string representation.Copyright © 2010–2015 The Apache Software Foundation. All rights reserved.