abscondment-rubyvor 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,36 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{rubyvor}
5
+ s.version = "0.1.2"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Brendan Ribera"]
9
+ s.date = %q{2009-04-24}
10
+ s.description = %q{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.}
11
+ s.email = ["brendan.ribera+rubyvor@gmail.com"]
12
+ s.extensions = ["ext/extconf.rb"]
13
+ s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"]
14
+ s.files = ["History.txt", "Manifest.txt", "README.txt", "Rakefile", "ext/Doc", "ext/edgelist.c", "ext/extconf.rb", "ext/geometry.c", "ext/heap.c", "ext/memory.c", "ext/output.c", "ext/rb_cComputation.c", "ext/rb_cPoint.c", "ext/rb_cPriorityQueue.c", "ext/ruby_vor_c.c", "ext/ruby_vor_c.h", "ext/vdefs.h", "ext/voronoi.c", "lib/ruby_vor.rb", "lib/ruby_vor/computation.rb", "lib/ruby_vor/geo_ruby_extensions.rb", "lib/ruby_vor/point.rb", "lib/ruby_vor/priority_queue.rb", "lib/ruby_vor/version.rb", "lib/ruby_vor/visualizer.rb", "rubyvor.gemspec", "test/test_computation.rb", "test/test_point.rb", "test/test_priority_queue.rb", "test/test_voronoi_interface.rb"]
15
+ s.has_rdoc = true
16
+ s.homepage = %q{http://github.com/bribera/rubyvor}
17
+ s.rdoc_options = ["--main", "README.txt"]
18
+ s.require_paths = ["lib", "ext"]
19
+ s.rubyforge_project = %q{rubyvor}
20
+ s.rubygems_version = %q{1.3.1}
21
+ s.summary = %q{RubyVor provides efficient computation of Voronoi diagrams and Delaunay triangulation for a set of Ruby points}
22
+ s.test_files = ["test/test_priority_queue.rb", "test/test_voronoi_interface.rb", "test/test_point.rb", "test/test_computation.rb"]
23
+
24
+ if s.respond_to? :specification_version then
25
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
26
+ s.specification_version = 2
27
+
28
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
29
+ s.add_development_dependency(%q<hoe>, [">= 1.12.1"])
30
+ else
31
+ s.add_dependency(%q<hoe>, [">= 1.12.1"])
32
+ end
33
+ else
34
+ s.add_dependency(%q<hoe>, [">= 1.12.1"])
35
+ end
36
+ end
@@ -0,0 +1,354 @@
1
+ require 'rubygems'
2
+ require 'minitest/unit'
3
+ require File.dirname(__FILE__) + '/../lib/ruby_vor'
4
+
5
+ class TestComputation < MiniTest::Unit::TestCase
6
+
7
+ def initialize(*args)
8
+ @points = @trianglulation_raw = @diagram_raw = nil
9
+ super(*args)
10
+ end
11
+
12
+ def test_empty_points
13
+ assert_raises TypeError do
14
+ RubyVor::VDDT::Computation.from_points(nil)
15
+ end
16
+
17
+ assert_raises RuntimeError do
18
+ RubyVor::VDDT::Computation.from_points([])
19
+ end
20
+ end
21
+
22
+ def test_nn_graph
23
+ comp = RubyVor::VDDT::Computation.from_points(sample_points)
24
+
25
+ # based on this expected delaunay trianglulation:
26
+ # 3 2 1
27
+ # 3 0 2
28
+ # 8 2 0
29
+ # 3 8 0
30
+ # 5 6 8
31
+ # 7 6 5
32
+ # 7 4 6
33
+ # 6 2 8
34
+ # 8 7 5
35
+
36
+ expected_graph = [
37
+ [2, 3, 8], # 0
38
+ [2, 3], # 1
39
+ [0, 1, 3, 6, 8], # 2
40
+ [0, 1, 2, 8], # 3
41
+ [6, 7], # 4
42
+ [6, 7, 8], # 5
43
+ [2, 4, 5, 7, 8], # 6
44
+ [4, 5, 6, 8], # 7
45
+ [0, 2, 3, 5, 6, 7], # 8
46
+ ]
47
+
48
+
49
+ comp.nn_graph.each_with_index do |neighbors,i|
50
+ refute_empty neighbors, "@nn_graph returned empty neighbors for node #{i}"
51
+ end
52
+
53
+ assert_equal comp.nn_graph.map{|v| v.sort}.sort, \
54
+ expected_graph.map{|v| v.sort}.sort
55
+ end
56
+
57
+ def test_simple_mst
58
+ points = [
59
+ RubyVor::Point.new(0,0),
60
+ RubyVor::Point.new(1.0,1.1),
61
+ RubyVor::Point.new(4.9,3.1),
62
+ ]
63
+
64
+ comp = RubyVor::VDDT::Computation.from_points(points)
65
+ expected_mst = [
66
+ [0,1],
67
+ [1,2]
68
+ ]
69
+ computed_mst = comp.minimum_spanning_tree
70
+
71
+ # Assert nodes are correct
72
+ assert_equal expected_mst.sort, \
73
+ computed_mst.keys.sort
74
+ end
75
+
76
+ def test_advanced_mst
77
+ # Test tree taken from an example SVG included in the Wikipedia article on Euclidean minimum spanning trees:
78
+ # http://en.wikipedia.org/wiki/Image:Euclidean_minimum_spanning_tree.svg
79
+
80
+ points = [
81
+ RubyVor::Point.new(155.692, 99.783), # 0
82
+ RubyVor::Point.new(162.285, 120.245), # 1
83
+ RubyVor::Point.new(143.692, 129.893), # 2
84
+ RubyVor::Point.new(150.128, 167.924), # 3
85
+ RubyVor::Point.new(137.617, 188.953), # 4
86
+ RubyVor::Point.new(193.467, 119.345), # 5
87
+ RubyVor::Point.new(196.754, 88.47), # 6
88
+ RubyVor::Point.new(241.629, 70.845), # 7
89
+ RubyVor::Point.new(262.692, 59.97), # 8
90
+ RubyVor::Point.new(269.629, 63.158), # 9
91
+ RubyVor::Point.new(247.257, 200.669), # 10
92
+ RubyVor::Point.new(231.28, 245.974), # 11
93
+ RubyVor::Point.new(268.002, 264.693), # 12
94
+ RubyVor::Point.new(155.442, 64.473), # 13
95
+ RubyVor::Point.new(198.598, 31.804), # 14
96
+ RubyVor::Point.new(216.816, 3.513), # 15
97
+ RubyVor::Point.new(89.624, 27.344), # 16
98
+ RubyVor::Point.new(67.925, 56.999), # 17
99
+ RubyVor::Point.new(77.328, 93.404), # 18
100
+ RubyVor::Point.new(65.525, 158.783), # 19
101
+ RubyVor::Point.new(63.525,170.783), # 20
102
+ RubyVor::Point.new(15.192, 192.783), # 21
103
+ RubyVor::Point.new(7.025, 236.949), # 22
104
+ RubyVor::Point.new(40.525, 262.949), # 23
105
+ RubyVor::Point.new(61.692, 225.95) # 24
106
+ ]
107
+
108
+ comp = RubyVor::VDDT::Computation.from_points(points)
109
+
110
+ expected_mst = [
111
+ [0,1],
112
+ [0,13],
113
+ [1,2],
114
+ [1,5],
115
+ [2,3],
116
+ [3,4],
117
+ [5,6],
118
+ [5,10],
119
+ [6,7],
120
+ [7,8],
121
+ [8,9],
122
+ [10,11],
123
+ [11,12],
124
+ [13,14],
125
+ [13,16],
126
+ [14,15],
127
+ [16,17],
128
+ [17,18],
129
+ [18,19],
130
+ [19,20],
131
+ [20,21],
132
+ [21,22],
133
+ [22,23],
134
+ [23,24]
135
+ ]
136
+ computed_mst = comp.minimum_spanning_tree
137
+
138
+ assert_equal expected_mst.sort, \
139
+ computed_mst.keys.sort
140
+ end
141
+
142
+ def test_cluster_by_distance
143
+ comp = RubyVor::VDDT::Computation.from_points(sample_points)
144
+
145
+ expected_clusters = [
146
+ [0,1,2,3],
147
+ [8],
148
+ [4,5,6,7]
149
+ ]
150
+
151
+ # We want to ensure that the nn_graph isn't modified by this call
152
+ original_nn_graph = comp.nn_graph.map{|v| v.clone}
153
+
154
+ # Compute clusters within a distance of 10
155
+ computed_clusters = comp.cluster_by_distance(10)
156
+
157
+ assert_equal expected_clusters.map{|cl| cl.sort}.sort, \
158
+ computed_clusters.map{|cl| cl.sort}.sort
159
+
160
+ assert_equal original_nn_graph, \
161
+ comp.nn_graph
162
+
163
+ end
164
+
165
+
166
+ def test_duplicate_points
167
+ comp = RubyVor::VDDT::Computation.from_points([
168
+ RubyVor::Point.new(2,3), # 0
169
+ RubyVor::Point.new(1,1), # 1
170
+ RubyVor::Point.new(1,1), # 2
171
+ RubyVor::Point.new(1,1), # 3
172
+ RubyVor::Point.new(1,1), # 4
173
+ RubyVor::Point.new(1,1), # 5
174
+ RubyVor::Point.new(1,1), # 6
175
+ RubyVor::Point.new(1,1), # 7
176
+ RubyVor::Point.new(1,1), # 8
177
+ RubyVor::Point.new(4,10), # 9
178
+ RubyVor::Point.new(4,10.0), # 10
179
+ RubyVor::Point.new(4.0,10.0), # 11
180
+ RubyVor::Point.new(4.0,10.0), # 12
181
+ ])
182
+ comp.nn_graph.each_with_index do |neighbors,i|
183
+ refute_empty neighbors, "@nn_graph has empty neighbors for node #{i}"
184
+ end
185
+
186
+ =begin
187
+ assert_equal [[0], [1,2,3,4,5,6,7,8], [9,10,11,12]], \
188
+ comp.cluster_by_distance(1).map{|cl| cl.sort}.sort, \
189
+ "cluster by distance 1"
190
+
191
+ assert_equal [[0,1,2,3,4,5,6,7,8], [9,10,11,12]], \
192
+ comp.cluster_by_distance(5).map{|cl| cl.sort}.sort, \
193
+ "cluster by distance 5"
194
+
195
+ assert_equal [[0,1,2,3,4,5,6,7,8,9,10,11,12]], \
196
+ comp.cluster_by_distance(10).map{|cl| cl.sort}.sort, \
197
+ "cluster by distance 10"
198
+
199
+ assert_equal [[0,1,2,3,4,5,6,7,8], [9,10,11,12]], \
200
+ comp.cluster_by_size([2])[2].map{|cl| cl.sort}.sort, \
201
+ "cluster by size 2"
202
+ =end
203
+
204
+ assert_equal [[0], [1], [2]], \
205
+ comp.cluster_by_distance(1).map{|cl| cl.sort}.sort, \
206
+ "cluster by distance 1"
207
+
208
+ assert_equal [[0,1], [2]], \
209
+ comp.cluster_by_distance(5).map{|cl| cl.sort}.sort, \
210
+ "cluster by distance 5"
211
+
212
+ assert_equal [[0,1,2]], \
213
+ comp.cluster_by_distance(10).map{|cl| cl.sort}.sort, \
214
+ "cluster by distance 10"
215
+
216
+ assert_equal [[0,1], [2]], \
217
+ comp.cluster_by_size([2])[2].map{|cl| cl.sort}.sort, \
218
+ "cluster by size 2"
219
+
220
+ end
221
+
222
+
223
+ def test_bad_data
224
+ assert_raises TypeError do
225
+ comp = RubyVor::VDDT::Computation.from_points([RubyVor::Point.new(1,1), RubyVor::Point.new(21,3), RubyVor::Point.new(2,:s)])
226
+ end
227
+
228
+ assert_raises TypeError do
229
+ comp = RubyVor::VDDT::Computation.from_points(RubyVor::Point.new(21,3))
230
+ end
231
+
232
+ assert_raises RuntimeError do
233
+ comp = RubyVor::VDDT::Computation.from_points([RubyVor::Point.new(1,1), RubyVor::Point.new(21,3), nil])
234
+ end
235
+
236
+ assert_raises RuntimeError do
237
+ comp = RubyVor::VDDT::Computation.from_points([])
238
+ end
239
+
240
+ comp = RubyVor::VDDT::Computation.from_points([RubyVor::Point.new(1,1), RubyVor::Point.new(21,3), RubyVor::Point.new(2,1.5)])
241
+ assert_raises ArgumentError do
242
+ cl = comp.cluster_by_distance(nil)
243
+ end
244
+ end
245
+
246
+
247
+ def test_no_neighbors
248
+ nn_graph = nil
249
+
250
+ # Test :raise
251
+ comp = RubyVor::VDDT::Computation.from_points([1,2,3,4,5].map{|xy| RubyVor::Point.new(xy,xy)})
252
+ comp.no_neighbor_response = :raise
253
+
254
+ assert_equal comp.no_neighbor_response, :raise
255
+ assert_raises(IndexError) { nn_graph = comp.nn_graph }
256
+ assert_raises(IndexError) { comp.cluster_by_distance(5) }
257
+ assert_equal nn_graph, nil
258
+
259
+
260
+ # Test :use_all (default)
261
+ comp = RubyVor::VDDT::Computation.from_points([1,2,3,4,5].map{|xy| RubyVor::Point.new(xy,xy)})
262
+ comp.no_neighbor_response = :use_all
263
+
264
+ assert_equal comp.no_neighbor_response, :use_all
265
+ assert_nothing_raised { nn_graph = comp.nn_graph }
266
+ assert_nothing_raised do
267
+ assert_equal comp.cluster_by_distance(5).map{|a| a.sort}.sort, [[0,1,2,3,4]]
268
+ end
269
+ refute_equal nn_graph, nil
270
+
271
+
272
+ # Test :ignore
273
+ comp = RubyVor::VDDT::Computation.from_points([1,2,3,4,5].map{|xy| RubyVor::Point.new(xy,xy)})
274
+ comp.no_neighbor_response = :ignore
275
+
276
+ assert_equal comp.no_neighbor_response, :ignore
277
+ assert_nothing_raised { nn_graph = comp.nn_graph }
278
+ assert_nothing_raised do
279
+ assert_equal comp.cluster_by_distance(5).map{|a| a.sort}.sort, [[0],[1],[2],[3],[4]]
280
+ end
281
+ refute_equal nn_graph, nil
282
+ end
283
+
284
+
285
+ def test_cluster_by_size
286
+ comp = RubyVor::VDDT::Computation.from_points([
287
+ RubyVor::Point.new(0.25, 0.25), # 0
288
+ RubyVor::Point.new(1, 0.25), # 1
289
+ RubyVor::Point.new(0.5, 1), # 2
290
+ RubyVor::Point.new(5, 5), # 3
291
+ RubyVor::Point.new(10.25, 10.25), # 4
292
+ RubyVor::Point.new(13, 9), # 5
293
+ RubyVor::Point.new(9, 9) # 6
294
+ ])
295
+
296
+ sizes = [1, 3, 5, 7]
297
+
298
+ computed_sized_clusters = comp.cluster_by_size(sizes)
299
+
300
+ # Check that we got clusters for each size requested
301
+ assert_equal sizes, \
302
+ computed_sized_clusters.keys.sort
303
+
304
+ assert_equal [[0,1,2,3,4,5,6]], \
305
+ computed_sized_clusters[1].map{|cl| cl.sort}.sort, \
306
+ 'Failed cluster of size 1'
307
+
308
+ assert_equal [[0,1,2], [3], [4,5,6]], \
309
+ computed_sized_clusters[3].map{|cl| cl.sort}.sort
310
+
311
+ assert_equal [[0,1,2], [3], [4], [5], [6]], \
312
+ computed_sized_clusters[5].map{|cl| cl.sort}.sort
313
+
314
+ assert_equal [[0], [1], [2], [3], [4], [5], [6]], \
315
+ computed_sized_clusters[7].sort
316
+ end
317
+
318
+ #
319
+ # A few helper methods
320
+ #
321
+
322
+ private
323
+
324
+ def sample_points
325
+ if @points.nil?
326
+ @points = [
327
+ [1.1,1],
328
+ [0,0],
329
+ [1,0],
330
+ [0,1.1],
331
+
332
+ [101.1,101],
333
+ [100,100],
334
+ [101,100],
335
+ [100,101.1],
336
+
337
+ [43, 55]
338
+ ].map{|x,y| RubyVor::Point.new(x,y)}
339
+ end
340
+ @points
341
+ end
342
+
343
+ def assert_nothing_raised(&b)
344
+ begin
345
+ yield
346
+ rescue Exception => e
347
+ flunk "#{mu_pp(e)} exception encountered, expected no exceptions"
348
+ return
349
+ end
350
+ pass()
351
+ end
352
+ end
353
+
354
+ MiniTest::Unit.autorun
@@ -0,0 +1,100 @@
1
+ require 'rubygems'
2
+ require 'minitest/unit'
3
+ require File.dirname(__FILE__) + '/../lib/ruby_vor'
4
+
5
+ class TestPoint < MiniTest::Unit::TestCase
6
+
7
+ def test_instantiation
8
+ a = b = nil
9
+
10
+ assert_raises TypeError do
11
+ a = RubyVor::Point.new(:"10", 10)
12
+ end
13
+
14
+ assert_raises TypeError do
15
+ a = RubyVor::Point.new(10, :"10")
16
+ end
17
+
18
+ assert_nothing_raised do
19
+ a = RubyVor::Point.new(123.456, 789.10)
20
+ b = RubyVor::Point.new("123.456", "789.10")
21
+ end
22
+
23
+ assert_equal a, b
24
+ end
25
+
26
+ def test_comparison
27
+ a = RubyVor::Point.new(10, 10)
28
+ b = RubyVor::Point.new(1, 1)
29
+
30
+ assert a > b
31
+ assert b < a
32
+ assert_equal(-1, (b <=> a))
33
+ end
34
+
35
+ def test_equality
36
+ a = RubyVor::Point.new(10, 10)
37
+ b = RubyVor::Point.new(10.0, 10)
38
+ c = RubyVor::Point.new(10.0, 10.0)
39
+ d = RubyVor::Point.new(10, 10.0)
40
+
41
+ z = RubyVor::Point.new(Math::PI, Math::PI)
42
+ o = a
43
+
44
+
45
+ # Test equality of values; both == and eql? perform this function.
46
+ assert a == a
47
+ assert a == b
48
+ assert a == c
49
+ assert a == d
50
+ assert a == o
51
+ assert a.eql?(a)
52
+ assert a.eql?(b)
53
+ assert a.eql?(c)
54
+ assert a.eql?(d)
55
+ assert a.eql?(o)
56
+
57
+ refute a == z
58
+ refute a.eql?(z)
59
+
60
+
61
+ # Test object equality.
62
+ refute a.equal?(b)
63
+ refute a.equal?(c)
64
+ refute a.equal?(d)
65
+ refute a.equal?(z)
66
+
67
+ assert a.equal?(a)
68
+ assert a.equal?(o)
69
+ end
70
+
71
+ def test_hash
72
+ a = RubyVor::Point.new(10, 10)
73
+ b = RubyVor::Point.new(10.0, 10)
74
+ c = RubyVor::Point.new(10.0, 10.0)
75
+ d = RubyVor::Point.new(10, 10.0)
76
+
77
+ z = RubyVor::Point.new(Math::PI, Math::PI)
78
+ o = a
79
+
80
+ assert_equal a.hash, b.hash
81
+ assert_equal a.hash, c.hash
82
+ assert_equal a.hash, d.hash
83
+ assert_equal a.hash, o.hash
84
+
85
+ refute_equal a.hash, z.hash
86
+ end
87
+
88
+ private
89
+
90
+ def assert_nothing_raised(&b)
91
+ begin
92
+ yield
93
+ rescue Exception => e
94
+ flunk "#{mu_pp(e)} exception encountered, expected no exceptions"
95
+ return
96
+ end
97
+ pass()
98
+ end
99
+
100
+ end