LinearTicks::_doAutoTickPos()   C
last analyzed

Complexity

Conditions 15
Paths 18

Size

Total Lines 78
Code Lines 49

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 48
CRAP Score 15.0019

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 15
eloc 49
c 1
b 0
f 0
nc 18
nop 1
dl 0
loc 78
ccs 48
cts 49
cp 0.9796
crap 15.0019
rs 5.9166

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * JPGraph v4.0.3
5
 */
6
7
namespace Amenadiel\JpGraph\Graph;
8
9
use Amenadiel\JpGraph\Util;
10
11
/**
12
 * @class LinearTicks
13
 * // Description: Draw linear ticks on axis
14
 */
15
class LinearTicks extends Ticks
16
{
17
    public $minor_step    = 1;
18
    public $major_step    = 2;
19
    public $xlabel_offset = 0;
20
    public $xtick_offset  = 0;
21
    private $label_offset = 0; // What offset should the displayed label have
22
    // i.e should we display 0,1,2 or 1,2,3,4 or 2,3,4 etc
23
    private $text_label_start = 0;
24
    private $iManualTickPos;
25
    private $iManualMinTickPos;
26
    private $iManualTickLabels;
27
    private $iAdjustForDST = false; // If a date falls within the DST period add one hour to the diaplyed time
28
29 19
    public function __construct()
30
    {
31 19
        $this->precision = -1;
32 19
    }
33
34
    // Return major step size in world coordinates
35 19
    public function GetMajor()
36
    {
37 19
        return $this->major_step;
38
    }
39
40
    // Return minor step size in world coordinates
41
    public function GetMinor()
42
    {
43
        return $this->minor_step;
44
    }
45
46
    // Set Minor and Major ticks (in world coordinates)
47 19
    public function Set($aMajStep, $aMinStep = false)
48
    {
49 19
        if ($aMinStep == false) {
50
            $aMinStep = $aMajStep;
51
        }
52
53 19
        if ($aMajStep <= 0 || $aMinStep <= 0) {
54
            Util\JpGraphError::RaiseL(25064);
55
            //(" Minor or major step size is 0. Check that you haven't got an accidental SetTextTicks(0) in your code. If this is not the case you might have stumbled upon a bug in JpGraph. Please report this and if possible include the data that caused the problem.");
56
        }
57
58 19
        $this->major_step = $aMajStep;
59 19
        $this->minor_step = $aMinStep;
60 19
        $this->is_set     = true;
61 19
    }
62
63
    public function SetMajTickPositions($aMajPos, $aLabels = null)
64
    {
65
        $this->SetTickPositions($aMajPos, null, $aLabels);
66
    }
67
68 2
    public function SetTickPositions($aMajPos, $aMinPos = null, $aLabels = null)
69
    {
70 2
        if (!is_array($aMajPos) || ($aMinPos !== null && !is_array($aMinPos))) {
71
            Util\JpGraphError::RaiseL(25065); //('Tick positions must be specifued as an array()');
72
            return;
73
        }
74 2
        $n = safe_count($aMajPos);
75 2
        if (is_array($aLabels) && (safe_count($aLabels) != $n)) {
76
            Util\JpGraphError::RaiseL(25066); //('When manually specifying tick positions and labels the number of labels must be the same as the number of specified ticks.');
77
        }
78 2
        $this->iManualTickPos    = $aMajPos;
79 2
        $this->iManualMinTickPos = $aMinPos;
80 2
        $this->iManualTickLabels = $aLabels;
81 2
    }
82
83 7
    public function HaveManualLabels()
84
    {
85 7
        return safe_count($this->iManualTickLabels) > 0;
86
    }
87
88
    // Specify all the tick positions manually and possible also the exact labels
89 2
    public function _doManualTickPos($aScale)
90
    {
91 2
        $n     = safe_count($this->iManualTickPos);
92 2
        $m     = safe_count($this->iManualMinTickPos);
93 2
        $doLbl = safe_count($this->iManualTickLabels) > 0;
94
95 2
        $this->maj_ticks_pos      = [];
96 2
        $this->maj_ticklabels_pos = [];
97 2
        $this->ticks_pos          = [];
98
99
        // Now loop through the supplied positions and translate them to screen coordinates
100
        // and store them in the maj_label_positions
101 2
        $minScale = $aScale->scale[0];
102 2
        $maxScale = $aScale->scale[1];
103 2
        $j        = 0;
104 2
        for ($i = 0; $i < $n; ++$i) {
105
            // First make sure that the first tick is not lower than the lower scale value
106 2
            if (!isset($this->iManualTickPos[$i]) || $this->iManualTickPos[$i] < $minScale || $this->iManualTickPos[$i] > $maxScale) {
107 2
                continue;
108
            }
109
110 2
            $this->maj_ticks_pos[$j]      = $aScale->Translate($this->iManualTickPos[$i]);
111 2
            $this->maj_ticklabels_pos[$j] = $this->maj_ticks_pos[$j];
112
113
            // Set the minor tick marks the same as major if not specified
114 2
            if ($m <= 0) {
115 2
                $this->ticks_pos[$j] = $this->maj_ticks_pos[$j];
116
            }
117 2
            if ($doLbl) {
118 1
                $this->maj_ticks_label[$j] = $this->iManualTickLabels[$i];
119
            } else {
120 1
                $this->maj_ticks_label[$j] = $this->_doLabelFormat($this->iManualTickPos[$i], $i, $n);
121
            }
122 2
            ++$j;
123
        }
124
125
        // Some sanity check
126 2
        if (safe_count($this->maj_ticks_pos) < 2) {
127
            Util\JpGraphError::RaiseL(25067); //('Your manually specified scale and ticks is not correct. The scale seems to be too small to hold any of the specified tickl marks.');
128
        }
129
130
        // Setup the minor tick marks
131 2
        $j = 0;
132 2
        for ($i = 0; $i < $m; ++$i) {
133
            if (empty($this->iManualMinTickPos[$i]) || $this->iManualMinTickPos[$i] < $minScale || $this->iManualMinTickPos[$i] > $maxScale) {
134
                continue;
135
            }
136
            $this->ticks_pos[$j] = $aScale->Translate($this->iManualMinTickPos[$i]);
137
            ++$j;
138
        }
139 2
    }
140
141 19
    public function _doAutoTickPos($aScale)
142
    {
143 19
        $maj_step_abs = $aScale->scale_factor * $this->major_step;
144 19
        $min_step_abs = $aScale->scale_factor * $this->minor_step;
145
146 19
        if ($min_step_abs == 0 || $maj_step_abs == 0) {
147
            Util\JpGraphError::RaiseL(25068); //("A plot has an illegal scale. This could for example be that you are trying to use text autoscaling to draw a line plot with only one point or that the plot area is too small. It could also be that no input data value is numeric (perhaps only '-' or 'x')");
148
        }
149
        // We need to make this an int since comparing it below
150
        // with the result from round() can give wrong result, such that
151
        // (40 < 40) == TRUE !!!
152 19
        $limit = (int) $aScale->scale_abs[1];
153
154 19
        if ($aScale->textscale) {
155
            // This can only be true for a X-scale (horizontal)
156
            // Define ticks for a text scale. This is slightly different from a
157
            // normal linear type of scale since the position might be adjusted
158
            // and the labels start at on
159 13
            $label       = (float) $aScale->GetMinVal() + $this->text_label_start + $this->label_offset;
160 13
            $start_abs   = $aScale->scale_factor * $this->text_label_start;
161 13
            $nbrmajticks = round(($aScale->GetMaxVal() - $aScale->GetMinVal() - $this->text_label_start) / $this->major_step) + 1;
162
163 13
            $x = $aScale->scale_abs[0] + $start_abs + $this->xlabel_offset * $min_step_abs;
164 13
            for ($i = 0; $label <= $aScale->GetMaxVal() + $this->label_offset; ++$i) {
165
                // Apply format to label
166 13
                $this->maj_ticks_label[$i] = $this->_doLabelFormat($label, $i, $nbrmajticks);
167 13
                $label += $this->major_step;
168
169
                // The x-position of the tick marks can be different from the labels.
170
                // Note that we record the tick position (not the label) so that the grid
171
                // happen upon tick marks and not labels.
172 13
                $xtick                        = $aScale->scale_abs[0] + $start_abs + $this->xtick_offset * $min_step_abs + $i * $maj_step_abs;
173 13
                $this->maj_ticks_pos[$i]      = $xtick;
174 13
                $this->maj_ticklabels_pos[$i] = round($x);
175 13
                $x += $maj_step_abs;
176
            }
177
        } else {
178 19
            $label   = $aScale->GetMinVal();
179 19
            $abs_pos = $aScale->scale_abs[0];
180 19
            $j       = 0;
181 19
            $i       = 0;
182 19
            $step    = round($maj_step_abs / $min_step_abs);
183 19
            if ($aScale->type == 'x') {
184
                // For a normal linear type of scale the major ticks will always be multiples
185
                // of the minor ticks. In order to avoid any rounding issues the major ticks are
186
                // defined as every "step" minor ticks and not calculated separately
187 8
                $nbrmajticks = round(($aScale->GetMaxVal() - $aScale->GetMinVal() - $this->text_label_start) / $this->major_step) + 1;
188 8
                while (round($abs_pos) <= $limit) {
189 8
                    $this->ticks_pos[]   = round($abs_pos);
190 8
                    $this->ticks_label[] = $label;
191 8
                    if ($step == 0 || $i % $step == 0 && $j < $nbrmajticks) {
192 8
                        $this->maj_ticks_pos[$j]      = round($abs_pos);
193 8
                        $this->maj_ticklabels_pos[$j] = round($abs_pos);
194 8
                        $this->maj_ticks_label[$j]    = $this->_doLabelFormat($label, $j, $nbrmajticks);
195 8
                        ++$j;
196
                    }
197 8
                    ++$i;
198 8
                    $abs_pos += $min_step_abs;
199 8
                    $label += $this->minor_step;
200
                }
201 18
            } elseif ($aScale->type == 'y') {
202
                //@todo  s=2:20,12  s=1:50,6  $this->major_step:$nbr
203
                // abs_point,limit s=1:270,80 s=2:540,160
204
                // $this->major_step = 50;
205 18
                $nbrmajticks = round(($aScale->GetMaxVal() - $aScale->GetMinVal()) / $this->major_step) + 1;
206
                //                $step = 5;
207 18
                while (round($abs_pos) >= $limit) {
208 18
                    $this->ticks_pos[$i]   = round($abs_pos);
209 18
                    $this->ticks_label[$i] = $label;
210 18
                    if ($step == 0 || $i % $step == 0 && $j < $nbrmajticks) {
211 18
                        $this->maj_ticks_pos[$j]      = round($abs_pos);
212 18
                        $this->maj_ticklabels_pos[$j] = round($abs_pos);
213 18
                        $this->maj_ticks_label[$j]    = $this->_doLabelFormat($label, $j, $nbrmajticks);
214 18
                        ++$j;
215
                    }
216 18
                    ++$i;
217 18
                    $abs_pos += $min_step_abs;
218 18
                    $label += $this->minor_step;
219
                }
220
            }
221
        }
222 19
    }
223
224
    public function AdjustForDST($aFlg = true)
225
    {
226
        $this->iAdjustForDST = $aFlg;
227
    }
228
229 19
    public function _doLabelFormat($aVal, $aIdx, $aNbrTicks)
230
    {
231
        // If precision hasn't been specified set it to a sensible value
232 19
        if ($this->precision == -1) {
233 19
            $t = log10($this->minor_step);
234 19
            if ($t > 0) {
235 16
                $precision = 0;
236
            } else {
237 19
                $precision = -floor($t);
238
            }
239
        } else {
240
            $precision = $this->precision;
241
        }
242
243 19
        if ($this->label_formfunc != '') {
244 2
            $f = $this->label_formfunc;
245 2
            if ($this->label_formatstr == '') {
246 2
                $l = call_user_func($f, $aVal);
247
            } else {
248 2
                $l = sprintf($this->label_formatstr, call_user_func($f, $aVal));
249
            }
250 19
        } elseif ($this->label_formatstr != '' || $this->label_dateformatstr != '') {
251 2
            if ($this->label_usedateformat) {
252
                // Adjust the value to take daylight savings into account
253 1
                if (date('I', $aVal) == 1 && $this->iAdjustForDST) {
254
                    // DST
255
                    $aVal += 3600;
256
                }
257
258 1
                $l = date($this->label_formatstr, $aVal);
259 1
                if ($this->label_formatstr == 'W') {
260
                    // If we use week formatting then add a single 'w' in front of the
261
                    // week number to differentiate it from dates
262 1
                    $l = 'w' . $l;
263
                }
264
            } else {
265 2
                if ($this->label_dateformatstr !== '') {
266
                    // Adjust the value to take daylight savings into account
267 1
                    if (date('I', $aVal) == 1 && $this->iAdjustForDST) {
268
                        // DST
269
                        $aVal += 3600;
270
                    }
271
272 1
                    $l = date($this->label_dateformatstr, $aVal);
273 1
                    if ($this->label_formatstr == 'W') {
274
                        // If we use week formatting then add a single 'w' in front of the
275
                        // week number to differentiate it from dates
276 1
                        $l = 'w' . $l;
277
                    }
278
                } else {
279 2
                    $l = sprintf($this->label_formatstr, $aVal);
280
                }
281
            }
282
        } else {
283
            //FIX: if negative precision  is returned "0f" , instead of formatted values
284 19
            $format = $precision > 0 ? '%01.' . $precision . 'f' : '%01.0f';
285 19
            $l      = sprintf($format, round($aVal, $precision));
0 ignored issues
show
Bug introduced by
It seems like $precision can also be of type double; however, parameter $precision of round() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

285
            $l      = sprintf($format, round($aVal, /** @scrutinizer ignore-type */ $precision));
Loading history...
286
        }
287
288 19
        if (($this->supress_zerolabel && $l == 0) || ($this->supress_first && $aIdx == 0) || ($this->supress_last && $aIdx == $aNbrTicks - 1)) {
289 9
            $l = '';
290
        }
291
292 19
        return $l;
293
    }
294
295
    // Stroke ticks on either X or Y axis
296 19
    public function _StrokeTicks($aImg, $aScale, $aPos)
297
    {
298 19
        $hor = $aScale->type == 'x';
299 19
        $aImg->SetLineWeight($this->weight);
300
301
        // We need to make this an int since comparing it below
302
        // with the result from round() can give wrong result, such that
303
        // (40 < 40) == TRUE !!!
304 19
        $limit = (int) $aScale->scale_abs[1];
0 ignored issues
show
Unused Code introduced by
The assignment to $limit is dead and can be removed.
Loading history...
305
306
        // A text scale doesn't have any minor ticks
307 19
        if (!$aScale->textscale) {
308
            // Stroke minor ticks
309 19
            $yu = $aPos - $this->direction * $this->GetMinTickAbsSize();
310 19
            $xr = $aPos + $this->direction * $this->GetMinTickAbsSize();
311 19
            $n  = safe_count($this->ticks_pos);
312 19
            for ($i = 0; $i < $n; ++$i) {
313 19
                if (!$this->supress_tickmarks && !$this->supress_minor_tickmarks) {
314 3
                    if ($this->mincolor != '') {
315
                        $aImg->PushColor($this->mincolor);
316
                    }
317 3
                    if ($hor) {
318
                        //if( $this->ticks_pos[$i] <= $limit )
319 1
                        $aImg->Line($this->ticks_pos[$i], $aPos, $this->ticks_pos[$i], $yu);
320
                    } else {
321
                        //if( $this->ticks_pos[$i] >= $limit )
322 3
                        $aImg->Line($aPos, $this->ticks_pos[$i], $xr, $this->ticks_pos[$i]);
323
                    }
324 3
                    if ($this->mincolor != '') {
325
                        $aImg->PopColor();
326
                    }
327
                }
328
            }
329
        }
330
331
        // Stroke major ticks
332 19
        $yu          = $aPos - $this->direction * $this->GetMajTickAbsSize();
333 19
        $xr          = $aPos + $this->direction * $this->GetMajTickAbsSize();
334 19
        $nbrmajticks = round(($aScale->GetMaxVal() - $aScale->GetMinVal() - $this->text_label_start) / $this->major_step) + 1;
335 19
        $n           = safe_count($this->maj_ticks_pos);
336 19
        for ($i = 0; $i < $n; ++$i) {
337 19
            if (!($this->xtick_offset > 0 && $i == $nbrmajticks - 1) && !$this->supress_tickmarks) {
338 5
                if ($this->majcolor != '') {
339
                    $aImg->PushColor($this->majcolor);
340
                }
341 5
                if ($hor) {
342
                    //if( $this->maj_ticks_pos[$i] <= $limit )
343 2
                    $aImg->Line($this->maj_ticks_pos[$i], $aPos, $this->maj_ticks_pos[$i], $yu);
344
                } else {
345
                    //if( $this->maj_ticks_pos[$i] >= $limit )
346 4
                    $aImg->Line($aPos, $this->maj_ticks_pos[$i], $xr, $this->maj_ticks_pos[$i]);
347
                }
348 5
                if ($this->majcolor != '') {
349
                    $aImg->PopColor();
350
                }
351
            }
352
        }
353 19
    }
354
355
    // Draw linear ticks
356 19
    public function Stroke($aImg, $aScale, $aPos)
357
    {
358 19
        if ($this->iManualTickPos != null) {
359 2
            $this->_doManualTickPos($aScale);
360
        } else {
361 19
            $this->_doAutoTickPos($aScale);
362
        }
363 19
        $this->_StrokeTicks($aImg, $aScale, $aPos, $aScale->type == 'x');
0 ignored issues
show
Unused Code introduced by
The call to Amenadiel\JpGraph\Graph\...arTicks::_StrokeTicks() has too many arguments starting with $aScale->type == 'x'. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

363
        $this->/** @scrutinizer ignore-call */ 
364
               _StrokeTicks($aImg, $aScale, $aPos, $aScale->type == 'x');

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
364 19
    }
365
366
    /**
367
     * PRIVATE METHODS.
368
     *
369
     * @param mixed $aLabelOff
370
     * @param mixed $aTickOff
371
     */
372
    // Spoecify the offset of the displayed tick mark with the tick "space"
373
    // Legal values for $o is [0,1] used to adjust where the tick marks and label
374
    // should be positioned within the major tick-size
375
    // $lo specifies the label offset and $to specifies the tick offset
376
    // this comes in handy for example in bar graphs where we wont no offset for the
377
    // tick but have the labels displayed halfway under the bars.
378 18
    public function SetXLabelOffset($aLabelOff, $aTickOff = -1)
379
    {
380 18
        $this->xlabel_offset = $aLabelOff;
381 18
        if ($aTickOff == -1) {
382
            // Same as label offset
383 16
            $this->xtick_offset = $aLabelOff;
384
        } else {
385 3
            $this->xtick_offset = $aTickOff;
386
        }
387 18
        if ($aLabelOff > 0) {
388 8
            $this->SupressLast(); // The last tick wont fit
389
        }
390 18
    }
391
392
    // Which tick label should we start with?
393 2
    public function SetTextLabelStart($aTextLabelOff)
394
    {
395 2
        $this->text_label_start = $aTextLabelOff;
396 2
    }
397
} // @class
398