001: /*
002: * Geotools2 - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002-2005, Geotools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.referencing.operation.builder;
017:
018: import org.geotools.geometry.DirectPosition2D;
019: import org.geotools.referencing.operation.transform.AbstractMathTransform;
020: import org.opengis.referencing.operation.MathTransform;
021: import org.opengis.referencing.operation.MathTransform2D;
022: import org.opengis.referencing.operation.TransformException;
023: import org.opengis.geometry.DirectPosition;
024: import java.awt.geom.AffineTransform;
025: import java.awt.geom.Point2D;
026: import java.util.ArrayList;
027: import java.util.HashMap;
028: import java.util.Iterator;
029:
030: /**
031: * This provides the transformation method based on RubberSheeting (also
032: * known as Billinear interpolated transformation) The class is accessed
033: * {@linkplain org.geotools.referencing.operation.builder.RubberSheetBuilder
034: * RubberSheetBuilder}. More about Rubber Sheet transformation can be seen <a
035: * href =
036: * "http://planner.t.u-tokyo.ac.jp/member/fuse/rubber_sheeting.pdf">here</a>.
037: *
038: * @since 2.4
039: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/main/java/org/geotools/referencing/operation/builder/RubberSheetTransform.java $
040: * @version $Id: RubberSheetTransform.java 28966 2008-01-27 17:36:43Z acuster $
041: * @author Jan Jezek
042: *
043: * @todo Consider moving this class to the {@linkplain
044: * org.geotools.referencing.operation.transform} package.
045: */
046: class RubberSheetTransform extends AbstractMathTransform implements
047: MathTransform2D {
048: /**
049: * The HashMap where the keys are the original {@link
050: * Polygon} and values are {@link
051: * #org.opengis.referencing.operation.MathTransform}.
052: */
053: private HashMap trianglesToKeysMap;
054:
055: /**
056: * Constructs the RubberSheetTransform.
057: *
058: * @param trianglesToAffineTransform The HashMap where the keys are the original
059: * {@linkplain org.geotools.referencing.operation.builder.algorithm.TINTriangle}
060: * and values are {@linkplain org.opengis.referencing.operation.MathTransform}.
061: */
062: public RubberSheetTransform(HashMap trianglesToAffineTransform) {
063: this .trianglesToKeysMap = trianglesToAffineTransform;
064: }
065:
066: /**
067: * Gets the dimension of input points, which is 2.
068: *
069: * @return dimension of input points
070: */
071: public final int getSourceDimensions() {
072: return 2;
073: }
074:
075: /**
076: * Gets the dimension of output points, which is 2.
077: *
078: * @return imension of output points
079: */
080: public final int getTargetDimensions() {
081: return 2;
082: }
083:
084: /**
085: * The method for generating a Map of Triangles mapped to ArrayList
086: * of points within this triangle.
087: *
088: * @param arraySrcPts of source points
089: *
090: * @return HashMap of wher keys are triangles and values are ArrayLists of
091: * points within these triangles
092: */
093: private HashMap mapTrianglesToPoints(ArrayList arraySrcPts) {
094: HashMap trianglesToPoints = new HashMap();
095:
096: for (Iterator i = trianglesToKeysMap.keySet().iterator(); i
097: .hasNext();) {
098: TINTriangle triangle = (TINTriangle) i.next();
099: ArrayList pointsInTriangle = new ArrayList();
100:
101: for (Iterator k = arraySrcPts.iterator(); k.hasNext();) {
102: DirectPosition p = ((DirectPosition) k.next());
103:
104: if (triangle.containsOrIsVertex(p)) {
105: pointsInTriangle.add(p);
106:
107: //arraySrcPts.remove(p);
108: }
109: }
110:
111: trianglesToPoints.put(triangle, pointsInTriangle);
112: }
113:
114: return trianglesToPoints;
115: }
116:
117: /* (non-Javadoc)
118: * @see org.opengis.referencing.operation.MathTransform#transform(double[], int, double[], int, int)
119: */
120: public void transform(double[] srcPts, int srcOff,
121: final double[] dstPts, int dstOff, int numPts)
122: throws TransformException {
123: ExtendedPosition ptSrc = null;
124:
125: ArrayList arraySrcPts = new ArrayList();
126:
127: while (--numPts >= 0) {
128: final DirectPosition coSrc = new DirectPosition2D(
129: srcPts[srcOff++], srcPts[srcOff++]);
130: DirectPosition coDst = new DirectPosition2D(0, 0);
131: ptSrc = new ExtendedPosition(coSrc, coDst);
132:
133: arraySrcPts.add(ptSrc);
134: }
135:
136: HashMap trianglestoPoints = mapTrianglesToPoints((ArrayList) arraySrcPts);
137:
138: // Circle goes trough each triangle
139: for (Iterator k = trianglestoPoints.keySet().iterator(); k
140: .hasNext();) {
141: TINTriangle triangle = (TINTriangle) k.next();
142: AffineTransform AT = (AffineTransform) trianglesToKeysMap
143: .get(triangle);
144:
145: // Circle for transforming points within this triangle
146: for (Iterator j = ((ArrayList) trianglestoPoints
147: .get(triangle)).iterator(); j.hasNext();) {
148: ExtendedPosition co = (ExtendedPosition) j.next();
149: Point2D ptS = new Point2D.Double(co.x, co.y);
150: Point2D ptD = new Point2D.Double();
151: AT.transform(ptS, ptD);
152:
153: DirectPosition coDst = new DirectPosition2D(co
154: .getCoordinateReferenceSystem(), ptD.getX(),
155: ptD.getY());
156: co.setMappedposition(coDst);
157: }
158: }
159:
160: for (Iterator j = arraySrcPts.iterator(); j.hasNext();) {
161: ExtendedPosition mc = (ExtendedPosition) j.next();
162: dstPts[dstOff++] = mc.getMappedposition().getCoordinates()[0];
163: dstPts[dstOff++] = mc.getMappedposition().getCoordinates()[1];
164: }
165: }
166:
167: /**
168: * String representation.
169: *
170: * @return String expression of the triangle and its affine transform
171: * parameters
172: *
173: * @todo This method doesn't meet the {@link MathTransform#toString}
174: * constract, which should uses Well Known Text (WKT) format as much
175: * as possible.
176: */
177: public String toString() {
178: final String lineSeparator = System.getProperty(
179: "line.separator", "\n");
180: final StringBuffer buffer = new StringBuffer();
181:
182: for (final Iterator i = trianglesToKeysMap.keySet().iterator(); i
183: .hasNext();) {
184: TINTriangle trian = (TINTriangle) i.next();
185: MathTransform mt = (MathTransform) trianglesToKeysMap
186: .get(trian);
187: buffer.append(trian.toString());
188: buffer.append(lineSeparator);
189: buffer.append(mt.toString());
190: buffer.append(lineSeparator);
191: }
192:
193: return buffer.toString();
194: }
195: }
|