gruff 0.14.0-java → 0.17.0-java
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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +28 -12
- data/.gitignore +1 -0
- data/.rubocop.yml +20 -24
- data/CHANGELOG.md +52 -0
- data/README.md +10 -3
- data/gruff.gemspec +9 -10
- data/lib/gruff/accumulator_bar.rb +1 -1
- data/lib/gruff/area.rb +6 -4
- data/lib/gruff/bar.rb +53 -31
- data/lib/gruff/base.rb +292 -184
- data/lib/gruff/bezier.rb +4 -2
- data/lib/gruff/box_plot.rb +180 -0
- data/lib/gruff/bullet.rb +6 -6
- data/lib/gruff/candlestick.rb +120 -0
- data/lib/gruff/dot.rb +11 -12
- data/lib/gruff/font.rb +3 -0
- data/lib/gruff/helper/bar_conversion.rb +6 -10
- data/lib/gruff/helper/bar_mixin.rb +25 -0
- data/lib/gruff/helper/bar_value_label.rb +24 -40
- data/lib/gruff/helper/stacked_mixin.rb +19 -1
- data/lib/gruff/histogram.rb +9 -5
- data/lib/gruff/line.rb +49 -48
- data/lib/gruff/mini/legend.rb +11 -11
- data/lib/gruff/net.rb +23 -18
- data/lib/gruff/patch/rmagick.rb +0 -1
- data/lib/gruff/patch/string.rb +1 -0
- data/lib/gruff/pie.rb +26 -12
- data/lib/gruff/renderer/dash_line.rb +3 -2
- data/lib/gruff/renderer/dot.rb +28 -15
- data/lib/gruff/renderer/line.rb +1 -3
- data/lib/gruff/renderer/rectangle.rb +6 -2
- data/lib/gruff/renderer/renderer.rb +4 -8
- data/lib/gruff/renderer/text.rb +7 -1
- data/lib/gruff/scatter.rb +64 -56
- data/lib/gruff/side_bar.rb +64 -30
- data/lib/gruff/side_stacked_bar.rb +43 -54
- data/lib/gruff/spider.rb +52 -18
- data/lib/gruff/stacked_area.rb +18 -8
- data/lib/gruff/stacked_bar.rb +59 -29
- data/lib/gruff/store/xy_data.rb +2 -0
- data/lib/gruff/version.rb +1 -1
- data/lib/gruff.rb +67 -58
- metadata +17 -16
- data/.rubocop_todo.yml +0 -116
- data/lib/gruff/scene.rb +0 -200
- data/lib/gruff/store/custom_data.rb +0 -36
data/lib/gruff/scatter.rb
CHANGED
@@ -114,16 +114,35 @@ private
|
|
114
114
|
@x_label_margin = nil
|
115
115
|
end
|
116
116
|
|
117
|
-
def
|
118
|
-
|
119
|
-
|
117
|
+
def setup_drawing
|
118
|
+
@center_labels_over_point = false
|
119
|
+
super
|
120
|
+
end
|
121
|
+
|
122
|
+
def setup_data
|
123
|
+
# TODO: Need to get x-axis labels working. Current behavior will be to not allow.
|
124
|
+
@labels = {}
|
125
|
+
|
126
|
+
# Update the global min/max values for the x data
|
127
|
+
@maximum_x_value = (@maximum_x_value || store.max_x).to_f
|
128
|
+
@minimum_x_value = (@minimum_x_value || store.min_x).to_f
|
129
|
+
|
130
|
+
if @x_axis_increment
|
131
|
+
# TODO: Make this work for negative values
|
132
|
+
@maximum_x_value = [@maximum_x_value.ceil, @x_axis_increment.to_f].max
|
133
|
+
@minimum_x_value = @minimum_x_value.floor
|
134
|
+
end
|
120
135
|
|
136
|
+
super
|
137
|
+
end
|
138
|
+
|
139
|
+
def draw_graph
|
121
140
|
store.norm_data.each do |data_row|
|
122
141
|
data_row.coordinates.each do |x_value, y_value|
|
123
142
|
next if y_value.nil? || x_value.nil?
|
124
143
|
|
125
144
|
new_x = get_x_coord(x_value, @graph_width, @graph_left)
|
126
|
-
new_y = @graph_top + (@graph_height - y_value * @graph_height)
|
145
|
+
new_y = @graph_top + (@graph_height - (y_value * @graph_height))
|
127
146
|
|
128
147
|
# Reset each time to avoid thin-line errors
|
129
148
|
stroke_width = @stroke_width || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 4), 5.0)
|
@@ -133,22 +152,7 @@ private
|
|
133
152
|
end
|
134
153
|
end
|
135
154
|
|
136
|
-
def
|
137
|
-
# Update the global min/max values for the x data
|
138
|
-
@maximum_x_value ||= store.max_x
|
139
|
-
@minimum_x_value ||= store.min_x
|
140
|
-
|
141
|
-
super
|
142
|
-
end
|
143
|
-
|
144
|
-
def setup_drawing
|
145
|
-
# TODO: Need to get x-axis labels working. Current behavior will be to not allow.
|
146
|
-
@labels = {}
|
147
|
-
|
148
|
-
super
|
149
|
-
end
|
150
|
-
|
151
|
-
def calculate_spread #:nodoc:
|
155
|
+
def calculate_spread
|
152
156
|
super
|
153
157
|
@x_spread = @maximum_x_value.to_f - @minimum_x_value.to_f
|
154
158
|
@x_spread = @x_spread > 0 ? @x_spread : 1
|
@@ -165,49 +169,21 @@ private
|
|
165
169
|
super
|
166
170
|
return if @hide_line_markers
|
167
171
|
|
168
|
-
|
169
|
-
# TODO: Do the same for larger numbers...100, 75, 50, 25
|
170
|
-
if @marker_x_count.nil?
|
171
|
-
(3..7).each do |lines|
|
172
|
-
if @x_spread % lines == 0.0
|
173
|
-
@marker_x_count = lines
|
174
|
-
break
|
175
|
-
end
|
176
|
-
end
|
177
|
-
@marker_x_count ||= 4
|
178
|
-
end
|
179
|
-
@x_increment = (@x_spread > 0) ? (@x_spread / @marker_x_count) : 1
|
180
|
-
unless @disable_significant_rounding_x_axis
|
181
|
-
@x_increment = significant(@x_increment)
|
182
|
-
end
|
183
|
-
else
|
184
|
-
# TODO: Make this work for negative values
|
185
|
-
@maximum_x_value = [@maximum_x_value.ceil, @x_axis_increment].max
|
186
|
-
@minimum_x_value = @minimum_x_value.floor
|
187
|
-
calculate_spread
|
188
|
-
normalize
|
189
|
-
|
190
|
-
@marker_x_count = (@x_spread / @x_axis_increment).to_i
|
191
|
-
@x_increment = @x_axis_increment
|
192
|
-
end
|
193
|
-
increment_x_scaled = @graph_width.to_f / (@x_spread / @x_increment)
|
172
|
+
increment_x_scaled = @graph_width / (@x_spread / x_increment)
|
194
173
|
|
195
174
|
# Draw vertical line markers and annotate with numbers
|
196
|
-
(0
|
175
|
+
(0..marker_x_count).each do |index|
|
197
176
|
# TODO: Fix the vertical lines, and enable them by default. Not pretty when they don't match up with top y-axis line
|
198
177
|
if @show_vertical_markers
|
199
|
-
|
200
|
-
|
201
|
-
line_renderer = Gruff::Renderer::Line.new(renderer, color: @marker_color, shadow_color: @marker_shadow_color)
|
202
|
-
line_renderer.render(x, @graph_top, x, @graph_bottom)
|
178
|
+
draw_marker_vertical_line(@graph_left + @graph_width - (index * increment_x_scaled))
|
203
179
|
end
|
204
180
|
|
205
181
|
unless @hide_line_numbers
|
206
|
-
marker_label = BigDecimal(index.to_s) * BigDecimal(
|
182
|
+
marker_label = (BigDecimal(index.to_s) * BigDecimal(x_increment.to_s)) + BigDecimal(@minimum_x_value.to_s)
|
207
183
|
y_offset = @graph_bottom + (@x_label_margin || LABEL_MARGIN)
|
208
|
-
x_offset = get_x_coord(index
|
184
|
+
x_offset = get_x_coord(index, increment_x_scaled, @graph_left)
|
209
185
|
|
210
|
-
label = x_axis_label(marker_label,
|
186
|
+
label = x_axis_label(marker_label, x_increment)
|
211
187
|
rotation = -90.0 if @use_vertical_x_labels
|
212
188
|
text_renderer = Gruff::Renderer::Text.new(renderer, label, font: @marker_font, rotation: rotation)
|
213
189
|
text_renderer.add_to_render_queue(1.0, 1.0, x_offset, y_offset)
|
@@ -215,7 +191,39 @@ private
|
|
215
191
|
end
|
216
192
|
end
|
217
193
|
|
218
|
-
def get_x_coord(x_data_point, width, offset)
|
219
|
-
x_data_point * width + offset
|
194
|
+
def get_x_coord(x_data_point, width, offset)
|
195
|
+
(x_data_point * width) + offset
|
196
|
+
end
|
197
|
+
|
198
|
+
def marker_x_count
|
199
|
+
# TODO: Do the same for larger numbers...100, 75, 50, 25
|
200
|
+
@marker_x_count ||= begin
|
201
|
+
if @x_axis_increment.nil?
|
202
|
+
count = nil
|
203
|
+
(3..7).each do |lines|
|
204
|
+
if @x_spread % lines == 0.0
|
205
|
+
count = lines and break
|
206
|
+
end
|
207
|
+
end
|
208
|
+
count || 4
|
209
|
+
else
|
210
|
+
(@x_spread / @x_axis_increment).to_i
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def x_increment
|
216
|
+
@x_increment ||= begin
|
217
|
+
if @x_axis_increment.nil?
|
218
|
+
increment = @x_spread > 0 ? (@x_spread / marker_x_count) : 1
|
219
|
+
unless @disable_significant_rounding_x_axis
|
220
|
+
increment = significant(increment)
|
221
|
+
end
|
222
|
+
else
|
223
|
+
increment = @x_axis_increment
|
224
|
+
end
|
225
|
+
|
226
|
+
increment
|
227
|
+
end
|
220
228
|
end
|
221
229
|
end
|
data/lib/gruff/side_bar.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'helper/bar_mixin'
|
4
|
+
|
3
5
|
# Graph with individual horizontal bars instead of vertical bars.
|
4
6
|
#
|
5
7
|
# Here's how to set up a Gruff::SideBar.
|
@@ -19,6 +21,8 @@
|
|
19
21
|
# g.write('sidebar.png')
|
20
22
|
#
|
21
23
|
class Gruff::SideBar < Gruff::Base
|
24
|
+
include BarMixin
|
25
|
+
|
22
26
|
# Spacing factor applied between bars.
|
23
27
|
attr_writer :bar_spacing
|
24
28
|
|
@@ -36,6 +40,15 @@ class Gruff::SideBar < Gruff::Base
|
|
36
40
|
# Prevent drawing of column labels left of a side bar graph. Default is +false+.
|
37
41
|
attr_writer :hide_labels
|
38
42
|
|
43
|
+
# Value to avoid completely overwriting the coordinate axis
|
44
|
+
AXIS_MARGIN = 0.5
|
45
|
+
private_constant :AXIS_MARGIN
|
46
|
+
|
47
|
+
def initialize(*)
|
48
|
+
super
|
49
|
+
@has_left_labels = true
|
50
|
+
end
|
51
|
+
|
39
52
|
# With Side Bars use the data label for the marker value to the left of the bar.
|
40
53
|
# @deprecated
|
41
54
|
def use_data_label=(_value)
|
@@ -51,7 +64,6 @@ private
|
|
51
64
|
@label_formatting = nil
|
52
65
|
@show_labels_for_bar_values = false
|
53
66
|
@hide_labels = false
|
54
|
-
@has_left_labels = true
|
55
67
|
end
|
56
68
|
|
57
69
|
def hide_labels?
|
@@ -59,20 +71,37 @@ private
|
|
59
71
|
end
|
60
72
|
|
61
73
|
def hide_left_label_area?
|
62
|
-
hide_labels?
|
74
|
+
hide_labels? && @y_axis_label.nil?
|
63
75
|
end
|
64
76
|
|
65
77
|
def hide_bottom_label_area?
|
66
|
-
@hide_line_markers
|
78
|
+
@hide_line_markers && @x_axis_label.nil? && @legend_at_bottom == false
|
67
79
|
end
|
68
80
|
|
69
|
-
|
70
|
-
|
81
|
+
def setup_graph_measurements
|
82
|
+
super
|
83
|
+
return if @hide_line_markers
|
84
|
+
|
85
|
+
if @show_labels_for_bar_values
|
86
|
+
if maximum_value >= 0
|
87
|
+
_, metrics = Gruff::BarValueLabel.metrics(maximum_value, @label_formatting, proc_text_metrics)
|
88
|
+
@graph_right -= metrics.width
|
89
|
+
end
|
90
|
+
|
91
|
+
if minimum_value < 0
|
92
|
+
_, metrics = Gruff::BarValueLabel.metrics(minimum_value, @label_formatting, proc_text_metrics)
|
93
|
+
width = metrics.width + LABEL_MARGIN
|
94
|
+
@graph_left += width - @graph_left if width > @graph_left
|
95
|
+
end
|
96
|
+
|
97
|
+
@graph_width = @graph_right - @graph_left
|
98
|
+
end
|
99
|
+
end
|
71
100
|
|
72
101
|
def draw_graph
|
73
102
|
# Setup spacing.
|
74
103
|
#
|
75
|
-
bars_width = (@graph_height - calculate_spacing) / column_count
|
104
|
+
bars_width = (@graph_height - calculate_spacing) / column_count
|
76
105
|
bar_width = bars_width / store.length
|
77
106
|
padding = (bar_width * (1 - @bar_spacing)) / 2
|
78
107
|
|
@@ -82,30 +111,33 @@ private
|
|
82
111
|
minimum_value: minimum_value, maximum_value: maximum_value, spread: @spread
|
83
112
|
)
|
84
113
|
|
85
|
-
|
86
|
-
|
87
|
-
group_spacing = @group_spacing * @scale * point_index
|
88
|
-
|
89
|
-
left_y = @graph_top + (bars_width * point_index) + (bar_width * row_index) + padding + group_spacing
|
90
|
-
right_y = left_y + bar_width * @bar_spacing
|
114
|
+
group_spacing = @group_spacing * @scale
|
115
|
+
group_left_y = @graph_top
|
91
116
|
|
92
|
-
|
117
|
+
normalized_group_bars.each_with_index do |group_bars, group_index|
|
118
|
+
right_y = 0
|
119
|
+
group_bars.each_with_index do |bar, index|
|
120
|
+
left_y = group_left_y + (bar_width * index) + padding
|
121
|
+
right_y = left_y + (bar_width * @bar_spacing)
|
93
122
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
123
|
+
bottom_x, top_x = conversion.get_top_bottom_scaled(bar.point).sort
|
124
|
+
if bar.point != 0
|
125
|
+
rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: bar.color)
|
126
|
+
rect_renderer.render(bottom_x + AXIS_MARGIN, left_y, top_x, right_y)
|
127
|
+
end
|
99
128
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
bar_value_label.prepare_rendering(@label_formatting, bar_width) do |x, y, text|
|
105
|
-
draw_value_label(x, y, text)
|
129
|
+
if @show_labels_for_bar_values && bar.value
|
130
|
+
bar_value_label = Gruff::BarValueLabel::SideBar.new([bottom_x, left_y, top_x, right_y], bar.value)
|
131
|
+
bar_value_label.prepare_rendering(@label_formatting, proc_text_metrics) do |x, y, text, text_width, _text_height|
|
132
|
+
draw_value_label(text_width, bar_width * @bar_spacing, x, y, text)
|
106
133
|
end
|
107
134
|
end
|
108
135
|
end
|
136
|
+
|
137
|
+
label_center = group_left_y + (bars_width / 2.0)
|
138
|
+
draw_label(label_center, group_index)
|
139
|
+
|
140
|
+
group_left_y = right_y + padding + group_spacing
|
109
141
|
end
|
110
142
|
end
|
111
143
|
|
@@ -118,17 +150,15 @@ private
|
|
118
150
|
number_of_lines = 1 if number_of_lines == 0
|
119
151
|
|
120
152
|
# TODO: Round maximum marker value to a round number like 100, 0.1, 0.5, etc.
|
121
|
-
increment = significant(@spread
|
153
|
+
increment = significant(@spread / number_of_lines)
|
122
154
|
(0..number_of_lines).each do |index|
|
123
155
|
line_diff = (@graph_right - @graph_left) / number_of_lines
|
124
156
|
x = @graph_right - (line_diff * index) - 1
|
125
|
-
|
126
|
-
line_renderer = Gruff::Renderer::Line.new(renderer, color: @marker_color, shadow_color: @marker_shadow_color)
|
127
|
-
line_renderer.render(x, @graph_bottom, x, @graph_top)
|
157
|
+
draw_marker_vertical_line(x)
|
128
158
|
|
129
159
|
unless @hide_line_numbers
|
130
160
|
diff = index - number_of_lines
|
131
|
-
marker_label = BigDecimal(diff.abs.to_s) * BigDecimal(increment.to_s) + BigDecimal(minimum_value.to_s)
|
161
|
+
marker_label = (BigDecimal(diff.abs.to_s) * BigDecimal(increment.to_s)) + BigDecimal(minimum_value.to_s)
|
132
162
|
label = x_axis_label(marker_label, @increment)
|
133
163
|
text_renderer = Gruff::Renderer::Text.new(renderer, label, font: @marker_font)
|
134
164
|
text_renderer.add_to_render_queue(0, 0, x, @graph_bottom + LABEL_MARGIN, Magick::CenterGravity)
|
@@ -141,11 +171,15 @@ private
|
|
141
171
|
|
142
172
|
def draw_label(y_offset, index)
|
143
173
|
draw_unique_label(index) do
|
144
|
-
draw_label_at(@graph_left - LABEL_MARGIN, 1.0, 0.0, y_offset, @labels[index], Magick::EastGravity)
|
174
|
+
draw_label_at(@graph_left - LABEL_MARGIN, 1.0, 0.0, y_offset, @labels[index], gravity: Magick::EastGravity)
|
145
175
|
end
|
146
176
|
end
|
147
177
|
|
148
178
|
def calculate_spacing
|
149
179
|
@scale * @group_spacing * (column_count - 1)
|
150
180
|
end
|
181
|
+
|
182
|
+
def proc_text_metrics
|
183
|
+
->(text) { text_metrics(@marker_font, text) }
|
184
|
+
end
|
151
185
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'helper/stacked_mixin'
|
4
|
+
|
3
5
|
#
|
4
6
|
# New gruff graph type added to enable sideways stacking bar charts
|
5
7
|
# (basically looks like a x/y flip of a standard stacking bar chart)
|
@@ -39,6 +41,11 @@ class Gruff::SideStackedBar < Gruff::SideBar
|
|
39
41
|
# Prevent drawing of column labels left of a side stacked bar graph. Default is +false+.
|
40
42
|
attr_writer :hide_labels
|
41
43
|
|
44
|
+
def initialize(*)
|
45
|
+
super
|
46
|
+
@has_left_labels = true
|
47
|
+
end
|
48
|
+
|
42
49
|
private
|
43
50
|
|
44
51
|
def initialize_attributes
|
@@ -48,7 +55,7 @@ private
|
|
48
55
|
@label_formatting = nil
|
49
56
|
@show_labels_for_bar_values = false
|
50
57
|
@hide_labels = false
|
51
|
-
@
|
58
|
+
@minimum_value = 0.0
|
52
59
|
end
|
53
60
|
|
54
61
|
def setup_data
|
@@ -56,66 +63,48 @@ private
|
|
56
63
|
super
|
57
64
|
end
|
58
65
|
|
59
|
-
def hide_labels?
|
60
|
-
@hide_labels
|
61
|
-
end
|
62
|
-
|
63
|
-
def hide_left_label_area?
|
64
|
-
hide_labels?
|
65
|
-
end
|
66
|
-
|
67
|
-
def hide_bottom_label_area?
|
68
|
-
@hide_line_markers
|
69
|
-
end
|
70
|
-
|
71
66
|
def draw_graph
|
72
67
|
# Setup spacing.
|
73
68
|
#
|
74
69
|
# Columns sit stacked.
|
75
|
-
bar_width = @graph_height / column_count
|
76
|
-
height = Array.new(column_count, 0)
|
77
|
-
length = Array.new(column_count, @graph_left)
|
70
|
+
bar_width = @graph_height / column_count
|
78
71
|
padding = (bar_width * (1 - @bar_spacing)) / 2
|
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
|
-
rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: data_row.color)
|
106
|
-
rect_renderer.render(left_x, left_y, right_x, right_y)
|
107
|
-
# Calculate center based on bar_width and current row
|
108
|
-
end
|
109
|
-
# we still need to draw the labels
|
110
|
-
# Calculate center based on bar_width and current row
|
111
|
-
label_center = left_y + bar_width / 2
|
112
|
-
draw_label(label_center, point_index)
|
72
|
+
|
73
|
+
# Setup the BarConversion Object
|
74
|
+
conversion = Gruff::BarConversion.new(
|
75
|
+
top: @graph_right, bottom: @graph_left,
|
76
|
+
minimum_value: minimum_value, maximum_value: maximum_value, spread: @spread
|
77
|
+
)
|
78
|
+
|
79
|
+
proc_text_metrics = ->(text) { text_metrics(@marker_font, text) }
|
80
|
+
|
81
|
+
normalized_stacked_bars.each_with_index do |stacked_bars, stacked_index|
|
82
|
+
total = 0
|
83
|
+
left_y = @graph_top + (bar_width * stacked_index) + padding
|
84
|
+
right_y = left_y + (bar_width * @bar_spacing)
|
85
|
+
|
86
|
+
top_x = 0
|
87
|
+
stacked_bars.each do |bar|
|
88
|
+
next if bar.point == 0
|
89
|
+
|
90
|
+
bottom_x, = conversion.get_top_bottom_scaled(total)
|
91
|
+
bottom_x += @segment_spacing
|
92
|
+
top_x, = conversion.get_top_bottom_scaled(total + bar.point)
|
93
|
+
|
94
|
+
rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: bar.color)
|
95
|
+
rect_renderer.render(bottom_x, left_y, top_x, right_y)
|
96
|
+
|
97
|
+
total += bar.point
|
113
98
|
end
|
114
|
-
end
|
115
99
|
|
116
|
-
|
117
|
-
|
118
|
-
|
100
|
+
label_center = left_y + (bar_width / 2.0)
|
101
|
+
draw_label(label_center, stacked_index)
|
102
|
+
|
103
|
+
if @show_labels_for_bar_values
|
104
|
+
bar_value_label = Gruff::BarValueLabel::SideBar.new([@graph_left, left_y, top_x, right_y], stacked_bars.sum(&:value))
|
105
|
+
bar_value_label.prepare_rendering(@label_formatting, proc_text_metrics) do |x, y, text, text_width, _text_height|
|
106
|
+
draw_value_label(text_width, bar_width * @bar_spacing, x, y, text)
|
107
|
+
end
|
119
108
|
end
|
120
109
|
end
|
121
110
|
end
|
data/lib/gruff/spider.rb
CHANGED
@@ -19,6 +19,11 @@ class Gruff::Spider < Gruff::Base
|
|
19
19
|
attr_writer :hide_axes
|
20
20
|
attr_writer :rotation
|
21
21
|
|
22
|
+
def initialize(max_value, target_width = 800)
|
23
|
+
super(target_width)
|
24
|
+
@max_value = max_value
|
25
|
+
end
|
26
|
+
|
22
27
|
def transparent_background=(value)
|
23
28
|
renderer.transparent_background(@columns, @rows) if value
|
24
29
|
end
|
@@ -27,11 +32,6 @@ class Gruff::Spider < Gruff::Base
|
|
27
32
|
@hide_title = @hide_text = value
|
28
33
|
end
|
29
34
|
|
30
|
-
def initialize(max_value, target_width = 800)
|
31
|
-
super(target_width)
|
32
|
-
@max_value = max_value
|
33
|
-
end
|
34
|
-
|
35
35
|
private
|
36
36
|
|
37
37
|
def initialize_attributes
|
@@ -46,6 +46,29 @@ private
|
|
46
46
|
@hide_line_markers.freeze
|
47
47
|
end
|
48
48
|
|
49
|
+
def setup_drawing
|
50
|
+
@center_labels_over_point = false
|
51
|
+
super
|
52
|
+
end
|
53
|
+
|
54
|
+
def setup_graph_measurements
|
55
|
+
super
|
56
|
+
|
57
|
+
@graph_left += LABEL_MARGIN
|
58
|
+
@graph_top += LABEL_MARGIN
|
59
|
+
@graph_right -= LABEL_MARGIN
|
60
|
+
@graph_bottom -= LABEL_MARGIN
|
61
|
+
|
62
|
+
@graph_width = @graph_right - @graph_left
|
63
|
+
@graph_height = @graph_bottom - @graph_top
|
64
|
+
end
|
65
|
+
|
66
|
+
def setup_data
|
67
|
+
raise(Gruff::IncorrectNumberOfDatasetsException, 'Requires 3 or more data sets') if store.length < 3
|
68
|
+
|
69
|
+
super
|
70
|
+
end
|
71
|
+
|
49
72
|
def draw_graph
|
50
73
|
# Setup basic positioning
|
51
74
|
radius = @graph_height / 2.0
|
@@ -64,23 +87,38 @@ private
|
|
64
87
|
end
|
65
88
|
|
66
89
|
def normalize_points(value)
|
67
|
-
value * @unit_length
|
90
|
+
value.to_f * @unit_length
|
68
91
|
end
|
69
92
|
|
70
93
|
def draw_label(center_x, center_y, angle, radius, amount)
|
71
|
-
|
72
|
-
|
73
|
-
|
94
|
+
degree = rad2deg(angle)
|
95
|
+
metrics = text_metrics(@marker_font, amount)
|
96
|
+
|
97
|
+
r_offset = LABEL_MARGIN # The distance out from the center of the pie to get point
|
98
|
+
x_offset = center_x # The label points need to be tweaked slightly
|
99
|
+
|
100
|
+
x_offset -= begin
|
101
|
+
case degree
|
102
|
+
when 0..45, 315..360
|
103
|
+
0
|
104
|
+
when 135..225
|
105
|
+
metrics.width
|
106
|
+
else
|
107
|
+
metrics.width / 2
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
y_offset = center_y - (metrics.height / 2.0) # This one doesn't though
|
74
112
|
x = x_offset + ((radius + r_offset) * Math.cos(angle))
|
75
113
|
y = y_offset + ((radius + r_offset) * Math.sin(angle))
|
76
114
|
|
77
|
-
draw_label_at(
|
115
|
+
draw_label_at(metrics.width, metrics.height, x, y, amount, gravity: Magick::CenterGravity)
|
78
116
|
end
|
79
117
|
|
80
118
|
def draw_axes(center_x, center_y, radius, additive_angle, line_color = nil)
|
81
119
|
return if @hide_axes
|
82
120
|
|
83
|
-
current_angle = @rotation
|
121
|
+
current_angle = deg2rad(@rotation)
|
84
122
|
|
85
123
|
store.data.each do |data_row|
|
86
124
|
x_offset = radius * Math.cos(current_angle)
|
@@ -97,18 +135,14 @@ private
|
|
97
135
|
|
98
136
|
def draw_polygon(center_x, center_y, additive_angle, color = nil)
|
99
137
|
points = []
|
100
|
-
current_angle = @rotation
|
138
|
+
current_angle = deg2rad(@rotation)
|
101
139
|
|
102
140
|
store.data.each do |data_row|
|
103
|
-
points << center_x + normalize_points(data_row.points.first) * Math.cos(current_angle)
|
104
|
-
points << center_y + normalize_points(data_row.points.first) * Math.sin(current_angle)
|
141
|
+
points << (center_x + (normalize_points(data_row.points.first) * Math.cos(current_angle)))
|
142
|
+
points << (center_y + (normalize_points(data_row.points.first) * Math.sin(current_angle)))
|
105
143
|
current_angle += additive_angle
|
106
144
|
end
|
107
145
|
|
108
146
|
Gruff::Renderer::Polygon.new(renderer, color: color || @marker_color, opacity: 0.4).render(points)
|
109
147
|
end
|
110
|
-
|
111
|
-
def sums_for_spider
|
112
|
-
store.data.sum { |data_row| data_row.points.first }
|
113
|
-
end
|
114
148
|
end
|
data/lib/gruff/stacked_area.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'helper/stacked_mixin'
|
4
|
+
|
3
5
|
#
|
4
6
|
# Here's how to set up a Gruff::StackedArea.
|
5
7
|
#
|
@@ -20,25 +22,31 @@ class Gruff::StackedArea < Gruff::Base
|
|
20
22
|
|
21
23
|
private
|
22
24
|
|
25
|
+
def initialize_attributes
|
26
|
+
super
|
27
|
+
@minimum_value = 0.0
|
28
|
+
end
|
29
|
+
|
23
30
|
def setup_data
|
24
31
|
calculate_maximum_by_stack
|
25
32
|
super
|
26
33
|
end
|
27
34
|
|
28
35
|
def draw_graph
|
29
|
-
x_increment = @graph_width / (column_count - 1)
|
36
|
+
x_increment = @graph_width / (column_count - 1)
|
30
37
|
|
31
38
|
height = Array.new(column_count, 0)
|
32
39
|
|
33
|
-
|
40
|
+
prev_data_points = nil
|
34
41
|
store.norm_data.each do |data_row|
|
35
|
-
|
42
|
+
next if data_row.points.empty?
|
43
|
+
|
36
44
|
data_points = []
|
37
45
|
|
38
46
|
data_row.points.each_with_index do |data_point, index|
|
39
47
|
# Use incremented x and scaled y
|
40
48
|
new_x = @graph_left + (x_increment * index)
|
41
|
-
new_y = @graph_top + (@graph_height - data_point * @graph_height - height[index])
|
49
|
+
new_y = @graph_top + (@graph_height - (data_point * @graph_height) - height[index])
|
42
50
|
|
43
51
|
height[index] += (data_point * @graph_height)
|
44
52
|
|
@@ -50,20 +58,22 @@ private
|
|
50
58
|
|
51
59
|
poly_points = data_points.dup
|
52
60
|
if prev_data_points
|
53
|
-
(prev_data_points.length / 2 - 1).downto(0) do |i|
|
61
|
+
((prev_data_points.length / 2) - 1).downto(0) do |i|
|
54
62
|
poly_points << prev_data_points[2 * i]
|
55
|
-
poly_points << prev_data_points[2 * i + 1]
|
63
|
+
poly_points << prev_data_points[(2 * i) + 1]
|
56
64
|
end
|
57
65
|
else
|
58
66
|
poly_points << @graph_right
|
59
|
-
poly_points << @graph_bottom - 1
|
67
|
+
poly_points << (@graph_bottom - 1)
|
60
68
|
poly_points << @graph_left
|
61
|
-
poly_points << @graph_bottom - 1
|
69
|
+
poly_points << (@graph_bottom - 1)
|
62
70
|
end
|
63
71
|
poly_points << data_points[0]
|
64
72
|
poly_points << data_points[1]
|
65
73
|
|
66
74
|
Gruff::Renderer::Polygon.new(renderer, color: data_row.color).render(poly_points)
|
75
|
+
|
76
|
+
prev_data_points = data_points
|
67
77
|
end
|
68
78
|
end
|
69
79
|
end
|