Heuristic ranking analysis
[contractdashboard.git] / lib / pChart2.1.0 / class / pDraw.class.php
blob:a/lib/pChart2.1.0/class/pDraw.class.php -> blob:b/lib/pChart2.1.0/class/pDraw.class.php
  <?php
  /*
  pDraw - class extension with drawing methods
   
  Version : 2.1.0
  Made by : Jean-Damien POGOLOTTI
  Last Update : 26/01/11
   
  This file can be distributed under the license you can find at :
   
  http://www.pchart.net/license
   
  You can find the whole class documentation on the pChart web site.
  */
   
  define("DIRECTION_VERTICAL" , 690001);
  define("DIRECTION_HORIZONTAL" , 690002);
   
  define("SCALE_POS_LEFTRIGHT" , 690101);
  define("SCALE_POS_TOPBOTTOM" , 690102);
   
  define("SCALE_MODE_FLOATING" , 690201);
  define("SCALE_MODE_START0" , 690202);
  define("SCALE_MODE_ADDALL" , 690203);
  define("SCALE_MODE_ADDALL_START0" , 690204);
  define("SCALE_MODE_MANUAL" , 690205);
   
  define("SCALE_SKIP_NONE" , 690301);
  define("SCALE_SKIP_SAME" , 690302);
  define("SCALE_SKIP_NUMBERS" , 690303);
   
  define("TEXT_ALIGN_TOPLEFT" , 690401);
  define("TEXT_ALIGN_TOPMIDDLE" , 690402);
  define("TEXT_ALIGN_TOPRIGHT" , 690403);
  define("TEXT_ALIGN_MIDDLELEFT" , 690404);
  define("TEXT_ALIGN_MIDDLEMIDDLE" , 690405);
  define("TEXT_ALIGN_MIDDLERIGHT" , 690406);
  define("TEXT_ALIGN_BOTTOMLEFT" , 690407);
  define("TEXT_ALIGN_BOTTOMMIDDLE" , 690408);
  define("TEXT_ALIGN_BOTTOMRIGHT" , 690409);
   
  define("POSITION_TOP" , 690501);
  define("POSITION_BOTTOM" , 690502);
   
  define("LABEL_POS_LEFT" , 690601);
  define("LABEL_POS_CENTER" , 690602);
  define("LABEL_POS_RIGHT" , 690603);
  define("LABEL_POS_TOP" , 690604);
  define("LABEL_POS_BOTTOM" , 690605);
  define("LABEL_POS_INSIDE" , 690606);
  define("LABEL_POS_OUTSIDE" , 690607);
   
  define("ORIENTATION_HORIZONTAL" , 690701);
  define("ORIENTATION_VERTICAL" , 690702);
   
  define("LEGEND_NOBORDER" , 690800);
  define("LEGEND_BOX" , 690801);
  define("LEGEND_ROUND" , 690802);
   
  define("LEGEND_VERTICAL" , 690901);
  define("LEGEND_HORIZONTAL" , 690902);
   
  define("LEGEND_FAMILY_BOX" , 691051);
  define("LEGEND_FAMILY_CIRCLE" , 691052);
  define("LEGEND_FAMILY_LINE" , 691053);
   
  define("DISPLAY_AUTO" , 691001);
  define("DISPLAY_MANUAL" , 691002);
   
  define("LABELING_ALL" , 691011);
  define("LABELING_DIFFERENT" , 691012);
   
  define("BOUND_MIN" , 691021);
  define("BOUND_MAX" , 691022);
  define("BOUND_BOTH" , 691023);
   
  define("BOUND_LABEL_POS_TOP" , 691031);
  define("BOUND_LABEL_POS_BOTTOM" , 691032);
  define("BOUND_LABEL_POS_AUTO" , 691033);
   
  define("CAPTION_LEFT_TOP" , 691041);
  define("CAPTION_RIGHT_BOTTOM" , 691042);
   
  define("GRADIENT_SIMPLE" , 691051);
  define("GRADIENT_EFFECT_CAN" , 691052);
   
  define("PI" , 3.14159265);
  define("ALL" , 69);
  define("NONE" , 31);
  define("AUTO" , 690000);
  define("OUT_OF_SIGHT" , -10000000000000);
   
  class pDraw
  {
  /* Returns the number of drawable series */
  function countDrawableSeries()
  {
  $Results = 0;
  $Data = $this->DataSet->getData();
   
  foreach($Data["Series"] as $SerieName => $Serie)
  { if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) { $Results++; } }
   
  return($Results);
  }
   
  /* Fix box coordinates */
  function fixBoxCoordinates($Xa,$Ya,$Xb,$Yb)
  {
  $X1 = min($Xa,$Xb); $Y1 = min($Ya,$Yb);
  $X2 = max($Xa,$Xb); $Y2 = max($Ya,$Yb);
   
  return(array($X1,$Y1,$X2,$Y2));
  }
   
  /* Draw a polygon */
  function drawPolygon($Points,$Format="")
  {
  $R = isset($Format["R"]) ? $Format["R"] : 0;
  $G = isset($Format["G"]) ? $Format["G"] : 0;
  $B = isset($Format["B"]) ? $Format["B"] : 0;
  $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
  $NoBorder = isset($Format["NoBorder"]) ? $Format["NoBorder"] : FALSE;
  $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : $R;
  $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : $G;
  $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : $B;
  $BorderAlpha = isset($Format["Alpha"]) ? $Format["Alpha"] : $Alpha / 2;
  $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL;
  $SkipX = isset($Format["SkipX"]) ? $Format["SkipX"] : OUT_OF_SIGHT;
  $SkipY = isset($Format["SkipY"]) ? $Format["SkipY"] : OUT_OF_SIGHT;
   
  /* Calling the ImageFilledPolygon() function over the $Points array will round it */
  $Backup = $Points;
   
  if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; }
   
  if ( $SkipX != OUT_OF_SIGHT ) { $SkipX = floor($SkipX); }
  if ( $SkipY != OUT_OF_SIGHT ) { $SkipY = floor($SkipY); }
   
  $RestoreShadow = $this->Shadow;
  if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 )
  {
  $this->Shadow = FALSE;
  for($i=0;$i<=count($Points)-1;$i=$i+2)
  { $Shadow[] = $Points[$i] + $this->ShadowX; $Shadow[] = $Points[$i+1] + $this->ShadowY; }
  $this->drawPolygon($Shadow,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa,"NoBorder"=>TRUE));
  }
   
  $FillColor = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha);
   
  if ( count($Points) >= 6 )
  { ImageFilledPolygon($this->Picture,$Points,count($Points)/2,$FillColor); }
   
  if ( !$NoBorder )
  {
  $Points = $Backup;
   
  $BorderSettings = array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha);
  for($i=0;$i<=count($Points)-1;$i=$i+2)
  {
  if ( isset($Points[$i+2]) )
  {
  if ( !($Points[$i] == $Points[$i+2] && $Points[$i] == $SkipX ) && !($Points[$i+1] == $Points[$i+3] && $Points[$i+1] == $SkipY ) )
  $this->drawLine($Points[$i],$Points[$i+1],$Points[$i+2],$Points[$i+3],$BorderSettings);
  }
  else
  {
  if ( !($Points[$i] == $Points[0] && $Points[$i] == $SkipX ) && !($Points[$i+1] == $Points[1] && $Points[$i+1] == $SkipY ) )
  $this->drawLine($Points[$i],$Points[$i+1],$Points[0],$Points[1],$BorderSettings);
  }
  }
  }
   
  $this->Shadow = $RestoreShadow;
  }
   
  /* Apply AALias correction to the rounded box boundaries */
  function offsetCorrection($Value,$Mode)
  {
  $Value = round($Value,1);
   
  if ( $Value == 0 && $Mode == 1 ) { return(.9); }
  if ( $Value == 0 ) { return(0); }
   
  if ( $Mode == 1)
  { if ( $Value == 1 ) { return(.9); }; if ( $Value == .1 ) { return(.9); }; if ( $Value == .2 ) { return(.8); }; if ( $Value == .3 ) { return(.8); }; if ( $Value == .4 ) { return(.7); }; if ( $Value == .5 ) { return(.5); }; if ( $Value == .6 ) { return(.8); }; if ( $Value == .7 ) { return(.7); }; if ( $Value == .8 ) { return(.6); }; if ( $Value == .9 ) { return(.9); }; }
   
  if ( $Mode == 2)
  { if ( $Value == 1 ) { return(.9); }; if ( $Value == .1 ) { return(.1); }; if ( $Value == .2 ) { return(.2); }; if ( $Value == .3 ) { return(.3); }; if ( $Value == .4 ) { return(.4); }; if ( $Value == .5 ) { return(.5); }; if ( $Value == .6 ) { return(.8); }; if ( $Value == .7 ) { return(.7); }; if ( $Value == .8 ) { return(.8); }; if ( $Value == .9 ) { return(.9); }; }
   
  if ( $Mode == 3)
  { if ( $Value == 1 ) { return(.1); }; if ( $Value == .1 ) { return(.1); }; if ( $Value == .2 ) { return(.2); }; if ( $Value == .3 ) { return(.3); }; if ( $Value == .4 ) { return(.4); }; if ( $Value == .5 ) { return(.9); }; if ( $Value == .6 ) { return(.6); }; if ( $Value == .7 ) { return(.7); }; if ( $Value == .8 ) { return(.4); }; if ( $Value == .9 ) { return(.5); }; }
   
  if ( $Mode == 4)
  { if ( $Value == 1 ) { return(-1); }; if ( $Value == .1 ) { return(.1); }; if ( $Value == .2 ) { return(.2); }; if ( $Value == .3 ) { return(.3); }; if ( $Value == .4 ) { return(.1); }; if ( $Value == .5 ) { return(-.1); }; if ( $Value == .6 ) { return(.8); }; if ( $Value == .7 ) { return(.1); }; if ( $Value == .8 ) { return(.1); }; if ( $Value == .9 ) { return(.1); }; }
  }
   
  /* Draw a rectangle with rounded corners */
  function drawRoundedRectangle($X1,$Y1,$X2,$Y2,$Radius,$Format="")
  {
  $R = isset($Format["R"]) ? $Format["R"] : 0;
  $G = isset($Format["G"]) ? $Format["G"] : 0;
  $B = isset($Format["B"]) ? $Format["B"] : 0;
  $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
   
  list($X1,$Y1,$X2,$Y2) = $this->fixBoxCoordinates($X1,$Y1,$X2,$Y2);
   
  if ( $X2 - $X1 < $Radius ) { $Radius = floor((($X2-$X1))/2); }
  if ( $Y2 - $Y1 < $Radius ) { $Radius = floor((($Y2-$Y1))/2); }
   
  $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"NoBorder"=>TRUE);
   
  if ( $Radius <= 0 ) { $this->drawRectangle($X1,$Y1,$X2,$Y2,$Color); return(0); }
   
  if ( $this->Antialias )
  {
  $this->drawLine($X1+$Radius,$Y1,$X2-$Radius,$Y1,$Color);
  $this->drawLine($X2,$Y1+$Radius,$X2,$Y2-$Radius,$Color);
  $this->drawLine($X2-$Radius,$Y2,$X1+$Radius,$Y2,$Color);
  $this->drawLine($X1,$Y1+$Radius,$X1,$Y2-$Radius,$Color);
  }
  else
  {
  $Color = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha);
  imageline($this->Picture,$X1+$Radius,$Y1,$X2-$Radius,$Y1,$Color);
  imageline($this->Picture,$X2,$Y1+$Radius,$X2,$Y2-$Radius,$Color);
  imageline($this->Picture,$X2-$Radius,$Y2,$X1+$Radius,$Y2,$Color);
  imageline($this->Picture,$X1,$Y1+$Radius,$X1,$Y2-$Radius,$Color);
  }
   
  $Step = 360 / (2 * PI * $Radius);
  for($i=0;$i<=90;$i=$i+$Step)
  {
  $X = cos(($i+180)*PI/180) * $Radius + $X1 + $Radius;
  $Y = sin(($i+180)*PI/180) * $Radius + $Y1 + $Radius;
  $this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha));
   
  $X = cos(($i+90)*PI/180) * $Radius + $X1 + $Radius;
  $Y = sin(($i+90)*PI/180) * $Radius + $Y2 - $Radius;
  $this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha));
   
  $X = cos($i*PI/180) * $Radius + $X2 - $Radius;
  $Y = sin($i*PI/180) * $Radius + $Y2 - $Radius;
  $this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha));
   
  $X = cos(($i+270)*PI/180) * $Radius + $X2 - $Radius;
  $Y = sin(($i+270)*PI/180) * $Radius + $Y1 + $Radius;
  $this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha));
  }
  }
   
  /* Draw a rectangle with rounded corners */
  function drawRoundedFilledRectangle($X1,$Y1,$X2,$Y2,$Radius,$Format="")
  {
  $R = isset($Format["R"]) ? $Format["R"] : 0;
  $G = isset($Format["G"]) ? $Format["G"] : 0;
  $B = isset($Format["B"]) ? $Format["B"] : 0;
  $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : -1;
  $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : -1;
  $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : -1;
  $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
  $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL;
   
  if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; }
  if ( $BorderR == -1 ) { $BorderR = $R; $BorderG = $G; $BorderB = $B; }
   
  list($X1,$Y1,$X2,$Y2) = $this->fixBoxCoordinates($X1,$Y1,$X2,$Y2);
   
  if ( $X2 - $X1 < $Radius ) { $Radius = floor((($X2-$X1))/2); }
  if ( $Y2 - $Y1 < $Radius ) { $Radius = floor((($Y2-$Y1))/2); }
   
  $RestoreShadow = $this->Shadow;
  if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 )
  {
  $this->Shadow = FALSE;
  $this->drawRoundedFilledRectangle($X1+$this->ShadowX,$Y1+$this->ShadowY,$X2+$this->ShadowX,$Y2+$this->ShadowY,$Radius,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa));
  }
   
  $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"NoBorder"=>TRUE);
   
  if ( $Radius <= 0 ) { $this->drawFilledRectangle($X1,$Y1,$X2,$Y2,$Color); return(0); }
   
  $YTop = $Y1+$Radius;
  $YBottom = $Y2-$Radius;
   
  $Step = 360 / (2 * PI * $Radius);
  $Positions = ""; $Radius--; $MinY = ""; $MaxY = "";
  for($i=0;$i<=90;$i=$i+$Step)
  {
  $Xp1 = cos(($i+180)*PI/180) * $Radius + $X1 + $Radius;
  $Xp2 = cos(((90-$i)+270)*PI/180) * $Radius + $X2 - $Radius;
  $Yp = floor(sin(($i+180)*PI/180) * $Radius + $YTop);
  if ( $MinY == "" || $Yp > $MinY ) { $MinY = $Yp; }
   
  if ( !isset($Positions[$Yp]) )
  { $Positions[$Yp]["X1"] = $Xp1; $Positions[$Yp]["X2"] = $Xp2; }
  else
  { $Positions[$Yp]["X1"] = min($Positions[$Yp]["X1"],$Xp1); $Positions[$Yp]["X2"] = max($Positions[$Yp]["X2"],$Xp2); }
   
  $Xp1 = cos(($i+90)*PI/180) * $Radius + $X1 + $Radius;
  $Xp2 = cos((90-$i)*PI/180) * $Radius + $X2 - $Radius;
  $Yp = floor(sin(($i+90)*PI/180) * $Radius + $YBottom);
  if ( $MaxY == "" || $Yp < $MaxY ) { $MaxY = $Yp; }
   
  if ( !isset($Positions[$Yp]["Bottom"]) )
  { $Positions[$Yp]["X1"] = $Xp1; $Positions[$Yp]["X2"] = $Xp2; }
  else
  { $Positions[$Yp]["X1"] = min($Positions[$Yp]["X1"],$Xp1); $Positions[$Yp]["X2"] = max($Positions[$Yp]["X2"],$Xp2); }
  }
   
  $ManualColor = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha);
  foreach($Positions as $Yp => $Bounds)
  {
  $X1 = $Bounds["X1"]; $X1Dec = $this->getFirstDecimal($X1); if ( $X1Dec != 0 ) { $X1 = floor($X1)+1; }
  $X2 = $Bounds["X2"]; $X2Dec = $this->getFirstDecimal($X2); if ( $X2Dec != 0 ) { $X2 = floor($X2)-1; }
   
  imageline($this->Picture,$X1,$Yp,$X2,$Yp,$ManualColor);
  }
  $this->drawFilledRectangle($X1,$MinY+1,floor($X2),$MaxY-1,$Color);
   
  $Radius++;
  $this->drawRoundedRectangle($X1,$Y1,$X2+1,$Y2-1,$Radius,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha));
   
  $this->Shadow = $RestoreShadow;
  }
   
  /* Draw a rectangle with rounded corners */
  function drawRoundedFilledRectangle_deprecated($X1,$Y1,$X2,$Y2,$Radius,$Format="")
  {
  $R = isset($Format["R"]) ? $Format["R"] : 0;
  $G = isset($Format["G"]) ? $Format["G"] : 0;
  $B = isset($Format["B"]) ? $Format["B"] : 0;
  $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : -1;
  $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : -1;
  $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : -1;
  $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
  $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL;
   
  if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; }
  if ( $BorderR == -1 ) { $BorderR =