PluginProbe
E2Pdf – Export Pdf Tool for WordPress / 1.32.32
E2Pdf – Export Pdf Tool for WordPress v1.32.32
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 / DisplayAxisRadar.php

DisplayAxisRadar.php in E2Pdf – Export Pdf Tool for WordPress 1.32.32, at vendors/svggraph/DisplayAxisRadar.php

288 lines 8.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Copyright (C) 2018-2021 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 /**
25 * Draws the radar graph X axis
26 */
27 class DisplayAxisRadar extends DisplayAxis {
28
29 protected $xc;
30 protected $yc;
31 protected $radius;
32 protected $arad;
33 protected $text_offset;
34 protected $no_axis;
35 protected $direction = 1;
36
37 /**
38 * $orientation = 'h' or 'v'
39 * $type = 'x' or 'y'
40 * $main = TRUE for the main axis
41 */
42 public function __construct(&$graph, &$axis, $axis_no, $orientation, $type,
43 $main, $xc, $yc, $radius)
44 {
45 // only use this class for the round axis
46 if($orientation != 'h')
47 throw new \Exception('DisplayAxisRadar: orientation != "h"');
48 $this->xc = $xc;
49 $this->yc = $yc;
50 $this->radius = $radius;
51 $this->arad = (90 + $graph->getOption('start_angle')) * M_PI / 180;
52 $this->text_offset = 0;
53 // the radar-only option for hiding axis but showing divisions
54 $this->no_axis = !$graph->getOption('show_x_axis');
55
56 // $label_centre = TRUE because the end of the axis is also the start
57 parent::__construct($graph, $axis, $axis_no, $orientation, $type, $main,
58 true);
59
60 // no boxed text because this isn't really a block-labelled axis
61 $this->boxed_text = false;
62
63 if($graph->getOption('reverse'))
64 $this->direction = -1;
65
66 // keep text next to axis
67 $this->styles['t_location'] = 'axis';
68 }
69
70 /**
71 * Returns the extents of the axis, relative to where it will be drawn from
72 * returns array('x', 'y', 'width', 'height')
73 */
74 public function measure($with_label = true)
75 {
76 $bbox = new BoundingBox($this->xc, $this->yc, $this->xc, $this->yc);
77 if($this->show_axis) {
78
79 // find radius including division marks
80 $d = 0;
81 if($this->show_divisions) {
82 $d_info = $this->getDivisionPathInfo(false, 0, 0, 0);
83 if($d_info['pos'] < 0)
84 $d = abs($d_info['pos']);
85 if($this->show_subdivisions) {
86 $s_info = $this->getDivisionPathInfo(true, 0, 0, 0);
87 if($s_info['pos'] < 0) {
88 $s = abs($s_info['pos']);
89 if($s > $d)
90 $d = $s;
91 }
92 }
93 }
94 $r = $this->radius + $d;
95 $bbox->grow($this->xc - $r, $this->yc - $r, $this->xc + $r, $this->yc + $r);
96 }
97
98 if($this->show_text) {
99 list($x_off, $y_off, $opp) = $this->getTextOffset(0, 0, 0, 0, 0, 0, 0);
100
101 $points = $this->axis->getGridPoints(0);
102 $count = count($points);
103 if($this->block_label)
104 --$count;
105 for($p = 0; $p < $count; ++$p) {
106
107 if($points[$p]->blank())
108 continue;
109
110 $lbl = $this->measureText($x_off, $y_off, $points[$p], $opp, 0);
111 $bbox->grow($lbl['x'], $lbl['y'], $lbl['x'] + $lbl['width'],
112 $lbl['y'] + $lbl['height']);
113 }
114 }
115
116 if($with_label && $this->show_label) {
117 $lpos = $this->getLabelPosition();
118 $bbox->grow($lpos['x'], $lpos['y'], $lpos['x'] + $lpos['width'],
119 $lpos['y'] + $lpos['height']);
120 }
121
122 return $bbox;
123 }
124
125 /**
126 * Draws the axis line
127 */
128 public function drawAxisLine($x, $y, $len)
129 {
130 // the 'show_x_axis' option turns the line off
131 if($this->no_axis)
132 return '';
133 $points = [new GridPoint($this->radius, '', 0)];
134 $attr = [
135 'stroke' => $this->styles['colour'],
136 'd' => $this->graph->yGrid($points),
137 'fill' => 'none',
138 ];
139
140 if($this->styles['stroke_width'] != 1)
141 $attr['stroke-width'] = $this->styles['stroke_width'];
142 return $this->graph->element('path', $attr);
143 }
144
145 /**
146 * Returns the path for divisions or subdivisions
147 */
148 protected function getDivisionPath($x, $y, $points, $path_info, $level)
149 {
150 $path = new PathData;
151 $len = -$path_info['sz'];
152 $r1 = $this->radius - $path_info['pos'];
153 foreach($points as $p) {
154 $a = $this->arad + $this->direction * $p->position / $this->radius;
155 $x1 = $x + $r1 * sin($a);
156 $y1 = $y + $r1 * cos($a);
157 $x2 = $len * sin($a);
158 $y2 = $len * cos($a);
159 $path->add('M', $x1, $y1, 'l', $x2, $y2);
160 }
161 if(!$path->isEmpty() && $path_info['box']) {
162 $points = [new GridPoint($this->radius + $path_info['sz'], '', 0)];
163 $path->add($this->graph->yGrid($points));
164 }
165 return $path;
166 }
167
168 /**
169 * Returns the distance from the axis to draw the text
170 */
171 protected function getTextOffset($ax, $ay, $gx, $gy, $g_width, $g_height, $level)
172 {
173 list($x, $y, $opposite) = parent::getTextOffset($ax, $ay, $gx, $gy,
174 $g_width, $g_height, $level);
175 $this->text_offset = $y;
176 return [$x, $y, $opposite];
177 }
178
179 /**
180 * Returns text information:
181 * [Text, $font_size, $attr, $anchor, $rcx, $rcy, $angle, $line_spacing]
182 */
183 protected function getTextInfo($x, $y, &$point, $opposite, $level)
184 {
185 $a = $this->arad + $this->direction * $point->position / $this->radius;
186 $r1 = $this->radius + $this->text_offset;
187 $x1 = $this->xc + $this->styles['t_offset_x'] + $r1 * sin($a);
188 $y1 = $this->yc + $this->styles['t_offset_y'] + $r1 * cos($a);
189 $text_angle = $this->styles['t_angle'];
190
191 $tau = 2 * M_PI;
192 while($a < 0)
193 $a += $tau;
194 $a = fmod($a, $tau);
195
196 $t_angle = deg2rad($text_angle);
197 while($t_angle < 0)
198 $t_angle += $tau;
199
200 $sector = floor(($a + $t_angle) * 15.999 / $tau) % 16;
201 // text anchor depends on angle between text and axis
202 $left = $opposite ? 'start' : 'end';
203 $right = $opposite ? 'end' : 'start';
204 $anchor = $right;
205 if($sector == 0 || $sector == 7 || $sector == 8 || $sector == 15)
206 $anchor = 'middle';
207 elseif($sector > 8)
208 $anchor = $left;
209 $top = ($opposite ? $sector == 7 || $sector == 8 :
210 $sector == 0 || $sector == 15);
211
212 $font_size = $this->styles['t_font_size'];
213 $line_spacing = $this->styles['t_line_spacing'];
214 $svg_text = new Text($this->graph, $this->styles['t_font'],
215 $this->styles['t_font_adjust']);
216 $baseline = $svg_text->baseline($font_size);
217 list($w, $h) = $svg_text->measure($point->getText(), $font_size, 0,
218 $line_spacing);
219
220 $attr['x'] = $x1;
221 if($anchor == 'middle')
222 $attr['y'] = $y1 + ($top ? $baseline : 0);
223 else
224 $attr['y'] = $y1 + $baseline - $h / 2;
225
226 $rcx = $rcy = null;
227 if($text_angle) {
228 $rcx = $x1;
229 $rcy = $y1;
230 $xform = new Transform;
231 $xform->rotate($text_angle, $rcx, $rcy);
232 $attr['transform'] = $xform;
233 }
234 $attr['text-anchor'] = $anchor;
235 return [$svg_text, $font_size, $attr, $anchor, $rcx, $rcy, $text_angle,
236 $line_spacing];
237 }
238
239 /**
240 * Returns the label
241 */
242 protected function getLabel($x, $y, $gx, $gy, $g_width, $g_height)
243 {
244 // GetLabelPosition returns absolute text position, so ignore $x and $y
245 return parent::getLabel(0, 0, $gx, $gy, $g_width, $g_height);
246 }
247
248 /**
249 * Override position correction
250 */
251 protected function getLabelOffset($x, $y, $gx, $gy, $g_width, $g_height)
252 {
253 // no need for correction
254 return ['x' => $x, 'y' => $y];
255 }
256
257 /**
258 * Returns the dimensions of the label
259 * x, y, width, height = position and size
260 * tx, tx = text anchor point
261 * angle = text angle
262 */
263 protected function getLabelPosition()
264 {
265 $bbox = $this->measure(false);
266 $font_size = $this->styles['l_font_size'];
267 $line_spacing = $this->styles['l_line_spacing'];
268 $svg_text = new Text($this->graph, $this->styles['l_font']);
269 $tsize = $svg_text->measure($this->label, $font_size, 0, $line_spacing);
270 $baseline = $svg_text->baseline($font_size);
271 $space = $this->styles['l_space'];
272
273 $width = $tsize[0];
274 $height = $tsize[1];
275 $y = $bbox->y2 + $space;
276 $tx = $this->xc;
277 $ty = $y + $baseline;
278 $x = $tx - $width / 2;
279
280 $height += $space;
281 $angle = 0;
282 $res = compact('x', 'y', 'width', 'height', 'tx', 'ty', 'angle', 'bbox');
283 return $res;
284 }
285
286 }
287
288