setValues($values); if (is_array($colors)) { $this->colors = $colors; } else { switch($colors) { case awPie::AQUA : $this->colors = array( new awColor(131, 220, 215), new awColor(131, 190, 215), new awColor(131, 160, 215), new awColor(160, 140, 215), new awColor(190, 131, 215), new awColor(220, 131, 215) ); break; case awPie::EARTH : $this->colors = array( new awColor(97, 179, 110), new awColor(130, 179, 97), new awColor(168, 179, 97), new awColor(179, 147, 97), new awColor(179, 108, 97), new awColor(99, 107, 189), new awColor(99, 165, 189) ); break; case awPie::DARK : $this->colors = array( new awColor(140, 100, 170), new awColor(130, 170, 100), new awColor(160, 160, 120), new awColor(150, 110, 140), new awColor(130, 150, 160), new awColor(90, 170, 140) ); break; default : $this->colors = array( new awColor(187, 213, 151), new awColor(223, 177, 151), new awColor(111, 186, 132), new awColor(197, 160, 230), new awColor(165, 169, 63), new awColor(218, 177, 89), new awColor(116, 205, 121), new awColor(200, 201, 78), new awColor(127, 205, 177), new awColor(205, 160, 160), new awColor(190, 190, 190) ); break; } } parent::__construct(); $this->label = new awLabel; $this->label->setCallbackFunction('callbackPerCent'); } /** * Change legend values * * @param array $legend An array of values for each part of the pie */ public function setLegend($legend) { $this->legendValues = (array)$legend; } /** * Set a border all around the pie * * @param awColor $color A color for the border */ public function setBorderColor(awColor $color) { $this->border = $color; } /** * Set a border all around the pie * * @param awColor $color A color for the border */ public function setBorder(awColor $color) { if (ARTICHOW_DEPRECATED === TRUE) { awImage::drawError('Class Pie: Method setBorder() has been deprecated since Artichow 1.0.9. Please use setBorderColor() instead.'); } else { $this->setBorderColor($color); } } /** * Change 3D effect intensity * * @param int $size Effect size */ public function set3D($size) { $this->size = (int)$size; } /** * Change initial angle * * @param int $angle New angle in degrees */ public function setStartAngle($angle) { $this->angle = (int)$angle; } /** * Change label precision * * @param int $precision New precision */ public function setLabelPrecision($precision) { $this->precision = (int)$precision; } /** * Change label position * * @param int $position New position in pixels */ public function setLabelPosition($position) { $this->position = (int)$position; } /** * Change label number * * @param int $number New number */ public function setLabelNumber($number) { $this->number = is_null($number) ? $number : (int)$number; } /** * Change label minimum * * @param int $minimum New minimum */ public function setLabelMinimum($minimum) { $this->minimum = is_null($minimum) ? $minimum : (int)$minimum; } /** * Change Pie explode * * @param array $explode */ public function explode($explode) { $this->explode = (array)$explode; } public function drawEnvelope(awDriver $driver) { } public function drawComponent(awDriver $driver, $x1, $y1, $x2, $y2, $aliasing) { $count = count($this->values); $sum = array_sum($this->values); $width = $x2 - $x1; $height = $y2 - $y1; if ($aliasing) { $x = $width / 2; $y = $height / 2; } else { $x = $width / 2 + $x1; $y = $height / 2 + $y1; } $position = $this->angle; $values = array(); $parts = array(); $angles = 0; if ($aliasing) { $side = new awSide(0, 0, 0, 0); } foreach($this->values as $key => $value) { $angle = ($value / $sum * 360); if ($key === $count - 1) { $angle = 360 - $angles; } $angles += $angle; if (array_key_exists($key, $this->explode)) { $middle = 360 - ($position + $angle / 2); $posX = $this->explode[$key] * cos($middle * M_PI / 180); $posY = $this->explode[$key] * sin($middle * M_PI / 180) * -1; if ($aliasing) { $explode = new awPoint( $posX * 2, $posY * 2 ); $side->set( max($side->left, $posX * -2), max($side->right, $posX * 2), max($side->top, $posY * -2), max($side->bottom, $posY * 2) ); } else { $explode = new awPoint( $posX, $posY ); } } else { $explode = new awPoint(0, 0); } $values[$key] = array( $position, ($position + $angle), $explode ); $color = $this->colors[$key % count($this->colors)]; $parts[$key] = new awPiePart($color); // Add part to the legend $legend = array_key_exists($key, $this->legendValues) ? $this->legendValues[$key] : $key; $this->legend->add($parts[$key], $legend, awLegend::BACKGROUND); $position += $angle; } if ($aliasing) { $mainDriver = $driver; $x *= 2; $y *= 2; $width *= 2; $height *= 2; $this->size *= 2; $image = new awImage; $image->border->hide(); // Adds support for antialiased pies on non-white background $background = $this->getBackground(); if ($background instanceof awColor) { $image->setBackgroundColor($background); } // elseif ($background instanceof awGradient) { // $image->setBackgroundColor(new White(100)); // } $image->setSize( $width + $side->left + $side->right, $height + $side->top + $side->bottom + $this->size + 1 /* bugs.php.net ! */ ); $driver = $image->getDriver( $width / $image->width, $height / $image->height, ($width / 2 + $side->left) / $image->width, ($height / 2 + $side->top) / $image->height ); } // Draw 3D effect for ($i = $this->size; $i > 0; $i--) { foreach($values as $key => $value) { $color = clone $this->colors[$key % count($this->colors)]; $color->brightness(-50); list($from, $to, $explode) = $value; $driver->filledArc($color, $explode->move($x, $y + $i), $width, $height, $from, $to); unset($color); if ($this->border instanceof awColor) { $point = $explode->move($x, $y); if ($i === $this->size) { $driver->arc($this->border, $point->move(0, $this->size), $width, $height, $from, $to); } } } } foreach($values as $key => $value) { $color = $this->colors[$key % count($this->colors)]; list($from, $to, $explode) = $value; $driver->filledArc($color, $explode->move($x, $y), $width, $height, $from, $to); if ($this->border instanceof awColor) { $point = $explode->move($x, $y); $driver->arc($this->border, $point, $width, $height, $from, $to); } } if ($aliasing) { $x = $x / 2 + $x1; $y = $y / 2 + $y1; $width /= 2; $height /= 2; $this->size /= 2; foreach($values as $key => $value) { $old = $values[$key][2]; $values[$key][2] = new awPoint( $old->x / 2, $old->y / 2 ); } $mainDriver->copyResizeImage( $image, new awPoint($x1 - $side->left / 2, $y1 - $side->top / 2), new awPoint($x1 - $side->left / 2 + $image->width / 2, $y1 - $side->top / 2 + $image->height/ 2), new awPoint(0, 0), new awPoint($image->width, $image->height), TRUE ); $driver = $mainDriver; } // Get labels values $pc = array(); foreach($this->values as $key => $value) { $pc[$key] = round($value / $sum * 100, $this->precision); } if ($this->label->count() === 0) { // Check that there is no user defined values $this->label->set($pc); } $position = 0; foreach($pc as $key => $value) { // Limit number of labels to display if ($position === $this->number) { break; } if (is_null($this->minimum) === FALSE and $value < $this->minimum) { continue; } $position++; list($from, $to, $explode) = $values[$key]; $angle = $from + ($to - $from) / 2; $angleRad = (360 - $angle) * M_PI / 180; $point = new awPoint( $x + $explode->x + cos($angleRad) * ($width / 2 + $this->position), $y + $explode->y - sin($angleRad) * ($height / 2 + $this->position) ); $angle %= 360; // We don't display labels on the 3D effect if ($angle > 0 and $angle < 180) { $point = $point->move(0, -1 * sin($angleRad) * $this->size); } if ($angle >= 45 and $angle < 135) { $this->label->setAlign(awLabel::CENTER, awLabel::BOTTOM); } elseif ($angle >= 135 and $angle < 225) { $this->label->setAlign(awLabel::RIGHT, awLabel::MIDDLE); } elseif ($angle >= 225 and $angle < 315) { $this->label->setAlign(awLabel::CENTER, awLabel::TOP); } else { $this->label->setAlign(awLabel::LEFT, awLabel::MIDDLE); } $this->label->draw( $driver, $point, $key ); } } /** * Return margins around the component * * @return array Left, right, top and bottom margins */ public function getMargin() { // Get axis informations $leftAxis = $this->padding->left; $rightAxis = $this->padding->right; $topAxis = $this->padding->top; $bottomAxis = $this->padding->bottom; return array($leftAxis, $rightAxis, $topAxis, $bottomAxis); } /** * Change values of Y axis * This method ignores not numeric values * * @param array $values */ public function setValues($values) { $this->checkArray($values); $this->values = $values; } /** * Return values of Y axis * * @return array */ public function getValues() { return $this->values; } private function checkArray(&$array) { if (is_array($array) === FALSE) { awImage::drawError("Class Pie: You tried to set values that are not an array."); } foreach($array as $key => $value) { if (is_numeric($value) === FALSE) { unset($array[$key]); } } if (count($array) < 1) { awImage::drawError("Class Pie: Your graph must have at least 1 value."); } } } registerClass('Pie'); /** * Pie * * @package Artichow */ class awPiePart implements awLegendable { /** * Pie part color * * @var Color */ protected $color; /** * Build a new awPiePart * * @param awColor $color Pie part color */ public function __construct(awColor $color) { $this->color = $color; } /** * Get the background color or gradient of an element of the component * * @return Color, Gradient */ public function getLegendBackground() { return $this->color; } /** * Get the line thickness * * @return NULL */ public function getLegendLineThickness() { } /** * Get the line type * * @return NULL */ public function getLegendLineStyle() { } /** * Get the color of line * * @return NULL */ public function getLegendLineColor() { } /** * Get a mark object * * @return NULL */ public function getLegendMark() { } } registerClass('PiePart'); function callbackPerCent($value) { return $value.'%'; }