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.opengis.referencing.crs.CoordinateReferenceSystem;
020: import org.opengis.geometry.DirectPosition;
021: import java.util.ArrayList;
022: import java.util.Iterator;
023: import java.util.List;
024:
025: /**
026: * A triangle, with special methods for use with RubberSheetTransform.
027: *
028: * @since 2.4
029: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/main/java/org/geotools/referencing/operation/builder/TINTriangle.java $
030: * @version $Id: TINTriangle.java 28966 2008-01-27 17:36:43Z acuster $
031: * @author Jan Jezek
032: *
033: */
034: class TINTriangle extends Polygon {
035: /** The first vertex. */
036: public DirectPosition p0;
037:
038: /** The second vertex. */
039: public DirectPosition p1;
040:
041: /** The third vertex. */
042: public DirectPosition p2;
043: private final List /*<TINTriangle>*/adjacentTriangles = new ArrayList();
044:
045: /**
046: * Creates a Triangle.
047: * @param p0 one vertex
048: * @param p1 another vertex
049: * @param p2 another vertex
050: */
051: protected TINTriangle(DirectPosition p0, DirectPosition p1,
052: DirectPosition p2) {
053: super (new DirectPosition[] { p0, p1, p2, p0 });
054: this .p0 = p0;
055: this .p1 = p1;
056: this .p2 = p2;
057: }
058:
059: /**
060: * Returns the CircumCicle of the this TINTriangle.
061: *
062: * @return Returns the CircumCicle of the this TINTriangle
063: */
064: protected Circle getCircumCicle() {
065: //DirectPosition center = new DirectPosition2D();
066: List reducedVertices = reduce();
067:
068: CoordinateReferenceSystem crs = ((DirectPosition) reducedVertices
069: .get(1)).getCoordinateReferenceSystem();
070:
071: double x1 = ((DirectPosition) reducedVertices.get(1))
072: .getCoordinates()[0];
073: double y1 = ((DirectPosition) reducedVertices.get(1))
074: .getCoordinates()[1];
075:
076: double x2 = ((DirectPosition) reducedVertices.get(2))
077: .getCoordinates()[0];
078: double y2 = ((DirectPosition) reducedVertices.get(2))
079: .getCoordinates()[1];
080:
081: // Calculation of Circumcicle center
082: double t = (0.5 * (((x1 * x1) + (y1 * y1)) - (x1 * x2) - (y1 * y2)))
083: / ((y1 * x2) - (x1 * y2));
084:
085: //t = Math.abs(t);
086: DirectPosition2D center = new DirectPosition2D(crs, (x2 / 2)
087: - (t * y2) + p0.getCoordinates()[0], (y2 / 2)
088: + (t * x2) + p0.getCoordinates()[1]);
089:
090: return new Circle(center.getPosition(), center
091: .distance(new DirectPosition2D(p0)));
092: }
093:
094: /**
095: * Returns the three triangles that are created by splitting this
096: * TINTriangle at a newVertex.
097: *
098: * @param newVertex the split point (must be inside triangle).
099: *
100: * @return three Triangles created by splitting this TINTriangle at a
101: * newVertex.
102: */
103: public List subTriangles(DirectPosition newVertex) {
104: ArrayList triangles = new ArrayList();
105: TINTriangle trigA = new TINTriangle(p0, p1, newVertex);
106: TINTriangle trigB = new TINTriangle(p1, p2, newVertex);
107: TINTriangle trigC = new TINTriangle(p2, p0, newVertex);
108:
109: // sub triangles are adjacent to each other.
110: try {
111: trigA.addAdjacentTriangle(trigB);
112: trigA.addAdjacentTriangle(trigC);
113:
114: trigB.addAdjacentTriangle(trigA);
115: trigB.addAdjacentTriangle(trigC);
116:
117: trigC.addAdjacentTriangle(trigA);
118: trigC.addAdjacentTriangle(trigB);
119: } catch (TriangulationException e) {
120: // should never reach here so we can ignore.
121: }
122:
123: //last adjacent triangle of each sub triangle is one of adjacent triangle of this triangle.
124: trigA.tryToAddAdjacent(this .getAdjacentTriangles());
125: trigB.tryToAddAdjacent(this .getAdjacentTriangles());
126: trigC.tryToAddAdjacent(this .getAdjacentTriangles());
127:
128: triangles.add(trigA);
129: triangles.add(trigB);
130: triangles.add(trigC);
131:
132: Iterator i = this .getAdjacentTriangles().iterator();
133:
134: while (i.hasNext()) {
135: TINTriangle trig = (TINTriangle) i.next();
136: trig.removeAdjacent(this );
137: }
138:
139: return triangles;
140: }
141:
142: /**
143: * Tries to add {@code adjacent} triangles. Before adding they are checked
144: * whether they are really adjacent or not and whether they are not already known.
145: * @param adjacents triangles to be added
146: * @return number of successfully added triangles
147: */
148: protected int tryToAddAdjacent(List adjacents) {
149: Iterator i = adjacents.iterator();
150: int count = 0;
151:
152: while (i.hasNext()) {
153: try {
154: TINTriangle candidate = (TINTriangle) i.next();
155:
156: if (candidate.isAdjacent(this )
157: && !this .adjacentTriangles.contains(candidate)) {
158: this .addAdjacentTriangle(candidate);
159: }
160:
161: if (candidate.isAdjacent(this )
162: && !candidate.adjacentTriangles.contains(this )) {
163: //this.addAdjacentTriangle(candidate);
164: candidate.addAdjacentTriangle(this );
165: count++;
166: }
167: } catch (TriangulationException e) {
168: // should never reach here so we can ignore
169: }
170: }
171:
172: return count;
173: }
174:
175: /**
176: * Adds adjacent triangles.
177: * @param adjacent triangles to be added
178: * @throws TriangulationException if triangle is not adjacent
179: * @return true if the triangle is adjacent
180: */
181: protected boolean addAdjacentTriangle(TINTriangle adjacent)
182: throws TriangulationException {
183: if (isAdjacent(adjacent)) {
184: adjacentTriangles.add(adjacent);
185:
186: return true;
187: }
188:
189: return false;
190: }
191:
192: /**
193: * Checks whether triangle is adjacent.
194: * @param adjacent triangle to be tested
195: * @return true if triangle is adjacent
196: * @throws TriangulationException if
197: */
198: private boolean isAdjacent(TINTriangle adjacent)
199: throws TriangulationException {
200: int identicalVertices = 0;
201:
202: if (adjacent.hasVertex(p0)) {
203: identicalVertices++;
204: }
205:
206: if (adjacent.hasVertex(p1)) {
207: identicalVertices++;
208: }
209:
210: if (adjacent.hasVertex(p2)) {
211: identicalVertices++;
212: }
213:
214: if (identicalVertices == 3) {
215: throw new TriangulationException("Same triangle");
216: }
217:
218: if (identicalVertices == 2) {
219: return true;
220: }
221:
222: return false;
223: }
224:
225: /**
226: * Returns adjacent triangles
227: * @return adjacent triangles
228: */
229: public List getAdjacentTriangles() {
230: return adjacentTriangles;
231: }
232:
233: /**
234: * Removes adjacent triangles
235: * @param remAdjacent
236: */
237: protected void removeAdjacent(TINTriangle remAdjacent) {
238: adjacentTriangles.remove(remAdjacent);
239: }
240: }
|