<?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);
}
}
?>