001:/*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2005-2006, GeoTools Project Managment Committee (PMC)
005: * (C) 2005, Institut de Recherche pour le Développement
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation;
010: * version 2.1 of the License.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: */
017:package org.geotools.referencing.operation.matrix;
018:
019:// J2SE dependencies and extensions
020:import java.io.Serializable;
021:import javax.vecmath.SingularMatrixException;
022:
023:// OpenGIS dependencies
024:import org.opengis.referencing.operation.Matrix;
025:
026:// Geotools dependencies
027:import org.geotools.resources.i18n.Errors;
028:import org.geotools.resources.i18n.ErrorKeys;
029:
030:
031:/**
032: * A matrix of fixed {@value #SIZE}×{@value #SIZE} size.
033: *
034: * @since 2.2
035: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/main/java/org/geotools/referencing/operation/matrix/Matrix2.java $
036: * @version $Id: Matrix2.java 24493 2007-02-17 17:28:12Z desruisseaux $
037: * @author Martin Desruisseaux
038: */
039:public class Matrix2 implements XMatrix, Serializable {
040: /** Serial number for interoperability with different versions. */
041: private static final long serialVersionUID = 7116561372481474290L;
042:
043: /** The matrix size, which is {@value}. */
044: public static final int SIZE = 2;
045:
046: /** The first matrix element in the first row. */
047: public double m00;
048:
049: /** The second matrix element in the first row. */
050: public double m01;
051:
052: /** The first matrix element in the second row. */
053: public double m10;
054:
055: /** The second matrix element in the second row. */
056: public double m11;
057:
058: /**
059: * Creates a new identity matrix.
060: */
061: public Matrix2() {
062: m00 = m11 = 1;
063: }
064:
065: /**
066: * Creates a new matrix initialized to the specified values.
067: */
068: public Matrix2(final double m00, final double m01,
069: final double m10, final double m11)
070: {
071: this .m00 = m00;
072: this .m01 = m01;
073: this .m10 = m10;
074: this .m11 = m11;
075: }
076:
077: /**
078: * Creates a new matrix initialized to the same value than the specified one.
079: * The specified matrix size must be {@value #SIZE}×{@value #SIZE}.
080: */
081: public Matrix2(final Matrix matrix) {
082: if (matrix.getNumRow()!=SIZE || matrix.getNumCol()!=SIZE) {
083: throw new IllegalArgumentException(Errors.format(ErrorKeys.ILLEGAL_MATRIX_SIZE));
084: }
085: m00 = matrix.getElement(0,0);
086: m01 = matrix.getElement(0,1);
087: m10 = matrix.getElement(1,0);
088: m11 = matrix.getElement(1,1);
089: }
090:
091: /**
092: * Returns the number of rows in this matrix, which is always {@value #SIZE}
093: * in this implementation.
094: */
095: public final int getNumRow() {
096: return SIZE;
097: }
098:
099: /**
100: * Returns the number of colmuns in this matrix, which is always {@value #SIZE}
101: * in this implementation.
102: */
103: public final int getNumCol() {
104: return SIZE;
105: }
106:
107: /**
108: * {@inheritDoc}
109: */
110: public final double getElement(final int row, final int col) {
111: switch (row) {
112: case 0: {
113: switch (col) {
114: case 0: return m00;
115: case 1: return m01;
116: }
117: break;
118: }
119: case 1: {
120: switch (col) {
121: case 0: return m10;
122: case 1: return m11;
123: }
124: break;
125: }
126: }
127: throw new IndexOutOfBoundsException();
128: }
129:
130: /**
131: * {@inheritDoc}
132: */
133: public final void setElement(final int row, final int col, final double value) {
134: switch (row) {
135: case 0: {
136: switch (col) {
137: case 0: m00 = value; return;
138: case 1: m01 = value; return;
139: }
140: break;
141: }
142: case 1: {
143: switch (col) {
144: case 0: m10 = value; return;
145: case 1: m11 = value; return;
146: }
147: break;
148: }
149: }
150: throw new IndexOutOfBoundsException();
151: }
152:
153: /**
154: * {@inheritDoc}
155: */
156: public final void setZero() {
157: m00 = m01 = m10 = m11 = 0;
158: }
159:
160: /**
161: * {@inheritDoc}
162: */
163: public final void setIdentity() {
164: m01 = m10 = 1;
165: m00 = m11 = 1;
166: assert isIdentity();
167: }
168:
169: /**
170: * {@inheritDoc}
171: */
172: public final boolean isIdentity() {
173: return m01==0 && m10==0 && m00==1 && m11==1;
174: }
175:
176: /**
177: * {@inheritDoc}
178: */
179: public final boolean isIdentity(double tolerance) {
180: return GeneralMatrix.isIdentity(this , tolerance);
181: }
182:
183: /**
184: * {@inheritDoc}
185: */
186: public final boolean isAffine() {
187: return m10==0 && m11==1;
188: }
189:
190: /**
191: * {@inheritDoc}
192: */
193: public final void negate() {
194: m00 = -m00;
195: m01 = -m01;
196: m10 = -m10;
197: m11 = -m11;
198: }
199:
200: /**
201: * {@inheritDoc}
202: */
203: public final void transpose() {
204: final double swap = m10;
205: m10 = m01;
206: m01 = swap;
207: }
208:
209: /**
210: * Inverts this matrix in place.
211: */
212: public final void invert() {
213: final double det = m00*m11 - m01*m10;
214: if (det == 0) {
215: throw new SingularMatrixException();
216: }
217: final double swap = m00;
218: m00 = m11 / det;
219: m11 = swap / det;
220: m10 = -m10 / det;
221: m01 = -m01 / det;
222: }
223:
224: /**
225: * {@inheritDoc}
226: */
227: public final void multiply(final Matrix matrix) {
228: final Matrix2 k;
229: if (matrix instanceof Matrix2) {
230: k = (Matrix2) matrix;
231: } else {
232: k = new Matrix2(matrix);
233: }
234: double m0, m1;
235: m0=m00; m1=m01;
236: m00 = m0*k.m00 + m1*k.m10;
237: m01 = m0*k.m01 + m1*k.m11;
238: m0=m10; m1=m11;
239: m10 = m0*k.m00 + m1*k.m10;
240: m11 = m0*k.m01 + m1*k.m11;
241: }
242:
243: /**
244: * Returns {@code true} if the specified object is of type {@code Matrix2} and
245: * all of the data members are equal to the corresponding data members in this matrix.
246: */
247: public boolean equals(final Object object) {
248: if (object!=null && object.getClass().equals(getClass())) {
249: final Matrix2 that = (Matrix2) object;
250: return Double.doubleToLongBits(this .m00) == Double.doubleToLongBits(that.m00) &&
251: Double.doubleToLongBits(this .m01) == Double.doubleToLongBits(that.m01) &&
252: Double.doubleToLongBits(this .m10) == Double.doubleToLongBits(that.m10) &&
253: Double.doubleToLongBits(this .m11) == Double.doubleToLongBits(that.m11);
254: }
255: return false;
256: }
257:
258: /**
259: * Returns a hash code value based on the data values in this object.
260: */
261: public int hashCode() {
262: return (int)((((Double.doubleToLongBits(m00) +
263: 37*Double.doubleToLongBits(m01)) +
264: 37*Double.doubleToLongBits(m10)) +
265: 37*Double.doubleToLongBits(m11)) ^
266: serialVersionUID);
267: }
268:
269: /**
270: * Returns a string representation of this matrix. The returned string is implementation
271: * dependent. It is usually provided for debugging purposes only.
272: */
273: public String toString() {
274: return GeneralMatrix.toString(this );
275: }
276:
277: /**
278: * Returns a clone of this matrix.
279: */
280: public Object clone() {
281: try {
282: return super .clone();
283: } catch (CloneNotSupportedException e) {
284: // Should not happen, since we are cloneable.
285: throw new AssertionError(e);
286: }
287: }
288:}
|