Completed
Branch master (42e482)
by Edgar
05:48 queued 02:06
created

Bezier::cubicBBox()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 38
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 26
c 1
b 0
f 1
nc 1
nop 8
dl 0
loc 38
rs 8.8571

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
    public static function quadraticBBox($p0x, $p0y, $p1x, $p1y, $p2x, $p2y)
15
    {
16
        $devx = $p0x + $p2x - 2 * $p1x;
17
        $devy = $p0y + $p2y - 2 * $p1y;
18
19
        self::avoidDivisionByZero($devy);
20
        self::avoidDivisionByZero($devx);
21
22
        $tx = ($p0x - $p1x) / $devx;
23
        $ty = ($p0y - $p1y) / $devy;
24
25
        self::checkBezierInterval($tx);
26
        self::checkBezierInterval($ty);
27
28
        $txByTX = $p0x * pow(1 - $tx, 2) + 2 * $tx * $p1x * (1 - $tx) + $p2x * $tx * $tx;
29
        $tyByTX = $p0y * pow(1 - $tx, 2) + 2 * $tx * $p1y * (1 - $tx) + $p2y * $tx * $tx;
30
31
        $txByTY = $p0x * pow(1 - $ty, 2) + 2 * $ty * $p1x * (1 - $ty) + $p2x * $ty * $ty;
32
        $tyByTY = $p0y * pow(1 - $ty, 2) + 2 * $ty * $p1y * (1 - $ty) + $p2y * $ty * $ty;
33
34
        $x1 = min($txByTX, $p0x, $p2x, $txByTY);
35
        $y1 = min($tyByTX, $p0y, $p2y, $tyByTY);
36
37
38
        $x2 = max($txByTX, $p0x, $p2x, $txByTY);
39
        $y2 = max($tyByTX, $p0y, $p2y, $tyByTY);
40
41
42
        return [
43
            'width'  => $x2 - min($x2, $x1),
44
            'height' => max($y2, $y1) - min($y2, $y1),
45
            'x'      => min($x2, $x1),
46
            'y'      => min($y2, $y1),
47
        ];
48
    }
49
50
    public static function cubicBBox($p0x, $p0y, $p1x, $p1y, $p2x, $p2y, $p3x, $p3y)
51
    {
52
        $ax = $p3x - $p0x + 3 * ($p1x - $p2x);
53
        $bx = 2 * ($p0x - 2 * $p1x + $p2x);
54
        $cx = $p1x - $p0x;
55
56
        $ay = $p3y - $p0y + 3 * ($p1y - $p2y);
57
        $by = 2 * ($p0y - 2 * $p1y + $p2y);
58
        $cy = $p1y - $p0y;
59
60
        $txRoots = self::getRoots($ax, $bx, $cx);
61
        $tyRoots = self::getRoots($ay, $by, $cy);
62
63
        $tv0x = self::getCubicValue(0, $p0x, $p1x, $p2x, $p3x);
64
        $tv1x = self::getCubicValue($txRoots[0], $p0x, $p1x, $p2x, $p3x);
65
        $tv2x = self::getCubicValue($txRoots[1], $p0x, $p1x, $p2x, $p3x);
66
        $tv3x = self::getCubicValue(1, $p0x, $p1x, $p2x, $p3x);
67
68
        $tv0y = self::getCubicValue(0, $p0y, $p1y, $p2y, $p3y);
69
        $tv1y = self::getCubicValue($tyRoots[0], $p0y, $p1y, $p2y, $p3y);
70
        $tv2y = self::getCubicValue($tyRoots[1], $p0y, $p1y, $p2y, $p3y);
71
        $tv3y = self::getCubicValue(1, $p0y, $p1y, $p2y, $p3y);
72
73
74
        $x1 = min($tv0x, $tv1x, $tv2x, $tv3x, $p0x, $p3x);
75
        $y1 = min($tv0y, $tv1y, $tv2y, $tv3y, $p0y, $p3y);
76
77
        $x2 = max($tv0x, $tv1x, $tv2x, $tv3x, $p0x, $p3x);
78
        $y2 = max($tv0y, $tv1y, $tv2y, $tv3y, $p0y, $p3y);
79
80
        return [
81
            'width'  => $x2 - min($x2, $x1),
82
            'height' => max($y2, $y1) - min($y2, $y1),
83
            'x'      => min($x2, $x1),
84
            'y'      => min($y2, $y1),
85
        ];
86
87
    }
88
89
    public static function getRoots($a, $b, $c)
90
    {
91
        $dis = $b * $b - 4 * $a * $c;
92
        if ($dis < 0) {
93
            return null;
94
        }
95
        self::avoidDivisionByZero($a);
96
97
        $disSqrt = sqrt($dis);
98
        $root1 = (-$b + $disSqrt) / (2 * $a);
99
        $root2 = (-$b - $disSqrt) / (2 * $a);
100
101
        self::checkBezierInterval($root1);
102
        self::checkBezierInterval($root2);
103
104
        return [$root1, $root2];
105
    }
106
107
    private static function getCubicValue($t, $p0, $p1, $p2, $p3)
108
    {
109
        $omt = 1 - $t;
110
        $value = $p0 * $omt * $omt *$omt +
111
            3 * $p1 * $t * $omt * $omt +
112
            3 * $p2 * $t * $t * $omt +
113
            $p3 * $t * $t * $t;
114
115
        return $value;
116
    }
117
118
    /**
119
     * @param $value
120
     */
121
    private static function avoidDivisionByZero(&$value)
122
    {
123
        if ($value === 0) {
124
            $value = self::EPSILON;
125
        }
126
    }
127
128
    /**
129
     * @param $t
130
     */
131
    private static function checkBezierInterval(&$t)
132
    {
133
        if ($t > 1 || $t < 0) {
134
            $t = 0;
135
        }
136
    }
137
}
138