Subversion Repositories Sites.tela-botanica.org

Rev

Details | Last modification | View Log | RSS feed

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