blob: 6edfb8fbb1ece8633bb02ad13c8bf433aaef65d6 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.sis.referencing.operation.matrix;
import org.opengis.referencing.operation.Matrix;
/**
* A matrix of fixed {@value #SIZE}×{@value #SIZE} size.
* The matrix members are:
*
* <blockquote><pre> ┌ ┐
* │ {@linkplain #m00} {@linkplain #m01} {@linkplain #m02} │
* │ {@linkplain #m10} {@linkplain #m11} {@linkplain #m12} │
* │ {@linkplain #m20} {@linkplain #m21} {@linkplain #m22} │
* └ ┘</pre></blockquote>
*
* @author Martin Desruisseaux (IRD, Geomatys)
* @version 0.6
*
* @see Matrix1
* @see Matrix2
* @see Matrix4
*
* @since 0.4
* @module
*/
@SuppressWarnings("CloneableClassWithoutClone") // No field in this class needs clone.
public final class Matrix3 extends MatrixSIS {
/**
* Serial number for inter-operability with different versions.
*/
private static final long serialVersionUID = 8902061778871586611L;
/**
* The matrix size, which is {@value}.
*/
public static final int SIZE = 3;
/** The first matrix element in the first row. */ public double m00;
/** The second matrix element in the first row. */ public double m01;
/** The third matrix element in the first row. */ public double m02;
/** The first matrix element in the second row. */ public double m10;
/** The second matrix element in the second row. */ public double m11;
/** The third matrix element in the second row. */ public double m12;
/** The first matrix element in the third row. */ public double m20;
/** The second matrix element in the third row. */ public double m21;
/** The third matrix element in the third row. */ public double m22;
/**
* Creates a new identity matrix.
*/
public Matrix3() {
m00 = m11 = m22 = 1;
}
/**
* Creates a new matrix filled with only zero values.
*
* @param ignore shall always be {@code false} in current version.
*/
Matrix3(final boolean ignore) {
}
/**
* Creates a new matrix initialized to the specified values.
*
* @param m00 the first matrix element in the first row.
* @param m01 the second matrix element in the first row.
* @param m02 the third matrix element in the first row.
* @param m10 the first matrix element in the second row.
* @param m11 the second matrix element in the second row.
* @param m12 the third matrix element in the second row.
* @param m20 the first matrix element in the third row.
* @param m21 the second matrix element in the third row.
* @param m22 the third matrix element in the third row.
*/
public Matrix3(final double m00, final double m01, final double m02,
final double m10, final double m11, final double m12,
final double m20, final double m21, final double m22)
{
this.m00 = m00; this.m01 = m01; this.m02 = m02;
this.m10 = m10; this.m11 = m11; this.m12 = m12;
this.m20 = m20; this.m21 = m21; this.m22 = m22;
}
/**
* Creates a new matrix initialized to the specified values.
* The length of the given array must be 9 and the values in the same order than the above constructor.
*
* @param elements elements of the matrix. Column indices vary fastest.
* @throws IllegalArgumentException if the given array does not have the expected length.
*
* @see #setElements(double[])
* @see Matrices#create(int, int, double[])
*/
public Matrix3(final double[] elements) throws IllegalArgumentException {
setElements(elements);
}
/**
* Creates a new matrix initialized to the same value than the specified one.
* The specified matrix size must be {@value #SIZE}×{@value #SIZE}.
* This is not verified by this constructor, since it shall be verified by {@link Matrices}.
*
* @param matrix the matrix to copy.
*/
Matrix3(final Matrix matrix) {
for (int j=0; j<SIZE; j++) {
for (int i=0; i<SIZE; i++) {
setElement(j,i, matrix.getElement(j,i));
}
}
}
/**
* 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);
}
/*
* The 'final' modifier in following method declarations is redundant with the 'final' modifier
* in this class declaration, but we keep them as a reminder of which methods should stay final
* if this class was modified to a non-final class. Some methods should stay final because:
*
* - returning a different value would make no-sense for this class (e.g. 'getNumRow()');
* - they are invoked by a constructor or by an other method expecting this exact semantic.
*/
/**
* Returns the number of rows in this matrix, which is always {@value #SIZE} in this implementation.
*
* @return always {@value #SIZE}.
*/
@Override
public final int getNumRow() {
return SIZE;
}
/**
* Returns the number of columns in this matrix, which is always {@value #SIZE} in this implementation.
*
* @return always {@value #SIZE}.
*/
@Override
public final int getNumCol() {
return SIZE;
}
/**
* Retrieves the value at the specified row and column of this matrix.
* This method can be invoked when the matrix size or type is unknown.
* If the matrix is known to be an instance of {@code Matrix3},
* then the {@link #m00} … {@link #m22} fields can be read directly for efficiency.
*
* @param row the row index, from 0 inclusive to {@value #SIZE} exclusive.
* @param column the column index, from 0 inclusive to {@value #SIZE} exclusive.
* @return the current value at the given row and column.
*/
@Override
public final double getElement(final int row, final int column) {
if (row >= 0 && row < SIZE && column >= 0 && column < SIZE) {
switch (row*SIZE + column) {
case 0: return m00;
case 1: return m01;
case 2: return m02;
case 3: return m10;
case 4: return m11;
case 5: return m12;
case 6: return m20;
case 7: return m21;
case 8: return m22;
}
}
throw indexOutOfBounds(row, column);
}
/**
* Modifies the value at the specified row and column of this matrix.
* This method can be invoked when the matrix size or type is unknown.
* If the matrix is known to be an instance of {@code Matrix3},
* then the {@link #m00} … {@link #m22} fields can be set directly for efficiency.
*
* @param row the row index, from 0 inclusive to {@value #SIZE} exclusive.
* @param column the column index, from 0 inclusive to {@value #SIZE} exclusive.
* @param value the new value to set at the given row and column.
*/
@Override
public final void setElement(final int row, final int column, final double value) {
if (row >= 0 && row < SIZE && column >= 0 && column < SIZE) {
switch (row*SIZE + column) {
case 0: m00 = value; return;
case 1: m01 = value; return;
case 2: m02 = value; return;
case 3: m10 = value; return;
case 4: m11 = value; return;
case 5: m12 = value; return;
case 6: m20 = value; return;
case 7: m21 = value; return;
case 8: m22 = value; return;
}
}
throw indexOutOfBounds(row, column);
}
/**
* Returns all matrix elements in a flat, row-major (column indices vary fastest) array.
* The array length is 9.
*
* @return {@inheritDoc}
*/
@Override
public final double[] getElements() {
final double[] elements = new double[SIZE*SIZE];
getElements(elements);
return elements;
}
/**
* Copies the matrix elements in the given flat array.
* The array length shall be at least 9, may also be 18.
*/
@Override
final void getElements(final double[] elements) {
elements[0] = m00; elements[1] = m01; elements[2] = m02;
elements[3] = m10; elements[4] = m11; elements[5] = m12;
elements[6] = m20; elements[7] = m21; elements[8] = m22;
}
/**
* Sets all matrix elements from a flat, row-major (column indices vary fastest) array.
* The array length shall be 9.
*/
@Override
public final void setElements(final double[] elements) {
ensureLengthMatch(SIZE*SIZE, elements);
m00 = elements[0]; m01 = elements[1]; m02 = elements[2];
m10 = elements[3]; m11 = elements[4]; m12 = elements[5];
m20 = elements[6]; m21 = elements[7]; m22 = elements[8];
}
/**
* {@inheritDoc}
*
* @return {@inheritDoc}
*/
@Override
public final boolean isAffine() {
return m20 == 0 && m21 == 0 && m22 == 1;
}
/**
* {@inheritDoc}
*
* @return {@inheritDoc}
*/
@Override
public final boolean isIdentity() {
return m00 == 1 && m01 == 0 && m02 == 0 &&
m10 == 0 && m11 == 1 && m12 == 0 &&
isAffine();
}
/**
* {@inheritDoc}
*/
@Override
public void transpose() {
double swap;
swap = m01; m01 = m10; m10 = swap;
swap = m02; m02 = m20; m20 = swap;
swap = m12; m12 = m21; m21 = swap;
}
}