PluginProbe
E2Pdf – Export Pdf Tool for WordPress / 1.32.23
E2Pdf – Export Pdf Tool for WordPress v1.32.23
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 / AxisLog.php

AxisLog.php in E2Pdf – Export Pdf Tool for WordPress 1.32.23, at vendors/svggraph/AxisLog.php

296 lines 8.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Copyright (C) 2013-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 * Class for calculating logarithmic axis measurements
26 */
27 class AxisLog extends Axis {
28
29 protected $lgmin;
30 protected $lgmax;
31 protected $base = 10;
32 protected $divisions;
33 protected $grid_space;
34 protected $grid_split = 0;
35 protected $negative = false;
36 protected $lgmul;
37 protected $int_base = true;
38
39 public function __construct($length, $max_val, $min_val, $min_unit,
40 $min_space, $fit, $units_before, $units_after, $decimal_digits,
41 $base, $divisions, $label_callback, $values)
42 {
43 if($min_val == 0 || $max_val == 0)
44 throw new \Exception('0 value on log axis');
45 if($min_val < 0 && $max_val > 0)
46 throw new \Exception('-ve and +ve on log axis');
47 if($max_val <= $min_val && $min_unit == 0)
48 throw new \Exception('Zero length axis (min >= max)');
49 $this->length = $length;
50 $this->min_unit = $min_unit;
51 $this->min_space = $min_space;
52 $this->units_before = $units_before;
53 $this->units_after = $units_after;
54 $this->decimal_digits = $decimal_digits;
55 $this->label_callback = $label_callback;
56 $this->values = $values;
57 if(is_numeric($base) && $base > 1) {
58 $this->base = $base * 1.0;
59 $this->int_base = $this->base == floor($this->base);
60 }
61 $this->uneven = false;
62 if($min_val < 0) {
63 $this->negative = true;
64 $m = $min_val;
65 $min_val = abs($max_val);
66 $max_val = abs($m);
67 }
68 if(is_numeric($divisions))
69 $this->divisions = $divisions;
70
71 if($fit && $this->int_base) {
72 // X-axis, try to use values
73 $lgminf = $this->bfloor($min_val);
74 $lgmaxf = $this->bceil($max_val);
75 $this->lgmin = log($lgminf, $this->base);
76 $this->lgmax = log($lgmaxf, $this->base);
77 } else {
78 // Y-axis, allow space
79 $this->lgmin = floor(log($min_val, $this->base));
80 $this->lgmax = ceil(log($max_val, $this->base));
81 }
82
83 // if all the values are the same, and a power of the base
84 if($this->lgmax <= $this->lgmin)
85 $this->lgmin -= 1.0;
86
87 $this->lgmul = $this->length / ($this->lgmax - $this->lgmin);
88 $this->min_value = pow($this->base, $this->lgmin);
89 $this->max_value = pow($this->base, $this->lgmax);
90 }
91
92 /**
93 * Floor to the nearest sensible number
94 */
95 protected function bfloor($value)
96 {
97 $b = floor(log($value, $this->base));
98 $bf = pow($this->base, $b);
99 $m = floor($value / $bf);
100 return $m * $bf;
101 }
102
103 /**
104 * Ceil to the nearest sensible number
105 */
106 protected function bceil($value)
107 {
108 $b = floor(log($value, $this->base));
109 $bf = pow($this->base, $b);
110 $m = ceil($value / $bf);
111 return $m * $bf;
112 }
113
114 /**
115 * Returns the grid points as an associative array:
116 * array($value => $position)
117 */
118 public function getGridPoints($start)
119 {
120 if($start === null)
121 return;
122
123 $pow_div = ceil($this->lgmax) - floor($this->lgmin);
124 $this->grid_space = $this->length / $pow_div;
125
126 $this->grid_split = $this->divisions ? $this->divisions :
127 $this->findDivision($this->grid_space, $this->min_space);
128
129 $spoints = [];
130 if($this->grid_split) {
131 for($l = $this->grid_split; $l < $this->base; $l += $this->grid_split)
132 $spoints[] = log($l, $this->base);
133 }
134
135 $points = [];
136 $val = $this->min_value;
137 while($val <= $this->max_value) {
138 $value = $this->negative ? -$val : $val;
139 $position = $this->position($value);
140 $position = $start + ($this->direction * $position);
141 $points[] = $this->getGridPoint($position, $value);
142
143 // inserted at start of loop, but calculated at end
144 if($val > ($this->max_value * 0.995))
145 break;
146
147 // find next point
148 $l = log($val, $this->base);
149 $l_floor = floor($l);
150 $l_dec = $l - $l_floor;
151 $l_next = 0;
152 foreach($spoints as $l1) {
153 if($l1 && ($l1 - $l_dec) > 0.001) {
154 $l_next = $l_floor + $l1;
155 break;
156 }
157 }
158 if(!$l_next || $l_next > $this->lgmax) {
159 // next full power or end of axis
160 $l_next = min($l_floor + 1, $this->lgmax);
161 }
162 $val = pow($this->base, $l_next);
163 }
164
165 if($this->direction < 0) {
166 usort($points, function($a, $b) { return $b->position - $a->position; });
167 } else {
168 usort($points, function($a, $b) { return $a->position - $b->position; });
169 }
170 return $points;
171 }
172
173 /**
174 * Returns the grid subdivision points as an array
175 */
176 public function getGridSubdivisions($min_space, $min_unit, $start, $fixed)
177 {
178 $points = [];
179 if($this->int_base) {
180 $split = $this->findDivision($this->grid_space, $min_space,
181 $this->grid_split);
182 if($split) {
183 for($l = $this->lgmin; $l < $this->lgmax; ++$l) {
184 for($l1 = $split; $l1 < $this->base; $l1 += $split) {
185 if($this->grid_split == 0 || $l1 % $this->grid_split) {
186 $p = log($l1, $this->base);
187 $val = pow($this->base, $l + $p);
188 $position = $start + $this->position($val) * $this->direction;
189 $points[] = new GridPoint($position, '', $val);
190 }
191 }
192 }
193 }
194 }
195 return $points;
196 }
197
198 /**
199 * Returns the distance in pixels $u takes from $pos
200 */
201 public function measureUnits($pos, $u)
202 {
203 $i = Coords::parseValue($pos);
204 if(!is_numeric($i['value']))
205 throw new \Exception("Unable to measure $u units from '{$i['value']}'");
206
207 $start_pos = $this->position($i['value']);
208 $end_pos = $this->position($i['value'] + $u);
209 return $end_pos - $start_pos;
210 }
211
212 /**
213 * Returns the position of a value on the axis, or NULL if the position is
214 * not possible
215 */
216 public function position($index, $item = null)
217 {
218 $value = $index;
219 if($item !== null && !$this->values->associativeKeys())
220 $value = $item->key;
221 if($this->negative) {
222 if($value >= 0)
223 return null;
224 $abs_value = abs($value);
225 if($abs_value < $this->min_value)
226 return null;
227 return $this->length - (log($abs_value, $this->base) - $this->lgmin) *
228 $this->lgmul;
229 }
230 if($value <= 0 || $value < $this->min_value)
231 return null;
232 return (log($value, $this->base) - $this->lgmin) * $this->lgmul;
233 }
234
235 /**
236 * Returns the position of the origin
237 */
238 public function origin()
239 {
240 // not the position of 0, because that doesn't exist
241 return $this->negative ? $this->length : 0;
242 }
243
244 /**
245 * Returns the value at a position on the axis
246 */
247 public function value($position)
248 {
249 $p = pow($this->base, $this->lgmin + $position / $this->lgmul);
250 return $p;
251 }
252
253 /**
254 * Finds an even division of the given space that is >= min_space
255 */
256 private function findDivision($space, $min_space, $main_division = 0)
257 {
258 $split = 0;
259 if($this->int_base) {
260 $division = $main_division ? $main_division : $this->base;
261 $l = $this->base - 1;
262 $lgs = $space * log($l, $this->base);
263
264 $smallest = $space - $lgs;
265 if($smallest < $min_space) {
266 $max_split = floor($division / 2);
267 for($i = 2; $smallest < $min_space && $i <= $max_split; ++$i) {
268 if($division % $i == 0) {
269 // the smallest gap is the one before the next power
270 $l = $this->base - $i;
271 $lgs = $space * log($l, $this->base);
272 $smallest = $space - $lgs;
273 $split = $i;
274 }
275 }
276 if($smallest < $min_space)
277 $split = 0;
278 } else {
279 $split = 1;
280 }
281 }
282 return $split;
283 }
284
285 /**
286 * Not actually 0, but the position of the axis
287 */
288 public function zero()
289 {
290 if($this->negative)
291 return $this->length;
292 return 0;
293 }
294 }
295
296