bribera-rubyvor 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +7 -0
- data/Manifest.txt +20 -0
- data/README.txt +45 -0
- data/Rakefile +36 -0
- data/ext/Doc +30 -0
- data/ext/edgelist.c +206 -0
- data/ext/extconf.rb +3 -0
- data/ext/geometry.c +221 -0
- data/ext/heap.c +120 -0
- data/ext/memory.c +120 -0
- data/ext/output.c +262 -0
- data/ext/vdefs.h +149 -0
- data/ext/voronoi.c +277 -0
- data/ext/voronoi_interface.c +213 -0
- data/lib/ruby_vor/decomposition.rb +22 -0
- data/lib/ruby_vor/point.rb +19 -0
- data/lib/ruby_vor/version.rb +3 -0
- data/lib/ruby_vor.rb +13 -0
- data/rubyvor.gemspec +34 -0
- data/test/test_voronoi_interface.rb +158 -0
- metadata +85 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest.txt
|
3
|
+
README.txt
|
4
|
+
Rakefile
|
5
|
+
ext/Doc
|
6
|
+
ext/edgelist.c
|
7
|
+
ext/extconf.rb
|
8
|
+
ext/geometry.c
|
9
|
+
ext/heap.c
|
10
|
+
ext/memory.c
|
11
|
+
ext/output.c
|
12
|
+
ext/vdefs.h
|
13
|
+
ext/voronoi.c
|
14
|
+
ext/voronoi_interface.c
|
15
|
+
lib/ruby_vor.rb
|
16
|
+
lib/ruby_vor/decomposition.rb
|
17
|
+
lib/ruby_vor/point.rb
|
18
|
+
lib/ruby_vor/version.rb
|
19
|
+
rubyvor.gemspec
|
20
|
+
test/test_voronoi_interface.rb
|
data/README.txt
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
= rubyvor
|
2
|
+
|
3
|
+
Efficient Voronoi diagrams and Delaunay trianglation for Ruby
|
4
|
+
|
5
|
+
== Description
|
6
|
+
|
7
|
+
RubyVor provides efficient computation of Voronoi diagrams and
|
8
|
+
Delaunay triangulation for a set of Ruby points. It is intended to
|
9
|
+
function as a complemenet to GeoRuby. These structures can be used to
|
10
|
+
compute a nearest-neighbor graph for a set of points. This graph can
|
11
|
+
in turn be used for proximity-based clustering of the input points.
|
12
|
+
|
13
|
+
== Usage:
|
14
|
+
|
15
|
+
TODO
|
16
|
+
|
17
|
+
== LICENSE:
|
18
|
+
|
19
|
+
Original public-domain C code (by Steven Fortune; http://ect.bell-labs.com/who/sjf/) and
|
20
|
+
memory-management fixes for said C code (by Derek Bradley; http://www.derekbradley.ca)
|
21
|
+
used (and released under the MIT-LICENSE) with permission.
|
22
|
+
|
23
|
+
|
24
|
+
(The MIT License)
|
25
|
+
|
26
|
+
Copyright (c) 2008 Brendan Ribera <brendan.ribera+rubyvor@gmail.com>
|
27
|
+
|
28
|
+
|
29
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
30
|
+
of this software and associated documentation files (the "Software"), to deal
|
31
|
+
in the Software without restriction, including without limitation the rights
|
32
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
33
|
+
copies of the Software, and to permit persons to whom the Software is
|
34
|
+
furnished to do so, subject to the following conditions:
|
35
|
+
|
36
|
+
The above copyright notice and this permission notice shall be included in
|
37
|
+
all copies or substantial portions of the Software.
|
38
|
+
|
39
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
40
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
41
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
42
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
43
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
44
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
45
|
+
THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
require './lib/ruby_vor/version.rb'
|
6
|
+
|
7
|
+
EXT = "ext/voronoi_interface.#{Hoe::DLEXT}"
|
8
|
+
|
9
|
+
Hoe.new('rubyvor', RubyVor::VERSION) do |p|
|
10
|
+
p.developer('Brendan Ribera', 'brendan.ribera+rubyvor@gmail.com')
|
11
|
+
|
12
|
+
p.url = 'http://github.com/bribera/rubyvor'
|
13
|
+
|
14
|
+
# C extension goodness
|
15
|
+
p.spec_extras[:extensions] = "ext/extconf.rb"
|
16
|
+
p.clean_globs << EXT << 'ext/*.o' << 'ext/Makefile'
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "Compile extensions"
|
20
|
+
task :compile => EXT
|
21
|
+
task :test => :compile
|
22
|
+
|
23
|
+
file EXT => ['ext/extconf.rb', 'ext/voronoi_interface.c'] do
|
24
|
+
Dir.chdir 'ext' do
|
25
|
+
ruby 'extconf.rb'
|
26
|
+
sh 'make'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "Prepare for github upload"
|
31
|
+
task :github do
|
32
|
+
system "git ls-files | egrep -v \"\\.gitignore\" > Manifest.txt"
|
33
|
+
system "rake debug_gem | egrep -v \"^\\(in\" > rubyvor.gemspec"
|
34
|
+
end
|
35
|
+
|
36
|
+
task :gem => :github
|
data/ext/Doc
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
voronoi - compute Voronoi diagram or Delaunay triangulation
|
2
|
+
SYNOPSIS
|
3
|
+
voronoi [-s -t] <pointfile >outputfile
|
4
|
+
|
5
|
+
Voronoi reads the standard input for a set of points in the plane and writes either
|
6
|
+
the Voronoi diagram or the Delaunay triangulation to the standard output.
|
7
|
+
Each input line should consist of two real numbers, separated by white space.
|
8
|
+
|
9
|
+
If option
|
10
|
+
-t
|
11
|
+
is present, the Delaunay triangulation is produced.
|
12
|
+
Each output line is a triple
|
13
|
+
i j k
|
14
|
+
which are the indices of the three points in a Delaunay triangle. Points are
|
15
|
+
numbered starting at 0. If this option is not present, the
|
16
|
+
Voronoi diagram is produced. There are four output record types.
|
17
|
+
s a b
|
18
|
+
indicates that an input point at coordinates
|
19
|
+
l a b c
|
20
|
+
indicates a line with equation ax + by = c.
|
21
|
+
v a b
|
22
|
+
indicates a vertex at a b.
|
23
|
+
e l v1 v2
|
24
|
+
indicates a Voronoi segment which is a subsegment of line number l;
|
25
|
+
with endpoints numbered v1 and v2. If v1 or v2 is -1, the line
|
26
|
+
extends to infinity.
|
27
|
+
|
28
|
+
AUTHOR
|
29
|
+
Steve J. Fortune (1987) A Sweepline Algorithm for Voronoi Diagrams,
|
30
|
+
Algorithmica 2, 153-174.
|
data/ext/edgelist.c
ADDED
@@ -0,0 +1,206 @@
|
|
1
|
+
|
2
|
+
/*** EDGELIST.C ***/
|
3
|
+
|
4
|
+
#include "vdefs.h"
|
5
|
+
|
6
|
+
VoronoiState rubyvorState;
|
7
|
+
|
8
|
+
static int ELhashsize ;
|
9
|
+
static Halfedge * ELleftend, * ELrightend, ** ELhash ;
|
10
|
+
static Freelist hfl ;
|
11
|
+
static int ntry, totalsearch ;
|
12
|
+
|
13
|
+
void
|
14
|
+
ELinitialize(void)
|
15
|
+
{
|
16
|
+
int i ;
|
17
|
+
|
18
|
+
freeinit(&hfl, sizeof(Halfedge)) ;
|
19
|
+
ELhashsize = 2 * rubyvorState.sqrt_nsites ;
|
20
|
+
ELhash = (Halfedge **)myalloc( sizeof(*ELhash) * ELhashsize) ;
|
21
|
+
for (i = 0 ; i < ELhashsize ; i++)
|
22
|
+
{
|
23
|
+
ELhash[i] = (Halfedge *)NULL ;
|
24
|
+
}
|
25
|
+
ELleftend = HEcreate((Edge *)NULL, 0) ;
|
26
|
+
ELrightend = HEcreate((Edge *)NULL, 0) ;
|
27
|
+
ELleftend->ELleft = (Halfedge *)NULL ;
|
28
|
+
ELleftend->ELright = ELrightend ;
|
29
|
+
ELrightend->ELleft = ELleftend ;
|
30
|
+
ELrightend->ELright = (Halfedge *)NULL ;
|
31
|
+
ELhash[0] = ELleftend ;
|
32
|
+
ELhash[ELhashsize-1] = ELrightend ;
|
33
|
+
}
|
34
|
+
|
35
|
+
Halfedge *
|
36
|
+
HEcreate(Edge * e, int pm)
|
37
|
+
{
|
38
|
+
Halfedge * answer ;
|
39
|
+
|
40
|
+
answer = (Halfedge *)getfree(&hfl) ;
|
41
|
+
answer->ELedge = e ;
|
42
|
+
answer->ELpm = pm ;
|
43
|
+
answer->PQnext = (Halfedge *)NULL ;
|
44
|
+
answer->vertex = (Site *)NULL ;
|
45
|
+
answer->ELrefcnt = 0 ;
|
46
|
+
return (answer) ;
|
47
|
+
}
|
48
|
+
|
49
|
+
void
|
50
|
+
ELinsert(Halfedge * lb, Halfedge * new)
|
51
|
+
{
|
52
|
+
new->ELleft = lb ;
|
53
|
+
new->ELright = lb->ELright ;
|
54
|
+
(lb->ELright)->ELleft = new ;
|
55
|
+
lb->ELright = new ;
|
56
|
+
}
|
57
|
+
|
58
|
+
/* Get entry from hash table, pruning any deleted nodes */
|
59
|
+
|
60
|
+
Halfedge *
|
61
|
+
ELgethash(int b)
|
62
|
+
{
|
63
|
+
Halfedge * he ;
|
64
|
+
|
65
|
+
if ((b < 0) || (b >= ELhashsize))
|
66
|
+
{
|
67
|
+
return ((Halfedge *)NULL) ;
|
68
|
+
}
|
69
|
+
he = ELhash[b] ;
|
70
|
+
if ((he == (Halfedge *)NULL) || (he->ELedge != (Edge *)DELETED))
|
71
|
+
{
|
72
|
+
return (he) ;
|
73
|
+
}
|
74
|
+
/* Hash table points to deleted half edge. Patch as necessary. */
|
75
|
+
ELhash[b] = (Halfedge *)NULL ;
|
76
|
+
if ((--(he->ELrefcnt)) == 0)
|
77
|
+
{
|
78
|
+
makefree((Freenode *)he, (Freelist *)&hfl) ;
|
79
|
+
}
|
80
|
+
return ((Halfedge *)NULL) ;
|
81
|
+
}
|
82
|
+
|
83
|
+
Halfedge *
|
84
|
+
ELleftbnd(Point * p)
|
85
|
+
{
|
86
|
+
int i, bucket ;
|
87
|
+
Halfedge * he ;
|
88
|
+
|
89
|
+
/* Use hash table to get close to desired halfedge */
|
90
|
+
bucket = (p->x - rubyvorState.xmin) / rubyvorState.deltax * ELhashsize ;
|
91
|
+
if (bucket < 0)
|
92
|
+
{
|
93
|
+
bucket = 0 ;
|
94
|
+
}
|
95
|
+
if (bucket >= ELhashsize)
|
96
|
+
{
|
97
|
+
bucket = ELhashsize - 1 ;
|
98
|
+
}
|
99
|
+
he = ELgethash(bucket) ;
|
100
|
+
if (he == (Halfedge *)NULL)
|
101
|
+
{
|
102
|
+
for (i = 1 ; 1 ; i++)
|
103
|
+
{
|
104
|
+
if ((he = ELgethash(bucket-i)) != (Halfedge *)NULL)
|
105
|
+
{
|
106
|
+
break ;
|
107
|
+
}
|
108
|
+
if ((he = ELgethash(bucket+i)) != (Halfedge *)NULL)
|
109
|
+
{
|
110
|
+
break ;
|
111
|
+
}
|
112
|
+
}
|
113
|
+
totalsearch += i ;
|
114
|
+
}
|
115
|
+
ntry++ ;
|
116
|
+
/* Now search linear list of halfedges for the corect one */
|
117
|
+
if (he == ELleftend || (he != ELrightend && right_of(he,p)))
|
118
|
+
{
|
119
|
+
do {
|
120
|
+
he = he->ELright ;
|
121
|
+
} while (he != ELrightend && right_of(he,p)) ;
|
122
|
+
he = he->ELleft ;
|
123
|
+
}
|
124
|
+
else
|
125
|
+
{
|
126
|
+
do {
|
127
|
+
he = he->ELleft ;
|
128
|
+
} while (he != ELleftend && !right_of(he,p)) ;
|
129
|
+
}
|
130
|
+
/*** Update hash table and reference counts ***/
|
131
|
+
if ((bucket > 0) && (bucket < ELhashsize-1))
|
132
|
+
{
|
133
|
+
if (ELhash[bucket] != (Halfedge *)NULL)
|
134
|
+
{
|
135
|
+
(ELhash[bucket]->ELrefcnt)-- ;
|
136
|
+
}
|
137
|
+
ELhash[bucket] = he ;
|
138
|
+
(ELhash[bucket]->ELrefcnt)++ ;
|
139
|
+
}
|
140
|
+
return (he) ;
|
141
|
+
}
|
142
|
+
|
143
|
+
/*** This delete routine can't reclaim node, since pointers from hash
|
144
|
+
: table may be present.
|
145
|
+
***/
|
146
|
+
|
147
|
+
void
|
148
|
+
ELdelete(Halfedge * he)
|
149
|
+
{
|
150
|
+
(he->ELleft)->ELright = he->ELright ;
|
151
|
+
(he->ELright)->ELleft = he->ELleft ;
|
152
|
+
he->ELedge = (Edge *)DELETED ;
|
153
|
+
}
|
154
|
+
|
155
|
+
Halfedge *
|
156
|
+
ELright(Halfedge * he)
|
157
|
+
{
|
158
|
+
return (he->ELright) ;
|
159
|
+
}
|
160
|
+
|
161
|
+
Halfedge *
|
162
|
+
ELleft(Halfedge * he)
|
163
|
+
{
|
164
|
+
return (he->ELleft) ;
|
165
|
+
}
|
166
|
+
|
167
|
+
Site *
|
168
|
+
leftreg(Halfedge * he)
|
169
|
+
{
|
170
|
+
if (he->ELedge == (Edge *)NULL)
|
171
|
+
{
|
172
|
+
return(rubyvorState.bottomsite) ;
|
173
|
+
}
|
174
|
+
return (he->ELpm == le ? he->ELedge->reg[le] :
|
175
|
+
he->ELedge->reg[re]) ;
|
176
|
+
}
|
177
|
+
|
178
|
+
Site *
|
179
|
+
rightreg(Halfedge * he)
|
180
|
+
{
|
181
|
+
if (he->ELedge == (Edge *)NULL)
|
182
|
+
{
|
183
|
+
return(rubyvorState.bottomsite) ;
|
184
|
+
}
|
185
|
+
return (he->ELpm == le ? he->ELedge->reg[re] :
|
186
|
+
he->ELedge->reg[le]) ;
|
187
|
+
}
|
188
|
+
|
189
|
+
/*
|
190
|
+
* Semi-hacky way to access these static variables. Placing them inside rubyvorState
|
191
|
+
* causes pointer issues that I don't want to debug, and they're only accessed briefly
|
192
|
+
* inside of voronoi.c. Since we're just doing pointer comparison there, this is an
|
193
|
+
* acceptable compromise.
|
194
|
+
*/
|
195
|
+
|
196
|
+
Halfedge *
|
197
|
+
getELleftend(void)
|
198
|
+
{
|
199
|
+
return(ELleftend);
|
200
|
+
}
|
201
|
+
|
202
|
+
Halfedge *
|
203
|
+
getELrightend(void)
|
204
|
+
{
|
205
|
+
return(ELrightend);
|
206
|
+
}
|
data/ext/extconf.rb
ADDED
data/ext/geometry.c
ADDED
@@ -0,0 +1,221 @@
|
|
1
|
+
|
2
|
+
/*** GEOMETRY.C ***/
|
3
|
+
|
4
|
+
#include <math.h>
|
5
|
+
#include "vdefs.h"
|
6
|
+
|
7
|
+
VoronoiState rubyvorState;
|
8
|
+
|
9
|
+
static Freelist efl;
|
10
|
+
|
11
|
+
void
|
12
|
+
geominit(void)
|
13
|
+
{
|
14
|
+
freeinit(&efl, sizeof(Edge)) ;
|
15
|
+
rubyvorState.nvertices = rubyvorState.nedges = 0 ;
|
16
|
+
rubyvorState.sqrt_nsites = sqrt(rubyvorState.nsites+4) ;
|
17
|
+
rubyvorState.deltay = rubyvorState.ymax - rubyvorState.ymin ;
|
18
|
+
rubyvorState.deltax = rubyvorState.xmax - rubyvorState.xmin ;
|
19
|
+
}
|
20
|
+
|
21
|
+
Edge *
|
22
|
+
bisect(Site * s1, Site * s2)
|
23
|
+
{
|
24
|
+
float dx, dy, adx, ady ;
|
25
|
+
Edge * newedge ;
|
26
|
+
|
27
|
+
newedge = (Edge *)getfree(&efl) ;
|
28
|
+
newedge->reg[0] = s1 ;
|
29
|
+
newedge->reg[1] = s2 ;
|
30
|
+
ref(s1) ;
|
31
|
+
ref(s2) ;
|
32
|
+
newedge->ep[0] = newedge->ep[1] = (Site *)NULL ;
|
33
|
+
dx = s2->coord.x - s1->coord.x ;
|
34
|
+
dy = s2->coord.y - s1->coord.y ;
|
35
|
+
adx = dx>0 ? dx : -dx ;
|
36
|
+
ady = dy>0 ? dy : -dy ;
|
37
|
+
newedge->c = s1->coord.x * dx + s1->coord.y * dy + (dx*dx +
|
38
|
+
dy*dy) * 0.5 ;
|
39
|
+
if (adx > ady)
|
40
|
+
{
|
41
|
+
newedge->a = 1.0 ;
|
42
|
+
newedge->b = dy/dx ;
|
43
|
+
newedge->c /= dx ;
|
44
|
+
}
|
45
|
+
else
|
46
|
+
{
|
47
|
+
newedge->b = 1.0 ;
|
48
|
+
newedge->a = dx/dy ;
|
49
|
+
newedge->c /= dy ;
|
50
|
+
}
|
51
|
+
newedge->edgenbr = rubyvorState.nedges ;
|
52
|
+
out_bisector(newedge) ;
|
53
|
+
rubyvorState.nedges++ ;
|
54
|
+
return (newedge) ;
|
55
|
+
}
|
56
|
+
|
57
|
+
Site *
|
58
|
+
intersect(Halfedge * el1, Halfedge * el2)
|
59
|
+
{
|
60
|
+
Edge * e1, * e2, * e ;
|
61
|
+
Halfedge * el ;
|
62
|
+
float d, xint, yint ;
|
63
|
+
int right_of_site ;
|
64
|
+
Site * v ;
|
65
|
+
|
66
|
+
e1 = el1->ELedge ;
|
67
|
+
e2 = el2->ELedge ;
|
68
|
+
if ((e1 == (Edge*)NULL) || (e2 == (Edge*)NULL))
|
69
|
+
{
|
70
|
+
return ((Site *)NULL) ;
|
71
|
+
}
|
72
|
+
if (e1->reg[1] == e2->reg[1])
|
73
|
+
{
|
74
|
+
return ((Site *)NULL) ;
|
75
|
+
}
|
76
|
+
d = (e1->a * e2->b) - (e1->b * e2->a) ;
|
77
|
+
if ((-1.0e-10 < d) && (d < 1.0e-10))
|
78
|
+
{
|
79
|
+
return ((Site *)NULL) ;
|
80
|
+
}
|
81
|
+
xint = (e1->c * e2->b - e2->c * e1->b) / d ;
|
82
|
+
yint = (e2->c * e1->a - e1->c * e2->a) / d ;
|
83
|
+
if ((e1->reg[1]->coord.y < e2->reg[1]->coord.y) ||
|
84
|
+
(e1->reg[1]->coord.y == e2->reg[1]->coord.y &&
|
85
|
+
e1->reg[1]->coord.x < e2->reg[1]->coord.x))
|
86
|
+
{
|
87
|
+
el = el1 ;
|
88
|
+
e = e1 ;
|
89
|
+
}
|
90
|
+
else
|
91
|
+
{
|
92
|
+
el = el2 ;
|
93
|
+
e = e2 ;
|
94
|
+
}
|
95
|
+
right_of_site = (xint >= e->reg[1]->coord.x) ;
|
96
|
+
if ((right_of_site && (el->ELpm == le)) ||
|
97
|
+
(!right_of_site && (el->ELpm == re)))
|
98
|
+
{
|
99
|
+
return ((Site *)NULL) ;
|
100
|
+
}
|
101
|
+
v = (Site *)getfree(&(rubyvorState.sfl)) ;
|
102
|
+
v->refcnt = 0 ;
|
103
|
+
v->coord.x = xint ;
|
104
|
+
v->coord.y = yint ;
|
105
|
+
return (v) ;
|
106
|
+
}
|
107
|
+
|
108
|
+
/*** returns 1 if p is to right of halfedge e ***/
|
109
|
+
|
110
|
+
int
|
111
|
+
right_of(Halfedge * el, Point * p)
|
112
|
+
{
|
113
|
+
Edge * e ;
|
114
|
+
Site * topsite ;
|
115
|
+
int right_of_site, above, fast ;
|
116
|
+
float dxp, dyp, dxs, t1, t2, t3, yl ;
|
117
|
+
|
118
|
+
e = el->ELedge ;
|
119
|
+
topsite = e->reg[1] ;
|
120
|
+
right_of_site = (p->x > topsite->coord.x) ;
|
121
|
+
if (right_of_site && (el->ELpm == le))
|
122
|
+
{
|
123
|
+
return (1) ;
|
124
|
+
}
|
125
|
+
if(!right_of_site && (el->ELpm == re))
|
126
|
+
{
|
127
|
+
return (0) ;
|
128
|
+
}
|
129
|
+
if (e->a == 1.0)
|
130
|
+
{
|
131
|
+
dyp = p->y - topsite->coord.y ;
|
132
|
+
dxp = p->x - topsite->coord.x ;
|
133
|
+
fast = 0 ;
|
134
|
+
if ((!right_of_site & (e->b < 0.0)) ||
|
135
|
+
(right_of_site & (e->b >= 0.0)))
|
136
|
+
{
|
137
|
+
fast = above = (dyp >= e->b*dxp) ;
|
138
|
+
}
|
139
|
+
else
|
140
|
+
{
|
141
|
+
above = ((p->x + p->y * e->b) > (e->c)) ;
|
142
|
+
if (e->b < 0.0)
|
143
|
+
{
|
144
|
+
above = !above ;
|
145
|
+
}
|
146
|
+
if (!above)
|
147
|
+
{
|
148
|
+
fast = 1 ;
|
149
|
+
}
|
150
|
+
}
|
151
|
+
if (!fast)
|
152
|
+
{
|
153
|
+
dxs = topsite->coord.x - (e->reg[0])->coord.x ;
|
154
|
+
above = (e->b * (dxp*dxp - dyp*dyp))
|
155
|
+
<
|
156
|
+
(dxs * dyp * (1.0 + 2.0 * dxp /
|
157
|
+
dxs + e->b * e->b)) ;
|
158
|
+
if (e->b < 0.0)
|
159
|
+
{
|
160
|
+
above = !above ;
|
161
|
+
}
|
162
|
+
}
|
163
|
+
}
|
164
|
+
else /*** e->b == 1.0 ***/
|
165
|
+
{
|
166
|
+
yl = e->c - e->a * p->x ;
|
167
|
+
t1 = p->y - yl ;
|
168
|
+
t2 = p->x - topsite->coord.x ;
|
169
|
+
t3 = yl - topsite->coord.y ;
|
170
|
+
above = ((t1*t1) > ((t2 * t2) + (t3 * t3))) ;
|
171
|
+
}
|
172
|
+
return (el->ELpm == le ? above : !above) ;
|
173
|
+
}
|
174
|
+
|
175
|
+
void
|
176
|
+
endpoint(Edge * e, int lr, Site * s)
|
177
|
+
{
|
178
|
+
e->ep[lr] = s ;
|
179
|
+
ref(s) ;
|
180
|
+
if (e->ep[re-lr] == (Site *)NULL)
|
181
|
+
{
|
182
|
+
return ;
|
183
|
+
}
|
184
|
+
out_ep(e) ;
|
185
|
+
deref(e->reg[le]) ;
|
186
|
+
deref(e->reg[re]) ;
|
187
|
+
makefree((Freenode *)e, (Freelist *) &efl) ;
|
188
|
+
}
|
189
|
+
|
190
|
+
float
|
191
|
+
dist(Site * s, Site * t)
|
192
|
+
{
|
193
|
+
float dx,dy ;
|
194
|
+
|
195
|
+
dx = s->coord.x - t->coord.x ;
|
196
|
+
dy = s->coord.y - t->coord.y ;
|
197
|
+
return (sqrt(dx*dx + dy*dy)) ;
|
198
|
+
}
|
199
|
+
|
200
|
+
void
|
201
|
+
makevertex(Site * v)
|
202
|
+
{
|
203
|
+
v->sitenbr = rubyvorState.nvertices++ ;
|
204
|
+
out_vertex(v) ;
|
205
|
+
}
|
206
|
+
|
207
|
+
void
|
208
|
+
deref(Site * v)
|
209
|
+
{
|
210
|
+
if (--(v->refcnt) == 0 )
|
211
|
+
{
|
212
|
+
makefree((Freenode *)v, (Freelist *)&(rubyvorState.sfl)) ;
|
213
|
+
}
|
214
|
+
}
|
215
|
+
|
216
|
+
void
|
217
|
+
ref(Site * v)
|
218
|
+
{
|
219
|
+
++(v->refcnt) ;
|
220
|
+
}
|
221
|
+
|