Bezier::cubicBBox()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 47

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 33
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 47
ccs 33
cts 33
cp 1
rs 9.1563
c 0
b 0
f 0
cc 2
nc 2
nop 8
crap 2

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
namespace nstdio\svg\util;
3
4
/**
5
 * Class Bezier
6
 *
7
 * @package nstdio\svg\util
8
 * @author  Edgar Asatryan <[email protected]>
9
 */
10
class Bezier
11
{
12
    const EPSILON = 0.00001;
13
14 5
    public static function quadraticBBox($p0x, $p0y, $p1x, $p1y, $p2x, $p2y)
15
    {
16 5
        $devx = $p0x + $p2x - 2 * $p1x;
17 5
        $devy = $p0y + $p2y - 2 * $p1y;
18
19 5
        self::avoidDivisionByZero($devy);
20 5
        self::avoidDivisionByZero($devx);
21
22 5
        $tx = ($p0x - $p1x) / $devx;
23 5
        $ty = ($p0y - $p1y) / $devy;
24
25 5
        self::checkBezierInterval($tx);
26 5
        self::checkBezierInterval($ty);
27
28 5
        $txByTX = self::getQuadraticValue($tx, $p0x, $p1x, $p2x);
29 5
        $tyByTX = self::getQuadraticValue($tx, $p0y, $p1y, $p2y);
30
31 5
        $txByTY = self::getQuadraticValue($ty, $p0x, $p1x, $p2x);
32 5
        $tyByTY = self::getQuadraticValue($ty, $p0y, $p1y, $p2y);
33
34 5
        $x1 = min($txByTX, $p0x, $p2x, $txByTY);
35 5
        $y1 = min($tyByTX, $p0y, $p2y, $tyByTY);
36
37
38 5
        $x2 = max($txByTX, $p0x, $p2x, $txByTY);
39 5
        $y2 = max($tyByTX, $p0y, $p2y, $tyByTY);
40
41
42
        return [
43 5
            min($x2, $x1),
44 5
            min($y2, $y1),
45 5
            max($x2, $x1),
46 5
            max($y2, $y1),
47 5
        ];
48
    }
49
50 7
    public static function cubicBBox($p0x, $p0y, $p1x, $p1y, $p2x, $p2y, $p3x, $p3y)
51
    {
52 7
        if (abs($p3y - $p0y) === 0) {
53 1
            $p3y += self::EPSILON;
54 1
        }
55
56 7
        $ax = $p3x - $p0x + 3 * ($p1x - $p2x);
57 7
        $bx = 2 * ($p0x - 2 * $p1x + $p2x);
58 7
        $cx = $p1x - $p0x;
59
60 7
        $ay = $p3y - $p0y + 3 * ($p1y - $p2y);
61 7
        $by = 2 * ($p0y - 2 * $p1y + $p2y);
62 7
        $cy = $p1y - $p0y;
63
64 7
        $txRoots = self::getRoots($ax, $bx, $cx);
65 7
        $tyRoots = self::getRoots($ay, $by, $cy);
66
67 7
        $tv0x = self::getCubicValue(0, $p0x, $p1x, $p2x, $p3x);
68 7
        $tv1x = self::getCubicValue($txRoots[0], $p0x, $p1x, $p2x, $p3x);
69 7
        $tv2x = self::getCubicValue($txRoots[1], $p0x, $p1x, $p2x, $p3x);
70 7
        $tv3x = self::getCubicValue(1, $p0x, $p1x, $p2x, $p3x);
71 7
        $tv4x = self::getCubicValue($tyRoots[0], $p0x, $p1x, $p2x, $p3x);
72 7
        $tv5x = self::getCubicValue($tyRoots[1], $p0x, $p1x, $p2x, $p3x);
73
74 7
        $tv0y = self::getCubicValue(0, $p0y, $p1y, $p2y, $p3y);
75 7
        $tv1y = self::getCubicValue($tyRoots[0], $p0y, $p1y, $p2y, $p3y);
76 7
        $tv2y = self::getCubicValue($tyRoots[1], $p0y, $p1y, $p2y, $p3y);
77 7
        $tv3y = self::getCubicValue(1, $p0y, $p1y, $p2y, $p3y);
78 7
        $tv4y = self::getCubicValue($txRoots[0], $p0y, $p1y, $p2y, $p3y);
79 7
        $tv5y = self::getCubicValue($txRoots[1], $p0y, $p1y, $p2y, $p3y);
80
81
82 7
        $x1 = min($tv0x, $tv1x, $tv2x, $tv3x, $p0x, $p3x, $tv4x, $tv5x);
83 7
        $y1 = min($tv0y, $tv1y, $tv2y, $tv3y, $p0y, $p3y, $tv4y, $tv5y);
84
85 7
        $x2 = max($tv0x, $tv1x, $tv2x, $tv3x, $p0x, $p3x, $tv4x, $tv5x);
86 7
        $y2 = max($tv0y, $tv1y, $tv2y, $tv3y, $p0y, $p3y, $tv4y, $tv5y);
87
88
89
        return [
90 7
            min($x2, $x1),
91 7
            min($y2, $y1),
92 7
            max($x2, $x1),
93 7
            max($y2, $y1),
94 7
        ];
95
96
    }
97
98 7
    public static function getRoots($a, $b, $c)
99
    {
100 7
        $dis = $b * $b - 4 * $a * $c;
101 7
        if ($dis < 0) {
102 2
            return null;
103
        }
104 7
        self::avoidDivisionByZero($a);
105
106 7
        $disSqrt = sqrt($dis);
107 7
        $root1 = (-$b + $disSqrt) / (2 * $a);
108 7
        $root2 = (-$b - $disSqrt) / (2 * $a);
109
110 7
        self::checkBezierInterval($root1);
111 7
        self::checkBezierInterval($root2);
112
113 7
        return [$root1, $root2];
114
    }
115
116 7
    private static function getCubicValue($t, $p0, $p1, $p2, $p3)
117
    {
118 7
        $omt = 1 - $t;
119 7
        $value = $p0 * $omt * $omt * $omt +
120 7
            3 * $p1 * $t * $omt * $omt +
121 7
            3 * $p2 * $t * $t * $omt +
122 7
            $p3 * $t * $t * $t;
123
124 7
        return $value;
125
    }
126
127
    /**
128
     * @param $value
129
     */
130 11
    private static function avoidDivisionByZero(&$value)
131
    {
132 11
        if ($value === 0) {
133
            $value = self::EPSILON;
134
        }
135 11
    }
136
137
    /**
138
     * @param $t
139
     */
140 11
    private static function checkBezierInterval(&$t)
141
    {
142 11
        if ($t > 1 || $t < 0) {
143 9
            $t = 0;
144 9
        }
145 11
    }
146
147
    /**
148
     * @param $t
149
     * @param $p0x
150
     * @param $p1x
151
     * @param $p2x
152
     *
153
     * @return mixed
154
     */
155 5
    private static function getQuadraticValue($t, $p0x, $p1x, $p2x)
156
    {
157 5
        $omt = 1 - $t;
158
159 5
        return $p0x * $omt * $omt + 2 * $t * $p1x * $omt + $p2x * $t * $t;
160
    }
161
}
162