Skip to content

Commit d40cd98

Browse files
committed
almost works
1 parent cd3ea50 commit d40cd98

File tree

6 files changed

+448
-245
lines changed

6 files changed

+448
-245
lines changed

.idea/workspace.xml

Lines changed: 238 additions & 185 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/java/convex_dt/ConvexDT.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,12 @@ public HalfEdge computeSmallDelaunay(ArrayList<KDSPoint> points) throws Exceptio
6464

6565
HalfEdge e1 = dcel.createEdge(a, b);
6666
HalfEdge e2 = dcel.createEdge(b, c);
67-
// connect a -> b with b -> c
67+
// connect a -> b with b -> c and a <- b with b <- c
6868
e1.setNext(e2);
69+
e1.getTwin().setPrev(e2.getTwin());
6970
e2.setPrev(e1);
71+
e2.getTwin().setNext(e1.getTwin());
72+
7073
if (leftOf(a, b, c) || rightOf(a, b, c)) {
7174
// connect and create a triangle
7275
System.out.println("Creating triangle!");
@@ -441,7 +444,12 @@ public HalfEdge delaunay(ArrayList<KDSPoint> points) throws Exception {
441444
}
442445

443446
// merge step
447+
int iteration = 0;
444448
while (true) {
449+
if (iteration > 0) {
450+
System.out.println("ROUND TWO");
451+
}
452+
++iteration;
445453
lcand = computeLcand();
446454
rcand = computeRcand();
447455
System.out.println(lcand.getTwin() == rcand || lcand == rcand);
@@ -456,6 +464,11 @@ public HalfEdge delaunay(ArrayList<KDSPoint> points) throws Exception {
456464
scene.repaint();
457465
sleep(2000);
458466

467+
scene.removeAllShapes();
468+
scene.repaint();
469+
sleep(500);
470+
dcel.draw(scene);
471+
sleep(5000);
459472
if (isValid(lcand) && isValid(rcand)) {
460473
System.out.println("1");
461474
switch (shape.inCircle(base.getOrigin(), base.getDestination(), lcand.getDestination(), rcand.getDestination())) {

src/main/java/convex_dt/Utils.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,27 @@
99
public class Utils {
1010
/* The following are some predicates */
1111

12+
public static boolean isCCW(HalfEdge a, HalfEdge b) {
13+
if (a == null || b == null) {
14+
return false;
15+
}
16+
17+
assert a.getDestination() == b.getOrigin();
18+
return isCCW(a.getOrigin(), a.getDestination(), b.getDestination());
19+
}
20+
21+
public static boolean isCCW(KDSPoint a, KDSPoint b, KDSPoint c) {
22+
if (a == null || b == null || c == null) {
23+
return false;
24+
}
25+
assert a != b && b != c;
26+
double edge1 = (b.getX() - a.getX()) * (b.getY() + a.getY());
27+
double edge2 = (c.getX() - b.getX()) * (c.getY() + b.getY());
28+
double edge3 = (a.getX() - c.getX()) * (a.getY() + c.getY());
29+
30+
return edge1 + edge2 + edge3 < 1e-10;
31+
}
32+
1233
public static boolean lowerThan(KDSPoint a, KDSPoint b) {
1334
return a.getY() < b.getY();
1435
}

src/main/java/convex_dt/run.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ public static void main(String[] args) throws Exception {
5252
//lower.draw(scene, 0, 2);
5353

5454
System.out.println("Printing DCEL!");
55-
//scene.removeAllShapes();
55+
scene.removeAllShapes();
56+
scene.repaint();
5657
for (KDSPoint p : points) {
5758
p.draw(scene, 0);
5859
}

src/main/java/dcel/DCEL.java

Lines changed: 169 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@
33
import ProGAL.geom2d.viewer.J2DScene;
44
import kds.KDSPoint;
55

6+
import java.awt.*;
67
import java.util.ArrayList;
78

9+
import static convex_dt.Utils.isCCW;
10+
import static convex_dt.Utils.leftOf;
11+
import static convex_dt.Utils.rightOf;
812
import static java.lang.Thread.sleep;
913

1014
/**
@@ -49,76 +53,184 @@ public HalfEdge createEdge() {
4953
public HalfEdge connect(HalfEdge a, HalfEdge b) {
5054
HalfEdge c = new HalfEdge(a.getDestination(), b.getOrigin());
5155
HalfEdge c_twin = new HalfEdge(b.getOrigin(), a.getDestination());
56+
c.setTwin(c_twin);
57+
c_twin.setTwin(c);
5258
edges.add(c);
5359
edges.add(c_twin);
5460

55-
// add prev and next
56-
c.setPrev(a);
57-
c.setNext(b);
61+
// Handling a
5862

59-
c.setTwin(c_twin);
60-
c_twin.setTwin(c);
61-
// remove the face because we'll most likely get 2 new ones
62-
faces.remove(a.getFace());
63-
// create two new faces
64-
Face c_face = createFace(c);
65-
Face c_twin_face = createFace(c_twin);
66-
c.setFace(c_face);
67-
c_twin.setFace(c_twin_face);
68-
// connect the twin
69-
if (a.getNext() != null) {
70-
c_twin.setNext(a.getNext());
71-
a.getNext().setPrev(c_twin);
72-
} else if (c.getPrev() != null){
73-
c_twin.setNext(c.getPrev().getTwin());
74-
c.getPrev().getTwin().setPrev(c_twin);
63+
// case 1: a has no next -> not much to do
64+
if (a.getNext() == null) {
65+
a.setNext(c);
66+
a.getTwin().setPrev(c_twin);
67+
68+
c.setPrev(a);
69+
c_twin.setNext(a.getTwin());
70+
71+
// update face
72+
c.setFace(a.getFace());
73+
c_twin.setFace(a.getTwin().getFace());
74+
}
75+
// case 2: a has a next -> locate the proper incident edges to pre/append c
76+
else if (a.getNext() != null) {
77+
// use a.twin to make it simpler. likewise, use c_twin
78+
// means we have to start from a.twin and not a.twin.next
79+
HalfEdge tmp = a.getTwin();
80+
HalfEdge ccw = tmp;
81+
boolean foundCCW = false;
82+
83+
// stop if the next edge is a.twin
84+
do {
85+
boolean edgeIsCCW = isCCW(c_twin, tmp);
86+
if (foundCCW && !edgeIsCCW) break;
87+
else if (edgeIsCCW) {
88+
foundCCW = true;
89+
// break if the new edge is to the right of our previous ccw edge
90+
if (rightOf(ccw.getOrigin(), ccw.getDestination(), tmp.getDestination())) break;
91+
ccw = tmp;
92+
}
93+
94+
// have to break because we're using do-while
95+
if (tmp.getTwin().getNext() == null) break;
96+
tmp = tmp.getTwin().getNext();
97+
} while (tmp != a.getTwin());
98+
99+
tmp = a.getTwin();
100+
HalfEdge cw = null;
101+
boolean foundCW = false;
102+
103+
// stop if the next edge is a.twin.prev, since we handle a.twin in the while loop
104+
do {
105+
boolean edgeIsCW = !isCCW(c_twin, tmp);
106+
if (foundCW && !edgeIsCW) break;
107+
else if (edgeIsCW) {
108+
foundCW = true;
109+
// break if the new edge is to the left of our previous cw edge
110+
if (cw != null && leftOf(cw.getOrigin(), cw.getDestination(), tmp.getDestination())) break;
111+
cw = tmp;
112+
}
113+
114+
// have to break because we're using do-while
115+
if (tmp.getTwin().getNext() == null) break;
116+
tmp = tmp.getTwin().getNext();
117+
} while (tmp != a.getTwin());
118+
119+
assert cw != null;
120+
assert ccw != null;
121+
// handle cw - set proper faces later
122+
c.setPrev(cw.getTwin());
123+
cw.getTwin().setNext(c);
124+
125+
// handle ccw - set proper faces later
126+
c_twin.setNext(ccw);
127+
ccw.setPrev(c_twin);
75128
}
76-
if (b.getPrev() != null) {
77-
c_twin.setPrev(b.getPrev());
78-
b.getPrev().setNext(c_twin);
79-
} else if (c.getNext() != null){
80-
c_twin.setPrev(c.getNext().getTwin());
81-
c.getNext().getTwin().setNext(c_twin);
129+
130+
// Handling b
131+
132+
// case 1: b has no prev -> c can be tacked on easily
133+
if (b.getPrev() == null) {
134+
b.setPrev(c);
135+
b.getTwin().setNext(c_twin);
136+
137+
c.setNext(b);
138+
c_twin.setPrev(b.getTwin());
139+
c.setFace(b.getFace()); // c shares the same face as b
140+
c_twin.setFace(b.getTwin().getFace()); // c twin shares same face with b twin
82141
}
83-
// update a and b's prev/next
84-
a.setNext(c);
85-
b.setPrev(c);
86-
// set faces
87-
HalfEdge tmp = c.getNext();
88-
int direction = 1; // 1 == next
89-
while (true) {
90-
if (tmp == c) break;
91-
if (tmp == null && direction == 1) {
92-
// this means the face is not closed, so we have to start over
93-
direction = 0;
94-
tmp = c.getPrev();
95-
if (tmp == null) break;
96-
} else if (tmp == null) {
97-
break;
142+
// case 2: b has a prev -> we need to locate the edges CCW and CW from c if they exist
143+
else if (b.getPrev() != null) {
144+
HalfEdge tmp = b;
145+
HalfEdge ccw = tmp;
146+
boolean foundCCW = false;
147+
// locate CCW edge by looking at incident edges
148+
do {
149+
boolean edgeIsCCW = isCCW(c, tmp);
150+
if (foundCCW && !edgeIsCCW) {
151+
// we found the CCW edge
152+
break;
153+
} else if (edgeIsCCW) {
154+
foundCCW = true;
155+
// break if the new edge is to the right of our previous ccw edge
156+
if (rightOf(ccw.getOrigin(), ccw.getDestination(), tmp.getDestination())) break;
157+
ccw = tmp;
158+
}
159+
// have to break because we're using do-while
160+
if (tmp.getTwin().getNext() == null) break;
161+
tmp = tmp.getTwin().getNext();
98162
}
99-
tmp.setFace(c_face);
100-
tmp = direction == 1 ? tmp.getNext() : tmp.getPrev();
163+
while (tmp != null && tmp.getTwin().getNext() != null && tmp != b);
164+
165+
tmp = b;
166+
HalfEdge cw = tmp;
167+
boolean foundCW = false;
168+
// locate CW edge by looking at incident edges
169+
do {
170+
boolean edgeIsCW = !isCCW(c, tmp);
171+
if (foundCW && !edgeIsCW) {
172+
// we found the CW edge
173+
break;
174+
} else if (edgeIsCW) {
175+
foundCW = true;
176+
// break if the new edge is to the left of our previous ccw edge
177+
if (leftOf(cw.getOrigin(), cw.getDestination(), tmp.getDestination())) break;
178+
cw = tmp;
179+
}
180+
// have to break because we're using do-while
181+
if (tmp.getPrev() == null) break;
182+
tmp = tmp.getPrev().getTwin();
183+
} while (tmp != null && tmp.getPrev() != null && tmp != b);
184+
assert ccw != null;
185+
assert cw != null;
186+
187+
// handle ccw - set proper faces later
188+
c.setNext(ccw);
189+
ccw.setPrev(c);
190+
191+
// handle cw - set proper faces later
192+
c_twin.setPrev(cw.getTwin());
193+
cw.getTwin().setNext(c_twin);
101194
}
102195

103-
tmp = c_twin.getNext();
104-
direction = 1; // 1 == next
105-
while (true) {
106-
if (tmp == c_twin) break;
107-
if (tmp == null && direction == 1) {
108-
// this means the face is not closed, so we have to start over
109-
direction = 0;
110-
tmp = c_twin.getPrev();
111-
if (tmp == null) break;
112-
} else if (tmp == null) {
113-
break;
196+
// only update faces if we created a new one
197+
if (a.getNext() != null || b.getPrev() != null) {
198+
// handle faces by traversing the edges and updating the face
199+
Face c_face = createFace(c);
200+
c.setFace(c_face);
201+
HalfEdge tmp = c.getNext();
202+
while (tmp != null && tmp != c) {
203+
tmp.setFace(c_face);
204+
tmp = tmp.getNext();
205+
}
206+
207+
Face c_twin_face = createFace(c_twin);
208+
c_twin.setFace(c_twin_face);
209+
tmp = c_twin.getNext();
210+
while (tmp != null && tmp != c_twin) {
211+
tmp.draw(scene, 0, Color.CYAN);
212+
scene.repaint();
213+
tmp.setFace(c_twin_face);
214+
tmp = tmp.getNext();
114215
}
115-
tmp.setFace(c_twin_face);
116-
tmp = direction == 1 ? tmp.getNext() : tmp.getPrev();
117216
}
118217

119-
//scene.removeAllShapes();
120-
c_face.draw(scene);
218+
c.getFace().draw(scene);
121219
scene.repaint();
220+
/*try {
221+
scene.removeAllShapes();
222+
scene.repaint();
223+
c.getFace().draw(scene);
224+
scene.repaint();
225+
sleep(5000);
226+
227+
scene.removeAllShapes();
228+
scene.repaint();
229+
sleep(1000);
230+
c_twin.getFace().draw(scene);
231+
scene.repaint();
232+
sleep(5000);
233+
} catch (Exception e) {}*/
122234
//scene.removeAllShapes();
123235
return c;
124236
}

src/main/java/dcel/HalfEdge.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
import kds.KDSPoint;
66

77
import java.awt.*;
8+
import java.util.Iterator;
9+
import java.util.Spliterator;
10+
import java.util.function.Consumer;
811

912
/**
1013
* Created by cvium on 29-11-2016.
@@ -86,7 +89,7 @@ public HalfEdge getNext() {
8689

8790
public void setNext(HalfEdge next) {
8891
// next half-edge must have this.destination as its origin
89-
assert next.getOrigin() == this.destination;
92+
assert next == null || next.getOrigin() == this.destination;
9093
this.next = next;
9194
}
9295

0 commit comments

Comments
 (0)