2 import java.util.Stack;
3 import java.util.Hashtable;*/
6 * A class that represents the quad edge data structure which implements
7 * the edge algebra as described in the algorithm.
9 * Each edge contains 4 parts, or other edges. Any edge in the group may
10 * be accessed using a series of rotate and flip operations. The 0th
11 * edge is the canonical representative of the group.
13 * The quad edge class does not contain separate information for vertice
14 * or faces; a vertex is implicitly defined as a ring of edges (the ring
15 * is created using the next field).
20 * Group of edges that describe the quad edge
24 * The position of this edge within the quad list
28 * The vertex that this edge represents
32 * Contains a reference to a connected quad edge
40 * Create a new edge which.
42 public Edge(Vertex v, Edge ql[], int pos)
50 * Create a new edge which.
52 public Edge(Edge ql[], int pos)
58 * Create a string representation of the edge
60 /*public String toString()
63 return vertex.toString();
68 public Edge makeEdge(Vertex o, Vertex d)
70 Edge ql[] = new Edge[4];
71 ql[0] = new Edge(ql, 0);
72 ql[1] = new Edge(ql, 1);
73 ql[2] = new Edge(ql, 2);
74 ql[3] = new Edge(ql, 3);
87 public void setNext(Edge n)
93 * Initialize the data (vertex) for the edge's origin
95 public void setOrig(Vertex o)
101 * Initialize the data (vertex) for the edge's destination
103 public void setDest(Vertex d)
105 symmetric().setOrig(d);
115 return this.rotate().oNext().rotate();
120 return this.rotateInv().oNext().rotate();
125 return this.oNext().symmetric();
130 return this.rotate().oNext().rotateInv();
135 return this.symmetric().oNext();
140 return this.symmetric().oNext().symmetric();
145 return this.rotateInv().oNext().rotateInv();
155 return symmetric().orig();
159 * Return the symmetric of the edge. The symmetric is the same edge
160 * with the opposite direction.
161 * @return the symmetric of the edge
165 return quadList[(listPos+2)%4];
169 * Return the rotated version of the edge. The rotated version is a
170 * 90 degree counterclockwise turn.
171 * @return the rotated version of the edge
175 return quadList[(listPos+1)%4];
179 * Return the inverse rotated version of the edge. The inverse
180 * is a 90 degree clockwise turn.
181 * @return the inverse rotated edge.
185 return quadList[(listPos+3)%4];
190 return quadList[(listPos+1)%4];
193 Edge connectLeft(Edge b)
202 ans = e.makeEdge(t1, t2);
204 ans.symmetric().splice(b);
208 Edge connectRight(Edge b)
218 ans = e.makeEdge(t1, t2);
219 ans.splice(symmetric());
220 ans.symmetric().splice(oprevb);
224 /****************************************************************/
225 /* Quad-edge manipulation primitives
226 ****************************************************************/
230 Edge syme = symmetric();
231 Edge b = syme.oPrev();
234 Edge lnexttmp = a.lNext();
236 lnexttmp = b.lNext();
237 syme.splice(lnexttmp);
238 Vertex a1 = a.dest();
239 Vertex b1 = b.dest();
246 Edge alpha = oNext().rotate();
247 Edge beta = b.oNext().rotate();
248 Edge t1 = beta.oNext();
249 Edge temp = alpha.oNext();
258 boolean valid(Edge basel)
260 Vertex t1 = basel.orig();
261 Vertex t3 = basel.dest();
263 return t1.ccw(t2, t3);
270 f = symmetric().oPrev();
271 symmetric().splice(f);
274 EdgePair doMerge(Edge ldo, Edge ldi, Edge rdi, Edge rdo)
276 boolean torun = true;
278 Vertex t3 = rdi.orig();
279 Vertex t1 = ldi.orig();
280 Vertex t2 = ldi.dest();
282 while (t1.ccw(t2, t3)) {
291 if (t2.ccw(t3, t1)) {
299 Edge basel = rdi.symmetric().connectLeft(ldi);
301 Edge lcand = basel.rPrev();
302 Edge rcand = basel.oPrev();
303 Vertex t1 = basel.orig();
304 Vertex t2 = basel.dest();
306 if (t1 == rdo.orig())
308 if (t2 == ldo.orig())
309 ldo = basel.symmetric();
312 Edge t = lcand.oNext();
313 if (t.valid(basel)) {
314 Vertex v4 = basel.orig();
316 Vertex v1 = lcand.dest();
317 Vertex v3 = lcand.orig();
318 Vertex v2 = t.dest();
319 while (v1.incircle(v2,v3,v4)){
331 if (t.valid(basel)) {
332 Vertex v4 = basel.dest();
333 Vertex v1 = t.dest();
334 Vertex v2 = rcand.dest();
335 Vertex v3 = rcand.orig();
336 while (v1.incircle(v2,v3,v4)) {
346 boolean lvalid = lcand.valid(basel);
348 boolean rvalid = rcand.valid(basel);
349 if ((!lvalid) && (!rvalid)) {
350 return new EdgePair(ldo, rdo);
353 Vertex v1 = lcand.dest();
354 Vertex v2 = lcand.orig();
355 Vertex v3 = rcand.orig();
356 Vertex v4 = rcand.dest();
357 if (!lvalid || (rvalid && v1.incircle(v2,v3,v4))) {
358 basel = rcand.connectLeft(basel.symmetric());
359 rcand = basel.symmetric().lNext();
361 basel = lcand.connectRight(basel).symmetric();
362 lcand = basel.rPrev();
369 * Print the voronoi diagram and its dual, the delaunay triangle for the
372 void outputVoronoiDiagram()
375 // Plot voronoi diagram edges with one endpoint at infinity.
377 Vec2 v21 = (Vec2)nex.dest();
378 Vec2 v22 = (Vec2)nex.orig();
379 Edge tmp = nex.oNext();
380 Vec2 v23 = (Vec2)tmp.dest();
381 Vec2 cvxvec = v21.sub(v22);
382 Vec2 center = v22.circle_center(v21, v23);
384 Vec2 vv1 = v22.sum(v22);
385 Vec2 vv2 = vv1.times((float) 0.5);
386 Vec2 vv3 = center.sub(vv2);
387 double ln = 1.0 + vv3.magn();
388 double d1 = ln/cvxvec.magn();
389 vv1 = cvxvec.cross();
390 vv2 = vv1.times((float) d1) ;
391 vv3 = center.sum(vv2);
392 System.out.println("Vedge " + center.toString() + " " + vv3.toString());
394 } while (nex != this);
396 // plot delaunay triangle edges and finite VD edges.
397 LinkedList edges = new LinkedList();
398 Hashtable seen = new Hashtable();
399 pushRing(edges, seen);
400 System.out.println("no. of edges = " + edges.size());
401 while (edges.size()!=0) {
402 Edge edge = (Edge)edges.pop();
403 Integer b = (Integer)seen.get(edge);
404 if (b != null && b.intValue()==1) {
408 Vertex v1 = prev.orig();
410 Vertex v2 = prev.dest();
413 System.out.println("Dedge " + v1 + " " + v2);
414 Edge sprev = prev.symmetric();
415 Edge snex = sprev.oNext();
418 Vertex v3 = nex.dest();
419 Vertex v4 = snex.dest();
420 if (v1.ccw(v2, v3) != v1.ccw(v2, v4)) {
421 Vec2 v21 = prev.orig();
422 Vec2 v22 = prev.dest();
423 Vec2 v23 = nex.dest();
424 Vec2 vv1 = v21.circle_center(v22, v23);
428 Vec2 vv2 = v21.circle_center(v22, v23);
429 System.out.println("Vedge " + vv1.toString() + " " + vv2.toString());
432 seen.put(prev, new Integer(0));
435 } while (prev != edge);
437 edge.symmetric().pushRing(edges, seen);
442 void pushRing(LinkedList stack, Hashtable seen)
445 while (nex != this) {
446 if (!seen.containsKey(nex)) {
447 seen.put(nex, new Integer(1));
454 void pushNonezeroRing(LinkedList stack, Hashtable seen)
457 while (nex != this) {
458 if (seen.containsKey(nex)) {