rubyvor 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,60 @@
1
+ === 0.1.3 / 2010-01-26
2
+
3
+ * Ruby 1.9 compatibility update; update for newer Hoe syntax.
4
+
5
+ === 0.1.2 / 2009-04-24
6
+
7
+ * Compilation fixes for OSX. Thanks to jpemberthy and febuiles!
8
+
9
+ === 0.1.1 / 2009-01-15
10
+
11
+ * LibXML require conflict fix.
12
+
13
+ === 0.1.0 / 2009-01-13
14
+
15
+ * Configurable handling of "no neighbors" case.
16
+ * Tests for "no neighbors" case.
17
+
18
+ === 0.0.9 / 2009-01-01
19
+
20
+ Happy New Year!
21
+ * New speed improvements.
22
+ * Additional visualization tweaks.
23
+ * More tests.
24
+
25
+ === 0.0.8 / 2008-12-23
26
+
27
+ * Several C warning fixes (more ISO C compliance unused variables, etc)
28
+ * Moved minimum_spanning_tree computation into C, yielding large speed gain.
29
+ * Basic SVG visualization.
30
+
31
+ === 0.0.7 / 2008-12-12
32
+
33
+ * 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).
34
+
35
+ * 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.
36
+
37
+ === 0.0.6 / 2008-12-11
38
+
39
+ * Implementation of cluster_by_size to partition points into N clusters.
40
+
41
+ === 0.0.5 / 2008-12-10
42
+
43
+ * Beginnings of clustering and useful graph algorithms.
44
+ * Some refactoring of C methods.
45
+
46
+ === 0.0.4 / 2008-12-04
47
+
48
+ * Fixed 64-bit segfaults due to improper definition of the myrealloc() function.
49
+
50
+ === 0.0.3 / 2008-12-03
51
+
52
+ * Fixed a segfault by using rb_ary_push instead of direct pointer manipulation. Much simpler.
53
+
54
+ === 0.0.2 / 2008-12-03
55
+
56
+ * Computations succeed on a naive Point class, returning raw values for the associated Voronoi Diagram and Delaunay triangulation.
57
+
58
+ === 0.0.1 / 2008-12-01
59
+
60
+ * Initial release. Nothing works.
@@ -0,0 +1,30 @@
1
+ History.rdoc
2
+ Manifest.txt
3
+ README.rdoc
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,41 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require 'lib/ruby_vor/version.rb'
6
+
7
+ EXT = "ext/voronoi_interface.#{Config::CONFIG['DLEXT']}"
8
+
9
+ Hoe.spec 'rubyvor' do
10
+ developer 'Brendan Ribera', 'brendan.ribera+rubyvor@gmail.com'
11
+
12
+ self.version = RubyVor::VERSION
13
+ self.url = 'http://github.com/bribera/rubyvor'
14
+ self.readme_file = 'README.rdoc'
15
+ self.history_file = 'History.rdoc'
16
+ self.summary = 'Efficient Voronoi diagrams and Delaunay trianglation for Ruby'
17
+ self.description = 'RubyVor provides efficient computation of Voronoi diagrams and Delaunay triangulation for a set of Ruby points. It is intended to function as a complemenet to GeoRuby. These structures can be used to compute a nearest-neighbor graph for a set of points. This graph can in turn be used for proximity-based clustering of the input points.'
18
+
19
+ # C extension goodness
20
+ self.spec_extras[:extensions] = "ext/extconf.rb"
21
+ self.clean_globs << EXT << 'ext/*.o' << 'ext/Makefile'
22
+ end
23
+
24
+ desc "Compile extensions"
25
+ task :compile => EXT
26
+ task :test => :compile
27
+
28
+ file EXT => ['ext/extconf.rb', 'ext/ruby_vor_c.c'] do
29
+ Dir.chdir 'ext' do
30
+ ruby 'extconf.rb'
31
+ sh 'make'
32
+ end
33
+ end
34
+
35
+ desc "Prepare for github upload"
36
+ task :github do
37
+ system "git ls-files | egrep -v \"\\.gitignore\" > Manifest.txt"
38
+ system "rake debug_gem | egrep -v \"^\\(in\" > rubyvor.gemspec"
39
+ end
40
+
41
+ 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')