function pPie::draw3DRing

5.x pPie.class.php pPie::draw3DRing($X, $Y, $Format = "")

File

inc/pchart/pchart/class/pPie.class.php, line 1094

Class

pPie

Code

function draw3DRing($X, $Y, $Format = "") 
 {
  $OuterRadius = isset($Format ["OuterRadius"]) ? $Format ["OuterRadius"] : 100;
  $Precision = isset($Format ["Precision"]) ? $Format ["Precision"] : 0;
  $InnerRadius = isset($Format ["InnerRadius"]) ? $Format ["InnerRadius"] : 30;
  $SkewFactor = isset($Format ["SkewFactor"]) ? $Format ["SkewFactor"] : .6;
  $SliceHeight = isset($Format ["SliceHeight"]) ? $Format ["SliceHeight"] : 10;
  $DataGapAngle = isset($Format ["DataGapAngle"]) ? $Format ["DataGapAngle"] : 10;
  $DataGapRadius = isset($Format ["DataGapRadius"]) ? $Format ["DataGapRadius"] : 10;
  $Border = isset($Format ["Border"]) ? $Format ["Border"] : FALSE;
  $Shadow = isset($Format ["Shadow"]) ? $Format ["Shadow"] : FALSE;
  $DrawLabels = isset($Format ["DrawLabels"]) ? $Format ["DrawLabels"] : FALSE;
  $LabelStacked = isset($Format ["LabelStacked"]) ? $Format ["LabelStacked"] : FALSE;
  $LabelColor = isset($Format ["LabelColor"]) ? $Format ["LabelColor"] : PIE_LABEL_COLOR_MANUAL;
  $LabelR = isset($Format ["LabelR"]) ? $Format ["LabelR"] : 0;
  $LabelG = isset($Format ["LabelG"]) ? $Format ["LabelG"] : 0;
  $LabelB = isset($Format ["LabelB"]) ? $Format ["LabelB"] : 0;
  $LabelAlpha = isset($Format ["LabelAlpha"]) ? $Format ["LabelAlpha"] : 100;
  $Cf = isset($Format ["Cf"]) ? $Format ["Cf"] : 20;
  $WriteValues = isset($Format ["WriteValues"]) ? $Format ["WriteValues"] : PIE_VALUE_NATURAL;
  $ValuePadding = isset($Format ["ValuePadding"]) ? $Format ["ValuePadding"] : $SliceHeight + 15;
  $ValuePosition = isset($Format ["ValuePosition"]) ? $Format ["ValuePosition"] : PIE_VALUE_OUTSIDE;
  $ValueSuffix = isset($Format ["ValueSuffix"]) ? $Format ["ValueSuffix"] : "";
  $ValueR = isset($Format ["ValueR"]) ? $Format ["ValueR"] : 255;
  $ValueG = isset($Format ["ValueG"]) ? $Format ["ValueG"] : 255;
  $ValueB = isset($Format ["ValueB"]) ? $Format ["ValueB"] : 255;
  $ValueAlpha = isset($Format ["ValueAlpha"]) ? $Format ["ValueAlpha"] : 100;
  $RecordImageMap = isset($Format ["RecordImageMap"]) ? $Format ["RecordImageMap"] : FALSE;

  /* Error correction for overlaying rounded corners */
  if ($SkewFactor < .5) {
    $SkewFactor = .5;
  }

  /* Data Processing */
  $Data = $this->pDataObject->getData();
  $Palette = $this->pDataObject->getPalette();

  /* Do we have an abscissa serie defined? */
  if ($Data ["Abscissa"] == "") {
    return (PIE_NO_ABSCISSA);
  }

  /* Try to find the data serie */
  $DataSerie = "";
  foreach ($Data ["Series"] as $SerieName => $SerieData) 
   {
    if ($SerieName != $Data ["Abscissa"]) {
      $DataSerie = $SerieName;
    }
  }

  /* Do we have data to compute? */
  if ($DataSerie == "") {
    return (PIE_NO_DATASERIE);
  }

  /* Remove unused data */
  list($Data, $Palette) = $this->clean0Values($Data, $Palette, $DataSerie, $Data ["Abscissa"]);

  /* Compute the pie sum */
  $SerieSum = $this->pDataObject->getSum($DataSerie);

  /* Do we have data to draw? */
  if ($SerieSum == 0) {
    return (PIE_SUMISNULL);
  }

  /* Dump the real number of data to draw */
  $Values = array();
  foreach ($Data ["Series"][$DataSerie]["Data"] as $Key => $Value) 
   {
    if ($Value != 0) {
      $Values [] = $Value;
    }
  }

  /* Compute the wasted angular space between series */
  if (count($Values) == 1) {
    $WastedAngular = 0;
  }
  else {
    $WastedAngular = count($Values) * $DataGapAngle;
  }

  /* Compute the scale */
  $ScaleFactor = (360 - $WastedAngular) / $SerieSum;

  $RestoreShadow = $this->pChartObject->Shadow;
  if ($this->pChartObject->Shadow) {
    $this->pChartObject->Shadow = FALSE;
  }

  /* Draw the polygon ring elements */
  $Offset = 360;
  $ID = count($Values) -1;
  $Values = array_reverse($Values);
  $Slice = 0;
  $Slices = array();
  $SliceColors = "";
  $Visible = "";
  $SliceAngle = "";
  foreach ($Values as $Key => $Value) 
   {
    if (!isset($Palette [$ID]["R"])) {
      $Color = $this->pChartObject->getRandomColor();
      $Palette [$ID] = $Color;
      $this->pDataObject->savePalette($ID, $Color);
    }
    $Settings = array("R" => $Palette [$ID]["R"], "G" => $Palette [$ID]["G"], "B" => $Palette [$ID]["B"], "Alpha" => $Palette [$ID]["Alpha"]);

    $SliceColors [$Slice] = $Settings;

    $StartAngle = $Offset;
    $EndAngle = $Offset -($Value * $ScaleFactor);
    if ($EndAngle < 0) {
      $EndAngle = 0;
    }

    if ($StartAngle > 180) {
      $Visible [$Slice]["Start"] = TRUE;
    }
    else {
      $Visible [$Slice]["Start"] = TRUE;
    }
    if ($EndAngle < 180) {
      $Visible [$Slice]["End"] = FALSE;
    }
    else {
      $Visible [$Slice]["End"] = TRUE;
    }

    $Step = (360 / (2 * PI * $OuterRadius)) / 2;
    $OutX1 = VOID;
    $OutY1 = VOID;
    for ($i = $Offset; $i >= $EndAngle; $i = $i -$Step) 
     {
      $Xc = cos(($i -90) * PI / 180) * ($OuterRadius + $DataGapRadius -2) + $X;
      $Yc = sin(($i -90) * PI / 180) * ($OuterRadius + $DataGapRadius -2) * $SkewFactor + $Y;
      $Slices [$Slice]["AA"][] = array($Xc, $Yc);

      $Xc = cos(($i -90) * PI / 180) * ($OuterRadius + $DataGapRadius -1) + $X;
      $Yc = sin(($i -90) * PI / 180) * ($OuterRadius + $DataGapRadius -1) * $SkewFactor + $Y;
      $Slices [$Slice]["AA"][] = array($Xc, $Yc);

      $Xc = cos(($i -90) * PI / 180) * ($OuterRadius + $DataGapRadius) + $X;
      $Yc = sin(($i -90) * PI / 180) * ($OuterRadius + $DataGapRadius) * $SkewFactor + $Y;
      $this->pChartObject->drawAntialiasPixel($Xc, $Yc, $Settings);

      if ($OutX1 == VOID) {
        $OutX1 = $Xc;
        $OutY1 = $Yc;
      }

      if ($i < 90) {
        $Yc++;
      }
      if ($i > 90 && $i < 180) {
        $Xc++;
      }
      if ($i > 180 && $i < 270) {
        $Xc++;
      }
      if ($i >= 270) {
        $Xc++;
        $Yc++;
      }

      $Slices [$Slice]["BottomPoly"][] = floor($Xc);
      $Slices [$Slice]["BottomPoly"][] = floor($Yc);
      $Slices [$Slice]["TopPoly"][] = floor($Xc);
      $Slices [$Slice]["TopPoly"][] = floor($Yc) -$SliceHeight;
      $Slices [$Slice]["Angle"][] = $i;
    }
    $OutX2 = $Xc;
    $OutY2 = $Yc;

    $Slices [$Slice]["Angle"][] = VOID;
    $Lasti = $i;

    $Step = (360 / (2 * PI * $InnerRadius)) / 2;
    $InX1 = VOID;
    $InY1 = VOID;
    for ($i = $EndAngle; $i <= $Offset; $i = $i + $Step) 
     {
      $Xc = cos(($i -90) * PI / 180) * ($InnerRadius + $DataGapRadius -1) + $X;
      $Yc = sin(($i -90) * PI / 180) * ($InnerRadius + $DataGapRadius -1) * $SkewFactor + $Y;
      $Slices [$Slice]["AA"][] = array($Xc, $Yc);

      $Xc = cos(($i -90) * PI / 180) * ($InnerRadius + $DataGapRadius) + $X;
      $Yc = sin(($i -90) * PI / 180) * ($InnerRadius + $DataGapRadius) * $SkewFactor + $Y;
      $Slices [$Slice]["AA"][] = array($Xc, $Yc);

      if ($InX1 == VOID) {
        $InX1 = $Xc;
        $InY1 = $Yc;
      }

      if ($i < 90) {
        $Yc++;
      }
      if ($i > 90 && $i < 180) {
        $Xc++;
      }
      if ($i > 180 && $i < 270) {
        $Xc++;
      }
      if ($i >= 270) {
        $Xc++;
        $Yc++;
      }

      $Slices [$Slice]["BottomPoly"][] = floor($Xc);
      $Slices [$Slice]["BottomPoly"][] = floor($Yc);
      $Slices [$Slice]["TopPoly"][] = floor($Xc);
      $Slices [$Slice]["TopPoly"][] = floor($Yc) -$SliceHeight;
      $Slices [$Slice]["Angle"][] = $i;
    }
    $InX2 = $Xc;
    $InY2 = $Yc;

    $Slices [$Slice]["InX1"] = $InX1;
    $Slices [$Slice]["InY1"] = $InY1;
    $Slices [$Slice]["InX2"] = $InX2;
    $Slices [$Slice]["InY2"] = $InY2;
    $Slices [$Slice]["OutX1"] = $OutX1;
    $Slices [$Slice]["OutY1"] = $OutY1;
    $Slices [$Slice]["OutX2"] = $OutX2;
    $Slices [$Slice]["OutY2"] = $OutY2;

    $Offset = $Lasti - $DataGapAngle;
    $ID--;
    $Slice++;
  }

  /* Draw the bottom pie splice */
  foreach ($Slices as $SliceID => $Plots) 
   {
    $Settings = $SliceColors [$SliceID];
    $Settings ["NoBorder"] = TRUE;
    $this->pChartObject->drawPolygon($Plots ["BottomPoly"], $Settings);

    foreach ($Plots ["AA"] as $Key => $Pos) {
      $this->pChartObject->drawAntialiasPixel($Pos [0], $Pos [1], $Settings);
    };

    $this->pChartObject->drawLine($Plots ["InX1"], $Plots ["InY1"], $Plots ["OutX2"], $Plots ["OutY2"], $Settings);
    $this->pChartObject->drawLine($Plots ["InX2"], $Plots ["InY2"], $Plots ["OutX1"], $Plots ["OutY1"], $Settings);
  }

  $Slices = array_reverse($Slices);
  $SliceColors = array_reverse($SliceColors);

  /* Draw the vertical edges (semi-visible) */
  foreach ($Slices as $SliceID => $Plots) 
   {
    $Settings = $SliceColors [$SliceID];
    $Settings ["NoBorder"] = TRUE;
    $Settings ["R"] = $Settings ["R"] + $Cf;
    $Settings ["G"] = $Settings ["G"] + $Cf;
    $Settings ["B"] = $Settings ["B"] + $Cf;

    $StartAngle = $Plots ["Angle"][0];
    foreach ($Plots ["Angle"] as $Key => $Angle) {
      if ($Angle == VOID) {
        $EndAngle = $Plots ["Angle"][$Key -1];
      }
    }

    if ($StartAngle >= 270 || $StartAngle <= 90) {
      $this->pChartObject->drawLine($Plots ["OutX1"], $Plots ["OutY1"], $Plots ["OutX1"], $Plots ["OutY1"] -$SliceHeight, $Settings);
    }
    if ($StartAngle >= 270 || $StartAngle <= 90) {
      $this->pChartObject->drawLine($Plots ["OutX2"], $Plots ["OutY2"], $Plots ["OutX2"], $Plots ["OutY2"] -$SliceHeight, $Settings);
    }

    $this->pChartObject->drawLine($Plots ["InX1"], $Plots ["InY1"], $Plots ["InX1"], $Plots ["InY1"] -$SliceHeight, $Settings);
    $this->pChartObject->drawLine($Plots ["InX2"], $Plots ["InY2"], $Plots ["InX2"], $Plots ["InY2"] -$SliceHeight, $Settings);
  }

  /* Draw the inner vertical slices */
  foreach ($Slices as $SliceID => $Plots) 
   {
    $Settings = $SliceColors [$SliceID];
    $Settings ["NoBorder"] = TRUE;
    $Settings ["R"] = $Settings ["R"] + $Cf;
    $Settings ["G"] = $Settings ["G"] + $Cf;
    $Settings ["B"] = $Settings ["B"] + $Cf;

    $Outer = TRUE;
    $Inner = FALSE;
    $InnerPlotsA = array();
    $InnerPlotsB = array();
    foreach ($Plots ["Angle"] as $ID => $Angle) 
     {
      if ($Angle == VOID) 
       {
        $Outer = FALSE;
        $Inner = TRUE;
      }
      elseif ($Inner) 
       {
        if (($Angle < 90 || $Angle > 270) && isset($Plots ["BottomPoly"][$ID * 2])) 
         {
          $Xo = $Plots ["BottomPoly"][$ID * 2];
          $Yo = $Plots ["BottomPoly"][$ID * 2 + 1];

          $InnerPlotsA [] = $Xo;
          $InnerPlotsA [] = $Yo;
          $InnerPlotsB [] = $Xo;
          $InnerPlotsB [] = $Yo -$SliceHeight;
        }
      }
    }

    if ($InnerPlotsA != "") 
     {
      $InnerPlots = array_merge($InnerPlotsA, $this->arrayReverse($InnerPlotsB));
      $this->pChartObject->drawPolygon($InnerPlots, $Settings);
    }
  }

  /* Draw the splice top and left poly */
  foreach ($Slices as $SliceID => $Plots) 
   {
    $Settings = $SliceColors [$SliceID];
    $Settings ["NoBorder"] = TRUE;
    $Settings ["R"] = $Settings ["R"] + $Cf * 1.5;
    $Settings ["G"] = $Settings ["G"] + $Cf * 1.5;
    $Settings ["B"] = $Settings ["B"] + $Cf * 1.5;

    $StartAngle = $Plots ["Angle"][0];
    foreach ($Plots ["Angle"] as $Key => $Angle) {
      if ($Angle == VOID) {
        $EndAngle = $Plots ["Angle"][$Key -1];
      }
    }

    if ($StartAngle < 180) 
     {
      $Points = array();
      $Points [] = $Plots ["InX2"];
      $Points [] = $Plots ["InY2"];
      $Points [] = $Plots ["InX2"];
      $Points [] = $Plots ["InY2"] -$SliceHeight;
      $Points [] = $Plots ["OutX1"];
      $Points [] = $Plots ["OutY1"] -$SliceHeight;
      $Points [] = $Plots ["OutX1"];
      $Points [] = $Plots ["OutY1"];

      $this->pChartObject->drawPolygon($Points, $Settings);
    }

    if ($EndAngle > 180) 
     {
      $Points = array();
      $Points [] = $Plots ["InX1"];
      $Points [] = $Plots ["InY1"];
      $Points [] = $Plots ["InX1"];
      $Points [] = $Plots ["InY1"] -$SliceHeight;
      $Points [] = $Plots ["OutX2"];
      $Points [] = $Plots ["OutY2"] -$SliceHeight;
      $Points [] = $Plots ["OutX2"];
      $Points [] = $Plots ["OutY2"];

      $this->pChartObject->drawPolygon($Points, $Settings);
    }
  }


  /* Draw the vertical edges (visible) */
  foreach ($Slices as $SliceID => $Plots) 
   {
    $Settings = $SliceColors [$SliceID];
    $Settings ["NoBorder"] = TRUE;
    $Settings ["R"] = $Settings ["R"] + $Cf;
    $Settings ["G"] = $Settings ["G"] + $Cf;
    $Settings ["B"] = $Settings ["B"] + $Cf;

    $StartAngle = $Plots ["Angle"][0];
    foreach ($Plots ["Angle"] as $Key => $Angle) {
      if ($Angle == VOID) {
        $EndAngle = $Plots ["Angle"][$Key -1];
      }
    }

    if ($StartAngle <= 270 && $StartAngle >= 90) {
      $this->pChartObject->drawLine($Plots ["OutX1"], $Plots ["OutY1"], $Plots ["OutX1"], $Plots ["OutY1"] -$SliceHeight, $Settings);
    }
    if ($EndAngle <= 270 && $EndAngle >= 90) {
      $this->pChartObject->drawLine($Plots ["OutX2"], $Plots ["OutY2"], $Plots ["OutX2"], $Plots ["OutY2"] -$SliceHeight, $Settings);
    }
  }


  /* Draw the outer vertical slices */
  foreach ($Slices as $SliceID => $Plots) 
   {
    $Settings = $SliceColors [$SliceID];
    $Settings ["NoBorder"] = TRUE;
    $Settings ["R"] = $Settings ["R"] + $Cf;
    $Settings ["G"] = $Settings ["G"] + $Cf;
    $Settings ["B"] = $Settings ["B"] + $Cf;

    $Outer = TRUE;
    $Inner = FALSE;
    $OuterPlotsA = array();
    $OuterPlotsB = array();
    $InnerPlotsA = "";
    $InnerPlotsB = "";
    foreach ($Plots ["Angle"] as $ID => $Angle) 
     {
      if ($Angle == VOID) 
       {
        $Outer = FALSE;
        $Inner = TRUE;
      }
      elseif ($Outer) 
       {
        if (($Angle > 90 && $Angle < 270) && isset($Plots ["BottomPoly"][$ID * 2])) 
         {
          $Xo = $Plots ["BottomPoly"][$ID * 2];
          $Yo = $Plots ["BottomPoly"][$ID * 2 + 1];

          $OuterPlotsA [] = $Xo;
          $OuterPlotsA [] = $Yo;
          $OuterPlotsB [] = $Xo;
          $OuterPlotsB [] = $Yo -$SliceHeight;
        }
      }
    }
    if ($OuterPlotsA != "") 
     {
      $OuterPlots = array_merge($OuterPlotsA, $this->arrayReverse($OuterPlotsB));
      $this->pChartObject->drawPolygon($OuterPlots, $Settings);
    }
  }

  $Slices = array_reverse($Slices);
  $SliceColors = array_reverse($SliceColors);


  /* Draw the top pie splice */
  foreach ($Slices as $SliceID => $Plots) 
   {
    $Settings = $SliceColors [$SliceID];
    $Settings ["NoBorder"] = TRUE;
    $Settings ["R"] = $Settings ["R"] + $Cf * 2;
    $Settings ["G"] = $Settings ["G"] + $Cf * 2;
    $Settings ["B"] = $Settings ["B"] + $Cf * 2;

    $this->pChartObject->drawPolygon($Plots ["TopPoly"], $Settings);

    if ($RecordImageMap) {
      $this->pChartObject->addToImageMap("POLY", $this->arraySerialize($Plots ["TopPoly"]), $this->pChartObject->toHTMLColor($Settings ["R"], $Settings ["G"], $Settings ["B"]), $Data ["Series"][$Data ["Abscissa"]]["Data"][$SliceID], $Data ["Series"][$DataSerie]["Data"][count($Slices) -$SliceID -1]);
    }

    foreach ($Plots ["AA"] as $Key => $Pos) {
      $this->pChartObject->drawAntialiasPixel($Pos [0], $Pos [1] -$SliceHeight, $Settings);
    };

    $this->pChartObject->drawLine($Plots ["InX1"], $Plots ["InY1"] -$SliceHeight, $Plots ["OutX2"], $Plots ["OutY2"] -$SliceHeight, $Settings);
    $this->pChartObject->drawLine($Plots ["InX2"], $Plots ["InY2"] -$SliceHeight, $Plots ["OutX1"], $Plots ["OutY1"] -$SliceHeight, $Settings);
  }

  if ($DrawLabels) 
   {
    $Offset = 360;
    foreach ($Values as $Key => $Value) 
     {
      $StartAngle = $Offset;
      $EndAngle = $Offset -($Value * $ScaleFactor);
      if ($EndAngle < 0) {
        $EndAngle = 0;
      }

      if ($LabelColor == PIE_LABEL_COLOR_AUTO) 
       {
        $Settings = array("FillR" => $Palette [$ID]["R"], "FillG" => $Palette [$ID]["G"], "FillB" => $Palette [$ID]["B"], "Alpha" => $Palette [$ID]["Alpha"]);
      }
      else 
       {
        $Settings = array("FillR" => $LabelR, "FillG" => $LabelG, "FillB" => $LabelB, "Alpha" => $LabelAlpha);
      }

      $Angle = ($EndAngle - $Offset) / 2 + $Offset;
      $Xc = cos(($Angle -90) * PI / 180) * ($OuterRadius + $DataGapRadius) + $X;
      $Yc = sin(($Angle -90) * PI / 180) * ($OuterRadius + $DataGapRadius) * $SkewFactor + $Y;

      if ($WriteValues == PIE_VALUE_PERCENTAGE) {
        $Label = $Display = round((100 / $SerieSum) * $Value, $Precision) . "%";
      }
      elseif ($WriteValues == PIE_VALUE_NATURAL) {
        $Label = $Data ["Series"][$Data ["Abscissa"]]["Data"][$Key];
      }
      else {
        $Label = "";
      }

      if ($LabelStacked) {
        $this->writePieLabel($Xc, $Yc -$SliceHeight, $Label, $Angle, $Settings, TRUE, $X, $Y, $OuterRadius);
      }
      else {
        $this->writePieLabel($Xc, $Yc -$SliceHeight, $Label, $Angle, $Settings, FALSE);
      }

      $Offset = $EndAngle - $DataGapAngle;
      $ID--;
      $Slice++;
    }
  }
  if ($DrawLabels && $LabelStacked) {
    $this->writeShiftedLabels();
  }

  $this->pChartObject->Shadow = $RestoreShadow;

  return (PIE_RENDERED);
}