Class: Rubyplot::Bar

Inherits:
Artist show all
Defined in:
lib/rubyplot/scripting/bar/data_conversion.rb,
lib/rubyplot/scripting/bar/bar.rb

Overview

This class perfoms the y coordinats conversion for the bar class.

There are three cases:

 1. Bars all go from zero in +ve direction
 2. Bars all go from zero to -ve direction
 3. Bars can either go from zero to +ve or from zero to -ve

Direct Known Subclasses

StackedBar

Constant Summary

Constants inherited from Artist

Artist::DATA_COLOR_INDEX, Artist::DATA_LABEL_INDEX, Artist::DATA_VALUES_INDEX, Artist::DATA_VALUES_X_INDEX, Artist::DEFAULT_MARGIN, Artist::DEFAULT_TARGET_WIDTH, Artist::LABEL_MARGIN, Artist::LEGEND_MARGIN, Artist::THOUSAND_SEPARATOR

Instance Attribute Summary collapse

Attributes inherited from Artist

#base_image, #font, #font_color, #has_left_labels, #hide_legend, #hide_line_numbers, #labels, #legend_font_size, #legend_margin, #marker_color, #marker_count, #marker_shadow_color, #maximum_value, #minimum_value, #title, #title_margin, #x_axis_label, #y_axis_label

Instance Method Summary collapse

Methods inherited from Artist

#artist_draw, #calculate_caps_height, #calculate_spread, #calculate_width, #center, #clip_value_if_greater_than, #construct_colors_array, #data, #draw_axis_labels, #draw_label, #draw_legend, #draw_line_markers!, #draw_title, #get_colors_array, #initialize_variables, #normalize, #render_gradiated_background, #reset_themes, #scale, #scale_fontsize, #set_colors_array, #setup_drawing, #setup_graph_measurements, #significant, #sort_norm_data, #sum, #theme=, #write

Constructor Details

#initialize(*args) ⇒ Bar

Returns a new instance of Bar


5
6
7
8
# File 'lib/rubyplot/scripting/bar/bar.rb', line 5

def initialize(*args)
  super
  @geometry = Rubyplot::BarGeometry.new
end

Instance Attribute Details

#bar_spacingObject

Spacing factor applied between bars


3
4
5
# File 'lib/rubyplot/scripting/bar/bar.rb', line 3

def bar_spacing
  @bar_spacing
end

#graph_height=(value) ⇒ Object (writeonly)

Sets the attribute graph_height

Parameters:

  • value

    the value to set the attribute graph_height to.


14
15
16
# File 'lib/rubyplot/scripting/bar/data_conversion.rb', line 14

def graph_height=(value)
  @graph_height = value
end

#graph_top=(value) ⇒ Object (writeonly)

Sets the attribute graph_top

Parameters:

  • value

    the value to set the attribute graph_top to.


13
14
15
# File 'lib/rubyplot/scripting/bar/data_conversion.rb', line 13

def graph_top=(value)
  @graph_top = value
end

#minimum_value=(value) ⇒ Object (writeonly)

Sets the attribute minimum_value

Parameters:

  • value

    the value to set the attribute minimum_value to.


15
16
17
# File 'lib/rubyplot/scripting/bar/data_conversion.rb', line 15

def minimum_value=(value)
  @minimum_value = value
end

#mode=(value) ⇒ Object (writeonly)

Sets the attribute mode

Parameters:

  • value

    the value to set the attribute mode to.


11
12
13
# File 'lib/rubyplot/scripting/bar/data_conversion.rb', line 11

def mode=(value)
  @mode = value
end

#spread=(value) ⇒ Object (writeonly)

Sets the attribute spread

Parameters:

  • value

    the value to set the attribute spread to.


16
17
18
# File 'lib/rubyplot/scripting/bar/data_conversion.rb', line 16

def spread=(value)
  @spread = value
end

#zero=(value) ⇒ Object (writeonly)

Sets the attribute zero

Parameters:

  • value

    the value to set the attribute zero to.


12
13
14
# File 'lib/rubyplot/scripting/bar/data_conversion.rb', line 12

def zero=(value)
  @zero = value
end

Instance Method Details

#drawObject


10
11
12
13
14
15
16
17
18
19
20
# File 'lib/rubyplot/scripting/bar/bar.rb', line 10

def draw
  # Labels will be centered over the left of the bar if
  # there are more labels than columns. This is basically the same
  # as where it would be for a line graph.
  @geometry.center_labels_over_point = (@labels.keys.length > @geometry.column_count)

  super
  return unless @geometry.has_data

  draw_bars
end

#draw_barsObject


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
# File 'lib/rubyplot/scripting/bar/bar.rb', line 33

def draw_bars
  # Setup spacing.
  #
  # Columns sit side-by-side.
  @bar_spacing ||= @geometry.spacing_factor # space between the bars
  @bar_width = @graph_width / (@geometry.column_count * @data.length).to_f
  padding = (@bar_width * (1 - @bar_spacing)) / 2

  @d = @d.stroke_opacity 0.0

  # Setup the BarConversion Object
  @graph_height = @graph_height
  @graph_top = @graph_top

  # Set up the right mode [1,2,3] see BarConversion for further explanation
  if @geometry.minimum_value >= 0
    # all bars go from zero to positiv
    @mode = :positive
  else
    # all bars go from 0 to negativ
    if @geometry.maximum_value <= 0
      @mode = :negative
    else
      # bars either go from zero to negativ or to positive
      @mode = :both
      @spread = @spread
      @minimum_value = @geometry.minimum_value
      @zero = -@geometry.minimum_value / @spread
    end
  end

  # iterate over all normalised data
  @geometry.norm_data.each_with_index do |data_row, row_index|
    data_row[DATA_VALUES_INDEX].each_with_index do |data_point, point_index|
      @d = @d.fill @plot_colors[row_index]
      # Use incremented x and scaled y
      # x
      left_x = @graph_left + (@bar_width * (row_index + point_index + ((@data.length - 1) * point_index))) + padding
      right_x = left_x + @bar_width * @bar_spacing
      # y
      conv = []
      get_left_y_right_y_scaled(data_point, conv)

      # create new bar
      @d = @d.rectangle(left_x, conv[0], right_x, conv[1])

      # Calculate center based on bar_width and current row
      label_center = @graph_left +
                     (@data.length * @bar_width * point_index) +
                     (@data.length * @bar_width / 2.0)

      # Subtract half a bar width to center left if requested
      draw_label(label_center - (@geometry.center_labels_over_point ? @bar_width / 2.0 : 0.0), point_index)
      if @geometry.show_labels_for_bar_values
        val = (@geometry.label_formatting || '%.2f') % @geometry.norm_data[row_index][3][point_index]
        draw_value_label(left_x + (right_x - left_x) / 2, conv[0] - 30, val.commify, true)
      end
    end
  end

  # Draw the last label if requested
  draw_label(@graph_right, @geometry.column_count) if @geometry.center_labels_over_point
  @d.draw(@base_image)
end

#get_left_y_right_y_scaled(data_point, result) ⇒ Object


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
# File 'lib/rubyplot/scripting/bar/data_conversion.rb', line 18

def get_left_y_right_y_scaled(data_point, result)
  case @mode
  when :positive then # Case one
    # minimum value >= 0 ( only positiv values ) -> all the bars go in the +ve direction
    result[0] = @graph_top + @graph_height * (1 - data_point) + 1
    result[1] = @graph_top + @graph_height - 1
  when :negative then # Case two
    # only negative values -> all the bars go in the -ve direction
    result[0] = @graph_top + 1
    result[1] = @graph_top + @graph_height * (1 - data_point) - 1
  when :both then # Case three
    # positive and negative values -> bars go in both the +ve and -ve direction
    val = data_point - @geometry.minimum_value / @spread
    if data_point >= @zero
      result[0] = @graph_top + @graph_height * (1 - (val - @zero)) + 1
      result[1] = @graph_top + @graph_height * (1 - @zero) - 1
    else
      result[0] = @graph_top + @graph_height * (1 - (val - @zero)) + 1
      result[1] = @graph_top + @graph_height * (1 - @zero) - 1
    end
  else
    result[0] = 0.0
    result[1] = 0.0
  end
end

#spacing_factor=(space_percent) ⇒ Object

Can be used to adjust the spaces between the bars. Accepts values between 0.00 and 1.00 where 0.00 means no spacing at all and 1 means that each bars' width is nearly 0 (so each bar is a simple line with no x dimension).

Default value is 0.9.

Raises:

  • (ArgumentError)

28
29
30
31
# File 'lib/rubyplot/scripting/bar/bar.rb', line 28

def spacing_factor=(space_percent)
  raise ArgumentError, 'geometry.spacing_factor must be between 0.00 and 1.00' unless (space_percent >= 0) && (space_percent <= 1)
  @geometry.spacing_factor = (1 - space_percent)
end