001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: *
005: * (C) 2003-2006, Geotools Project Managment Committee (PMC)
006: * (C) 2002, Institut de Recherche pour le Développement
007: *
008: * This library is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU Lesser General Public
010: * License as published by the Free Software Foundation; either
011: * version 2.1 of the License, or (at your option) any later version.
012: *
013: * This library is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
016: * Lesser General Public License for more details.
017: */
018: package org.geotools.referencing.operation.transform;
019:
020: // J2SE dependencies
021: import java.awt.geom.AffineTransform;
022: import java.io.Serializable;
023:
024: // OpenGIS dependencies
025: import org.opengis.parameter.ParameterDescriptorGroup;
026: import org.opengis.parameter.ParameterValueGroup;
027: import org.opengis.referencing.operation.Matrix;
028: import org.opengis.referencing.operation.MathTransform;
029: import org.opengis.referencing.operation.TransformException;
030: import org.opengis.geometry.DirectPosition;
031:
032: // Geotools dependencies
033: import org.geotools.geometry.GeneralDirectPosition;
034: import org.geotools.referencing.operation.LinearTransform;
035: import org.geotools.referencing.operation.matrix.MatrixFactory;
036:
037: /**
038: * The identity transform. The data are only copied without any transformation. This class is
039: * used for identity transform of dimension greater than 2. For 1D and 2D identity transforms,
040: * {@link LinearTransform1D} and {@link java.awt.geom.AffineTransform} already provide their
041: * own optimisations.
042: *
043: * @since 2.0
044: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/main/java/org/geotools/referencing/operation/transform/IdentityTransform.java $
045: * @version $Id: IdentityTransform.java 24925 2007-03-27 20:12:08Z jgarnett $
046: * @author Martin Desruisseaux
047: */
048: public class IdentityTransform extends AbstractMathTransform implements
049: LinearTransform, Serializable {
050: /**
051: * Serial number for interoperability with different versions.
052: */
053: private static final long serialVersionUID = -5339040282922138164L;
054:
055: /**
056: * The input and output dimension.
057: */
058: private final int dimension;
059:
060: /**
061: * Identity transforms for dimensions ranging from to 0 to 7.
062: * Elements in this array will be created only when first requested.
063: */
064: private static final LinearTransform[] POOL = new LinearTransform[8];
065:
066: /**
067: * Constructs an identity transform of the specified dimension.
068: */
069: protected IdentityTransform(final int dimension) {
070: this .dimension = dimension;
071: }
072:
073: /**
074: * Constructs an identity transform of the specified dimension.
075: */
076: public static LinearTransform create(final int dimension) {
077: // No need to synchronize; not a big deal in a few objects are duplicated.
078: LinearTransform candidate;
079: if (dimension < POOL.length) {
080: candidate = POOL[dimension];
081: if (candidate != null) {
082: return candidate;
083: }
084: }
085: switch (dimension) {
086: case 1:
087: candidate = LinearTransform1D.IDENTITY;
088: break;
089: case 2:
090: candidate = new AffineTransform2D(new AffineTransform());
091: break;
092: default:
093: candidate = new IdentityTransform(dimension);
094: break;
095: }
096: if (dimension < POOL.length) {
097: POOL[dimension] = candidate;
098: }
099: return candidate;
100: }
101:
102: /**
103: * Tests whether this transform does not move any points.
104: * This implementation always returns {@code true}.
105: */
106: public boolean isIdentity() {
107: return true;
108: }
109:
110: /**
111: * Tests whether this transform does not move any points.
112: * This implementation always returns {@code true}.
113: */
114: public boolean isIdentity(double tolerance) {
115: return true;
116: }
117:
118: /**
119: * Gets the dimension of input points.
120: */
121: public int getSourceDimensions() {
122: return dimension;
123: }
124:
125: /**
126: * Gets the dimension of output points.
127: */
128: public int getTargetDimensions() {
129: return dimension;
130: }
131:
132: /**
133: * Returns the parameter descriptors for this math transform.
134: */
135: public ParameterDescriptorGroup getParameterDescriptors() {
136: return ProjectiveTransform.ProviderAffine.PARAMETERS;
137: }
138:
139: /**
140: * Returns the matrix elements as a group of parameters values.
141: *
142: * @return A copy of the parameter values for this math transform.
143: */
144: public ParameterValueGroup getParameterValues() {
145: return ProjectiveTransform.getParameterValues(getMatrix());
146: }
147:
148: /**
149: * Returns a copy of the identity matrix.
150: */
151: public Matrix getMatrix() {
152: return MatrixFactory.create(dimension + 1);
153: }
154:
155: /**
156: * Gets the derivative of this transform at a point. For an identity transform,
157: * the derivative is the same everywhere.
158: */
159: public Matrix derivative(final DirectPosition point) {
160: return MatrixFactory.create(dimension);
161: }
162:
163: /**
164: * Copies the values from {@code ptSrc} to {@code ptDst}.
165: * Overrides the super-class method for performance reason.
166: *
167: * @since 2.2
168: */
169: public DirectPosition transform(final DirectPosition ptSrc,
170: final DirectPosition ptDst) {
171: if (ptSrc.getDimension() == dimension) {
172: if (ptDst == null) {
173: return new GeneralDirectPosition(ptSrc);
174: }
175: if (ptDst.getDimension() == dimension) {
176: for (int i = 0; i < dimension; i++) {
177: ptDst.setOrdinate(i, ptSrc.getOrdinate(i));
178: }
179: return ptDst;
180: }
181: }
182: try {
183: // The super class will take care of throwing the MismatchedDimensionException.
184: return super .transform(ptSrc, ptDst);
185: } catch (TransformException e) {
186: throw new AssertionError(e); // Should never happen.
187: }
188: }
189:
190: /**
191: * Transforms an array of floating point coordinates by this transform.
192: */
193: public void transform(final float[] srcPts, int srcOff,
194: final float[] dstPts, int dstOff, int numPts) {
195: System.arraycopy(srcPts, srcOff, dstPts, dstOff, numPts
196: * dimension);
197: }
198:
199: /**
200: * Transforms an array of floating point coordinates by this transform.
201: */
202: public void transform(final double[] srcPts, int srcOff,
203: final double[] dstPts, int dstOff, int numPts) {
204: System.arraycopy(srcPts, srcOff, dstPts, dstOff, numPts
205: * dimension);
206: }
207:
208: /**
209: * Returns the inverse transform of this object, which
210: * is this transform itself
211: */
212: public MathTransform inverse() {
213: return this ;
214: }
215:
216: /**
217: * Returns a hash value for this transform.
218: * This value need not remain consistent between
219: * different implementations of the same class.
220: */
221: public int hashCode() {
222: return (int) serialVersionUID + dimension;
223: }
224:
225: /**
226: * Compares the specified object with
227: * this math transform for equality.
228: */
229: public boolean equals(final Object object) {
230: if (object == this ) {
231: // Slight optimization
232: return true;
233: }
234: if (super .equals(object)) {
235: final IdentityTransform that = (IdentityTransform) object;
236: return this .dimension == that.dimension;
237: }
238: return false;
239: }
240: }
|