Class: Squid::Plotter

Inherits:
Object
  • Object
show all
Defined in:
lib/squid/plotter.rb

Overview

A Plotter wraps a Prawn::Document object in order to provide new methods like ‘gridline` or `ticks` used by Squid::Graph to plot graph elements.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(pdf, bottom:) ⇒ Plotter

Returns a new instance of Plotter.

Parameters:

  • a (Prawn::Document)

    PDF document to wrap in a Plotter instance.



10
11
12
13
# File 'lib/squid/plotter.rb', line 10

def initialize(pdf, bottom:)
  @pdf = pdf
  @bottom = bottom
end

Instance Attribute Details

#paddingsObject

Returns the value of attribute paddings.



8
9
10
# File 'lib/squid/plotter.rb', line 8

def paddings
  @paddings
end

Instance Method Details

#axis_labels(labels) ⇒ Object



56
57
58
59
60
61
62
63
# File 'lib/squid/plotter.rb', line 56

def axis_labels(labels)
  labels.each do |label|
    x = (label.align == :right) ? 0 : @pdf.bounds.right - label.width
    y = label.y + @bottom + text_options[:height] / 2
    options = text_options.merge width: label.width, at: [x, y]
    @pdf.text_box label.label, options.merge(align: label.align)
  end
end

#box(x: 0, y: @pdf.cursor, w: @pdf.bounds.width, h:, border: false) ⇒ Object

Draws a bounding box of the given height, rendering the block inside it.



16
17
18
19
20
21
# File 'lib/squid/plotter.rb', line 16

def box(x: 0, y: @pdf.cursor, w: @pdf.bounds.width, h:, border: false)
  @pdf.bounding_box [x, y], width: w, height: h do
    @pdf.stroke_bounds if border
    yield
  end
end

#categories(labels, every:, ticks:) ⇒ Object



65
66
67
68
69
70
71
72
73
74
# File 'lib/squid/plotter.rb', line 65

def categories(labels, every:, ticks:)
  labels.each.with_index do |label, index|
    w = width / labels.count.to_f
    x = left + w * (index)
    padding = 2
    options = category_options.merge(width: every*w-2*padding, at: [x+padding-w*(every/2.0-0.5), @bottom])
    @pdf.text_box label, **options if (index % every).zero?
    @pdf.stroke_vertical_line @bottom, @bottom - 2, at: x + w/2 if ticks
  end
end

#columns(series, options = {}) ⇒ Object



103
104
105
106
107
108
109
# File 'lib/squid/plotter.rb', line 103

def columns(series, options = {})
  items(series, **options.merge(fill: true, count: series.size)) do |point, w, i, padding|
    item_w = (w - 2 * padding)/ series.size
    x, y = point.index*w + padding + left + i*item_w, point.y + @bottom
    @pdf.fill_rectangle [x, y], item_w, point.height
  end
end

#horizontal_line(y, options = {}) ⇒ Object

Draws a horizontal line.



45
46
47
48
49
50
# File 'lib/squid/plotter.rb', line 45

def horizontal_line(y, options = {})
  with options do
    at = y + @bottom
    @pdf.stroke_horizontal_line left, @pdf.bounds.right - right, at: at
  end
end

#legend(labels, height:, right: 0, colors: []) ⇒ Object

Draws the graph legend with the given labels.

Parameters:

  • The (Array<LegendItem>)

    labels to write as part of the legend.



25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/squid/plotter.rb', line 25

def legend(labels, height:, right: 0, colors: [])
  left = @pdf.bounds.width/2
  box(x: left, y: @pdf.bounds.top, w: left, h: height) do
    x = @pdf.bounds.right - right
    options = {size: 7, height: @pdf.bounds.height, valign: :center}
    labels.each.with_index do |label, i|
      index = labels.size - 1 - i
      series_color = colors.fetch index, series_colors(index)
      color = Array.wrap(series_color).first
      x = legend_item label, x, color, options
    end
  end
end

#lines(series, options = {}) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/squid/plotter.rb', line 83

def lines(series, options = {})
  x, y = nil, nil
  line_widths = options.delete(:line_widths) { [] }
  items(series, **options) do |point, w, i, padding|
    prev_x, prev_y = x, y
    x, y = (point.index + 0.5)*w + left, point.y + @bottom
    line_width = line_widths.fetch i, 3
    with line_width: line_width, cap_style: :round do
      @pdf.line [prev_x, prev_y], [x,y] unless point.index.zero? || prev_y.nil? || prev_x > x
    end
  end
end

#points(series, options = {}) ⇒ Object



76
77
78
79
80
81
# File 'lib/squid/plotter.rb', line 76

def points(series, options = {})
  items(series, **options) do |point, w, i, padding|
    x, y = (point.index + 0.5)*w + left, point.y + @bottom
    @pdf.fill_circle [x, y], 5
  end
end

#series_colors(index) ⇒ Object



39
40
41
42
# File 'lib/squid/plotter.rb', line 39

def series_colors(index)
  default_colors = %w(2e578c 5d9648 e7a13d bc2d30 6f3d79 7d807f)
  default_colors.fetch(index % default_colors.size)
end

#stacks(series, options = {}) ⇒ Object



96
97
98
99
100
101
# File 'lib/squid/plotter.rb', line 96

def stacks(series, options = {})
  items(series, **options.merge(fill: true)) do |point, w, i, padding|
    x, y = point.index*w + padding + left, point.y + @bottom
    @pdf.fill_rectangle [x, y], w - 2*padding, point.height
  end
end

#width_of(label) ⇒ Object



52
53
54
# File 'lib/squid/plotter.rb', line 52

def width_of(label)
  @pdf.width_of(label, size: 8).ceil
end