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,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