You are here

function pChart::drawPieGraph in Visitors 8

Same name and namespace in other branches
  1. 7.0 pchart/pChart.inc \pChart::drawPieGraph()

File

pchart/pChart.inc, line 1972

Class

pChart

Code

function drawPieGraph(&$Data, &$DataDescription, $XPos, $YPos, $Radius = 100, $DrawLabels = PIE_NOLABEL, $EnhanceColors = TRUE, $Skew = 60, $SpliceHeight = 20, $SpliceDistance = 0, $Decimals = 0) {

  /* Validate the Data and DataDescription array */
  $this
    ->validateDataDescription("drawPieGraph", $DataDescription, FALSE);
  $this
    ->validateData("drawPieGraph", $Data);

  /* Determine pie sum */
  $Series = 0;
  $PieSum = 0;
  $rPieSum = 0;
  foreach ($DataDescription["Values"] as $Key2 => $ColName) {
    if ($ColName != $DataDescription["Position"]) {
      $Series++;
      foreach ($Data as $Key => $Values) {
        if (isset($Data[$Key][$ColName])) {
          if ($Data[$Key][$ColName] == 0) {
            $PieSum++;
            $iValues[] = 1;
            $rValues[] = 0;
          }
          else {
            $PieSum += $Data[$Key][$ColName];
            $iValues[] = $Data[$Key][$ColName];
            $iLabels[] = $Data[$Key][$DataDescription["Position"]];
            $rValues[] = $Data[$Key][$ColName];
            $rPieSum += $Data[$Key][$ColName];
          }
        }
      }
    }
  }

  /* Validate serie */
  if ($Series != 1) {
    RaiseFatal("Pie chart can only accept one serie of data.");
  }
  $SpliceDistanceRatio = $SpliceDistance;
  $SkewHeight = $Radius * $Skew / 100;
  $SpliceRatio = (360 - $SpliceDistanceRatio * count($iValues)) / $PieSum;
  $SplicePercent = 100 / $PieSum;
  $rSplicePercent = 100 / $rPieSum;

  /* Calculate all polygons */
  $Angle = 0;
  $TopPlots = "";
  $BotPlots = "";
  $CDev = 5;
  foreach ($iValues as $Key => $Value) {
    $XCenterPos = cos(($Angle - $CDev + ($Value * $SpliceRatio + $SpliceDistanceRatio) / 2) * 3.1418 / 180) * $SpliceDistance + $XPos;
    $YCenterPos = sin(($Angle - $CDev + ($Value * $SpliceRatio + $SpliceDistanceRatio) / 2) * 3.1418 / 180) * $SpliceDistance + $YPos;
    $XCenterPos2 = cos(($Angle + $CDev + ($Value * $SpliceRatio + $SpliceDistanceRatio) / 2) * 3.1418 / 180) * $SpliceDistance + $XPos;
    $YCenterPos2 = sin(($Angle + $CDev + ($Value * $SpliceRatio + $SpliceDistanceRatio) / 2) * 3.1418 / 180) * $SpliceDistance + $YPos;
    $TopPlots[$Key][] = $XCenterPos;
    $BotPlots[$Key][] = $XCenterPos;
    $TopPlots[$Key][] = $YCenterPos;
    $BotPlots[$Key][] = $YCenterPos + $SpliceHeight;

    /* Process labels position & size */
    if (!($DrawLabels == PIE_NOLABEL)) {
      $TAngle = $Angle + $Value * $SpliceRatio / 2;
      if ($DrawLabels == PIE_PERCENTAGE) {
        $Caption = floor($rValues[$Key] * pow(10, $Decimals) * $rSplicePercent) / pow(10, $Decimals) . "%";
      }
      elseif ($DrawLabels == PIE_LABELS) {
        $Caption = $iLabels[$Key];
      }
      $TX = cos($TAngle * 3.1418 / 180) * ($Radius + 10) + $XPos;
      if ($TAngle > 0 && $TAngle < 180) {
        $TY = sin($TAngle * 3.1418 / 180) * ($SkewHeight + 10) + $YPos + $SpliceHeight + 4;
      }
      else {
        $TY = sin($TAngle * 3.1418 / 180) * ($SkewHeight + 10) + $YPos + 4;
      }
      if ($TAngle > 90 && $TAngle < 270) {
        $Position = imageftbbox($this->FontSize, 0, $this->FontName, $Caption);
        $TextWidth = $Position[2] - $Position[0];
        $TX = $TX - $TextWidth;
      }
      $C_TextColor = imagecolorallocate($this->Picture, 70, 70, 70);
      imagettftext($this->Picture, $this->FontSize, 0, $TX, $TY, $C_TextColor, $this->FontName, $Caption);
    }

    /* Process pie slices */
    for ($iAngle = $Angle; $iAngle <= $Angle + $Value * $SpliceRatio; $iAngle = $iAngle + 0.5) {
      $TopX = cos($iAngle * 3.1418 / 180) * $Radius + $XPos;
      $TopY = sin($iAngle * 3.1418 / 180) * $SkewHeight + $YPos;
      $TopPlots[$Key][] = $TopX;
      $BotPlots[$Key][] = $TopX;
      $TopPlots[$Key][] = $TopY;
      $BotPlots[$Key][] = $TopY + $SpliceHeight;
    }
    $TopPlots[$Key][] = $XCenterPos2;
    $BotPlots[$Key][] = $XCenterPos2;
    $TopPlots[$Key][] = $YCenterPos2;
    $BotPlots[$Key][] = $YCenterPos2 + $SpliceHeight;
    $Angle = $iAngle + $SpliceDistanceRatio;
  }

  /* Draw Bottom polygons */
  foreach ($iValues as $Key => $Value) {
    $C_GraphLo = $this
      ->AllocateColor($this->Picture, $this->Palette[$Key]["R"], $this->Palette[$Key]["G"], $this->Palette[$Key]["B"], -20);
    imagefilledpolygon($this->Picture, $BotPlots[$Key], (count($BotPlots[$Key]) + 1) / 2, $C_GraphLo);
    for ($j = 0; $j <= count($BotPlots[$Key]) - 4; $j = $j + 2) {
      $this
        ->drawLine($BotPlots[$Key][$j], $BotPlots[$Key][$j + 1], $BotPlots[$Key][$j + 2], $BotPlots[$Key][$j + 3], $this->Palette[$Key]["R"] - 20, $this->Palette[$Key]["G"] - 20, $this->Palette[$Key]["B"] - 20);
    }
  }

  /* Draw pie layers */
  if ($EnhanceColors) {
    $ColorRatio = 30 / $SpliceHeight;
  }
  else {
    $ColorRatio = 25 / $SpliceHeight;
  }
  for ($i = $SpliceHeight - 1; $i >= 1; $i--) {
    foreach ($iValues as $Key => $Value) {
      $C_GraphLo = $this
        ->AllocateColor($this->Picture, $this->Palette[$Key]["R"], $this->Palette[$Key]["G"], $this->Palette[$Key]["B"], -10);
      $Plots = "";
      $Plot = 0;
      foreach ($TopPlots[$Key] as $Key2 => $Value2) {
        $Plot++;
        if ($Plot % 2 == 1) {
          $Plots[] = $Value2;
        }
        else {
          $Plots[] = $Value2 + $i;
        }
      }
      imagefilledpolygon($this->Picture, $Plots, (count($Plots) + 1) / 2, $C_GraphLo);
      $Index = count($Plots);
      $ColorFactor = -20 + ($SpliceHeight - $i) * $ColorRatio;
      $this
        ->drawAntialiasPixel($Plots[0], $Plots[1], $this->Palette[$Key]["R"] + $ColorFactor, $this->Palette[$Key]["G"] + $ColorFactor, $this->Palette[$Key]["B"] + $ColorFactor);
      $this
        ->drawAntialiasPixel($Plots[2], $Plots[3], $this->Palette[$Key]["R"] + $ColorFactor, $this->Palette[$Key]["G"] + $ColorFactor, $this->Palette[$Key]["B"] + $ColorFactor);
      $this
        ->drawAntialiasPixel($Plots[$Index - 4], $Plots[$Index - 3], $this->Palette[$Key]["R"] + $ColorFactor, $this->Palette[$Key]["G"] + $ColorFactor, $this->Palette[$Key]["B"] + $ColorFactor);
    }
  }

  /* Draw Top polygons */
  for ($Key = count($iValues) - 1; $Key >= 0; $Key--) {
    $C_GraphLo = $this
      ->AllocateColor($this->Picture, $this->Palette[$Key]["R"], $this->Palette[$Key]["G"], $this->Palette[$Key]["B"]);
    imagefilledpolygon($this->Picture, $TopPlots[$Key], (count($TopPlots[$Key]) + 1) / 2, $C_GraphLo);
    if ($EnhanceColors) {
      $En = 10;
    }
    else {
      $En = 5;
    }
    for ($j = 0; $j <= count($TopPlots[$Key]) - 4; $j = $j + 2) {
      $this
        ->drawLine($TopPlots[$Key][$j], $TopPlots[$Key][$j + 1], $TopPlots[$Key][$j + 2], $TopPlots[$Key][$j + 3], $this->Palette[$Key]["R"] + $En, $this->Palette[$Key]["G"] + $En, $this->Palette[$Key]["B"] + $En);
    }
  }
}