1 /*
2  * Copyright (c) 2016 Vivid Solutions.
3  *
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
7  * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
8  * and the Eclipse Distribution License is available at
9  *
10  * http://www.eclipse.org/org/documents/edl-v10.php.
11  */
12 
13 package org.locationtech.jts.triangulate.quadedge;
14 
15 import java.util.ArrayList;
16 import java.util.Arrays;
17 import java.util.List;
18 
19 import org.locationtech.jts.algorithm.PointLocation;
20 import org.locationtech.jts.geom.Coordinate;
21 import org.locationtech.jts.geom.Geometry;
22 import org.locationtech.jts.geom.GeometryFactory;
23 import org.locationtech.jts.geom.LineSegment;
24 import org.locationtech.jts.geom.LinearRing;
25 import org.locationtech.jts.geom.Polygon;
26 
27 
28 /**
29  * Models a triangle formed from {@link QuadEdge}s in a {@link QuadEdgeSubdivision}
30  * which forms a triangulation. The class provides methods to access the
31  * topological and geometric properties of the triangle and its neighbours in
32  * the triangulation. Triangle vertices are ordered in CCW orientation in the
33  * structure.
34  * <p>
35  * QuadEdgeTriangles support having an external data attribute attached to them.
36  * Alternatively, this class can be subclassed and attributes can
37  * be defined in the subclass.  Subclasses will need to define
38  * their own <tt>BuilderVisitor</tt> class
39  * and <tt>createOn</tt> method.
40  *
41  * @author Martin Davis
42  * @version 1.0
43  */
44 public class QuadEdgeTriangle
45 {
46 	/**
47 	 * Creates {@link QuadEdgeTriangle}s for all facets of a
48 	 * {@link QuadEdgeSubdivision} representing a triangulation.
49 	 * The <tt>data</tt> attributes of the {@link QuadEdge}s in the subdivision
50 	 * will be set to point to the triangle which contains that edge.
51 	 * This allows tracing the neighbour triangles of any given triangle.
52 	 *
53 	 * @param subdiv
54 	 * 				the QuadEdgeSubdivision to create the triangles on.
55 	 * @return a List of the created QuadEdgeTriangles
56 	 */
createOn(QuadEdgeSubdivision subdiv)57 	public static List createOn(QuadEdgeSubdivision subdiv)
58 	{
59 		QuadEdgeTriangleBuilderVisitor visitor = new QuadEdgeTriangleBuilderVisitor();
60 		subdiv.visitTriangles(visitor, false);
61 		return visitor.getTriangles();
62 	}
63 
64 	/**
65 	 * Tests whether the point pt is contained in the triangle defined by 3
66 	 * {@link Vertex}es.
67 	 *
68 	 * @param tri
69 	 *          an array containing at least 3 Vertexes
70 	 * @param pt
71 	 *          the point to test
72 	 * @return true if the point is contained in the triangle
73 	 */
contains(Vertex[] tri, Coordinate pt)74 	public static boolean contains(Vertex[] tri, Coordinate pt) {
75 		Coordinate[] ring = new Coordinate[] { tri[0].getCoordinate(),
76 				tri[1].getCoordinate(), tri[2].getCoordinate(), tri[0].getCoordinate() };
77 		return PointLocation.isInRing(pt, ring);
78 	}
79 
80 	/**
81 	 * Tests whether the point pt is contained in the triangle defined by 3
82 	 * {@link QuadEdge}es.
83 	 *
84 	 * @param tri
85 	 *          an array containing at least 3 QuadEdges
86 	 * @param pt
87 	 *          the point to test
88 	 * @return true if the point is contained in the triangle
89 	 */
contains(QuadEdge[] tri, Coordinate pt)90 	public static boolean contains(QuadEdge[] tri, Coordinate pt) {
91 		Coordinate[] ring = new Coordinate[] { tri[0].orig().getCoordinate(),
92 				tri[1].orig().getCoordinate(), tri[2].orig().getCoordinate(),
93 				tri[0].orig().getCoordinate() };
94 		return PointLocation.isInRing(pt, ring);
95 	}
96 
toPolygon(Vertex[] v)97 	public static Geometry toPolygon(Vertex[] v) {
98 		Coordinate[] ringPts = new Coordinate[] { v[0].getCoordinate(),
99 				v[1].getCoordinate(), v[2].getCoordinate(), v[0].getCoordinate() };
100 		GeometryFactory fact = new GeometryFactory();
101 		LinearRing ring = fact.createLinearRing(ringPts);
102 		Polygon tri = fact.createPolygon(ring);
103 		return tri;
104 	}
105 
toPolygon(QuadEdge[] e)106 	public static Geometry toPolygon(QuadEdge[] e) {
107 		Coordinate[] ringPts = new Coordinate[] { e[0].orig().getCoordinate(),
108 				e[1].orig().getCoordinate(), e[2].orig().getCoordinate(),
109 				e[0].orig().getCoordinate() };
110 		GeometryFactory fact = new GeometryFactory();
111 		LinearRing ring = fact.createLinearRing(ringPts);
112 		Polygon tri = fact.createPolygon(ring);
113 		return tri;
114 	}
115 
116 	/**
117 	 * Finds the next index around the triangle. Index may be an edge or vertex
118 	 * index.
119 	 *
120 	 * @param index
121 	 * @return the next index
122 	 */
nextIndex(int index)123 	public static int nextIndex(int index) {
124 		return index = (index + 1) % 3;
125 	}
126 
127 	private QuadEdge[] edge;
128 	private Object data;
129 
130 	/**
131 	 * Creates a new triangle from the given edges.
132 	 *
133 	 * @param edge an array of the edges of the triangle in CCW order
134 	 */
QuadEdgeTriangle(QuadEdge[] edge)135 	public QuadEdgeTriangle(QuadEdge[] edge) {
136 		this.edge = (QuadEdge[]) Arrays.copyOf(edge, edge.length);
137 		// link the quadedges back to this triangle
138 		for (int i = 0; i < 3; i++) {
139 			edge[i].setData(this);
140 		}
141 	}
142 
143   /**
144    * Sets the external data value for this triangle.
145    *
146    * @param data an object containing external data
147    */
setData(Object data)148   public void setData(Object data) {
149       this.data = data;
150   }
151 
152   /**
153    * Gets the external data value for this triangle.
154    *
155    * @return the data object
156    */
getData()157   public Object getData() {
158       return data;
159   }
160 
kill()161 	public void kill() {
162 		edge = null;
163 	}
164 
isLive()165 	public boolean isLive() {
166 		return edge != null;
167 	}
168 
getEdges()169 	public QuadEdge[] getEdges() {
170 		return edge;
171 	}
172 
getEdge(int i)173 	public QuadEdge getEdge(int i) {
174 		return edge[i];
175 	}
176 
getVertex(int i)177 	public Vertex getVertex(int i) {
178 		return edge[i].orig();
179 	}
180 
181 	/**
182 	 * Gets the vertices for this triangle.
183 	 *
184 	 * @return a new array containing the triangle vertices
185 	 */
getVertices()186 	public Vertex[] getVertices() {
187 		Vertex[] vert = new Vertex[3];
188 		for (int i = 0; i < 3; i++) {
189 			vert[i] = getVertex(i);
190 		}
191 		return vert;
192 	}
193 
getCoordinate(int i)194 	public Coordinate getCoordinate(int i) {
195 		return edge[i].orig().getCoordinate();
196 	}
197 
198 	/**
199 	 * Gets the index for the given edge of this triangle
200 	 *
201 	 * @param e
202 	 *          a QuadEdge
203 	 * @return the index of the edge in this triangle
204 	 * or -1 if the edge is not an edge of this triangle
205 	 */
getEdgeIndex(QuadEdge e)206 	public int getEdgeIndex(QuadEdge e) {
207 		for (int i = 0; i < 3; i++) {
208 			if (edge[i] == e)
209 				return i;
210 		}
211 		return -1;
212 	}
213 
214 	/**
215 	 * Gets the index for the edge that starts at vertex v.
216 	 *
217 	 * @param v
218 	 *          the vertex to find the edge for
219 	 * @return the index of the edge starting at the vertex
220 	 * or -1 if the vertex is not in the triangle
221 	 */
getEdgeIndex(Vertex v)222 	public int getEdgeIndex(Vertex v) {
223 		for (int i = 0; i < 3; i++) {
224 			if (edge[i].orig() == v)
225 				return i;
226 		}
227 		return -1;
228 	}
229 
getEdgeSegment(int i, LineSegment seg)230 	public void getEdgeSegment(int i, LineSegment seg) {
231 		seg.p0 = edge[i].orig().getCoordinate();
232 		int nexti = (i + 1) % 3;
233 		seg.p1 = edge[nexti].orig().getCoordinate();
234 	}
235 
getCoordinates()236 	public Coordinate[] getCoordinates() {
237 		Coordinate[] pts = new Coordinate[4];
238 		for (int i = 0; i < 3; i++) {
239 			pts[i] = edge[i].orig().getCoordinate();
240 		}
241 		pts[3] = new Coordinate(pts[0]);
242 		return pts;
243 	}
244 
contains(Coordinate pt)245 	public boolean contains(Coordinate pt) {
246 		Coordinate[] ring = getCoordinates();
247 		return PointLocation.isInRing(pt, ring);
248 	}
249 
getGeometry(GeometryFactory fact)250 	public Polygon getGeometry(GeometryFactory fact) {
251 		LinearRing ring = fact.createLinearRing(getCoordinates());
252 		Polygon tri = fact.createPolygon(ring);
253 		return tri;
254 	}
255 
toString()256 	public String toString() {
257 		return getGeometry(new GeometryFactory()).toString();
258 	}
259 
260 	/**
261 	 * Tests whether this triangle is adjacent to the outside of the subdivision.
262 	 *
263 	 * @return true if the triangle is adjacent to the subdivision exterior
264 	 */
isBorder()265 	public boolean isBorder() {
266 		for (int i = 0; i < 3; i++) {
267 			if (getAdjacentTriangleAcrossEdge(i) == null)
268 				return true;
269 		}
270 		return false;
271 	}
272 
isBorder(int i)273 	public boolean isBorder(int i) {
274 		return getAdjacentTriangleAcrossEdge(i) == null;
275 	}
276 
getAdjacentTriangleAcrossEdge(int edgeIndex)277 	public QuadEdgeTriangle getAdjacentTriangleAcrossEdge(int edgeIndex) {
278 		return (QuadEdgeTriangle) getEdge(edgeIndex).sym().getData();
279 	}
280 
getAdjacentTriangleEdgeIndex(int i)281 	public int getAdjacentTriangleEdgeIndex(int i) {
282 		return getAdjacentTriangleAcrossEdge(i).getEdgeIndex(getEdge(i).sym());
283 	}
284 
285 	/**
286 	 * Gets the triangles which are adjacent (include) to a
287 	 * given vertex of this triangle.
288 	 *
289 	 * @param vertexIndex the vertex to query
290 	 * @return a list of the vertex-adjacent triangles
291 	 */
getTrianglesAdjacentToVertex(int vertexIndex)292 	public List getTrianglesAdjacentToVertex(int vertexIndex) {
293 		// Assert: isVertex
294 		List adjTris = new ArrayList();
295 
296 		QuadEdge start = getEdge(vertexIndex);
297 		QuadEdge qe = start;
298 		do {
299 			QuadEdgeTriangle adjTri = (QuadEdgeTriangle) qe.getData();
300 			if (adjTri != null) {
301 				adjTris.add(adjTri);
302 			}
303 			qe = qe.oNext();
304 		} while (qe != start);
305 
306 		return adjTris;
307 
308 	}
309 
310 	/**
311 	 * Gets the neighbours of this triangle. If there is no neighbour triangle,
312 	 * the array element is <code>null</code>
313 	 *
314 	 * @return an array containing the 3 neighbours of this triangle
315 	 */
getNeighbours()316 	public QuadEdgeTriangle[] getNeighbours() {
317 		QuadEdgeTriangle[] neigh = new QuadEdgeTriangle[3];
318 		for (int i = 0; i < 3; i++) {
319 			neigh[i] = (QuadEdgeTriangle) getEdge(i).sym().getData();
320 		}
321 		return neigh;
322 	}
323 
324 	private static class QuadEdgeTriangleBuilderVisitor implements TriangleVisitor {
325 		private List triangles = new ArrayList();
326 
QuadEdgeTriangleBuilderVisitor()327 		public QuadEdgeTriangleBuilderVisitor() {
328 		}
329 
visit(QuadEdge[] edges)330 		public void visit(QuadEdge[] edges) {
331 			triangles.add(new QuadEdgeTriangle(edges));
332 		}
333 
getTriangles()334 		public List getTriangles() {
335 			return triangles;
336 		}
337 	}
338 }
339 
340 
341