WindrosePlot::_StrokeWindLeg()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 26
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 17
c 1
b 0
f 0
nc 2
nop 8
dl 0
loc 26
rs 9.7

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/**
4
 * JPGraph v4.0.3
5
 */
6
7
namespace Amenadiel\JpGraph\Plot;
8
9
use Amenadiel\JpGraph\Graph;
10
use Amenadiel\JpGraph\Image;
11
use Amenadiel\JpGraph\Text;
12
use Amenadiel\JpGraph\Util;
13
14
define('WINDROSE_TYPE4', 1);
15
define('WINDROSE_TYPE8', 2);
16
define('WINDROSE_TYPE16', 3);
17
define('WINDROSE_TYPEFREE', 4);
18
19
/*
20
 * How should the labels for the circular grids be aligned
21
 */
22
define('LBLALIGN_CENTER', 1);
23
define('LBLALIGN_TOP', 2);
24
25
/*
26
 * How should the labels around the plot be align
27
 */
28
define('LBLPOSITION_CENTER', 1);
29
define('LBLPOSITION_EDGE', 2);
30
31
/*
32
 * Interpretation of ordinal values in the data
33
 */
34
define('KEYENCODING_CLOCKWISE', 1);
35
define('KEYENCODING_ANTICLOCKWISE', 2);
36
37
// Internal debug flag
38
define('__DEBUG', false);
39
define('RANGE_OVERLAPPING', 0);
40
define('RANGE_DISCRETE', 1);
41
42
/**
43
 * @class WindrosePlot
44
 */
45
class WindrosePlot
46
{
47
    private $iAntiAlias          = true;
48
    private $iData               = [];
49
    public $iX                   = 0.5;
50
    public $iY                   = 0.5;
51
    public $iSize                = 0.55;
52
    private $iGridColor1         = 'gray';
53
    private $iGridColor2         = 'darkgreen';
54
    private $iRadialColorArray   = [];
55
    private $iRadialWeightArray  = [];
56
    private $iRadialStyleArray   = [];
57
    private $iRanges             = [1, 2, 3, 5, 6, 10, 13.5, 99.0];
58
    private $iRangeStyle         = RANGE_OVERLAPPING;
59
    public $iCenterSize          = 60;
60
    private $iType               = WINDROSE_TYPE16;
61
    public $iFontFamily          = FF_VERDANA;
62
    public $iFontStyle           = FS_NORMAL;
63
    public $iFontSize            = 10;
64
    public $iFontColor           = 'darkgray';
65
    private $iRadialGridStyle    = 'longdashed';
66
    private $iAllDirectionLabels = ['E', 'ENE', 'NE', 'NNE', 'N', 'NNW', 'NW', 'WNW', 'W', 'WSW', 'SW', 'SSW', 'S', 'SSE', 'SE', 'ESE'];
67
    private $iStandardDirections = [];
68
    private $iCircGridWeight     = 3;
69
    private $iRadialGridWeight   = 1;
70
    private $iLabelMargin        = 12;
71
    private $iLegweights         = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20];
72
    private $iLegColors          = ['orange', 'black', 'blue', 'red', 'green', 'purple', 'navy', 'yellow', 'brown'];
73
    private $iLabelFormatString  = '';
74
    private $iLabels             = [];
75
    private $iLabelPositioning   = LBLPOSITION_EDGE;
76
    private $iColor              = 'white';
77
    private $iShowBox            = false;
78
    private $iBoxColor           = 'black';
79
    private $iBoxWeight          = 1;
80
    private $iBoxStyle           = 'solid';
81
    private $iOrdinalEncoding    = KEYENCODING_ANTICLOCKWISE;
82
    public $legend;
83
84
    public function __construct($aData)
85
    {
86
        $this->iData  = $aData;
87
        $this->legend = new LegendStyle();
88
89
        // Setup the scale
90
        $this->scale = new Graph\WindrosePlotScale($this->iData);
0 ignored issues
show
Bug Best Practice introduced by
The property scale does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
91
92
        // default label for free type i agle and a degree sign
93
        $this->iLabelFormatString = '%.1f' . Graph\SymChar::Get('degree');
94
95
        $delta = 2 * M_PI / 16;
96
        for ($i = 0, $a = 0; $i < 16; ++$i, $a += $delta) {
97
            $this->iStandardDirections[$this->iAllDirectionLabels[$i]] = $a;
98
        }
99
    }
100
101
    // Dummy method to make window plots have the same signature as the
102
    // layout classes since windrose plots are "leaf" classes in the hierarchy
103
    public function LayoutSize()
104
    {
105
        return 1;
106
    }
107
108
    public function SetSize($aSize)
109
    {
110
        $this->iSize = $aSize;
111
    }
112
113
    public function SetDataKeyEncoding($aEncoding)
114
    {
115
        $this->iOrdinalEncoding = $aEncoding;
116
    }
117
118
    public function SetColor($aColor)
119
    {
120
        $this->iColor = $aColor;
121
    }
122
123
    public function SetRadialColors($aColors)
124
    {
125
        $this->iRadialColorArray = $aColors;
126
    }
127
128
    public function SetRadialWeights($aWeights)
129
    {
130
        $this->iRadialWeightArray = $aWeights;
131
    }
132
133
    public function SetRadialStyles($aStyles)
134
    {
135
        $this->iRadialStyleArray = $aStyles;
136
    }
137
138
    public function SetBox($aColor = 'black', $aWeight = 1, $aStyle = 'solid', $aShow = true)
139
    {
140
        $this->iShowBox   = $aShow;
141
        $this->iBoxColor  = $aColor;
142
        $this->iBoxWeight = $aWeight;
143
        $this->iBoxStyle  = $aStyle;
144
    }
145
146
    public function SetLabels($aLabels)
147
    {
148
        $this->iLabels = $aLabels;
149
    }
150
151
    public function SetLabelMargin($aMarg)
152
    {
153
        $this->iLabelMargin = $aMarg;
154
    }
155
156
    public function SetLabelFormat($aLblFormat)
157
    {
158
        $this->iLabelFormatString = $aLblFormat;
159
    }
160
161
    public function SetCompassLabels($aLabels)
162
    {
163
        if (safe_count($aLabels) != 16) {
164
            Util\JpGraphError::RaiseL(22004); //('Label specification for windrose directions must have 16 values (one for each compass direction).');
165
        }
166
        $this->iAllDirectionLabels = $aLabels;
167
168
        $delta = 2 * M_PI / 16;
169
        for ($i = 0, $a = 0; $i < 16; ++$i, $a += $delta) {
170
            $this->iStandardDirections[$this->iAllDirectionLabels[$i]] = $a;
171
        }
172
    }
173
174
    public function SetCenterSize($aSize)
175
    {
176
        $this->iCenterSize = $aSize;
177
    }
178
179
    // Alias for SetCenterSize
180
    public function SetZCircleSize($aSize)
181
    {
182
        $this->iCenterSize = $aSize;
183
    }
184
185
    public function SetFont($aFFam, $aFStyle = FS_NORMAL, $aFSize = 10)
186
    {
187
        $this->iFontFamily = $aFFam;
188
        $this->iFontStyle  = $aFStyle;
189
        $this->iFontSize   = $aFSize;
190
    }
191
192
    public function SetFontColor($aColor)
193
    {
194
        $this->iFontColor = $aColor;
195
    }
196
197
    public function SetGridColor($aColor1, $aColor2)
198
    {
199
        $this->iGridColor1 = $aColor1;
200
        $this->iGridColor2 = $aColor2;
201
    }
202
203
    public function SetGridWeight($aGrid1 = 1, $aGrid2 = 2)
204
    {
205
        $this->iCircGridWeight   = $aGrid1;
206
        $this->iRadialGridWeight = $aGrid2;
207
    }
208
209
    public function SetRadialGridStyle($aStyle)
210
    {
211
        $aStyle = strtolower($aStyle);
212
        if (!in_array($aStyle, ['solid', 'dotted', 'dashed', 'longdashed'], true)) {
213
            Util\JpGraphError::RaiseL(22005); //("Line style for radial lines must be on of ('solid','dotted','dashed','longdashed') ");
214
        }
215
        $this->iRadialGridStyle = $aStyle;
216
    }
217
218
    public function SetRanges($aRanges)
219
    {
220
        $this->iRanges = $aRanges;
221
    }
222
223
    public function SetRangeStyle($aStyle)
224
    {
225
        $this->iRangeStyle = $aStyle;
226
    }
227
228
    public function SetRangeColors($aLegColors)
229
    {
230
        $this->iLegColors = $aLegColors;
231
    }
232
233
    public function SetRangeWeights($aWeights)
234
    {
235
        $n = safe_count($aWeights);
236
        for ($i = 0; $i < $n; ++$i) {
237
            $aWeights[$i] = floor($aWeights[$i] / 2);
238
        }
239
        $this->iLegweights = $aWeights;
240
    }
241
242
    public function SetType($aType)
243
    {
244
        if ($aType < WINDROSE_TYPE4 || $aType > WINDROSE_TYPEFREE) {
245
            Util\JpGraphError::RaiseL(22006); //('Illegal windrose type specified.');
246
        }
247
        $this->iType = $aType;
248
    }
249
250
    // Alias for SetPos()
251
    public function SetCenterPos($aX, $aY)
252
    {
253
        $this->iX = $aX;
254
        $this->iY = $aY;
255
    }
256
257
    public function SetPos($aX, $aY)
258
    {
259
        $this->iX = $aX;
260
        $this->iY = $aY;
261
    }
262
263
    public function SetAntiAlias($aFlag)
264
    {
265
        $this->iAntiAlias = $aFlag;
266
        if (!$aFlag) {
267
            $this->iCircGridWeight = 1;
268
        }
269
    }
270
271
    public function _ThickCircle($aImg, $aXC, $aYC, $aRad, $aWeight, $aColor)
272
    {
273
        $aImg->SetColor($aColor);
274
        $aRad *= 2;
275
        $aImg->Ellipse($aXC, $aYC, $aRad, $aRad);
276
        if ($aWeight > 1) {
277
            $aImg->Ellipse($aXC, $aYC, $aRad + 1, $aRad + 1);
278
            $aImg->Ellipse($aXC, $aYC, $aRad + 2, $aRad + 2);
279
            if ($aWeight > 2) {
280
                $aImg->Ellipse($aXC, $aYC, $aRad + 3, $aRad + 3);
281
                $aImg->Ellipse($aXC, $aYC, $aRad + 3, $aRad + 4);
282
                $aImg->Ellipse($aXC, $aYC, $aRad + 4, $aRad + 3);
283
            }
284
        }
285
    }
286
287
    public function _StrokeWindLeg($aImg, $xc, $yc, $a, $ri, $r, $weight, $color)
288
    {
289
        // If less than 1 px long then we assume this has been caused by rounding problems
290
        // and should not be stroked
291
        if ($r < 1) {
292
            return;
293
        }
294
295
        $xt  = $xc + cos($a) * $ri;
296
        $yt  = $yc - sin($a) * $ri;
297
        $xxt = $xc + cos($a) * ($ri + $r);
298
        $yyt = $yc - sin($a) * ($ri + $r);
299
300
        $x1 = $xt - $weight * sin($a);
301
        $y1 = $yt - $weight * cos($a);
302
        $x2 = $xxt - $weight * sin($a);
303
        $y2 = $yyt - $weight * cos($a);
304
305
        $x3 = $xxt + $weight * sin($a);
306
        $y3 = $yyt + $weight * cos($a);
307
        $x4 = $xt + $weight * sin($a);
308
        $y4 = $yt + $weight * cos($a);
309
310
        $pts = [$x1, $y1, $x2, $y2, $x3, $y3, $x4, $y4];
311
        $aImg->SetColor($color);
312
        $aImg->FilledPolygon($pts);
313
    }
314
315
    public function _StrokeLegend($aImg, $x, $y, $scaling = 1, $aReturnWidth = false)
316
    {
317
        if (!$this->legend->iShow) {
318
            return 0;
319
        }
320
321
        $nlc = safe_count($this->iLegColors);
322
        $nlw = safe_count($this->iLegweights);
323
324
        // Setup font for ranges
325
        $value = new Text\Text();
326
        $value->SetAlign('center', 'bottom');
327
        $value->SetFont(
328
            $this->legend->iLblFontFamily,
329
            $this->legend->iLblFontStyle,
330
            $this->legend->iLblFontSize * $scaling
331
        );
332
        $value->SetColor($this->legend->iLblFontColor);
333
334
        // Remember x-center
335
        $xcenter = $x;
336
337
        // Construct format string
338
        $fmt = $this->legend->iFormatString . '-' . $this->legend->iFormatString;
339
340
        // Make sure that the length of each range is enough to cover the
341
        // size of the labels
342
        $tst = sprintf($fmt, $this->iRanges[0], $this->iRanges[1]);
343
        $value->Set($tst);
344
        $w = $value->GetWidth($aImg);
345
        $l = round(max($this->legend->iLength * $scaling, $w * 1.5));
346
347
        $r   = $this->legend->iCircleRadius * $scaling;
348
        $len = 2 * $r + $this->scale->iMaxNum * $l;
349
350
        // We are called just to find out the width
351
        if ($aReturnWidth) {
352
            return $len;
353
        }
354
355
        $x -= round($len / 2);
356
        $x += $r;
357
358
        // 4 pixels extra vertical margin since the circle sometimes is +/- 1 pixel of the
359
        // theorethical radius due to imperfection in the GD library
360
        //$y -= round(max($r,$scaling*$this->iLegweights[($this->scale->iMaxNum-1) % $nlw])+4*$scaling);
361
        $y -= ($this->legend->iCircleRadius + 2) * $scaling + $this->legend->iBottomMargin * $scaling;
362
363
        // Adjust for bottom text
364
        if ($this->legend->iTxt != '') {
365
            // Setup font for text
366
            $value->Set($this->legend->iTxt);
367
            $y -= /*$this->legend->iTxtMargin + */$value->GetHeight($aImg);
368
        }
369
370
        // Stroke 0-circle
371
        $this->_ThickCircle(
372
            $aImg,
373
            $x,
374
            $y,
375
            $r,
376
            $this->legend->iCircleWeight,
377
            $this->legend->iCircleColor
378
        );
379
380
        // Remember the center of the circe
381
        $xc = $x;
382
        $yc = $y;
383
384
        $value->SetAlign('center', 'bottom');
385
        $x += $r + 1;
386
387
        // Stroke all used ranges
388
        $txty = $y -
389
        round($this->iLegweights[($this->scale->iMaxNum - 1) % $nlw] * $scaling) - 4 * $scaling;
390
        if ($this->scale->iMaxNum >= safe_count($this->iRanges)) {
391
            Util\JpGraphError::RaiseL(22007); //('To few values for the range legend.');
392
        }
393
        $i   = 0;
394
        $idx = 0;
395
        while ($i < $this->scale->iMaxNum) {
396
            $y1 = $y - round($this->iLegweights[$i % $nlw] * $scaling);
397
            $y2 = $y + round($this->iLegweights[$i % $nlw] * $scaling);
398
            $x2 = $x + $l;
399
            $aImg->SetColor($this->iLegColors[$i % $nlc]);
400
            $aImg->FilledRectangle($x, $y1, $x2, $y2);
401
            if ($this->iRangeStyle == RANGE_OVERLAPPING) {
402
                $lbl = sprintf($fmt, $this->iRanges[$idx], $this->iRanges[$idx + 1]);
403
            } else {
404
                $lbl = sprintf($fmt, $this->iRanges[$idx], $this->iRanges[$idx + 1]);
405
                ++$idx;
406
            }
407
            $value->Set($lbl);
408
            $value->Stroke($aImg, $x + $l / 2, $txty);
409
            $x = $x2;
410
            ++$i;
411
            ++$idx;
412
        }
413
414
        // Setup circle font
415
        $value->SetFont(
416
            $this->legend->iCircleFontFamily,
417
            $this->legend->iCircleFontStyle,
418
            $this->legend->iCircleFontSize * $scaling
419
        );
420
        $value->SetColor($this->legend->iCircleFontColor);
421
422
        // Stroke 0-circle text
423
        $value->Set($this->legend->iZCircleTxt);
424
        $value->SetAlign('center', 'center');
425
        $value->ParagraphAlign('center');
426
        $value->Stroke($aImg, $xc, $yc);
427
428
        // Setup circle font
429
        $value->SetFont(
430
            $this->legend->iTxtFontFamily,
431
            $this->legend->iTxtFontStyle,
432
            $this->legend->iTxtFontSize * $scaling
433
        );
434
        $value->SetColor($this->legend->iTxtFontColor);
435
436
        // Draw the text under the legend
437
        $value->Set($this->legend->iTxt);
438
        $value->SetAlign('center', 'top');
439
        $value->SetParagraphAlign('center');
440
        $value->Stroke($aImg, $xcenter, $y2 + $this->legend->iTxtMargin * $scaling);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $y2 does not seem to be defined for all execution paths leading up to this point.
Loading history...
441
    }
442
443
    public function SetAutoScaleAngle($aIsRegRose = true)
444
    {
445
        // If the user already has manually set an angle don't
446
        // trye to find a position
447
        if (is_numeric($this->scale->iAngle)) {
448
            return;
449
        }
450
451
        if ($aIsRegRose) {
452
            // Create a complete data for all directions
453
            // and translate string directions to ordinal values.
454
            // This will much simplify the logic below
455
            for ($i = 0; $i < 16; ++$i) {
456
                $dtxt = $this->iAllDirectionLabels[$i];
457
                if (!empty($this->iData[$dtxt])) {
458
                    $data[$i] = $this->iData[$dtxt];
459
                } elseif (!empty($this->iData[strtolower($dtxt)])) {
460
                    $data[$i] = $this->iData[strtolower($dtxt)];
461
                } elseif (!empty($this->iData[$i])) {
462
                    $data[$i] = $this->iData[$i];
463
                } else {
464
                    $data[$i] = [];
465
                }
466
            }
467
468
            // Find the leg which has the lowest weighted sum of number of data around it
469
            $c0    = array_sum($data[0]);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $data does not seem to be defined for all execution paths leading up to this point.
Loading history...
470
            $c1    = array_sum($data[1]);
471
            $found = 1;
472
            $min   = $c0 + $c1 * 100; // Initialize to a high value
473
            for ($i = 1; $i < 15; ++$i) {
474
                $c2 = array_sum($data[$i + 1]);
475
476
                // Weight the leg we will use more to give preference
477
                // to a short middle leg even if the 3 way sum is similair
478
                $w = $c0 + 3 * $c1 + $c2;
479
                if ($w < $min) {
480
                    $min   = $w;
481
                    $found = $i;
482
                }
483
                $c0 = $c1;
484
                $c1 = $c2;
485
            }
486
            $this->scale->iAngle = $found * 22.5;
487
        } else {
488
            $n = safe_count($this->iData);
0 ignored issues
show
Unused Code introduced by
The assignment to $n is dead and can be removed.
Loading history...
489
            foreach ($this->iData as $dir => $leg) {
490
                if (!is_numeric($dir)) {
491
                    $pos = array_search(strtoupper($dir), $this->iAllDirectionLabels, true);
492
                    if ($pos !== false) {
493
                        $dir = $pos * 22.5;
494
                    }
495
                }
496
                $data[round($dir)] = $leg;
497
            }
498
499
            // Get all the angles for the data and sort it
500
            $keys = array_keys($data);
501
            sort($keys, SORT_NUMERIC);
502
503
            $n     = safe_count($data);
504
            $found = false;
505
            $max   = 0;
506
            for ($i = 0; $i < 15; ++$i) {
507
                $try_a = round(22.5 * $i);
508
509
                if ($try_a > $keys[$n - 1]) {
510
                    break;
511
                }
512
513
                if (in_array($try_a, $keys, true)) {
514
                    continue;
515
                }
516
517
                // Find the angle just lower than this
518
                $j = 0;
519
                while ($j < $n && $keys[$j] <= $try_a) {
520
                    ++$j;
521
                }
522
523
                if ($j == 0) {
524
                    $kj = 0;
525
                    $keys[$n - 1];
526
                    $d1 = 0;
527
                    abs($kj - $try_a);
528
                } else {
529
                    --$j;
530
                    $kj = $keys[$j];
531
                    $d1 = abs($kj - $try_a);
532
                }
533
534
                // Find the angle just larger than this
535
                $l = $n - 1;
536
                while ($l >= 0 && $keys[$l] >= $try_a) {
537
                    --$l;
538
                }
539
540
                if ($l == $n - 1) {
541
                    $kl = $keys[0];
542
                    $d2 = abs($kl - $try_a);
543
                } else {
544
                    ++$l;
545
                    $kl = $keys[$l];
546
                    $d2 = abs($kl - $try_a);
547
                }
548
549
                // Weight the distance so that legs with large spread
550
                // gets a better weight
551
                $w = $d1 + $d2;
552
                if ($i == 0) {
553
                    $w = round(1.4 * $w);
554
                }
555
                $diff = abs($d1 - $d2);
556
                $w *= (360 - $diff);
557
                if ($w > $max) {
558
                    $found = $i;
559
                    $max   = $w;
560
                }
561
            }
562
563
            $a = $found * 22.5;
564
565
            // Some heuristics to have some preferred positions
566
            if ($keys[$n - 1] < 25) {
567
                $a = 45;
568
            } elseif ($keys[0] > 60) {
569
                $a = 45;
570
            } elseif ($keys[0] > 25 && $keys[$n - 1] < 340) {
571
                $a = 0;
572
            } elseif ($keys[$n - 1] < 75) {
573
                $a = 90;
574
            } elseif ($keys[$n - 1] < 120) {
575
                $a = 135;
576
            } elseif ($keys[$n - 1] < 160) {
577
                $a = 180;
578
            }
579
580
            $this->scale->iAngle = $a;
581
        }
582
    }
583
584
    public function NormAngle($a)
585
    {
586
        while ($a > 360) {
587
            $a -= 360;
588
        }
589
590
        return $a;
591
    }
592
593
    public function SetLabelPosition($aPos)
594
    {
595
        $this->iLabelPositioning = $aPos;
596
    }
597
598
    public function _StrokeFreeRose($dblImg, $value, $scaling, $xc, $yc, $r, $ri)
599
    {
600
        // Plot radial grid lines and remember the end position
601
        // and the angle for later use when plotting the labels
602
        if ($this->iType != WINDROSE_TYPEFREE) {
603
            Util\JpGraphError::RaiseL(22008); //('Internal error: Trying to plot free Windrose even though type is not a free windorose');
604
        }
605
606
        // Check if we should auto-position the angle for the
607
        // labels. Basically we try to find a firection with smallest
608
        // (or none) data.
609
        $this->SetAutoScaleAngle(false);
610
611
        $nlc = safe_count($this->iLegColors);
612
        $nlw = safe_count($this->iLegweights);
613
614
        // Stroke grid lines for directions and remember the
615
        // position for the labels
616
        $txtpos = [];
617
        $num    = safe_count($this->iData);
618
619
        $keys = array_keys($this->iData);
620
621
        foreach ($this->iData as $dir => $legdata) {
622
            if (in_array($dir, $this->iAllDirectionLabels, true) === true) {
623
                $a = $this->iStandardDirections[strtoupper($dir)];
624
                if (in_array($a * 180 / M_PI, $keys, true)) {
625
                    Util\JpGraphError::RaiseL(22009, round($a * 180 / M_PI));
626
                    //('You have specified the same direction twice, once with an angle and once with a compass direction ('.$a*180/M_PI.' degrees.)');
627
                }
628
            } elseif (is_numeric($dir)) {
629
                $this->NormAngle($dir);
630
631
                if ($this->iOrdinalEncoding == KEYENCODING_CLOCKWISE) {
632
                    $dir = 360 - $dir;
633
                }
634
635
                $a = $dir * M_PI / 180;
636
            } else {
637
                Util\JpGraphError::RaiseL(22010); //('Direction must either be a numeric value or one of the 16 compass directions');
638
            }
639
640
            $xxc = round($xc + cos($a) * $ri);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $a does not seem to be defined for all execution paths leading up to this point.
Loading history...
641
            $yyc = round($yc - sin($a) * $ri);
642
            $x   = round($xc + cos($a) * $r);
643
            $y   = round($yc - sin($a) * $r);
644
            if (empty($this->iRadialColorArray[$dir])) {
645
                $dblImg->SetColor($this->iGridColor2);
646
            } else {
647
                $dblImg->SetColor($this->iRadialColorArray[$dir]);
648
            }
649
            if (empty($this->iRadialWeightArray[$dir])) {
650
                $dblImg->SetLineWeight($this->iRadialGridWeight);
651
            } else {
652
                $dblImg->SetLineWeight($this->iRadialWeightArray[$dir]);
653
            }
654
            if (empty($this->iRadialStyleArray[$dir])) {
655
                $dblImg->SetLineStyle($this->iRadialGridStyle);
656
            } else {
657
                $dblImg->SetLineStyle($this->iRadialStyleArray[$dir]);
658
            }
659
            $dblImg->StyleLine($xxc, $yyc, $x, $y);
660
            $txtpos[] = [$x, $y, $a];
661
        }
662
        $dblImg->SetLineWeight(1);
663
664
        // Setup labels
665
        $lr = $scaling * $this->iLabelMargin;
666
667
        if ($this->iLabelPositioning == LBLPOSITION_EDGE) {
668
            $value->SetAlign('left', 'top');
669
        } else {
670
            $value->SetAlign('center', 'center');
671
            $value->SetMargin(0);
672
        }
673
674
        for ($i = 0; $i < $num; ++$i) {
675
            list($x, $y, $a) = $txtpos[$i];
676
677
            // Determine the label
678
679
            $da = $a * 180 / M_PI;
680
            if ($this->iOrdinalEncoding == KEYENCODING_CLOCKWISE) {
681
                $da = 360 - $da;
682
            }
683
684
            //$da = 360-$da;
685
686
            if (!empty($this->iLabels[$keys[$i]])) {
687
                $lbl = $this->iLabels[$keys[$i]];
688
            } else {
689
                $lbl = sprintf($this->iLabelFormatString, $da);
690
            }
691
692
            if ($this->iLabelPositioning == LBLPOSITION_CENTER) {
693
                $dx = $dy = 0;
694
            } else {
695
                // LBLPOSIITON_EDGE
696
                if ($a >= 7 * M_PI / 4 || $a <= M_PI / 4) {
697
                    $dx = 0;
698
                }
699
700
                if ($a >= M_PI / 4 && $a <= 3 * M_PI / 4) {
701
                    $dx = ($a - M_PI / 4) * 2 / M_PI;
702
                }
703
704
                if ($a >= 3 * M_PI / 4 && $a <= 5 * M_PI / 4) {
705
                    $dx = 1;
706
                }
707
708
                if ($a >= 5 * M_PI / 4 && $a <= 7 * M_PI / 4) {
709
                    $dx = (1 - ($a - M_PI * 5 / 4) * 2 / M_PI);
710
                }
711
712
                if ($a >= 7 * M_PI / 4) {
713
                    $dy = (($a - M_PI) - 3 * M_PI / 4) * 2 / M_PI;
714
                }
715
716
                if ($a <= M_PI / 4) {
717
                    $dy = (0.5 + $a * 2 / M_PI);
718
                }
719
720
                if ($a >= M_PI / 4 && $a <= 3 * M_PI / 4) {
721
                    $dy = 1;
722
                }
723
724
                if ($a >= 3 * M_PI / 4 && $a <= 5 * M_PI / 4) {
725
                    $dy = (1 - ($a - 3 * M_PI / 4) * 2 / M_PI);
726
                }
727
728
                if ($a >= 5 * M_PI / 4 && $a <= 7 * M_PI / 4) {
729
                    $dy = 0;
730
                }
731
            }
732
733
            $value->Set($lbl);
734
            $th = $value->GetHeight($dblImg);
735
            $tw = $value->GetWidth($dblImg);
736
            $xt = round($lr * cos($a) + $x) - $dx * $tw;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dx does not seem to be defined for all execution paths leading up to this point.
Loading history...
737
            $yt = round($y - $lr * sin($a)) - $dy * $th;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dy does not seem to be defined for all execution paths leading up to this point.
Loading history...
738
739
            $value->Stroke($dblImg, $xt, $yt);
740
        }
741
742
        if (__DEBUG) {
743
            $dblImg->SetColor('red');
744
            $dblImg->Circle($xc, $yc, $lr + $r);
745
        }
746
747
        // Stroke all the legs
748
        reset($this->iData);
749
        $i = 0;
750
        foreach ($this->iData as $dir => $legdata) {
751
            $legdata = array_slice($legdata, 1);
752
            $nn      = safe_count($legdata);
753
754
            $a   = $txtpos[$i][2];
755
            $rri = $ri / $scaling;
756
            for ($j = 0; $j < $nn; ++$j) {
757
                // We want the non scaled original radius
758
                $legr = $this->scale->RelTranslate($legdata[$j], $r / $scaling, $ri / $scaling);
759
                $this->_StrokeWindLeg(
760
                    $dblImg,
761
                    $xc,
762
                    $yc,
763
                    $a,
764
                    $rri * $scaling,
765
                    $legr * $scaling,
766
                    $this->iLegweights[$j % $nlw] * $scaling,
767
                    $this->iLegColors[$j % $nlc]
768
                );
769
                $rri += $legr;
770
            }
771
            ++$i;
772
        }
773
    }
774
775
    // Translate potential string specified compass labels to their
776
    // corresponding index.
777
    public function FixupIndexes($aDataArray, $num)
778
    {
779
        $ret  = [];
780
        $keys = array_keys($aDataArray);
781
        foreach ($aDataArray as $idx => $data) {
782
            if (is_string($idx)) {
783
                $idx = strtoupper($idx);
784
                $res = array_search($idx, $this->iAllDirectionLabels, true);
785
                if ($res === false) {
786
                    Util\JpGraphError::RaiseL(22011, $idx); //('Windrose index must be numeric or direction label. You have specified index='.$idx);
787
                }
788
                $idx = $res;
789
                if ($idx % (16 / $num) !== 0) {
790
                    Util\JpGraphError::RaiseL(22012); //('Windrose radial axis specification contains a direction which is not enabled.');
791
                }
792
                $idx /= (16 / $num);
793
794
                if (in_array($idx, $keys, 1)) {
795
                    Util\JpGraphError::RaiseL(22013, $idx); //('You have specified the look&feel for the same compass direction twice, once with text and once with index (Index='.$idx.')');
796
                }
797
            }
798
            if ($idx < 0 || $idx > 15) {
799
                Util\JpGraphError::RaiseL(22014); //('Index for copmass direction must be between 0 and 15.');
800
            }
801
            $ret[$idx] = $data;
802
        }
803
804
        return $ret;
805
    }
806
807
    public function _StrokeRegularRose($dblImg, $value, $scaling, $xc, $yc, $r, $ri)
808
    {
809
        // _StrokeRegularRose($dblImg,$xc,$yc,$r,$ri)
810
        // Plot radial grid lines and remember the end position
811
        // and the angle for later use when plotting the labels
812
        switch ($this->iType) {
813
            case WINDROSE_TYPE4:
814
                $num = 4;
815
816
                break;
817
            case WINDROSE_TYPE8:
818
                $num = 8;
819
820
                break;
821
            case WINDROSE_TYPE16:
822
                $num = 16;
823
824
                break;
825
            default:
826
                Util\JpGraphError::RaiseL(22015); //('You have specified an undefined Windrose plot type.');
827
        }
828
829
        // Check if we should auto-position the angle for the
830
        // labels. Basically we try to find a firection with smallest
831
        // (or none) data.
832
        $this->SetAutoScaleAngle(true);
833
834
        $nlc = safe_count($this->iLegColors);
835
        $nlw = safe_count($this->iLegweights);
836
837
        $this->iRadialColorArray  = $this->FixupIndexes($this->iRadialColorArray, $num);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $num does not seem to be defined for all execution paths leading up to this point.
Loading history...
838
        $this->iRadialWeightArray = $this->FixupIndexes($this->iRadialWeightArray, $num);
839
        $this->iRadialStyleArray  = $this->FixupIndexes($this->iRadialStyleArray, $num);
840
841
        $txtpos = [];
842
        $a      = 2 * M_PI / $num;
843
        $dblImg->SetColor($this->iGridColor2);
844
        $dblImg->SetLineStyle($this->iRadialGridStyle);
845
        $dblImg->SetLineWeight($this->iRadialGridWeight);
846
847
        // Translate any name specified directions to the index
848
        // so we can easily use it in the loop below
849
        for ($i = 0; $i < $num; ++$i) {
850
            $xxc = round($xc + cos($a * $i) * $ri);
851
            $yyc = round($yc - sin($a * $i) * $ri);
852
            $x   = round($xc + cos($a * $i) * $r);
853
            $y   = round($yc - sin($a * $i) * $r);
854
            if (empty($this->iRadialColorArray[$i])) {
855
                $dblImg->SetColor($this->iGridColor2);
856
            } else {
857
                $dblImg->SetColor($this->iRadialColorArray[$i]);
858
            }
859
            if (empty($this->iRadialWeightArray[$i])) {
860
                $dblImg->SetLineWeight($this->iRadialGridWeight);
861
            } else {
862
                $dblImg->SetLineWeight($this->iRadialWeightArray[$i]);
863
            }
864
            if (empty($this->iRadialStyleArray[$i])) {
865
                $dblImg->SetLineStyle($this->iRadialGridStyle);
866
            } else {
867
                $dblImg->SetLineStyle($this->iRadialStyleArray[$i]);
868
            }
869
870
            $dblImg->StyleLine($xxc, $yyc, $x, $y);
871
            $txtpos[] = [$x, $y, $a * $i];
872
        }
873
        $dblImg->SetLineWeight(1);
874
875
        $lr = $scaling * $this->iLabelMargin;
876
        if ($this->iLabelPositioning == LBLPOSITION_CENTER) {
877
            $value->SetAlign('center', 'center');
878
        } else {
879
            $value->SetAlign('left', 'top');
880
            $value->SetMargin(0);
881
            $lr /= 2;
882
        }
883
884
        for ($i = 0; $i < $num; ++$i) {
885
            list($x, $y, $a) = $txtpos[$i];
886
887
            // Set the position of the label
888
            if ($this->iLabelPositioning == LBLPOSITION_CENTER) {
889
                $dx = $dy = 0;
890
            } else {
891
                // LBLPOSIITON_EDGE
892
                if ($a >= 7 * M_PI / 4 || $a <= M_PI / 4) {
893
                    $dx = 0;
894
                }
895
896
                if ($a >= M_PI / 4 && $a <= 3 * M_PI / 4) {
897
                    $dx = ($a - M_PI / 4) * 2 / M_PI;
898
                }
899
900
                if ($a >= 3 * M_PI / 4 && $a <= 5 * M_PI / 4) {
901
                    $dx = 1;
902
                }
903
904
                if ($a >= 5 * M_PI / 4 && $a <= 7 * M_PI / 4) {
905
                    $dx = (1 - ($a - M_PI * 5 / 4) * 2 / M_PI);
906
                }
907
908
                if ($a >= 7 * M_PI / 4) {
909
                    $dy = (($a - M_PI) - 3 * M_PI / 4) * 2 / M_PI;
910
                }
911
912
                if ($a <= M_PI / 4) {
913
                    $dy = (0.5 + $a * 2 / M_PI);
914
                }
915
916
                if ($a >= M_PI / 4 && $a <= 3 * M_PI / 4) {
917
                    $dy = 1;
918
                }
919
920
                if ($a >= 3 * M_PI / 4 && $a <= 5 * M_PI / 4) {
921
                    $dy = (1 - ($a - 3 * M_PI / 4) * 2 / M_PI);
922
                }
923
924
                if ($a >= 5 * M_PI / 4 && $a <= 7 * M_PI / 4) {
925
                    $dy = 0;
926
                }
927
            }
928
929
            $value->Set($this->iAllDirectionLabels[$i * (16 / $num)]);
930
            $th = $value->GetHeight($dblImg);
931
            $tw = $value->GetWidth($dblImg);
932
            $xt = round($lr * cos($a) + $x) - $dx * $tw;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dx does not seem to be defined for all execution paths leading up to this point.
Loading history...
933
            $yt = round($y - $lr * sin($a)) - $dy * $th;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dy does not seem to be defined for all execution paths leading up to this point.
Loading history...
934
935
            $value->Stroke($dblImg, $xt, $yt);
936
        }
937
938
        if (__DEBUG) {
939
            $dblImg->SetColor('red');
940
            $dblImg->Circle($xc, $yc, $lr + $r);
941
        }
942
943
        // Stroke all the legs
944
        reset($this->iData);
945
        $keys = array_keys($this->iData);
946
        foreach ($this->iData as $idx => $legdata) {
947
            $legdata = array_slice($legdata, 1);
948
            $nn      = safe_count($legdata);
949
            if (is_string($idx)) {
950
                $idx = strtoupper($idx);
951
                $idx = array_search($idx, $this->iAllDirectionLabels, true);
952
                if ($idx === false) {
953
                    Util\JpGraphError::RaiseL(22016); //('Windrose leg index must be numeric or direction label.');
954
                }
955
                if ($idx % (16 / $num) !== 0) {
956
                    Util\JpGraphError::RaiseL(22017); //('Windrose data contains a direction which is not enabled. Please adjust what labels are displayed.');
957
                }
958
                $idx /= (16 / $num);
959
960
                if (in_array($idx, $keys, 1)) {
961
                    Util\JpGraphError::RaiseL(22018, $idx); //('You have specified data for the same compass direction twice, once with text and once with index (Index='.$idx.')');
962
                }
963
            }
964
            if ($idx < 0 || $idx > 15) {
965
                Util\JpGraphError::RaiseL(22019); //('Index for direction must be between 0 and 15. You can\'t specify angles for a Regular Windplot, only index and compass directions.');
966
            }
967
            $a = $idx * (360 / $num);
968
            $a *= M_PI / 180.0;
969
            $rri = $ri / $scaling;
970
            for ($j = 0; $j < $nn; ++$j) {
971
                // We want the non scaled original radius
972
                $legr = $this->scale->RelTranslate($legdata[$j], $r / $scaling, $ri / $scaling);
973
                $this->_StrokeWindLeg(
974
                    $dblImg,
975
                    $xc,
976
                    $yc,
977
                    $a,
978
                    $rri * $scaling,
979
                    $legr * $scaling,
980
                    $this->iLegweights[$j % $nlw] * $scaling,
981
                    $this->iLegColors[$j % $nlc]
982
                );
983
                $rri += $legr;
984
            }
985
        }
986
    }
987
988
    public function getWidth($aImg)
989
    {
990
        $scaling = 1; //$this->iAntiAlias ? 2 : 1 ;
991
        if ($this->iSize > 0 && $this->iSize < 1) {
992
            $this->iSize *= min($aImg->width, $aImg->height);
993
        }
994
995
        $value = new Text\Text();
996
        $value->SetFont($this->iFontFamily, $this->iFontStyle, $this->iFontSize * $scaling);
997
        $value->SetColor($this->iFontColor);
998
        // Setup extra size around the graph needed so that the labels
999
        // doesn't get cut. For this we need to find the largest label.
1000
        // The code below gives a possible a little to large margin. The
1001
        // really, really proper way would be to account for what angle
1002
        // the label are at
1003
        $n = safe_count($this->iLabels);
1004
        if ($n > 0) {
1005
            $maxh = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $maxh is dead and can be removed.
Loading history...
1006
            $maxw = 0;
1007
            foreach ($this->iLabels as $key => $lbl) {
1008
                $value->Set($lbl);
1009
                $maxw = max($maxw, $value->GetWidth($aImg));
1010
            }
1011
        } else {
1012
            $value->Set('888.888'); // Dummy value to get width/height
1013
            $maxw = $value->GetWidth($aImg);
1014
        }
1015
        // Add an extra margin of 50% the font size
1016
        $maxw += round($this->iFontSize * $scaling * 0.4);
1017
1018
        $valxmarg = 1.5 * $maxw + 2 * $this->iLabelMargin * $scaling;
1019
        $w        = round($this->iSize * $scaling + $valxmarg);
1020
1021
        // Make sure that the width of the legend fits
1022
        $legendwidth = $this->_StrokeLegend($aImg, 0, 0, $scaling, true) + 10 * $scaling;
1023
        $w           = max($w, $legendwidth);
1024
1025
        return $w;
1026
    }
1027
1028
    public function getHeight($aImg)
1029
    {
1030
        $scaling = 1; //$this->iAntiAlias ? 2 : 1 ;
1031
        if ($this->iSize > 0 && $this->iSize < 1) {
1032
            $this->iSize *= min($aImg->width, $aImg->height);
1033
        }
1034
1035
        $value = new Text\Text();
1036
        $value->SetFont($this->iFontFamily, $this->iFontStyle, $this->iFontSize * $scaling);
1037
        $value->SetColor($this->iFontColor);
1038
        // Setup extra size around the graph needed so that the labels
1039
        // doesn't get cut. For this we need to find the largest label.
1040
        // The code below gives a possible a little to large margin. The
1041
        // really, really proper way would be to account for what angle
1042
        // the label are at
1043
        $n = safe_count($this->iLabels);
1044
        if ($n > 0) {
1045
            $maxh = 0;
1046
            $maxw = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $maxw is dead and can be removed.
Loading history...
1047
            foreach ($this->iLabels as $key => $lbl) {
1048
                $value->Set($lbl);
1049
                $maxh = max($maxh, $value->GetHeight($aImg));
1050
            }
1051
        } else {
1052
            $value->Set('180.8'); // Dummy value to get width/height
1053
            $maxh = $value->GetHeight($aImg);
1054
        }
1055
        // Add an extra margin of 50% the font size
1056
        //$maxh += round($this->iFontSize*$scaling * 0.5) ;
1057
        $valymarg = 2 * $maxh + 2 * $this->iLabelMargin * $scaling;
1058
1059
        $legendheight = round($this->legend->iShow ? 1 : 0);
1060
        $legendheight *= max($this->legend->iCircleRadius * 2, $this->legend->iTxtFontSize * 2) +
1061
        $this->legend->iMargin + $this->legend->iBottomMargin + 2;
1062
        $legendheight *= $scaling;
1063
        $h = round($this->iSize * $scaling + $valymarg) + $legendheight;
1064
1065
        return $h;
1066
    }
1067
1068
    public function Stroke($aGraph)
1069
    {
1070
        $aImg = $aGraph->img;
1071
1072
        if ($this->iX > 0 && $this->iX < 1) {
1073
            $this->iX = round($aImg->width * $this->iX);
1074
        }
1075
1076
        if ($this->iY > 0 && $this->iY < 1) {
1077
            $this->iY = round($aImg->height * $this->iY);
1078
        }
1079
1080
        if ($this->iSize > 0 && $this->iSize < 1) {
1081
            $this->iSize *= min($aImg->width, $aImg->height);
1082
        }
1083
1084
        if ($this->iCenterSize > 0 && $this->iCenterSize < 1) {
1085
            $this->iCenterSize *= $this->iSize;
1086
        }
1087
1088
        $this->scale->AutoScale(($this->iSize - $this->iCenterSize) / 2, round(2.5 * $this->scale->iFontSize));
1089
1090
        $scaling = $this->iAntiAlias ? 2 : 1;
1091
1092
        $value = new Text\Text();
1093
        $value->SetFont($this->iFontFamily, $this->iFontStyle, $this->iFontSize * $scaling);
1094
        $value->SetColor($this->iFontColor);
1095
1096
        $legendheight = round($this->legend->iShow ? 1 : 0);
1097
        $legendheight *= max($this->legend->iCircleRadius * 2, $this->legend->iTxtFontSize * 2) +
1098
        $this->legend->iMargin + $this->legend->iBottomMargin + 2;
1099
        $legendheight *= $scaling;
1100
1101
        $w = $scaling * $this->getWidth($aImg);
1102
        $h = $scaling * $this->getHeight($aImg);
1103
1104
        // Copy back the double buffered image to the proper canvas
1105
        $ww = $w / $scaling;
1106
        $hh = $h / $scaling;
1107
1108
        // Create the double buffer
1109
        if ($this->iAntiAlias) {
1110
            $dblImg = new Image\RotImage($w, $h);
1111
            // Set the background color
1112
            $dblImg->SetColor($this->iColor);
1113
            $dblImg->FilledRectangle(0, 0, $w, $h);
1114
        } else {
1115
            $dblImg = $aImg;
1116
            // Make sure the ix and it coordinates correpond to the new top left center
1117
            $dblImg->SetTranslation($this->iX - $w / 2, $this->iY - $h / 2);
1118
        }
1119
1120
        if (__DEBUG) {
1121
            $dblImg->SetColor('red');
1122
            $dblImg->Rectangle(0, 0, $w - 1, $h - 1);
1123
        }
1124
1125
        $dblImg->SetColor('black');
1126
1127
        if ($this->iShowBox) {
1128
            $dblImg->SetColor($this->iBoxColor);
1129
            $old = $dblImg->SetLineWeight($this->iBoxWeight);
1130
            $dblImg->SetLineStyle($this->iBoxStyle);
1131
            $dblImg->Rectangle(0, 0, $w - 1, $h - 1);
1132
            $dblImg->SetLineWeight($old);
1133
        }
1134
1135
        $xc = round($w / 2);
1136
        $yc = round(($h - $legendheight) / 2);
1137
1138
        if (__DEBUG) {
1139
            $dblImg->SetColor('red');
1140
            $old = $dblImg->SetLineWeight(2);
1141
            $dblImg->Line($xc - 5, $yc - 5, $xc + 5, $yc + 5);
1142
            $dblImg->Line($xc + 5, $yc - 5, $xc - 5, $yc + 5);
1143
            $dblImg->SetLineWeight($old);
1144
        }
1145
1146
        $this->iSize *= $scaling;
1147
1148
        // Inner circle size
1149
        $ri = $this->iCenterSize / 2;
1150
1151
        // Full circle radius
1152
        $r = round($this->iSize / 2);
1153
1154
        // Get number of grid circles
1155
        $n = $this->scale->GetNumCirc();
1156
1157
        // Plot circle grids
1158
        $ri *= $scaling;
1159
        $rr = round(($r - $ri) / $n);
1160
        for ($i = 1; $i <= $n; ++$i) {
1161
            $this->_ThickCircle(
1162
                $dblImg,
1163
                $xc,
1164
                $yc,
1165
                $rr * $i + $ri,
1166
                $this->iCircGridWeight,
1167
                $this->iGridColor1
1168
            );
1169
        }
1170
1171
        $num = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $num is dead and can be removed.
Loading history...
1172
1173
        if ($this->iType == WINDROSE_TYPEFREE) {
1174
            $this->_StrokeFreeRose($dblImg, $value, $scaling, $xc, $yc, $r, $ri);
1175
        } else {
1176
            // Check if we need to re-code the interpretation of the ordinal
1177
            // number in the data. Internally ordinal value 0 is East and then
1178
            // counted anti-clockwise. The user might choose an encoding
1179
            // that have 0 being the first axis to the right of the "N" axis and then
1180
            // counted clock-wise
1181
            if ($this->iOrdinalEncoding == KEYENCODING_CLOCKWISE) {
1182
                if ($this->iType == WINDROSE_TYPE16) {
1183
                    $const1 = 19;
1184
                    $const2 = 16;
1185
                } elseif ($this->iType == WINDROSE_TYPE8) {
1186
                    $const1 = 9;
1187
                    $const2 = 8;
1188
                } else {
1189
                    $const1 = 4;
1190
                    $const2 = 4;
1191
                }
1192
                $tmp = [];
1193
                $n   = safe_count($this->iData);
0 ignored issues
show
Unused Code introduced by
The assignment to $n is dead and can be removed.
Loading history...
1194
                foreach ($this->iData as $key => $val) {
1195
                    if (is_numeric($key)) {
1196
                        $key = ($const1 - $key) % $const2;
1197
                    }
1198
                    $tmp[$key] = $val;
1199
                }
1200
                $this->iData = $tmp;
1201
            }
1202
            $this->_StrokeRegularRose($dblImg, $value, $scaling, $xc, $yc, $r, $ri);
1203
        }
1204
1205
        // Stroke the labels
1206
        $this->scale->iFontSize *= $scaling;
1207
        $this->scale->iZFontSize *= $scaling;
1208
        $this->scale->StrokeLabels($dblImg, $xc, $yc, $ri, $rr);
1209
1210
        // Stroke the inner circle again since the legs
1211
        // might have written over it
1212
        $this->_ThickCircle($dblImg, $xc, $yc, $ri, $this->iCircGridWeight, $this->iGridColor1);
1213
1214
        if ($ww > $aImg->width) {
1215
            Util\JpGraphError::RaiseL(22020);
1216
            //('Windrose plot is too large to fit the specified Graph size. Please use WindrosePlot::SetSize() to make the plot smaller or increase the size of the Graph in the initial WindroseGraph() call.');
1217
        }
1218
1219
        $x = $xc;
1220
        $y = $h;
1221
        $this->_StrokeLegend($dblImg, $x, $y, $scaling);
1222
1223
        if ($this->iAntiAlias) {
1224
            $aImg->Copy($dblImg->img, $this->iX - $ww / 2, $this->iY - $hh / 2, 0, 0, $ww, $hh, $w, $h);
1225
        }
1226
1227
        // We need to restore the translation matrix
1228
        $aImg->SetTranslation(0, 0);
1229
    }
1230
}
1231