1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 | const base3 = (t, p1, p2, p3, p4) => {
|
14 | const t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4,
|
15 | t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3;
|
16 | return t * t2 - 3 * p1 + 3 * p2;
|
17 | };
|
18 |
|
19 | const belzen = exports.bezlen = (x1, y1, x2, y2, x3, y3, x4, y4, z) => {
|
20 | if (z == null) {
|
21 | z = 1;
|
22 | }
|
23 | z = z > 1 ? 1 : z < 0 ? 0 : z;
|
24 | var z2 = z / 2,
|
25 | n = 12,
|
26 | Tvalues = [-.1252,.1252,-.3678,.3678,-.5873,.5873,-.7699,.7699,-.9041,.9041,-.9816,.9816],
|
27 | Cvalues = [0.2491,0.2491,0.2335,0.2335,0.2032,0.2032,0.1601,0.1601,0.1069,0.1069,0.0472,0.0472],
|
28 | sum = 0;
|
29 | for (var i = 0; i < n; i++) {
|
30 | var ct = z2 * Tvalues[i] + z2,
|
31 | xbase = base3(ct, x1, x2, x3, x4),
|
32 | ybase = base3(ct, y1, y2, y3, y4),
|
33 | comb = xbase * xbase + ybase * ybase;
|
34 | sum += Cvalues[i] * Math.sqrt(comb);
|
35 | }
|
36 | return z2 * sum;
|
37 | };
|
38 |
|
39 | const findDotsAtSegment = exports.findDotsAtSegment = (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) => {
|
40 | const t1 = 1 - t,
|
41 | t12 = t1 * t1,
|
42 | t13 = t12 * t1,
|
43 | t2 = t * t,
|
44 | t3 = t2 * t,
|
45 | x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x,
|
46 | y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y;
|
47 | return {
|
48 | x: x,
|
49 | y: y
|
50 | };
|
51 | };
|
52 |
|
53 | const catmullRom2bezier = exports.catmullRom2bezier = (crp, z) => {
|
54 | const d = [];
|
55 | let end = {x: +crp[0], y: +crp[1]};
|
56 | for (let i = 0, iLen = crp.length; iLen - 2 * !z > i; i += 2) {
|
57 | const p = [
|
58 | {x: +crp[i - 2], y: +crp[i - 1]},
|
59 | {x: +crp[i], y: +crp[i + 1]},
|
60 | {x: +crp[i + 2], y: +crp[i + 3]},
|
61 | {x: +crp[i + 4], y: +crp[i + 5]}
|
62 | ];
|
63 | if (z) {
|
64 | if (!i) {
|
65 | p[0] = {x: +crp[iLen - 2], y: +crp[iLen - 1]};
|
66 | } else if (iLen - 4 == i) {
|
67 | p[3] = {x: +crp[0], y: +crp[1]};
|
68 | } else if (iLen - 2 == i) {
|
69 | p[2] = {x: +crp[0], y: +crp[1]};
|
70 | p[3] = {x: +crp[2], y: +crp[3]};
|
71 | }
|
72 | } else {
|
73 | if (iLen - 4 == i) {
|
74 | p[3] = p[2];
|
75 | } else if (!i) {
|
76 | p[0] = {x: +crp[i], y: +crp[i + 1]};
|
77 | }
|
78 | }
|
79 | d.push([
|
80 | end.x,
|
81 | end.y,
|
82 | (-p[0].x + 6 * p[1].x + p[2].x) / 6,
|
83 | (-p[0].y + 6 * p[1].y + p[2].y) / 6,
|
84 | (p[1].x + 6 * p[2].x - p[3].x) / 6,
|
85 | (p[1].y + 6 * p[2].y - p[3].y) / 6,
|
86 | p[2].x,
|
87 | p[2].y
|
88 | ]);
|
89 | end = p[2];
|
90 | }
|
91 |
|
92 | return d;
|
93 | };
|
94 |
|
95 | const prepareCurve = exports.prepareCurve = (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) => {
|
96 | const len = Math.floor(bezlen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) * .75);
|
97 | const map = new Map;
|
98 | for (let i = 0; i <= len; i++) {
|
99 | const t = i / len;
|
100 | map.set(t, findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t));
|
101 | }
|
102 | return x => {
|
103 | const keys = Array.from(map.keys());
|
104 | let p = map.get(keys[0]);
|
105 | const last = map.get(keys[keys.length - 1]);
|
106 | if (x < p.x || x > last.x) {
|
107 | return null;
|
108 | }
|
109 | for (let i = 0; i < keys.length; i++) {
|
110 | const value = map.get(keys[i]);
|
111 | if (value.x >= x) {
|
112 | const x1 = p.x;
|
113 | const x2 = value.x;
|
114 | const y1 = p.y;
|
115 | const y2 = value.y;
|
116 | if (!i) {
|
117 | return y2;
|
118 | }
|
119 | return (x - x1) * (y2 - y1) / (x2 - x1) + y1;
|
120 | }
|
121 | p = value;
|
122 | }
|
123 | };
|
124 | };
|