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