PHP - ImageMagick command line Pie Chart

This code was converted from a bash version to create pie charts. It is much faster and does not require bc on the server.

PHP is used to create the ImageMagick command line.

This code creates pie chart and legend images which can then be placed on a web page or added in to a document.

To call the code, create an array of values, instantiate the GFX objects, establish the label_color_map as an associative array where the label text is the key and the value is a hex color code, and finally create the chart, sending a name and the data array, like so:

PHP

$data array(5070100349);
                        $chart = new GFX();
                        $chart->label_color_map(array('one' => '#1c28a1'
                          'two' => '#600087',
                          'three' => '#107a3f',
                          'four' => '#bf0000',
                          'five' => '#ff6d00'));
                        $chart->piechart('project',$data);

PHP

<?php 
Class GFX extends Base {
 
        public function __construct($parms null) {
                $this->_properties array('centerx','centery','width','height',
'radius');
                if (!is_array($parms)) {
                        $parms['width'] = $parms ['height'] = 330;
                        $parms['centerx'] = $parms['centery'] = 160;
                        $parms['radius'] = 135;
                }
                parent::__construct($parms);
        }
 
        public function label_color_map ($map array()) {
                $this->_data['labels'] = array();
                foreach ($map as $k => $v) {
                        $this->_data['labels'][$k] = $v;
                }
        }
        public function piechart($name null$data array()) {
                // Thanks to: http://jbkflex.wordpress.com/2011/07/28/creating-a-svg-pie-chart-html5/
                if ($name === null) return;
 
                $total array_sum($data);
 
                $max=0;$kmax='None';
                foreach ($data as $k => $v) {
                        $value[$k] = (int)(($v/$total) * 100);
                        if ($value[$k] > $max) {
                                $kmax=$k;
                                $max=$value[$k];
                        }
                }
                while (array_sum($value) < 100) {
                        $value[$kmax]++;
                }
 
                foreach ($data as $k => $v) {
                        $value[$k] = (int)(($v/$total) * 100);
                        if ($value[$k] > $max) {
                                $kmax=$k;
                                $max=$value[$k];
                        }
                }
                while (array_sum($value) < 100) {
                        $value[$kmax]++;
                }
                $centerx $this->_data['centerx'];
                $centery $this->_data['centery'];
                $radius$this->_data['radius'];
                $count=0;
                $startAngle=0;
                $endAngle=0;
                $arc=0;
                $x1=0;
                $x2=0;
                $y1=0;
                $y2=0;
                $pi=pi();
                $cmd='convert -size '.$this->_data['width'].'x'.$this->_data['height'].' xc:white -stroke white -strokewidth 5 ';
 
                foreach ($value as $k => $v) {
                        $startAngle=$endAngle;
                        $endAngle=$startAngle+(360*$v/100);
                        $theta $pi*$startAngle/180;
                        $x1=$centerx+$radius*cos($theta);
                        $y1=$centery+$radius*sin($theta);
                        $theta $pi*$endAngle/180;
                        $x2=$centerx+$radius*cos($theta);
                        $y2=$centery+$radius*sin($theta);
                        $arc = ($v >= 50) ? '1' '0';
                        $cmd.=' -fill "'.$this->_data['labels'][$k].'" -draw "path \'M '.$centerx.','.$centery.' L '.$x1.','.$y1.
                                ' A '.$radius.','.$radius.' 0 '.$arc.',1 '.$x2.','.$y2.' Z"';
                        $count++;
                }
                $cmd.=' '.escapeshellarg(_GFX_DIR_.'/'.$name.'_chart.jpg');
                `$cmd`;
 
                if (!is_array($this->_data['labels'])) return;
 
                $KEY_SIZE=20;
                $MARGIN=5;
                $TEXT_X=$KEY_SIZE+$MARGIN;
 
                $height =  $TEXT_X count($value);
 
                $cmd 'convert -size 135x'.$height.' xc:white -fill white ';
                $label " -font 'Nimbus-Sans-Bold' -stroke none -pointsize 12 ";
                $count=0;
                $y1=5;
                foreach ($value as $k => $v) {
                        $y2=$y1+$KEY_SIZE;
                        $y3=$y2-$MARGIN;
                        $label.=' -fill "'.$this->_data['labels'][$k].'" -draw "rectangle 0,'.$y1.' '.$KEY_SIZE.','.$y2.'"'.
                                ' -draw "text '.$TEXT_X.','.$y3.' '.escapeshellarg(/*$data[$k].' '.*/$v.'% '.$k).'"';
                        $count++;
                        $y1=$y1+$KEY_SIZE+$MARGIN;
                }
                $cmd.= $label.' '.escapeshellarg(_GFX_DIR_.'/'.$name.'_legend.jpg');
                `$cmd`;
        }
}

PHP

<?php
Abstract Class Base {
 
        protected $_properties;
        protected $_data;
        protected $_valid false;
        protected $_error_message array();
 
        function __construct($props) {
                $this->_data array_fill_keys($this->_propertiesnull);
                $this->_data array_merge($this->_data$props);
        }
 
        function __get($property) {
                return isset($this->_data[$property]) ? $this->_data[$property] : null;
        }
 
        function __set($property$value) {
                $this->_data[$property] = $value;
        }
 
        function isValid($property null) {
                if ($property === null)
                        return $this->_valid || (count($this->_error_message) == 0);
                else
                        return !isset($this->_error_message[$property]);
        }
 
        function error($property) {
                if (isset($this->_error_message[$property])) {
                        return $this->_error_message[$property];
                } else {
                        return '';
                }
        }
}

Many thanks to the link above for the chart algorithm.

This post courtesy of Worktrainer.