PHP Radial Pie Chart

Chris_Ryan
Chris_Ryan used Ask the Experts™
on
Hi,

We have a JS library that we use to generate a Pie Chart that the displays data as radial differential (rather than an angular one).  See attached for an example

Could anyone point us at a PHP Chart Library or expression that could generate this in PHP?

Many thanks
Chris
Radial-Pie-Chart.jpg
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Software Engineer
Commented:
Not sure if there is a library that does this. After looking around the net, I decided to give it a try and started coding and with a lot of help I got most of the way I think: http://schutt.nl/ee/Q_28933776/
outputI used code/information from: http://www.ulrichmierendorff.com/software/antialiased_arcs.html and http://members.chello.at/easyfilter/Bresenham.pdf

First the main file which produces the graphic (so it can be used as the src atrribute of an img on your page), below that the 2 include files.
<?
error_reporting(-1);

// http://www.ulrichmierendorff.com/software/antialiased_arcs.html
include ("./imageSmoothArc.php");

// bresenham aa circle, adapted from http://members.chello.at/easyfilter/Bresenham.pdf
include ("./BresenhamCircleAA.php");


// settings
$w = 600;
$h = 400;

// explode slices out from center
$explode = 2;

// init
$image = imagecreatetruecolor($w, $h);
imagealphablending($image, true);
imageantialias($image, false);

$white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
$black = imagecolorallocate($image, 0x00, 0x00, 0x00);
$gray = imagecolorallocate($image, 0xEE, 0xEE, 0xEE);

imagefilledrectangle($image, 0, 0, $w-1, $h-1, $white);

// data and colors
$data = [36, 43, 49, 58, 60, 52];
$labels = ['Segment A', 'Segment B', 'Segment C', 'Segment D', 'Segment E', 'Segment F'];

$colors = [];
$colors[] = imagecolorallocate($image, 130,  88, 250);
$colors[] = imagecolorallocate($image,  52, 237,  19);
$colors[] = imagecolorallocate($image, 255, 255,   2);
$colors[] = imagecolorallocate($image, 254,   0,   0);
$colors[] = imagecolorallocate($image,   1, 255, 255);
$colors[] = imagecolorallocate($image, 238, 155,  79);

$colors[] = imagecolorallocate($image, 0xFF, 0x00, 0x00);
$colors[] = imagecolorallocate($image, 0x00, 0xFF, 0x00);
$colors[] = imagecolorallocate($image, 0x00, 0x00, 0xFF);

$sz = min($w, $h) * 0.9;

$max = max($data);
$cnt = count($data);
$a = floor(360 / $cnt);

$fw = imagefontwidth(4);
$fh = imagefontheight(4);

for ($i = 0; $i < $cnt; $i++) {
  $x = $w/2 + $explode * cos(deg2rad(($i + 0.5) * $a - 90));
  $y = $h/2 + $explode * sin(deg2rad(($i + 0.5) * $a - 90));
  $s = $sz * $data[$i] / 100; // $max
  imagefilledsmootharc($image, $x, $y, $s, $s, $i * $a + 1 - 90, ($i + 1) * $a - 90, $colors[$i % count($colors)]); // , IMG_ARC_PIE
  $s = $s / 2 + 10;
  $x = $w/2 + $s * cos(deg2rad(($i + 0.5) * $a - 90));
  $y = $h/2 + $s * sin(deg2rad(($i + 0.5) * $a - 90));
  if (($i + 0.5) * $a > 180) {
    $x -= $fw * strlen($labels[$i]);
  }
  $y -= $fh * (1 - $y / $h);
  imagestring($image, 4, $x, $y, $labels[$i], $black);
}

for ($i = 10; $i <= 100; $i+=10) {
  plotCircleAA($image, $w/2, $h/2, $sz * $i / 100 / 2 + $explode, $gray);
}

//imagestring($image, 2, 0, 0, date(DATE_ATOM), $black);

header('Content-type: image/png');
imagepng($image);
imagedestroy($image);

?>

Open in new window

imageSmoothArc.php
BresenhamCircleAA.php
Most Valuable Expert 2011
Top Expert 2016

Commented:
The code cries out for refactoring, but the results are wonderful, and a perfect example of why E-E is a great place to post question, share ideas and learn as a community!  +1 for Robert!
Robert SchuttSoftware Engineer

Commented:
Wow thanks Ray, that's high praise coming from you! Of course it depends greatly on the work of those who made the anti-aliasing code. I was actually anticipating the question to make it into a class for easy re-use etc but don't have much experience with that. I'll post my efforts here anyway, maybe you can add some 'class' to it ;-)
<?

// http://www.ulrichmierendorff.com/software/antialiased_arcs.html
include ("./imageSmoothArc.php");

// bresenham aa circle, adapted from http://members.chello.at/easyfilter/Bresenham.pdf
include ("./BresenhamCircleAA.php");

class RadialPieChart {
  private $w;
  private $h;
  private $e; // explode from center

  public $image;
  private $white;
  private $black;
  private $gray;

  private $data;
  private $labels;
  private $colors;

  private $sz;
  private $cnt;
  private $max;
  private $a;
  private $fw;
  private $fh;

  private $xx;
  private $yy;

  public function __construct($w = 100, $h = 100, $e = 1, $image = null)
  {
    $this->w = $w;
    $this->h = $h;
    $this->e = $e;
    $this->image = $this->image != null ? $image : imagecreatetruecolor($w, $h);
    imagealphablending($this->image, true);
    imageantialias($this->image, false);

    $this->white = imagecolorallocate($this->image, 0xFF, 0xFF, 0xFF);
    $this->black = imagecolorallocate($this->image, 0x00, 0x00, 0x00);
    $this->gray = imagecolorallocate($this->image, 0xEE, 0xEE, 0xEE);
  }

  function SetData($data = null, $labels = null, $colors = null) {

    $this->data = $data != null ? $data : [1, 2, 3];
    $this->labels = $labels != null ? $labels : ['Segment A', 'Segment B', 'Segment C'];
    $this->colors = $colors != null ? $colors : [imagecolorallocate($this->image, 0xFF, 0x00, 0x00), imagecolorallocate($this->image, 0x00, 0xFF, 0x00), imagecolorallocate($this->image, 0x00, 0x00, 0xFF)];

    $this->max = max($this->data);
    $this->cnt = count($this->data);
    $this->a = floor(360 / $this->cnt);

    $this->fw = imagefontwidth(4);
    $this->fh = imagefontheight(4);
  }

  function Draw($xx = null, $yy = null, $w = null, $h = null) {

    $this->xx = $xx != null ? $xx : 0;
    $this->yy = $yy != null ? $yy : 0;
    $this->w = $w != null ? $w : $this->w;
    $this->h = $h != null ? $h : $this->h;

    $this->sz = min($this->w, $this->h) * 0.9;

    imagefilledrectangle($this->image, $this->xx, $this->yy, $this->xx + $this->w - 1, $this->yy + $this->h - 1, $this->white);

    for ($i = 0; $i < $this->cnt; $i++) {
      $x = $this->xx + $this->w / 2 + $this->e * cos(deg2rad(($i + 0.5) * $this->a - 90));
      $y = $this->yy + $this->h / 2 + $this->e * sin(deg2rad(($i + 0.5) * $this->a - 90));
      $s = $this->sz * $this->data[$i] / 100; // $max
      imagefilledsmootharc($this->image, $x, $y, $s, $s, $i * $this->a - 90, ($i + 1) * $this->a - 90, $this->colors[$i % count($this->colors)]); // , IMG_ARC_PIE
      $s = $s / 2 + 10;
      $x = $this->xx + $this->w / 2 + $s * cos(deg2rad(($i + 0.5) * $this->a - 90));
      $y = $this->yy + $this->h / 2 + $s * sin(deg2rad(($i + 0.5) * $this->a - 90));
      if (($i + 0.5) * $this->a > 180) {
        $x -= $this->fw * strlen($this->labels[$i]);
      }
      $y -= $this->fh * (1 - ($y - $this->yy) / $this->h);
      imagestring($this->image, 4, $x, $y, $this->labels[$i], $this->black);
    }

    for ($i = 10; $i <= 100; $i += 10) {
      plotCircleAA($this->image, $this->xx + $this->w / 2, $this->yy + $this->h / 2, $this->sz * $i / 100 / 2 + $this->e, $this->gray);
    }
  }

  function Output() {
    header('Content-type: image/png');
    imagepng($this->image);
    imagedestroy($this->image);
  }
}

// create chart object

$chart = new RadialPieChart(600, 400, 3);

// data and colors

$data = [36, 43, 49, 58, 60, 52];
$labels = ['Segment A', 'Segment B', 'Segment C', 'Segment D', 'Segment E', 'Segment F'];

$colors = [];
$colors[] = imagecolorallocate($chart->image, 130,  88, 250);
$colors[] = imagecolorallocate($chart->image,  52, 237,  19);
$colors[] = imagecolorallocate($chart->image, 255, 255,   2);
$colors[] = imagecolorallocate($chart->image, 254,   0,   0);
$colors[] = imagecolorallocate($chart->image,   1, 255, 255);
$colors[] = imagecolorallocate($chart->image, 238, 155,  79);

$chart->SetData($data, $labels, $colors);
if (true) {
  $chart->Draw();
} else {
  $chart->Draw(0,0,300,200);
  $chart->Draw(300,0,300,200);
  $chart->Draw(0,200,300,200);
  $chart->Draw(300,200,300,200);
}
$chart->Output();

?>

Open in new window

Author

Commented:
Hi Robert,

What can I say.

This is above and beyond

Thank you so much

Chris

Author

Commented:
This is a brilliant example of EE working at its best.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial