jpgraph_pie.php
上传用户:gzy2002
上传日期:2010-02-11
资源大小:1785k
文件大小:24k
源码类别:

电子政务应用

开发平台:

Java

  1. <?php
  2. /*=======================================================================
  3. // File: JPGRAPH_PIE.PHP
  4. // Description: Pie plot extension for JpGraph
  5. // Created:  2001-02-14
  6. // Author: Johan Persson (johanp@aditus.nu)
  7. // Ver: $Id: jpgraph_pie.php,v 1.5 2003/10/10 03:37:56 wwf Exp $
  8. //
  9. // License: This code is released under QPL
  10. // Copyright (C) 2001,2002 Johan Persson
  11. //========================================================================
  12. */
  13. // Defines for PiePlot::SetLabelType()
  14. DEFINE("PIE_VALUE_ABS",1);
  15. DEFINE("PIE_VALUE_PER",0);
  16. DEFINE("PIE_VALUE_PERCENTAGE",0);
  17. //===================================================
  18. // CLASS PiePlot
  19. // Description: Draws a pie plot
  20. //===================================================
  21. class PiePlot {
  22.     var $posx=0.5,$posy=0.5;
  23.     var $radius=0.3;
  24.     var $explode_radius=array(),$explode_all=false,$explode_r=20;
  25.     var $labels=null, $legends=null;
  26.     var $csimtargets=null;  // Array of targets for CSIM
  27.     var $csimareas=''; // Generated CSIM text
  28.     var $csimalts=null; // ALT tags for corresponding target
  29.     var $data=null;
  30.     var $title;
  31.     var $startangle=0;
  32.     var $weight=1, $color="black";
  33.     var $legend_margin=6,$show_labels=true;
  34.     var $themearr = array(
  35. "earth"  => array(136,34,40,45,46,62,63,134,74,10,120,136,141,168,180,77,209,218,346,395,89,430),
  36. "pastel" => array(27,415,128,59,66,79,105,110,42,147,152,230,236,240,331,337,405,38),
  37. "water"  => array(8,370,24,40,335,56,213,237,268,14,326,387,10,388),
  38. "sand"   => array(27,168,34,170,19,50,65,72,131,209,46,393));
  39.     var $theme="earth";
  40.     var $setslicecolors=array();
  41.     var $labeltype=0; // Default to percentage
  42.     var $pie_border=true,$pie_interior_border=true;
  43.     var $value;
  44.     var $ishadowcolor='',$ishadowdrop=4;
  45.     var $ilabelposadj=1;
  46.     var $legendcsimtargets = array();
  47.     var $legendcsimalts = array();
  48. //---------------
  49. // CONSTRUCTOR
  50.     function PiePlot($data) {
  51. $this->data = array_reverse($data);
  52. $this->title = new Text("");
  53. $this->title->SetFont(FF_FONT1,FS_BOLD);
  54. $this->value = new DisplayValue();
  55. $this->value->Show();
  56. $this->value->SetFormat('%.1f%%');
  57.     }
  58. //---------------
  59. // PUBLIC METHODS
  60.     function SetCenter($x,$y=0.5) {
  61. $this->posx = $x;
  62. $this->posy = $y;
  63.     }
  64.     function SetColor($aColor) {
  65. $this->color = $aColor;
  66.     }
  67.     function SetSliceColors($aColors) {
  68. $this->setslicecolors = $aColors;
  69.     }
  70.     function SetShadow($aColor='darkgray',$aDropWidth=4) {
  71. $this->ishadowcolor = $aColor;
  72. $this->ishadowdrop = $aDropWidth;
  73.     }
  74.     function SetCSIMTargets($targets,$alts=null) {
  75. $this->csimtargets=array_reverse($targets);
  76. if( is_array($alts) )
  77.     $this->csimalts=array_reverse($alts);
  78.     }
  79.     function GetCSIMareas() {
  80. return $this->csimareas;
  81.     }
  82.     function AddSliceToCSIM($i,$xc,$yc,$radius,$sa,$ea) {  
  83.         //Slice number, ellipse centre (x,y), height, width, start angle, end angle
  84. while( $sa > 2*M_PI ) $sa = $sa - 2*M_PI;
  85. while( $ea > 2*M_PI ) $ea = $ea - 2*M_PI;
  86. $sa = 2*M_PI - $sa;
  87. $ea = 2*M_PI - $ea;
  88. //add coordinates of the centre to the map
  89. $coords = "$xc, $yc";
  90. //add coordinates of the first point on the arc to the map
  91. $xp = floor(($radius*cos($ea))+$xc);
  92. $yp = floor($yc-$radius*sin($ea));
  93. $coords.= ", $xp, $yp";
  94. //add coordinates every 0.2 radians
  95. $a=$ea+0.2;
  96. while ($a<$sa) {
  97.     $xp = floor($radius*cos($a)+$xc);
  98.     $yp = floor($yc-$radius*sin($a));
  99.     $coords.= ", $xp, $yp";
  100.     $a += 0.2;
  101. }
  102. //Add the last point on the arc
  103. $xp = floor($radius*cos($sa)+$xc);
  104. $yp = floor($yc-$radius*sin($sa));
  105. $coords.= ", $xp, $yp";
  106. if( !empty($this->csimtargets[$i]) )
  107.     $this->csimareas .= "<area shape="poly" coords="$coords" href="".
  108. $this->csimtargets[$i].""";
  109. if( !empty($this->csimalts[$i]) ) {
  110.     $tmp=sprintf($this->csimalts[$i],$this->data[$i]);
  111.     $this->csimareas .= " alt="$tmp" title="$tmp"";
  112. }
  113. $this->csimareas .= ">n";
  114.     }
  115.     function SetTheme($aTheme) {
  116. if( in_array($aTheme,array_keys($this->themearr)) )
  117.     $this->theme = $aTheme;
  118. else
  119.     JpGraphError::Raise("PiePLot::SetTheme() Unknown theme: $aTheme");
  120.     }
  121.     function ExplodeSlice($e,$radius=20) {
  122. $this->explode_radius[$e]=$radius;
  123.     }
  124.     function ExplodeAll($radius=20) {
  125. $this->explode_all=true;
  126. $this->explode_r = $radius;
  127.     }
  128.     function Explode($aExplodeArr) {
  129. if( !is_array($aExplodeArr) ) {
  130.     JpGraphError::Raise("Argument to PiePlot::Explode() must be an array.");
  131. }
  132. $this->explode_radius = $aExplodeArr;
  133.     }
  134.     function SetStartAngle($aStart) {
  135. if( $aStart < 0 || $aStart > 360 ) {
  136.     JpGraphError::Raise('Slice start angle must be between 0 and 360 degrees.');
  137. }
  138. $this->startangle = 360-$aStart;
  139.     }
  140.     function SetFont($family,$style=FS_NORMAL,$size=10) {
  141. JpGraphError::Raise('PiePlot::SetFont() is deprecated. Use PiePlot->value->SetFont() instead.');
  142.     }
  143.     // Size in percentage
  144.     function SetSize($aSize) {
  145. if( ($aSize>0 && $aSize<=0.5) || ($aSize>10 && $aSize<1000) )
  146.     $this->radius = $aSize;
  147. else
  148.     JpGraphError::Raise("PiePlot::SetSize() Radius for pie must either be specified as a fraction
  149.                                 [0, 0.5] of the size of the image or as an absolute size in pixels 
  150.                                 in the range [10, 1000]");
  151.     }
  152.     function SetFontColor($aColor) {
  153. JpGraphError::Raise('PiePlot::SetFontColor() is deprecated. Use PiePlot->value->SetColor() instead.');
  154.     }
  155.     // Set label arrays
  156.     function SetLegends($aLegend) {
  157. $this->legends = $aLegend;
  158.     }
  159.     // Set text labels for slices 
  160.     function SetLabels($aLabels,$aLblPosAdj="auto") {
  161. $this->labels = array_reverse($aLabels);
  162. $this->ilabelposadj=$aLblPosAdj;
  163.     }
  164.     function SetLabelPos($aLblPosAdj) {
  165. $this->ilabelposadj=$aLblPosAdj;
  166.     }
  167.     // Should we display actual value or percentage?
  168.     function SetLabelType($t) {
  169. if( $t<0 || $t>1 ) 
  170.     JpGraphError::Raise("PiePlot::SetLabelType() Type for pie plots must be 0 or 1 (not $t).");
  171. $this->labeltype=$t;
  172.     }
  173.     function SetValueType($aType) {
  174. $this->SetLabelType($aType);
  175.     }
  176.     // Should the circle around a pie plot be displayed
  177.     function ShowBorder($exterior=true,$interior=true) {
  178. $this->pie_border = $exterior;
  179. $this->pie_interior_border = $interior;
  180.     }
  181.     // Setup the legends
  182.     function Legend(&$graph) {
  183. $colors = array_keys($graph->img->rgb->rgb_table);
  184.     sort($colors);
  185.     $ta=$this->themearr[$this->theme];
  186.     $n = count($this->data);
  187.     if( $this->setslicecolors==null ) 
  188.     $numcolors=count($ta);
  189.     else {
  190.     $this->setslicecolors = array_slice($this->setslicecolors,0,$n);
  191.     $numcolors=$n; 
  192.     if( $graph->pieaa && get_class($this)==='pieplot' ) { 
  193. $this->setslicecolors = array_reverse($this->setslicecolors);
  194.     }
  195. }
  196. $sum=0;
  197. for($i=0; $i < $n; ++$i)
  198.     $sum += $this->data[$i];
  199. // Bail out with error if the sum is 0
  200. if( $sum==0 )
  201.     JpGraphError::Raise("Illegal pie plot. Sum of all data is zero for Pie!");
  202. // Make sure we don't plot more values than data points
  203. // (in case the user added more legends than data points)
  204. $n = min(count($this->legends),count($this->data));
  205. if( $this->legends != "" )
  206.     $this->legends = array_reverse($this->legends);
  207. for( $i=$n-1; $i >= 0; --$i ) {
  208.     $l = $this->legends[$i];
  209.     // Replace possible format with actual values
  210.     if( $this->labeltype==0 ) {
  211. $l = sprintf($l,100*$this->data[$i]/$sum);
  212.     }
  213.     else {
  214. $l = sprintf($l,$this->data[$i]);
  215.     }
  216.     
  217.     $alt = sprintf($this->csimalts[$i],$this->data[$i]);
  218.     if( $this->setslicecolors==null ) 
  219. $graph->legend->Add($l,$colors[$ta[$i%$numcolors]],"",0,
  220.     $this->csimtargets[$i],$alt);
  221.     else
  222. $graph->legend->Add($l,$this->setslicecolors[$i%$numcolors],"",0,
  223.     $this->csimtargets[$i],$alt);
  224. }
  225.     }
  226.     function Stroke(&$img,$aaoption=0) {
  227. // aaoption is used to handle antialias
  228. // aaoption == 0 a normal pie
  229. // aaoption == 1 just the body
  230. // aaoption == 2 just the values
  231. // Explode scaling. If anti anti alias we scale the image
  232. // twice and we also need to scale the exploding distance
  233. $expscale = $aaoption === 1 ? 2 : 1;
  234. $colors = array_keys($img->rgb->rgb_table);
  235.     sort($colors);
  236.     $ta=$this->themearr[$this->theme];
  237. $n = count($this->data);
  238.    
  239.     if( $this->setslicecolors==null ) 
  240.     $numcolors=count($ta);
  241.     else {
  242.     $this->setslicecolors = array_reverse(array_slice($this->setslicecolors,0,$n));
  243.     $numcolors=$n; 
  244. }
  245.    
  246. // Draw the slices
  247. $sum=0;
  248. for($i=0; $i < $n; ++$i)
  249.     $sum += $this->data[$i];
  250. // Bail out with error if the sum is 0
  251. if( $sum==0 )
  252.     JpGraphError::Raise("Sum of all data is 0 for Pie.");
  253. // Set up the pie-circle
  254. if( $this->radius <= 1 )
  255.     $radius = floor($this->radius*min($img->width,$img->height));
  256. else {
  257.     $radius = $aaoption === 1 ? $this->radius*2 : $this->radius;
  258. }
  259. if( $this->posx <= 1 && $this->posx > 0 )
  260.     $xc = round($this->posx*$img->width);
  261. else
  262.     $xc = $this->posx ;
  263. if( $this->posy <= 1 && $this->posy > 0 )
  264.     $yc = round($this->posy*$img->height);
  265. else
  266.     $yc = $this->posy ;
  267. $this->startangle = $this->startangle*M_PI/180;
  268. $n = count($this->data);
  269. if( $this->explode_all )
  270.     for($i=0; $i < $n; ++$i)
  271. $this->explode_radius[$i]=$this->explode_r;
  272. if( $this->ishadowcolor != "" && $aaoption !== 2) {
  273.     $accsum=0;
  274.     $angle2 = $this->startangle;
  275.     $img->SetColor($this->ishadowcolor);
  276.     for($i=0; $sum>0 && $i < $n; ++$i) {
  277. $d = $this->data[$i];
  278. $angle1 = $angle2;
  279. $accsum += $d;
  280. $angle2 = $this->startangle+2*M_PI*$accsum/$sum;
  281. if( empty($this->explode_radius[$i]) )
  282.     $this->explode_radius[$i]=0;
  283. $la = 2*M_PI - (abs($angle2-$angle1)/2.0+$angle1);
  284. $xcm = $xc + $this->explode_radius[$i]*cos($la)*$expscale;
  285. $ycm = $yc - $this->explode_radius[$i]*sin($la)*$expscale;
  286. $xcm += $this->ishadowdrop*$expscale;
  287. $ycm += $this->ishadowdrop*$expscale;
  288. $img->CakeSlice($xcm,$ycm,$radius,$radius,
  289. $angle1*180/M_PI,$angle2*180/M_PI,$this->ishadowcolor);
  290.     }
  291. }
  292. $accsum=0;
  293. $angle2 = $this->startangle;
  294. $img->SetColor($this->color);
  295. for($i=0; $sum>0 && $i < $n; ++$i) {
  296.     $d = $this->data[$i];
  297.     $angle1 = $angle2;
  298.     $accsum += $d;
  299.     $angle2 = $this->startangle+2*M_PI*$accsum/$sum;
  300.     if( $this->setslicecolors==null )
  301. $slicecolor=$colors[$ta[$i%$numcolors]];
  302.     else
  303. $slicecolor=$this->setslicecolors[$i%$numcolors];
  304.     if( $this->pie_interior_border && $aaoption===0 )
  305. $img->SetColor($this->color);
  306.     else
  307. $img->SetColor($slicecolor);
  308.     $arccolor = $this->pie_border && $aaoption===0 ? $this->color : "";
  309.     $this->la[$i] = 2*M_PI - (abs($angle2-$angle1)/2.0+$angle1);
  310.     if( empty($this->explode_radius[$i]) )
  311. $this->explode_radius[$i]=0;
  312.     $xcm = $xc + $this->explode_radius[$i]*cos($this->la[$i])*$expscale;
  313.     $ycm = $yc - $this->explode_radius[$i]*sin($this->la[$i])*$expscale;
  314.     if( $aaoption !== 2 ) {
  315. $img->CakeSlice($xcm,$ycm,$radius-1,$radius-1,
  316. $angle1*180/M_PI,$angle2*180/M_PI,$slicecolor,$arccolor);
  317.     }
  318.     if ($this->csimtargets && $aaoption !== 1 ) 
  319. $this->AddSliceToCSIM($i,$xcm,$ycm,$radius,$angle1,$angle2);
  320. }
  321. if( $this->value->show && $aaoption !== 1 ) {
  322.     // Format the titles for each slice
  323.     for( $i=0; $i < $n; ++$i) {
  324. if( $this->labeltype==0 )
  325.     if( $sum != 0 )
  326. $l = 100.0*$this->data[$i]/$sum;
  327.     else
  328. $l = 0.0;
  329. else
  330.     $l = $this->data[$i]*1.0;
  331. if( isset($this->labels[$i]) && is_string($this->labels[$i]) )
  332.     $this->labels[$i]=sprintf($this->labels[$i],$l);
  333. else
  334.     $this->labels[$i]=$l;
  335.     }
  336.     $this->StrokeAllLabels($img,$xc,$yc,$radius);
  337. }
  338. // Adjust title position
  339. if( $aaoption !== 1 ) {
  340.     $this->title->Pos($xc,
  341.   $yc-$this->title->GetFontHeight($img)-$radius-$this->title->margin,
  342.   "center","bottom");
  343.     $this->title->Stroke($img);
  344. }
  345.     }
  346. //---------------
  347. // PRIVATE METHODS
  348.     function StrokeAllLabels($img,$xc,$yc,$radius) {
  349. $n = count($this->labels);
  350. for($i=0; $i < $n; ++$i) {
  351.     $this->StrokeLabel($this->labels[$i],$img,$xc,$yc,$this->la[$i],
  352.        $radius + $this->explode_radius[$i]); 
  353. }
  354.     }
  355.     // Position the labels of each slice
  356.     function StrokeLabel($label,$img,$xc,$yc,$a,$r) {
  357. // Default value
  358. if( $this->ilabelposadj === 'auto' )
  359.     $this->ilabelposadj = 0.65;
  360. // We position the values diferently depending on if they are inside
  361. // or outside the pie
  362. if( $this->ilabelposadj < 1.0 ) {
  363.     $this->value->SetAlign('center','center');
  364.     $this->value->margin = 0;
  365.     
  366.     $xt=round($this->ilabelposadj*$r*cos($a)+$xc);
  367.     $yt=round($yc-$this->ilabelposadj*$r*sin($a));
  368.     
  369.     $this->value->Stroke($img,$label,$xt,$yt);
  370. }
  371. else {
  372.     $this->value->halign = "left";
  373.     $this->value->valign = "top";
  374.     $this->value->margin = 0;
  375.     
  376.     
  377.     // Position the axis title. 
  378.     // dx, dy is the offset from the top left corner of the bounding box that sorrounds the text
  379.     // that intersects with the extension of the corresponding axis. The code looks a little
  380.     // bit messy but this is really the only way of having a reasonable position of the
  381.     // axis titles.
  382.     $img->SetFont($this->value->ff,$this->value->fs,$this->value->fsize);
  383.     $h=$img->GetTextHeight($label);
  384.     // For numeric values the format of the display value
  385.     // must be taken into account
  386.     if( is_numeric($label) ) {
  387. if( $label > 0 )
  388.     $w=$img->GetTextWidth(sprintf($this->value->format,$label));
  389. else
  390.     $w=$img->GetTextWidth(sprintf($this->value->negformat,$label));
  391.     }
  392.     else
  393. $w=$img->GetTextWidth($label);
  394.     if( $this->ilabelposadj > 1.0 && $this->ilabelposadj < 5.0) {
  395. $r *= $this->ilabelposadj;
  396.     }
  397.     $r += $img->GetFontHeight()/1.5;
  398.     $xt=round($r*cos($a)+$xc);
  399.     $yt=round($yc-$r*sin($a));
  400.     while( $a < 0 ) $a += 2*M_PI;
  401.     while( $a > 2*M_PI ) $a -= 2*M_PI;
  402.     if( $a>=7*M_PI/4 || $a <= M_PI/4 ) $dx=0;
  403.     if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dx=($a-M_PI/4)*2/M_PI; 
  404.     if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dx=1;
  405.     if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dx=(1-($a-M_PI*5/4)*2/M_PI);
  406.     
  407.     if( $a>=7*M_PI/4 ) $dy=(($a-M_PI)-3*M_PI/4)*2/M_PI;
  408.     if( $a<=M_PI/4 ) $dy=(1-$a*2/M_PI);
  409.     if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dy=1;
  410.     if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dy=(1-($a-3*M_PI/4)*2/M_PI);
  411.     if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dy=0;
  412.     $this->value->Stroke($img,$label,$xt-$dx*$w,$yt-$dy*$h);
  413. }
  414.     }
  415. } // Class
  416. //===================================================
  417. // CLASS PiePlotC
  418. // Description: Same as a normal pie plot but with a 
  419. // filled circle in the center
  420. //===================================================
  421. class PiePlotC extends PiePlot {
  422.     var $imidsize=0.5; // Fraction of total width
  423.     var $imidcolor='white';
  424.     var $midtitle='';
  425.     var $middlecsimtarget="",$middlecsimalt="";
  426.     function PiePlotC($data,$aCenterTitle='') {
  427. parent::PiePlot($data);
  428. $this->midtitle = new Text();
  429. $this->midtitle->ParagraphAlign('center');
  430.     }
  431.     function SetMid($aTitle,$aColor='white',$aSize=0.5) {
  432. $this->midtitle->Set($aTitle);
  433. $this->imidsize = $aSize ; 
  434. $this->imidcolor = $aColor ; 
  435.     }
  436.     function SetMidTitle($aTitle) {
  437. $this->midtitle->Set($aTitle);
  438.     }
  439.     function SetMidSize($aSize) {
  440. $this->imidsize = $aSize ; 
  441.     }
  442.     function SetMidColor($aColor) {
  443. $this->imidcolor = $aColor ; 
  444.     }
  445.     function SetMidCSIM($aTarget,$aAlt) {
  446. $this->middlecsimtarget = $aTarget;
  447. $this->middlecsimalt = $aAlt;
  448.     }
  449.     function AddSliceToCSIM($i,$xc,$yc,$radius,$sa,$ea) {  
  450.         //Slice number, ellipse centre (x,y), radius, start angle, end angle
  451. while( $sa > 2*M_PI ) $sa = $sa - 2*M_PI;
  452. while( $ea > 2*M_PI ) $ea = $ea - 2*M_PI;
  453. $sa = 2*M_PI - $sa;
  454. $ea = 2*M_PI - $ea;
  455. // Add inner circle first point
  456. $xp = floor(($this->imidsize*$radius*cos($ea))+$xc);
  457. $yp = floor($yc-($this->imidsize*$radius*sin($ea)));
  458. $coords = "$xp, $yp";
  459. //add coordinates every 0.25 radians
  460. $a=$ea+0.25;
  461. while ($a < $sa) {
  462.     $xp = floor(($this->imidsize*$radius*cos($a)+$xc));
  463.     $yp = floor($yc-($this->imidsize*$radius*sin($a)));
  464.     $coords.= ", $xp, $yp";
  465.     $a += 0.25;
  466. }
  467. // Make sure we end at the last point
  468. $xp = floor(($this->imidsize*$radius*cos($sa)+$xc));
  469. $yp = floor($yc-($this->imidsize*$radius*sin($sa)));
  470. $coords.= ", $xp, $yp";
  471. // Straight line to outer circle
  472. $xp = floor($radius*cos($sa)+$xc);
  473. $yp = floor($yc-$radius*sin($sa));
  474. $coords.= ", $xp, $yp";
  475. //add coordinates every 0.25 radians
  476. $a=$sa - 0.25;
  477. while ($a > $ea) {
  478.     $xp = floor($radius*cos($a)+$xc);
  479.     $yp = floor($yc-$radius*sin($a));
  480.     $coords.= ", $xp, $yp";
  481.     $a -= 0.25;
  482. }
  483. //Add the last point on the arc
  484. $xp = floor($radius*cos($ea)+$xc);
  485. $yp = floor($yc-$radius*sin($ea));
  486. $coords.= ", $xp, $yp";
  487. // Close the arc
  488. $xp = floor(($this->imidsize*$radius*cos($ea))+$xc);
  489. $yp = floor($yc-($this->imidsize*$radius*sin($ea)));
  490. $coords .= ", $xp, $yp";
  491. if( !empty($this->csimtargets[$i]) )
  492.     $this->csimareas .= "<area shape="poly" coords="$coords" href="".
  493. $this->csimtargets[$i].""";
  494. if( !empty($this->csimalts[$i]) ) {
  495.     $tmp=sprintf($this->csimalts[$i],$this->data[$i]);
  496.     $this->csimareas .= " alt="$tmp" title="$tmp"";
  497. }
  498. $this->csimareas .= ">n";
  499.     }
  500.     function Stroke($img,$aaoption=0) {
  501. // Stroke the pie but don't stroke values
  502. $tmp =  $this->value->show;
  503. $this->value->show = false;
  504. parent::Stroke($img,$aaoption);
  505. $this->value->show = $tmp;
  506.   $xc = round($this->posx*$img->width);
  507. $yc = round($this->posy*$img->height);
  508. $radius = floor($this->radius * min($img->width,$img->height)) ;
  509. if( $this->imidsize > 0 && $aaoption !== 2 ) {
  510.     if( $this->ishadowcolor != "" ) {
  511. $img->SetColor($this->ishadowcolor);
  512. $img->FilledCircle($xc+$this->ishadowdrop,$yc+$this->ishadowdrop,
  513.    round($radius*$this->imidsize));
  514.     }
  515.     $img->SetColor($this->imidcolor);
  516.     $img->FilledCircle($xc,$yc,round($radius*$this->imidsize));
  517.     if(  $this->pie_border && $aaoption === 0 ) {
  518. $img->SetColor($this->color);
  519. $img->Circle($xc,$yc,round($radius*$this->imidsize));
  520.     }
  521.     if( !empty($this->middlecsimtarget) )
  522. $this->AddMiddleCSIM($xc,$yc,round($radius*$this->imidsize));
  523. }
  524. if( $this->value->show && $aaoption !== 1) {
  525.     $this->StrokeAllLabels($img,$xc,$yc,$radius);
  526.     $this->midtitle->Pos($xc,$yc,'center','center');
  527.     $this->midtitle->Stroke($img);
  528. }
  529.     }
  530.     function AddMiddleCSIM($xc,$yc,$r) {
  531. $this->csimareas .= "<area shape="circle" coords="$xc,$yc,$r" href="".
  532.     $this->middlecsimtarget.""";
  533. if( !empty($this->middlecsimalt) ) {
  534.     $tmp = $this->middlecsimalt;
  535.     $this->csimareas .= " alt="$tmp" title="$tmp"";
  536. }
  537. $this->csimareas .= ">n";
  538.     }
  539.     function StrokeLabel($label,$img,$xc,$yc,$a,$r) {
  540. if( $this->ilabelposadj === 'auto' )
  541.     $this->ilabelposadj = (1-$this->imidsize)/2+$this->imidsize;
  542. parent::StrokeLabel($label,$img,$xc,$yc,$a,$r);
  543.     }
  544. }
  545. //===================================================
  546. // CLASS PieGraph
  547. // Description: 
  548. //===================================================
  549. class PieGraph extends Graph {
  550.     var $posx, $posy, $radius;
  551.     var $legends=array();
  552.     var $plots=array();
  553.     var $pieaa = false ;
  554. //---------------
  555. // CONSTRUCTOR
  556.     function PieGraph($width=300,$height=200,$cachedName="",$timeout=0,$inline=1) {
  557. $this->Graph($width,$height,$cachedName,$timeout,$inline);
  558. $this->posx=$width/2;
  559. $this->posy=$height/2;
  560. $this->SetColor(array(255,255,255));
  561.     }
  562. //---------------
  563. // PUBLIC METHODS
  564.     function Add($aObj) {
  565. if( is_array($aObj) && count($aObj) > 0 )
  566.     $cl = get_class($aObj[0]);
  567. else
  568.     $cl = get_class($aObj);
  569. if( $cl == 'text' ) 
  570.     $this->AddText($aObj);
  571. else
  572.     $this->plots[] = $aObj;
  573.     }
  574.     function SetAntiAliasing($aFlg=true) {
  575. $this->pieaa = $aFlg;
  576.     }
  577.     function SetColor($c) {
  578. $this->SetMarginColor($c);
  579.     }
  580.     function DisplayCSIMAreas() {
  581.     $csim="";
  582.     foreach($this->plots as $p ) {
  583. $csim .= $p->GetCSIMareas();
  584.     }
  585.     //$csim.= $this->legend->GetCSIMareas();
  586.     if (preg_match_all("/area shape="(w+)" coords="([0-9, ]+)"/", $csim, $coords)) {
  587. $this->img->SetColor($this->csimcolor);
  588. for ($i=0; $i<count($coords[0]); $i++) {
  589.     if ($coords[1][$i]=="poly") {
  590. preg_match_all('/s*([0-9]+)s*,s*([0-9]+)s*,*/',$coords[2][$i],$pts);
  591. $this->img->SetStartPoint($pts[1][count($pts[0])-1],$pts[2][count($pts[0])-1]);
  592. for ($j=0; $j<count($pts[0]); $j++) {
  593.     $this->img->LineTo($pts[1][$j],$pts[2][$j]);
  594. }
  595.     } else if ($coords[1][$i]=="rect") {
  596. $pts = preg_split('/,/', $coords[2][$i]);
  597. $this->img->SetStartPoint($pts[0],$pts[1]);
  598. $this->img->LineTo($pts[2],$pts[1]);
  599. $this->img->LineTo($pts[2],$pts[3]);
  600. $this->img->LineTo($pts[0],$pts[3]);
  601. $this->img->LineTo($pts[0],$pts[1]);
  602.     }
  603. }
  604.     }
  605.     }
  606.     // Method description
  607.     function Stroke($aStrokeFileName="") {
  608. // If the filename is the predefined value = '_csim_special_'
  609. // we assume that the call to stroke only needs to do enough
  610. // to correctly generate the CSIM maps.
  611. // We use this variable to skip things we don't strictly need
  612. // to do to generate the image map to improve performance
  613. // a best we can. Therefor you will see a lot of tests !$_csim in the
  614. // code below.
  615. $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE);
  616. // We need to know if we have stroked the plot in the
  617. // GetCSIMareas. Otherwise the CSIM hasn't been generated
  618. // and in the case of GetCSIM called before stroke to generate
  619. // CSIM without storing an image to disk GetCSIM must call Stroke.
  620. $this->iHasStroked = true;
  621. $n = count($this->plots);
  622. if( $this->pieaa ) {
  623.     if( !$_csim ) {
  624. if( $this->background_image != "" ) {
  625.     $this->StrokeFrameBackground();
  626. }
  627. else {
  628.     $this->StrokeFrame();
  629. }
  630.     }
  631.     $w = $this->img->width;
  632.     $h = $this->img->height;
  633.     $oldimg = $this->img->img;
  634.     $this->img->CreateImgCanvas(2*$w,2*$h);
  635.     
  636.     $this->img->SetColor( $this->margin_color );
  637.     $this->img->FilledRectangle(0,0,2*$w-1,2*$h-1);
  638.     for($i=0; $i < $n; ++$i) {
  639. if( $this->plots[$i]->posx > 1 ) 
  640.     $this->plots[$i]->posx *= 2 ;
  641. if( $this->plots[$i]->posy > 1 ) 
  642.     $this->plots[$i]->posy *= 2 ;
  643. $this->plots[$i]->Stroke($this->img,1);
  644. if( $this->plots[$i]->posx > 1 ) 
  645.     $this->plots[$i]->posx /= 2 ;
  646. if( $this->plots[$i]->posy > 1 ) 
  647.     $this->plots[$i]->posy /= 2 ;
  648.     }
  649.     $indent = $this->doframe ? ($this->frame_weight + ($this->doshadow ? $this->shadow_width : 0 )) : 0 ;
  650.     $indent += $this->framebevel ? $this->framebeveldepth + 1 : 0 ;
  651.     $this->img->CopyCanvasH($oldimg,$this->img->img,$indent,$indent,$indent,$indent,
  652.     $w-2*$indent,$h-2*$indent,2*($w-$indent),2*($h-$indent));
  653.     $this->img->img = $oldimg ;
  654.     $this->img->width = $w ;
  655.     $this->img->height = $h ;
  656.     for($i=0; $i < $n; ++$i) {
  657. $this->plots[$i]->Stroke($this->img,2);
  658. $this->plots[$i]->Legend($this);
  659.     }
  660. }
  661. else {
  662.     if( !$_csim ) {
  663. if( $this->background_image != "" ) {
  664.     $this->StrokeFrameBackground();
  665. }
  666. else {
  667.     $this->StrokeFrame();
  668. }
  669.     }
  670.     
  671.     for($i=0; $i < $n; ++$i) {
  672. $this->plots[$i]->Stroke($this->img);
  673. $this->plots[$i]->Legend($this);
  674.     }
  675. }
  676. $this->legend->Stroke($this->img);
  677. $this->footer->Stroke($this->img);
  678. if( !$_csim ) {
  679.     $this->StrokeTitles();
  680.     // Stroke texts
  681.     if( $this->texts != null ) {
  682. $n = count($this->texts);
  683. for($i=0; $i < $n; ++$i ) {
  684.     $this->texts[$i]->Stroke($this->img);
  685. }
  686.     }
  687.     if( JPG_DEBUG ) {
  688. $this->DisplayCSIMAreas();
  689.     }
  690.     // If the filename is given as the special "__handle"
  691.     // then the image handler is returned and the image is NOT
  692.     // streamed back
  693.     if( $aStrokeFileName == _IMG_HANDLER ) {
  694. return $this->img->img;
  695.     }
  696.     else {
  697. // Finally stream the generated picture
  698. $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,
  699.    $aStrokeFileName);
  700.     }
  701. }
  702.     }
  703. } // Class
  704. /* EOF */
  705. ?>