10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
|
# File 'lib/ruby_vor/visualizer.rb', line 10
def self.make_svg(computation, opts={})
@opts = opts = {
:name => 'vddt.svg',
:triangulation => true,
:voronoi_diagram => false,
:mst => false,
:cbd => false,
}.merge(opts)
line_colors = COLORS.clone
doc = XML::Document.new()
doc.root = XML::Node.new('svg')
doc.root['xmlns'] = 'http://www.w3.org/2000/svg'
doc.root['xml:space'] = 'preserve'
max_x = 0
min_x = Float::MAX
max_y = 0
min_y = Float::MAX
pmax_x = 0
pmin_x = Float::MAX
pmax_y = 0
pmin_y = Float::MAX
computation.points.each do |point|
max_x = point.x if point.x > max_x
min_x = point.x if point.x < min_x
max_y = point.y if point.y > max_y
min_y = point.y if point.y < min_y
pmax_x = point.x if point.x > pmax_x
pmin_x = point.x if point.x < pmin_x
pmax_y = point.y if point.y > pmax_y
pmin_y = point.y if point.y < pmin_y
end
if opts[:voronoi_diagram]
computation.voronoi_diagram_raw.each do |item|
if item.first == :v
max_x = item[1] if item[1] > max_x
min_x = item[1] if item[1] < min_x
max_y = item[2] if item[2] > max_y
min_y = item[2] if item[2] < min_y
end
end
end
opts[:offset_x] = -1.0 * min_x + 20
opts[:offset_y] = -1.0 * min_y + 20
if opts[:triangulation]
color = line_colors.shift
computation.delaunay_triangulation_raw.each do |triplet|
for i in 0..2
line = line_from_points(computation.points[triplet[i % 2 + 1]], computation.points[triplet[i & 6]])
line['style'] = "stroke:#{color};stroke-width:1;"
doc.root << line
end
end
end
if opts[:mst]
color = line_colors.shift
computation.minimum_spanning_tree.each do |edge, weight|
line = line_from_points(computation.points[edge[0]], computation.points[edge[1]])
line['style'] = "stroke:#{color};stroke-width:1;"
doc.root << line
end
end
if opts[:cbd]
mst = computation.minimum_spanning_tree
computation.cluster_by_distance(opts[:cbd]).each do |cluster|
color = new_color
min_dist = Float::MAX
set_min = false
cluster.each do |a|
cluster.each do |b|
next if a == b
k = a < b ? [a,b] : [b,a]
next unless mst.has_key?(k)
if mst[k] < min_dist
min_dist = mst[k]
set_min = true
end
end
end
min_dist = 10 unless set_min
cluster.each do |v|
node = circle_from_point(computation.points[v])
node['r'] = (min_dist + 10).to_s
node['style'] = "fill:#{color};stroke:#{color};"
node['opacity'] = '0.4'
doc.root << node
end
end
end
if opts[:voronoi_diagram]
voronoi_vertices = []
draw_lines = []
draw_points = []
line_functions = []
xcut = (pmax_x + pmin_x) / 2.0
ycut = (pmax_y + pmin_y) / 2.0
color = line_colors.shift
computation.voronoi_diagram_raw.each do |item|
case item.first
when :v
v = RubyVor::Point.new(item[1], item[2])
voronoi_vertices.push(v)
node = circle_from_point(v)
node['fill'] = 'red'
node['r'] = '2'
node['stroke'] = 'black'
node['stroke-width'] = '1'
draw_points << node
when :l
a = item[1]
b = item[2]
c = item[3]
line_functions.push({ :y => lambda{|x| (c - a * x) / b},
:x => lambda{|y| (c - b * y) / a} })
when :e
if item[2] == -1 || item[3] == -1
from_vertex = voronoi_vertices[item[2] == -1 ? item[3] : item[2]]
next if from_vertex < RubyVor::Point.new(0,0)
if item[2] == -1
inf_vertex = RubyVor::Point.new(0, line_functions[item[1]][:y][0])
else
inf_vertex = RubyVor::Point.new(max_x, line_functions[item[1]][:y][max_x])
end
line = line_from_points(from_vertex, inf_vertex)
else
line = line_from_points(voronoi_vertices[item[2]], voronoi_vertices[item[3]])
end
line['style'] = "stroke:#{color};stroke-width:1;"
draw_lines << line
end
end
draw_lines.each {|l| doc.root << l}
draw_points.each {|p| doc.root << p}
end
computation.points.each do |point|
node = circle_from_point(point)
node['fill'] = 'lime'
doc.root << node
end
doc.root['width'] = (max_x + opts[:offset_x] + 50).to_s
doc.root['height'] = (max_y + opts[:offset_y] + 50).to_s
doc.save(opts[:name] || 'vddt.svg')
end
|