Location: PHPKode > projects > TVEz - Media Library > tvez-0.2.1/html/shared/Graph/PieChart.php
<?php

# -----------------------------------------------------------------------------
#
# Plots al simple pie chart
#
# -----------------------------------------------------------------------------
#
# Copyright (C) 2004 Christian Eheim
#
# This file is part of TVEz (tvez.sourceforge.net).
#
# TVEz is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# TVEz is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with TVEz; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# -----------------------------------------------------------------------------
#
# Created on 02/01/2004 by Christian Eheim (hide@address.com)
#
# LAST MODIFIED:
# $Date: 2004/02/03 00:02:17 $
# $Revision: 1.2 $
# $Author: eheim $
#
# -----------------------------------------------------------------------------

/*
-------------------------------------------------------------------------------
TODO:
- Percentage is not always exactly 100%
  and then the last slice does not line up with the 0 line
- More themes
  For a nice named color chart: http://wtv-zone.com/mechtild/chart/sandy.html
-------------------------------------------------------------------------------
*/


include("Graph.php");

class PieChart extends Graph {
	
	var $_themes = array(
		"default"     => array(
				array (
				182,286,258,354,386,278,411,230,302,254,149,242,190,266,295,72
				),
				array (
				184,288,260,356,388,280,413,232,304,256,151,244,192,268,297,74
				)
			),
		"pastel" => array(
				array (
				190,266,314,374,254,149,286,238,318,242,38,262,307,280,258,326
				),
				array (
				192,268,316,376,256,151,288,240,320,244,36,264,309,281,260,328
				)
			)
	);

    var $_theme;
	var $_pieBorder;
	var $_sliceBorder;
	var $_sorted;

	var $_legendType;

	# the poisition and size of the pie
	var $_xCenter;
	var $_yCenter;
	var $_diameter;
	var $_radius;
	var $_sum;

	function PieChart($width,$height,$title=null) {
		# Instantiate the base class
		$this->Graph($width,$height,$title);

		# Set the base class properties
		$this->set_legend_font(3);
		$this->set_legend_alignment("middle");
		$this->legend_show(true);
		$this->set_label_type("percent");
		$this->x_axis_show(false);
		$this->y_axis_show(false);
		$this->set_plot_bgcolor(false);
		
		$this->_theme		= "default";
		$this->_pieBorder	= false;
		$this->_sliceBorder	= false;
		$this->_legendType  = "value";
		$this->_sorted		= false;
		$this->_labelInside	= true;
	}
	# Sort the data 'up', 'down', or false
	function sort($sort) {
		$this->_sorted = $sort;	
	}
	function show_pieborder($bool) {
		$this->_pieBorder = $bool;	
	}
	function show_sliceborder($bool) {
		$this->_sliceBorder = $bool;	
	}
	function set_theme($theme) {
		$this->_theme = $theme;	
	}
	# Set the value shown in the legend. 'value', 'percent', false
	function set_legend_value($val) {
		$this->_legendType = $val;	
	}

	#
	# Generate the axes
	#
	function generate_axes() {
		;
	}
	#
	# Generate the legend items
	#
	function generate_legend() {
		if ($this->_sorted == "down")
			$this->sort_down();
		elseif ($this->_sorted == "up")
			$this->sort_up();
		$n = count($this->_themes[$this->_theme][0]);
		$i = 0;
		$colors = array_keys($this->_image->_rgb->_colorTable);
		$this->_sum = $this->sum();
		foreach ($this->_data as $label => $value) {
			#
			# Add this item to the legend
			#
			$text = $label;
			$percent = sprintf("%.1f",$value/$this->_sum*100);
			if ($this->_legendType == "value")
				$text .= " (".$value.")";
			elseif ($this->_legendType == "percent")
				$text .= " (".$percent."%)";
			$this->_legend->add(
				$text,
				$colors[$this->_themes{$this->_theme}[0][$i%$n]]
			);
			$i++;
		}
	}
	#
	# Draw the Pie
	#
	function create_graph() {

		list($min,$max) = $this->minmax();
		
		$this->compute();

		$black = $this->_image->_rgb->allocate_color("black");
		$colors = array_keys($this->_image->_rgb->_colorTable);
		$n = count($this->_themes[$this->_theme][0]);
		$start = 270;
		$i = 0;
		$count = count($this->_data);
		foreach ($this->_data as $label => $value) {
			# Allocate a color for this slice
			$color = $this->_image->_rgb->allocate_color($colors[$this->_themes{$this->_theme}[0][$i%$n]]);

			$percent = sprintf("%.1f",$value/$this->_sum*100);
			$end = (round($value/$this->_sum*360)+$start)%360;
			#
			# Fill the slice
			#
			# Hack for only one slice !!!
			if ($count==1) {
                ImageFilledArc(
                    $this->_image->_image,
                    $this->_xCenter, $this->_yCenter,
                    $this->_diameter, $height,
                    268, 270,
                    $color, IMG_ARC_PIE
                );
                $end -= 2;
			}
			ImageFilledArc(
				$this->_image->_image,
				$this->_xCenter, $this->_yCenter,
				$this->_diameter, $this->_diameter,
				$start, $end,
				$color, IMG_ARC_PIE
			);
			#
			# If the slice is big enough, write the percentage inside
			# let's assume 10 degrees
			#
			if ( $this->_showLabels && ($end-$start+360)%360 > 10 ) {
				if ($this->_labelType == "percent")
					$pt = new Text($percent."%",$this->_labelFont);
				else
					$pt = new Text("$value",$this->_labelFont);
				$tw = round($pt->get_width()/2);
				$th = round($pt->get_height()/2);
				$pt->set_color("black");
				list($dx,$dy) = $this->compute_label_pos(
					$start,$end);
				$pt->set_pos(
					$this->_xCenter+$dx-$tw,
					$this->_yCenter+$dy-$th
				);
				$pt->draw($this->_image);
			}
			#
			# Draw the slice border
			#
			if ($this->_sliceBorder) {
				ImageFilledArc(
					$this->_image->_image,
					$this->_xCenter, $this->_yCenter,
					$this->_diameter+1, $this->_diameter+1,
					$start, $end,
					$black, IMG_ARC_EDGED|IMG_ARC_NOFILL
				);
			}
			#
			# Make the new starting angle the end of this one
			#
			$start = $end;
			$i++;
		}
		#
		# Draw a border around the entire pie
		#
		if ($this->_pieBorder) {
			ImageEllipse(
				$this->_image->_image,
				$this->_xCenter, $this->_yCenter,
				$this->_diameter+1, $this->_diameter+1,
				$black
			);
		}
	}
	#
	# Compute the center and size
	#
	function compute() {
		list(
			$this->_graphLeft, $this->_graphTop,
			$this->_graphWidth, $this->_graphHeight
		) = $this->_image->get_plot_area();

		#
		# Compute the center and the width of the pie
		#
		$minWidth = ($this->_graphWidth < $this->_graphHeight)
						? $this->_graphWidth : $this->_graphHeight;
		# Make it 90% of the available size
		if ($this->_showLabels && $this->_labelPos == 'outside')
			$this->_radius		= round( $minWidth/2 * 0.75 );
		else
			$this->_radius		= round( $minWidth/2 * 0.95 );
		$this->_diameter	= 2*$this->_radius;

		$this->_xCenter = $this->_graphLeft + round($this->_graphWidth/2);
		if (get_class($this) == "piechart3d")
			$this->_yCenter = $this->_graphTop + round(($this->_graphHeight-$this->_radius*0.2)/2);
		else
			$this->_yCenter = $this->_graphTop + round($this->_graphHeight/2);
	}
	#
	# Compute the position of the labels
	#
	function compute_label_pos($start,$end) {
		# Find the center angle
		$angle = ( round((($end-$start+360)%360)/2) + $start)%360;
		if ($this->_labelPos == 'outside')
			$h = 1.2 * $this->_radius;
		else
			$h = 0.8 * $this->_radius;
		# Which quadrant are we in
		# Remember 0deg is at 3 o'clock
		$alpha = deg2rad($angle%90);
		if ( $angle >= 270 && $angle < 360 ) {
			$x = round( $h * sin($alpha) );
			$y = -round( $h * cos($alpha) );
		}
		elseif ( $angle >= 0 && $angle < 90 ) {
			$x = round( $h * cos($alpha) );
			$y = round( $h * sin($alpha) );
		}
		elseif ( $angle >= 90 && $angle < 180 ) {
			$x = - round( $h * sin($alpha) );
			$y = round( $h * cos($alpha) );
		}
		else {
			$x = - round( $h * cos($alpha) );
			$y = - round( $h * sin($alpha) );
		}
		if (get_class($this) == "piechart3d")
			$y *= $this->_ecc;
		return array($x,$y);	
	}
}

?>
Return current item: TVEz - Media Library