1 | 'use strict';
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 | const getTimeGivenProgression = (p0, p1, p2, p3, progression) => {
|
23 | return solveCubicBezier(p0[1], p1[1], p2[1], p3[1], progression).map(tValue => {
|
24 | return solveCubicParametricEquation(p0[0], p1[0], p2[0], p3[0], tValue);
|
25 | });
|
26 | };
|
27 |
|
28 |
|
29 |
|
30 | const solveCubicParametricEquation = (p0, p1, p2, p3, t) => {
|
31 | const partA = (3 * p1) * Math.pow(t - 1, 2);
|
32 | const partB = (-3 * p2 * t) + (3 * p2) + (p3 * t);
|
33 | const partC = p0 * Math.pow(t - 1, 3);
|
34 | return t * (partA + (t * partB)) - partC;
|
35 | };
|
36 |
|
37 |
|
38 |
|
39 | const solveCubicBezier = (p0, p1, p2, p3, refPoint) => {
|
40 | p0 -= refPoint;
|
41 | p1 -= refPoint;
|
42 | p2 -= refPoint;
|
43 | p3 -= refPoint;
|
44 | const roots = solveCubicEquation(p3 - 3 * p2 + 3 * p1 - p0, 3 * p2 - 6 * p1 + 3 * p0, 3 * p1 - 3 * p0, p0);
|
45 | return roots.filter(root => root >= 0 && root <= 1);
|
46 | };
|
47 | const solveQuadraticEquation = (a, b, c) => {
|
48 | const discriminant = b * b - 4 * a * c;
|
49 | if (discriminant < 0) {
|
50 | return [];
|
51 | }
|
52 | else {
|
53 | return [
|
54 | (-b + Math.sqrt(discriminant)) / (2 * a),
|
55 | (-b - Math.sqrt(discriminant)) / (2 * a)
|
56 | ];
|
57 | }
|
58 | };
|
59 | const solveCubicEquation = (a, b, c, d) => {
|
60 | if (a === 0) {
|
61 | return solveQuadraticEquation(b, c, d);
|
62 | }
|
63 | b /= a;
|
64 | c /= a;
|
65 | d /= a;
|
66 | const p = (3 * c - b * b) / 3;
|
67 | const q = (2 * b * b * b - 9 * b * c + 27 * d) / 27;
|
68 | if (p === 0) {
|
69 | return [Math.pow(-q, 1 / 3)];
|
70 | }
|
71 | else if (q === 0) {
|
72 | return [Math.sqrt(-p), -Math.sqrt(-p)];
|
73 | }
|
74 | const discriminant = Math.pow(q / 2, 2) + Math.pow(p / 3, 3);
|
75 | if (discriminant === 0) {
|
76 | return [Math.pow(q / 2, 1 / 2) - b / 3];
|
77 | }
|
78 | else if (discriminant > 0) {
|
79 | return [Math.pow(-(q / 2) + Math.sqrt(discriminant), 1 / 3) - Math.pow((q / 2) + Math.sqrt(discriminant), 1 / 3) - b / 3];
|
80 | }
|
81 | const r = Math.sqrt(Math.pow(-(p / 3), 3));
|
82 | const phi = Math.acos(-(q / (2 * Math.sqrt(Math.pow(-(p / 3), 3)))));
|
83 | const s = 2 * Math.pow(r, 1 / 3);
|
84 | return [
|
85 | s * Math.cos(phi / 3) - b / 3,
|
86 | s * Math.cos((phi + 2 * Math.PI) / 3) - b / 3,
|
87 | s * Math.cos((phi + 4 * Math.PI) / 3) - b / 3
|
88 | ];
|
89 | };
|
90 |
|
91 | exports.getTimeGivenProgression = getTimeGivenProgression;
|