8
9
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
|
# File 'lib/cmd_plot/plot.rb', line 8
def plot(x, y = nil)
if y.nil?
y = x
x = BasicData::linspace(0.0, y.length, y.length)
end
x_max = x.compact.max
x_min = x.compact.min
x = x.map { |v| v.nil? ? nil : ((v - x_min) / (x_max - x_min).to_f * (@width - 1)).round }
y_max = y.compact.max
y_min = y.compact.min
y = y.map { |v| v.nil? ? nil : ((v - y_min) / (y_max - y_min).to_f * (@height - 1)).round }
picture = Array.new(@height) { Array.new(@width) {' '} }
for point in x.zip(y)
next if point[1].nil? || point[0].nil?
picture[@height - 1 - point[1]][point[0]] = @symbol
end
x_ticks = BasicData::linspace(x_min, x_max, [2, @width / 15].max).map { |v|
tick_to_display(v)
}
y_ticks = BasicData::linspace(y_max, y_min, [2, @height / 10].max).map { |v|
tick_to_display(v)
}
y_tick_width = y_ticks.map { |e| e.length }.max
y_tick_spacing = (@height - y_ticks.length) / (y_ticks.length - 1)
missing = @height - (y_tick_spacing * (y_ticks.length - 1) + y_ticks.length)
missing_dist = missing == 0 ? @height : y_ticks.length / missing.to_f
row = 0
next_tick = 0
tick_offset = 0
for line in picture
if row == (tick_offset + next_tick * (y_tick_spacing + 1))
print ' ' * (y_tick_width - y_ticks[next_tick].length)
print y_ticks[next_tick] + ' ├ '
next_tick += 1
tick_offset += 1 if ((tick_offset + 1) * missing_dist) < (next_tick + 2)
else
print ' ' * y_tick_width + ' │ '
end
puts line.join
row += 1
end
x_tick_spacing = (@width - x_ticks.length) / (x_ticks.length - 1)
missing = @width - (x_tick_spacing * (x_ticks.length - 1) + x_ticks.length)
missing_dist = missing == 0 ? @width : x_ticks.length / missing.to_f
print ' ' * y_tick_width + ' └─'
next_tick = 0
added_space = 0
for tick in x_ticks
if tick == x_ticks[-1]
puts '┴'
else
print '┴'
print '─' * x_tick_spacing
next_tick += 1
if ((added_space + 1) * missing_dist) < (next_tick + 2)
added_space += 1
print '─'
end
end
end
total_label_length = x_ticks.map(&:length).inject(:+)
x_tick_label_spacing = (@width - total_label_length) / (x_ticks.length - 1)
missing = @width - (x_tick_label_spacing * (x_ticks.length - 1) + total_label_length)
missing_dist = missing == 0 ? @width : x_ticks.length / missing.to_f
print ' ' * y_tick_width + ' '
next_tick = 0
added_space = 0
for tick in x_ticks
if tick == x_ticks[-1]
puts tick
else
print tick
print ' ' * x_tick_label_spacing
next_tick += 1
if ((added_space + 1) * missing_dist) < (next_tick + 2)
added_space += 1
print ' '
end
end
end
return nil
end
|