1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 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 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 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
require File.dirname(__FILE__) + '/base'
# Experimental!!! See also the Net graph.
#
# Submitted by Kevin Clark http://glu.ttono.us/
class Gruff::Spider < Gruff::Base
# Hide all text
attr_reader :hide_text
attr_accessor :hide_axes
attr_reader :transparent_background
attr_accessor :rotation
def transparent_background=(value)
@transparent_background = value
@base_image = render_transparent_background if value
end
def hide_text=(value)
@hide_title = @hide_text = value
end
def initialize(max_value, target_width = 800)
super(target_width)
@max_value = max_value
@hide_legend = true;
@rotation = 0
end
def draw
@hide_line_markers = true
super
return unless @has_data
# Setup basic positioning
diameter = @graph_height
radius = @graph_height / 2.0
top_x = @graph_left + (@graph_width - diameter) / 2.0
center_x = @graph_left + (@graph_width / 2.0)
center_y = @graph_top + (@graph_height / 2.0) - 25 # Move graph up a bit
@unit_length = radius / @max_value
total_sum = sums_for_spider
prev_degrees = 0.0
additive_angle = (2 * Math::PI)/ @data.size
current_angle = rotation * Math::PI / 180.0
# Draw axes
draw_axes(center_x, center_y, radius, additive_angle) unless hide_axes
# Draw polygon
draw_polygon(center_x, center_y, additive_angle)
@d.draw(@base_image)
end
private
def normalize_points(value)
value * @unit_length
end
def draw_label(center_x, center_y, angle, radius, amount)
r_offset = 50 # The distance out from the center of the pie to get point
x_offset = center_x # The label points need to be tweaked slightly
y_offset = center_y + 0 # This one doesn't though
x = x_offset + ((radius + r_offset) * Math.cos(angle))
y = y_offset + ((radius + r_offset) * Math.sin(angle))
# Draw label
@d.fill = @marker_color
@d.font = @font if @font
@d.pointsize = scale_fontsize(legend_font_size)
@d.stroke = 'transparent'
@d.font_weight = BoldWeight
@d.gravity = CenterGravity
@d.annotate_scaled( @base_image,
0, 0,
x, y,
amount, @scale)
end
def draw_axes(center_x, center_y, radius, additive_angle, line_color = nil)
return if hide_axes
current_angle = rotation * Math::PI / 180.0
@data.each do |data_row|
@d.stroke(line_color || data_row[DATA_COLOR_INDEX])
@d.stroke_width 5.0
x_offset = radius * Math.cos(current_angle)
y_offset = radius * Math.sin(current_angle)
@d.line(center_x, center_y,
center_x + x_offset,
center_y + y_offset)
draw_label(center_x, center_y, current_angle, radius, data_row[DATA_LABEL_INDEX].to_s) unless hide_text
current_angle += additive_angle
end
end
def draw_polygon(center_x, center_y, additive_angle, color = nil)
points = []
current_angle = rotation * Math::PI / 180.0
@data.each do |data_row|
points << center_x + normalize_points(data_row[DATA_VALUES_INDEX].first) * Math.cos(current_angle)
points << center_y + normalize_points(data_row[DATA_VALUES_INDEX].first) * Math.sin(current_angle)
current_angle += additive_angle
end
@d.stroke_width 1.0
@d.stroke(color || @marker_color)
@d.fill(color || @marker_color)
@d.fill_opacity 0.4
@d.polygon(*points)
end
def sums_for_spider
@data.inject(0.0) {|sum, data_row| sum += data_row[DATA_VALUES_INDEX].first}
end
end
|