PluginProbe
E2Pdf – Export Pdf Tool for WordPress / 1.32.17
E2Pdf – Export Pdf Tool for WordPress v1.32.17
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 / PieSliceEdge.php

PieSliceEdge.php in E2Pdf – Export Pdf Tool for WordPress 1.32.17, at vendors/svggraph/PieSliceEdge.php

263 lines 6.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Copyright (C) 2019-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 /**
25 * The PieSliceEdge class calculates and draws the 3D slice edges
26 */
27 class PieSliceEdge {
28
29 const SCALE = 2000.0;
30 public $y;
31 public $slice;
32
33 // types: 0 => start, 1 => end, 2 => curve,
34 // 3 => second curve (if it exists), -1 = no edge
35 protected $type;
36 protected $a1;
37 protected $a2;
38
39 /**
40 * $slice is the slice details array
41 * $s_angle is the start angle in radians
42 */
43 public function __construct(&$graph, $type, $slice, $s_angle)
44 {
45 $this->type = -1;
46 $this->slice = $slice;
47 $tau = M_PI * 2.0;
48
49 $start_angle = $slice['angle_start'] + $s_angle;
50 $end_angle = $slice['angle_end'] + $s_angle;
51
52 if(isset($slice['single_slice']) && $slice['single_slice'] &&
53 !is_numeric($graph->end_angle)) {
54 // if end_angle is not set, then single_slice is full pie
55 $start_angle = 0.0;
56 $end_angle = M_PI;
57 } elseif($graph->getOption('reverse')) {
58 // apply reverse now to save thinking about it later
59 $s = M_PI * 4.0 - $end_angle;
60 $e = M_PI * 4.0 - $start_angle;
61 $start_angle = $s;
62 $end_angle = $e;
63 }
64
65 $this->a1 = fmod($start_angle, $tau);
66 $this->a2 = fmod($end_angle, $tau);
67 if($this->a2 < $this->a1)
68 $this->a2 += $tau;
69
70 switch($type) {
71 case 0:
72 // flat edge at a1
73 $this->a2 = $this->a1;
74 break;
75 case 1:
76 // flat edge at a2
77 $this->a1 = $this->a2;
78 break;
79 case 2:
80 // bottom edge
81 if($this->a1 > M_PI && $this->a2 < $tau)
82 return;
83 // truncate curves to visible area
84 if($this->a1 <= M_PI && $this->a2 >= M_PI)
85 $this->a2 = M_PI;
86 elseif($this->a1 > M_PI && $this->a2 > $tau)
87 $this->a1 = $tau;
88 if($this->a2 > M_PI * 3.0)
89 $this->a2 = M_PI * 3.0;
90 break;
91 case 3:
92 // type 3 edges are where the slice starts bottom, goes through top and ends at bottom
93 if($this->a2 < $tau || $this->a2 > M_PI * 3.0 || $this->a1 >= M_PI)
94 return;
95
96 $this->a1 = $tau;
97 break;
98 }
99
100 $this->setupSort();
101 $this->type = $type;
102 }
103
104 /**
105 * Fills in $this->y, for sorting slices by layer depth
106 */
107 protected function setupSort()
108 {
109 if($this->a1 < M_PI_2 && $this->a2 > M_PI_2)
110 $ac = M_PI_2;
111 else
112 $ac = ($this->a1 + $this->a2) / 2;
113 $this->y = PieSliceEdge::SCALE * sin($ac);
114 }
115
116 /**
117 * Returns the number of edge types this class supports
118 */
119 protected static function getEdgeTypes()
120 {
121 return 3;
122 }
123
124 /**
125 * Returns a array of edges for the slice
126 */
127 public static function getEdges(&$graph, $slice, $start_angle, $flat)
128 {
129 $class = get_called_class();
130 $start = $flat ? 0 : 2;
131 $end = $class::getEdgeTypes();
132 $edges = [];
133 for($e = $start; $e <= $end; ++$e) {
134 $edge = new $class($graph, $e, $slice, $start_angle);
135 if($edge->visible())
136 $edges[] = $edge;
137 }
138 return $edges;
139 }
140
141 /**
142 * Returns TRUE if the edge faces forwards
143 */
144 public function visible()
145 {
146 // type -1 is for non-existent edges
147 if($this->type == -1)
148 return false;
149
150 // the flat edges are visible left or right
151 if($this->type == 0) {
152 // start on right not visible
153 if($this->a1 < M_PI * 0.5 || $this->a1 > M_PI * 1.5)
154 return false;
155 return true;
156 }
157
158 $a2 = fmod($this->a2, M_PI * 2.0);
159 if($this->type == 1) {
160 // end on left not visible
161 if($a2 > M_PI * 0.5 && $a2 < M_PI * 1.5)
162 return false;
163 return true;
164 }
165
166 // if both ends are at top and slice angle < 180, not visible
167 if($this->a1 >= M_PI && $this->a2 <= M_PI * 2.0 &&
168 $this->a2 - $this->a1 < M_PI * 2.0)
169 return false;
170 return true;
171 }
172
173 /**
174 * Returns TRUE if this is a curved edge
175 */
176 public function curve()
177 {
178 return $this->type > 1;
179 }
180
181 /**
182 * Returns angle of flat path
183 */
184 public function angle()
185 {
186 if($this->type > 1)
187 return 0;
188 return $this->type == 1 ? $this->a2 : $this->a1;
189 }
190
191 /**
192 * Draws the edge
193 */
194 public function draw(&$graph, $x_centre, $y_centre, $depth, $attr = null)
195 {
196 $attr = ($attr === null ? $this->slice['attr'] :
197 array_merge($this->slice['attr'], $attr));
198 $attr['d'] = $this->getPath($x_centre, $y_centre, $depth);
199 return $graph->element('path', $attr);
200 }
201
202 /**
203 * Returns the edge as a clipPath element
204 */
205 public function getClipPath(&$graph, $x_centre, $y_centre, $depth, $clip_id)
206 {
207 $attr = ['id' => $clip_id];
208 $path = ['d' => $this->getPath($x_centre, $y_centre, $depth)];
209
210 return $graph->element('clipPath', $attr, null,
211 $graph->element('path', $path));
212 }
213
214 /**
215 * Returns the correct path
216 */
217 protected function getPath($x_centre, $y_centre, $depth)
218 {
219 if($this->type == 0 || $this->type == 1) {
220 $path = $this->getFlatPath($this->type == 1 ? $this->a2 : $this->a1,
221 $x_centre, $y_centre, $depth);
222 } else {
223 $path = $this->getCurvedPath($x_centre, $y_centre, $depth);
224 }
225 return $path;
226 }
227
228 /**
229 * Returns the path for a flat edge
230 */
231 protected function getFlatPath($angle, $x_centre, $y_centre, $depth)
232 {
233 $x1 = $x_centre + $this->slice['radius_x'] * cos($angle);
234 $y1 = $y_centre + $this->slice['radius_y'] * sin($angle) + $depth;
235 return new PathData('M', $x_centre, $y_centre, 'v', $depth, 'L', $x1, $y1,
236 'v', -$depth, 'z');
237 }
238
239 /**
240 * Returns the path for the curved edge
241 */
242 protected function getCurvedPath($x_centre, $y_centre, $depth)
243 {
244 $rx = $this->slice['radius_x'];
245 $ry = $this->slice['radius_y'];
246 $x1 = $x_centre + $rx * cos($this->a1);
247 $y1 = $y_centre + $ry * sin($this->a1);
248 $x2 = $x_centre + $rx * cos($this->a2);
249 $y2 = $y_centre + $ry * sin($this->a2);
250 $y2d = $y2 + $depth;
251
252 $outer = 0; // edge is never > PI
253 $sweep = 1;
254
255 $path = new PathData('M', $x1, $y1, 'v', $depth, 'A', $rx, $ry, 0,
256 $outer, $sweep, $x2, $y2d, 'v', -$depth);
257 $sweep = $sweep ? 0 : 1;
258 $path->add('A', $rx, $ry, 0, $outer, $sweep, $x1, $y1);
259 return $path;
260 }
261 }
262
263