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.builder.MappedPosition;
020: import org.opengis.geometry.DirectPosition;
021: import java.util.HashMap;
022: import java.util.Iterator;
023: import java.util.List;
024: import java.util.Map;
025:
026: /**
027: * Implements methods for triangulation for {@linkplain org.geotools.referencing.operation.builder.RubberSheetBuilder
028: * RubberSheeting} transformation.
029: *
030: * @since 2.4
031: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/main/java/org/geotools/referencing/operation/builder/MapTriangulationFactory.java $
032: * @version $Id: MapTriangulationFactory.java 28966 2008-01-27 17:36:43Z acuster $
033: * @author Jan Jezek
034: */
035: class MapTriangulationFactory {
036: private final Quadrilateral quad;
037: private final List /*<MappedPosition>*/vectors;
038:
039: /**
040: *
041: * @param quad defines the area for transformation.
042: * @param vectors represents pairs of identical points.
043: * @throws TriangulationException thrown when the source points are outside the quad.
044: */
045: public MapTriangulationFactory(Quadrilateral quad,
046: List /*<MappedPosition>*/vectors)
047: throws TriangulationException {
048: this .quad = quad;
049: this .vectors = vectors;
050: }
051:
052: /**
053: * Generates map of source and destination triangles.
054: *
055: * @return Map of a source and destination triangles.
056: *
057: * @throws TriangulationException thrown when the source points are outside
058: * the quad.
059: */
060: public Map getTriangleMap() throws TriangulationException {
061: Quadrilateral mQuad = mappedQuad(quad, vectors);
062:
063: ExtendedPosition[] vertices = new ExtendedPosition[vectors
064: .size()];
065:
066: // converts MappedPosition to ExtendedPosition
067: for (int i = 0; i < vectors.size(); i++) {
068: vertices[i] = new ExtendedPosition(
069: ((MappedPosition) vectors.get(i)).getSource(),
070: ((MappedPosition) vectors.get(i)).getTarget());
071: }
072:
073: TriangulationFactory triangulator = new TriangulationFactory(
074: mQuad, vertices);
075: List taggedSourceTriangles = triangulator.getTriangulation();
076: final HashMap triangleMap = new HashMap();
077:
078: for (Iterator i = taggedSourceTriangles.iterator(); i.hasNext();) {
079: final TINTriangle sourceTriangle = (TINTriangle) i.next();
080: triangleMap.put(sourceTriangle, new TINTriangle(
081: ((ExtendedPosition) sourceTriangle.p0)
082: .getMappedposition(),
083: ((ExtendedPosition) sourceTriangle.p1)
084: .getMappedposition(),
085: ((ExtendedPosition) sourceTriangle.p2)
086: .getMappedposition()));
087: }
088:
089: return triangleMap;
090: }
091:
092: /**
093: * Generates mapped quad from destination quad and source quad. The
094: * vertices of destination quad are calculated from source quad and
095: * difference of nearest pair of identical points.
096: *
097: * @param sourceQuad the quad that defines the area for triangulating.
098: * @param vectors of identical points (MappedCoordinates).
099: *
100: * @return destination quad
101: */
102: private Quadrilateral mappedQuad(Quadrilateral sourceQuad,
103: List vectors) {
104: if (vectors.isEmpty()) {
105: return (Quadrilateral) sourceQuad.clone();
106: }
107:
108: //super.setMappedPositions(vectors);
109: MappedPosition[] mappedVertices = new MappedPosition[4];
110:
111: for (int i = 0; i < mappedVertices.length; i++) {
112: mappedVertices[i] = generateCoordFromNearestOne(sourceQuad
113: .getPoints()[i], vectors);
114: }
115:
116: return new Quadrilateral(new ExtendedPosition(mappedVertices[0]
117: .getSource(), mappedVertices[0].getTarget()),
118: new ExtendedPosition(mappedVertices[1].getSource(),
119: mappedVertices[1].getTarget()),
120: new ExtendedPosition(mappedVertices[2].getSource(),
121: mappedVertices[2].getTarget()),
122: new ExtendedPosition(mappedVertices[3].getSource(),
123: mappedVertices[3].getTarget()));
124: }
125:
126: /**
127: * Calculate the destination position for the quad vertex as source
128: * position using the difference between nearest source and destination
129: * point pair.
130: *
131: * @param x the original coordinate.
132: * @param vertices List of the MappedPosition.
133: *
134: * @return MappedPosition from the original and new coordinate, so the
135: * difference between them is the same as for the nearest one
136: * MappedPosition. It is used for calculating destination quad.
137: */
138: protected MappedPosition generateCoordFromNearestOne(
139: DirectPosition x, List /*<MappedPosition>*/vertices) {
140: MappedPosition nearestOne = nearestMappedCoordinate(x, vertices);
141:
142: double dstX = x.getCoordinates()[0]
143: + (nearestOne.getTarget().getCoordinates()[0] - nearestOne
144: .getSource().getCoordinates()[0]);
145: double dstY = x.getCoordinates()[1]
146: + (nearestOne.getTarget().getCoordinates()[1] - nearestOne
147: .getSource().getCoordinates()[1]);
148: DirectPosition dst = new DirectPosition2D(nearestOne
149: .getTarget().getCoordinateReferenceSystem(), dstX, dstY);
150:
151: return new MappedPosition(x, dst);
152: }
153:
154: /**
155: * Returns the nearest MappedPosition to specified point P.
156: *
157: * @param dp P point.
158: * @param vertices the List of MappedCoordinates.
159: *
160: * @return the MappedPosition to the x Coordinate.
161: */
162: protected MappedPosition nearestMappedCoordinate(DirectPosition dp,
163: List /*<MappedPosition>*/vertices) {
164: DirectPosition2D x = new DirectPosition2D(dp);
165:
166: // Assert.isTrue(vectors.size() > 0);
167: MappedPosition nearestOne = (MappedPosition) vertices.get(0);
168:
169: for (Iterator i = vertices.iterator(); i.hasNext();) {
170: MappedPosition candidate = (MappedPosition) i.next();
171:
172: if (((DirectPosition2D) candidate.getSource()).distance(x
173: .toPoint2D()) < ((DirectPosition2D) nearestOne
174: .getSource()).distance(x.toPoint2D())) {
175: nearestOne = candidate;
176: }
177: }
178:
179: return nearestOne;
180: }
181: }
|