Revision 21245
trunk/libraries/libTopology/src/org/gvsig/jts/voronoi/chen/Segment.java | ||
---|---|---|
1 |
package org.gvsig.jts.voronoi.chen; |
|
2 |
|
|
3 |
/** |
|
4 |
* Voronoi diagram |
|
5 |
* |
|
6 |
* Copyright(c) 1998 Ping-Che Chen |
|
7 |
* |
|
8 |
* This program defines the segemnt. |
|
9 |
* |
|
10 |
*/ |
|
11 |
|
|
12 |
public class Segment { |
|
13 |
|
|
14 |
public Coord p1, p2; |
|
15 |
public boolean i1, i2; // true if not the end of a segment |
|
16 |
|
|
17 |
public String toString() { |
|
18 |
return p1 + "-" + p2; |
|
19 |
} |
|
20 |
|
|
21 |
public static Segment getMidNormal(final Segment l) { |
|
22 |
if(l.i1 || l.i2) { |
|
23 |
return null; |
|
24 |
} |
|
25 |
|
|
26 |
Segment s = new Segment(); |
|
27 |
s.p1 = new Coord(); |
|
28 |
s.p2 = new Coord(); |
|
29 |
|
|
30 |
s.i1 = s.i2 = true; |
|
31 |
|
|
32 |
if(l.p1.y == l.p2.y) { |
|
33 |
s.p1.x = s.p2.x = (l.p1.x + l.p2.x) / 2; |
|
34 |
s.p1.y = l.p1.y - 1; |
|
35 |
s.p2.y = l.p1.y + 1; |
|
36 |
} |
|
37 |
else { |
|
38 |
double x = (l.p2.x + l.p1.x) / 2; |
|
39 |
double y = (l.p2.y + l.p1.y) / 2; |
|
40 |
double m = (l.p1.x - l.p2.x) / (l.p2.y - l.p1.y); |
|
41 |
double b = y - m * x; |
|
42 |
|
|
43 |
s.p1.x = l.p1.x; |
|
44 |
s.p2.x = l.p2.x; |
|
45 |
if(s.p1.x == s.p2.x) { |
|
46 |
s.p2.x += 1; |
|
47 |
} |
|
48 |
s.p1.y = m * s.p1.x + b; |
|
49 |
s.p2.y = m * s.p2.x + b; |
|
50 |
} |
|
51 |
|
|
52 |
return s; |
|
53 |
} |
|
54 |
|
|
55 |
public static Coord getIntersect(final Segment l1, final Segment l2) { |
|
56 |
double m1, m2, b1, b2; |
|
57 |
Coord result = new Coord(); |
|
58 |
|
|
59 |
l1.normalize(); |
|
60 |
l2.normalize(); |
|
61 |
|
|
62 |
if(l1.p2.x == l1.p1.x) { |
|
63 |
if(l2.p2.x == l2.p1.x) { |
|
64 |
return null; |
|
65 |
} |
|
66 |
else { |
|
67 |
m2 = (l2.p2.y - l2.p1.y) / (l2.p2.x - l2.p1.x); |
|
68 |
b2 = l2.p1.y - m2 * l2.p1.x; |
|
69 |
result.x = l1.p1.x; |
|
70 |
result.y = l1.p1.x * m2 + b2; |
|
71 |
} |
|
72 |
} |
|
73 |
else if(l2.p2.x == l2.p1.x) { |
|
74 |
if(l1.p2.x == l1.p1.x) { |
|
75 |
return null; |
|
76 |
} |
|
77 |
else { |
|
78 |
m1 = (l1.p2.y - l1.p1.y) / (l1.p2.x - l1.p1.x); |
|
79 |
b1 = l1.p1.y - m1 * l1.p1.x; |
|
80 |
result.x = l2.p1.x; |
|
81 |
result.y = l2.p1.x * m1 + b1; |
|
82 |
} |
|
83 |
} |
|
84 |
else { |
|
85 |
m1 = (l1.p2.y - l1.p1.y) / (l1.p2.x - l1.p1.x); |
|
86 |
m2 = (l2.p2.y - l2.p1.y) / (l2.p2.x - l2.p1.x); |
|
87 |
|
|
88 |
b1 = l1.p1.y - m1 * l1.p1.x; |
|
89 |
b2 = l2.p1.y - m2 * l2.p1.x; |
|
90 |
|
|
91 |
if(m1 == m2) { |
|
92 |
return null; |
|
93 |
} |
|
94 |
|
|
95 |
result.x = (b2 - b1) / (m1 - m2); |
|
96 |
result.y = (m1 * b2 - m2 * b1) / (m1 - m2); |
|
97 |
} |
|
98 |
|
|
99 |
if(!l1.i1) { |
|
100 |
if(result.x < l1.p1.x) |
|
101 |
return null; |
|
102 |
if(result.x == l1.p1.x && result.y < l1.p1.y) |
|
103 |
return null; |
|
104 |
} |
|
105 |
|
|
106 |
if(!l1.i2) { |
|
107 |
if(result.x > l1.p2.x) |
|
108 |
return null; |
|
109 |
if(result.x == l1.p2.x && result.y > l1.p2.y) |
|
110 |
return null; |
|
111 |
} |
|
112 |
|
|
113 |
if(!l2.i1) { |
|
114 |
if(result.x < l2.p1.x) |
|
115 |
return null; |
|
116 |
if(result.x == l2.p1.x && result.y < l2.p1.y) |
|
117 |
return null; |
|
118 |
} |
|
119 |
|
|
120 |
if(!l2.i2) { |
|
121 |
if(result.x > l2.p2.x) |
|
122 |
return null; |
|
123 |
if(result.x == l2.p2.x && result.y > l2.p2.y) |
|
124 |
return null; |
|
125 |
} |
|
126 |
|
|
127 |
return result; |
|
128 |
} |
|
129 |
|
|
130 |
public void normalize() { |
|
131 |
if(p1.x > p2.x || (p1.x == p2.x && p1.y > p2.y)) { |
|
132 |
Coord t; |
|
133 |
t = p1; |
|
134 |
p1 = p2; |
|
135 |
p2 = t; |
|
136 |
boolean t2; |
|
137 |
t2 = i1; |
|
138 |
i1 = i2; |
|
139 |
i2 = t2; |
|
140 |
} |
|
141 |
} |
|
142 |
} |
trunk/libraries/libTopology/src/org/gvsig/jts/voronoi/chen/Main.java | ||
---|---|---|
1 |
package org.gvsig.jts.voronoi.chen; |
|
2 |
|
|
3 |
/** |
|
4 |
* Voronoi diagram |
|
5 |
* |
|
6 |
* Copyright(c) 1998 Ping-Che Chen |
|
7 |
* |
|
8 |
* This is the main program. |
|
9 |
* |
|
10 |
*/ |
|
11 |
|
|
12 |
import java.applet.Applet; |
|
13 |
import java.awt.Color; |
|
14 |
import java.awt.Graphics; |
|
15 |
import java.awt.event.MouseAdapter; |
|
16 |
import java.awt.event.MouseEvent; |
|
17 |
import java.util.Enumeration; |
|
18 |
import java.util.Random; |
|
19 |
|
|
20 |
public class Main extends Applet { |
|
21 |
|
|
22 |
List vertices; |
|
23 |
int status = 1; |
|
24 |
int v = 0; |
|
25 |
Vertex[] diagram; |
|
26 |
String message; |
|
27 |
|
|
28 |
public void init() { |
|
29 |
vertices = new List(); |
|
30 |
|
|
31 |
addMouseListener(new MyMouseListener()); |
|
32 |
} |
|
33 |
|
|
34 |
public void paint(Graphics g) { |
|
35 |
g.setColor(Color.red); |
|
36 |
g.fillRect(0, 0, 10, 10); |
|
37 |
g.setColor(Color.green); |
|
38 |
g.fillRect(10, 0, 10, 10); |
|
39 |
g.setColor(Color.blue); |
|
40 |
g.fillRect(20, 0, 10, 10); |
|
41 |
g.setColor(Color.white); |
|
42 |
g.fillRect(30, 0, 10, 10); |
|
43 |
|
|
44 |
g.setColor(Color.black); |
|
45 |
Enumeration i = vertices.elements(); |
|
46 |
while(i.hasMoreElements()) { |
|
47 |
Coord p = (Coord)i.nextElement(); |
|
48 |
g.fillArc((int)p.x - 1, (int)(-p.y) - 1, 3, 3, 0, 360); |
|
49 |
} |
|
50 |
if(status == 2) { |
|
51 |
for(int j = 0; j < diagram.length; j++) { |
|
52 |
i = diagram[j].edges.elements(); |
|
53 |
while(i.hasMoreElements()) { |
|
54 |
VoronoiSegment s = (VoronoiSegment)i.nextElement(); |
|
55 |
|
|
56 |
if(s.floating) { |
|
57 |
continue; |
|
58 |
} |
|
59 |
|
|
60 |
int x1, y1, x2, y2; |
|
61 |
int rx1, ry1, rx2, ry2; |
|
62 |
|
|
63 |
double dx = s.p2.x - s.p1.x; |
|
64 |
double dy = s.p2.y - s.p1.y; |
|
65 |
|
|
66 |
double m = dy / dx; |
|
67 |
double b = s.p1.y - m * s.p1.x; |
|
68 |
|
|
69 |
if(dx > 0) { |
|
70 |
rx1 = 0; |
|
71 |
rx2 = getSize().width; |
|
72 |
} |
|
73 |
else { |
|
74 |
rx1 = getSize().width; |
|
75 |
rx2 = 0; |
|
76 |
} |
|
77 |
|
|
78 |
if(dy > 0) { |
|
79 |
ry1 = 0; |
|
80 |
ry2 = getSize().height; |
|
81 |
} |
|
82 |
else { |
|
83 |
ry1 = getSize().height; |
|
84 |
ry2 = 0; |
|
85 |
} |
|
86 |
|
|
87 |
x1 = (int)s.p1.x; |
|
88 |
y1 = -(int)s.p1.y; |
|
89 |
x2 = (int)s.p2.x; |
|
90 |
y2 = -(int)s.p2.y; |
|
91 |
|
|
92 |
if(s.i1) { |
|
93 |
if(dx == 0) { |
|
94 |
y1 = ry1; |
|
95 |
} |
|
96 |
else { |
|
97 |
x1 = rx1; |
|
98 |
y1 = -(int)(m * rx1 + b); |
|
99 |
} |
|
100 |
} |
|
101 |
if(s.i2) { |
|
102 |
if(dx == 0) { |
|
103 |
y2 = ry2; |
|
104 |
} |
|
105 |
else { |
|
106 |
x2 = rx2; |
|
107 |
y2 = -(int)(m * rx2 + b); |
|
108 |
} |
|
109 |
} |
|
110 |
|
|
111 |
g.setColor(Color.black); |
|
112 |
g.drawLine(x1, y1, x2, y2); |
|
113 |
} |
|
114 |
} |
|
115 |
} |
|
116 |
else if(status == 3) { |
|
117 |
for(int j = 0; j < diagram.length; j++) { |
|
118 |
i = diagram[j].edges.elements(); |
|
119 |
while(i.hasMoreElements()) { |
|
120 |
VoronoiSegment s = (VoronoiSegment)i.nextElement(); |
|
121 |
if(s.floating) |
|
122 |
continue; |
|
123 |
|
|
124 |
int x1 = (int)s.v1.x; |
|
125 |
int y1 = -(int)s.v1.y; |
|
126 |
int x2 = (int)s.v2.x; |
|
127 |
int y2 = -(int)s.v2.y; |
|
128 |
|
|
129 |
g.setColor(Color.black); |
|
130 |
g.drawLine(x1, y1, x2, y2); |
|
131 |
} |
|
132 |
} |
|
133 |
} |
|
134 |
} |
|
135 |
|
|
136 |
public void update(Graphics g) { |
|
137 |
Color old = g.getColor(); |
|
138 |
g.setColor(Color.lightGray); |
|
139 |
g.fillRect(0, 0, getSize().width, getSize().height); |
|
140 |
g.setColor(old); |
|
141 |
paint(g); |
|
142 |
} |
|
143 |
|
|
144 |
class MyMouseListener extends MouseAdapter { |
|
145 |
public void mouseClicked(MouseEvent e) { |
|
146 |
if(e.getX() < 30 && e.getX() >= 20 && e.getY() < 10) { |
|
147 |
status = 1; |
|
148 |
vertices.removeAll(); |
|
149 |
v = 0; |
|
150 |
repaint(); |
|
151 |
} |
|
152 |
else if(status < 2) { |
|
153 |
if(e.getX() < 20 && e.getX() >= 10 && e.getY() < 10) { |
|
154 |
Random r = new Random(); |
|
155 |
for(int i = 0; i < 10; i++) { |
|
156 |
int x = Math.abs(r.nextInt()) % getSize().width; |
|
157 |
int y = Math.abs(r.nextInt()) % getSize().height; |
|
158 |
Coord p = new Coord(); |
|
159 |
p.x = x; |
|
160 |
p.y = -y; |
|
161 |
vertices.insertTail(p); |
|
162 |
} |
|
163 |
v += 10; |
|
164 |
|
|
165 |
repaint(); |
|
166 |
} |
|
167 |
else if(e.getX() < 10 && e.getY() < 10) { |
|
168 |
status++; |
|
169 |
|
|
170 |
Coord[] t = new Coord[v]; |
|
171 |
Enumeration p = vertices.elements(); |
|
172 |
for(int i = 0; i < v; i++) { |
|
173 |
t[i] = (Coord)p.nextElement(); |
|
174 |
} |
|
175 |
|
|
176 |
Voronoi.g = getGraphics(); |
|
177 |
Voronoi.row = 1; |
|
178 |
diagram = Voronoi.generate(t); |
|
179 |
|
|
180 |
repaint(); |
|
181 |
} |
|
182 |
else { |
|
183 |
Coord p = new Coord(); |
|
184 |
p.x = e.getX(); |
|
185 |
p.y = -e.getY(); |
|
186 |
|
|
187 |
vertices.insertTail(p); |
|
188 |
v++; |
|
189 |
|
|
190 |
repaint(); |
|
191 |
} |
|
192 |
} |
|
193 |
else if(e.getX() < 40 && e.getX() >= 30 && e.getY() < 10) { |
|
194 |
if(status == 2) |
|
195 |
status = 3; |
|
196 |
else |
|
197 |
status = 2; |
|
198 |
|
|
199 |
repaint(); |
|
200 |
} |
|
201 |
} |
|
202 |
} |
|
203 |
|
|
204 |
} |
trunk/libraries/libTopology/src/org/gvsig/jts/voronoi/chen/Coord.java | ||
---|---|---|
1 |
package org.gvsig.jts.voronoi.chen; |
|
2 |
|
|
3 |
/** |
|
4 |
* Voronoi Diagram |
|
5 |
* |
|
6 |
* Copyright(c) 1998 Ping-Che Chen |
|
7 |
* |
|
8 |
* This is the definition of the coordinate system. |
|
9 |
* |
|
10 |
*/ |
|
11 |
|
|
12 |
|
|
13 |
public class Coord { |
|
14 |
|
|
15 |
public double x, y; |
|
16 |
|
|
17 |
public String toString() { |
|
18 |
return "(" + x + "," + y + ")"; |
|
19 |
} |
|
20 |
|
|
21 |
public boolean equals(final Coord p) { |
|
22 |
if(Math.abs(p.x - x) < 1E-5 && Math.abs(p.y - y) < 1E-5) |
|
23 |
return true; |
|
24 |
else |
|
25 |
return false; |
|
26 |
} |
|
27 |
} |
trunk/libraries/libTopology/src/org/gvsig/jts/voronoi/chen/ConvexHull.java | ||
---|---|---|
1 |
package org.gvsig.jts.voronoi.chen; |
|
2 |
|
|
3 |
/** |
|
4 |
* Voronoi diagram |
|
5 |
* |
|
6 |
* Copyright(c) 1998 Ping-Che Chen |
|
7 |
* |
|
8 |
* This program deals with the convex hull in the Voronoi problem. |
|
9 |
*/ |
|
10 |
|
|
11 |
public class ConvexHull { |
|
12 |
|
|
13 |
public Coord[] points; |
|
14 |
|
|
15 |
private static class NewCoord { |
|
16 |
public Coord point; |
|
17 |
public double angle; |
|
18 |
public int group; |
|
19 |
} |
|
20 |
|
|
21 |
/** calculates (one of) the supporting line |
|
22 |
* note: no optimized version, need O(N log N) time |
|
23 |
*/ |
|
24 |
public static Segment[] getSupportLine(final ConvexHull ch1, final ConvexHull ch2, ConvexHull newch) { |
|
25 |
NewCoord[] a = new NewCoord[ch1.points.length + ch2.points.length]; |
|
26 |
Coord o = new Coord(); |
|
27 |
int[] c = new int[ch1.points.length + ch2.points.length]; |
|
28 |
|
|
29 |
if(ch1.points[0].y < ch2.points[0].y) { |
|
30 |
o = ch1.points[0]; |
|
31 |
} |
|
32 |
else { |
|
33 |
o = ch2.points[0]; |
|
34 |
} |
|
35 |
|
|
36 |
for(int i = 0; i < ch1.points.length; i++) { |
|
37 |
a[i] = new NewCoord(); |
|
38 |
a[i].point = ch1.points[i]; |
|
39 |
a[i].angle = angle(o, ch1.points[i]); |
|
40 |
a[i].group = 1; |
|
41 |
} |
|
42 |
|
|
43 |
for(int i = 0; i < ch2.points.length; i++) { |
|
44 |
a[i + ch1.points.length] = new NewCoord(); |
|
45 |
a[i + ch1.points.length].point = ch2.points[i]; |
|
46 |
a[i + ch1.points.length].angle = angle(o, ch2.points[i]); |
|
47 |
a[i + ch1.points.length].group = 2; |
|
48 |
} |
|
49 |
|
|
50 |
sort(a, 0, a.length); |
|
51 |
|
|
52 |
for(int i = 0; i < c.length; i++) { |
|
53 |
c[i] = -1; |
|
54 |
} |
|
55 |
|
|
56 |
c[0] = 0; |
|
57 |
c[1] = 1; |
|
58 |
int j = 2; |
|
59 |
for(int i = 2; i < c.length; i++) { |
|
60 |
while(ccw(a[c[j-2]].point, a[c[j-1]].point, a[i].point) < 0) { |
|
61 |
j--; |
|
62 |
} |
|
63 |
c[j++] = i; |
|
64 |
} |
|
65 |
|
|
66 |
Segment[] s = new Segment[2]; |
|
67 |
|
|
68 |
j = 1; |
|
69 |
while(j < c.length && c[j] >= 0) { |
|
70 |
if(a[c[j]].group != a[c[j-1]].group) { |
|
71 |
break; |
|
72 |
} |
|
73 |
j++; |
|
74 |
} |
|
75 |
|
|
76 |
s[0] = new Segment(); |
|
77 |
s[0].p1 = a[c[j-1]].point; |
|
78 |
s[0].p2 = a[c[j]].point; |
|
79 |
|
|
80 |
j++; |
|
81 |
while(j < c.length && c[j] >= 0) { |
|
82 |
if(a[c[j]].group != a[c[j-1]].group) { |
|
83 |
break; |
|
84 |
} |
|
85 |
j++; |
|
86 |
} |
|
87 |
|
|
88 |
if(j < c.length && c[j] >= 0) { |
|
89 |
s[1] = new Segment(); |
|
90 |
s[1].p1 = a[c[j-1]].point; |
|
91 |
s[1].p2 = a[c[j]].point; |
|
92 |
} |
|
93 |
else if(a[c[j-1]].group != a[c[0]].group) { |
|
94 |
s[1] = new Segment(); |
|
95 |
s[1].p1 = a[c[j-1]].point; |
|
96 |
s[1].p2 = a[c[0]].point; |
|
97 |
} |
|
98 |
else { |
|
99 |
s[1] = null; |
|
100 |
} |
|
101 |
|
|
102 |
if(s[1] != null && s[1].p1 == s[0].p1 && s[1].p2 == s[0].p2) { |
|
103 |
s[1] = null; |
|
104 |
} |
|
105 |
|
|
106 |
if(newch != null) { |
|
107 |
int i = 0; |
|
108 |
while(i < c.length && c[i] >= 0) i++; |
|
109 |
newch.points = new Coord[i]; |
|
110 |
for(int k = 0; k < i; k++) { |
|
111 |
newch.points[k] = a[c[k]].point; |
|
112 |
} |
|
113 |
} |
|
114 |
|
|
115 |
return s; |
|
116 |
} |
|
117 |
|
|
118 |
private static int ccw(final Coord p1, final Coord p2, final Coord p3) { |
|
119 |
double a, b, x, y; |
|
120 |
|
|
121 |
x = p2.x - p1.x; |
|
122 |
y = p2.y - p1.y; |
|
123 |
a = p3.x - p1.x; |
|
124 |
b = p3.y - p1.y; |
|
125 |
|
|
126 |
double t = b * x - a * y; |
|
127 |
|
|
128 |
if(t > 0) |
|
129 |
return 1; |
|
130 |
else if(t < 0) |
|
131 |
return -1; |
|
132 |
else |
|
133 |
return 0; |
|
134 |
} |
|
135 |
|
|
136 |
/** compute the 'angle' which is not truly the angle */ |
|
137 |
private static double angle(final Coord p1, final Coord p2) { |
|
138 |
double x, y; |
|
139 |
|
|
140 |
x = p2.x - p1.x; |
|
141 |
y = p2.y - p1.y; |
|
142 |
|
|
143 |
if(x == 0 && y == 0) |
|
144 |
return -1; |
|
145 |
|
|
146 |
double t = y / (Math.abs(x) + Math.abs(y)); |
|
147 |
|
|
148 |
if(x < 0) { |
|
149 |
t = 2 - t; |
|
150 |
} |
|
151 |
else if(y < 0) { |
|
152 |
t = 4 + t; |
|
153 |
} |
|
154 |
|
|
155 |
return t; |
|
156 |
} |
|
157 |
|
|
158 |
/** sort */ |
|
159 |
private static void sort(NewCoord[] s, int start, int end) { |
|
160 |
if(end - start > 1) { |
|
161 |
sort(s, start, (start + end) / 2); |
|
162 |
sort(s, (start + end) / 2, end); |
|
163 |
|
|
164 |
NewCoord[] t = new NewCoord[end - start]; |
|
165 |
int i = start; |
|
166 |
int j = (start + end) / 2; |
|
167 |
int k = 0; |
|
168 |
while(i < (start + end) / 2 && j < end) { |
|
169 |
if(s[i].angle < s[j].angle) { |
|
170 |
t[k++] = s[i++]; |
|
171 |
} |
|
172 |
else { |
|
173 |
t[k++] = s[j++]; |
|
174 |
} |
|
175 |
} |
|
176 |
|
|
177 |
while(i < (start + end) / 2) { |
|
178 |
t[k++] = s[i++]; |
|
179 |
} |
|
180 |
|
|
181 |
while(j < end) { |
|
182 |
t[k++] = s[j++]; |
|
183 |
} |
|
184 |
|
|
185 |
for(k = start; k < end; k++) { |
|
186 |
s[k] = t[k - start]; |
|
187 |
} |
|
188 |
} |
|
189 |
} |
|
190 |
} |
trunk/libraries/libTopology/src/org/gvsig/jts/voronoi/chen/List.java | ||
---|---|---|
1 |
package org.gvsig.jts.voronoi.chen; |
|
2 |
|
|
3 |
/** |
|
4 |
* Voronoi diagram |
|
5 |
* |
|
6 |
* Copyright(c) 1998 Ping-Che Chen |
|
7 |
* |
|
8 |
* Linked List |
|
9 |
* |
|
10 |
*/ |
|
11 |
|
|
12 |
import java.util.Enumeration; |
|
13 |
import java.util.NoSuchElementException; |
|
14 |
|
|
15 |
public class List { |
|
16 |
|
|
17 |
static class Node { |
|
18 |
Object p; |
|
19 |
Node next; |
|
20 |
Node prev; |
|
21 |
} |
|
22 |
|
|
23 |
public static class ForwardEnumeration implements Enumeration { |
|
24 |
private Node current; |
|
25 |
|
|
26 |
ForwardEnumeration(Node n) { |
|
27 |
current = n; |
|
28 |
} |
|
29 |
|
|
30 |
public boolean hasMoreElements() { |
|
31 |
return current != null; |
|
32 |
} |
|
33 |
|
|
34 |
public Object nextElement() { |
|
35 |
if(current != null) { |
|
36 |
Object p = current.p; |
|
37 |
current = current.next; |
|
38 |
return p; |
|
39 |
} |
|
40 |
else { |
|
41 |
throw new NoSuchElementException(); |
|
42 |
} |
|
43 |
} |
|
44 |
} |
|
45 |
|
|
46 |
public static class BackwardEnumeration implements Enumeration { |
|
47 |
private Node current; |
|
48 |
|
|
49 |
BackwardEnumeration(Node n) { |
|
50 |
current = n; |
|
51 |
} |
|
52 |
|
|
53 |
public boolean hasMoreElements() { |
|
54 |
return current != null; |
|
55 |
} |
|
56 |
|
|
57 |
public Object nextElement() { |
|
58 |
if(current != null) { |
|
59 |
Object p = current.p; |
|
60 |
current = current.prev; |
|
61 |
return p; |
|
62 |
} |
|
63 |
else { |
|
64 |
throw new NoSuchElementException(); |
|
65 |
} |
|
66 |
} |
|
67 |
} |
|
68 |
|
|
69 |
private Node head, tail; |
|
70 |
|
|
71 |
public List() { |
|
72 |
head = tail = null; |
|
73 |
} |
|
74 |
|
|
75 |
public void insertHead(Object p) { |
|
76 |
Node n = new Node(); |
|
77 |
n.p = p; |
|
78 |
n.next = head; |
|
79 |
n.prev = null; |
|
80 |
if(head != null) |
|
81 |
head.prev = n; |
|
82 |
head = n; |
|
83 |
if(tail == null) { |
|
84 |
tail = n; |
|
85 |
} |
|
86 |
} |
|
87 |
|
|
88 |
public void insertTail(Object p) { |
|
89 |
Node n = new Node(); |
|
90 |
n.p = p; |
|
91 |
n.next = null; |
|
92 |
n.prev = tail; |
|
93 |
if(tail != null) |
|
94 |
tail.next = n; |
|
95 |
tail = n; |
|
96 |
if(head == null) { |
|
97 |
head = n; |
|
98 |
} |
|
99 |
} |
|
100 |
|
|
101 |
public boolean isEmpty() { |
|
102 |
return head == null; |
|
103 |
} |
|
104 |
|
|
105 |
public Object firstElement() throws NoSuchElementException { |
|
106 |
if(head == null) |
|
107 |
throw new NoSuchElementException(); |
|
108 |
return head.p; |
|
109 |
} |
|
110 |
|
|
111 |
public Object lastElement() throws NoSuchElementException { |
|
112 |
if(tail == null) |
|
113 |
throw new NoSuchElementException(); |
|
114 |
return tail.p; |
|
115 |
} |
|
116 |
|
|
117 |
public boolean contains(Object p) { |
|
118 |
Node n = head; |
|
119 |
while(n != null) { |
|
120 |
if(n.p == p) |
|
121 |
return true; |
|
122 |
else |
|
123 |
n = n.next; |
|
124 |
} |
|
125 |
|
|
126 |
return false; |
|
127 |
} |
|
128 |
|
|
129 |
public boolean remove(Object p) { |
|
130 |
Node n = head; |
|
131 |
while(n != null) { |
|
132 |
if(n.p == p) { |
|
133 |
if(n.prev != null) { |
|
134 |
n.prev.next = n.next; |
|
135 |
} |
|
136 |
if(n.next != null) { |
|
137 |
n.next.prev = n.prev; |
|
138 |
} |
|
139 |
return true; |
|
140 |
} |
|
141 |
else { |
|
142 |
n = n.next; |
|
143 |
} |
|
144 |
} |
|
145 |
|
|
146 |
return false; |
|
147 |
} |
|
148 |
|
|
149 |
public void removeAll() { |
|
150 |
head = tail = null; |
|
151 |
} |
|
152 |
|
|
153 |
public Enumeration elements() { |
|
154 |
return new ForwardEnumeration(head); |
|
155 |
} |
|
156 |
|
|
157 |
public Enumeration elementsR() { |
|
158 |
return new BackwardEnumeration(tail); |
|
159 |
} |
|
160 |
} |
|
161 |
|
|
162 |
|
|
163 |
|
|
164 |
|
|
165 |
|
|
166 |
|
|
167 |
|
|
168 |
|
|
169 |
|
trunk/libraries/libTopology/src/org/gvsig/jts/voronoi/chen/Voronoi.java | ||
---|---|---|
1 |
package org.gvsig.jts.voronoi.chen; |
|
2 |
|
|
3 |
/** |
|
4 |
* Voronoi diagram |
|
5 |
* |
|
6 |
* Copyright(c) 1998 Ping-Che Chen |
|
7 |
* |
|
8 |
* This programs contains the main part of the Voronoi diagram |
|
9 |
* generators. |
|
10 |
*/ |
|
11 |
|
|
12 |
import java.awt.Graphics; |
|
13 |
import java.util.Enumeration; |
|
14 |
|
|
15 |
public class Voronoi { |
|
16 |
|
|
17 |
private static class CompoundLine { |
|
18 |
public Coord point; |
|
19 |
public Segment line; |
|
20 |
} |
|
21 |
|
|
22 |
public static Graphics g; |
|
23 |
public static int row; |
|
24 |
|
|
25 |
/** generate the Voronoi diagram */ |
|
26 |
public static Vertex[] generate(final Coord[] points) { |
|
27 |
Vertex[] v = new Vertex[points.length]; |
|
28 |
|
|
29 |
for(int i = 0; i < points.length; i++) { |
|
30 |
v[i] = new Vertex(); |
|
31 |
v[i].x = points[i].x; |
|
32 |
v[i].y = points[i].y; |
|
33 |
v[i].originalOrder = i; |
|
34 |
} |
|
35 |
|
|
36 |
sort(v, 0, v.length); |
|
37 |
for(int i = 0; i < points.length; i++) { |
|
38 |
v[i].number = i; |
|
39 |
} |
|
40 |
|
|
41 |
internal(v, 0, v.length); |
|
42 |
|
|
43 |
return v; |
|
44 |
} |
|
45 |
|
|
46 |
/** the internal help-function */ |
|
47 |
private static ConvexHull internal(Vertex[] points, int start, int end) { |
|
48 |
if(end - start > 1) { |
|
49 |
ConvexHull ch1 = internal(points, start, (start + end) / 2); |
|
50 |
ConvexHull ch2 = internal(points, (start + end) / 2, end); |
|
51 |
return merge(points, ch1, ch2, start, (start + end) / 2, end); |
|
52 |
} |
|
53 |
else { |
|
54 |
ConvexHull ch = new ConvexHull(); |
|
55 |
ch.points = new Coord[1]; |
|
56 |
ch.points[0] = points[start]; |
|
57 |
|
|
58 |
return ch; |
|
59 |
} |
|
60 |
} |
|
61 |
|
|
62 |
/** merges two adjacent exclusive Voronoi diagrams */ |
|
63 |
private static ConvexHull merge(Vertex[] points, ConvexHull ch1, ConvexHull ch2, int start, int mid, int end) { |
|
64 |
ConvexHull ch = new ConvexHull(); |
|
65 |
|
|
66 |
Segment[] supports = ConvexHull.getSupportLine(ch1, ch2, ch); |
|
67 |
Segment support = supports[0]; |
|
68 |
Segment line = Segment.getMidNormal(support); |
|
69 |
|
|
70 |
List intersects; |
|
71 |
|
|
72 |
intersects = getAllIntersects(line, support); |
|
73 |
CompoundLine p = findFirstPoint(line, intersects, support); |
|
74 |
|
|
75 |
Vertex v1 = (Vertex)support.p1; |
|
76 |
Vertex v2 = (Vertex)support.p2; |
|
77 |
|
|
78 |
VoronoiSegment l = new VoronoiSegment(v1, v2); |
|
79 |
l.p1 = line.p1; |
|
80 |
l.p2 = line.p2; |
|
81 |
l.i1 = line.i1; |
|
82 |
l.i2 = line.i2; |
|
83 |
|
|
84 |
v1.edges.insertTail(l); |
|
85 |
v2.edges.insertTail(l); |
|
86 |
|
|
87 |
while(p != null) { |
|
88 |
if(supports[1] != null && support.p1 == supports[1].p2 && support.p2 == supports[1].p1) { |
|
89 |
break; |
|
90 |
} |
|
91 |
|
|
92 |
support = findSupportLine(p, v1, v2); |
|
93 |
line = Segment.getMidNormal(support); |
|
94 |
|
|
95 |
cutLine(line, p, support); |
|
96 |
cutOldLine(v1, v2, p); |
|
97 |
|
|
98 |
intersects = getAllIntersects(line, support); |
|
99 |
p = findNextPoint(line, intersects, support); |
|
100 |
|
|
101 |
v1 = (Vertex)support.p1; |
|
102 |
v2 = (Vertex)support.p2; |
|
103 |
|
|
104 |
l = new VoronoiSegment(v1, v2); |
|
105 |
l.p1 = line.p1; |
|
106 |
l.p2 = line.p2; |
|
107 |
l.i1 = line.i1; |
|
108 |
l.i2 = line.i2; |
|
109 |
|
|
110 |
v1.edges.insertTail(l); |
|
111 |
v2.edges.insertTail(l); |
|
112 |
} |
|
113 |
|
|
114 |
return ch; |
|
115 |
} |
|
116 |
|
|
117 |
private static void cutOldLine(Vertex v1, Vertex v2, CompoundLine p) { |
|
118 |
VoronoiSegment l = (VoronoiSegment)p.line; |
|
119 |
Vertex O, A; |
|
120 |
double dx, dy; |
|
121 |
|
|
122 |
if(v1 == l.v1 || v2 == l.v1) { |
|
123 |
O = l.v1; |
|
124 |
} |
|
125 |
else { |
|
126 |
O = l.v2; |
|
127 |
} |
|
128 |
|
|
129 |
if(v1 == O) { |
|
130 |
A = v2; |
|
131 |
} |
|
132 |
else { |
|
133 |
A = v1; |
|
134 |
} |
|
135 |
|
|
136 |
dx = l.p1.x - l.p2.x; |
|
137 |
dy = l.p1.y - l.p2.y; |
|
138 |
if(l.i1) { |
|
139 |
l.p1.x = p.point.x + dx; |
|
140 |
l.p1.y = p.point.y + dy; |
|
141 |
} |
|
142 |
if(l.i2) { |
|
143 |
l.p2.x = p.point.x - dx; |
|
144 |
l.p2.y = p.point.y - dy; |
|
145 |
} |
|
146 |
|
|
147 |
double dx1, dy1, dx2, dy2; |
|
148 |
|
|
149 |
dx1 = l.p1.x - O.x; |
|
150 |
dy1 = l.p1.y - O.y; |
|
151 |
dx2 = l.p1.x - A.x; |
|
152 |
dy2 = l.p1.y - A.y; |
|
153 |
|
|
154 |
Coord oldp = null; |
|
155 |
if(dx1 * dx1 + dy1 * dy1 < dx2 * dx2 + dy2 * dy2) { |
|
156 |
if(!l.i2) { |
|
157 |
oldp = l.p2; |
|
158 |
} |
|
159 |
l.p2 = p.point; |
|
160 |
l.i2 = false; |
|
161 |
} |
|
162 |
else { |
|
163 |
if(!l.i1) { |
|
164 |
oldp = l.p1; |
|
165 |
} |
|
166 |
l.p1 = p.point; |
|
167 |
l.i1 = false; |
|
168 |
} |
|
169 |
|
|
170 |
if(oldp != null && oldp != p.point) { |
|
171 |
removeOldLines(oldp, O); |
|
172 |
} |
|
173 |
} |
|
174 |
|
|
175 |
/** remove "floating" lines */ |
|
176 |
private static void removeOldLines(Coord p, Vertex v) { |
|
177 |
Coord oldp = null; |
|
178 |
while(oldp != p) { |
|
179 |
oldp = p; |
|
180 |
Enumeration i = v.edges.elements(); |
|
181 |
while(i.hasMoreElements()) { |
|
182 |
VoronoiSegment s = (VoronoiSegment)i.nextElement(); |
|
183 |
if(s.floating) |
|
184 |
continue; |
|
185 |
if(!s.i1 && s.p1 == p) { |
|
186 |
s.floating = true; |
|
187 |
if(!s.i2) { |
|
188 |
p = s.p2; |
|
189 |
} |
|
190 |
break; |
|
191 |
} |
|
192 |
else if(!s.i2 && s.p2 == p) { |
|
193 |
s.floating = true; |
|
194 |
if(!s.i1) { |
|
195 |
p = s.p1; |
|
196 |
} |
|
197 |
break; |
|
198 |
} |
|
199 |
} |
|
200 |
} |
|
201 |
} |
|
202 |
|
|
203 |
/** Cut the mid-normal line */ |
|
204 |
private static Segment cutLine(final Segment line, CompoundLine p, Segment s) { |
|
205 |
double dx, dy; |
|
206 |
dx = line.p1.x - line.p2.x; |
|
207 |
dy = line.p1.y - line.p2.y; |
|
208 |
|
|
209 |
line.p1 = p.point; |
|
210 |
line.i1 = false; |
|
211 |
|
|
212 |
if(s.p1.x > s.p2.x) { |
|
213 |
if(dy < 0) { |
|
214 |
dy = -dy; |
|
215 |
dx = -dx; |
|
216 |
} |
|
217 |
|
|
218 |
line.p2 = new Coord(); |
|
219 |
line.p2.x = line.p1.x - dx; |
|
220 |
line.p2.y = line.p1.y - dy; |
|
221 |
} |
|
222 |
else if(s.p1.x < s.p2.x) { |
|
223 |
if(dy < 0) { |
|
224 |
dy = -dy; |
|
225 |
dx = -dx; |
|
226 |
} |
|
227 |
line.p2 = new Coord(); |
|
228 |
line.p2.x = line.p1.x + dx; |
|
229 |
line.p2.y = line.p1.y + dy; |
|
230 |
} |
|
231 |
else if(s.p1.y < s.p2.y) { |
|
232 |
if(dx < 0) { |
|
233 |
dx = -dx; |
|
234 |
dy = -dy; |
|
235 |
} |
|
236 |
line.p2 = new Coord(); |
|
237 |
line.p2.x = line.p1.x - dx; |
|
238 |
line.p2.y = line.p1.y - dy; |
|
239 |
} |
|
240 |
else { |
|
241 |
if(dx < 0) { |
|
242 |
dx = -dx; |
|
243 |
dy = -dy; |
|
244 |
} |
|
245 |
line.p2 = new Coord(); |
|
246 |
line.p2.x = line.p1.x + dx; |
|
247 |
line.p2.y = line.p1.y + dy; |
|
248 |
} |
|
249 |
|
|
250 |
return line; |
|
251 |
} |
|
252 |
|
|
253 |
/** find next supporting line */ |
|
254 |
private static Segment findSupportLine(CompoundLine p, Vertex v1, Vertex v2) { |
|
255 |
VoronoiSegment s = (VoronoiSegment)p.line; |
|
256 |
Segment r = new Segment(); |
|
257 |
|
|
258 |
if(s.v1 == v1) { |
|
259 |
r.p1 = s.v2; |
|
260 |
r.p2 = v2; |
|
261 |
} |
|
262 |
else if(s.v1 == v2) { |
|
263 |
r.p1 = v1; |
|
264 |
r.p2 = s.v2; |
|
265 |
} |
|
266 |
else if(s.v2 == v1) { |
|
267 |
r.p1 = s.v1; |
|
268 |
r.p2 = v2; |
|
269 |
} |
|
270 |
else { |
|
271 |
r.p1 = v1; |
|
272 |
r.p2 = s.v1; |
|
273 |
} |
|
274 |
|
|
275 |
return r; |
|
276 |
} |
|
277 |
|
|
278 |
/** get all intersects */ |
|
279 |
private static List getAllIntersects(final Segment l, final Segment s) { |
|
280 |
List intersects = new List(); |
|
281 |
Vertex v1 = (Vertex)s.p1; |
|
282 |
Vertex v2 = (Vertex)s.p2; |
|
283 |
Segment t = new Segment(); |
|
284 |
t.p1 = l.p1; |
|
285 |
t.p2 = l.p2; |
|
286 |
t.i1 = l.i1; |
|
287 |
t.i2 = l.i2; |
|
288 |
|
|
289 |
Enumeration i; |
|
290 |
i = v1.edges.elements(); |
|
291 |
while(i.hasMoreElements()) { |
|
292 |
VoronoiSegment ss = (VoronoiSegment)i.nextElement(); |
|
293 |
Segment sss = new Segment(); |
|
294 |
sss.p1 = ss.p1; |
|
295 |
sss.p2 = ss.p2; |
|
296 |
sss.i1 = ss.i1; |
|
297 |
sss.i2 = ss.i2; |
|
298 |
Coord p = Segment.getIntersect(sss, t); |
|
299 |
if(p != null) { |
|
300 |
CompoundLine ll = new CompoundLine(); |
|
301 |
ll.point = p; |
|
302 |
ll.line = ss; |
|
303 |
intersects.insertTail(ll); |
|
304 |
} |
|
305 |
} |
|
306 |
i = v2.edges.elements(); |
|
307 |
while(i.hasMoreElements()) { |
|
308 |
VoronoiSegment ss = (VoronoiSegment)i.nextElement(); |
|
309 |
Segment sss = new Segment(); |
|
310 |
sss.p1 = ss.p1; |
|
311 |
sss.p2 = ss.p2; |
|
312 |
sss.i1 = ss.i1; |
|
313 |
sss.i2 = ss.i2; |
|
314 |
Coord p = Segment.getIntersect(sss, t); |
|
315 |
if(p != null) { |
|
316 |
CompoundLine ll = new CompoundLine(); |
|
317 |
ll.point = p; |
|
318 |
ll.line = ss; |
|
319 |
intersects.insertTail(ll); |
|
320 |
} |
|
321 |
} |
|
322 |
|
|
323 |
return intersects; |
|
324 |
} |
|
325 |
|
|
326 |
/** find first point */ |
|
327 |
private static CompoundLine findFirstPoint(Segment line, final List intersects, final Segment s) { |
|
328 |
CompoundLine m; |
|
329 |
Enumeration i = intersects.elements(); |
|
330 |
if(!i.hasMoreElements()) |
|
331 |
return null; |
|
332 |
|
|
333 |
m = (CompoundLine)i.nextElement(); |
|
334 |
double dx = line.p1.x - line.p2.x; |
|
335 |
double dy = line.p1.y - line.p2.y; |
|
336 |
|
|
337 |
if(s.p1.x > s.p2.x) { |
|
338 |
// find max y |
|
339 |
while(i.hasMoreElements()) { |
|
340 |
CompoundLine k = (CompoundLine)i.nextElement(); |
|
341 |
if(k.point.y > m.point.y) { |
|
342 |
m = k; |
|
343 |
} |
|
344 |
} |
|
345 |
|
|
346 |
if(dy < 0) { |
|
347 |
dx = -dx; |
|
348 |
dy = -dy; |
|
349 |
} |
|
350 |
|
|
351 |
line.p1 = m.point; |
|
352 |
line.p2.x = m.point.x + dx; |
|
353 |
line.p2.y = m.point.y + dy; |
|
354 |
line.i1 = false; |
|
355 |
} |
|
356 |
else if(s.p1.x < s.p2.x) { |
|
357 |
// find min y |
|
358 |
while(i.hasMoreElements()) { |
|
359 |
CompoundLine k = (CompoundLine)i.nextElement(); |
|
360 |
if(k.point.y < m.point.y) { |
|
361 |
m = k; |
|
362 |
} |
|
363 |
} |
|
364 |
|
|
365 |
if(dy < 0) { |
|
366 |
dx = -dx; |
|
367 |
dy = -dy; |
|
368 |
} |
|
369 |
|
|
370 |
line.p1 = m.point; |
|
371 |
line.p2.x = m.point.x - dx; |
|
372 |
line.p2.y = m.point.y - dy; |
|
373 |
line.i1 = false; |
|
374 |
} |
|
375 |
else if(s.p1.y < s.p2.y) { |
|
376 |
// find max x |
|
377 |
while(i.hasMoreElements()) { |
|
378 |
CompoundLine k = (CompoundLine)i.nextElement(); |
|
379 |
if(k.point.x > m.point.x) { |
|
380 |
m = k; |
|
381 |
} |
|
382 |
} |
|
383 |
|
|
384 |
if(dx < 0) { |
|
385 |
dx = -dx; |
|
386 |
dy = -dy; |
|
387 |
} |
|
388 |
|
|
389 |
line.p1 = m.point; |
|
390 |
line.p2.x = m.point.x + dx; |
|
391 |
line.p2.y = m.point.y + dy; |
|
392 |
line.i1 = false; |
|
393 |
} |
|
394 |
else { |
|
395 |
// find min x |
|
396 |
while(i.hasMoreElements()) { |
|
397 |
CompoundLine k = (CompoundLine)i.nextElement(); |
|
398 |
if(k.point.x < m.point.x) { |
|
399 |
m = k; |
|
400 |
} |
|
401 |
} |
|
402 |
|
|
403 |
if(dx < 0) { |
|
404 |
dx = -dx; |
|
405 |
dy = -dy; |
|
406 |
} |
|
407 |
|
|
408 |
line.p1 = m.point; |
|
409 |
line.p2.x = m.point.x - dx; |
|
410 |
line.p2.y = m.point.y - dy; |
|
411 |
line.i1 = false; |
|
412 |
} |
|
413 |
|
|
414 |
return m; |
|
415 |
} |
|
416 |
|
|
417 |
/** find next point */ |
|
418 |
private static CompoundLine findNextPoint(Segment line, final List intersects, final Segment s) { |
|
419 |
CompoundLine m; |
|
420 |
Enumeration i = intersects.elements(); |
|
421 |
if(!i.hasMoreElements()) |
|
422 |
return null; |
|
423 |
|
|
424 |
do { |
|
425 |
if(!i.hasMoreElements()) |
|
426 |
return null; |
|
427 |
m = (CompoundLine)i.nextElement(); |
|
428 |
} while((!line.i1 && m.point.equals(line.p1)) || |
|
429 |
(!line.i2 && m.point.equals(line.p2))); |
|
430 |
|
|
431 |
if(s.p1.x < s.p2.x) { |
|
432 |
// find min y |
|
433 |
while(i.hasMoreElements()) { |
|
434 |
CompoundLine k = (CompoundLine)i.nextElement(); |
|
435 |
if((!line.i1 && k.point.equals(line.p1)) || |
|
436 |
(!line.i2 && k.point.equals(line.p2))) |
|
437 |
continue; |
|
438 |
if(k.point.y < m.point.y) { |
|
439 |
m = k; |
|
440 |
} |
|
441 |
} |
|
442 |
} |
|
443 |
else if(s.p1.x > s.p2.x) { |
|
444 |
// find max y |
|
445 |
while(i.hasMoreElements()) { |
|
446 |
CompoundLine k = (CompoundLine)i.nextElement(); |
|
447 |
if((!line.i1 && k.point.equals(line.p1)) || |
|
448 |
(!line.i2 && k.point.equals(line.p2))) |
|
449 |
continue; |
|
450 |
if(k.point.y > m.point.y) { |
|
451 |
m = k; |
|
452 |
|
|
453 |
} |
|
454 |
} |
|
455 |
} |
|
456 |
else if(s.p1.y > s.p2.y) { |
|
457 |
// find min x |
|
458 |
while(i.hasMoreElements()) { |
|
459 |
CompoundLine k = (CompoundLine)i.nextElement(); |
|
460 |
if((!line.i1 && k.point.equals(line.p1)) || |
|
461 |
(!line.i2 && k.point.equals(line.p2))) |
|
462 |
continue; |
|
463 |
if(k.point.x < m.point.x) { |
|
464 |
m = k; |
|
465 |
} |
|
466 |
} |
|
467 |
} |
|
468 |
else { |
|
469 |
// find max x |
|
470 |
while(i.hasMoreElements()) { |
|
471 |
CompoundLine k = (CompoundLine)i.nextElement(); |
|
472 |
if((!line.i1 && k.point.equals(line.p1)) || |
|
473 |
(!line.i2 && k.point.equals(line.p2))) |
|
474 |
continue; |
|
475 |
if(k.point.x > m.point.x) { |
|
476 |
m = k; |
|
477 |
} |
|
478 |
} |
|
479 |
} |
|
480 |
|
|
481 |
line.p2 = m.point; |
|
482 |
line.i2 = false; |
|
483 |
|
|
484 |
return m; |
|
485 |
} |
|
486 |
|
|
487 |
/** compares two points by x and y */ |
|
488 |
private static int compare(final Coord p1, final Coord p2) { |
|
489 |
if(p1.x < p2.x) { |
|
490 |
return 1; |
|
491 |
} |
|
492 |
else if(p1.x > p2.x) { |
|
493 |
return -1; |
|
494 |
} |
|
495 |
else if(p1.y < p2.y) { |
|
496 |
return 1; |
|
497 |
} |
|
498 |
else if(p1.y > p2.y) { |
|
499 |
return -1; |
|
500 |
} |
|
501 |
else { |
|
502 |
return 0; |
|
503 |
} |
|
504 |
} |
|
505 |
|
|
506 |
/** sorts an array of points (by merge sort) */ |
|
507 |
private static void sort(Coord[] points, int start, int end) { |
|
508 |
if(end - start > 1) { |
|
509 |
sort(points, start, (start + end) / 2); |
|
510 |
sort(points, (start + end) / 2, end); |
|
511 |
|
|
512 |
Coord[] t = new Coord[end - start]; |
|
513 |
int i = start; |
|
514 |
int j = (start + end) / 2; |
|
515 |
int k = 0; |
|
516 |
while(i < (start + end) / 2 && j < end) { |
|
517 |
if(compare(points[i], points[j]) > 0) { |
|
518 |
t[k++] = points[i++]; |
|
519 |
} |
|
520 |
else { |
|
521 |
t[k++] = points[j++]; |
|
522 |
} |
|
523 |
} |
|
524 |
|
|
525 |
while(i < (start + end) / 2) { |
|
526 |
t[k++] = points[i++]; |
|
527 |
} |
|
528 |
|
|
529 |
while(j < end) { |
|
530 |
t[k++] = points[j++]; |
|
531 |
} |
|
532 |
|
|
533 |
for(k = start; k < end; k++) { |
|
534 |
points[k] = t[k - start]; |
|
535 |
} |
|
536 |
} |
|
537 |
} |
|
538 |
} |
trunk/libraries/libTopology/src/org/gvsig/jts/voronoi/chen/Vertex.java | ||
---|---|---|
1 |
package org.gvsig.jts.voronoi.chen; |
|
2 |
|
|
3 |
/** |
|
4 |
* Voronoi diagram |
|
5 |
* |
|
6 |
* Copyright(c) 1998 Ping-Che Chen |
|
7 |
* |
|
8 |
* This program defines the vertices in a voronoi diagram. |
|
9 |
* This is a internal data structure. |
|
10 |
*/ |
|
11 |
|
|
12 |
public class Vertex extends Coord { |
|
13 |
|
|
14 |
public List edges = null; |
|
15 |
public int number; |
|
16 |
|
|
17 |
public int originalOrder; |
|
18 |
|
|
19 |
public Vertex() { |
|
20 |
edges = new List(); |
|
21 |
} |
|
22 |
} |
trunk/libraries/libTopology/src/org/gvsig/jts/voronoi/chen/VoronoiSegment.java | ||
---|---|---|
1 |
package org.gvsig.jts.voronoi.chen; |
|
2 |
|
|
3 |
/** |
|
4 |
* Voronoi diagram |
|
5 |
* |
|
6 |
* Copyright(c) 1998 Ping-Che Chen |
|
7 |
* |
|
8 |
* This program defines the line segment used in the Voronoi |
|
9 |
* diagram problem. |
|
10 |
* |
|
11 |
*/ |
|
12 |
|
|
13 |
public class VoronoiSegment extends Segment { |
|
14 |
|
|
15 |
VoronoiSegment(Vertex v1, Vertex v2) { |
|
16 |
this.v1 = v1; |
|
17 |
this.v2 = v2; |
|
18 |
floating = false; |
|
19 |
} |
|
20 |
|
|
21 |
public final Vertex v1, v2; |
|
22 |
public boolean floating; |
|
23 |
|
|
24 |
} |
Also available in: Unified diff