forked from Alchemist0823/three.quarks
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Bezier.ts
103 lines (92 loc) · 2.77 KB
/
Bezier.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
export class Bezier {
p: number[];
constructor(p1: number, p2: number, p3: number, p4: number) {
this.p = [p1 ,p2, p3, p4];
}
genValue(t: number): number {
const t2 = t * t;
const t3 = t * t * t;
const mt = 1 - t;
const mt2 = mt * mt;
const mt3 = mt2 * mt;
return this.p[0] * mt3 + this.p[1] * mt2 * t * 3 + this.p[2] * mt * t2 * 3 + this.p[3] * t3;
}
// get the coefficients of the polynomial's derivatives
derivativeCoefficients(points: number[]): number[][] {
const dpoints = [];
for (let p = points, c = p.length - 1; c > 0; c--) {
const list = [];
for (let j = 0; j < c; j++) {
const dpt = c * (p[j + 1] - p[j]);
list.push(dpt);
}
dpoints.push(list);
p = list;
}
return dpoints;
}
// calculate the slope
getSlope(t: number): number {
const p = this.derivativeCoefficients(this.p)[0];
const mt = 1 - t;
const a = mt * mt;
const b = mt * t * 2;
const c = t * t;
return a * p[0] + b * p[1] + c * p[2];
//return a * (p[1] - p[0]) * 3 + b * (p[2] - p[1]) * 3 + c * (p[3] - p[2]) * 3;
}
// derivative(0) = (p[1] - p[0]) * 3
// derivative(1) = (p[3] - p[2]) * 3
controlCurve(d0: number, d1: number) {
this.p[1] = d0 / 3 + this.p[0];
this.p[2] = this.p[3] - d1 / 3;
}
hull(t: number) {
let p = this.p;
let _p = [],
pt,
idx = 0,
i = 0,
l = 0;
const q = [];
q[idx++] = p[0];
q[idx++] = p[1];
q[idx++] = p[2];
q[idx++] = p[3];
// we lerp between all points at each iteration, until we have 1 point left.
while (p.length > 1) {
_p = [];
for (i = 0, l = p.length - 1; i < l; i++) {
pt = t * p[i] + (1 - t) * p[i + 1];
q[idx++] = pt;
_p.push(pt);
}
p = _p;
}
return q;
}
split(t: number) {
// no shortcut: use "de Casteljau" iteration.
const q = this.hull(t);
const result = {
left : new Bezier(q[0], q[4], q[7], q[9]),
right: new Bezier(q[9], q[8], q[6], q[3]),
span: q
};
return result;
}
clone() {
return new Bezier(this.p[0], this.p[1], this.p[2], this.p[3]);
}
toJSON() {
return {
p0 : this.p[0],
p1 : this.p[1],
p2 : this.p[2],
p3 : this.p[3],
};
}
static fromJSON(json: {p0: number, p1: number, p2: number, p3: number}): Bezier {
return new Bezier(json.p0, json.p1, json.p2, json.p3);
}
}