From 55eddd7accf2c5f9b0f52b22a010c4c4b7c130d1 Mon Sep 17 00:00:00 2001 From: Bill Marquette Date: Fri, 6 Feb 2009 19:18:00 -0600 Subject: mv packages to config dir to match web layout --- config/dspam/pear/Image/Graph/Plot/Pie.php | 623 +++++++++++++++++++++++++++++ 1 file changed, 623 insertions(+) create mode 100644 config/dspam/pear/Image/Graph/Plot/Pie.php (limited to 'config/dspam/pear/Image/Graph/Plot/Pie.php') diff --git a/config/dspam/pear/Image/Graph/Plot/Pie.php b/config/dspam/pear/Image/Graph/Plot/Pie.php new file mode 100644 index 00000000..f0e872c3 --- /dev/null +++ b/config/dspam/pear/Image/Graph/Plot/Pie.php @@ -0,0 +1,623 @@ + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id$ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * 2D Piechart. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Plot_Pie extends Image_Graph_Plot +{ + + /** + * The radius of the 'pie' spacing + * @access private + * @var int + */ + var $_radius = 3; + + /** + * Explode pie slices. + * @access private + * @var mixed + */ + var $_explode = false; + + /** + * The starting angle of the plot + * @access private + * @var int + */ + var $_startingAngle = 0; + + /** + * The angle direction (1 = CCW, -1 = CW) + * @access private + * @var int + */ + var $_angleDirection = 1; + + /** + * The diameter of the pie plot + * @access private + * @var int + */ + var $_diameter = false; + + /** + * Group items below this limit together as "the rest" + * @access private + * @var double + */ + var $_restGroupLimit = false; + + /** + * Rest group title + * @access private + * @var string + */ + var $_restGroupTitle = 'The rest'; + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $y = ($y0 + $y1) / 2; + $this->_canvas->pieslice( + array( + 'x' => $x1, + 'y' => $y, + 'rx' => abs($x1 - $x0) / 2, + 'ry' => abs($y1 - $y0) / 2, + 'v1' => 45, + 'v2' => 315 + ) + ); + } + + /** + * Calculate marker point data + * + * @param array $point The point to calculate data for + * @param array $nextPoint The next point + * @param array $prevPoint The previous point + * @param array $totals The pre-calculated totals, if needed + * @return array An array containing marker point data + * @access private + */ + function _getMarkerData($point, $nextPoint, $prevPoint, &$totals) + { + $point = parent::_getMarkerData($point, $nextPoint, $prevPoint, $totals); + + $y = $totals['CURRENT_Y']; + + if ($this->_angleDirection < 0) { + $y = $totals['ALL_SUM_Y'] - $y; + } + + $point['ANGLE'] = 360 * (($y + ($point['Y'] / 2)) / $totals['ALL_SUM_Y']) + $this->_startingAngle; + $totals['CURRENT_Y'] += $point['Y']; + + $point['ANG_X'] = cos(deg2rad($point['ANGLE'])); + $point['ANG_Y'] = sin(deg2rad($point['ANGLE'])); + + $point['AX'] = -10 * $point['ANG_X']; + $point['AY'] = -10 * $point['ANG_Y']; + + if ((isset($totals['ALL_SUM_Y'])) && ($totals['ALL_SUM_Y'] != 0)) { + $point['PCT_MIN_Y'] = $point['PCT_MAX_Y'] = (100 * $point['Y'] / $totals['ALL_SUM_Y']); + } + + $point['LENGTH'] = 10; //$radius; + + $x = $point['X']; + $explodeRadius = 0; + if ((is_array($this->_explode)) && (isset($this->_explode[$x]))) { + $explodeRadius = $this->_explode[$x]; + } elseif (is_numeric($this->_explode)) { + $explodeRadius = $this->_explode; + } + + $point['MARKER_X'] = $totals['CENTER_X'] + + ($totals['RADIUS'] + $explodeRadius) * $point['ANG_X']; + $point['MARKER_Y'] = $totals['CENTER_Y'] + + ($totals['RADIUS'] + $explodeRadius) * $point['ANG_Y']; + + return $point; + } + + /** + * Draws markers on the canvas + * + * @access private + */ + function _drawMarker() + { + + if ($this->_marker) { + $totals = $this->_getTotals(); + + $totals['CENTER_X'] = (int) (($this->_left + $this->_right) / 2); + $totals['CENTER_Y'] = (int) (($this->_top + $this->_bottom) / 2); + + $totals['CURRENT_Y'] = 0; + $number = 0; + + $diameter = $this->_getDiameter(); + + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + + if (count($this->_dataset) == 1) { + $totals['RADIUS0'] = false; + $totals['RADIUS'] = $diameter / 2; + } else { + $dr = $diameter / (2 * count($this->_dataset)); + + $totals['RADIUS0'] = $number * $dr + ($number > 0 ? $this->_radius : 0); + $totals['RADIUS'] = ($number + 1) * $dr; + } + + $totals['ALL_SUM_Y'] = 0; + $totals['CURRENT_Y'] = 0; + $dataset->_reset(); + while ($point = $dataset->_next()) { + $totals['ALL_SUM_Y'] += $point['Y']; + } + + $dataset->_reset(); + $currentY = 0; + $the_rest = 0; + while ($point = $dataset->_next()) { + if (($this->_restGroupLimit !== false) && ($point['Y'] <= $this->_restGroupLimit)) { + $the_rest += $point['Y']; + } + else { + if ((!is_object($this->_dataSelector)) || + ($this->_dataSelector->select($point)) + ) { + $point = $this->_getMarkerData( + $point, + false, + false, + $totals + ); + if (is_array($point)) { + $this->_marker->_drawMarker( + $point['MARKER_X'], + $point['MARKER_Y'], + $point + ); + } + } + } + } + if ($the_rest > 0) { + $point = array('X' => $this->_restGroupTitle, 'Y' => $the_rest); + $point = $this->_getMarkerData( + $point, + false, + false, + $totals + ); + if (is_array($point)) { + $this->_marker->_drawMarker( + $point['MARKER_X'], + $point['MARKER_Y'], + $point + ); + } + } + $number++; + } + unset($keys); + } + } + + /** + * Explodes a piece of this pie chart + * + * @param int $explode Radius to explode with (or an array) + * @param string $x The 'x' value to explode or omitted + */ + function explode($explode, $x = false) + { + if ($x === false) { + $this->_explode = $explode; + } else { + $this->_explode[$x] = $explode; + } + } + + /** + * Set the starting angle of the plot + * + * East is 0 degrees + * South is 90 degrees + * West is 180 degrees + * North is 270 degrees + * + * It is also possible to specify the direction of the plot angles (i.e. clockwise 'cw' or + * counterclockwise 'ccw') + */ + function setStartingAngle($angle = 0, $direction = 'ccw') + { + $this->_startingAngle = ($angle % 360); + $this->_angleDirection = ($direction == 'ccw' ? 1 : -1); + } + + /** + * Set the diameter of the pie plot (i.e. the number of pixels the + * pie plot should be across) + * + * Use 'max' for the maximum possible diameter + * + * Use negative values for the maximum possible - minus this value (fx -2 + * to leave 1 pixel at each side) + * + * @param mixed @diameter The number of pixels + */ + function setDiameter($diameter) + { + $this->_diameter = $diameter; + } + + /** + * Set the limit for the y-value, where values below are grouped together + * as "the rest" + * + * @param double $limit The limit + * @param string $title The title to display in the legends (default 'The + * rest') + */ + function setRestGroup($limit, $title = 'The rest') + { + $this->_restGroupLimit = $limit; + $this->_restGroupTitle = $title; + } + + /** + * Get the diameter of the plot + * @return int The number of pixels the diameter is + * @access private + */ + function _getDiameter() + { + $diameter = 0; + if ($this->_diameter === false) { + $diameter = min($this->height(), $this->width()) * 0.75; + } + else { + if ($this->_diameter === 'max') { + $diameter = min($this->height(), $this->width()); + } + elseif ($this->_diameter < 0) { + $diameter = min($this->height(), $this->width()) + $this->_diameter; + } else { + $diameter = $this->_diameter; + } + } + return $diameter; + } + + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + $number = 0; + + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + + $totalY = 0; + $dataset->_reset(); + while ($point = $dataset->_next()) { + $totalY += $point['Y']; + } + + $centerX = (int) (($this->_left + $this->_right) / 2); + $centerY = (int) (($this->_top + $this->_bottom) / 2); + $diameter = $this->_getDiameter(); + if ($this->_angleDirection < 0) { + $currentY = $totalY; + } else { + $currentY = 0; //rand(0, 100)*$totalY/100; + } + $dataset->_reset(); + + if (count($this->_dataset) == 1) { + $radius0 = false; + $radius1 = $diameter / 2; + } else { + $dr = $diameter / (2 * count($this->_dataset)); + + $radius0 = $number * $dr + ($number > 0 ? $this->_radius : 0); + $radius1 = ($number + 1) * $dr; + } + + $the_rest = 0; + while ($point = $dataset->_next()) { + if (($this->_restGroupLimit !== false) && ($point['Y'] <= $this->_restGroupLimit)) { + $the_rest += $point['Y']; + } + else { + $angle1 = 360 * ($currentY / $totalY) + $this->_startingAngle; + $currentY += $this->_angleDirection * $point['Y']; + $angle2 = 360 * ($currentY / $totalY) + $this->_startingAngle; + + $x = $point['X']; + $id = $point['ID']; + + $dX = 0; + $dY = 0; + $explodeRadius = 0; + if ((is_array($this->_explode)) && (isset($this->_explode[$x]))) { + $explodeRadius = $this->_explode[$x]; + } elseif (is_numeric($this->_explode)) { + $explodeRadius = $this->_explode; + } + + if ($explodeRadius > 0) { + $dX = $explodeRadius * cos(deg2rad(($angle1 + $angle2) / 2)); + $dY = $explodeRadius * sin(deg2rad(($angle1 + $angle2) / 2)); + } + + $ID = $point['ID']; + $this->_getFillStyle($ID); + $this->_getLineStyle($ID); + $this->_canvas->pieslice( + $this->_mergeData( + $point, + array( + 'x' => $centerX + $dX, + 'y' => $centerY + $dY, + 'rx' => $radius1, + 'ry' => $radius1, + 'v1' => $angle1, + 'v2' => $angle2, + 'srx' => $radius0, + 'sry' => $radius0 + ) + ) + ); + } + } + + if ($the_rest > 0) { + $angle1 = 360 * ($currentY / $totalY) + $this->_startingAngle; + $currentY += $this->_angleDirection * $the_rest; + $angle2 = 360 * ($currentY / $totalY) + $this->_startingAngle; + + $x = 'rest'; + $id = 'rest'; + + $dX = 0; + $dY = 0; + $explodeRadius = 0; + if ((is_array($this->_explode)) && (isset($this->_explode[$x]))) { + $explodeRadius = $this->_explode[$x]; + } elseif (is_numeric($this->_explode)) { + $explodeRadius = $this->_explode; + } + + if ($explodeRadius > 0) { + $dX = $explodeRadius * cos(deg2rad(($angle1 + $angle2) / 2)); + $dY = $explodeRadius * sin(deg2rad(($angle1 + $angle2) / 2)); + } + + $ID = $id; + $this->_getFillStyle($ID); + $this->_getLineStyle($ID); + $this->_canvas->pieslice( + $this->_mergeData( + $point, + array( + 'x' => $centerX + $dX, + 'y' => $centerY + $dY, + 'rx' => $radius1, + 'ry' => $radius1, + 'v1' => $angle1, + 'v2' => $angle2, + 'srx' => $radius0, + 'sry' => $radius0 + ) + ) + ); + } + $number++; + } + unset($keys); + $this->_drawMarker(); + return true; + } + + /** + * Draw a sample for use with legend + * + * @param array $param The parameters for the legend + * @access private + */ + function _legendSample(&$param) + { + if (is_array($this->_dataset)) { + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + $this->_clip(true); + + $totals = $this->_getTotals(); + $totals['CENTER_X'] = (int) (($this->_left + $this->_right) / 2); + $totals['CENTER_Y'] = (int) (($this->_top + $this->_bottom) / 2); + $totals['RADIUS'] = min($this->height(), $this->width()) * 0.75 * 0.5; + $totals['CURRENT_Y'] = 0; + + if (is_a($this->_fillStyle, "Image_Graph_Fill")) { + $this->_fillStyle->_reset(); + } + + $count = 0; + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $count++; + + $dataset->_reset(); + $the_rest = 0; + while ($point = $dataset->_next()) { + $caption = $point['X']; + if (($this->_restGroupLimit !== false) && ($point['Y'] <= $this->_restGroupLimit)) { + $the_rest += $point['Y']; + } + else { + $this->_canvas->setFont($param['font']); + $width = 20 + $param['width'] + $this->_canvas->textWidth($caption); + $param['maxwidth'] = max($param['maxwidth'], $width); + $x2 = $param['x'] + $width; + $y2 = $param['y'] + $param['height']+5; + + if ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) && ($y2 > $param['bottom'])) { + $param['y'] = $param['top']; + $param['x'] = $x2; + $y2 = $param['y'] + $param['height']; + } elseif ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) == 0) && ($x2 > $param['right'])) { + $param['x'] = $param['left']; + $param['y'] = $y2; + $x2 = $param['x'] + 20 + $param['width'] + $this->_canvas->textWidth($caption); + } + + $x = $x0 = $param['x']; + $y = $param['y']; + $y0 = $param['y'] - $param['height']/2; + $x1 = $param['x'] + $param['width']; + $y1 = $param['y'] + $param['height']/2; + + if (!isset($param['simulate'])) { + $this->_getFillStyle($point['ID']); + $this->_getLineStyle($point['ID']); + $this->_drawLegendSample($x0, $y0, $x1, $y1); + + if (($this->_marker) && ($dataset) && ($param['show_marker'])) { + $prevPoint = $dataset->_nearby(-2); + $nextPoint = $dataset->_nearby(); + + $p = $this->_getMarkerData($point, $nextPoint, $prevPoint, $totals); + if (is_array($point)) { + $p['MARKER_X'] = $x+$param['width']/2; + $p['MARKER_Y'] = $y; + unset ($p['AVERAGE_Y']); + $this->_marker->_drawMarker($p['MARKER_X'], $p['MARKER_Y'], $p); + } + } + $this->write($x + $param['width'] +10, $y, $caption, IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, $param['font']); + } + + if (($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) { + $param['y'] = $y2; + } else { + $param['x'] = $x2; + } + } + } + if ($the_rest > 0) { + $this->_canvas->setFont($param['font']); + $width = 20 + $param['width'] + $this->_canvas->textWidth($this->_restGroupTitle); + $param['maxwidth'] = max($param['maxwidth'], $width); + $x2 = $param['x'] + $width; + $y2 = $param['y'] + $param['height']+5; + + if ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) && ($y2 > $param['bottom'])) { + $param['y'] = $param['top']; + $param['x'] = $x2; + $y2 = $param['y'] + $param['height']; + } elseif ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) == 0) && ($x2 > $param['right'])) { + $param['x'] = $param['left']; + $param['y'] = $y2; + $x2 = $param['x'] + 20 + $param['width'] + $this->_canvas->textWidth($this->_restGroupTitle); + } + + $x = $x0 = $param['x']; + $y = $param['y']; + $y0 = $param['y'] - $param['height']/2; + $x1 = $param['x'] + $param['width']; + $y1 = $param['y'] + $param['height']/2; + + if (!isset($param['simulate'])) { + $this->_getFillStyle('rest'); + $this->_getLineStyle('rest'); + $this->_drawLegendSample($x0, $y0, $x1, $y1); + + $this->write($x + $param['width'] + 10, $y, $this->_restGroupTitle, IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, $param['font']); + } + + if (($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) { + $param['y'] = $y2; + } else { + $param['x'] = $x2; + } + } + } + unset($keys); + $this->_clip(false); + $this->_canvas->endGroup(); + } + } + +} + +?> \ No newline at end of file -- cgit v1.2.3