Added the Gruff library to the lib/ directory of the the rails folder, and the
[selectricity-live] / lib / gruff-0.2.8 / lib / gruff / pie.rb
diff --git a/lib/gruff-0.2.8/lib/gruff/pie.rb b/lib/gruff-0.2.8/lib/gruff/pie.rb
new file mode 100644 (file)
index 0000000..b143e70
--- /dev/null
@@ -0,0 +1,108 @@
+
+require File.dirname(__FILE__) + '/base'
+
+class Gruff::Pie < Gruff::Base
+
+  TEXT_OFFSET_PERCENTAGE = 0.15
+
+  # Can be used to make the pie start cutting slices at the top (-90.0)
+  # or at another angle. Default is 0.0, which starts at 3 o'clock.
+  attr_accessor :zero_degree
+  
+  def initialize_ivars
+    super
+    @zero_degree = 0.0
+  end
+
+  def draw
+    @hide_line_markers = true
+    
+    super
+
+    return unless @has_data
+
+    diameter = @graph_height
+    radius = ([@graph_width, @graph_height].min / 2.0) * 0.8
+    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) - 10 # Move graph up a bit
+    total_sum = sums_for_pie()
+    prev_degrees = @zero_degree
+
+    # Use full data since we can easily calculate percentages
+    @data.sort{ |a, b| a[DATA_VALUES_INDEX][0] <=> b[DATA_VALUES_INDEX][0] }.each do |data_row|
+      if data_row[DATA_VALUES_INDEX][0] > 0
+        @d = @d.stroke data_row[DATA_COLOR_INDEX]
+        @d = @d.fill 'transparent'
+        @d.stroke_width(radius) # stroke width should be equal to radius. we'll draw centered on (radius / 2)
+
+        current_degrees = (data_row[DATA_VALUES_INDEX][0] / total_sum) * 360.0 
+
+        # ellipse will draw the the stroke centered on the first two parameters offset by the second two.
+        # therefore, in order to draw a circle of the proper diameter we must center the stroke at
+        # half the radius for both x and y
+        @d = @d.ellipse(center_x, center_y, 
+                  radius / 2.0, radius / 2.0,
+                  prev_degrees, prev_degrees + current_degrees + 0.5) # <= +0.5 'fudge factor' gets rid of the ugly gaps
+                  
+        half_angle = prev_degrees + ((prev_degrees + current_degrees) - prev_degrees) / 2
+
+        # End the string with %% to escape the single %.
+        # RMagick must use sprintf with the string and % has special significance.
+        label_string = ((data_row[DATA_VALUES_INDEX][0] / total_sum) * 100.0).round.to_s + '%%'
+        @d = draw_label(center_x,center_y, 
+                    half_angle, radius + (radius * TEXT_OFFSET_PERCENTAGE), 
+                    label_string)
+      
+        prev_degrees += current_degrees
+      end
+    end
+
+    # TODO debug a circle where the text is drawn...
+    
+    @d.draw(@base_image)
+  end
+
+private
+
+  ##
+  # Labels are drawn around a slightly wider ellipse to give room for 
+  # labels on the left and right.
+  def draw_label(center_x, center_y, angle, radius, amount)
+    # TODO Don't use so many hard-coded numbers
+    r_offset = 20.0      # The distance out from the center of the pie to get point
+    x_offset = center_x # + 15.0 # The label points need to be tweaked slightly
+    y_offset = center_y  # This one doesn't though
+    radius_offset = (radius + r_offset)
+    ellipse_factor = radius_offset * 0.15
+    x = x_offset + ((radius_offset + ellipse_factor) * Math.cos(angle.deg2rad))
+    y = y_offset + (radius_offset * Math.sin(angle.deg2rad))
+    
+    # Draw label
+    @d.fill = @font_color
+    @d.font = @font if @font
+    @d.pointsize = scale_fontsize(@marker_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 sums_for_pie
+    total_sum = 0.0
+    @data.collect {|data_row| total_sum += data_row[DATA_VALUES_INDEX][0] }
+    total_sum
+  end
+
+end
+
+
+class Float
+  # Used for degree => radian conversions
+  def deg2rad
+    self * (Math::PI/180.0)
+  end
+end

Benjamin Mako Hill || Want to submit a patch?