rubyvor 0.1.3

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,87 @@
1
+ module RubyVor
2
+ class PriorityQueue
3
+
4
+ attr_reader :data, :size
5
+
6
+ class << self
7
+ def build_queue(max_index=-1,&block)
8
+ data = []
9
+
10
+ index = 0
11
+ loop do
12
+ x = QueueItem.new(nil, nil, nil)
13
+
14
+ yield(x)
15
+ break if !(max_index < 0 || index < max_index) || x.priority.nil?
16
+
17
+ x.index = index
18
+ data.push(x)
19
+ index += 1
20
+ end
21
+
22
+ q = new
23
+ q.instance_variable_set(:@data, data)
24
+ q.instance_variable_set(:@size, data.length)
25
+ q.heapify()
26
+
27
+ return q
28
+ end
29
+ end
30
+
31
+ def initialize
32
+ @data = []
33
+ @size = 0
34
+ heapify()
35
+ end
36
+
37
+ def peek
38
+ @data[0]
39
+ end
40
+
41
+ def pop
42
+ return nil if @size < 1
43
+
44
+ r = @data[0]
45
+
46
+ @data[0] = @data[@size-1]
47
+ @data[0].index = 0
48
+ @data.delete_at(@size-1)
49
+
50
+ @size -= 1
51
+
52
+ percolate_down(0) if @size > 0
53
+
54
+ return r
55
+ end
56
+
57
+ def push(data, priority=data)
58
+ @size += 1
59
+ @data[@size - 1] = QueueItem.new(priority, @size - 1, data)
60
+ percolate_up(@size - 1)
61
+ end
62
+
63
+ # Implemented in C
64
+ def reorder_queue;end
65
+
66
+ protected
67
+
68
+ # Implemented in C
69
+ # def heapify(data);end
70
+
71
+ # Implemented in C
72
+ # def percolate_up(i);end
73
+
74
+ # Implemented in C
75
+ # def percolate_down(i);end
76
+
77
+ class QueueItem
78
+ attr_accessor :priority, :index, :data
79
+ def initialize(p, i, d)
80
+ @priority = p
81
+ @index = i
82
+ @data = d
83
+ end
84
+ end
85
+
86
+ end
87
+ end
@@ -0,0 +1,3 @@
1
+ module RubyVor
2
+ VERSION = '0.1.3'
3
+ end
@@ -0,0 +1,218 @@
1
+ require 'xml/libxml' unless defined?(LibXML)
2
+ module RubyVor
3
+ class Visualizer
4
+
5
+ COLORS = %w{black red blue lime gray yellow purple orange pink}
6
+
7
+ # Support various versions of LibXML
8
+ include LibXML if defined?(LibXML)
9
+
10
+ def self.make_svg(computation, opts={})
11
+ @opts = opts = {
12
+ :name => 'vddt.svg',
13
+ :triangulation => true,
14
+ :voronoi_diagram => false,
15
+ :mst => false,
16
+ :cbd => false,
17
+ }.merge(opts)
18
+
19
+ line_colors = COLORS.clone
20
+
21
+ doc = XML::Document.new()
22
+
23
+ doc.root = XML::Node.new('svg')
24
+ doc.root['xmlns'] = 'http://www.w3.org/2000/svg'
25
+ doc.root['xml:space'] = 'preserve'
26
+
27
+ max_x = 0
28
+ min_x = Float::MAX
29
+ max_y = 0
30
+ min_y = Float::MAX
31
+ pmax_x = 0
32
+ pmin_x = Float::MAX
33
+ pmax_y = 0
34
+ pmin_y = Float::MAX
35
+
36
+ computation.points.each do |point|
37
+ max_x = point.x if point.x > max_x
38
+ min_x = point.x if point.x < min_x
39
+ max_y = point.y if point.y > max_y
40
+ min_y = point.y if point.y < min_y
41
+ pmax_x = point.x if point.x > pmax_x
42
+ pmin_x = point.x if point.x < pmin_x
43
+ pmax_y = point.y if point.y > pmax_y
44
+ pmin_y = point.y if point.y < pmin_y
45
+ end
46
+
47
+ if opts[:voronoi_diagram]
48
+ computation.voronoi_diagram_raw.each do |item|
49
+ if item.first == :v
50
+ max_x = item[1] if item[1] > max_x
51
+ min_x = item[1] if item[1] < min_x
52
+ max_y = item[2] if item[2] > max_y
53
+ min_y = item[2] if item[2] < min_y
54
+ end
55
+ end
56
+ end
57
+
58
+ opts[:offset_x] = -1.0 * min_x + 20
59
+ opts[:offset_y] = -1.0 * min_y + 20
60
+
61
+ if opts[:triangulation]
62
+ # Draw in the triangulation
63
+ color = line_colors.shift
64
+ computation.delaunay_triangulation_raw.each do |triplet|
65
+ for i in 0..2
66
+ line = line_from_points(computation.points[triplet[i % 2 + 1]], computation.points[triplet[i & 6]])
67
+ line['style'] = "stroke:#{color};stroke-width:1;"
68
+ doc.root << line
69
+ end
70
+ end
71
+ end
72
+
73
+ if opts[:mst]
74
+ color = line_colors.shift
75
+ computation.minimum_spanning_tree.each do |edge, weight|
76
+ line = line_from_points(computation.points[edge[0]], computation.points[edge[1]])
77
+ line['style'] = "stroke:#{color};stroke-width:1;"
78
+ doc.root << line
79
+ end
80
+ end
81
+
82
+ if opts[:cbd]
83
+ mst = computation.minimum_spanning_tree
84
+
85
+ computation.cluster_by_distance(opts[:cbd]).each do |cluster|
86
+
87
+ color = new_color
88
+ min_dist = Float::MAX
89
+ set_min = false
90
+ cluster.each do |a|
91
+ cluster.each do |b|
92
+ next if a == b
93
+ k = a < b ? [a,b] : [b,a]
94
+ next unless mst.has_key?(k)
95
+
96
+ if mst[k] < min_dist
97
+ min_dist = mst[k]
98
+ set_min = true
99
+ end
100
+ end
101
+ end
102
+
103
+ min_dist = 10 unless set_min
104
+
105
+
106
+ cluster.each do |v|
107
+ node = circle_from_point(computation.points[v])
108
+ node['r'] = (min_dist + 10).to_s
109
+ node['style'] = "fill:#{color};stroke:#{color};"
110
+ node['opacity'] = '0.4'
111
+
112
+ doc.root << node
113
+ end
114
+
115
+ end
116
+ end
117
+
118
+ if opts[:voronoi_diagram]
119
+ voronoi_vertices = []
120
+ draw_lines = []
121
+ draw_points = []
122
+ line_functions = []
123
+
124
+ xcut = (pmax_x + pmin_x) / 2.0
125
+ ycut = (pmax_y + pmin_y) / 2.0
126
+
127
+ color = line_colors.shift
128
+
129
+ computation.voronoi_diagram_raw.each do |item|
130
+ case item.first
131
+ when :v
132
+ # Draw a voronoi vertex
133
+ v = RubyVor::Point.new(item[1], item[2])
134
+ voronoi_vertices.push(v)
135
+ node = circle_from_point(v)
136
+ node['fill'] = 'red'
137
+ node['r'] = '2'
138
+ node['stroke'] = 'black'
139
+ node['stroke-width'] = '1'
140
+
141
+ draw_points << node
142
+ when :l
143
+ # :l a b c --> ax + by = c
144
+ a = item[1]
145
+ b = item[2]
146
+ c = item[3]
147
+ line_functions.push({ :y => lambda{|x| (c - a * x) / b},
148
+ :x => lambda{|y| (c - b * y) / a} })
149
+ when :e
150
+ if item[2] == -1 || item[3] == -1
151
+ from_vertex = voronoi_vertices[item[2] == -1 ? item[3] : item[2]]
152
+
153
+ next if from_vertex < RubyVor::Point.new(0,0)
154
+
155
+ if item[2] == -1
156
+ inf_vertex = RubyVor::Point.new(0, line_functions[item[1]][:y][0])
157
+ else
158
+ inf_vertex = RubyVor::Point.new(max_x, line_functions[item[1]][:y][max_x])
159
+ end
160
+
161
+ line = line_from_points(from_vertex, inf_vertex)
162
+ else
163
+ line = line_from_points(voronoi_vertices[item[2]], voronoi_vertices[item[3]])
164
+ end
165
+
166
+ line['style'] = "stroke:#{color};stroke-width:1;"
167
+ draw_lines << line
168
+
169
+ end
170
+ end
171
+
172
+ draw_lines.each {|l| doc.root << l}
173
+ draw_points.each {|p| doc.root << p}
174
+ end
175
+
176
+ # Now draw in nodes
177
+ computation.points.each do |point|
178
+ node = circle_from_point(point)
179
+ node['fill'] = 'lime'
180
+
181
+ doc.root << node
182
+ end
183
+
184
+ doc.root['width'] = (max_x + opts[:offset_x] + 50).to_s
185
+ doc.root['height'] = (max_y + opts[:offset_y] + 50).to_s
186
+
187
+ doc.save(opts[:name] || 'vddt.svg')
188
+ end
189
+
190
+ private
191
+ def self.line_from_points(a, b)
192
+ line = XML::Node.new('line')
193
+ line['x1'] = (a.x + @opts[:offset_x] + 10).to_s
194
+ line['y1'] = (a.y + @opts[:offset_y] + 10).to_s
195
+ line['x2'] = (b.x + @opts[:offset_x] + 10).to_s
196
+ line['y2'] = (b.y + @opts[:offset_y] + 10).to_s
197
+ line
198
+ end
199
+
200
+ def self.circle_from_point(point)
201
+ node = XML::Node.new('circle')
202
+ node['cx'] = (point.x + @opts[:offset_x] + 10).to_s
203
+ node['cy'] = (point.y + @opts[:offset_y] + 10).to_s
204
+ node['r'] = 5.to_s
205
+ node['stroke'] = 'black'
206
+ node['stroke-width'] = 2.to_s
207
+ node
208
+ end
209
+
210
+ def self.new_color
211
+ a = rand(256)
212
+ b = rand(256) | a
213
+ c = rand(256) ^ b
214
+
215
+ "rgb(#{[a,b,c].sort{|k,l| rand(3)-1}.join(',')})"
216
+ end
217
+ end
218
+ end
@@ -0,0 +1,35 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{rubyvor}
5
+ s.version = "0.1.3"
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{2010-01-26}
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 = ["Manifest.txt"]
14
+ s.files = ["History.rdoc", "Manifest.txt", "README.rdoc", "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.homepage = %q{http://github.com/bribera/rubyvor}
16
+ s.rdoc_options = ["--main", "README.rdoc"]
17
+ s.require_paths = ["lib", "ext"]
18
+ s.rubyforge_project = %q{rubyvor}
19
+ s.rubygems_version = %q{1.3.5}
20
+ s.summary = %q{Efficient Voronoi diagrams and Delaunay trianglation for Ruby}
21
+ s.test_files = ["test/test_computation.rb", "test/test_point.rb", "test/test_priority_queue.rb", "test/test_voronoi_interface.rb"]
22
+
23
+ if s.respond_to? :specification_version then
24
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
25
+ s.specification_version = 3
26
+
27
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
28
+ s.add_development_dependency(%q<hoe>, [">= 2.4.0"])
29
+ else
30
+ s.add_dependency(%q<hoe>, [">= 2.4.0"])
31
+ end
32
+ else
33
+ s.add_dependency(%q<hoe>, [">= 2.4.0"])
34
+ end
35
+ 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