]> git.llucax.com Git - mecon/meconlib.git/blob - lib/MECON/Graph/external/jpgraph/src/jpgraph_polar.php
- Correccion de bugs
[mecon/meconlib.git] / lib / MECON / Graph / external / jpgraph / src / jpgraph_polar.php
1 <?php
2 /*=======================================================================
3 // File:        JPGRAPH_POLAR.PHP
4 // Description: Polar plot extension for JpGraph
5 // Created:     2003-02-02
6 // Author:      Johan Persson (johanp@aditus.nu)
7 // Ver:         $Id: jpgraph_polar.php,v 1.2.2.1 2003/08/07 19:31:34 aditus Exp $
8 //
9 // License:     This code is released under QPL
10 // Copyright (C) 2003 Johan Persson
11 //========================================================================
12 */
13 require_once "jpgraph_log.php";
14
15
16 DEFINE('POLAR_360',1);
17 DEFINE('POLAR_180',2);
18
19 //
20 // Note. Don't attempt to make sense of this code.
21 // In order not to have to be able to inherit the scaling code
22 // from the main graph package we have had to make some "tricks" since
23 // the original scaling and axis was not designed to do what is
24 // required here.
25 // There were two option. 1: Re-implement everything and get a clean design
26 // and 2: do some "small" trickery and be able to inherit most of
27 // the functionlity from the main graph package. 
28 // We choose 2: here in order to save some time.
29 // 
30
31 //--------------------------------------------------------------------------
32 // class PolarPlot
33 //--------------------------------------------------------------------------
34 class PolarPlot {
35     var $numpoints=0;
36     var $iColor='navy',$iFillColor='';
37     var $iLineWeight=1;
38     var $coord=null;
39     var $legendcsimtarget='';
40     var $legendcsimalt='';
41     var $legend="";
42     var $csimtargets=array();   // Array of targets for CSIM
43     var $csimareas="";                  // Resultant CSIM area tags     
44     var $csimalts=null;                 // ALT:s for corresponding target
45     var $line_style='solid',$mark;
46
47     function PolarPlot($aData) {
48         $n = count($aData);
49         if( $n & 1 ) {
50             JpGraphError::Raise('Polar plots must have an even number of data point. Each data point is a tuple (angle,radius).');
51         }
52         $this->numpoints = $n/2;
53         $this->coord = $aData;
54         $this->mark = new PlotMark();
55     }
56
57     function SetWeight($aWeight) {
58         $this->iLineWeight = $aWeight;
59     }
60
61     function SetColor($aColor){
62         $this->iColor = $aColor;
63     }
64
65     function SetFillColor($aColor){
66         $this->iFillColor = $aColor;
67     }
68
69     function Max() {
70         $m = $this->coord[1];
71         $i=1;
72         while( $i < $this->numpoints ) {
73             $m = max($m,$this->coord[2*$i+1]);  
74             ++$i;
75         } 
76         return $m;
77     }
78     // Set href targets for CSIM        
79     function SetCSIMTargets($aTargets,$aAlts=null) {
80         $this->csimtargets=$aTargets;
81         $this->csimalts=$aAlts;         
82     }
83         
84     // Get all created areas
85     function GetCSIMareas() {
86         return $this->csimareas;
87     }   
88         
89     function SetLegend($aLegend,$aCSIM="",$aCSIMAlt="") {
90         $this->legend = $aLegend;
91         $this->legendcsimtarget = $aCSIM;
92         $this->legendcsimalt = $aCSIMAlt;
93     }
94
95     // Private methods
96
97     function Legend(&$aGraph) {
98         $color = $this->iColor ;
99         if( $this->legend != "" ) {
100             if( $this->iFillColor!='' ) {
101                 $color = $this->iFillColor;
102                 $aGraph->legend->Add($this->legend,$color,$this->mark,0,
103                                      $this->legendcsimtarget,$this->legendcsimalt);    
104             }
105             else {
106                 $aGraph->legend->Add($this->legend,$color,$this->mark,$this->line_style,
107                                      $this->legendcsimtarget,$this->legendcsimalt);    
108             }
109         }
110     }
111
112     function Stroke($img,$scale) {
113
114         $i=0;
115         $p=array();
116         $this->csimareas='';
117         while($i < $this->numpoints) {
118             list($x1,$y1) = $scale->PTranslate($this->coord[2*$i],$this->coord[2*$i+1]);
119             $p[2*$i] = $x1;
120             $p[2*$i+1] = $y1;
121         
122             if( isset($this->csimtargets[$i]) ) {
123                 $this->mark->SetCSIMTarget($this->csimtargets[$i]);
124                 $this->mark->SetCSIMAlt($this->csimalts[$i]);
125                 $this->mark->SetCSIMAltVal($this->coord[2*$i], $this->coord[2*$i+1]);
126                 $this->mark->Stroke($img,$x1,$y1);
127                 $this->csimareas .= $this->mark->GetCSIMAreas();
128             }
129             else
130                 $this->mark->Stroke($img,$x1,$y1);
131
132             ++$i;
133         }
134
135         if( $this->iFillColor != '' ) {
136             $img->SetColor($this->iFillColor);
137             $img->FilledPolygon($p);
138         }
139         $img->SetLineWeight($this->iLineWeight);
140         $img->SetColor($this->iColor);
141         $img->Polygon($p,$this->iFillColor!='');
142     }
143 }
144
145 //--------------------------------------------------------------------------
146 // class PolarAxis
147 //--------------------------------------------------------------------------
148 class PolarAxis extends Axis {
149     var $angle_step=15,$angle_color='lightgray',$angle_label_color='black';
150     var $angle_fontfam=FF_FONT1,$angle_fontstyle=FS_NORMAL,$angle_fontsize=10;
151     var $angle_fontcolor = 'navy';
152     var $gridminor_color='lightgray',$gridmajor_color='lightgray';
153     var $show_minor_grid = false, $show_major_grid = true ;
154     var $show_angle_mark=true, $show_angle_grid=true, $show_angle_label=true;
155     var $angle_tick_len=3, $angle_tick_len2=3, $angle_tick_color='black';
156     var $show_angle_tick=true;
157     var $radius_tick_color='black';
158
159     function PolarAxis(&$img,&$aScale) {
160         parent::Axis($img,$aScale);
161     }
162
163     function ShowAngleDegreeMark($aFlg=true) {
164         $this->show_angle_mark = $aFlg;
165     }
166
167     function SetAngleStep($aStep) {
168         $this->angle_step=$aStep;
169     }
170
171     function HideTicks($aFlg=true,$aAngleFlg=true) {
172         parent::HideTicks($aFlg,$aFlg);
173         $this->show_angle_tick = !$aAngleFlg;
174     }
175
176     function ShowAngleLabel($aFlg=true) {
177         $this->show_angle_label = $aFlg;
178     }
179
180     function ShowGrid($aMajor=true,$aMinor=false,$aAngle=true) {
181         $this->show_minor_grid = $aMinor;
182         $this->show_major_grid = $aMajor;
183         $this->show_angle_grid = $aAngle ;
184     }
185
186     function SetAngleFont($aFontFam,$aFontStyle=FS_NORMAL,$aFontSize=10) {
187         $this->angle_fontfam = $aFontFam;
188         $this->angle_fontstyle = $aFontStyle;
189         $this->angle_fontsize = $aFontSize;
190     }
191
192     function SetColor($aColor,$aRadColor='',$aAngleColor='') {
193         if( $aAngleColor == '' )
194             $aAngleColor=$aColor;
195         parent::SetColor($aColor,$aRadColor);
196         $this->angle_fontcolor = $aAngleColor;
197     }
198
199     function SetGridColor($aMajorColor,$aMinorColor='',$aAngleColor='') {
200         if( $aMinorColor == '' ) 
201             $aMinorColor = $aMajorColor;
202         if( $aAngleColor == '' ) 
203             $aAngleColor = $aMajorColor;
204
205         $this->gridminor_color = $aMinorColor;
206         $this->gridmajor_color = $aMajorColor;
207         $this->angle_color = $aAngleColor;
208     }
209
210     function SetTickColors($aRadColor,$aAngleColor='') {
211         $this->radius_tick_color = $aRadColor;
212         $this->angle_tick_color = $aAngleColor;
213     }
214     
215     // Private methods
216     function StrokeGrid($pos) {
217         $x = round($this->img->left_margin + $this->img->plotwidth/2);
218         $this->scale->ticks->Stroke($this->img,$this->scale,$pos);
219
220         // Stroke the minor arcs 
221         $pmin = array();
222         $p = $this->scale->ticks->ticks_pos;
223         $n = count($p);
224         $i = 0;
225         $this->img->SetColor($this->gridminor_color);
226         while( $i < $n ) {
227             $r = $p[$i]-$x+1;
228             $pmin[]=$r;
229             if( $this->show_minor_grid ) {
230                 $this->img->Circle($x,$pos,$r);
231             }
232             $i++;
233         }
234         
235         $limit = max($this->img->plotwidth,$this->img->plotheight)*1.4 ;
236         while( $r < $limit ) {
237             $off = $r;
238             $i=1;
239             $r = $off + round($p[$i]-$x+1);
240             while( $r < $limit && $i < $n ) {
241                 $r = $off+$p[$i]-$x;
242                 $pmin[]=$r;
243                 if( $this->show_minor_grid ) {
244                     $this->img->Circle($x,$pos,$r);
245                 }
246                 $i++;
247             }
248         }
249
250         // Stroke the major arcs 
251         if( $this->show_major_grid ) {
252             // First determine how many minor step on
253             // every major step. We have recorded the minor radius
254             // in pmin and use these values. This is done in order
255             // to avoid rounding errors if we were to recalculate the
256             // different major radius.
257             $pmaj = $this->scale->ticks->maj_ticks_pos;
258             $p = $this->scale->ticks->ticks_pos;
259             if( $this->scale->name == 'lin' ) {
260                 $step=round(($pmaj[1] - $pmaj[0])/($p[1] - $p[0]));
261             }
262             else {
263                 $step=9;
264             }
265             $n = round(count($pmin)/$step);
266             $i = 0;
267             $this->img->SetColor($this->gridmajor_color);
268             $limit = max($this->img->plotwidth,$this->img->plotheight)*1.4 ;
269             $off = $r;
270             $i=0;
271             $r = $pmin[$i*$step];
272             while( $r < $limit && $i < $n ) {
273                 $r = $pmin[$i*$step];
274                 $this->img->Circle($x,$pos,$r);
275                 $i++;
276             }
277         }
278
279         // Draw angles
280         if( $this->show_angle_grid ) {
281             $this->img->SetColor($this->angle_color);
282             $d = max($this->img->plotheight,$this->img->plotwidth)*1.4 ;
283             $a = 0;
284             $p = $this->scale->ticks->ticks_pos;
285             $start_radius = $p[1]-$x;
286             while( $a < 360 ) {
287                 if( $a == 90 || $a == 270 ) {
288                     // Make sure there are no rounding problem with
289                     // exactly vertical lines
290                     $this->img->Line($x+$start_radius*cos($a/180*M_PI)+1,
291                                      $pos-$start_radius*sin($a/180*M_PI),
292                                      $x+$start_radius*cos($a/180*M_PI)+1,
293                                      $pos-$d*sin($a/180*M_PI));
294                     
295                 }
296                 else {
297                     $this->img->Line($x+$start_radius*cos($a/180*M_PI)+1,
298                                      $pos-$start_radius*sin($a/180*M_PI),
299                                      $x+$d*cos($a/180*M_PI),
300                                      $pos-$d*sin($a/180*M_PI));
301                 }
302                 $a += $this->angle_step;
303             }
304         }
305     }
306
307     function StrokeAngleLabels($pos,$type) {
308
309         if( !$this->show_angle_label ) 
310             return;
311         
312         $x0 = round($this->img->left_margin+$this->img->plotwidth/2)+1;
313
314         $d = max($this->img->plotwidth,$this->img->plotheight)*1.42;
315         $a = $this->angle_step;
316         $t = new Text();
317         $t->SetColor($this->angle_fontcolor);
318         $t->SetFont($this->angle_fontfam,$this->angle_fontstyle,$this->angle_fontsize);
319         $xright = $this->img->width - $this->img->right_margin;
320         $ytop = $this->img->top_margin;
321         $xleft = $this->img->left_margin;
322         $ybottom = $this->img->height - $this->img->bottom_margin;
323         $ha = 'left';
324         $va = 'center';
325         $w = $this->img->plotwidth/2;
326         $h = $this->img->plotheight/2;
327         $xt = $x0; $yt = $pos;
328         $margin=5;
329
330         $tl  = $this->angle_tick_len ; // Outer len
331         $tl2 = $this->angle_tick_len2 ; // Interior len
332
333         $this->img->SetColor($this->angle_tick_color);
334         $rot90 = $this->img->a == 90 ;
335
336         if( $type == POLAR_360 ) {
337             $ca1 = atan($h/$w)/M_PI*180;
338             $ca2 = 180-$ca1;
339             $ca3 = $ca1+180;
340             $ca4 = 360-$ca1;
341             $end = 360;
342             while( $a < $end ) {
343                 $ca = cos($a/180*M_PI);
344                 $sa = sin($a/180*M_PI);
345                 $x = $d*$ca;
346                 $y = $d*$sa;
347                 $xt=1000;$yt=1000;
348                 if( $a <= $ca1 || $a >= $ca4 ) {
349                     $yt = $pos - $w * $y/$x;
350                     $xt = $xright + $margin;
351                     if( $rot90 ) {
352                         $ha = 'center';
353                         $va = 'top';
354                     }
355                     else {
356                         $ha = 'left';
357                         $va = 'center';
358                     }
359                     $x1=$xright-$tl2; $x2=$xright+$tl;
360                     $y1=$y2=$yt;
361                 }
362                 elseif( $a > $ca1 && $a < $ca2 ) { 
363                     $xt = $x0 + $h * $x/$y;
364                     $yt = $ytop - $margin;
365                     if( $rot90 ) {
366                         $ha = 'left';
367                         $va = 'center';
368                     }
369                     else {
370                         $ha = 'center';
371                         $va = 'bottom';
372                     }
373                     $y1=$ytop+$tl2;$y2=$ytop-$tl;
374                     $x1=$x2=$xt;
375                 }
376                 elseif( $a >= $ca2 && $a <= $ca3 ) { 
377                     $yt = $pos + $w * $y/$x;
378                     $xt = $xleft - $margin;
379                     if( $rot90 ) {
380                         $ha = 'center';
381                         $va = 'bottom';
382                     }
383                     else {
384                         $ha = 'right';
385                         $va = 'center';
386                     }
387                     $x1=$xleft+$tl2;$x2=$xleft-$tl;
388                     $y1=$y2=$yt;
389                 }
390                 else { 
391                     $xt = $x0 - $h * $x/$y;
392                     $yt = $ybottom + $margin;
393                     if( $rot90 ) {
394                         $ha = 'right';
395                         $va = 'center';
396                     }
397                     else {
398                         $ha = 'center';
399                         $va = 'top';
400                     }
401                     $y1=$ybottom-$tl2;$y2=$ybottom+$tl;
402                     $x1=$x2=$xt;
403                 }
404                 if( $a != 0 && $a != 180 ) {
405                     $t->Align($ha,$va);
406                     if( $this->show_angle_mark )
407                         $a .= '°';
408                     $t->Set($a);
409                     $t->Stroke($this->img,$xt,$yt);   
410                     if( $this->show_angle_tick )
411                         $this->img->Line($x1,$y1,$x2,$y2);
412                 }
413                 $a += $this->angle_step;
414             }
415         }
416         else {
417             // POLAR_HALF
418             $ca1 = atan($h/$w*2)/M_PI*180;
419             $ca2 = 180-$ca1;
420             $end = 180;     
421             while( $a < $end ) {
422                 $ca = cos($a/180*M_PI);
423                 $sa = sin($a/180*M_PI);
424                 $x = $d*$ca;
425                 $y = $d*$sa;
426                 if( $a <= $ca1 ) {
427                     $yt = $pos - $w * $y/$x;
428                     $xt = $xright + $margin;
429                     if( $rot90 ) {
430                         $ha = 'center';
431                         $va = 'top';
432                     }
433                     else {
434                         $ha = 'left';
435                         $va = 'center';
436                     }
437                     $x1=$xright-$tl2; $x2=$xright+$tl;
438                     $y1=$y2=$yt;
439                 }
440                 elseif( $a > $ca1 && $a < $ca2 ) { 
441                     $xt = $x0 + 2*$h * $x/$y;
442                     $yt = $ytop - $margin;
443                     if( $rot90 ) {
444                         $ha = 'left';
445                         $va = 'center';
446                     }
447                     else {
448                         $ha = 'center';
449                         $va = 'bottom';
450                     }
451                     $y1=$ytop+$tl2;$y2=$ytop-$tl;
452                     $x1=$x2=$xt;
453                 }
454                 elseif( $a >= $ca2 ) { 
455                     $yt = $pos + $w * $y/$x;
456                     $xt = $xleft - $margin;
457                     if( $rot90 ) {
458                         $ha = 'center';
459                         $va = 'bottom';
460                     }
461                     else {
462                         $ha = 'right';
463                         $va = 'center';
464                     }
465                     $x1=$xleft+$tl2;$x2=$xleft-$tl;
466                     $y1=$y2=$yt;
467                 }
468                 $t->Align($ha,$va);
469                 if( $this->show_angle_mark )
470                     $a .= '°';
471                 $t->Set($a);
472                 $t->Stroke($this->img,$xt,$yt);  
473                 if( $this->show_angle_tick )
474                     $this->img->Line($x1,$y1,$x2,$y2);  
475                 $a += $this->angle_step;
476             }
477         }
478     }
479
480     function Stroke($pos) {
481
482         $this->img->SetLineWeight($this->weight);
483         $this->img->SetColor($this->color);             
484         $this->img->SetFont($this->font_family,$this->font_style,$this->font_size);
485         if( !$this->hide_line ) 
486             $this->img->FilledRectangle($this->img->left_margin,$pos,
487                      $this->img->width-$this->img->right_margin,$pos+$this->weight-1);
488         $y=$pos+$this->img->GetFontHeight()+$this->title_margin+$this->title->margin;
489         if( $this->title_adjust=="high" )
490             $this->title->Pos($this->img->width-$this->img->right_margin,$y,"right","top");
491         elseif( $this->title_adjust=="middle" || $this->title_adjust=="center" ) 
492             $this->title->Pos(($this->img->width-$this->img->left_margin-
493                                $this->img->right_margin)/2+$this->img->left_margin,
494                               $y,"center","top");
495         elseif($this->title_adjust=="low")
496             $this->title->Pos($this->img->left_margin,$y,"left","top");
497         else {  
498             JpGraphError::Raise('Unknown alignment specified for X-axis title. ('.
499                                 $this->title_adjust.')');
500         }
501
502         $this->StrokeLabels($pos,false);
503         $this->img->SetColor($this->radius_tick_color);
504         $this->scale->ticks->Stroke($this->img,$this->scale,$pos);
505
506         //
507         // Mirror the positions for the left side of the scale
508         //
509         $mid = 2*($this->img->left_margin+$this->img->plotwidth/2);
510         $n = count($this->scale->ticks->ticks_pos);
511         $i=0;
512         while( $i < $n ) {
513             $this->scale->ticks->ticks_pos[$i] = 
514                 $mid-$this->scale->ticks->ticks_pos[$i] ;
515             ++$i;
516         }
517
518         $n = count($this->scale->ticks->maj_ticks_pos);
519         $i=0;
520         while( $i < $n ) {
521             $this->scale->ticks->maj_ticks_pos[$i] = 
522                 $mid-$this->scale->ticks->maj_ticks_pos[$i] ;
523             ++$i;
524         }
525         
526         $n = count($this->scale->ticks->maj_ticklabels_pos);
527         $i=1;
528         while( $i < $n ) {
529             $this->scale->ticks->maj_ticklabels_pos[$i] =
530                 $mid-$this->scale->ticks->maj_ticklabels_pos[$i] ;
531             ++$i;
532         }
533
534         // Draw the left side of the scale
535         $n = count($this->scale->ticks->ticks_pos);
536         $yu = $pos - $this->scale->ticks->direction*$this->scale->ticks->GetMinTickAbsSize();
537
538
539         // Minor ticks
540         $i=1;
541         while( $i < $n/2 ) {
542             $x = round($this->scale->ticks->ticks_pos[$i]) ;
543             $this->img->Line($x,$pos,$x,$yu);
544             ++$i;
545         }
546
547         $n = count($this->scale->ticks->maj_ticks_pos);
548         $yu = $pos - $this->scale->ticks->direction*$this->scale->ticks->GetMajTickAbsSize();
549
550
551         // Major ticks
552         $i=1;
553         while( $i < $n/2 ) {
554             $x = round($this->scale->ticks->maj_ticks_pos[$i]) ;
555             $this->img->Line($x,$pos,$x,$yu);
556             ++$i;
557         }
558
559         $this->StrokeLabels($pos,false);
560         $this->title->Stroke($this->img);       
561     }
562 }
563
564 class PolarScale extends LinearScale {
565     var $graph;
566     function PolarScale($aMax=0,&$graph) {
567         parent::LinearScale(0,$aMax,'x');
568         $this->graph = &$graph;
569     }
570
571     function _Translate($v) {
572         return parent::Translate($v);
573     }
574
575     function PTranslate($aAngle,$aRad) {
576         
577         $m = $this->scale[1];
578         $w = $this->graph->img->plotwidth/2;
579         $aRad = $aRad/$m*$w;
580
581         $x = cos( $aAngle/180 * M_PI ) * $aRad;
582         $y = sin( $aAngle/180 * M_PI ) * $aRad;
583
584         $x += $this->_Translate(0);
585
586         if( $this->graph->iType == POLAR_360 ) {
587             $y = ($this->graph->img->top_margin + $this->graph->img->plotheight/2) - $y;
588         }
589         else {
590             $y = ($this->graph->img->top_margin + $this->graph->img->plotheight) - $y;
591         }
592         return array($x,$y);
593     }
594 }
595
596 class PolarLogScale extends LogScale {
597     var $graph;
598     function PolarLogScale($aMax=1,&$graph) {
599         parent::LogScale(0,$aMax,'x');
600         $this->graph = &$graph;
601         $this->ticks->SetLabelLogType(LOGLABELS_MAGNITUDE);
602
603     }
604
605     function PTranslate($aAngle,$aRad) {
606
607         if( $aRad == 0 ) 
608             $aRad = 1;
609         $aRad = log10($aRad);
610         $m = $this->scale[1];
611         $w = $this->graph->img->plotwidth/2;
612         $aRad = $aRad/$m*$w;
613
614         $x = cos( $aAngle/180 * M_PI ) * $aRad;
615         $y = sin( $aAngle/180 * M_PI ) * $aRad;
616
617         $x += $w+$this->graph->img->left_margin;//$this->_Translate(0);
618         if( $this->graph->iType == POLAR_360 ) {
619             $y = ($this->graph->img->top_margin + $this->graph->img->plotheight/2) - $y;
620         }
621         else {
622             $y = ($this->graph->img->top_margin + $this->graph->img->plotheight) - $y;
623         }
624         return array($x,$y);
625     }
626 }
627
628 class PolarGraph extends Graph {
629     var $scale;
630     var $iType=POLAR_360;
631     var $axis;
632     
633     function PolarGraph($aWidth=300,$aHeight=200,$aCachedName="",$aTimeOut=0,$aInline=true) {
634         parent::Graph($aWidth,$aHeight,$aCachedName,$aTimeOut,$aInline) ;
635         $this->SetDensity(TICKD_DENSE);
636         $this->SetBox();
637         $this->SetMarginColor('white');
638     }
639
640     function SetDensity($aDense) {
641         $this->SetTickDensity(TICKD_NORMAL,$aDense);
642     }
643
644     function Set90AndMargin($lm=0,$rm=0,$tm=0,$bm=0) {
645         $adj = ($this->img->height - $this->img->width)/2;
646         $this->SetAngle(90);
647         $this->img->SetMargin($lm-$adj,$rm-$adj,$tm+$adj,$bm+$adj);
648         $this->img->SetCenter(floor($this->img->width/2),floor($this->img->height/2));
649         $this->axis->SetLabelAlign('right','center');
650         //JpGraphError::Raise('Set90AndMargin() is not supported for polar graphs.');
651     }
652
653     function SetScale($aScale,$rmax=0) {
654         if( $aScale == 'lin' ) 
655             $this->scale = new PolarScale($rmax,$this);
656         elseif( $aScale == 'log' ) {
657             $this->scale = new PolarLogScale($rmax,$this);
658         }
659         else {
660             JpGraphError::Raise('Unknown scale type for polar graph. Must be "lin" or "log"');
661         }
662
663         $this->scale->Init($this->img);
664         $this->axis = new PolarAxis($this->img,$this->scale);
665         $this->SetMargin(40,40,50,40);
666     }
667
668     function SetType($aType) {
669         $this->iType = $aType;
670     }
671
672     function SetPlotSize($w,$h) {
673         $this->SetMargin(($this->img->width-$w)/2,($this->img->width-$w)/2,
674                          ($this->img->height-$h)/2,($this->img->height-$h)/2);
675     }
676
677     // Private methods
678     function GetPlotsMax() {
679         $n = count($this->plots);
680         $m = $this->plots[0]->Max();
681         $i=1;
682         while($i < $n) {
683             $m = max($this->plots[$i]->Max());
684             ++$i;
685         }
686         return $m;
687     }
688
689     function Stroke($aStrokeFileName="") {
690
691         // Start by adjusting the margin so that potential titles will fit.
692         $this->AdjustMarginsForTitles();
693             
694         // If the filename is the predefined value = '_csim_special_'
695         // we assume that the call to stroke only needs to do enough
696         // to correctly generate the CSIM maps.
697         // We use this variable to skip things we don't strictly need
698         // to do to generate the image map to improve performance
699         // a best we can. Therefor you will see a lot of tests !$_csim in the
700         // code below.
701         $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE);
702
703         // We need to know if we have stroked the plot in the
704         // GetCSIMareas. Otherwise the CSIM hasn't been generated
705         // and in the case of GetCSIM called before stroke to generate
706         // CSIM without storing an image to disk GetCSIM must call Stroke.
707         $this->iHasStroked = true;
708
709         //Check if we should autoscale axis
710         if( !$this->scale->IsSpecified() && count($this->plots)>0 ) {
711             $max = $this->GetPlotsMax();
712             $t1 = $this->img->plotwidth;
713             $this->img->plotwidth /= 2;
714             $t2 = $this->img->left_margin;
715             $this->img->left_margin += $this->img->plotwidth+1;
716             $this->scale->AutoScale($this->img,0,$max,
717                                      $this->img->plotwidth/$this->xtick_factor/2);
718             $this->img->plotwidth = $t1;
719             $this->img->left_margin = $t2;
720         }
721         else {
722             // The tick calculation will use the user suplied min/max values to determine
723             // the ticks. If auto_ticks is false the exact user specifed min and max
724             // values will be used for the scale. 
725             // If auto_ticks is true then the scale might be slightly adjusted
726             // so that the min and max values falls on an even major step.
727             //$min = 0;
728             $max = $this->scale->scale[1];
729             $t1 = $this->img->plotwidth;
730             $this->img->plotwidth /= 2;
731             $t2 = $this->img->left_margin;
732             $this->img->left_margin += $this->img->plotwidth+1;
733             $this->scale->AutoScale($this->img,0,$max,
734                                      $this->img->plotwidth/$this->xtick_factor/2);
735             $this->img->plotwidth = $t1;
736             $this->img->left_margin = $t2;
737         }
738
739         if( $this->iType ==  POLAR_180 ) 
740             $pos = $this->img->height - $this->img->bottom_margin;
741         else
742             $pos = $this->img->plotheight/2 + $this->img->top_margin;
743
744
745         if( !$_csim ) {
746             $this->StrokePlotArea();
747         }
748
749         $this->iDoClipping = true;
750
751         if( $this->iDoClipping ) {
752             $oldimage = $this->img->CloneCanvasH();
753         }
754
755         if( !$_csim ) {
756             $this->axis->StrokeGrid($pos);
757         }
758
759         // Stroke all plots for Y1 axis
760         for($i=0; $i < count($this->plots); ++$i) {
761             $this->plots[$i]->Stroke($this->img,$this->scale);
762         }                                               
763
764
765         if( $this->iDoClipping ) {
766             // Clipping only supports graphs at 0 and 90 degrees
767             if( $this->img->a == 0  ) {
768                 $this->img->CopyCanvasH($oldimage,$this->img->img,
769                                         $this->img->left_margin,$this->img->top_margin,
770                                         $this->img->left_margin,$this->img->top_margin,
771                                         $this->img->plotwidth+1,$this->img->plotheight+1);
772             }
773             elseif( $this->img->a == 90 ) {
774                 $adj = round(($this->img->height - $this->img->width)/2);
775                 $this->img->CopyCanvasH($oldimage,$this->img->img,
776                                         $this->img->bottom_margin-$adj,$this->img->left_margin+$adj,
777                                         $this->img->bottom_margin-$adj,$this->img->left_margin+$adj,
778                                         $this->img->plotheight,$this->img->plotwidth);
779             }
780             $this->img->Destroy();
781             $this->img->SetCanvasH($oldimage);
782         }
783
784         if( !$_csim ) {
785             $this->axis->Stroke($pos);
786             $this->axis->StrokeAngleLabels($pos,$this->iType);
787         }
788
789         if( !$_csim ) {
790             $this->StrokePlotBox();
791             $this->footer->Stroke($this->img);
792
793             // The titles and legends never gets rotated so make sure
794             // that the angle is 0 before stroking them                         
795             $aa = $this->img->SetAngle(0);
796             $this->StrokeTitles();
797         }
798
799         for($i=0; $i < count($this->plots) ; ++$i ) {
800             $this->plots[$i]->Legend($this);
801         }
802
803         $this->legend->Stroke($this->img);              
804
805         if( !$_csim ) {
806
807             $this->StrokeTexts();       
808             $this->img->SetAngle($aa);  
809                         
810             // Draw an outline around the image map     
811             if(JPG_DEBUG)
812                 $this->DisplayClientSideaImageMapAreas();               
813             
814             // Adjust the appearance of the image
815             $this->AdjustSaturationBrightnessContrast();
816
817             // If the filename is given as the special "__handle"
818             // then the image handler is returned and the image is NOT
819             // streamed back
820             if( $aStrokeFileName == _IMG_HANDLER ) {
821                 return $this->img->img;
822             }
823             else {
824                 // Finally stream the generated picture                                 
825                 $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,
826                                            $aStrokeFileName);           
827             }
828         }
829     }
830 }
831
832
833
834 ?>