/**
  *  This function creates the graph and either sends it to the browser
  *  of saves it to a file.
  *
  *  @param  $file   (optional) If specified, the graph will be saved to
  *                  the indicated file. If left as default, the graph
  *                  will be outputted to the browser.
  */
 function plot($file = '')
 {
     // margins
     $margin = $this->m_margin;
     $marginy = $margin;
     $marginx = $margin + 5;
     if ($this->m_title) {
         $marginy += $this->m_fontHeight * 1.5;
     }
     $marginbottom = $margin + 5;
     $height = $this->m_height - $marginy - $marginbottom;
     $width = $this->m_width - $marginx - $margin;
     imagefilledrectangle($this->m_image, $marginx, $marginy, $marginx + $width, $marginy + $height, $this->m_fillColor);
     // plot title
     if ($this->m_title) {
         imagestring($this->m_image, $this->m_font, ($this->m_width - strlen($this->m_title) * $this->m_fontWidth) / 2, $margin, $this->m_title, $this->m_textColor);
     }
     YDGraph::_set_style($this->m_image, SOLID, $this->m_strokeColor, $this->m_fillColor);
     $sum = array_sum($this->m_values);
     $colors = array('#CC3232', '#70DBDB', '#66CD00', '#FF4040', '#8A2BE2', '#5F9F9F', '#EED2EE', '#E9967A', '#6666FF', '#A2C257', '#EEB4B4', '#8F5E99', '#EEC900', '#EE799F', '#B2DFEE', '#70DB93', '#F4A460', '#AAAAFF', '#CC3232', '#70DBDB', '#66CD00', '#FF4040', '#8A2BE2', '#5F9F9F', '#EED2EE', '#E9967A', '#6666FF', '#A2C257', '#EEB4B4', '#8F5E99', '#EEC900', '#EE799F', '#B2DFEE', '#70DB93', '#F4A460', '#AAAAFF');
     // pieces
     $degrees = array();
     for ($i = 0; $i < count($this->m_values); $i++) {
         $value = $this->m_values[$i] / $sum * 360;
         if ($value > 0 && floor($value / 360 * 100) > 0) {
             $degrees[$i] = $value;
         }
     }
     // sizes
     $diamx = $width / 2;
     $diamy = $height;
     if ($diamx > $diamy) {
         $diam = $diamy;
     } else {
         $diam = $diamx;
     }
     $radius = $diam / 2;
     $x = $marginx + $radius;
     $y = $marginy + $radius;
     imagearc($this->m_image, $x, $y, $diam, $diam, 0, 360, $this->m_strokeColor);
     // lines
     $last_angle = 0;
     foreach ($degrees as $i => $deg) {
         $last_angle = $last_angle + $deg;
         $end_x = floor($x + $radius * cos($last_angle * pi() / 180));
         $end_y = floor($y + $radius * sin($last_angle * pi() / 180));
         imageline($this->m_image, $x, $y, $end_x, $end_y, $this->m_strokeColor);
     }
     // colors
     $last_angle = 0;
     $pointer = 0;
     $max_len = 0;
     foreach ($degrees as $i => $deg) {
         $pointer = $last_angle + $deg;
         $this_angle = ($last_angle + $pointer) / 2;
         $last_angle = $pointer;
         $end_x = floor($x + $radius * cos($this_angle * pi() / 180));
         $end_y = floor($y + $radius * sin($this_angle * pi() / 180));
         $mid_x = floor(($x + $end_x) / 2);
         $mid_y = floor(($y + $end_y) / 2);
         $hex_split = YDGraph::_decode_color($colors[$i]);
         if (isset($this->m_colors[$i])) {
             $hex_split = YDGraph::_decode_color($this->m_colors[$i]);
         }
         $piece_color = imagecolorallocate($this->m_image, $hex_split[0], $hex_split[1], $hex_split[2]);
         imagefilltoborder($this->m_image, $mid_x, $mid_y, $this->m_strokeColor, $piece_color);
         $percent = number_format($deg / 360 * 100, $this->m_numberOfDecimals, $this->m_decimalSeparator, $this->m_thousandsSeparator);
         $max_len = strlen($percent) > $max_len ? strlen($percent) : $max_len;
     }
     // labels
     $last_position = $marginy;
     foreach ($degrees as $i => $deg) {
         $percent = number_format($deg / 360 * 100, $this->m_numberOfDecimals, $this->m_decimalSeparator, $this->m_thousandsSeparator);
         $align = 0;
         switch ($this->m_labelsFont) {
             case 1:
                 $align = 1;
                 break;
             case 2:
                 $align = -1;
                 break;
             case 3:
             case 4:
                 $align = -2;
                 break;
             case 5:
             case 6:
             case 7:
             case 8:
                 $align = -3;
                 break;
         }
         if ($this->m_labelsFontHeight + 3 >= 15) {
             $last_position += $this->m_labelsFontHeight + 3;
         } else {
             $last_position += 15;
         }
         $hex_split = YDGraph::_decode_color($colors[$i]);
         if (isset($this->m_colors[$i])) {
             $hex_split = YDGraph::_decode_color($this->m_colors[$i]);
         }
         $piece_color = imagecolorallocate($this->m_image, $hex_split[0], $hex_split[1], $hex_split[2]);
         $w = $x + $radius;
         $h = $last_position;
         imagefilledrectangle($this->m_image, $w + 20, $h, $w + 30, $h + 10, $piece_color);
         imagestring($this->m_image, $this->m_labelsFont, $w + 40, $h + $align, str_repeat(' ', $max_len - strlen($percent)) . $percent . "% " . $this->m_labels[$i], $this->m_labelsTextColor);
     }
     if ($this->m_showtotal) {
         if (isset($this->m_total)) {
             $sum = $this->m_total;
         }
         if ($this->m_formattotal) {
             $sum = number_format($sum, $this->m_numberOfDecimals, $this->m_decimalSeparator, $this->m_thousandsSeparator);
         }
         imagestring($this->m_image, $this->m_labelsFont, $w + 20, $h + 20, $this->m_totalstring . $sum, $this->m_labelsTextColor);
     }
     if (strlen($file) > 0) {
         switch (YDConfig::get('YD_GRAPH_TYPE')) {
             case IMG_GIF:
                 imagegif($this->m_image, $file);
                 break;
             case IMG_JPG:
             case IMG_JPEG:
                 imagejpeg($this->m_image, $file);
                 break;
             default:
                 imagepng($this->m_image, $file);
                 break;
         }
     } else {
         switch (YDConfig::get('YD_GRAPH_TYPE')) {
             case IMG_GIF:
                 header('Content-type: image/gif');
                 imagegif($this->m_image);
                 break;
             case IMG_JPG:
             case IMG_JPEG:
                 header('Content-type: image/jpeg');
                 imagejpeg($this->m_image);
                 break;
             default:
                 header('Content-type: image/png');
                 imagepng($this->m_image);
                 break;
         }
     }
 }