
#==============================================================================#
# $Id: chart.rb,v 1.2 2004/01/23 00:38:04 yuya Exp $
# $Source: /cvsroot/gruby/gruby/lib/grb/chart/pie_3d/chart.rb,v $
#==============================================================================#

require 'grb/chart/pie_base/chart'
require 'grb/math_ex'

#==============================================================================#

module GRb

  module Chart

    class Pie3DChart < PieChartBase

      def initialize(property)
        super(property)
      end

      # FIXME: using GRb::Image
      def draw_sector(image, cx, cy, rx, ry, rz, begin_r, end_r, line_color, fill)
        fill_color = fill.set(image)

        angle_start  = begin_r % 360
        angle_end    = end_r   % 360
        angle_median = (angle_end - angle_start) / 2 + angle_start

        angle_side_start  = (angle_start <  90 ?  90 : angle_start)
        angle_side_end    = (angle_end   > 270 ? 270 : angle_end  )
        angle_side_median = (angle_side_end - angle_side_start) / 2 + angle_side_start

        begin_x = cx + MathEx.cos(angle_start - 90)       * (rx - 1)
        begin_y = cy + MathEx.sin(angle_start - 90)       * (ry - 1)
        end_x   = cx + MathEx.cos(angle_end - 90)         * (rx - 1)
        end_y   = cy + MathEx.sin(angle_end - 90)         * (ry - 1)
        fill_x  = cx + MathEx.cos(angle_median - 90)      * (rx - 3)
        fill_y  = cy + MathEx.sin(angle_median - 90)      * (ry - 3)
        side_x  = cx + MathEx.cos(angle_side_median - 90) * (rx - 3)
        side_y  = cy + MathEx.sin(angle_side_median - 90) * (ry - 3)

        image.image.filledArc(cx, cy, rx * 2, ry * 2, (angle_start + 270) % 360, (angle_end + 270) % 360, fill_color, GD::Arc)
        image.image.filledArc(cx, cy, rx * 2, ry * 2, (angle_start + 270) % 360, (angle_end + 270) % 360, line_color, GD::Arc | GD::NoFill | GD::Edged)

        if angle_start > 90 && angle_start < 270
          image.image.line(begin_x, begin_y, begin_x, begin_y + rz, line_color)
        end

        if angle_end > 90 && angle_end < 270
          image.image.line(end_x, end_y, end_x, end_y + rz, line_color)
        end

        if (angle_start > 90 && angle_start < 270) || (angle_end > 90 && angle_end < 270) || (angle_start < 90 && angle_end > 270)
          shade_color = (fill - @property.shade).set(image)
          image.image.fillToBorder(side_x, side_y + rz, line_color, shade_color)
        end
      end
      protected :draw_sector

      # FIXME: using GRb::Image
      def draw(image, box)
        dx, dy, rx, ry, cx, cy = self.calculate_box(box, @property.stretch)
        rz    = @property.height
        total = self.calculate_total(@values)
        ratio = self.calculate_ratio(@values, total)

        line = @property.edge.color.set(image)

        image.image.arc(cx, cy,      rx * 2, ry * 0.8, 0, 360, line)
        image.image.arc(cx, cy + rz, rx * 2, ry * 0.8, 0, 180, line)
        image.image.line(cx - rx, cy, cx - rx, cy + rz, line)
        image.image.line(cx + rx, cy, cx + rx, cy + rz, line)

        ratio.inject(0) { |current, item|
          angle_start  = current.ceil
          angle_end    = (current + item.ratio).ceil
          angle_median = (angle_end - angle_start) / 2 + angle_start

          self.draw_sector(image, cx, cy, rx, ry * 0.4, rz, angle_start, angle_end, line, item.value.color)
          self.draw_label(image, cx, cy, rx, ry * 0.4, angle_median, item.value.name)

          current + item.ratio
        }
      end

    end # Pie3DChart

  end # Graph

end # GRb

#==============================================================================#
#==============================================================================#
