Revision 21245

View differences:

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