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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +28 -12
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +20 -24
  5. data/CHANGELOG.md +52 -0
  6. data/README.md +10 -3
  7. data/gruff.gemspec +9 -10
  8. data/lib/gruff/accumulator_bar.rb +1 -1
  9. data/lib/gruff/area.rb +6 -4
  10. data/lib/gruff/bar.rb +53 -31
  11. data/lib/gruff/base.rb +292 -184
  12. data/lib/gruff/bezier.rb +4 -2
  13. data/lib/gruff/box_plot.rb +180 -0
  14. data/lib/gruff/bullet.rb +6 -6
  15. data/lib/gruff/candlestick.rb +120 -0
  16. data/lib/gruff/dot.rb +11 -12
  17. data/lib/gruff/font.rb +3 -0
  18. data/lib/gruff/helper/bar_conversion.rb +6 -10
  19. data/lib/gruff/helper/bar_mixin.rb +25 -0
  20. data/lib/gruff/helper/bar_value_label.rb +24 -40
  21. data/lib/gruff/helper/stacked_mixin.rb +19 -1
  22. data/lib/gruff/histogram.rb +9 -5
  23. data/lib/gruff/line.rb +49 -48
  24. data/lib/gruff/mini/legend.rb +11 -11
  25. data/lib/gruff/net.rb +23 -18
  26. data/lib/gruff/patch/rmagick.rb +0 -1
  27. data/lib/gruff/patch/string.rb +1 -0
  28. data/lib/gruff/pie.rb +26 -12
  29. data/lib/gruff/renderer/dash_line.rb +3 -2
  30. data/lib/gruff/renderer/dot.rb +28 -15
  31. data/lib/gruff/renderer/line.rb +1 -3
  32. data/lib/gruff/renderer/rectangle.rb +6 -2
  33. data/lib/gruff/renderer/renderer.rb +4 -8
  34. data/lib/gruff/renderer/text.rb +7 -1
  35. data/lib/gruff/scatter.rb +64 -56
  36. data/lib/gruff/side_bar.rb +64 -30
  37. data/lib/gruff/side_stacked_bar.rb +43 -54
  38. data/lib/gruff/spider.rb +52 -18
  39. data/lib/gruff/stacked_area.rb +18 -8
  40. data/lib/gruff/stacked_bar.rb +59 -29
  41. data/lib/gruff/store/xy_data.rb +2 -0
  42. data/lib/gruff/version.rb +1 -1
  43. data/lib/gruff.rb +67 -58
  44. metadata +17 -16
  45. data/.rubocop_todo.yml +0 -116
  46. data/lib/gruff/scene.rb +0 -200
  47. 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 draw_graph
118
- # Check to see if more than one datapoint was given. NaN can result otherwise.
119
- @x_increment = (@x_spread > 1) ? (@graph_width / (@x_spread - 1).to_f) : @graph_width
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 setup_data
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
- if @x_axis_increment.nil?
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..@marker_x_count).each do |index|
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
- x = @graph_left + @graph_width - index.to_f * increment_x_scaled
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(@x_increment.to_s) + BigDecimal(@minimum_x_value.to_s)
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.to_f, increment_x_scaled, @graph_left)
184
+ x_offset = get_x_coord(index, increment_x_scaled, @graph_left)
209
185
 
210
- label = x_axis_label(marker_label, @x_increment)
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) #:nodoc:
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
@@ -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
- # Value to avoid completely overwriting the coordinate axis
70
- AXIS_MARGIN = 0.5
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.to_f
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
- store.norm_data.each_with_index do |data_row, row_index|
86
- data_row.points.each_with_index do |data_point, point_index|
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
- left_x, right_x = conversion.get_top_bottom_scaled(data_point).sort
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
- rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: data_row.color)
95
- rect_renderer.render(left_x + AXIS_MARGIN, left_y, right_x + AXIS_MARGIN, right_y)
96
-
97
- # Calculate center based on bar_width and current row
98
- label_center = left_y + bars_width / 2
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
- # Subtract half a bar width to center left if requested
101
- draw_label(label_center, point_index)
102
- if @show_labels_for_bar_values
103
- bar_value_label = Gruff::BarValueLabel::SideBar.new([left_x, left_y, right_x, right_y], store.data[row_index].points[point_index])
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.to_f / number_of_lines)
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
- @has_left_labels = true
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.to_f
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
- stack_bar_value_label = Gruff::BarValueLabel::StackedBar.new
80
-
81
- store.norm_data.each_with_index do |data_row, row_index|
82
- data_row.points.each_with_index do |data_point, point_index|
83
- ## using the original calculations from the stacked bar chart to get the difference between
84
- ## part of the bart chart we wish to stack.
85
- temp1 = @graph_left + (@graph_width -
86
- data_point * @graph_width -
87
- height[point_index]) + 1
88
- temp2 = @graph_left + @graph_width - height[point_index] - 1
89
- difference = temp2 - temp1
90
-
91
- left_x = length[point_index]
92
- left_y = @graph_top + (bar_width * point_index) + padding
93
- right_x = left_x + difference - @segment_spacing
94
- right_y = left_y + bar_width * @bar_spacing
95
- length[point_index] += difference
96
- height[point_index] += (data_point * @graph_width - 2)
97
-
98
- bar_value_label = Gruff::BarValueLabel::SideBar.new([left_x, left_y, right_x, right_y], store.data[row_index].points[point_index])
99
- stack_bar_value_label.add(bar_value_label, point_index)
100
-
101
- # if a data point is 0 it can result in weird really thing lines
102
- # that shouldn't even be there being drawn on top of the existing
103
- # bar - this is bad
104
- if data_point != 0
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
- if @show_labels_for_bar_values
117
- stack_bar_value_label.prepare_rendering(@label_formatting, bar_width) do |x, y, text|
118
- draw_value_label(x, y, text)
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
- r_offset = 50 # The distance out from the center of the pie to get point
72
- x_offset = center_x # The label points need to be tweaked slightly
73
- y_offset = center_y + 0 # This one doesn't though
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(1.0, 1.0, x, y, amount, Magick::CenterGravity)
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 * Math::PI / 180.0
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 * Math::PI / 180.0
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
@@ -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).to_f
36
+ x_increment = @graph_width / (column_count - 1)
30
37
 
31
38
  height = Array.new(column_count, 0)
32
39
 
33
- data_points = nil
40
+ prev_data_points = nil
34
41
  store.norm_data.each do |data_row|
35
- prev_data_points = data_points
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