/** * Casts or copies the given matrix to a {@code Matrix3} implementation. If the given {@code matrix} * is already an instance of {@code Matrix3}, then it is returned unchanged. Otherwise this method * verifies the matrix size, then copies all elements in a new {@code Matrix3} object. * * @param matrix the matrix to cast or copy, or {@code null}. * @return the matrix argument if it can be safely casted (including {@code null} argument), * or a copy of the given matrix otherwise. * @throws MismatchedMatrixSizeException if the size of the given matrix is not {@value #SIZE}×{@value #SIZE}. */ public static Matrix3 castOrCopy(final Matrix matrix) throws MismatchedMatrixSizeException { if (matrix == null || matrix instanceof Matrix3) { return (Matrix3) matrix; } ensureSizeMatch(SIZE, SIZE, matrix); return new Matrix3(matrix); }
/** * Casts or copies the given matrix to a {@code Matrix3} implementation. If the given {@code matrix} * is already an instance of {@code Matrix3}, then it is returned unchanged. Otherwise this method * verifies the matrix size, then copies all elements in a new {@code Matrix3} object. * * @param matrix the matrix to cast or copy, or {@code null}. * @return the matrix argument if it can be safely casted (including {@code null} argument), * or a copy of the given matrix otherwise. * @throws MismatchedMatrixSizeException if the size of the given matrix is not {@value #SIZE}×{@value #SIZE}. */ public static Matrix3 castOrCopy(final Matrix matrix) throws MismatchedMatrixSizeException { if (matrix == null || matrix instanceof Matrix3) { return (Matrix3) matrix; } ensureSizeMatch(SIZE, SIZE, matrix); return new Matrix3(matrix); }
/** * Tests {@link MatrixSIS#convertAfter(int, Number, Number)} * using {@link java.awt.geom.AffineTransform} as a reference implementation. * * @since 0.6 */ @Test public void testConvertAfter() { testConvertAfter(new Matrix3()); }
/** * Tests {@link MatrixSIS#translate(double[])} * using {@link java.awt.geom.AffineTransform} as a reference implementation. * * @since 1.0 */ @Test public void testTranslateVector() { testTranslateVector(new Matrix3()); } }
/** * Tests {@link MatrixSIS#multiply(double[])} * using {@link java.awt.geom.AffineTransform} as a reference implementation. * * @since 0.8 */ @Test public void testMultiplyVector() { testMultiplyVector(new Matrix3()); }
/** * Tests {@link MatrixSIS#convertBefore(int, Number, Number)} * using {@link java.awt.geom.AffineTransform} as a reference implementation. * * @since 0.6 */ @Test public void testConvertBefore() { testConvertBefore(new Matrix3(), true); }
/** * Creates a square identity matrix of size {@code size} × {@code size}. * Elements on the diagonal (<var>j</var> == <var>i</var>) are set to 1. * * <div class="note"><b>Implementation note:</b> * For sizes between {@value org.apache.sis.referencing.operation.matrix.Matrix1#SIZE} and * {@value org.apache.sis.referencing.operation.matrix.Matrix4#SIZE} inclusive, the matrix * is guaranteed to be an instance of one of {@link Matrix1} … {@link Matrix4} subtypes.</div> * * @param size numbers of row and columns. For an affine transform matrix, this is the number of * {@linkplain MathTransform#getSourceDimensions() source} and * {@linkplain MathTransform#getTargetDimensions() target} dimensions + 1. * @return an identity matrix of the given size. */ public static MatrixSIS createIdentity(final int size) { switch (size) { case 1: return new Matrix1(); case 2: return new Matrix2(); case 3: return new Matrix3(); case 4: return new Matrix4(); default: return new GeneralMatrix(size, size, true, 1); } }
/** * Creates a 3×3 matrix from the given affine transform. * * @param transform the affine transform to copy as a matrix. * @return a matrix containing the same terms than the given affine transform. */ public static Matrix3 toMatrix(final AffineTransform transform) { return new Matrix3(transform.getScaleX(), transform.getShearX(), transform.getTranslateX(), transform.getShearY(), transform.getScaleY(), transform.getTranslateY(), 0, 0, 1); }
/** * Creates a 3×3 matrix from the given affine transform. * * @param transform the affine transform to copy as a matrix. * @return a matrix containing the same terms than the given affine transform. */ public static Matrix3 toMatrix(final AffineTransform transform) { return new Matrix3(transform.getScaleX(), transform.getShearX(), transform.getTranslateX(), transform.getShearY(), transform.getScaleY(), transform.getTranslateY(), 0, 0, 1); }
/** * Creates a grid geometry with the given extent and scale for testing purpose. * An arbitrary translation of (2,3) is added to the "grid to CRS" conversion. */ private static GridGeometry grid(int xmin, int ymin, int xmax, int ymax, int xScale, int yScale) throws TransformException { GridExtent extent = new GridExtent(null, new long[] {xmin, ymin}, new long[] {xmax, ymax}, true); Matrix3 gridToCRS = new Matrix3(); gridToCRS.m00 = xScale; gridToCRS.m11 = yScale; gridToCRS.m02 = 200; // Arbitrary translation. gridToCRS.m12 = 500; return new GridGeometry(extent, PixelInCell.CELL_CORNER, MathTransforms.linear(gridToCRS), null); }
/** * Creates a matrix of size {@code numRow} × {@code numCol} filled with zero values. * This constructor is convenient when the caller wants to initialize the matrix elements himself. * * <div class="note"><b>Implementation note:</b> * For {@code numRow} == {@code numCol} with a value between * {@value org.apache.sis.referencing.operation.matrix.Matrix1#SIZE} and * {@value org.apache.sis.referencing.operation.matrix.Matrix4#SIZE} inclusive, the matrix * is guaranteed to be an instance of one of {@link Matrix1} … {@link Matrix4} subtypes.</div> * * @param numRow for a math transform, this is the number of {@linkplain MathTransform#getTargetDimensions() target dimensions} + 1. * @param numCol for a math transform, this is the number of {@linkplain MathTransform#getSourceDimensions() source dimensions} + 1. * @return a matrix of the given size with only zero values. */ public static MatrixSIS createZero(final int numRow, final int numCol) { if (numRow == numCol) switch (numRow) { case 1: return new Matrix1(false); case 2: return new Matrix2(false); case 3: return new Matrix3(false); case 4: return new Matrix4(false); default: return new GeneralMatrix(numRow, numCol, false, 1); } return new NonSquareMatrix(numRow, numCol, false, 1); }
/** * Tests the pass through transform using an identity transform. * The "pass-through" of such transform shall be itself the identity transform. * * @throws TransformException should never happen. */ @Test public void testIdentity() throws TransformException { final Matrix matrix = new Matrix3(); runTest(MathTransforms.linear(matrix), IdentityTransform.class); }
/** * Tests the pass-through transform using an affine transform. * The "pass-through" of such transforms are optimized using matrix arithmetic. * * @throws TransformException should never happen. */ @Test public void testLinear() throws TransformException { final Matrix matrix = new Matrix3( 4, 0, 0, 0, 3, 0, 0, 0, 1); runTest(MathTransforms.linear(matrix), LinearTransform.class); }
/** * Tests {@link Matrices#copy(Matrix)} */ @Test public void testCopy() { final Matrix matrix = new Matrix3(10, 20, 30, 40, 50, 60, 70, 80, 90); final Matrix copy = Matrices.copy(matrix); assertNotSame("copy", matrix, copy); assertEquals ("copy", matrix, copy); }
/** * Tests {@link NonSquareMatrix#solve(Matrix)} with a non-square matrix. * * @throws NoninvertibleMatrixException if the matrix can not be inverted. */ @Test @Override public void testSolve() throws NoninvertibleMatrixException { testDimensionReduction(new Matrix3( 2, 0, 0, 0, 2, 0, 0, 0, 1), 2); testDimensionIncrease(new GeneralMatrix(5, 5, new double[] { 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1}), 2); }
/** * Tests the {@link Matrix3#Matrix3(double, double, double, * double, double, double, double, double, double)} constructor. * This constructor is specific to the implementation class. */ @Test public void testConstructor() { initialize(-2078758443421995879L); final double[] elements = createRandomPositiveValues(SIZE * SIZE); final Matrix3 matrix = new Matrix3( elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8]); validate(matrix); assertArrayEquals(elements, matrix.getElements(), STRICT); }
/** * Tests construction from a <cite>grid to CRS</cite> having a 0.5 pixel translation. * This translation happens in transform mapping <cite>pixel center</cite> when the * corresponding <cite>pixel corner</cite> transformation is identity. * * @throws TransformException if an error occurred while using the "grid to CRS" transform. */ @Test public void testShifted() throws TransformException { final long[] low = new long[] {100, 300}; final long[] high = new long[] {200, 400}; final GridExtent extent = new GridExtent(null, low, high, true); final MathTransform identity = MathTransforms.linear(new Matrix3( 1, 0, 0.5, 0, 1, 0.5, 0, 0, 1)); final GridGeometry grid = new GridGeometry(extent, PixelInCell.CELL_CENTER, identity, null); assertTrue("gridToCRS.isIdentity", grid.getGridToCRS(PixelInCell.CELL_CORNER).isIdentity()); }
/** * Tests {@link PixelTranslation#translate(MathTransform, PixelOrientation, PixelOrientation, int, int)}. * See {@link #testTranslatePixelInCell()} for discussion on expected values. */ @Test public void testTranslatePixelOrientation() { MathTransform mt = centerToCorner2D(); assertMatrixEquals("center → corner", new Matrix3( 1, 0, -0.5, 0, 1, -0.5, 0, 0, 1), MathTransforms.getMatrix(mt), STRICT); mt = PixelTranslation.translate(MathTransforms.identity(3), PixelOrientation.LOWER_LEFT, PixelOrientation.CENTER, 1, 2); assertMatrixEquals("corner → center", new Matrix4( 1, 0, 0, 0.0, 0, 1, 0, +0.5, 0, 0, 1, -0.5, 0, 0, 0, 1), MathTransforms.getMatrix(mt), STRICT); }
/** * Tests {@code LongitudeRotation.createMathTransform(…)}. */ @Test public void testCreateMathTransform() { final LongitudeRotation provider = new LongitudeRotation(); ParameterValueGroup p = provider.getParameters().createValue(); p.parameter("Longitude offset").setValue(2.5969213, Units.GRAD); // Paris meridian final MathTransform mt = provider.createMathTransform(null, p); /* * Verify the full matrix. Note that the longitude offset is expected to be in degrees. * This conversion from grad to degrees is specific to Apache SIS and may be revised in * future version. See org.apache.sis.referencing.operation package javadoc. */ assertInstanceOf("Shall be an affine transform.", LinearTransform.class, mt); assertMatrixEquals("Expected a longitude rotation", new Matrix3(1, 0, 2.33722917, 0, 1, 0, 0, 0, 1), ((LinearTransform) mt).getMatrix(), 1E-16); }
/** * Tests the construction of a {@link DefaultDerivedCRS}. */ @Test public void testConstruction() { final DefaultDerivedCRS crs = createLongitudeRotation(); // Validators.validate(crs); assertEquals("name", "Back to Greenwich", crs.getName().getCode()); assertEquals("baseCRS", "NTF (Paris)", crs.getBaseCRS().getName().getCode()); assertEquals("datum", "Nouvelle Triangulation Française", crs.getDatum().getName().getCode()); assertSame ("coordinateSystem", HardCodedCS.GEODETIC_φλ, crs.getCoordinateSystem()); final Conversion conversion = crs.getConversionFromBase(); assertSame("sourceCRS", crs.getBaseCRS(), conversion.getSourceCRS()); assertSame("targetCRS", crs, conversion.getTargetCRS()); assertMatrixEquals("Longitude rotation", new Matrix3( 0, 1, 0, 1, 0, 2.33722917, 0, 0, 1), MathTransforms.getMatrix(conversion.getMathTransform()), STRICT); }