Added the Gruff library to the lib/ directory of the the rails folder, and the
[selectricity] / lib / gruff-0.2.8 / lib / gruff / spider.rb
1
2 require File.dirname(__FILE__) + '/base'
3
4 # Experimental!!! See also the Net graph.
5 #
6 # Submitted by Kevin Clark http://glu.ttono.us/
7 class Gruff::Spider < Gruff::Base
8   
9   # Hide all text
10   attr_reader :hide_text
11   attr_accessor :hide_axes
12   attr_reader :transparent_background
13   
14   def transparent_background=(value)
15     @transparent_background = value
16     @base_image = render_transparent_background if value
17   end
18
19   def hide_text=(value)
20     @hide_title = @hide_text = value
21   end
22   
23   def initialize(max_value, target_width = 800)
24     super(target_width)
25     @max_value = max_value
26     @hide_legend = true;
27   end
28   
29   def draw
30     @hide_line_markers = true
31     
32     super
33
34     return unless @has_data
35
36     # Setup basic positioning
37     diameter = @graph_height
38     radius = @graph_height / 2.0
39     top_x = @graph_left + (@graph_width - diameter) / 2.0
40     center_x = @graph_left + (@graph_width / 2.0)
41     center_y = @graph_top + (@graph_height / 2.0) - 25 # Move graph up a bit
42     
43     @unit_length = radius / @max_value
44     
45         
46     total_sum = sums_for_spider
47     prev_degrees = 0.0
48     additive_angle = (2 * Math::PI)/ @data.size
49     
50     current_angle = 0.0
51
52     # Draw axes
53     draw_axes(center_x, center_y, radius, additive_angle) unless hide_axes    
54     
55     # Draw polygon
56     draw_polygon(center_x, center_y, additive_angle)
57     
58      
59     @d.draw(@base_image)
60   end
61
62 private
63   
64   def normalize_points(value)
65     value * @unit_length
66   end
67   
68   def draw_label(center_x, center_y, angle, radius, amount)
69     r_offset = 50      # The distance out from the center of the pie to get point
70     x_offset = center_x      # The label points need to be tweaked slightly
71     y_offset = center_y + 0  # This one doesn't though
72     x = x_offset + ((radius + r_offset) * Math.cos(angle))
73     y = y_offset + ((radius + r_offset) * Math.sin(angle))
74     
75     # Draw label
76     @d.fill = @marker_color
77     @d.font = @font if @font
78     @d.pointsize = scale_fontsize(legend_font_size)
79     @d.stroke = 'transparent'
80     @d.font_weight = BoldWeight
81     @d.gravity = CenterGravity
82     @d.annotate_scaled( @base_image, 
83                       0, 0,
84                       x, y, 
85                       amount, @scale)
86   end
87   
88   def draw_axes(center_x, center_y, radius, additive_angle, line_color = nil)
89     return if hide_axes
90     
91     current_angle = 0.0
92     
93     @data.each do |data_row|
94       @d.stroke(line_color || data_row[DATA_COLOR_INDEX])
95       @d.stroke_width 5.0
96     
97       x_offset = radius * Math.cos(current_angle)
98       y_offset = radius * Math.sin(current_angle)
99
100       @d.line(center_x, center_y,
101               center_x + x_offset,
102               center_y + y_offset)
103             
104       draw_label(center_x, center_y, current_angle, radius, data_row[0].to_s) unless hide_text
105             
106       current_angle += additive_angle
107     end
108   end
109   
110   def draw_polygon(center_x, center_y, additive_angle, color = nil)
111     points = []
112     current_angle = 0.0
113     @data.each do |data_row|
114       points << center_x + normalize_points(data_row[1][0]) * Math.cos(current_angle)
115       points << center_y + normalize_points(data_row[1][0]) * Math.sin(current_angle)
116       current_angle += additive_angle
117     end
118     
119     @d.stroke_width 1.0
120     @d.stroke(color || @marker_color)
121     @d.fill(color || @marker_color)
122     @d.fill_opacity 0.4
123     @d.polygon(*points)
124   end
125   
126   def sums_for_spider
127     @data.inject(0.0) {|sum, data_row| sum += data_row[1][0]}
128   end
129
130 end

Benjamin Mako Hill || Want to submit a patch?