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\Util; |
12
|
|
|
|
13
|
|
|
/* |
14
|
|
|
* File: JPGRAPH_BAR.PHP |
15
|
|
|
* // Description: Bar plot extension for JpGraph |
16
|
|
|
* // Created: 2001-01-08 |
17
|
|
|
* // Ver: $Id: jpgraph_bar.php 1905 2009-10-06 18:00:21Z ljp $ |
18
|
|
|
* // |
19
|
|
|
* // Copyright (c) Asial Corporation. All rights reserved. |
20
|
|
|
*/ |
21
|
|
|
// Pattern for Bars |
22
|
1 |
|
define('PATTERN_DIAG1', 1); |
23
|
1 |
|
define('PATTERN_DIAG2', 2); |
24
|
1 |
|
define('PATTERN_DIAG3', 3); |
25
|
1 |
|
define('PATTERN_DIAG4', 4); |
26
|
1 |
|
define('PATTERN_CROSS1', 5); |
27
|
1 |
|
define('PATTERN_CROSS2', 6); |
28
|
1 |
|
define('PATTERN_CROSS3', 7); |
29
|
1 |
|
define('PATTERN_CROSS4', 8); |
30
|
1 |
|
define('PATTERN_STRIPE1', 9); |
31
|
1 |
|
define('PATTERN_STRIPE2', 10); |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* @class BarPlot |
35
|
|
|
* // Description: Main code to produce a bar plot |
36
|
|
|
*/ |
37
|
|
|
class BarPlot extends Plot |
38
|
|
|
{ |
39
|
|
|
public $fill = false; |
40
|
|
|
public $fill_color = 'lightblue'; // Default is to fill with light blue |
41
|
|
|
public $iPattern = -1; |
42
|
|
|
public $iPatternDensity = 80; |
43
|
|
|
public $iPatternColor = 'black'; |
44
|
|
|
public $valuepos = 'top'; |
45
|
|
|
public $grad = false; |
46
|
|
|
public $grad_style = 1; |
47
|
|
|
public $grad_fromcolor = [50, 50, 200]; |
48
|
|
|
public $grad_tocolor = [255, 255, 255]; |
49
|
|
|
public $ymin = 0; |
50
|
|
|
protected $width = 0.4; // in percent of major ticks |
51
|
|
|
protected $abswidth = -1; // Width in absolute pixels |
52
|
|
|
protected $ybase = 0; // Bars start at 0 |
53
|
|
|
protected $align = 'center'; |
54
|
|
|
protected $bar_shadow = false; |
55
|
|
|
protected $bar_shadow_color = 'black'; |
56
|
|
|
protected $bar_shadow_hsize = 3; |
57
|
|
|
protected $bar_shadow_vsize = 3; |
58
|
|
|
protected $bar_3d = false; |
59
|
|
|
protected $bar_3d_hsize = 3; |
60
|
|
|
protected $bar_3d_vsize = 3; |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* CONSTRUCTOR. |
64
|
|
|
* |
65
|
|
|
* @param mixed $datay |
66
|
|
|
* @param mixed $datax |
67
|
|
|
*/ |
68
|
3 |
|
public function __construct($datay, $datax = false) |
69
|
|
|
{ |
70
|
3 |
|
parent::__construct($datay, $datax); |
71
|
3 |
|
++$this->numpoints; |
72
|
3 |
|
} |
73
|
|
|
|
74
|
|
|
/** |
75
|
|
|
* PUBLIC METHODS. |
76
|
|
|
* |
77
|
|
|
* @param mixed $aColor |
78
|
|
|
* @param mixed $aHSize |
79
|
|
|
* @param mixed $aVSize |
80
|
|
|
* @param mixed $aShow |
81
|
|
|
*/ |
82
|
|
|
// Set a drop shadow for the bar (or rather an "up-right" shadow) |
83
|
2 |
|
public function SetShadow($aColor = 'black', $aHSize = 3, $aVSize = 3, $aShow = true) |
84
|
|
|
{ |
85
|
2 |
|
$this->bar_shadow = $aShow; |
86
|
2 |
|
$this->bar_shadow_color = $aColor; |
87
|
2 |
|
$this->bar_shadow_vsize = $aVSize; |
88
|
2 |
|
$this->bar_shadow_hsize = $aHSize; |
89
|
|
|
|
90
|
|
|
// Adjust the value margin to compensate for shadow |
91
|
2 |
|
$this->value->margin += $aVSize; |
92
|
2 |
|
} |
93
|
|
|
|
94
|
|
|
public function Set3D($aHSize = 3, $aVSize = 3, $aShow = true) |
95
|
|
|
{ |
96
|
|
|
$this->bar_3d = $aShow; |
97
|
|
|
$this->bar_3d_vsize = $aVSize; |
98
|
|
|
$this->bar_3d_hsize = $aHSize; |
99
|
|
|
|
100
|
|
|
$this->value->margin += $aVSize; |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
// DEPRECATED use SetYBase instead |
104
|
|
|
public function SetYMin($aYStartValue) |
105
|
|
|
{ |
106
|
|
|
//die("JpGraph Error: Deprecated function SetYMin. Use SetYBase() instead."); |
107
|
|
|
$this->ybase = $aYStartValue; |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
// Specify the base value for the bars |
111
|
|
|
public function SetYBase($aYStartValue) |
112
|
|
|
{ |
113
|
|
|
$this->ybase = $aYStartValue; |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
// The method will take the specified pattern anre |
117
|
|
|
// return a pattern index that corresponds to the original |
118
|
|
|
// patterm being rotated 90 degreees. This is needed when plottin |
119
|
|
|
// Horizontal bars |
120
|
|
|
public function RotatePattern($aPat, $aRotate = true) |
121
|
|
|
{ |
122
|
|
|
$rotate = [1 => 2, 2 => 1, 3 => 3, 4 => 5, 5 => 4, 6 => 6, 7 => 7, 8 => 8]; |
123
|
|
|
if ($aRotate) { |
124
|
|
|
return $rotate[$aPat]; |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
return $aPat; |
128
|
|
|
} |
129
|
|
|
|
130
|
3 |
|
public function Legend($graph) |
131
|
|
|
{ |
132
|
3 |
|
if ($this->grad && $this->legend != '' && !$this->fill) { |
133
|
|
|
$color = [$this->grad_fromcolor, $this->grad_tocolor]; |
134
|
|
|
// In order to differentiate between gradients and cooors specified as an Image\RGB triple |
135
|
|
|
$graph->legend->Add( |
136
|
|
|
$this->legend, |
137
|
|
|
$color, |
138
|
|
|
'', |
139
|
|
|
-$this->grad_style, |
140
|
|
|
$this->legendcsimtarget, |
141
|
|
|
$this->legendcsimalt, |
142
|
|
|
$this->legendcsimwintarget |
143
|
|
|
); |
144
|
3 |
|
} elseif ($this->legend != '' && ($this->iPattern > -1 || is_array($this->iPattern))) { |
145
|
|
|
if (is_array($this->iPattern)) { |
146
|
|
|
$p1 = $this->RotatePattern($this->iPattern[0], $graph->img->a == 90); |
147
|
|
|
$p2 = $this->iPatternColor[0]; |
148
|
|
|
$p3 = $this->iPatternDensity[0]; |
149
|
|
|
} else { |
150
|
|
|
$p1 = $this->RotatePattern($this->iPattern, $graph->img->a == 90); |
151
|
|
|
$p2 = $this->iPatternColor; |
152
|
|
|
$p3 = $this->iPatternDensity; |
153
|
|
|
} |
154
|
|
|
if ($p3 < 90) { |
155
|
|
|
$p3 += 5; |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
$color = [$p1, $p2, $p3, $this->fill_color]; |
159
|
|
|
// A kludge: Too mark that we add a pattern we use a type value of < 100 |
160
|
|
|
$graph->legend->Add( |
161
|
|
|
$this->legend, |
162
|
|
|
$color, |
163
|
|
|
'', |
164
|
|
|
-101, |
165
|
|
|
$this->legendcsimtarget, |
166
|
|
|
$this->legendcsimalt, |
167
|
|
|
$this->legendcsimwintarget |
168
|
|
|
); |
169
|
3 |
|
} elseif ($this->fill_color && $this->legend != '') { |
170
|
3 |
|
if (is_array($this->fill_color)) { |
|
|
|
|
171
|
|
|
$graph->legend->Add( |
172
|
|
|
$this->legend, |
173
|
|
|
$this->fill_color[0], |
174
|
|
|
'', |
175
|
|
|
0, |
176
|
|
|
$this->legendcsimtarget, |
177
|
|
|
$this->legendcsimalt, |
178
|
|
|
$this->legendcsimwintarget |
179
|
|
|
); |
180
|
|
|
} else { |
181
|
3 |
|
$graph->legend->Add( |
182
|
3 |
|
$this->legend, |
183
|
3 |
|
$this->fill_color, |
184
|
3 |
|
'', |
185
|
3 |
|
0, |
186
|
3 |
|
$this->legendcsimtarget, |
187
|
3 |
|
$this->legendcsimalt, |
188
|
3 |
|
$this->legendcsimwintarget |
189
|
|
|
); |
190
|
|
|
} |
191
|
|
|
} |
192
|
3 |
|
} |
193
|
|
|
|
194
|
|
|
// Gets called before any axis are stroked |
195
|
3 |
|
public function PreStrokeAdjust($graph) |
196
|
|
|
{ |
197
|
3 |
|
parent::PreStrokeAdjust($graph); |
198
|
|
|
|
199
|
|
|
// If we are using a log Y-scale we want the base to be at the |
200
|
|
|
// minimum Y-value unless the user have specifically set some other |
201
|
|
|
// value than the default. |
202
|
3 |
|
if (substr($graph->axtype, -3, 3) == 'log' && $this->ybase == 0) { |
203
|
|
|
$this->ybase = $graph->yaxis->scale->GetMinVal(); |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
// For a "text" X-axis scale we will adjust the |
207
|
|
|
// display of the bars a little bit. |
208
|
3 |
|
if (substr($graph->axtype, 0, 3) == 'tex') { |
209
|
|
|
// Position the ticks between the bars |
210
|
3 |
|
$graph->xaxis->scale->ticks->SetXLabelOffset(0.5, 0); |
211
|
|
|
|
212
|
|
|
// Center the bars |
213
|
3 |
|
if ($this->abswidth > -1) { |
214
|
1 |
|
$graph->SetTextScaleAbsCenterOff($this->abswidth); |
215
|
|
|
} else { |
216
|
2 |
|
if ($this->align == 'center') { |
217
|
2 |
|
$graph->SetTextScaleOff(0.5 - $this->width / 2); |
218
|
|
|
} elseif ($this->align == 'right') { |
219
|
3 |
|
$graph->SetTextScaleOff(1 - $this->width); |
220
|
|
|
} |
221
|
|
|
} |
222
|
1 |
|
} elseif (($this instanceof AccBarPlot) || ($this instanceof GroupBarPlot)) { |
223
|
|
|
// We only set an absolute width for linear and int scale |
224
|
|
|
// for text scale the width will be set to a fraction of |
225
|
|
|
// the majstep width. |
226
|
|
|
if ($this->abswidth == -1) { |
227
|
|
|
// Not set |
228
|
|
|
// set width to a visuable sensible default |
229
|
|
|
$this->abswidth = $graph->img->plotwidth / (2 * $this->numpoints); |
230
|
|
|
} |
231
|
|
|
} |
232
|
3 |
|
} |
233
|
|
|
|
234
|
3 |
|
public function Min() |
235
|
|
|
{ |
236
|
3 |
|
$m = parent::Min(); |
237
|
3 |
|
if ($m[1] >= $this->ybase) { |
238
|
2 |
|
$m[1] = $this->ybase; |
239
|
|
|
} |
240
|
|
|
|
241
|
3 |
|
return $m; |
242
|
|
|
} |
243
|
|
|
|
244
|
3 |
|
public function Max() |
245
|
|
|
{ |
246
|
3 |
|
$m = parent::Max(); |
247
|
3 |
|
if ($m[1] <= $this->ybase) { |
248
|
|
|
$m[1] = $this->ybase; |
249
|
|
|
} |
250
|
|
|
|
251
|
3 |
|
return $m; |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
// Specify width as fractions of the major stepo size |
255
|
2 |
|
public function SetWidth($aWidth) |
256
|
|
|
{ |
257
|
2 |
|
if ($aWidth > 1) { |
258
|
|
|
// Interpret this as absolute width |
259
|
|
|
$this->abswidth = $aWidth; |
260
|
|
|
} else { |
261
|
2 |
|
$this->width = $aWidth; |
262
|
|
|
} |
263
|
2 |
|
} |
264
|
|
|
|
265
|
|
|
// Specify width in absolute pixels. If specified this |
266
|
|
|
// overrides SetWidth() |
267
|
1 |
|
public function SetAbsWidth($aWidth) |
268
|
|
|
{ |
269
|
1 |
|
$this->abswidth = $aWidth; |
270
|
1 |
|
} |
271
|
|
|
|
272
|
1 |
|
public function SetAlign($aAlign) |
273
|
|
|
{ |
274
|
1 |
|
$this->align = $aAlign; |
275
|
1 |
|
} |
276
|
|
|
|
277
|
|
|
public function SetNoFill() |
278
|
|
|
{ |
279
|
|
|
$this->grad = false; |
280
|
|
|
$this->fill_color = false; |
281
|
|
|
$this->fill = false; |
282
|
|
|
} |
283
|
|
|
|
284
|
1 |
|
public function SetFillColor($aColor) |
285
|
|
|
{ |
286
|
|
|
// Do an extra error check if the color is specified as an Image\RGB array triple |
287
|
|
|
// In that case convert it to a hex string since it will otherwise be |
288
|
|
|
// interpretated as an array of colors for each individual bar. |
289
|
|
|
|
290
|
1 |
|
$aColor = Image\RGB::tryHexConversion($aColor); |
291
|
1 |
|
$this->fill = true; |
292
|
1 |
|
$this->fill_color = $aColor; |
293
|
1 |
|
} |
294
|
|
|
|
295
|
|
|
public function SetFillGradient($aFromColor, $aToColor = null, $aStyle = null) |
296
|
|
|
{ |
297
|
|
|
$this->grad = true; |
298
|
|
|
$this->grad_fromcolor = $aFromColor; |
299
|
|
|
$this->grad_tocolor = $aToColor; |
300
|
|
|
$this->grad_style = $aStyle; |
301
|
|
|
} |
302
|
|
|
|
303
|
|
|
public function SetValuePos($aPos) |
304
|
|
|
{ |
305
|
|
|
$this->valuepos = $aPos; |
306
|
|
|
} |
307
|
|
|
|
308
|
|
|
public function SetPattern($aPattern, $aColor = 'black') |
309
|
|
|
{ |
310
|
|
|
if (is_array($aPattern)) { |
311
|
|
|
$n = safe_count($aPattern); |
312
|
|
|
$this->iPattern = []; |
313
|
|
|
$this->iPatternDensity = []; |
314
|
|
|
if (is_array($aColor)) { |
315
|
|
|
$this->iPatternColor = []; |
316
|
|
|
if (safe_count($aColor) != $n) { |
317
|
|
|
Util\JpGraphError::RaiseL(2001); //('NUmber of colors is not the same as the number of patterns in BarPlot::SetPattern()'); |
318
|
|
|
} |
319
|
|
|
} else { |
320
|
|
|
$this->iPatternColor = $aColor; |
321
|
|
|
} |
322
|
|
|
for ($i = 0; $i < $n; ++$i) { |
323
|
|
|
$this->_SetPatternHelper($aPattern[$i], $this->iPattern[$i], $this->iPatternDensity[$i]); |
324
|
|
|
if (is_array($aColor)) { |
325
|
|
|
$this->iPatternColor[$i] = $aColor[$i]; |
326
|
|
|
} |
327
|
|
|
} |
328
|
|
|
} else { |
329
|
|
|
$this->_SetPatternHelper($aPattern, $this->iPattern, $this->iPatternDensity); |
330
|
|
|
$this->iPatternColor = $aColor; |
331
|
|
|
} |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
public function _SetPatternHelper($aPattern, &$aPatternValue, &$aDensity) |
335
|
|
|
{ |
336
|
|
|
switch ($aPattern) { |
337
|
|
|
case PATTERN_DIAG1: |
338
|
|
|
$aPatternValue = 1; |
339
|
|
|
$aDensity = 92; |
340
|
|
|
|
341
|
|
|
break; |
342
|
|
|
case PATTERN_DIAG2: |
343
|
|
|
$aPatternValue = 1; |
344
|
|
|
$aDensity = 78; |
345
|
|
|
|
346
|
|
|
break; |
347
|
|
|
case PATTERN_DIAG3: |
348
|
|
|
$aPatternValue = 2; |
349
|
|
|
$aDensity = 92; |
350
|
|
|
|
351
|
|
|
break; |
352
|
|
|
case PATTERN_DIAG4: |
353
|
|
|
$aPatternValue = 2; |
354
|
|
|
$aDensity = 78; |
355
|
|
|
|
356
|
|
|
break; |
357
|
|
|
case PATTERN_CROSS1: |
358
|
|
|
$aPatternValue = 8; |
359
|
|
|
$aDensity = 90; |
360
|
|
|
|
361
|
|
|
break; |
362
|
|
|
case PATTERN_CROSS2: |
363
|
|
|
$aPatternValue = 8; |
364
|
|
|
$aDensity = 78; |
365
|
|
|
|
366
|
|
|
break; |
367
|
|
|
case PATTERN_CROSS3: |
368
|
|
|
$aPatternValue = 8; |
369
|
|
|
$aDensity = 65; |
370
|
|
|
|
371
|
|
|
break; |
372
|
|
|
case PATTERN_CROSS4: |
373
|
|
|
$aPatternValue = 7; |
374
|
|
|
$aDensity = 90; |
375
|
|
|
|
376
|
|
|
break; |
377
|
|
|
case PATTERN_STRIPE1: |
378
|
|
|
$aPatternValue = 5; |
379
|
|
|
$aDensity = 94; |
380
|
|
|
|
381
|
|
|
break; |
382
|
|
|
case PATTERN_STRIPE2: |
383
|
|
|
$aPatternValue = 5; |
384
|
|
|
$aDensity = 85; |
385
|
|
|
|
386
|
|
|
break; |
387
|
|
|
default: |
388
|
|
|
Util\JpGraphError::RaiseL(2002); |
389
|
|
|
//('Unknown pattern specified in call to BarPlot::SetPattern()'); |
390
|
|
|
} |
391
|
|
|
} |
392
|
|
|
|
393
|
3 |
|
public function Stroke($img, $xscale, $yscale) |
394
|
|
|
{ |
395
|
3 |
|
$numpoints = safe_count($this->coords[0]); |
396
|
3 |
|
if (isset($this->coords[1])) { |
397
|
1 |
|
if (safe_count($this->coords[1]) != $numpoints) { |
398
|
|
|
Util\JpGraphError::RaiseL(2003, safe_count($this->coords[1]), $numpoints); |
399
|
|
|
//"Number of X and Y points are not equal. Number of X-points:". safe_count($this->coords[1])."Number of Y-points:$numpoints"); |
400
|
|
|
} else { |
401
|
1 |
|
$exist_x = true; |
402
|
|
|
} |
403
|
|
|
} else { |
404
|
3 |
|
$exist_x = false; |
405
|
|
|
} |
406
|
|
|
|
407
|
3 |
|
$numbars = safe_count($this->coords[0]); |
408
|
|
|
|
409
|
|
|
// Use GetMinVal() instead of scale[0] directly since in the case |
410
|
|
|
// of log scale we get a correct value. Log scales will have negative |
411
|
|
|
// values for values < 1 while still not representing negative numbers. |
412
|
3 |
|
if ($yscale->GetMinVal() >= 0) { |
413
|
2 |
|
$zp = $yscale->scale_abs[0]; |
414
|
|
|
} else { |
415
|
1 |
|
$zp = $yscale->Translate(0); |
416
|
|
|
} |
417
|
|
|
|
418
|
3 |
|
if ($this->abswidth > -1) { |
419
|
1 |
|
$abswidth = $this->abswidth; |
420
|
|
|
} else { |
421
|
3 |
|
$abswidth = round($this->width * $xscale->scale_factor, 0); |
422
|
|
|
} |
423
|
|
|
|
424
|
|
|
// Count pontetial pattern array to avoid doing the count for each iteration |
425
|
3 |
|
if (is_array($this->iPattern)) { |
426
|
|
|
$np = safe_count($this->iPattern); |
427
|
|
|
} |
428
|
|
|
|
429
|
3 |
|
$grad = null; |
430
|
3 |
|
for ($i = 0; $i < $numbars; ++$i) { |
431
|
|
|
// If value is NULL, or 0 then don't draw a bar at all |
432
|
3 |
|
if ($this->coords[0][$i] === null || $this->coords[0][$i] === '') { |
433
|
|
|
continue; |
434
|
|
|
} |
435
|
|
|
|
436
|
3 |
|
if ($exist_x) { |
|
|
|
|
437
|
1 |
|
$x = $this->coords[1][$i]; |
438
|
|
|
} else { |
439
|
3 |
|
$x = $i; |
440
|
|
|
} |
441
|
|
|
|
442
|
3 |
|
$x = $xscale->Translate($x); |
443
|
|
|
|
444
|
|
|
// Comment Note: This confuses the positioning when using acc together with |
445
|
|
|
// grouped bars. Workaround for fixing #191 |
446
|
|
|
/* |
447
|
|
|
if( !$xscale->textscale ) { |
448
|
|
|
if($this->align=="center") |
449
|
|
|
$x -= $abswidth/2; |
450
|
|
|
elseif($this->align=="right") |
451
|
|
|
$x -= $abswidth; |
452
|
|
|
} |
453
|
|
|
*/ |
454
|
|
|
// Stroke fill color and fill gradient |
455
|
|
|
$pts = [ |
456
|
3 |
|
$x, $zp, |
457
|
3 |
|
$x, $yscale->Translate($this->coords[0][$i]), |
458
|
3 |
|
$x + $abswidth, $yscale->Translate($this->coords[0][$i]), |
459
|
3 |
|
$x + $abswidth, $zp, ]; |
460
|
3 |
|
if ($this->grad) { |
461
|
|
|
if ($grad === null) { |
462
|
|
|
$grad = new Gradient($img); |
463
|
|
|
} |
464
|
|
|
if (is_array($this->grad_fromcolor)) { |
465
|
|
|
// The first argument (grad_fromcolor) can be either an array or a single color. If it is an array |
466
|
|
|
// then we have two choices. It can either a) be a single color specified as an Image\RGB triple or it can be |
467
|
|
|
// an array to specify both (from, to style) for each individual bar. The way to know the difference is |
468
|
|
|
// to investgate the first element. If this element is an integer [0,255] then we assume it is an Image\RGB |
469
|
|
|
// triple. |
470
|
|
|
$ng = safe_count($this->grad_fromcolor); |
471
|
|
|
if ($ng === 3) { |
472
|
|
|
if (is_numeric($this->grad_fromcolor[0]) && $this->grad_fromcolor[0] > 0 && $this->grad_fromcolor[0] < 256) { |
473
|
|
|
// Image\RGB Triple |
474
|
|
|
$fromcolor = $this->grad_fromcolor; |
475
|
|
|
$tocolor = $this->grad_tocolor; |
476
|
|
|
$style = $this->grad_style; |
477
|
|
|
} else { |
478
|
|
|
$fromcolor = $this->grad_fromcolor[$i % $ng][0]; |
479
|
|
|
$tocolor = $this->grad_fromcolor[$i % $ng][1]; |
480
|
|
|
$style = $this->grad_fromcolor[$i % $ng][2]; |
481
|
|
|
} |
482
|
|
|
} else { |
483
|
|
|
$fromcolor = $this->grad_fromcolor[$i % $ng][0]; |
484
|
|
|
$tocolor = $this->grad_fromcolor[$i % $ng][1]; |
485
|
|
|
$style = $this->grad_fromcolor[$i % $ng][2]; |
486
|
|
|
} |
487
|
|
|
$grad->FilledRectangle( |
488
|
|
|
$pts[2], |
489
|
|
|
$pts[3], |
490
|
|
|
$pts[6], |
491
|
|
|
$pts[7], |
492
|
|
|
$fromcolor, |
493
|
|
|
$tocolor, |
494
|
|
|
$style |
495
|
|
|
); |
496
|
|
|
} else { |
497
|
|
|
$grad->FilledRectangle( |
498
|
|
|
$pts[2], |
499
|
|
|
$pts[3], |
500
|
|
|
$pts[6], |
501
|
|
|
$pts[7], |
502
|
|
|
$this->grad_fromcolor, |
503
|
|
|
$this->grad_tocolor, |
504
|
|
|
$this->grad_style |
505
|
|
|
); |
506
|
|
|
} |
507
|
3 |
|
} elseif (!empty($this->fill_color)) { |
508
|
3 |
|
if (is_array($this->fill_color)) { |
509
|
|
|
$img->PushColor($this->fill_color[$i % safe_count($this->fill_color)]); |
510
|
|
|
} else { |
511
|
3 |
|
$img->PushColor($this->fill_color); |
512
|
|
|
} |
513
|
3 |
|
$img->FilledPolygon($pts); |
514
|
3 |
|
$img->PopColor(); |
515
|
|
|
} |
516
|
|
|
|
517
|
|
|
/////////////////////////kokorahen rectangle polygon////////////////////// |
518
|
|
|
|
519
|
|
|
// Remember value of this bar |
520
|
3 |
|
$val = $this->coords[0][$i]; |
521
|
|
|
|
522
|
3 |
|
if (!empty($val) && !is_numeric($val)) { |
523
|
|
|
Util\JpGraphError::RaiseL(2004, $i, $val); |
524
|
|
|
//'All values for a barplot must be numeric. You have specified value['.$i.'] == \''.$val.'\''); |
525
|
|
|
} |
526
|
|
|
|
527
|
|
|
// Determine the shadow |
528
|
3 |
|
if ($this->bar_shadow && $val != 0) { |
529
|
2 |
|
$ssh = $this->bar_shadow_hsize; |
530
|
2 |
|
$ssv = $this->bar_shadow_vsize; |
531
|
|
|
// Create points to create a "upper-right" shadow |
532
|
2 |
|
if ($val > 0) { |
533
|
2 |
|
$sp[0] = $pts[6]; |
534
|
2 |
|
$sp[1] = $pts[7]; |
535
|
2 |
|
$sp[2] = $pts[4]; |
536
|
2 |
|
$sp[3] = $pts[5]; |
537
|
2 |
|
$sp[4] = $pts[2]; |
538
|
2 |
|
$sp[5] = $pts[3]; |
539
|
2 |
|
$sp[6] = $pts[2] + $ssh; |
540
|
2 |
|
$sp[7] = $pts[3] - $ssv; |
541
|
2 |
|
$sp[8] = $pts[4] + $ssh; |
542
|
2 |
|
$sp[9] = $pts[5] - $ssv; |
543
|
2 |
|
$sp[10] = $pts[6] + $ssh; |
544
|
2 |
|
$sp[11] = $pts[7] - $ssv; |
545
|
|
|
} elseif ($val < 0) { |
546
|
|
|
$sp[0] = $pts[4]; |
547
|
|
|
$sp[1] = $pts[5]; |
548
|
|
|
$sp[2] = $pts[6]; |
549
|
|
|
$sp[3] = $pts[7]; |
550
|
|
|
$sp[4] = $pts[0]; |
551
|
|
|
$sp[5] = $pts[1]; |
552
|
|
|
$sp[6] = $pts[0] + $ssh; |
553
|
|
|
$sp[7] = $pts[1] - $ssv; |
554
|
|
|
$sp[8] = $pts[6] + $ssh; |
555
|
|
|
$sp[9] = $pts[7] - $ssv; |
556
|
|
|
$sp[10] = $pts[4] + $ssh; |
557
|
|
|
$sp[11] = $pts[5] - $ssv; |
558
|
|
|
} |
559
|
2 |
|
if (is_array($this->bar_shadow_color)) { |
560
|
|
|
$numcolors = safe_count($this->bar_shadow_color); |
561
|
|
|
if ($numcolors == 0) { |
562
|
|
|
Util\JpGraphError::RaiseL(2005); //('You have specified an empty array for shadow colors in the bar plot.'); |
563
|
|
|
} |
564
|
|
|
$img->PushColor($this->bar_shadow_color[$i % $numcolors]); |
565
|
|
|
} else { |
566
|
2 |
|
$img->PushColor($this->bar_shadow_color); |
567
|
|
|
} |
568
|
2 |
|
$img->FilledPolygon($sp); |
|
|
|
|
569
|
2 |
|
$img->PopColor(); |
570
|
2 |
|
} elseif ($this->bar_3d && $val != 0) { |
571
|
|
|
// Determine the 3D |
572
|
|
|
|
573
|
|
|
$ssh = $this->bar_3d_hsize; |
574
|
|
|
$ssv = $this->bar_3d_vsize; |
575
|
|
|
|
576
|
|
|
// Create points to create a "upper-right" shadow |
577
|
|
|
if ($val > 0) { |
578
|
|
|
$sp1[0] = $pts[6]; |
579
|
|
|
$sp1[1] = $pts[7]; |
580
|
|
|
$sp1[2] = $pts[4]; |
581
|
|
|
$sp1[3] = $pts[5]; |
582
|
|
|
$sp1[4] = $pts[4] + $ssh; |
583
|
|
|
$sp1[5] = $pts[5] - $ssv; |
584
|
|
|
$sp1[6] = $pts[6] + $ssh; |
585
|
|
|
$sp1[7] = $pts[7] - $ssv; |
586
|
|
|
|
587
|
|
|
$sp2[0] = $pts[4]; |
588
|
|
|
$sp2[1] = $pts[5]; |
589
|
|
|
$sp2[2] = $pts[2]; |
590
|
|
|
$sp2[3] = $pts[3]; |
591
|
|
|
$sp2[4] = $pts[2] + $ssh; |
592
|
|
|
$sp2[5] = $pts[3] - $ssv; |
593
|
|
|
$sp2[6] = $pts[4] + $ssh; |
594
|
|
|
$sp2[7] = $pts[5] - $ssv; |
595
|
|
|
} elseif ($val < 0) { |
596
|
|
|
$sp1[0] = $pts[4]; |
597
|
|
|
$sp1[1] = $pts[5]; |
598
|
|
|
$sp1[2] = $pts[6]; |
599
|
|
|
$sp1[3] = $pts[7]; |
600
|
|
|
$sp1[4] = $pts[6] + $ssh; |
601
|
|
|
$sp1[5] = $pts[7] - $ssv; |
602
|
|
|
$sp1[6] = $pts[4] + $ssh; |
603
|
|
|
$sp1[7] = $pts[5] - $ssv; |
604
|
|
|
|
605
|
|
|
$sp2[0] = $pts[6]; |
606
|
|
|
$sp2[1] = $pts[7]; |
607
|
|
|
$sp2[2] = $pts[0]; |
608
|
|
|
$sp2[3] = $pts[1]; |
609
|
|
|
$sp2[4] = $pts[0] + $ssh; |
610
|
|
|
$sp2[5] = $pts[1] - $ssv; |
611
|
|
|
$sp2[6] = $pts[6] + $ssh; |
612
|
|
|
$sp2[7] = $pts[7] - $ssv; |
613
|
|
|
} |
614
|
|
|
|
615
|
|
|
$base_color = $this->fill_color; |
616
|
|
|
|
617
|
|
|
$img->PushColor($base_color . ':0.7'); |
618
|
|
|
$img->FilledPolygon($sp1); |
|
|
|
|
619
|
|
|
$img->PopColor(); |
620
|
|
|
|
621
|
|
|
$img->PushColor($base_color . ':1.1'); |
622
|
|
|
$img->FilledPolygon($sp2); |
|
|
|
|
623
|
|
|
$img->PopColor(); |
624
|
|
|
} |
625
|
|
|
|
626
|
|
|
// Stroke the pattern |
627
|
3 |
|
if (is_array($this->iPattern)) { |
628
|
|
|
$f = new Graph\RectPatternFactory(); |
629
|
|
|
if (is_array($this->iPatternColor)) { |
630
|
|
|
$pcolor = $this->iPatternColor[$i % $np]; |
|
|
|
|
631
|
|
|
} else { |
632
|
|
|
$pcolor = $this->iPatternColor; |
633
|
|
|
} |
634
|
|
|
$prect = $f->Create($this->iPattern[$i % $np], $pcolor, 1); |
635
|
|
|
$prect->SetDensity($this->iPatternDensity[$i % $np]); |
636
|
|
|
|
637
|
|
|
if ($val < 0) { |
638
|
|
|
$rx = $pts[0]; |
639
|
|
|
$ry = $pts[1]; |
640
|
|
|
} else { |
641
|
|
|
$rx = $pts[2]; |
642
|
|
|
$ry = $pts[3]; |
643
|
|
|
} |
644
|
|
|
$width = abs($pts[4] - $pts[0]) + 1; |
645
|
|
|
$height = abs($pts[1] - $pts[3]) + 1; |
646
|
|
|
$prect->SetPos(new Util\Rectangle($rx, $ry, $width, $height)); |
647
|
|
|
$prect->Stroke($img); |
648
|
|
|
} else { |
649
|
3 |
|
if ($this->iPattern > -1) { |
650
|
|
|
$f = new Graph\RectPatternFactory(); |
651
|
|
|
$prect = $f->Create($this->iPattern, $this->iPatternColor, 1); |
652
|
|
|
$prect->SetDensity($this->iPatternDensity); |
653
|
|
|
if ($val < 0) { |
654
|
|
|
$rx = $pts[0]; |
655
|
|
|
$ry = $pts[1]; |
656
|
|
|
} else { |
657
|
|
|
$rx = $pts[2]; |
658
|
|
|
$ry = $pts[3]; |
659
|
|
|
} |
660
|
|
|
$width = abs($pts[4] - $pts[0]) + 1; |
661
|
|
|
$height = abs($pts[1] - $pts[3]) + 1; |
662
|
|
|
$prect->SetPos(new Util\Rectangle($rx, $ry, $width, $height)); |
663
|
|
|
$prect->Stroke($img); |
664
|
|
|
} |
665
|
|
|
} |
666
|
|
|
|
667
|
|
|
// Stroke the outline of the bar |
668
|
3 |
|
if (is_array($this->color)) { |
669
|
|
|
$img->SetColor($this->color[$i % safe_count($this->color)]); |
670
|
|
|
} else { |
671
|
3 |
|
$img->SetColor($this->color); |
672
|
|
|
} |
673
|
|
|
|
674
|
3 |
|
$pts[] = $pts[0]; |
675
|
3 |
|
$pts[] = $pts[1]; |
676
|
|
|
|
677
|
3 |
|
if ($this->weight > 0) { |
678
|
3 |
|
$img->SetLineWeight($this->weight); |
679
|
3 |
|
$img->Polygon($pts); |
680
|
|
|
} |
681
|
|
|
|
682
|
|
|
// Determine how to best position the values of the individual bars |
683
|
3 |
|
$x = $pts[2] + ($pts[4] - $pts[2]) / 2; |
684
|
3 |
|
$this->value->SetMargin(5); |
685
|
|
|
|
686
|
3 |
|
if ($this->valuepos == 'top') { |
687
|
3 |
|
$y = $pts[3]; |
688
|
3 |
|
if ($img->a === 90) { |
689
|
|
|
if ($val < 0) { |
690
|
|
|
$this->value->SetAlign('right', 'center'); |
691
|
|
|
} else { |
692
|
|
|
$this->value->SetAlign('left', 'center'); |
693
|
|
|
} |
694
|
|
|
} else { |
695
|
3 |
|
if ($val < 0) { |
696
|
1 |
|
$this->value->SetMargin(-5); |
697
|
1 |
|
$y = $pts[1]; |
698
|
1 |
|
$this->value->SetAlign('center', 'bottom'); |
699
|
|
|
} else { |
700
|
3 |
|
$this->value->SetAlign('center', 'bottom'); |
701
|
|
|
} |
702
|
|
|
} |
703
|
3 |
|
$this->value->Stroke($img, $val, $x, $y); |
704
|
|
|
} elseif ($this->valuepos == 'max') { |
705
|
|
|
$y = $pts[3]; |
706
|
|
|
if ($img->a === 90) { |
707
|
|
|
if ($val < 0) { |
708
|
|
|
$this->value->SetAlign('left', 'center'); |
709
|
|
|
} else { |
710
|
|
|
$this->value->SetAlign('right', 'center'); |
711
|
|
|
} |
712
|
|
|
} else { |
713
|
|
|
if ($val < 0) { |
714
|
|
|
$this->value->SetAlign('center', 'bottom'); |
715
|
|
|
} else { |
716
|
|
|
$this->value->SetAlign('center', 'top'); |
717
|
|
|
} |
718
|
|
|
} |
719
|
|
|
$this->value->SetMargin(-5); |
720
|
|
|
$this->value->Stroke($img, $val, $x, $y); |
721
|
|
|
} elseif ($this->valuepos == 'center') { |
722
|
|
|
$y = ($pts[3] + $pts[1]) / 2; |
723
|
|
|
$this->value->SetAlign('center', 'center'); |
724
|
|
|
$this->value->SetMargin(0); |
725
|
|
|
$this->value->Stroke($img, $val, $x, $y); |
726
|
|
|
} elseif ($this->valuepos == 'bottom' || $this->valuepos == 'min') { |
727
|
|
|
$y = $pts[1]; |
728
|
|
|
if ($img->a === 90) { |
729
|
|
|
if ($val < 0) { |
730
|
|
|
$this->value->SetAlign('right', 'center'); |
731
|
|
|
} else { |
732
|
|
|
$this->value->SetAlign('left', 'center'); |
733
|
|
|
} |
734
|
|
|
} |
735
|
|
|
$this->value->SetMargin(3); |
736
|
|
|
$this->value->Stroke($img, $val, $x, $y); |
737
|
|
|
} else { |
738
|
|
|
Util\JpGraphError::RaiseL(2006, $this->valuepos); |
739
|
|
|
//'Unknown position for values on bars :'.$this->valuepos); |
740
|
|
|
} |
741
|
|
|
// Create the client side image map |
742
|
3 |
|
$rpts = $img->ArrRotate($pts); |
743
|
3 |
|
$csimcoord = round($rpts[0]) . ', ' . round($rpts[1]); |
744
|
3 |
|
for ($j = 1; $j < 4; ++$j) { |
745
|
3 |
|
$csimcoord .= ', ' . round($rpts[2 * $j]) . ', ' . round($rpts[2 * $j + 1]); |
746
|
|
|
} |
747
|
3 |
|
if (!empty($this->csimtargets[$i])) { |
748
|
|
|
$this->csimareas .= '<area shape="poly" coords="' . $csimcoord . '" '; |
749
|
|
|
$this->csimareas .= ' href="' . htmlentities($this->csimtargets[$i]) . '"'; |
750
|
|
|
|
751
|
|
|
if (!empty($this->csimwintargets[$i])) { |
752
|
|
|
$this->csimareas .= ' target="' . $this->csimwintargets[$i] . '" '; |
753
|
|
|
} |
754
|
|
|
|
755
|
|
|
$sval = ''; |
756
|
|
|
if (!empty($this->csimalts[$i])) { |
757
|
|
|
$sval = sprintf($this->csimalts[$i], $this->coords[0][$i]); |
758
|
|
|
$this->csimareas .= " title=\"${sval}\" alt=\"${sval}\" "; |
759
|
|
|
} |
760
|
|
|
$this->csimareas .= " />\n"; |
761
|
|
|
} |
762
|
|
|
} |
763
|
|
|
|
764
|
3 |
|
return true; |
765
|
|
|
} |
766
|
|
|
} // @class |
767
|
|
|
|
768
|
|
|
/* EOF */ |
769
|
|
|
|