PHP Radial Pie Chart

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
Chris_RyanAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Robert SchuttSoftware EngineerCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Ray PaseurCommented:
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 EngineerCommented:
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

Chris_RyanAuthor Commented:
Hi Robert,

What can I say.

This is above and beyond

Thank you so much

Chris
Chris_RyanAuthor Commented:
This is a brilliant example of EE working at its best.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.