abscondment-rubyvor 0.1.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.
@@ -0,0 +1,56 @@
1
+ === 0.1.2 / 2009-04-24
2
+
3
+ * Compilation fixes for OSX. Thanks to jpemberthy and febuiles!
4
+
5
+ === 0.1.1 / 2009-01-15
6
+
7
+ * LibXML require conflict fix.
8
+
9
+ === 0.1.0 / 2009-01-13
10
+
11
+ * Configurable handling of "no neighbors" case.
12
+ * Tests for "no neighbors" case.
13
+
14
+ === 0.0.9 / 2009-01-01
15
+
16
+ Happy New Year!
17
+ * New speed improvements.
18
+ * Additional visualization tweaks.
19
+ * More tests.
20
+
21
+ === 0.0.8 / 2008-12-23
22
+
23
+ * Several C warning fixes (more ISO C compliance unused variables, etc)
24
+ * Moved minimum_spanning_tree computation into C, yielding large speed gain.
25
+ * Basic SVG visualization.
26
+
27
+ === 0.0.7 / 2008-12-12
28
+
29
+ * Bugfix: there are cases where performing a Delaunay triangulation on a set of points will not yield a complete nearest neighbor graph. This causes computation of the minimum spanning tree and clustering to fail for these nodes (they always appear as disconnected from the main graph).
30
+
31
+ * To fix this, the nn_graph function now treats any point that is excluded from Delaunay triangulation as having *all* other points as nearest neighbors. This is a naive approach, but is a good fix while a more efficient solution is considered.
32
+
33
+ === 0.0.6 / 2008-12-11
34
+
35
+ * Implementation of cluster_by_size to partition points into N clusters.
36
+
37
+ === 0.0.5 / 2008-12-10
38
+
39
+ * Beginnings of clustering and useful graph algorithms.
40
+ * Some refactoring of C methods.
41
+
42
+ === 0.0.4 / 2008-12-04
43
+
44
+ * Fixed 64-bit segfaults due to improper definition of the myrealloc() function.
45
+
46
+ === 0.0.3 / 2008-12-03
47
+
48
+ * Fixed a segfault by using rb_ary_push instead of direct pointer manipulation. Much simpler.
49
+
50
+ === 0.0.2 / 2008-12-03
51
+
52
+ * Computations succeed on a naive Point class, returning raw values for the associated Voronoi Diagram and Delaunay triangulation.
53
+
54
+ === 0.0.1 / 2008-12-01
55
+
56
+ * Initial release. Nothing works.
@@ -0,0 +1,30 @@
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/rb_cComputation.c
13
+ ext/rb_cPoint.c
14
+ ext/rb_cPriorityQueue.c
15
+ ext/ruby_vor_c.c
16
+ ext/ruby_vor_c.h
17
+ ext/vdefs.h
18
+ ext/voronoi.c
19
+ lib/ruby_vor.rb
20
+ lib/ruby_vor/computation.rb
21
+ lib/ruby_vor/geo_ruby_extensions.rb
22
+ lib/ruby_vor/point.rb
23
+ lib/ruby_vor/priority_queue.rb
24
+ lib/ruby_vor/version.rb
25
+ lib/ruby_vor/visualizer.rb
26
+ rubyvor.gemspec
27
+ test/test_computation.rb
28
+ test/test_point.rb
29
+ test/test_priority_queue.rb
30
+ test/test_voronoi_interface.rb
@@ -0,0 +1,76 @@
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
+ require 'lib/ruby_vor'
16
+ require 'pp'
17
+
18
+ points = [
19
+ RubyVor::Point.new(120, 290),
20
+ RubyVor::Point.new(110, 120),
21
+ RubyVor::Point.new(160, 90.2),
22
+ RubyVor::Point.new(3.14159265, 3.14159265)
23
+ ]
24
+
25
+ # Compute the diagram & triangulation
26
+ comp = RubyVor::VDDT::Computation.from_points(points)
27
+
28
+ puts "The nearest-neighbor graph:"
29
+ pp comp.nn_graph
30
+
31
+ puts "\nThe minimum-spanning tree:"
32
+ pp comp.minimum_spanning_tree
33
+
34
+ #
35
+ # Visualize these things as SVGs
36
+ #
37
+
38
+ # Just the triangulation
39
+ RubyVor::Visualizer.make_svg(comp, :name => 'tri.svg')
40
+
41
+ # Just the MST
42
+ RubyVor::Visualizer.make_svg(comp, :name => 'mst.svg', :triangulation => false, :mst => true)
43
+
44
+ # Voronoi diagram and the triangulation
45
+ RubyVor::Visualizer.make_svg(comp, :name => 'dia.svg', :voronoi_diagram => true)
46
+
47
+
48
+ == LICENSE:
49
+
50
+ Original public-domain C code (by Steven Fortune; http://ect.bell-labs.com/who/sjf/) and
51
+ memory-management fixes for said C code (by Derek Bradley; http://www.derekbradley.ca)
52
+ used (and released under the MIT-LICENSE) with permission.
53
+
54
+
55
+ (The MIT License)
56
+
57
+ Copyright (c) 2008 Brendan Ribera <brendan.ribera+rubyvor@gmail.com>
58
+
59
+
60
+ Permission is hereby granted, free of charge, to any person obtaining a copy
61
+ of this software and associated documentation files (the "Software"), to deal
62
+ in the Software without restriction, including without limitation the rights
63
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
64
+ copies of the Software, and to permit persons to whom the Software is
65
+ furnished to do so, subject to the following conditions:
66
+
67
+ The above copyright notice and this permission notice shall be included in
68
+ all copies or substantial portions of the Software.
69
+
70
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
71
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
72
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
73
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
74
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
75
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
76
+ THE SOFTWARE.
@@ -0,0 +1,35 @@
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
+ p.url = 'http://github.com/bribera/rubyvor'
12
+
13
+ # C extension goodness
14
+ p.spec_extras[:extensions] = "ext/extconf.rb"
15
+ p.clean_globs << EXT << 'ext/*.o' << 'ext/Makefile'
16
+ end
17
+
18
+ desc "Compile extensions"
19
+ task :compile => EXT
20
+ task :test => :compile
21
+
22
+ file EXT => ['ext/extconf.rb', 'ext/ruby_vor_c.c'] do
23
+ Dir.chdir 'ext' do
24
+ ruby 'extconf.rb'
25
+ sh 'make'
26
+ end
27
+ end
28
+
29
+ desc "Prepare for github upload"
30
+ task :github do
31
+ system "git ls-files | egrep -v \"\\.gitignore\" > Manifest.txt"
32
+ system "rake debug_gem | egrep -v \"^\\(in\" > rubyvor.gemspec"
33
+ end
34
+
35
+ 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.
@@ -0,0 +1,204 @@
1
+
2
+ /*** EDGELIST.C ***/
3
+
4
+ #include "vdefs.h"
5
+
6
+ static int ELhashsize ;
7
+ static Halfedge * ELleftend, * ELrightend, ** ELhash ;
8
+ static Freelist hfl ;
9
+ static int ntry, totalsearch ;
10
+
11
+ void
12
+ ELinitialize(void)
13
+ {
14
+ int i ;
15
+
16
+ freeinit(&hfl, sizeof(Halfedge)) ;
17
+ ELhashsize = 2 * rubyvorState.sqrt_nsites ;
18
+ ELhash = (Halfedge **)myalloc( sizeof(*ELhash) * ELhashsize) ;
19
+ for (i = 0 ; i < ELhashsize ; i++)
20
+ {
21
+ ELhash[i] = (Halfedge *)NULL ;
22
+ }
23
+ ELleftend = HEcreate((Edge *)NULL, 0) ;
24
+ ELrightend = HEcreate((Edge *)NULL, 0) ;
25
+ ELleftend->ELleft = (Halfedge *)NULL ;
26
+ ELleftend->ELright = ELrightend ;
27
+ ELrightend->ELleft = ELleftend ;
28
+ ELrightend->ELright = (Halfedge *)NULL ;
29
+ ELhash[0] = ELleftend ;
30
+ ELhash[ELhashsize-1] = ELrightend ;
31
+ }
32
+
33
+ Halfedge *
34
+ HEcreate(Edge * e, int pm)
35
+ {
36
+ Halfedge * answer ;
37
+
38
+ answer = (Halfedge *)getfree(&hfl) ;
39
+ answer->ELedge = e ;
40
+ answer->ELpm = pm ;
41
+ answer->PQnext = (Halfedge *)NULL ;
42
+ answer->vertex = (Site *)NULL ;
43
+ answer->ELrefcnt = 0 ;
44
+ return (answer) ;
45
+ }
46
+
47
+ void
48
+ ELinsert(Halfedge * lb, Halfedge * new)
49
+ {
50
+ new->ELleft = lb ;
51
+ new->ELright = lb->ELright ;
52
+ (lb->ELright)->ELleft = new ;
53
+ lb->ELright = new ;
54
+ }
55
+
56
+ /* Get entry from hash table, pruning any deleted nodes */
57
+
58
+ Halfedge *
59
+ ELgethash(int b)
60
+ {
61
+ Halfedge * he ;
62
+
63
+ if ((b < 0) || (b >= ELhashsize))
64
+ {
65
+ return ((Halfedge *)NULL) ;
66
+ }
67
+ he = ELhash[b] ;
68
+ if ((he == (Halfedge *)NULL) || (he->ELedge != (Edge *)DELETED))
69
+ {
70
+ return (he) ;
71
+ }
72
+ /* Hash table points to deleted half edge. Patch as necessary. */
73
+ ELhash[b] = (Halfedge *)NULL ;
74
+ if ((--(he->ELrefcnt)) == 0)
75
+ {
76
+ makefree((Freenode *)he, (Freelist *)&hfl) ;
77
+ }
78
+ return ((Halfedge *)NULL) ;
79
+ }
80
+
81
+ Halfedge *
82
+ ELleftbnd(Point * p)
83
+ {
84
+ int i, bucket ;
85
+ Halfedge * he ;
86
+
87
+ /* Use hash table to get close to desired halfedge */
88
+ bucket = (p->x - rubyvorState.xmin) / rubyvorState.deltax * ELhashsize ;
89
+ if (bucket < 0)
90
+ {
91
+ bucket = 0 ;
92
+ }
93
+ if (bucket >= ELhashsize)
94
+ {
95
+ bucket = ELhashsize - 1 ;
96
+ }
97
+ he = ELgethash(bucket) ;
98
+ if (he == (Halfedge *)NULL)
99
+ {
100
+ for (i = 1 ; 1 ; i++)
101
+ {
102
+ if ((he = ELgethash(bucket-i)) != (Halfedge *)NULL)
103
+ {
104
+ break ;
105
+ }
106
+ if ((he = ELgethash(bucket+i)) != (Halfedge *)NULL)
107
+ {
108
+ break ;
109
+ }
110
+ }
111
+ totalsearch += i ;
112
+ }
113
+ ntry++ ;
114
+ /* Now search linear list of halfedges for the corect one */
115
+ if (he == ELleftend || (he != ELrightend && right_of(he,p)))
116
+ {
117
+ do {
118
+ he = he->ELright ;
119
+ } while (he != ELrightend && right_of(he,p)) ;
120
+ he = he->ELleft ;
121
+ }
122
+ else
123
+ {
124
+ do {
125
+ he = he->ELleft ;
126
+ } while (he != ELleftend && !right_of(he,p)) ;
127
+ }
128
+ /*** Update hash table and reference counts ***/
129
+ if ((bucket > 0) && (bucket < ELhashsize-1))
130
+ {
131
+ if (ELhash[bucket] != (Halfedge *)NULL)
132
+ {
133
+ (ELhash[bucket]->ELrefcnt)-- ;
134
+ }
135
+ ELhash[bucket] = he ;
136
+ (ELhash[bucket]->ELrefcnt)++ ;
137
+ }
138
+ return (he) ;
139
+ }
140
+
141
+ /*** This delete routine can't reclaim node, since pointers from hash
142
+ : table may be present.
143
+ ***/
144
+
145
+ void
146
+ ELdelete(Halfedge * he)
147
+ {
148
+ (he->ELleft)->ELright = he->ELright ;
149
+ (he->ELright)->ELleft = he->ELleft ;
150
+ he->ELedge = (Edge *)DELETED ;
151
+ }
152
+
153
+ Halfedge *
154
+ ELright(Halfedge * he)
155
+ {
156
+ return (he->ELright) ;
157
+ }
158
+
159
+ Halfedge *
160
+ ELleft(Halfedge * he)
161
+ {
162
+ return (he->ELleft) ;
163
+ }
164
+
165
+ Site *
166
+ leftreg(Halfedge * he)
167
+ {
168
+ if (he->ELedge == (Edge *)NULL)
169
+ {
170
+ return(rubyvorState.bottomsite) ;
171
+ }
172
+ return (he->ELpm == le ? he->ELedge->reg[le] :
173
+ he->ELedge->reg[re]) ;
174
+ }
175
+
176
+ Site *
177
+ rightreg(Halfedge * he)
178
+ {
179
+ if (he->ELedge == (Edge *)NULL)
180
+ {
181
+ return(rubyvorState.bottomsite) ;
182
+ }
183
+ return (he->ELpm == le ? he->ELedge->reg[re] :
184
+ he->ELedge->reg[le]) ;
185
+ }
186
+
187
+ /*
188
+ * Semi-hacky way to access these static variables. Placing them inside rubyvorState
189
+ * causes pointer issues that I don't want to debug, and they're only accessed briefly
190
+ * inside of voronoi.c. Since we're just doing pointer comparison there, this is an
191
+ * acceptable compromise.
192
+ */
193
+
194
+ Halfedge *
195
+ getELleftend(void)
196
+ {
197
+ return(ELleftend);
198
+ }
199
+
200
+ Halfedge *
201
+ getELrightend(void)
202
+ {
203
+ return(ELrightend);
204
+ }
@@ -0,0 +1,3 @@
1
+ require 'mkmf'
2
+ dir_config('ruby_vor_c')
3
+ create_makefile('ruby_vor_c')
@@ -0,0 +1,219 @@
1
+
2
+ /*** GEOMETRY.C ***/
3
+
4
+ #include <math.h>
5
+ #include "vdefs.h"
6
+
7
+ static Freelist efl;
8
+
9
+ void
10
+ geominit(void)
11
+ {
12
+ freeinit(&efl, sizeof(Edge)) ;
13
+ rubyvorState.nvertices = rubyvorState.nedges = 0 ;
14
+ rubyvorState.sqrt_nsites = sqrt(rubyvorState.nsites+4) ;
15
+ rubyvorState.deltay = rubyvorState.ymax - rubyvorState.ymin ;
16
+ rubyvorState.deltax = rubyvorState.xmax - rubyvorState.xmin ;
17
+ }
18
+
19
+ Edge *
20
+ bisect(Site * s1, Site * s2)
21
+ {
22
+ float dx, dy, adx, ady ;
23
+ Edge * newedge ;
24
+
25
+ newedge = (Edge *)getfree(&efl) ;
26
+ newedge->reg[0] = s1 ;
27
+ newedge->reg[1] = s2 ;
28
+ ref(s1) ;
29
+ ref(s2) ;
30
+ newedge->ep[0] = newedge->ep[1] = (Site *)NULL ;
31
+ dx = s2->coord.x - s1->coord.x ;
32
+ dy = s2->coord.y - s1->coord.y ;
33
+ adx = dx>0 ? dx : -dx ;
34
+ ady = dy>0 ? dy : -dy ;
35
+ newedge->c = s1->coord.x * dx + s1->coord.y * dy + (dx*dx +
36
+ dy*dy) * 0.5 ;
37
+ if (adx > ady)
38
+ {
39
+ newedge->a = 1.0 ;
40
+ newedge->b = dy/dx ;
41
+ newedge->c /= dx ;
42
+ }
43
+ else
44
+ {
45
+ newedge->b = 1.0 ;
46
+ newedge->a = dx/dy ;
47
+ newedge->c /= dy ;
48
+ }
49
+ newedge->edgenbr = rubyvorState.nedges ;
50
+ out_bisector(newedge) ;
51
+ rubyvorState.nedges++ ;
52
+ return (newedge) ;
53
+ }
54
+
55
+ Site *
56
+ intersect(Halfedge * el1, Halfedge * el2)
57
+ {
58
+ Edge * e1, * e2, * e ;
59
+ Halfedge * el ;
60
+ float d, xint, yint ;
61
+ int right_of_site ;
62
+ Site * v ;
63
+
64
+ e1 = el1->ELedge ;
65
+ e2 = el2->ELedge ;
66
+ if ((e1 == (Edge*)NULL) || (e2 == (Edge*)NULL))
67
+ {
68
+ return ((Site *)NULL) ;
69
+ }
70
+ if (e1->reg[1] == e2->reg[1])
71
+ {
72
+ return ((Site *)NULL) ;
73
+ }
74
+ d = (e1->a * e2->b) - (e1->b * e2->a) ;
75
+ if ((-1.0e-10 < d) && (d < 1.0e-10))
76
+ {
77
+ return ((Site *)NULL) ;
78
+ }
79
+ xint = (e1->c * e2->b - e2->c * e1->b) / d ;
80
+ yint = (e2->c * e1->a - e1->c * e2->a) / d ;
81
+ if ((e1->reg[1]->coord.y < e2->reg[1]->coord.y) ||
82
+ (e1->reg[1]->coord.y == e2->reg[1]->coord.y &&
83
+ e1->reg[1]->coord.x < e2->reg[1]->coord.x))
84
+ {
85
+ el = el1 ;
86
+ e = e1 ;
87
+ }
88
+ else
89
+ {
90
+ el = el2 ;
91
+ e = e2 ;
92
+ }
93
+ right_of_site = (xint >= e->reg[1]->coord.x) ;
94
+ if ((right_of_site && (el->ELpm == le)) ||
95
+ (!right_of_site && (el->ELpm == re)))
96
+ {
97
+ return ((Site *)NULL) ;
98
+ }
99
+ v = (Site *)getfree(&(rubyvorState.sfl)) ;
100
+ v->refcnt = 0 ;
101
+ v->coord.x = xint ;
102
+ v->coord.y = yint ;
103
+ return (v) ;
104
+ }
105
+
106
+ /*** returns 1 if p is to right of halfedge e ***/
107
+
108
+ int
109
+ right_of(Halfedge * el, Point * p)
110
+ {
111
+ Edge * e ;
112
+ Site * topsite ;
113
+ int right_of_site, above, fast ;
114
+ float dxp, dyp, dxs, t1, t2, t3, yl ;
115
+
116
+ e = el->ELedge ;
117
+ topsite = e->reg[1] ;
118
+ right_of_site = (p->x > topsite->coord.x) ;
119
+ if (right_of_site && (el->ELpm == le))
120
+ {
121
+ return (1) ;
122
+ }
123
+ if(!right_of_site && (el->ELpm == re))
124
+ {
125
+ return (0) ;
126
+ }
127
+ if (e->a == 1.0)
128
+ {
129
+ dyp = p->y - topsite->coord.y ;
130
+ dxp = p->x - topsite->coord.x ;
131
+ fast = 0 ;
132
+ if ((!right_of_site & (e->b < 0.0)) ||
133
+ (right_of_site & (e->b >= 0.0)))
134
+ {
135
+ fast = above = (dyp >= e->b*dxp) ;
136
+ }
137
+ else
138
+ {
139
+ above = ((p->x + p->y * e->b) > (e->c)) ;
140
+ if (e->b < 0.0)
141
+ {
142
+ above = !above ;
143
+ }
144
+ if (!above)
145
+ {
146
+ fast = 1 ;
147
+ }
148
+ }
149
+ if (!fast)
150
+ {
151
+ dxs = topsite->coord.x - (e->reg[0])->coord.x ;
152
+ above = (e->b * (dxp*dxp - dyp*dyp))
153
+ <
154
+ (dxs * dyp * (1.0 + 2.0 * dxp /
155
+ dxs + e->b * e->b)) ;
156
+ if (e->b < 0.0)
157
+ {
158
+ above = !above ;
159
+ }
160
+ }
161
+ }
162
+ else /*** e->b == 1.0 ***/
163
+ {
164
+ yl = e->c - e->a * p->x ;
165
+ t1 = p->y - yl ;
166
+ t2 = p->x - topsite->coord.x ;
167
+ t3 = yl - topsite->coord.y ;
168
+ above = ((t1*t1) > ((t2 * t2) + (t3 * t3))) ;
169
+ }
170
+ return (el->ELpm == le ? above : !above) ;
171
+ }
172
+
173
+ void
174
+ endpoint(Edge * e, int lr, Site * s)
175
+ {
176
+ e->ep[lr] = s ;
177
+ ref(s) ;
178
+ if (e->ep[re-lr] == (Site *)NULL)
179
+ {
180
+ return ;
181
+ }
182
+ out_ep(e) ;
183
+ deref(e->reg[le]) ;
184
+ deref(e->reg[re]) ;
185
+ makefree((Freenode *)e, (Freelist *) &efl) ;
186
+ }
187
+
188
+ float
189
+ dist(Site * s, Site * t)
190
+ {
191
+ float dx,dy ;
192
+
193
+ dx = s->coord.x - t->coord.x ;
194
+ dy = s->coord.y - t->coord.y ;
195
+ return (sqrt(dx*dx + dy*dy)) ;
196
+ }
197
+
198
+ void
199
+ makevertex(Site * v)
200
+ {
201
+ v->sitenbr = rubyvorState.nvertices++ ;
202
+ out_vertex(v) ;
203
+ }
204
+
205
+ void
206
+ deref(Site * v)
207
+ {
208
+ if (--(v->refcnt) == 0 )
209
+ {
210
+ makefree((Freenode *)v, (Freelist *)&(rubyvorState.sfl)) ;
211
+ }
212
+ }
213
+
214
+ void
215
+ ref(Site * v)
216
+ {
217
+ ++(v->refcnt) ;
218
+ }
219
+