source: trunk/client/modules/Elezioni/grafici/jpgraph_radar.php@ 417

Last change on this file since 417 was 284, checked in by roby, 6 years ago
File size: 28.1 KB
RevLine 
[2]1<?php
2/*=======================================================================
[284]3 // File: JPGRAPH_RADAR.PHP
4 // Description: Radar plot extension for JpGraph
5 // Created: 2001-02-04
6 // Ver: $Id: jpgraph_radar.php 1783 2009-08-25 11:41:01Z ljp $
7 //
8 // Copyright (c) Asial Corporation. All rights reserved.
9 //========================================================================
10 */
[2]11
12require_once('jpgraph_plotmark.inc.php');
13
[284]14//===================================================
15// CLASS RadarLogTicks
16// Description: Logarithmic ticks
17//===================================================
[2]18class RadarLogTicks extends Ticks {
[284]19
20 function __construct() {
21 // Empty
[2]22 }
23
24 function Stroke($aImg,&$grid,$aPos,$aAxisAngle,$aScale,&$aMajPos,&$aMajLabel) {
[284]25 $start = $aScale->GetMinVal();
26 $limit = $aScale->GetMaxVal();
27 $nextMajor = 10*$start;
28 $step = $nextMajor / 10.0;
29 $count=1;
[2]30
[284]31 $ticklen_maj=5;
32 $dx_maj=round(sin($aAxisAngle)*$ticklen_maj);
33 $dy_maj=round(cos($aAxisAngle)*$ticklen_maj);
34 $ticklen_min=3;
35 $dx_min=round(sin($aAxisAngle)*$ticklen_min);
36 $dy_min=round(cos($aAxisAngle)*$ticklen_min);
[2]37
[284]38 $aMajPos=array();
39 $aMajLabel=array();
40
41 if( $this->supress_first ) {
42 $aMajLabel[] = '';
43 }
44 else {
45 $aMajLabel[]=$start;
46 }
47
48 $yr=$aScale->RelTranslate($start);
49 $xt=round($yr*cos($aAxisAngle))+$aScale->scale_abs[0];
50 $yt=$aPos-round($yr*sin($aAxisAngle));
51 $aMajPos[]=$xt+2*$dx_maj;
52 $aMajPos[]=$yt-$aImg->GetFontheight()/2;
53 $grid[]=$xt;
54 $grid[]=$yt;
55
56 $aImg->SetLineWeight($this->weight);
57
58 for($y=$start; $y<=$limit; $y+=$step,++$count ) {
59 $yr=$aScale->RelTranslate($y);
60 $xt=round($yr*cos($aAxisAngle))+$aScale->scale_abs[0];
61 $yt=$aPos-round($yr*sin($aAxisAngle));
62 if( $count % 10 == 0 ) {
63 $grid[]=$xt;
64 $grid[]=$yt;
65 $aMajPos[]=$xt+2*$dx_maj;
66 $aMajPos[]=$yt-$aImg->GetFontheight()/2;
67 if( !$this->supress_tickmarks ) {
68 if( $this->majcolor != '' ) {
69 $aImg->PushColor($this->majcolor);
70 }
71 $aImg->Line($xt+$dx_maj,$yt+$dy_maj,$xt-$dx_maj,$yt-$dy_maj);
72 if( $this->majcolor != '' ) {
73 $aImg->PopColor();
74 }
75 }
76 if( $this->label_formfunc != '' ) {
77 $f=$this->label_formfunc;
78 $l = call_user_func($f,$nextMajor);
79 }
80 else {
81 $l = $nextMajor;
82 }
83
84 $aMajLabel[]=$l;
85 $nextMajor *= 10;
86 $step *= 10;
87 $count=1;
88 }
89 else {
90 if( !$this->supress_minor_tickmarks ) {
91 if( $this->mincolor != '' ) {
92 $aImg->PushColor($this->mincolor);
93 }
94 $aImg->Line($xt+$dx_min,$yt+$dy_min,$xt-$dx_min,$yt-$dy_min);
95 if( $this->mincolor != '' ) {
96 $aImg->PopColor();
97 }
98 }
99 }
100 }
101 }
[2]102}
103
[284]104//===================================================
105// CLASS RadarLinear
106// Description: Linear ticks
107//===================================================
108class RadarLinearTicks extends Ticks {
109
[2]110 private $minor_step=1, $major_step=2;
111 private $xlabel_offset=0,$xtick_offset=0;
112
[284]113 function __construct() {
114 // Empty
[2]115 }
116
117 // Return major step size in world coordinates
118 function GetMajor() {
[284]119 return $this->major_step;
[2]120 }
[284]121
[2]122 // Return minor step size in world coordinates
123 function GetMinor() {
[284]124 return $this->minor_step;
[2]125 }
[284]126
[2]127 // Set Minor and Major ticks (in world coordinates)
128 function Set($aMajStep,$aMinStep=false) {
[284]129 if( $aMinStep==false ) {
130 $aMinStep=$aMajStep;
131 }
132
133 if( $aMajStep <= 0 || $aMinStep <= 0 ) {
134 JpGraphError::RaiseL(25064);
135 //JpGraphError::Raise(" Minor or major step size is 0. Check that you haven't got an accidental SetTextTicks(0) in your code. If this is not the case you might have stumbled upon a bug in JpGraph. Please report this and if possible include the data that caused the problem.");
136 }
137
138 $this->major_step=$aMajStep;
139 $this->minor_step=$aMinStep;
140 $this->is_set = true;
[2]141 }
142
143 function Stroke($aImg,&$grid,$aPos,$aAxisAngle,$aScale,&$aMajPos,&$aMajLabel) {
[284]144 // Prepare to draw linear ticks
145 $maj_step_abs = abs($aScale->scale_factor*$this->major_step);
146 $min_step_abs = abs($aScale->scale_factor*$this->minor_step);
147 $nbrmaj = round($aScale->world_abs_size/$maj_step_abs);
148 $nbrmin = round($aScale->world_abs_size/$min_step_abs);
149 $skip = round($nbrmin/$nbrmaj); // Don't draw minor on top of major
[2]150
[284]151 // Draw major ticks
152 $ticklen2=$this->major_abs_size;
153 $dx=round(sin($aAxisAngle)*$ticklen2);
154 $dy=round(cos($aAxisAngle)*$ticklen2);
155 $label=$aScale->scale[0]+$this->major_step;
[2]156
[284]157 $aImg->SetLineWeight($this->weight);
[2]158
[284]159 $aMajPos = array();
160 $aMajLabel = array();
[2]161
[284]162 for($i=1; $i<=$nbrmaj; ++$i) {
163 $xt=round($i*$maj_step_abs*cos($aAxisAngle))+$aScale->scale_abs[0];
164 $yt=$aPos-round($i*$maj_step_abs*sin($aAxisAngle));
165
166 if( $this->label_formfunc != '' ) {
167 $f=$this->label_formfunc;
168 $l = call_user_func($f,$label);
169 }
170 else {
171 $l = $label;
172 }
173
174 $aMajLabel[]=$l;
175 $label += $this->major_step;
176 $grid[]=$xt;
177 $grid[]=$yt;
178 $aMajPos[($i-1)*2]=$xt+2*$dx;
179 $aMajPos[($i-1)*2+1]=$yt-$aImg->GetFontheight()/2;
180 if( !$this->supress_tickmarks ) {
181 if( $this->majcolor != '' ) {
182 $aImg->PushColor($this->majcolor);
183 }
184 $aImg->Line($xt+$dx,$yt+$dy,$xt-$dx,$yt-$dy);
185 if( $this->majcolor != '' ) {
186 $aImg->PopColor();
187 }
188 }
189 }
190
191 // Draw minor ticks
192 $ticklen2=$this->minor_abs_size;
193 $dx=round(sin($aAxisAngle)*$ticklen2);
194 $dy=round(cos($aAxisAngle)*$ticklen2);
195 if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) {
196 if( $this->mincolor != '' ) {
197 $aImg->PushColor($this->mincolor);
198 }
199 for($i=1; $i<=$nbrmin; ++$i) {
200 if( ($i % $skip) == 0 ) {
201 continue;
202 }
203 $xt=round($i*$min_step_abs*cos($aAxisAngle))+$aScale->scale_abs[0];
204 $yt=$aPos-round($i*$min_step_abs*sin($aAxisAngle));
205 $aImg->Line($xt+$dx,$yt+$dy,$xt-$dx,$yt-$dy);
206 }
207 if( $this->mincolor != '' ) {
208 $aImg->PopColor();
209 }
210 }
[2]211 }
212}
213
214
215//===================================================
216// CLASS RadarAxis
217// Description: Implements axis for the radar graph
218//===================================================
219class RadarAxis extends AxisPrototype {
220 public $title=null;
[284]221 private $title_color='navy';
[2]222 private $len=0;
[284]223
224 function __construct($img,$aScale,$color=array(0,0,0)) {
225 parent::__construct($img,$aScale,$color);
226 $this->len = $img->plotheight;
227 $this->title = new Text();
228 $this->title->SetFont(FF_FONT1,FS_BOLD);
229 $this->color = array(0,0,0);
[2]230 }
[284]231
232 // Stroke the axis
233 // $pos = Vertical position of axis
[2]234 // $aAxisAngle = Axis angle
[284]235 // $grid = Returns an array with positions used to draw the grid
236 // $lf = Label flag, TRUE if the axis should have labels
[2]237 function Stroke($pos,$aAxisAngle,&$grid,$title,$lf) {
[284]238 $this->img->SetColor($this->color);
239
240 // Determine end points for the axis
241 $x=round($this->scale->world_abs_size*cos($aAxisAngle)+$this->scale->scale_abs[0]);
242 $y=round($pos-$this->scale->world_abs_size*sin($aAxisAngle));
243
244 // Draw axis
245 $this->img->SetColor($this->color);
246 $this->img->SetLineWeight($this->weight);
247 if( !$this->hide ) {
248 $this->img->Line($this->scale->scale_abs[0],$pos,$x,$y);
249 }
250
251 $this->scale->ticks->Stroke($this->img,$grid,$pos,$aAxisAngle,$this->scale,$majpos,$majlabel);
252 $ncolor=0;
253 if( isset($this->ticks_label_colors) ) {
254 $ncolor=count($this->ticks_label_colors);
255 }
256
257 // Draw labels
258 if( $lf && !$this->hide ) {
259 $this->img->SetFont($this->font_family,$this->font_style,$this->font_size);
260 $this->img->SetTextAlign('left','top');
261 $this->img->SetColor($this->label_color);
262
263 // majpos contains (x,y) coordinates for labels
264 if( ! $this->hide_labels ) {
265 $n = floor(count($majpos)/2);
266 for($i=0; $i < $n; ++$i) {
267 // Set specific label color if specified
268 if( $ncolor > 0 ) {
269 $this->img->SetColor($this->ticks_label_colors[$i % $ncolor]);
270 }
271
272 if( $this->ticks_label != null && isset($this->ticks_label[$i]) ) {
273 $this->img->StrokeText($majpos[$i*2],$majpos[$i*2+1],$this->ticks_label[$i]);
274 }
275 else {
276 $this->img->StrokeText($majpos[$i*2],$majpos[$i*2+1],$majlabel[$i]);
277 }
278 }
279 }
280 }
281 $this->_StrokeAxisTitle($pos,$aAxisAngle,$title);
[2]282 }
[284]283
[2]284 function _StrokeAxisTitle($pos,$aAxisAngle,$title) {
[284]285 $this->title->Set($title);
286 $marg=6+$this->title->margin;
287 $xt=round(($this->scale->world_abs_size+$marg)*cos($aAxisAngle)+$this->scale->scale_abs[0]);
288 $yt=round($pos-($this->scale->world_abs_size+$marg)*sin($aAxisAngle));
[2]289
[284]290 // Position the axis title.
291 // dx, dy is the offset from the top left corner of the bounding box that sorrounds the text
292 // that intersects with the extension of the corresponding axis. The code looks a little
293 // bit messy but this is really the only way of having a reasonable position of the
294 // axis titles.
295 if( $this->title->iWordwrap > 0 ) {
296 $title = wordwrap($title,$this->title->iWordwrap,"\n");
297 }
[2]298
[284]299 $h=$this->img->GetTextHeight($title)*1.2;
300 $w=$this->img->GetTextWidth($title)*1.2;
[2]301
[284]302 while( $aAxisAngle > 2*M_PI )
303 $aAxisAngle -= 2*M_PI;
304
305 // Around 3 a'clock
306 if( $aAxisAngle>=7*M_PI/4 || $aAxisAngle <= M_PI/4 ) $dx=-0.15; // Small trimming to make the dist to the axis more even
307
308 // Around 12 a'clock
309 if( $aAxisAngle>=M_PI/4 && $aAxisAngle <= 3*M_PI/4 ) $dx=($aAxisAngle-M_PI/4)*2/M_PI;
310
311 // Around 9 a'clock
312 if( $aAxisAngle>=3*M_PI/4 && $aAxisAngle <= 5*M_PI/4 ) $dx=1;
313
314 // Around 6 a'clock
315 if( $aAxisAngle>=5*M_PI/4 && $aAxisAngle <= 7*M_PI/4 ) $dx=(1-($aAxisAngle-M_PI*5/4)*2/M_PI);
316
317 if( $aAxisAngle>=7*M_PI/4 ) $dy=(($aAxisAngle-M_PI)-3*M_PI/4)*2/M_PI;
318 if( $aAxisAngle<=M_PI/12 ) $dy=(0.5-$aAxisAngle*2/M_PI);
319 if( $aAxisAngle<=M_PI/4 && $aAxisAngle > M_PI/12) $dy=(1-$aAxisAngle*2/M_PI);
320 if( $aAxisAngle>=M_PI/4 && $aAxisAngle <= 3*M_PI/4 ) $dy=1;
321 if( $aAxisAngle>=3*M_PI/4 && $aAxisAngle <= 5*M_PI/4 ) $dy=(1-($aAxisAngle-3*M_PI/4)*2/M_PI);
322 if( $aAxisAngle>=5*M_PI/4 && $aAxisAngle <= 7*M_PI/4 ) $dy=0;
323
324 if( !$this->hide ) {
325 $this->title->Stroke($this->img,$xt-$dx*$w,$yt-$dy*$h,$title);
326 }
[2]327 }
[284]328
[2]329} // Class
330
331
332//===================================================
333// CLASS RadarGrid
334// Description: Draws grid for the radar graph
335//===================================================
336class RadarGrid { //extends Grid {
337 private $type='solid';
338 private $grid_color='#DDDDDD';
339 private $show=false, $weight=1;
340
[284]341 function __construct() {
342 // Empty
[2]343 }
344
345 function SetColor($aMajColor) {
[284]346 $this->grid_color = $aMajColor;
[2]347 }
[284]348
[2]349 function SetWeight($aWeight) {
[284]350 $this->weight=$aWeight;
[2]351 }
[284]352
[2]353 // Specify if grid should be dashed, dotted or solid
354 function SetLineStyle($aType) {
[284]355 $this->type = $aType;
[2]356 }
[284]357
[2]358 // Decide if both major and minor grid should be displayed
359 function Show($aShowMajor=true) {
[284]360 $this->show=$aShowMajor;
[2]361 }
[284]362
[2]363 function Stroke($img,$grid) {
[284]364 if( !$this->show ) {
365 return;
366 }
367
368 $nbrticks = count($grid[0])/2;
369 $nbrpnts = count($grid);
370 $img->SetColor($this->grid_color);
371 $img->SetLineWeight($this->weight);
372
373 for($i=0; $i<$nbrticks; ++$i) {
374 for($j=0; $j<$nbrpnts; ++$j) {
375 $pnts[$j*2]=$grid[$j][$i*2];
376 $pnts[$j*2+1]=$grid[$j][$i*2+1];
377 }
378 for($k=0; $k<$nbrpnts; ++$k ){
379 $l=($k+1)%$nbrpnts;
380 if( $this->type == 'solid' )
381 $img->Line($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1]);
382 elseif( $this->type == 'dotted' )
383 $img->DashedLine($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1],1,6);
384 elseif( $this->type == 'dashed' )
385 $img->DashedLine($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1],2,4);
386 elseif( $this->type == 'longdashed' )
387 $img->DashedLine($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1],8,6);
388 }
389 $pnts=array();
390 }
[2]391 }
392} // Class
393
394
395//===================================================
396// CLASS RadarPlot
397// Description: Plot a radarplot
398//===================================================
399class RadarPlot {
400 public $mark=null;
[284]401 public $legend='';
402 public $legendcsimtarget='';
403 public $legendcsimalt='';
404 public $csimtargets=array(); // Array of targets for CSIM
405 public $csimareas=""; // Resultant CSIM area tags
406 public $csimalts=null; // ALT:s for corresponding target
[2]407 private $data=array();
408 private $fill=false, $fill_color=array(200,170,180);
409 private $color=array(0,0,0);
410 private $weight=1;
411 private $linestyle='solid';
[284]412
413 //---------------
414 // CONSTRUCTOR
415 function __construct($data) {
416 $this->data = $data;
417 $this->mark = new PlotMark();
[2]418 }
419
420 function Min() {
[284]421 return Min($this->data);
[2]422 }
[284]423
[2]424 function Max() {
[284]425 return Max($this->data);
[2]426 }
[284]427
[2]428 function SetLegend($legend) {
[284]429 $this->legend=$legend;
[2]430 }
431
432 function SetLineStyle($aStyle) {
[284]433 $this->linestyle=$aStyle;
[2]434 }
[284]435
[2]436 function SetLineWeight($w) {
[284]437 $this->weight=$w;
[2]438 }
[284]439
[2]440 function SetFillColor($aColor) {
[284]441 $this->fill_color = $aColor;
442 $this->fill = true;
[2]443 }
[284]444
[2]445 function SetFill($f=true) {
[284]446 $this->fill = $f;
[2]447 }
[284]448
[2]449 function SetColor($aColor,$aFillColor=false) {
[284]450 $this->color = $aColor;
451 if( $aFillColor ) {
452 $this->SetFillColor($aFillColor);
453 $this->fill = true;
454 }
[2]455 }
[284]456
457 // Set href targets for CSIM
458 function SetCSIMTargets($aTargets,$aAlts=null) {
459 $this->csimtargets=$aTargets;
460 $this->csimalts=$aAlts;
461 }
462
463 // Get all created areas
[2]464 function GetCSIMareas() {
[284]465 return $this->csimareas;
[2]466 }
[284]467
[2]468 function Stroke($img, $pos, $scale, $startangle) {
[284]469 $nbrpnts = count($this->data);
470 $astep=2*M_PI/$nbrpnts;
471 $a=$startangle;
[2]472
[284]473 for($i=0; $i<$nbrpnts; ++$i) {
[2]474
[284]475 // Rotate each non null point to the correct axis-angle
476 $cs=$scale->RelTranslate($this->data[$i]);
477 $x=round($cs*cos($a)+$scale->scale_abs[0]);
478 $y=round($pos-$cs*sin($a));
[2]479
[284]480 $pnts[$i*2]=$x;
481 $pnts[$i*2+1]=$y;
482
483 // If the next point is null then we draw this polygon segment
484 // to the center, skip the next and draw the next segment from
485 // the center up to the point on the axis with the first non-null
486 // value and continues from that point. Some additoinal logic is necessary
487 // to handle the boundary conditions
488 if( $i < $nbrpnts-1 ) {
489 if( is_null($this->data[$i+1]) ) {
490 $cs = 0;
491 $x=round($cs*cos($a)+$scale->scale_abs[0]);
492 $y=round($pos-$cs*sin($a));
493 $pnts[$i*2]=$x;
494 $pnts[$i*2+1]=$y;
495 $a += $astep;
496 }
497 }
498
499 $a += $astep;
500 }
501
502 if( $this->fill ) {
503 $img->SetColor($this->fill_color);
504 $img->FilledPolygon($pnts);
505 }
506
507 $img->SetLineWeight($this->weight);
508 $img->SetColor($this->color);
509 $img->SetLineStyle($this->linestyle);
510 $pnts[] = $pnts[0];
511 $pnts[] = $pnts[1];
512 $img->Polygon($pnts);
513 $img->SetLineStyle('solid'); // Reset line style to default
514
515 // Add plotmarks on top
516 if( $this->mark->show ) {
517 for($i=0; $i < $nbrpnts; ++$i) {
518 if( isset($this->csimtargets[$i]) ) {
519 $this->mark->SetCSIMTarget($this->csimtargets[$i]);
520 $this->mark->SetCSIMAlt($this->csimalts[$i]);
521 $this->mark->SetCSIMAltVal($pnts[$i*2], $pnts[$i*2+1]);
522 $this->mark->Stroke($img, $pnts[$i*2], $pnts[$i*2+1]);
523 $this->csimareas .= $this->mark->GetCSIMAreas();
524 }
525 else {
526 $this->mark->Stroke($img,$pnts[$i*2],$pnts[$i*2+1]);
527 }
528 }
529 }
530
[2]531 }
[284]532
[2]533 function GetCount() {
[284]534 return count($this->data);
[2]535 }
[284]536
[2]537 function Legend($graph) {
[284]538 if( $this->legend == '' ) {
539 return;
540 }
541 if( $this->fill ) {
542 $graph->legend->Add($this->legend,$this->fill_color,$this->mark);
543 } else {
544 $graph->legend->Add($this->legend,$this->color,$this->mark);
545 }
[2]546 }
[284]547
[2]548} // Class
549
550//===================================================
551// CLASS RadarGraph
552// Description: Main container for a radar graph
553//===================================================
554class RadarGraph extends Graph {
555 public $grid,$axis=null;
556 private $posx,$posy;
[284]557 private $len;
[2]558 private $axis_title=null;
559
[284]560 function __construct($width=300,$height=200,$cachedName="",$timeout=0,$inline=1) {
561 parent::__construct($width,$height,$cachedName,$timeout,$inline);
562 $this->posx = $width/2;
563 $this->posy = $height/2;
564 $this->len = min($width,$height)*0.35;
565 $this->SetColor(array(255,255,255));
566 $this->SetTickDensity(TICKD_NORMAL);
567 $this->SetScale('lin');
568 $this->SetGridDepth(DEPTH_FRONT);
[2]569 }
570
[284]571 function HideTickMarks($aFlag=true) {
572 $this->axis->scale->ticks->SupressTickMarks($aFlag);
[267]573 }
574
[2]575 function ShowMinorTickmarks($aFlag=true) {
[284]576 $this->yscale->ticks->SupressMinorTickMarks(!$aFlag);
[2]577 }
[284]578
[2]579 function SetScale($axtype,$ymin=1,$ymax=1,$dummy1=null,$dumy2=null) {
[284]580 if( $axtype != 'lin' && $axtype != 'log' ) {
581 JpGraphError::RaiseL(18003,$axtype);
582 //("Illegal scale for radarplot ($axtype). Must be \"lin\" or \"log\"");
583 }
584 if( $axtype == 'lin' ) {
585 $this->yscale = new LinearScale($ymin,$ymax);
586 $this->yscale->ticks = new RadarLinearTicks();
587 $this->yscale->ticks->SupressMinorTickMarks();
588 }
589 elseif( $axtype == 'log' ) {
590 $this->yscale = new LogScale($ymin,$ymax);
591 $this->yscale->ticks = new RadarLogTicks();
592 }
593
594 $this->axis = new RadarAxis($this->img,$this->yscale);
595 $this->grid = new RadarGrid();
[2]596 }
597
598 function SetSize($aSize) {
[284]599 if( $aSize < 0.1 || $aSize>1 ) {
600 JpGraphError::RaiseL(18004,$aSize);
601 //("Radar Plot size must be between 0.1 and 1. (Your value=$s)");
602 }
603 $this->len=min($this->img->width,$this->img->height)*$aSize/2;
[2]604 }
605
606 function SetPlotSize($aSize) {
[284]607 $this->SetSize($aSize);
[2]608 }
609
610 function SetTickDensity($densy=TICKD_NORMAL,$dummy1=null) {
[284]611 $this->ytick_factor=25;
612 switch( $densy ) {
613 case TICKD_DENSE:
614 $this->ytick_factor=12;
615 break;
616 case TICKD_NORMAL:
617 $this->ytick_factor=25;
618 break;
619 case TICKD_SPARSE:
620 $this->ytick_factor=40;
621 break;
622 case TICKD_VERYSPARSE:
623 $this->ytick_factor=70;
624 break;
625 default:
626 JpGraphError::RaiseL(18005,$densy);
627 //("RadarPlot Unsupported Tick density: $densy");
628 }
[2]629 }
630
631 function SetPos($px,$py=0.5) {
[284]632 $this->SetCenter($px,$py);
[2]633 }
634
635 function SetCenter($px,$py=0.5) {
[284]636 if( $px >= 0 && $px <= 1 ) {
637 $this->posx = $this->img->width*$px;
638 }
639 else {
640 $this->posx = $px;
641 }
642 if( $py >= 0 && $py <= 1 ) {
643 $this->posy = $this->img->height*$py;
644 }
645 else {
646 $this->posy = $py;
647 }
[2]648 }
649
[284]650 function SetColor($aColor) {
651 $this->SetMarginColor($aColor);
[2]652 }
[284]653
654 function SetTitles($aTitleArray) {
655 $this->axis_title = $aTitleArray;
[2]656 }
657
[284]658 function Add($aPlot) {
659 if( $aPlot == null ) {
660 JpGraphError::RaiseL(25010);//("Graph::Add() You tried to add a null plot to the graph.");
661 }
662 if( is_array($aPlot) && count($aPlot) > 0 ) {
663 $cl = $aPlot[0];
664 }
665 else {
666 $cl = $aPlot;
667 }
668
669 if( $cl instanceof Text ) $this->AddText($aPlot);
670 elseif( class_exists('IconPlot',false) && ($cl instanceof IconPlot) ) $this->AddIcon($aPlot);
671 else {
672 $this->plots[] = $aPlot;
673 }
[2]674 }
[284]675
[2]676 function GetPlotsYMinMax($aPlots) {
[284]677 $min=$aPlots[0]->Min();
678 $max=$aPlots[0]->Max();
679 foreach( $this->plots as $p ) {
680 $max=max($max,$p->Max());
681 $min=min($min,$p->Min());
682 }
683 if( $min < 0 ) {
684 JpGraphError::RaiseL(18006,$min);
685 //("Minimum data $min (Radar plots should only be used when all data points > 0)");
686 }
687 return array($min,$max);
688 }
[2]689
[284]690 function StrokeIcons() {
691 if( $this->iIcons != null ) {
692 $n = count($this->iIcons);
693 for( $i=0; $i < $n; ++$i ) {
694 $this->iIcons[$i]->Stroke($this->img);
695 }
696 }
697 }
698
699 function StrokeTexts() {
700 if( $this->texts != null ) {
701 $n = count($this->texts);
702 for( $i=0; $i < $n; ++$i ) {
703 $this->texts[$i]->Stroke($this->img);
704 }
705 }
706 }
707
[2]708 // Stroke the Radar graph
[284]709 function Stroke($aStrokeFileName='') {
[2]710
[284]711 // If the filename is the predefined value = '_csim_special_'
712 // we assume that the call to stroke only needs to do enough
713 // to correctly generate the CSIM maps.
714 // We use this variable to skip things we don't strictly need
715 // to do to generate the image map to improve performance
716 // a best we can. Therefor you will see a lot of tests !$_csim in the
717 // code below.
718 $_csim = ( $aStrokeFileName === _CSIM_SPECIALFILE );
[2]719
[284]720 // We need to know if we have stroked the plot in the
721 // GetCSIMareas. Otherwise the CSIM hasn't been generated
722 // and in the case of GetCSIM called before stroke to generate
723 // CSIM without storing an image to disk GetCSIM must call Stroke.
724 $this->iHasStroked = true;
[2]725
[284]726 $n = count($this->plots);
727 // Set Y-scale
[2]728
[284]729 if( !$this->yscale->IsSpecified() && count($this->plots) > 0 ) {
730 list($min,$max) = $this->GetPlotsYMinMax($this->plots);
731 $this->yscale->AutoScale($this->img,0,$max,$this->len/$this->ytick_factor);
732 }
733 elseif( $this->yscale->IsSpecified() &&
734 ( $this->yscale->auto_ticks || !$this->yscale->ticks->IsSpecified()) ) {
[2]735
[284]736 // The tick calculation will use the user suplied min/max values to determine
737 // the ticks. If auto_ticks is false the exact user specifed min and max
738 // values will be used for the scale.
739 // If auto_ticks is true then the scale might be slightly adjusted
740 // so that the min and max values falls on an even major step.
741 $min = $this->yscale->scale[0];
742 $max = $this->yscale->scale[1];
743 $this->yscale->AutoScale($this->img,$min,$max,
744 $this->len/$this->ytick_factor,
745 $this->yscale->auto_ticks);
746 }
747
748 // Set start position end length of scale (in absolute pixels)
749 $this->yscale->SetConstants($this->posx,$this->len);
750
751 // We need as many axis as there are data points
752 $nbrpnts=$this->plots[0]->GetCount();
753
754 // If we have no titles just number the axis 1,2,3,...
755 if( $this->axis_title==null ) {
756 for($i=0; $i < $nbrpnts; ++$i ) {
757 $this->axis_title[$i] = $i+1;
758 }
759 }
760 elseif( count($this->axis_title) < $nbrpnts) {
761 JpGraphError::RaiseL(18007);
762 // ("Number of titles does not match number of points in plot.");
763 }
764 for( $i=0; $i < $n; ++$i ) {
765 if( $nbrpnts != $this->plots[$i]->GetCount() ) {
766 JpGraphError::RaiseL(18008);
767 //("Each radar plot must have the same number of data points.");
768 }
769 }
770
771 if( !$_csim ) {
772 if( $this->background_image != '' ) {
773 $this->StrokeFrameBackground();
774 }
775 else {
776 $this->StrokeFrame();
777 $this->StrokeBackgroundGrad();
778 }
779 }
780 $astep=2*M_PI/$nbrpnts;
781
782 if( !$_csim ) {
783 if( $this->iIconDepth == DEPTH_BACK ) {
784 $this->StrokeIcons();
785 }
786
787
788 // Prepare legends
789 for($i=0; $i < $n; ++$i) {
790 $this->plots[$i]->Legend($this);
791 }
792 $this->legend->Stroke($this->img);
793 $this->footer->Stroke($this->img);
794 }
795
796 if( !$_csim ) {
797 if( $this->grid_depth == DEPTH_BACK ) {
798 // Draw axis and grid
799 for( $i=0,$a=M_PI/2; $i < $nbrpnts; ++$i, $a += $astep ) {
800 $this->axis->Stroke($this->posy,$a,$grid[$i],$this->axis_title[$i],$i==0);
801 }
802 $this->grid->Stroke($this->img,$grid);
803 }
804 if( $this->iIconDepth == DEPTH_BACK ) {
805 $this->StrokeIcons();
806 }
807
808 }
809
810 // Plot points
811 $a=M_PI/2;
812 for($i=0; $i < $n; ++$i ) {
813 $this->plots[$i]->Stroke($this->img, $this->posy, $this->yscale, $a);
814 }
815
816 if( !$_csim ) {
817 if( $this->grid_depth != DEPTH_BACK ) {
818 // Draw axis and grid
819 for( $i=0,$a=M_PI/2; $i < $nbrpnts; ++$i, $a += $astep ) {
820 $this->axis->Stroke($this->posy,$a,$grid[$i],$this->axis_title[$i],$i==0);
821 }
822 $this->grid->Stroke($this->img,$grid);
823 }
824
825 $this->StrokeTitles();
826 $this->StrokeTexts();
827 if( $this->iIconDepth == DEPTH_FRONT ) {
828 $this->StrokeIcons();
829 }
830 }
831
832 // Should we do any final image transformation
833 if( $this->iImgTrans && !$_csim ) {
834 if( !class_exists('ImgTrans',false) ) {
835 require_once('jpgraph_imgtrans.php');
836 }
837
838 $tform = new ImgTrans($this->img->img);
839 $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist,
840 $this->iImgTransDirection,$this->iImgTransHighQ,
841 $this->iImgTransMinSize,$this->iImgTransFillColor,
842 $this->iImgTransBorder);
843 }
844
845 if( !$_csim ) {
846 // If the filename is given as the special "__handle"
847 // then the image handler is returned and the image is NOT
848 // streamed back
849 if( $aStrokeFileName == _IMG_HANDLER ) {
850 return $this->img->img;
851 }
852 else {
853 // Finally stream the generated picture
854 $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,$aStrokeFileName);
855 }
856 }
[2]857 }
858} // Class
859
860/* EOF */
861?>
Note: See TracBrowser for help on using the repository browser.