class Charma::Chart
Public Class Methods
new(opts)
click to toggle source
# File lib/charma/chart.rb, line 5 def initialize(opts) @opts = opts end
Public Instance Methods
abs_x_positoin(v, rc, xrange)
click to toggle source
# File lib/charma/chart.rb, line 57 def abs_x_positoin(v, rc, xrange) rx, min, max = [ v, *xrange ].map{ |e| scale_value(:x, e) } (rx-min) * rc.w / (max-min) + rc.x end
abs_y_positoin(v, rc, yrange)
click to toggle source
# File lib/charma/chart.rb, line 62 def abs_y_positoin(v, rc, yrange) ry, min, max = [ v, *yrange ].map{ |e| scale_value(:y, e) } (ry-min) * rc.h / (max-min) + rc.bottom end
bottom_legend?()
click to toggle source
# File lib/charma/chart.rb, line 21 def bottom_legend? has_legend? end
colors(n)
click to toggle source
# File lib/charma/chart.rb, line 87 def colors(n) case n when 0, 1 return ["666666"] else f = ->(t0){ t = t0 % 3 v = case t when 0..1 then t when 1..2 then 2-t else 0 end "%02x" % (v**0.5*255).round } Array.new(n){ |i| t = i*3.0/n+0.5 [f[t],f[t+1],f[t+2]].join } end end
draw_samesize_texts( pdf, rects, texts, opts={} )
click to toggle source
# File lib/charma/chart.rb, line 108 def draw_samesize_texts( pdf, rects, texts, opts={} ) pdf.save_graphics_state do size = texts.zip(rects).map{ |txt,rc| w = pdf.width_of(txt, size:1) h = pdf.height_of(txt, size:1) [rc.w.to_f/w ,rc.h.to_f/h].min }.min texts.zip(rects).each do |txt, rc| draw_text( pdf, rc, txt, size:size, **opts ) end end end
draw_text( pdf, rect, text, opts = {} )
click to toggle source
# File lib/charma/chart.rb, line 76 def draw_text( pdf, rect, text, opts = {} ) pdf.text_box( text, at:rect.topleft, width:rect.w, height:rect.h, align: (opts[:align] || :center), valign: (opts[:valign] || :center), size: (opts[:size] || rect.h), overflow: :shrink_to_fit ) end
fill_rect( pdf, rect, col )
click to toggle source
# File lib/charma/chart.rb, line 67 def fill_rect( pdf, rect, col ) pdf.save_graphics_state do pdf.fill{ pdf.fill_color( col ) pdf.rectangle( [rect.x, rect.y], rect.w, rect.h ) } end end
has_legend?()
click to toggle source
# File lib/charma/chart.rb, line 25 def has_legend? @opts[:series].any?{ |s| ! s[:name].nil? } end
render_legend( pdf, rect )
click to toggle source
# File lib/charma/chart.rb, line 131 def render_legend( pdf, rect ) names = @opts[:series].map.with_index{ |e,ix| e[:name] || "series #{ix}" } rects = rect.hsplit( *([1]*names.size) ) name_areas, bar_areas = rects.map{ |rc| rc.hsplit(1,1) }.transpose draw_samesize_texts( pdf, name_areas, names, align: :right ) cols = colors(names.size) bar_areas.zip(cols).each do |rc0, col| _, rc1, = rc0.vsplit(1,1,1) rc, = rc1.hsplit(2,1) fill_rect( pdf, rc, col ) end end
render_rottext( pdf, rect, text )
click to toggle source
# File lib/charma/chart.rb, line 121 def render_rottext( pdf, rect, text ) pdf.rotate(90, origin: rect.center) do rc = rect.rot90 w = pdf.width_of(text, size:1) h = pdf.height_of(text, size:1) size = [rc.w.to_f/w ,rc.h.to_f/h].min pdf.draw_text( text, size:size, at:rc.bottomleft ) end end
render_y_grid(pdf, area, yrange, yvalues)
click to toggle source
# File lib/charma/chart.rb, line 170 def render_y_grid(pdf, area, yrange, yvalues) pdf.save_graphics_state do pdf.line_width = 0.5 yvalues.each do |v| if v==0 pdf.stroke_color "000000" pdf.undash else pdf.stroke_color "888888" pdf.dash([2,2]) end abs_y = abs_y_positoin( v, area, yrange ) pdf.stroke_horizontal_line area.x, area.right, at: abs_y end end end
render_yticks(pdf, area, yrange, yvalues)
click to toggle source
# File lib/charma/chart.rb, line 160 def render_yticks(pdf, area, yrange, yvalues) h = (area.h / yvalues.size) * 0.7 rects = yvalues.map{ |v| abs_y = abs_y_positoin( v, area, yrange ) Rect.new( area.x, abs_y + h/2, area.w*0.9, h ) } svalues = yvalues.map{ |v| "%g " % v } draw_samesize_texts( pdf, rects, svalues, align: :right ) end
scale_type(sym)
click to toggle source
# File lib/charma/chart.rb, line 29 def scale_type(sym) key = :"#{sym}_scale" case @opts[key] when :log10 :log10 else :linear end end
scale_value(axis, v)
click to toggle source
# File lib/charma/chart.rb, line 39 def scale_value(axis, v) case scale_type(axis) when :log10 Math.log10(v) else v end end
stroke_rect( pdf, rect )
click to toggle source
# File lib/charma/chart.rb, line 9 def stroke_rect( pdf, rect ) pdf.stroke{ pdf.rectangle( [rect.x, rect.y], rect.w, rect.h ) } end
tick_unit(v)
click to toggle source
# File lib/charma/chart.rb, line 144 def tick_unit(v) base = (10**Math.log10(v).round).to_f man = v/base return 0.5*base if man<0.6 return base if man<1.2 base*2 end
tick_values(axis, range)
click to toggle source
# File lib/charma/chart.rb, line 152 def tick_values(axis, range) min, max = range.minmax.map{ |e| scale_value( axis, e ) } unit = tick_unit((max - min) * 0.1) i_low = (min / unit).ceil i_hi = (max / unit).floor (i_low..i_hi).map{ |i| unscale_value( axis, i*unit ) } end
unscale_value(axis, v)
click to toggle source
# File lib/charma/chart.rb, line 48 def unscale_value(axis, v) case scale_type(axis) when :log10 10.0**v else v end end
values(sym)
click to toggle source
# File lib/charma/chart.rb, line 15 def values(sym) @opts[:series].map{ |s| s[sym].map(&:to_f) } end