home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 April / CMCD0404.ISO / Software / Freeware / Programare / dotproject / lib / jpgraph / src / jpgraph_bar.php < prev    next >
PHP Script  |  2003-02-14  |  22KB  |  741 lines

  1. <?php
  2. /*=======================================================================
  3. // File:    JPGRAPH_BAR.PHP
  4. // Description:    Bar plot extension for JpGraph
  5. // Created:     2001-01-08
  6. // Author:    Johan Persson (johanp@aditus.nu)
  7. // Ver:        $Id: jpgraph_bar.php,v 1.3 2003/02/14 18:21:11 kobudo Exp $
  8. //
  9. // License:    This code is released under QPL
  10. // Copyright (C) 2001,2002 Johan Persson
  11. //========================================================================
  12. */
  13.   
  14. //===================================================
  15. // CLASS Gradient
  16. // Description: Handles gradient fills. This is to be
  17. // considered a "friend" class of Class Image.
  18. //===================================================
  19. class Gradient {
  20.     var $img=null;
  21. //---------------
  22. // CONSTRUCTOR
  23.     function Gradient(&$img) {
  24.     $this->img = $img;
  25.     }
  26.  
  27. //---------------
  28. // PUBLIC METHODS    
  29.     // Produce a gradient filled rectangle with a smooth transition between
  30.     // two colors.
  31.     // ($xl,$yt)     Top left corner
  32.     // ($xr,$yb)    Bottom right
  33.     // $from_color    Starting color in gradient
  34.     // $to_color    End color in the gradient
  35.     // $style        Which way is the gradient oriented?
  36.     function FilledRectangle($xl,$yt,$xr,$yb,$from_color,$to_color,$style=1) {
  37.     switch( $style ) {    
  38.         case 1:  // HORIZONTAL
  39.         $steps = abs($xr-$xl);
  40.         $delta = $xr>=$xl ? 1 : -1;
  41.         $this->GetColArray($from_color,$to_color,$steps,$colors);
  42.         for( $i=0, $x=$xl; $i<$steps; ++$i ) {
  43.         $this->img->current_color = $colors[$i];
  44.         $this->img->Line($x,$yt,$x,$yb);
  45.         $x += $delta;
  46.         }
  47.         break;
  48.  
  49.         case 2: // VERTICAL
  50.         $steps = abs($yb-$yt);
  51.         $delta = $yb>=$yt ? 1 : -1;
  52.         $this->GetColArray($from_color,$to_color,$steps,$colors);
  53.         for($i=0,$y=$yt; $i<$steps; ++$i) {
  54.         $this->img->current_color = $colors[$i];
  55.         $this->img->Line($xl,$y,$xr,$y);
  56.         $y += $delta;
  57.         }
  58.         break;
  59.  
  60.         case 3: // VERTICAL FROM MIDDLE
  61.         $steps = abs($yb-$yt)/2;
  62.         $delta = $yb>=$yt ? 1 : -1;
  63.         $this->GetColArray($from_color,$to_color,$steps,$colors);
  64.         for($y=$yt, $i=0; $i<$steps;  ++$i) {
  65.         $this->img->current_color = $colors[$i];
  66.         $this->img->Line($xl,$y,$xr,$y);
  67.         $y += $delta;
  68.         }
  69.         --$i;
  70.         for($j=0; $j<$steps; ++$j, --$i) {
  71.         $this->img->current_color = $colors[$i];
  72.         $this->img->Line($xl,$y,$xr,$y);
  73.         $y += $delta;
  74.         }
  75.         $this->img->Line($xl,$y,$xr,$y);
  76.         break;
  77.  
  78.         case 4: // HORIZONTAL FROM MIDDLE
  79.         $steps = abs($xr-$xl)/2;
  80.         $delta = $xr>=$xl ? 1 : -1;
  81.         $this->GetColArray($from_color,$to_color,$steps,$colors);
  82.         for($x=$xl, $i=0; $i<$steps; ++$i) {
  83.         $this->img->current_color = $colors[$i];
  84.         $this->img->Line($x,$yb,$x,$yt);
  85.         $x += $delta;
  86.         }
  87.         --$i;
  88.         for($j=0; $j<$steps; ++$j, --$i) {
  89.         $this->img->current_color = $colors[$i];
  90.         $this->img->Line($x,$yb,$x,$yt);
  91.         $x += $delta;
  92.         }
  93.         $this->img->Line($x,$yb,$x,$yt);        
  94.         break;
  95.  
  96.         case 6: // HORIZONTAL WIDER MIDDLE
  97.         $steps = abs($xr-$xl)/3;
  98.         $delta = $xr>=$xl ? 1 : -1;
  99.         $this->GetColArray($from_color,$to_color,$steps,$colors);
  100.         for($x=$xl, $i=0; $i<$steps; ++$i) {
  101.         $this->img->current_color = $colors[$i];
  102.         $this->img->Line($x,$yb,$x,$yt);
  103.         $x += $delta;
  104.         }
  105.         --$i;
  106.         $this->img->current_color = $colors[$i];
  107.         for($j=0; $j< $steps; ++$j) {
  108.         $this->img->Line($x,$yb,$x,$yt);
  109.         $x += $delta;
  110.         }
  111.  
  112.         for($j=0; $j<$steps; ++$j, --$i) {
  113.         $this->img->current_color = $colors[$i];                
  114.         $this->img->Line($x,$yb,$x,$yt);    
  115.         $x += $delta;
  116.         }                
  117.         break;
  118.  
  119.         case 7: // VERTICAL WIDER MIDDLE
  120.         $steps = abs($yb-$yt)/3;
  121.         $delta = $yb>=$yt? 1 : -1;
  122.         $this->GetColArray($from_color,$to_color,$steps,$colors);
  123.         for($y=$yt, $i=0; $i<$steps;  ++$i) {
  124.         $this->img->current_color = $colors[$i];
  125.         $this->img->Line($xl,$y,$xr,$y);
  126.         $y += $delta;
  127.         }
  128.         --$i;
  129.         $this->img->current_color = $colors[$i];
  130.         for($j=0; $j< $steps; ++$j) {
  131.         $this->img->Line($xl,$y,$xr,$y);
  132.         $y += $delta;
  133.         }
  134.         for($j=0; $j<$steps; ++$j, --$i) {
  135.         $this->img->current_color = $colors[$i];                
  136.         $this->img->Line($xl,$y,$xr,$y);
  137.         $y += $delta;
  138.         }                
  139.         break;
  140.  
  141.         case 5: // Rectangle
  142.         $steps = floor(min(($yb-$yt)+1,($xr-$xl)+1)/2);    
  143.         $this->GetColArray($from_color,$to_color,$steps,$colors);
  144.         $dx = ($xr-$xl)/2;
  145.         $dy = ($yb-$yt)/2;
  146.         $x=$xl;$y=$yt;$x2=$xr;$y2=$yb;
  147.         for($x=$xl, $i=0; $x<$xl+$dx && $y<$yt+$dy ; ++$x, ++$y, --$x2, --$y2, ++$i) {
  148.         assert($i<count($colors));
  149.         $this->img->current_color = $colors[$i];            
  150.         $this->img->Rectangle($x,$y,$x2,$y2);
  151.         }
  152.         $this->img->Line($x,$y,$x2,$y2);
  153.         break;
  154.  
  155.         default:
  156.         die("JpGraph Error: Unknown gradient style (=$style).");
  157.         break;
  158.     }
  159.     }
  160.  
  161. //---------------
  162. // PRIVATE METHODS    
  163.     // Add to the image color map the necessary colors to do the transition
  164.     // between the two colors using $numcolors intermediate colors
  165.     function GetColArray($from_color,$to_color,$arr_size,&$colors,$numcols=100) {
  166.     if( $arr_size==0 ) return;
  167.     // If color is give as text get it's corresponding r,g,b values
  168.     $from_color = $this->img->rgb->Color($from_color);
  169.     $to_color = $this->img->rgb->Color($to_color);
  170.         
  171.     $rdelta=($to_color[0]-$from_color[0])/$numcols;
  172.     $gdelta=($to_color[1]-$from_color[1])/$numcols;
  173.     $bdelta=($to_color[2]-$from_color[2])/$numcols;
  174.     $stepspercolor    = $numcols/$arr_size;
  175.     $prevcolnum    = -1;
  176.     for ($i=0; $i<$arr_size; ++$i) {
  177.         $colnum    = floor($stepspercolor*$i);
  178.         if ( $colnum == $prevcolnum ) 
  179.         $colors[$i]    = $colidx;
  180.         else {
  181.         $r = floor($from_color[0] + $colnum*$rdelta);
  182.         $g = floor($from_color[1] + $colnum*$gdelta);
  183.         $b = floor($from_color[2] + $colnum*$bdelta);
  184.         $colidx = $this->img->rgb->Allocate(sprintf("#%02x%02x%02x",$r,$g,$b));
  185.         $colors[$i]    = $colidx;
  186.         }
  187.         $prevcolnum = $colnum;
  188.     }
  189.     }    
  190. } // Class
  191.  
  192.  
  193. //===================================================
  194. // CLASS BarPlot
  195. // Description: Main code to produce a bar plot 
  196. //===================================================
  197. class BarPlot extends Plot {
  198.     var $width=0.4; // in percent of major ticks
  199.     var $abswidth=-1; // Width in absolute pixels
  200.     var $fill_color="lightblue"; // Default is to fill with light blue
  201.     var $ybase=0; // Bars start at 0 
  202.     var $align="center";
  203.     var $grad=false,$grad_style=1;
  204.     var $grad_fromcolor=array(50,50,200),$grad_tocolor=array(255,255,255);
  205.     var $bar_shadow=false;
  206.     var $bar_shadow_color="black";
  207.     var $bar_shadow_hsize=3,$bar_shadow_vsize=3;    
  208.     var $valuepos='top';
  209.     
  210. //---------------
  211. // CONSTRUCTOR
  212.     function BarPlot(&$datay,$datax=false) {
  213.     $this->Plot($datay,$datax);        
  214.     ++$this->numpoints;
  215.     }
  216.  
  217. //---------------
  218. // PUBLIC METHODS    
  219.     
  220.     // Set a drop shadow for the bar (or rather an "up-right" shadow)
  221.     function SetShadow($color="black",$hsize=3,$vsize=3) {
  222.     $this->bar_shadow=true;
  223.     $this->bar_shadow_color=$color;
  224.     $this->bar_shadow_vsize=$vsize;
  225.     $this->bar_shadow_hsize=$hsize;
  226.         
  227.     // Adjust the value margin to compensate for shadow
  228.     $this->value->margin += $vsize;
  229.     }
  230.         
  231.     // DEPRECATED use SetYBase instead
  232.     function SetYMin($aYStartValue) {
  233.     //die("JpGraph Error: Deprecated function SetYMin. Use SetYBase() instead.");        
  234.     $this->ybase=$aYStartValue;
  235.     }
  236.  
  237.     // Specify the base value for the bars
  238.     function SetYBase($aYStartValue) {
  239.     $this->ybase=$aYStartValue;
  240.     }
  241.     
  242.     function Legend(&$graph) {
  243.     if( $this->fill_color && $this->legend!="" ) {
  244.         if( is_array($this->fill_color) )
  245.         $graph->legend->Add($this->legend,$this->fill_color[0],"",0,$this->legendcsimtarget,$this->legendcsimalt);
  246.         else
  247.         $graph->legend->Add($this->legend,$this->fill_color,"",0,$this->legendcsimtarget,$this->legendcsimalt);    
  248.     }
  249.     }
  250.  
  251.     // Gets called before any axis are stroked
  252.     function PreStrokeAdjust(&$graph) {
  253.     parent::PreStrokeAdjust($graph);
  254.  
  255.     // If we are using a log Y-scale we want the base to be at the
  256.     // minimum Y-value unless the user have specifically set some other
  257.     // value than the default.
  258.     if( substr($graph->axtype,-3,3)=="log" && $this->ybase==0 )
  259.         $this->ybase = $graph->yaxis->scale->GetMinVal();
  260.         
  261.     // For a "text" X-axis scale we will adjust the
  262.     // display of the bars a little bit.
  263.     if( substr($graph->axtype,0,3)=="tex" ) {
  264.         // Position the ticks between the bars
  265.         $graph->xaxis->scale->ticks->SetXLabelOffset(0.5,0);
  266.         
  267.         // Center the bars 
  268.         if( $this->align == "center" )
  269.             $graph->SetTextScaleOff(0.5-$this->width/2);                        
  270.         elseif( $this->align == "right" )
  271.             $graph->SetTextScaleOff(1-$this->width);                        
  272.     }
  273.     else {
  274.         // We only set an absolute width for linear and int scale
  275.         // for text scale the width will be set to a fraction of
  276.         // the majstep width.
  277.         if( $this->abswidth == -1 ) // Not set
  278.         // set width to a visuable sensible default
  279.         $this->abswidth = $graph->img->plotwidth/(2*count($this->coords[0]));
  280.     }
  281.     }
  282.  
  283.     function Min() {
  284.     $m = parent::Min();
  285.     if( $m[1] >= $this->ybase )
  286.         $m[1] = $this->ybase;
  287.     return $m;    
  288.     }
  289.  
  290.     function Max() {
  291.     $m = parent::Max();
  292.     if( $m[1] <= $this->ybase )
  293.         $m[1] = $this->ybase;
  294.     return $m;    
  295.     }    
  296.     
  297.     // Specify width as fractions of the major stepo size
  298.     function SetWidth($aFractionWidth) {
  299.     $this->width=$aFractionWidth;
  300.     }
  301.     
  302.     // Specify width in absolute pixels. If specified this
  303.     // overrides SetWidth()
  304.     function SetAbsWidth($aWidth) {
  305.     $this->abswidth=$aWidth;
  306.     }
  307.         
  308.     function SetAlign($aAlign) {
  309.     $this->align=$aAlign;
  310.     }
  311.     
  312.     function SetNoFill() {
  313.     $this->grad = false;
  314.     $this->fill_color=false;
  315.     }
  316.         
  317.     function SetFillColor($aColor) {
  318.     $this->fill_color=$aColor;
  319.     }
  320.     
  321.     function SetFillGradient($from_color,$to_color,$style) {
  322.     $this->grad=true;
  323.     $this->grad_fromcolor=$from_color;
  324.     $this->grad_tocolor=$to_color;
  325.     $this->grad_style=$style;
  326.     }
  327.     
  328.     function SetValuePos($aPos) {
  329.     $this->valuepos = $aPos;
  330.     }
  331.  
  332.     function Stroke(&$img,&$xscale,&$yscale) { 
  333.         
  334.     $numpoints = count($this->coords[0]);
  335.     if( isset($this->coords[1]) ) {
  336.         if( count($this->coords[1])!=$numpoints )
  337.         die("JpGraph Error: Number of X and Y points are not equal.<br>
  338.                     Number of X-points:".count($this->coords[1])."<br>
  339.                     Number of Y-points:$numpoints");
  340.         else
  341.         $exist_x = true;
  342.     }
  343.     else 
  344.         $exist_x = false;
  345.         
  346.         
  347.     $numbars=count($this->coords[0]);
  348.  
  349.     // Use GetMinVal() instead of scale[0] directly since in the case
  350.     // of log scale we get a correct value. Log scales will have negative
  351.     // values for values < 1 while still not representing negative numbers.
  352.     if( $yscale->GetMinVal() >= 0 ) 
  353.         $zp=$yscale->scale_abs[0]; 
  354.     else {
  355.         $zp=$yscale->Translate(0);
  356.     }
  357.     
  358.     if( $this->abswidth > -1 )
  359.         $abswidth=$this->abswidth;
  360.     else
  361.         $abswidth=round($this->width*$xscale->scale_factor,0);
  362.                     
  363.     for($i=0; $i<$numbars; $i++) {
  364.         if( $exist_x ) $x=$this->coords[1][$i];
  365.         else $x=$i;
  366.             
  367.         $x=$xscale->Translate($x);
  368.         
  369.          //if($this->align=="center")
  370.         //$x -= $abswidth/2;
  371.         //elseif($this->align=="right")
  372.         //$x -= $abswidth;        
  373.         
  374.         if( !$xscale->textscale ) {
  375.             if($this->align=="center")
  376.                 $x -= $abswidth/2;
  377.             elseif($this->align=="right")
  378.                 $x -= $abswidth;            
  379.         }
  380.                             
  381.         $pts=array(
  382.         $x,$zp,
  383.         $x,$yscale->Translate($this->coords[0][$i]),
  384.         $x+$abswidth,$yscale->Translate($this->coords[0][$i]),
  385.         $x+$abswidth,$zp);
  386.         if( $this->grad ) {
  387.         $grad = new Gradient($img);
  388.         $grad->FilledRectangle($pts[2],$pts[3],
  389.         $pts[6],$pts[7],
  390.         $this->grad_fromcolor,$this->grad_tocolor,$this->grad_style); 
  391.         }
  392.         elseif( !empty($this->fill_color) ) {
  393.         if(is_array($this->fill_color)) {
  394.             $img->PushColor($this->fill_color[$i % count($this->fill_color)]);
  395.         } else {
  396.             $img->PushColor($this->fill_color);
  397.         }
  398.         $img->FilledPolygon($pts);
  399.         $img->PopColor();
  400.         }
  401.             
  402.         // Remember value of this bar
  403.         $val=$this->coords[0][$i];
  404.             
  405.         if( $this->bar_shadow && $val != 0 ) {
  406.         $ssh = $this->bar_shadow_hsize;
  407.         $ssv = $this->bar_shadow_vsize;
  408.                 // Create points to create a "upper-right" shadow
  409.         if( $val > 0 ) {
  410.             $sp[0]=$pts[6];        $sp[1]=$pts[7];
  411.             $sp[2]=$pts[4];        $sp[3]=$pts[5];
  412.             $sp[4]=$pts[2];        $sp[5]=$pts[3];
  413.             $sp[6]=$pts[2]+$ssh;    $sp[7]=$pts[3]-$ssv;
  414.             $sp[8]=$pts[4]+$ssh;    $sp[9]=$pts[5]-$ssv;
  415.             $sp[10]=$pts[6]+$ssh;    $sp[11]=$pts[7]-$ssv;
  416.         } 
  417.         elseif( $val < 0 ) {
  418.             $sp[0]=$pts[4];        $sp[1]=$pts[5];
  419.             $sp[2]=$pts[6];        $sp[3]=$pts[7];
  420.             $sp[4]=$pts[0];    $sp[5]=$pts[1];
  421.             $sp[6]=$pts[0]+$ssh;    $sp[7]=$pts[1]-$ssv;
  422.             $sp[8]=$pts[6]+$ssh;    $sp[9]=$pts[7]-$ssv;
  423.             $sp[10]=$pts[4]+$ssh;    $sp[11]=$pts[5]-$ssv;
  424.         }
  425.                 
  426.         $img->PushColor($this->bar_shadow_color);
  427.         $img->FilledPolygon($sp);
  428.         $img->PopColor();
  429.         }
  430.             
  431.         // Stroke the outline of the bar
  432.         if( is_array($this->color) )
  433.         $img->SetColor($this->color[$i % count($this->color)]);
  434.         else
  435.         $img->SetColor($this->color);
  436.         $img->SetLineWeight($this->weight);
  437.         $pts[] = $pts[0];
  438.         $pts[] = $pts[1];
  439.         $img->Polygon($pts);
  440.                 
  441.         $x=$pts[2]+($pts[4]-$pts[2])/2;
  442.         if( $this->valuepos=='top' ) {
  443.         $y=$pts[3];
  444.         $this->value->Stroke($img,$val,$x,$y);
  445.         }
  446.         elseif( $this->valuepos=='center' ) {
  447.         $y = ($pts[3] + $pts[1])/2;
  448.         $this->value->SetAlign('center','center');
  449.         $this->value->SetMargin(0);
  450.         $this->value->Stroke($img,$val,$x,$y);
  451.         }
  452.         elseif( $this->valuepos=='bottom' ) {
  453.         $y=$pts[1];
  454.         $this->value->SetMargin(0);
  455.         $this->value->Stroke($img,$val,$x,$y);
  456.         }
  457.         else {
  458.         JpGraphError::Raise('Unknown position for values on bars :'.$this->valuepos);
  459.         die();
  460.         }
  461.         // Create the client side image map
  462.         $rpts = $img->ArrRotate($pts);        
  463.         $csimcoord=round($rpts[0]).", ".round($rpts[1]);
  464.         for( $j=1; $j < 4; ++$j){
  465.         $csimcoord .= ", ".round($rpts[2*$j]).", ".round($rpts[2*$j+1]);
  466.         }                
  467.         $this->csimareas.= '<area shape="poly" coords="'.$csimcoord.'" ';            
  468.         if( !empty($this->csimtargets[$i]) )
  469.         $this->csimareas .= " href=\"".$this->csimtargets[$i]."\"";
  470.         if( !empty($this->csimalts[$i]) ) {
  471.         $sval=sprintf($this->csimalts[$i],$this->coords[0][$i]);
  472.         $this->csimareas .= " alt=\"$sval\" title=\"$sval\" ";
  473.         }
  474.         $this->csimareas .= ">\n";
  475.     }
  476.     return true;
  477.     }
  478. } // Class
  479.  
  480. //===================================================
  481. // CLASS GroupBarPlot
  482. // Description: Produce grouped bar plots
  483. //===================================================
  484. class GroupBarPlot extends BarPlot {
  485.     var $plots;
  486.     var $width=0.7;
  487.     var $nbrplots=0;
  488.     var $numpoints;
  489. //---------------
  490. // CONSTRUCTOR
  491.     function GroupBarPlot($plots) {
  492.     $this->plots = $plots;
  493.     $this->nbrplots = count($plots);
  494.     $this->numpoints = $plots[0]->numpoints;
  495.     }
  496.  
  497. //---------------
  498. // PUBLIC METHODS    
  499.     function Legend(&$graph) {
  500.     $n = count($this->plots);
  501.     for($i=0; $i<$n; ++$i)
  502.         $this->plots[$i]->Legend($graph);
  503.     }
  504.     
  505.     function Min() {
  506.     list($xmin,$ymin) = $this->plots[0]->Min();
  507.     $n = count($this->plots);
  508.     for($i=0; $i<$n; ++$i) {
  509.         list($xm,$ym) = $this->plots[$i]->Min();
  510.         $xmin = max($xmin,$xm);
  511.         $ymin = min($ymin,$ym);
  512.     }
  513.     return array($xmin,$ymin);        
  514.     }
  515.     
  516.     function Max() {
  517.     list($xmax,$ymax) = $this->plots[0]->Max();
  518.     $n = count($this->plots);
  519.     for($i=0; $i<$n; ++$i) {
  520.         list($xm,$ym) = $this->plots[$i]->Max();
  521.         $xmax = max($xmax,$xm);
  522.         $ymax = max($ymax,$ym);
  523.     }
  524.     return array($xmax,$ymax);
  525.     }
  526.     
  527.     function GetCSIMareas() {
  528.     $n = count($this->plots);
  529.     $csimareas='';
  530.     for($i=0; $i < $n; ++$i) {
  531.         $csimareas .= $this->plots[$i]->csimareas;
  532.     }
  533.     return $csimareas;
  534.     }
  535.     
  536.     // Stroke all the bars next to each other
  537.     function Stroke(&$img,&$xscale,&$yscale) { 
  538.     $tmp=$xscale->off;
  539.     $n = count($this->plots);
  540.     for( $i=0; $i<$n; ++$i ) {
  541.         $this->plots[$i]->ymin=$this->ybase;
  542.         $this->plots[$i]->SetWidth($this->width/$this->nbrplots);
  543.         $xscale->off = $tmp+$i*round($xscale->ticks->major_step*$xscale->scale_factor*$this->width/$this->nbrplots);
  544.         $this->plots[$i]->Stroke($img,$xscale,$yscale);
  545.     }
  546.     $xscale->off=$tmp;
  547.     }
  548. } // Class
  549.  
  550. //===================================================
  551. // CLASS AccBarPlot
  552. // Description: Produce accumulated bar plots
  553. //===================================================
  554. class AccBarPlot extends BarPlot {
  555.     var $plots=null,$nbrplots=0,$numpoints=0;
  556. //---------------
  557. // CONSTRUCTOR
  558.     function AccBarPlot($plots) {
  559.     $this->plots = $plots;
  560.     $this->nbrplots = count($plots);
  561.     $this->numpoints = $plots[0]->numpoints;        
  562.     $this->value = new DisplayValue();
  563.     }
  564.  
  565. //---------------
  566. // PUBLIC METHODS    
  567.     function Legend(&$graph) {
  568.     $n = count($this->plots);
  569.     for( $i=$n-1; $i>=0; --$i ) 
  570.         $this->plots[$i]->Legend($graph);
  571.     }
  572.  
  573.     function Max() {
  574.     list($xmax) = $this->plots[0]->Max();
  575.     $nmax=0;
  576.     for($i=0; $i<count($this->plots); ++$i) {
  577.         $n = count($this->plots[$i]->coords[0]);
  578.         $nmax = max($nmax,$n);
  579.         list($x) = $this->plots[$i]->Max();
  580.         $xmax = Max($xmax,$x);
  581.     }
  582.     for( $i = 0; $i < $nmax; $i++ ) {
  583.         // Get y-value for bar $i by adding the
  584.         // individual bars from all the plots added.
  585.         // It would be wrong to just add the
  586.         // individual plots max y-value since that
  587.         // would in most cases give to large y-value.
  588.         $y=$this->plots[0]->coords[0][$i];
  589.         for( $j = 1; $j < $this->nbrplots; $j++ ) {
  590.         $y += $this->plots[ $j ]->coords[0][$i];
  591.         }
  592.         $ymax[$i] = $y;
  593.     }
  594.     $ymax = max($ymax);
  595.  
  596.     // Bar always start at baseline
  597.     if( $ymax <= $this->ybase ) 
  598.         $ymax = $this->ybase;
  599.     return array($xmax,$ymax);
  600.     }
  601.  
  602.     function Min() {
  603.     $nmax=0;
  604.     list($xmin,$ysetmin) = $this->plots[0]->Min();
  605.     for($i=0; $i<count($this->plots); ++$i) {
  606.         $n = count($this->plots[$i]->coords[0]);
  607.         $nmax = max($nmax,$n);
  608.         list($x,$y) = $this->plots[$i]->Min();
  609.         $xmin = Min($xmin,$x);
  610.         $ysetmin = Min($y,$ysetmin);
  611.     }
  612.     for( $i = 0; $i < $nmax; $i++ ) {
  613.         // Get y-value for bar $i by adding the
  614.         // individual bars from all the plots added.
  615.         // It would be wrong to just add the
  616.         // individual plots max y-value since that
  617.         // would in most cases give to large y-value.
  618.         $y=$this->plots[0]->coords[0][$i];
  619.         for( $j = 1; $j < $this->nbrplots; $j++ ) {
  620.         $y += $this->plots[ $j ]->coords[0][$i];
  621.         }
  622.         $ymin[$i] = $y;
  623.     }
  624.     $ymin = Min($ysetmin,Min($ymin));
  625.     // Bar always start at baseline
  626.     if( $ymin >= $this->ybase )
  627.         $ymin = $this->ybase;
  628.     return array($xmin,$ymin);
  629.     }
  630.  
  631.     // Stroke acc bar plot
  632.     function Stroke(&$img,&$xscale,&$yscale) {
  633.     $img->SetLineWeight($this->weight);
  634.     for($i=0; $i<$this->numpoints-1; $i++) {
  635.         $accy = 0;
  636.         $accy_neg = 0; 
  637.         for($j=0; $j<$this->nbrplots; ++$j ) {                
  638.         $img->SetColor($this->plots[$j]->color);
  639.  
  640.         if ($this->plots[$j]->coords[0][$i] > 0) {
  641.             $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy);
  642.             $accyt=$yscale->Translate($accy);
  643.             $accy+=$this->plots[$j]->coords[0][$i];
  644.         } else {
  645.             $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg);
  646.             $accyt=$yscale->Translate($accy_neg);
  647.             $accy_neg+=$this->plots[$j]->coords[0][$i];
  648.         }                
  649.                 
  650.         $xt=$xscale->Translate($i);
  651.  
  652.         //echo "$i => $xt<br>";
  653.         
  654.         if( $this->abswidth > -1 )
  655.             $abswidth=$this->abswidth;
  656.         else
  657.             $abswidth=round($this->width*$xscale->scale_factor,0);
  658.         
  659.         $pts=array($xt,$accyt,$xt,$yt,$xt+$abswidth,$yt,$xt+$abswidth,$accyt);
  660.  
  661.         if( $this->plots[$j]->grad ) {
  662.             $grad = new Gradient($img);
  663.             $grad->FilledRectangle(
  664.             $pts[2],$pts[3],
  665.             $pts[6],$pts[7],
  666.             $this->plots[$j]->grad_fromcolor,
  667.             $this->plots[$j]->grad_tocolor,
  668.             $this->plots[$j]->grad_style);                
  669.         } elseif ($this->plots[$j]->fill_color ) {
  670.             $img->SetColor($this->plots[$j]->fill_color);
  671.             $img->FilledPolygon($pts);
  672.             $img->SetColor($this->plots[$j]->color);
  673.         }                  
  674.  
  675.         if( $this->bar_shadow ) {
  676.             $ssh = $this->bar_shadow_hsize;
  677.             $ssv = $this->bar_shadow_vsize;
  678.             // Create points to create a "upper-right" shadow
  679.             $sp[0]=$pts[6];        $sp[1]=$pts[7];
  680.             $sp[2]=$pts[4];        $sp[3]=$pts[5];
  681.             $sp[4]=$pts[2];    $sp[5]=$pts[3];
  682.             $sp[6]=$pts[2]+$ssh;    $sp[7]=$pts[3]-$ssv;
  683.             $sp[8]=$pts[4]+$ssh;    $sp[9]=$pts[5]-$ssv;
  684.             $sp[10]=$pts[6]+$ssh;    $sp[11]=$pts[7]-$ssv;
  685.             $img->SetColor($this->bar_shadow_color);
  686.             $img->FilledPolygon($sp,4);
  687.         }
  688.  
  689.         if( $i < count($this->plots[$j]->csimtargets) ) {
  690.             // Create the client side image map
  691.             $rpts = $img->ArrRotate($pts);        
  692.             $csimcoord=round($rpts[0]).", ".round($rpts[1]);
  693.             for( $k=1; $k < 4; ++$k){
  694.             $csimcoord .= ", ".round($rpts[2*$k]).", ".round($rpts[2*$k+1]);
  695.             }                
  696.             $this->csimareas.= '<area shape="poly" coords="'.$csimcoord.'" '; 
  697.             $this->csimareas.= " href=\"".$this->plots[$j]->csimtargets[$i]."\"";
  698.             if( !empty($this->plots[$j]->csimalts[$i]) ) {
  699.             $sval=sprintf($this->plots[$j]->csimalts[$i],$this->plots[$j]->coords[0][$i]);
  700.             $this->csimareas .= " alt=\"$sval\" title=\"$sval\" ";
  701.             }
  702.             $this->csimareas .= ">\n";                
  703.         }
  704.         $pts[] = $pts[0];
  705.         $pts[] = $pts[1];
  706.         $img->Polygon($pts);
  707.         }
  708.         
  709.     
  710.         $x=$pts[2]+($pts[4]-$pts[2])/2;
  711.         $y=$yscale->Translate($accy);            
  712.         if($this->bar_shadow) $x += $ssh;
  713.         $this->value->Stroke($img,$accy,$x,$y);
  714.  
  715.         $accy = 0;
  716.         $accy_neg = 0; 
  717.         for($j=0; $j<$this->nbrplots; ++$j ) {                
  718.         if ($this->plots[$j]->coords[0][$i] > 0) {
  719.             $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy);
  720.             $accyt=$yscale->Translate($accy);
  721.             $y = $accyt-($accyt-$yt)/2;
  722.             $accy+=$this->plots[$j]->coords[0][$i];
  723.         } else {
  724.             $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg);
  725.             $accyt=$yscale->Translate($accy_neg);
  726.             $y=0;
  727.             $accy_neg+=$this->plots[$j]->coords[0][$i];
  728.         }    
  729.         $this->plots[$j]->value->SetAlign("center","center");
  730.         $this->plots[$j]->value->SetMargin(0);
  731.         $this->plots[$j]->value->Stroke($img,$this->plots[$j]->coords[0][$i],$x,$y);
  732.         }
  733.  
  734.     }
  735.     return true;
  736.     }
  737. } // Class
  738.  
  739. /* EOF */
  740. ?>
  741.