001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: *
005: * (C) 2003-2006, Geotools Project Managment Committee (PMC)
006: * (C) 2001, 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.awt.geom.Point2D;
023: import java.util.prefs.Preferences;
024:
025: // OpenGIS dependencies
026: import org.opengis.parameter.ParameterValueGroup;
027: import org.opengis.referencing.operation.MathTransform;
028: import org.opengis.referencing.operation.MathTransform2D;
029: import org.opengis.referencing.operation.Matrix;
030: import org.opengis.referencing.operation.NoninvertibleTransformException;
031: import org.opengis.geometry.DirectPosition;
032: import org.opengis.geometry.MismatchedDimensionException;
033:
034: // Geotools dependencies
035: import org.geotools.geometry.GeneralDirectPosition;
036: import org.geotools.referencing.operation.LinearTransform;
037: import org.geotools.referencing.operation.matrix.Matrix2;
038: import org.geotools.referencing.operation.matrix.Matrix3;
039: import org.geotools.referencing.operation.matrix.XAffineTransform;
040: import org.geotools.referencing.wkt.Formatter;
041: import org.geotools.referencing.wkt.Symbols;
042: import org.geotools.resources.Formattable;
043: import org.geotools.resources.i18n.Errors;
044: import org.geotools.resources.i18n.ErrorKeys;
045:
046: /**
047: * Transforms two-dimensional coordinate points using an {@link AffineTransform}.
048: *
049: * @since 2.0
050: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/main/java/org/geotools/referencing/operation/transform/AffineTransform2D.java $
051: * @version $Id: AffineTransform2D.java 24925 2007-03-27 20:12:08Z jgarnett $
052: * @author Martin Desruisseaux
053: */
054: final class AffineTransform2D extends XAffineTransform implements
055: MathTransform2D, LinearTransform, Formattable {
056: /**
057: * Serial number for interoperability with different versions.
058: */
059: private static final long serialVersionUID = -5299837898367149069L;
060:
061: /**
062: * The inverse transform. This field
063: * will be computed only when needed.
064: */
065: private transient AffineTransform2D inverse;
066:
067: /**
068: * Constructs an affine transform.
069: */
070: protected AffineTransform2D(final AffineTransform transform) {
071: super (transform);
072: }
073:
074: /**
075: * Throws an {@link UnsupportedOperationException} when a mutable method
076: * is invoked, since {@code AffineTransform2D} must be immutable.
077: */
078: protected void checkPermission() {
079: throw new UnsupportedOperationException(Errors
080: .format(ErrorKeys.UNMODIFIABLE_AFFINE_TRANSFORM));
081: }
082:
083: /**
084: * Returns the matrix elements as a group of parameters values. The number of parameters
085: * depends on the matrix size. Only matrix elements different from their default value
086: * will be included in this group.
087: *
088: * @return A copy of the parameter values for this math transform.
089: */
090: public ParameterValueGroup getParameterValues() {
091: return ProjectiveTransform.getParameterValues(getMatrix());
092: }
093:
094: /**
095: * Gets the dimension of input points.
096: */
097: public int getSourceDimensions() {
098: return 2;
099: }
100:
101: /**
102: * Gets the dimension of output points.
103: */
104: public int getTargetDimensions() {
105: return 2;
106: }
107:
108: /**
109: * Transforms the specified {@code ptSrc} and stores the result in {@code ptDst}.
110: */
111: public DirectPosition transform(final DirectPosition ptSrc,
112: DirectPosition ptDst) {
113: if (ptDst == null) {
114: ptDst = new GeneralDirectPosition(2);
115: } else {
116: final int dimension = ptDst.getDimension();
117: if (dimension != 2) {
118: throw new MismatchedDimensionException(Errors.format(
119: ErrorKeys.MISMATCHED_DIMENSION_$3, "ptDst",
120: new Integer(dimension), new Integer(2)));
121: }
122: }
123: final double[] array = ptSrc.getCoordinates();
124: transform(array, 0, array, 0, 1);
125: ptDst.setOrdinate(0, array[0]);
126: ptDst.setOrdinate(1, array[1]);
127: return ptDst;
128: }
129:
130: /**
131: * Returns this transform as an affine transform matrix.
132: */
133: public Matrix getMatrix() {
134: return new Matrix3(this );
135: }
136:
137: /**
138: * Gets the derivative of this transform at a point. For an affine transform,
139: * the derivative is the same everywhere.
140: */
141: public Matrix derivative(final Point2D point) {
142: return new Matrix2(getScaleX(), getShearX(), getShearY(),
143: getScaleY());
144: }
145:
146: /**
147: * Gets the derivative of this transform at a point.
148: * For an affine transform, the derivative is the
149: * same everywhere.
150: */
151: public Matrix derivative(final DirectPosition point) {
152: return derivative((Point2D) null);
153: }
154:
155: /**
156: * Creates the inverse transform of this object.
157: */
158: public MathTransform inverse()
159: throws NoninvertibleTransformException {
160: if (inverse == null) {
161: if (isIdentity()) {
162: inverse = this ;
163: } else
164: try {
165: synchronized (this ) {
166: inverse = new AffineTransform2D(createInverse());
167: inverse.inverse = this ;
168: }
169: } catch (java.awt.geom.NoninvertibleTransformException exception) {
170: throw new NoninvertibleTransformException(exception
171: .getLocalizedMessage(), exception);
172: }
173: }
174: return inverse;
175: }
176:
177: /**
178: * Format the inner part of a
179: * <A HREF="http://geoapi.sourceforge.net/snapshot/javadoc/org/opengis/referencing/doc-files/WKT.html"><cite>Well
180: * Known Text</cite> (WKT)</A> element.
181: *
182: * @param formatter The formatter to use.
183: * @return The WKT element name.
184: */
185: public String formatWKT(final Formatter formatter) {
186: final ParameterValueGroup parameters = getParameterValues();
187: formatter.append(formatter.getName(parameters.getDescriptor()));
188: formatter.append(parameters);
189: return "PARAM_MT";
190: }
191:
192: /**
193: * Returns the WKT for this transform.
194: */
195: public String toWKT() {
196: int indentation = 2;
197: try {
198: indentation = Preferences.userNodeForPackage(
199: Formattable.class).getInt("Indentation",
200: indentation);
201: } catch (SecurityException ignore) {
202: // Ignore. Will fallback on the default indentation.
203: }
204: final Formatter formatter = new Formatter(Symbols.DEFAULT,
205: indentation);
206: formatter.append(this );
207: return formatter.toString();
208: }
209:
210: /**
211: * Returns the WKT representation of this transform.
212: */
213: public String toString() {
214: return toWKT();
215: }
216: }
|