PluginProbe
E2Pdf – Export Pdf Tool for WordPress / 1.32.49
E2Pdf – Export Pdf Tool for WordPress v1.32.49
1.32.49 1.32.48 1.32.43 1.32.40 1.32.34 1.32.32 1.32.31 1.32.26 1.32.22 1.32.23 1.32.18 1.32.17 1.32.15 trunk 1.00.00 1.00.13 1.01.01 1.02.02 1.03.07 1.04.07 1.05.03 1.06.02 1.07.11 1.08.00 1.08.06 All 72 releases
e2pdf / vendors / svggraph / BarAndLineGraph.php

BarAndLineGraph.php in E2Pdf – Export Pdf Tool for WordPress 1.32.49, at vendors/svggraph/BarAndLineGraph.php

261 lines 7.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Copyright (C) 2015-2022 Graham Breach
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 /**
19 * For more information, please contact <graham@goat1000.com>
20 */
21
22 namespace Goat1000\SVGGraph;
23
24 class BarAndLineGraph extends GroupedBarGraph {
25
26 protected $linegraph = null;
27 protected $line_datasets = [];
28 protected $bar_datasets = [];
29
30 /**
31 * We need an instance of the LineGraph class
32 */
33 public function __construct($w, $h, array $settings, array $fixed_settings = [])
34 {
35 parent::__construct($w, $h, $settings, $fixed_settings);
36
37 // prevent repeated labels
38 unset($settings['label']);
39 $this->linegraph = new MultiLineGraph($w, $h, $settings);
40 }
41
42 /**
43 * Draws the bars and lines
44 */
45 protected function draw()
46 {
47 $body = $this->grid() . $this->underShapes();
48
49 // LineGraph has not been initialised, need to copy in details
50 $copy = ['colours', 'links', 'x_axes', 'y_axes', 'main_x_axis',
51 'main_y_axis', 'legend',
52 // needed for best-fit line support
53 'g_width', 'g_height', 'pad_left', 'pad_top'];
54 foreach($copy as $member)
55 $this->linegraph->{$member} = $this->{$member};
56
57 // keep gradients and patterns synced
58 $this->linegraph->defs =& $this->defs;
59
60 // find the lines
61 $chunk_count = count($this->multi_graph);
62 $lines = $this->getOption('line_dataset');
63 $line_breaks = [];
64 $line_points = [];
65 $line_offsets = [];
66 $points = [];
67 if(!is_array($lines))
68 $lines = [$lines];
69 rsort($lines);
70 foreach($lines as $line) {
71 $line_breaks[$line] = $this->getOption(['line_breaks', $line]);
72 $line_points[$line] = [];
73 $points[$line] = [];
74 }
75 $this->line_datasets = $lines = array_flip($lines);
76
77 $y_axis_pos = $this->height - $this->pad_bottom -
78 $this->y_axes[$this->main_y_axis]->zero();
79 $y_bottom = min($y_axis_pos, $this->height - $this->pad_bottom);
80
81 // set up bars, then find line offsets
82 $this->barSetup();
83 foreach($lines as $k => $l)
84 $line_offsets[$k] = $this->getLineOffset($k);
85
86 // draw bars, store line points
87 $datasets = $this->multi_graph->getEnabledDatasets();
88 $line_dataset = 0;
89 $bars = '';
90 foreach($this->multi_graph as $bnum => $itemlist) {
91 $item = $itemlist[0];
92 $bar_pos = $this->gridPosition($item, $bnum);
93 if($bar_pos !== null) {
94 for($j = 0; $j < $chunk_count; ++$j) {
95 if(!in_array($j, $datasets))
96 continue;
97 $y_axis = $this->datasetYAxis($j);
98 $item = $itemlist[$j];
99
100 if(array_key_exists($j, $lines)) {
101 $line_dataset = $j;
102 if($line_breaks[$line_dataset] && $item->value === null &&
103 count($points[$line_dataset]) > 0) {
104 $line_points[$line_dataset][] = $points[$line_dataset];
105 $points[$line_dataset] = [];
106 } elseif($item->value !== null) {
107 $x = $bar_pos + $line_offsets[$line_dataset];
108 $y = $this->gridY($item->value, $y_axis);
109 $points[$line_dataset][] = [$x, $y, $item, $line_dataset, $bnum];
110 }
111 continue;
112 }
113
114 $this->setBarLegendEntry($j, $bnum, $item);
115 $bars .= $this->drawBar($item, $bnum, 0, $y_axis, $j);
116 }
117 }
118 }
119
120 foreach($points as $line_dataset => $line) {
121 if(!empty($line))
122 $line_points[$line_dataset][] = $line;
123 }
124
125 // draw lines clipped to grid
126 $graph_line = '';
127 foreach($line_points as $dataset => $points) {
128 foreach($points as $p) {
129 $graph_line .= $this->drawLine($dataset, $p, $y_bottom);
130 }
131 }
132 $group = [];
133 $this->clipGrid($group);
134 list($best_fit_above, $best_fit_below) = $this->linegraph->bestFitLines();
135 $bars .= $best_fit_below;
136 $bars .= $this->element('g', $group, null, $graph_line);
137
138 $group = [];
139 if($this->getOption('semantic_classes'))
140 $group['class'] = 'series';
141 $shadow_id = $this->defs->getShadow();
142 if($shadow_id !== null)
143 $group['filter'] = 'url(#' . $shadow_id . ')';
144 if(!empty($group))
145 $bars = $this->element('g', $group, null, $bars);
146 $body .= $bars;
147
148 $body .= $this->overShapes();
149 $body .= $this->axes();
150
151 // add in the markers created by line graph
152 $body .= $this->linegraph->drawMarkers();
153 $body .= $best_fit_above;
154
155 return $body;
156 }
157
158 /**
159 * Sets up bar details
160 */
161 protected function barSetup()
162 {
163 parent::barSetup();
164 $datasets = $this->multi_graph->getEnabledDatasets();
165 $chunk_count = count($datasets);
166 $bar = 0;
167 foreach($datasets as $i) {
168 // reduce chunk count for lines, add bars to list
169 if(array_key_exists($i, $this->line_datasets))
170 --$chunk_count;
171 else
172 $this->bar_datasets[$i] = $bar++;
173 }
174
175 if(count($this->bar_datasets) < 1)
176 throw new \Exception('No bar datasets enabled');
177
178 list($chunk_width, $bspace, $chunk_unit_width) =
179 $this->barPosition($this->getOption('bar_width'), $this->getOption('bar_width_min'),
180 $this->x_axes[$this->main_x_axis]->unit(), $chunk_count, $this->getOption('bar_space'),
181 $this->getOption('group_space'));
182 $this->group_bar_spacing = $chunk_unit_width;
183 $this->setBarWidth($chunk_width, $bspace);
184 }
185
186 /**
187 * Fills in the x and width of bar
188 */
189 protected function barX($item, $index, &$bar, $axis, $dataset)
190 {
191 $bar_x = $this->gridPosition($item, $index);
192 if($bar_x === null)
193 return null;
194
195 // relative position of bars stored in barSetup()
196 $bar['x'] = $bar_x + $this->calculated_bar_space +
197 ($this->bar_datasets[$dataset] * $this->group_bar_spacing);
198 $bar['width'] = $this->calculated_bar_width;
199 return $bar_x;
200 }
201
202 /**
203 * Return box or line for legend
204 */
205 public function drawLegendEntry($x, $y, $w, $h, $entry)
206 {
207 if(isset($entry->style['line_style']))
208 return $this->linegraph->drawLegendEntry($x, $y, $w, $h, $entry);
209 return parent::drawLegendEntry($x, $y, $w, $h, $entry);
210 }
211
212 /**
213 * Draws this graph's data labels, and the line graph's data labels
214 */
215 protected function drawDataLabels()
216 {
217 $labels = parent::drawDataLabels();
218 $labels .= $this->linegraph->drawDataLabels();
219 return $labels;
220 }
221
222 /**
223 * Returns the normal dataset order
224 */
225 public function getLegendOrder()
226 {
227 $datasets = count($this->multi_graph);
228 return range(0, $datasets - 1);
229 }
230
231 /**
232 * Returns the horizontal offset of the line relative to the grid
233 */
234 public function getLineOffset($dataset)
235 {
236 if($this->getOption('datetime_keys'))
237 return 0;
238
239 $offset = 0;
240 $o = $this->getOption(['line_bar', $dataset]);
241 if(is_numeric($o) && in_array($o, $this->bar_datasets)) {
242 $offset = $this->calculated_bar_space +
243 ($this->dataset_offsets[$o] * $this->group_bar_spacing) +
244 ($this->calculated_bar_width / 2);
245 } else {
246 $g_width = $this->x_axes[$this->main_x_axis]->unit();
247 $offset = $g_width / 2;
248 }
249 return $offset;
250 }
251
252 /**
253 * Draws a single line
254 */
255 public function drawLine($dataset, $points, $y_bottom)
256 {
257 return $this->linegraph->drawLine($dataset, $points, $y_bottom);
258 }
259 }
260
261