1<?php
2 /*
3     pRadar - class to draw radar charts
4
5     Version     : 2.1.3
6     Made by     : Jean-Damien POGOLOTTI
7     Last Update : 09/09/11
8
9     This file can be distributed under the license you can find at :
10
11                       http://www.pchart.net/license
12
13     You can find the whole class documentation on the pChart web site.
14 */
15
16 define("SEGMENT_HEIGHT_AUTO"		, 690001);
17
18 define("RADAR_LAYOUT_STAR"		, 690011);
19 define("RADAR_LAYOUT_CIRCLE"		, 690012);
20
21 define("RADAR_LABELS_ROTATED"		, 690021);
22 define("RADAR_LABELS_HORIZONTAL"	, 690022);
23
24 /* pRadar class definition */
25 class pRadar
26  {
27   var $pChartObject;
28
29   /* Class creator */
30   function pRadar()
31    { }
32
33   /* Draw a radar chart */
34   function drawRadar($Object,$Values,$Format="")
35    {
36     $this->pChartObject = $Object;
37
38     $FixedMax		= isset($Format["FixedMax"]) ? $Format["FixedMax"] : VOID;
39     $AxisR		= isset($Format["AxisR"]) ? $Format["AxisR"] : 60;
40     $AxisG		= isset($Format["AxisG"]) ? $Format["AxisG"] : 60;
41     $AxisB		= isset($Format["AxisB"]) ? $Format["AxisB"] : 60;
42     $AxisAlpha		= isset($Format["AxisAlpha"]) ? $Format["AxisAlpha"] : 50;
43     $AxisRotation      = isset($Format["AxisRotation"]) ? $Format["AxisRotation"] : 0;
44     $DrawTicks		= isset($Format["DrawTicks"]) ? $Format["DrawTicks"] : TRUE;
45     $TicksLength	= isset($Format["TicksLength"]) ? $Format["TicksLength"] : 2;
46     $DrawAxisValues	= isset($Format["DrawAxisValues"]) ? $Format["DrawAxisValues"] : TRUE;
47     $AxisBoxRounded	= isset($Format["AxisBoxRounded"]) ? $Format["AxisBoxRounded"] : TRUE;
48     $AxisFontName	= isset($Format["AxisFontName"]) ? $Format["AxisFontName"] : $this->pChartObject->FontName;
49     $AxisFontSize	= isset($Format["AxisFontSize"]) ? $Format["AxisFontSize"] : $this->pChartObject->FontSize;
50     $WriteValues	= isset($Format["WriteValues"]) ? $Format["WriteValues"] : FALSE;
51     $WriteValuesInBubble = isset($Format["WriteValuesInBubble"]) ? $Format["WriteValuesInBubble"] : TRUE;
52     $ValueFontName	= isset($Format["ValueFontName"]) ? $Format["ValueFontName"] : $this->pChartObject->FontName;
53     $ValueFontSize	= isset($Format["ValueFontSize"]) ? $Format["ValueFontSize"] : $this->pChartObject->FontSize;
54     $ValuePadding	= isset($Format["ValuePadding"]) ? $Format["ValuePadding"] : 4;
55     $OuterBubbleRadius	= isset($Format["OuterBubbleRadius"]) ? $Format["OuterBubbleRadius"] : 2;
56     $OuterBubbleR	= isset($Format["OuterBubbleR"]) ? $Format["OuterBubbleR"] : VOID;
57     $OuterBubbleG	= isset($Format["OuterBubbleG"]) ? $Format["OuterBubbleG"] : VOID;
58     $OuterBubbleB	= isset($Format["OuterBubbleB"]) ? $Format["OuterBubbleB"] : VOID;
59     $OuterBubbleAlpha	= isset($Format["OuterBubbleAlpha"]) ? $Format["OuterBubbleAlpha"] : 100;
60     $InnerBubbleR	= isset($Format["InnerBubbleR"]) ? $Format["InnerBubbleR"] : 255;
61     $InnerBubbleG	= isset($Format["InnerBubbleG"]) ? $Format["InnerBubbleG"] : 255;
62     $InnerBubbleB	= isset($Format["InnerBubbleB"]) ? $Format["InnerBubbleB"] : 255;
63     $InnerBubbleAlpha	= isset($Format["InnerBubbleAlpha"]) ? $Format["InnerBubbleAlpha"] : 100;
64     $DrawBackground	= isset($Format["DrawBackground"]) ? $Format["DrawBackground"] : TRUE;
65     $BackgroundR	= isset($Format["BackgroundR"]) ? $Format["BackgroundR"] : 255;
66     $BackgroundG	= isset($Format["BackgroundG"]) ? $Format["BackgroundG"] : 255;
67     $BackgroundB	= isset($Format["BackgroundB"]) ? $Format["BackgroundB"] : 255;
68     $BackgroundAlpha	= isset($Format["BackgroundAlpha"]) ? $Format["BackgroundAlpha"] : 50;
69     $BackgroundGradient= isset($Format["BackgroundGradient"]) ? $Format["BackgroundGradient"] : NULL;
70     $Layout		= isset($Format["Layout"]) ? $Format["Layout"] : RADAR_LAYOUT_STAR;
71     $SegmentHeight	= isset($Format["SegmentHeight"]) ? $Format["SegmentHeight"] : SEGMENT_HEIGHT_AUTO;
72     $Segments		= isset($Format["Segments"]) ? $Format["Segments"] : 4;
73     $WriteLabels	= isset($Format["WriteLabels"]) ? $Format["WriteLabels"] : TRUE;
74     $SkipLabels	= isset($Format["SkipLabels"]) ? $Format["SkipLabels"] : 1;
75     $LabelMiddle	= isset($Format["LabelMiddle"]) ? $Format["LabelMiddle"] : FALSE;
76     $LabelsBackground	= isset($Format["LabelsBackground"]) ? $Format["LabelsBackground"] : TRUE;
77     $LabelsBGR		= isset($Format["LabelsBGR"]) ? $Format["LabelsBGR"] : 255;
78     $LabelsBGG		= isset($Format["LabelsBGR"]) ? $Format["LabelsBGG"] : 255;
79     $LabelsBGB		= isset($Format["LabelsBGR"]) ? $Format["LabelsBGB"] : 255;
80     $LabelsBGAlpha	= isset($Format["LabelsBGAlpha"]) ? $Format["LabelsBGAlpha"] : 50;
81     $LabelPos		= isset($Format["LabelPos"]) ? $Format["LabelPos"] : RADAR_LABELS_ROTATED;
82     $LabelPadding	= isset($Format["LabelPadding"]) ? $Format["LabelPadding"] : 4;
83     $DrawPoints	= isset($Format["DrawPoints"]) ? $Format["DrawPoints"] : TRUE;
84     $PointRadius	= isset($Format["PointRadius"]) ? $Format["PointRadius"] : 4;
85     $PointSurrounding	= isset($Format["PointRadius"]) ? $Format["PointRadius"] : -30;
86     $DrawLines		= isset($Format["DrawLines"]) ? $Format["DrawLines"] : TRUE;
87     $LineLoopStart	= isset($Format["LineLoopStart"]) ? $Format["LineLoopStart"] : TRUE;
88     $DrawPoly		= isset($Format["DrawPoly"]) ? $Format["DrawPoly"] : FALSE;
89     $PolyAlpha		= isset($Format["PolyAlpha"]) ? $Format["PolyAlpha"] : 40;
90     $FontSize		= $Object->FontSize;
91     $X1		= $Object->GraphAreaX1;
92     $Y1		= $Object->GraphAreaY1;
93     $X2		= $Object->GraphAreaX2;
94     $Y2		= $Object->GraphAreaY2;
95     $RecordImageMap	= isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE;
96
97     /* Cancel default tick length if ticks not enabled */
98     if ( $DrawTicks == FALSE ) { $TicksLength = 0; }
99
100     /* Data Processing */
101     $Data    = $Values->getData();
102     $Palette = $Values->getPalette();
103
104     /* Catch the number of required axis */
105     $LabelSerie = $Data["Abscissa"];
106     if ( $LabelSerie != "" )
107      { $Points = count($Data["Series"][$LabelSerie]["Data"]); }
108     else
109      {
110       $Points = 0;
111       foreach($Data["Series"] as $SerieName => $DataArray)
112        { if ( count($DataArray["Data"]) > $Points ) { $Points = count($DataArray["Data"]); } }
113      }
114
115     /* Draw the axis */
116     $CenterX = ($X2-$X1)/2 + $X1;
117     $CenterY = ($Y2-$Y1)/2 + $Y1;
118
119     $EdgeHeight = min(($X2-$X1)/2,($Y2-$Y1)/2);
120     if ( $WriteLabels )
121      $EdgeHeight = $EdgeHeight - $FontSize - $LabelPadding - $TicksLength;
122
123     /* Determine the scale if set to automatic */
124     if ( $SegmentHeight == SEGMENT_HEIGHT_AUTO)
125      {
126       if ( $FixedMax != VOID )
127        $Max = $FixedMax;
128       else
129        {
130         $Max = 0;
131         foreach($Data["Series"] as $SerieName => $DataArray)
132          {
133           if ( $SerieName != $LabelSerie )
134            {
135             if ( max($DataArray["Data"]) > $Max ) { $Max = max($DataArray["Data"]); }
136            }
137          }
138        }
139       $MaxSegments = $EdgeHeight/20;
140       $Scale = $Object->computeScale(0,$Max,$MaxSegments,array(1,2,5));
141
142       $Segments      = $Scale["Rows"];
143       $SegmentHeight = $Scale["RowHeight"];
144      }
145
146     if ( $LabelMiddle && $SkipLabels == 1 )
147      { $Axisoffset = (360/$Points)/2; }
148     elseif ( $LabelMiddle && $SkipLabels != 1 )
149      { $Axisoffset = (360/($Points/$SkipLabels))/2; }
150     elseif ( !$LabelMiddle )
151      { $Axisoffset = 0; }
152
153     /* Background processing */
154     if ( $DrawBackground )
155      {
156       $RestoreShadow = $Object->Shadow;
157       $Object->Shadow = FALSE;
158
159       if ($BackgroundGradient == NULL)
160        {
161         if ( $Layout == RADAR_LAYOUT_STAR )
162          {
163           $Color      = array("R"=>$BackgroundR,"G"=>$BackgroundG,"B"=>$BackgroundB,"Alpha"=>$BackgroundAlpha);
164           $PointArray = "";
165           for($i=0;$i<=360;$i=$i+(360/$Points))
166            {
167             $PointArray[] = cos(deg2rad($i+$AxisRotation)) * $EdgeHeight + $CenterX;
168             $PointArray[] = sin(deg2rad($i+$AxisRotation)) * $EdgeHeight + $CenterY;
169            }
170           $Object->drawPolygon($PointArray,$Color);
171          }
172         elseif ( $Layout == RADAR_LAYOUT_CIRCLE )
173          {
174           $Color = array("R"=>$BackgroundR,"G"=>$BackgroundG,"B"=>$BackgroundB,"Alpha"=>$BackgroundAlpha);
175           $Object->drawFilledCircle($CenterX,$CenterY,$EdgeHeight,$Color);
176          }
177        }
178       else
179        {
180         $GradientROffset	= ($BackgroundGradient["EndR"] - $BackgroundGradient["StartR"]) / $Segments;
181         $GradientGOffset	= ($BackgroundGradient["EndG"] - $BackgroundGradient["StartG"]) / $Segments;
182         $GradientBOffset	= ($BackgroundGradient["EndB"] - $BackgroundGradient["StartB"]) / $Segments;
183         $GradientAlphaOffset	= ($BackgroundGradient["EndAlpha"] - $BackgroundGradient["StartAlpha"]) / $Segments;
184
185         if ( $Layout == RADAR_LAYOUT_STAR )
186          {
187           for($j=$Segments;$j>=1;$j--)
188            {
189             $Color      = array("R"=>$BackgroundGradient["StartR"]+$GradientROffset*$j,"G"=>$BackgroundGradient["StartG"]+$GradientGOffset*$j,"B"=>$BackgroundGradient["StartB"]+$GradientBOffset*$j,"Alpha"=>$BackgroundGradient["StartAlpha"]+$GradientAlphaOffset*$j);
190             $PointArray = "";
191
192             for($i=0;$i<=360;$i=$i+(360/$Points))
193              {
194               $PointArray[] = cos(deg2rad($i+$AxisRotation)) * ($EdgeHeight/$Segments)*$j + $CenterX;
195               $PointArray[] = sin(deg2rad($i+$AxisRotation)) * ($EdgeHeight/$Segments)*$j + $CenterY;
196              }
197             $Object->drawPolygon($PointArray,$Color);
198            }
199          }
200         elseif ( $Layout == RADAR_LAYOUT_CIRCLE )
201          {
202           for($j=$Segments;$j>=1;$j--)
203            {
204             $Color = array("R"=>$BackgroundGradient["StartR"]+$GradientROffset*$j,"G"=>$BackgroundGradient["StartG"]+$GradientGOffset*$j,"B"=>$BackgroundGradient["StartB"]+$GradientBOffset*$j,"Alpha"=>$BackgroundGradient["StartAlpha"]+$GradientAlphaOffset*$j);
205             $Object->drawFilledCircle($CenterX,$CenterY,($EdgeHeight/$Segments)*$j,$Color);
206            }
207          }
208        }
209       $Object->Shadow = $RestoreShadow;
210      }
211
212     /* Axis to axis lines */
213     $Color = array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha);
214     $ColorDotted = array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha*.8, "Ticks"=>2);
215     if ( $Layout == RADAR_LAYOUT_STAR )
216      {
217       for($j=1;$j<=$Segments;$j++)
218        {
219         for($i=0;$i<360;$i=$i+(360/$Points))
220          {
221           $EdgeX1 = cos(deg2rad($i+$AxisRotation)) * ($EdgeHeight/$Segments)*$j + $CenterX;
222           $EdgeY1 = sin(deg2rad($i+$AxisRotation)) * ($EdgeHeight/$Segments)*$j + $CenterY;
223           $EdgeX2 = cos(deg2rad($i+$AxisRotation+(360/$Points))) * ($EdgeHeight/$Segments)*$j + $CenterX;
224           $EdgeY2 = sin(deg2rad($i+$AxisRotation+(360/$Points))) * ($EdgeHeight/$Segments)*$j + $CenterY;
225
226           $Object->drawLine($EdgeX1,$EdgeY1,$EdgeX2,$EdgeY2,$Color);
227          }
228        }
229      }
230     elseif ( $Layout == RADAR_LAYOUT_CIRCLE )
231      {
232       for($j=1;$j<=$Segments;$j++)
233        {
234         $Radius = ($EdgeHeight/$Segments)*$j;
235         $Object->drawCircle($CenterX,$CenterY,$Radius,$Radius,$Color);
236        }
237      }
238
239     if ( $DrawAxisValues )
240      {
241       if ( $LabelsBackground )
242        $Options = array("DrawBox"=>TRUE, "Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"BoxR"=>$LabelsBGR,"BoxG"=>$LabelsBGG,"BoxB"=>$LabelsBGB,"BoxAlpha"=>$LabelsBGAlpha);
243       else
244        $Options = array("Align"=>TEXT_ALIGN_MIDDLEMIDDLE);
245
246       if ( $AxisBoxRounded ) { $Options["BoxRounded"] = TRUE; }
247
248       $Options["FontName"] = $AxisFontName;
249       $Options["FontSize"] = $AxisFontSize;
250
251       $Angle  = 360 / ($Points*2);
252       for($j=1;$j<=$Segments;$j++)
253        {
254         $Label  = $j * $SegmentHeight;
255
256         if ( $Layout == RADAR_LAYOUT_CIRCLE )
257          {
258           $EdgeX1 = cos(deg2rad($Angle+$AxisRotation)) * ($EdgeHeight/$Segments)*$j + $CenterX;
259           $EdgeY1 = sin(deg2rad($Angle+$AxisRotation)) * ($EdgeHeight/$Segments)*$j + $CenterY;
260          }
261         elseif ( $Layout == RADAR_LAYOUT_STAR )
262          {
263           $EdgeX1 = cos(deg2rad($AxisRotation)) * ($EdgeHeight/$Segments)*$j + $CenterX;
264           $EdgeY1 = sin(deg2rad($AxisRotation)) * ($EdgeHeight/$Segments)*$j + $CenterY;
265           $EdgeX2 = cos(deg2rad((360 / $Points) + $AxisRotation)) * ($EdgeHeight/$Segments)*$j + $CenterX;
266           $EdgeY2 = sin(deg2rad((360 / $Points) + $AxisRotation)) * ($EdgeHeight/$Segments)*$j + $CenterY;
267
268           $EdgeX1 = ($EdgeX2 - $EdgeX1)/2 + $EdgeX1;
269           $EdgeY1 = ($EdgeY2 - $EdgeY1)/2 + $EdgeY1;
270          }
271
272         $Object->drawText($EdgeX1,$EdgeY1,$Label,$Options);
273        }
274      }
275
276     /* Axis lines */
277     $ID = 0;
278     for($i=0;$i<360;$i=$i+(360/$Points))
279      {
280       $EdgeX = cos(deg2rad($i+$AxisRotation)) * ($EdgeHeight+$TicksLength) + $CenterX;
281       $EdgeY = sin(deg2rad($i+$AxisRotation)) * ($EdgeHeight+$TicksLength) + $CenterY;
282
283       if ($ID % $SkipLabels == 0)
284        { $Object->drawLine($CenterX,$CenterY,$EdgeX,$EdgeY,$Color); }
285       else
286        { $Object->drawLine($CenterX,$CenterY,$EdgeX,$EdgeY,$ColorDotted); }
287
288       if ( $WriteLabels )
289        {
290         $LabelX = cos(deg2rad($i+$AxisRotation+$Axisoffset)) * ($EdgeHeight+$LabelPadding+$TicksLength) + $CenterX;
291         $LabelY = sin(deg2rad($i+$AxisRotation+$Axisoffset)) * ($EdgeHeight+$LabelPadding+$TicksLength) + $CenterY;
292
293         if ( $LabelSerie != "" )
294          { $Label = isset($Data["Series"][$LabelSerie]["Data"][$ID]) ? $Data["Series"][$LabelSerie]["Data"][$ID] : ""; }
295         else
296          $Label = $ID;
297
298         if ($ID % $SkipLabels == 0)
299          {
300           if ( $LabelPos == RADAR_LABELS_ROTATED )
301            $Object->drawText($LabelX,$LabelY,$Label,array("Angle"=>(360-($i+$AxisRotation+$Axisoffset))-90,"Align"=>TEXT_ALIGN_BOTTOMMIDDLE));
302           else
303            {
304             if ( (floor($LabelX) == floor($CenterX)) && (floor($LabelY) <  floor($CenterY)) )	{ $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); }
305             if ( (floor($LabelX) >  floor($CenterX)) && (floor($LabelY) <  floor($CenterY)) )	{ $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_BOTTOMLEFT)); }
306             if ( (floor($LabelX) >  floor($CenterX)) && (floor($LabelY) == floor($CenterY)) )	{ $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_MIDDLELEFT)); }
307             if ( (floor($LabelX) >  floor($CenterX)) && (floor($LabelY) >  floor($CenterY)) )	{ $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_TOPLEFT)); }
308             if ( (floor($LabelX) <  floor($CenterX)) && (floor($LabelY) <  floor($CenterY)) )	{ $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_BOTTOMRIGHT)); }
309             if ( (floor($LabelX) <  floor($CenterX)) && (floor($LabelY) == floor($CenterY)) )	{ $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_MIDDLERIGHT)); }
310             if ( (floor($LabelX) <  floor($CenterX)) && (floor($LabelY) >  floor($CenterY)) )	{ $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_TOPRIGHT)); }
311             if ( (floor($LabelX) == floor($CenterX)) && (floor($LabelY) >  floor($CenterY)) )	{ $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_TOPMIDDLE)); }
312            }
313          }
314        }
315       $ID++;
316      }
317
318     /* Compute the plots position */
319     $ID = 0; $Plot = "";
320     foreach($Data["Series"] as $SerieName => $DataS)
321      {
322       if ( $SerieName != $LabelSerie )
323        {
324         $Color = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"],"Surrounding"=>$PointSurrounding);
325         foreach($DataS["Data"] as $Key => $Value)
326          {
327           $Angle  = (360/$Points) * $Key;
328           $Length = ($EdgeHeight/($Segments*$SegmentHeight))*$Value;
329
330           $X = cos(deg2rad($Angle+$AxisRotation)) * $Length  + $CenterX;
331           $Y = sin(deg2rad($Angle+$AxisRotation)) * $Length  + $CenterY;
332
333           $Plot[$ID][] = array($X,$Y,$Value);
334
335           if ( $RecordImageMap ) { $this->pChartObject->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".floor($PointRadius),$this->pChartObject->toHTMLColor($Palette[$ID]["R"],$Palette[$ID]["G"],$Palette[$ID]["B"]),$DataS["Description"],$Data["Series"][$LabelSerie]["Data"][$Key]." = ".$Value); }
336          }
337         $ID++;
338        }
339      }
340
341     /* Draw all that stuff! */
342     foreach($Plot as $ID => $Points)
343      {
344       $Color = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"],"Surrounding"=>$PointSurrounding);
345
346       /* Draw the polygons */
347       if ( $DrawPoly )
348        {
349         if ($PolyAlpha != NULL)
350          $Color = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$PolyAlpha,"Surrounding"=>$PointSurrounding);
351
352         $PointsArray = "";
353         for($i=0; $i<count($Points);$i++)
354          { $PointsArray[] = $Points[$i][0]; $PointsArray[] = $Points[$i][1]; }
355         $Object->drawPolygon($PointsArray,$Color);
356        }
357
358       $Color = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"],"Surrounding"=>$PointSurrounding);
359
360       /* Bubble and labels settings */
361       $TextSettings = array("Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"FontName"=>$ValueFontName,"FontSize"=>$ValueFontSize,"R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"]);
362       $InnerColor = array("R"=>$InnerBubbleR,"G"=>$InnerBubbleG,"B"=>$InnerBubbleB,"Alpha"=>$InnerBubbleAlpha);
363       if ( $OuterBubbleR != VOID )
364        $OuterColor = array("R"=>$OuterBubbleR,"G"=>$OuterBubbleG,"B"=>$OuterBubbleB,"Alpha"=>$OuterBubbleAlpha);
365       else
366        $OuterColor = array("R"=>$Palette[$ID]["R"]+20,"G"=>$Palette[$ID]["G"]+20,"B"=>$Palette[$ID]["B"]+20,"Alpha"=>$Palette[$ID]["Alpha"]);
367
368       /* Loop to the starting points if asked */
369       if ( $LineLoopStart && $DrawLines )
370        $Object->drawLine($Points[count($Points)-1][0],$Points[count($Points)-1][1],$Points[0][0],$Points[0][1],$Color);
371
372       /* Draw the lines & points */
373       for($i=0; $i<count($Points);$i++)
374        {
375         if ( $DrawLines && $i < count($Points)-1)
376          $Object->drawLine($Points[$i][0],$Points[$i][1],$Points[$i+1][0],$Points[$i+1][1],$Color);
377
378         if ( $DrawPoints )
379          $Object->drawFilledCircle($Points[$i][0],$Points[$i][1],$PointRadius,$Color);
380
381         if ( $WriteValuesInBubble && $WriteValues )
382          {
383           $TxtPos = $this->pChartObject->getTextBox($Points[$i][0],$Points[$i][1],$ValueFontName,$ValueFontSize,0,$Points[$i][2]);
384           $Radius = floor(($TxtPos[1]["X"] - $TxtPos[0]["X"] + $ValuePadding*2)/2);
385
386           $this->pChartObject->drawFilledCircle($Points[$i][0],$Points[$i][1],$Radius+$OuterBubbleRadius,$OuterColor);
387           $this->pChartObject->drawFilledCircle($Points[$i][0],$Points[$i][1],$Radius,$InnerColor);
388          }
389
390         if ( $WriteValues )
391          $this->pChartObject->drawText($Points[$i][0]-1,$Points[$i][1]-1,$Points[$i][2],$TextSettings);
392        }
393      }
394    }
395
396
397
398   /* Draw a radar chart */
399   function drawPolar($Object,$Values,$Format="")
400    {
401     $this->pChartObject = $Object;
402
403     $FixedMax		= isset($Format["FixedMax"]) ? $Format["FixedMax"] : VOID;
404     $AxisR		= isset($Format["AxisR"]) ? $Format["AxisR"] : 60;
405     $AxisG		= isset($Format["AxisG"]) ? $Format["AxisG"] : 60;
406     $AxisB		= isset($Format["AxisB"]) ? $Format["AxisB"] : 60;
407     $AxisAlpha		= isset($Format["AxisAlpha"]) ? $Format["AxisAlpha"] : 50;
408     $AxisRotation      = isset($Format["AxisRotation"]) ? $Format["AxisRotation"] : -90;
409     $DrawTicks		= isset($Format["DrawTicks"]) ? $Format["DrawTicks"] : TRUE;
410     $TicksLength	= isset($Format["TicksLength"]) ? $Format["TicksLength"] : 2;
411     $DrawAxisValues	= isset($Format["DrawAxisValues"]) ? $Format["DrawAxisValues"] : TRUE;
412     $AxisBoxRounded	= isset($Format["AxisBoxRounded"]) ? $Format["AxisBoxRounded"] : TRUE;
413     $AxisFontName	= isset($Format["FontName"]) ? $Format["FontName"] : $this->pChartObject->FontName;
414     $AxisFontSize	= isset($Format["FontSize"]) ? $Format["FontSize"] : $this->pChartObject->FontSize;
415     $WriteValues	= isset($Format["WriteValues"]) ? $Format["WriteValues"] : FALSE;
416     $WriteValuesInBubble = isset($Format["WriteValuesInBubble"]) ? $Format["WriteValuesInBubble"] : TRUE;
417     $ValueFontName	= isset($Format["ValueFontName"]) ? $Format["ValueFontName"] : $this->pChartObject->FontName;
418     $ValueFontSize	= isset($Format["ValueFontSize"]) ? $Format["ValueFontSize"] : $this->pChartObject->FontSize;
419     $ValuePadding	= isset($Format["ValuePadding"]) ? $Format["ValuePadding"] : 4;
420     $OuterBubbleRadius	= isset($Format["OuterBubbleRadius"]) ? $Format["OuterBubbleRadius"] : 2;
421     $OuterBubbleR	= isset($Format["OuterBubbleR"]) ? $Format["OuterBubbleR"] : VOID;
422     $OuterBubbleG	= isset($Format["OuterBubbleG"]) ? $Format["OuterBubbleG"] : VOID;
423     $OuterBubbleB	= isset($Format["OuterBubbleB"]) ? $Format["OuterBubbleB"] : VOID;
424     $OuterBubbleAlpha	= isset($Format["OuterBubbleAlpha"]) ? $Format["OuterBubbleAlpha"] : 100;
425     $InnerBubbleR	= isset($Format["InnerBubbleR"]) ? $Format["InnerBubbleR"] : 255;
426     $InnerBubbleG	= isset($Format["InnerBubbleG"]) ? $Format["InnerBubbleG"] : 255;
427     $InnerBubbleB	= isset($Format["InnerBubbleB"]) ? $Format["InnerBubbleB"] : 255;
428     $InnerBubbleAlpha	= isset($Format["InnerBubbleAlpha"]) ? $Format["InnerBubbleAlpha"] : 100;
429     $DrawBackground	= isset($Format["DrawBackground"]) ? $Format["DrawBackground"] : TRUE;
430     $BackgroundR	= isset($Format["BackgroundR"]) ? $Format["BackgroundR"] : 255;
431     $BackgroundG	= isset($Format["BackgroundG"]) ? $Format["BackgroundG"] : 255;
432     $BackgroundB	= isset($Format["BackgroundB"]) ? $Format["BackgroundB"] : 255;
433     $BackgroundAlpha	= isset($Format["BackgroundAlpha"]) ? $Format["BackgroundAlpha"] : 50;
434     $BackgroundGradient= isset($Format["BackgroundGradient"]) ? $Format["BackgroundGradient"] : NULL;
435     $AxisSteps		= isset($Format["AxisSteps"]) ? $Format["AxisSteps"] : 20;
436     $SegmentHeight	= isset($Format["SegmentHeight"]) ? $Format["SegmentHeight"] : SEGMENT_HEIGHT_AUTO;
437     $Segments		= isset($Format["Segments"]) ? $Format["Segments"] : 4;
438     $WriteLabels	= isset($Format["WriteLabels"]) ? $Format["WriteLabels"] : TRUE;
439     $LabelsBackground	= isset($Format["LabelsBackground"]) ? $Format["LabelsBackground"] : TRUE;
440     $LabelsBGR		= isset($Format["LabelsBGR"]) ? $Format["LabelsBGR"] : 255;
441     $LabelsBGG		= isset($Format["LabelsBGR"]) ? $Format["LabelsBGG"] : 255;
442     $LabelsBGB		= isset($Format["LabelsBGR"]) ? $Format["LabelsBGB"] : 255;
443     $LabelsBGAlpha	= isset($Format["LabelsBGAlpha"]) ? $Format["LabelsBGAlpha"] : 50;
444     $LabelPos		= isset($Format["LabelPos"]) ? $Format["LabelPos"] : RADAR_LABELS_ROTATED;
445     $LabelPadding	= isset($Format["LabelPadding"]) ? $Format["LabelPadding"] : 4;
446     $DrawPoints	= isset($Format["DrawPoints"]) ? $Format["DrawPoints"] : TRUE;
447     $PointRadius	= isset($Format["PointRadius"]) ? $Format["PointRadius"] : 4;
448     $PointSurrounding	= isset($Format["PointRadius"]) ? $Format["PointRadius"] : -30;
449     $DrawLines		= isset($Format["DrawLines"]) ? $Format["DrawLines"] : TRUE;
450     $LineLoopStart	= isset($Format["LineLoopStart"]) ? $Format["LineLoopStart"] : FALSE;
451     $DrawPoly		= isset($Format["DrawPoly"]) ? $Format["DrawPoly"] : FALSE;
452     $PolyAlpha		= isset($Format["PolyAlpha"]) ? $Format["PolyAlpha"] : NULL;
453     $FontSize		= $Object->FontSize;
454     $X1		= $Object->GraphAreaX1;
455     $Y1		= $Object->GraphAreaY1;
456     $X2		= $Object->GraphAreaX2;
457     $Y2		= $Object->GraphAreaY2;
458     $RecordImageMap	= isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE;
459
460     if ( $AxisBoxRounded ) { $DrawAxisValues = TRUE; }
461
462     /* Cancel default tick length if ticks not enabled */
463     if ( $DrawTicks == FALSE ) { $TicksLength = 0; }
464
465     /* Data Processing */
466     $Data    = $Values->getData();
467     $Palette = $Values->getPalette();
468
469     /* Catch the number of required axis */
470     $LabelSerie = $Data["Abscissa"];
471     if ( $LabelSerie != "" )
472      { $Points = count($Data["Series"][$LabelSerie]["Data"]); }
473     else
474      {
475       $Points = 0;
476       foreach($Data["Series"] as $SerieName => $DataArray)
477        { if ( count($DataArray["Data"]) > $Points ) { $Points = count($DataArray["Data"]); } }
478      }
479
480     /* Draw the axis */
481     $CenterX = ($X2-$X1)/2 + $X1;
482     $CenterY = ($Y2-$Y1)/2 + $Y1;
483
484     $EdgeHeight = min(($X2-$X1)/2,($Y2-$Y1)/2);
485     if ( $WriteLabels )
486      $EdgeHeight = $EdgeHeight - $FontSize - $LabelPadding - $TicksLength;
487
488     /* Determine the scale if set to automatic */
489     if ( $SegmentHeight == SEGMENT_HEIGHT_AUTO)
490      {
491       if ( $FixedMax != VOID )
492        $Max = $FixedMax;
493       else
494        {
495         $Max = 0;
496         foreach($Data["Series"] as $SerieName => $DataArray)
497          {
498           if ( $SerieName != $LabelSerie )
499            {
500             if ( max($DataArray["Data"]) > $Max ) { $Max = max($DataArray["Data"]); }
501            }
502          }
503         }
504       $MaxSegments = $EdgeHeight/20;
505       $Scale = $Object->computeScale(0,$Max,$MaxSegments,array(1,2,5));
506
507       $Segments      = $Scale["Rows"];
508       $SegmentHeight = $Scale["RowHeight"];
509      }
510
511
512     /* Background processing */
513     if ( $DrawBackground )
514      {
515       $RestoreShadow = $Object->Shadow;
516       $Object->Shadow = FALSE;
517
518       if ($BackgroundGradient == NULL)
519        {
520         $Color = array("R"=>$BackgroundR,"G"=>$BackgroundG,"B"=>$BackgroundB,"Alpha"=>$BackgroundAlpha);
521         $Object->drawFilledCircle($CenterX,$CenterY,$EdgeHeight,$Color);
522        }
523       else
524        {
525         $GradientROffset	= ($BackgroundGradient["EndR"] - $BackgroundGradient["StartR"]) / $Segments;
526         $GradientGOffset	= ($BackgroundGradient["EndG"] - $BackgroundGradient["StartG"]) / $Segments;
527         $GradientBOffset	= ($BackgroundGradient["EndB"] - $BackgroundGradient["StartB"]) / $Segments;
528         $GradientAlphaOffset	= ($BackgroundGradient["EndAlpha"] - $BackgroundGradient["StartAlpha"]) / $Segments;
529
530         for($j=$Segments;$j>=1;$j--)
531          {
532           $Color      = array("R"=>$BackgroundGradient["StartR"]+$GradientROffset*$j,"G"=>$BackgroundGradient["StartG"]+$GradientGOffset*$j,"B"=>$BackgroundGradient["StartB"]+$GradientBOffset*$j,"Alpha"=>$BackgroundGradient["StartAlpha"]+$GradientAlphaOffset*$j);
533           $Object->drawFilledCircle($CenterX,$CenterY,($EdgeHeight/$Segments)*$j,$Color);
534          }
535        }
536       $Object->Shadow = $RestoreShadow;
537      }
538
539     /* Axis to axis lines */
540     $Color = array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha);
541     for($j=1;$j<=$Segments;$j++)
542      {
543       $Radius = ($EdgeHeight/$Segments)*$j;
544       $Object->drawCircle($CenterX,$CenterY,$Radius,$Radius,$Color);
545      }
546
547     if ( $DrawAxisValues )
548      {
549       if ( $LabelsBackground )
550        $Options = array("DrawBox"=>TRUE, "Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"BoxR"=>$LabelsBGR,"BoxG"=>$LabelsBGG,"BoxB"=>$LabelsBGB,"BoxAlpha"=>$LabelsBGAlpha);
551       else
552        $Options = array("Align"=>TEXT_ALIGN_MIDDLEMIDDLE);
553
554       if ( $AxisBoxRounded ) { $Options["BoxRounded"] = TRUE; }
555
556       $Options["FontName"] = $AxisFontName;
557       $Options["FontSize"] = $AxisFontSize;
558
559       $Angle  = 360 / ($Points*2);
560       for($j=1;$j<=$Segments;$j++)
561        {
562         $EdgeX1 = cos(deg2rad($Angle+$AxisRotation)) * ($EdgeHeight/$Segments)*$j + $CenterX;
563         $EdgeY1 = sin(deg2rad($Angle+$AxisRotation)) * ($EdgeHeight/$Segments)*$j + $CenterY;
564         $Label  = $j*$SegmentHeight;
565
566         $Object->drawText($EdgeX1,$EdgeY1,$Label,$Options);
567        }
568      }
569
570     /* Axis lines */
571     $ID = 0;
572     for($i=0;$i<=359;$i=$i+$AxisSteps)
573      {
574       $EdgeX = cos(deg2rad($i+$AxisRotation)) * ($EdgeHeight+$TicksLength) + $CenterX;
575       $EdgeY = sin(deg2rad($i+$AxisRotation)) * ($EdgeHeight+$TicksLength) + $CenterY;
576
577       $Object->drawLine($CenterX,$CenterY,$EdgeX,$EdgeY,$Color);
578
579       if ( $WriteLabels )
580        {
581         $LabelX = cos(deg2rad($i+$AxisRotation)) * ($EdgeHeight+$LabelPadding+$TicksLength) + $CenterX;
582         $LabelY = sin(deg2rad($i+$AxisRotation)) * ($EdgeHeight+$LabelPadding+$TicksLength) + $CenterY;
583         $Label = $i."�";
584
585         if ( $LabelPos == RADAR_LABELS_ROTATED )
586          $Object->drawText($LabelX,$LabelY,$Label,array("Angle"=>(360-$i),"Align"=>TEXT_ALIGN_BOTTOMMIDDLE));
587         else
588          {
589           if ( (floor($LabelX) == floor($CenterX)) && (floor($LabelY) <  floor($CenterY)) )	{ $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); }
590           if ( (floor($LabelX) >  floor($CenterX)) && (floor($LabelY) <  floor($CenterY)) )	{ $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_BOTTOMLEFT)); }
591           if ( (floor($LabelX) >  floor($CenterX)) && (floor($LabelY) == floor($CenterY)) )	{ $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_MIDDLELEFT)); }
592           if ( (floor($LabelX) >  floor($CenterX)) && (floor($LabelY) >  floor($CenterY)) )	{ $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_TOPLEFT)); }
593           if ( (floor($LabelX) <  floor($CenterX)) && (floor($LabelY) <  floor($CenterY)) )	{ $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_BOTTOMRIGHT)); }
594           if ( (floor($LabelX) <  floor($CenterX)) && (floor($LabelY) == floor($CenterY)) )	{ $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_MIDDLERIGHT)); }
595           if ( (floor($LabelX) <  floor($CenterX)) && (floor($LabelY) >  floor($CenterY)) )	{ $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_TOPRIGHT)); }
596           if ( (floor($LabelX) == floor($CenterX)) && (floor($LabelY) >  floor($CenterY)) )	{ $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_TOPMIDDLE)); }
597          }
598        }
599       $ID++;
600      }
601
602     /* Compute the plots position */
603     $ID = 0; $Plot = "";
604     foreach($Data["Series"] as $SerieName => $DataSet)
605      {
606       if ( $SerieName != $LabelSerie )
607        {
608         $Color = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"],"Surrounding"=>$PointSurrounding);
609         foreach($DataSet["Data"] as $Key => $Value)
610          {
611           $Angle  = $Data["Series"][$LabelSerie]["Data"][$Key];
612           $Length = ($EdgeHeight/($Segments*$SegmentHeight))*$Value;
613
614           $X = cos(deg2rad($Angle+$AxisRotation)) * $Length  + $CenterX;
615           $Y = sin(deg2rad($Angle+$AxisRotation)) * $Length  + $CenterY;
616
617           if ( $RecordImageMap ) { $this->pChartObject->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".floor($PointRadius),$this->pChartObject->toHTMLColor($Palette[$ID]["R"],$Palette[$ID]["G"],$Palette[$ID]["B"]),$DataSet["Description"],$Data["Series"][$LabelSerie]["Data"][$Key]."&deg = ".$Value); }
618
619           $Plot[$ID][] = array($X,$Y,$Value);
620          }
621         $ID++;
622        }
623      }
624
625     /* Draw all that stuff! */
626     foreach($Plot as $ID => $Points)
627      {
628       $Color = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"],"Surrounding"=>$PointSurrounding);
629
630       /* Draw the polygons */
631       if ( $DrawPoly )
632        {
633         if ($PolyAlpha != NULL)
634          $Color = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$PolyAlpha,"Surrounding"=>$PointSurrounding);
635
636         $PointsArray = "";
637         for($i=0; $i<count($Points);$i++)
638          { $PointsArray[] = $Points[$i][0]; $PointsArray[] = $Points[$i][1]; }
639
640         $Object->drawPolygon($PointsArray,$Color);
641        }
642
643       $Color = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"],"Surrounding"=>$PointSurrounding);
644
645       /* Bubble and labels settings */
646       $TextSettings = array("Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"FontName"=>$ValueFontName,"FontSize"=>$ValueFontSize,"R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"]);
647       $InnerColor = array("R"=>$InnerBubbleR,"G"=>$InnerBubbleG,"B"=>$InnerBubbleB,"Alpha"=>$InnerBubbleAlpha);
648       if ( $OuterBubbleR != VOID )
649        $OuterColor = array("R"=>$OuterBubbleR,"G"=>$OuterBubbleG,"B"=>$OuterBubbleB,"Alpha"=>$OuterBubbleAlpha);
650       else
651        $OuterColor = array("R"=>$Palette[$ID]["R"]+20,"G"=>$Palette[$ID]["G"]+20,"B"=>$Palette[$ID]["B"]+20,"Alpha"=>$Palette[$ID]["Alpha"]);
652
653       /* Loop to the starting points if asked */
654       if ( $LineLoopStart && $DrawLines )
655        $Object->drawLine($Points[count($Points)-1][0],$Points[count($Points)-1][1],$Points[0][0],$Points[0][1],$Color);
656
657       /* Draw the lines & points */
658       for($i=0; $i<count($Points);$i++)
659        {
660         if ( $DrawLines && $i < count($Points)-1)
661          $Object->drawLine($Points[$i][0],$Points[$i][1],$Points[$i+1][0],$Points[$i+1][1],$Color);
662
663         if ( $DrawPoints )
664          $Object->drawFilledCircle($Points[$i][0],$Points[$i][1],$PointRadius,$Color);
665
666         if ( $WriteValuesInBubble && $WriteValues )
667          {
668           $TxtPos = $this->pChartObject->getTextBox($Points[$i][0],$Points[$i][1],$ValueFontName,$ValueFontSize,0,$Points[$i][2]);
669           $Radius = floor(($TxtPos[1]["X"] - $TxtPos[0]["X"] + $ValuePadding*2)/2);
670
671           $this->pChartObject->drawFilledCircle($Points[$i][0],$Points[$i][1],$Radius+$OuterBubbleRadius,$OuterColor);
672           $this->pChartObject->drawFilledCircle($Points[$i][0],$Points[$i][1],$Radius,$InnerColor);
673          }
674
675         if ( $WriteValues )
676          $this->pChartObject->drawText($Points[$i][0]-1,$Points[$i][1]-1,$Points[$i][2],$TextSettings);
677        }
678      }
679    }
680  }
681?>