| 20 | }); |
| 21 | |
| 22 | const catmullRom = (points: XY[], samples = 12): Coordinate[] => { |
| 23 | if (points.length < 2) return points.map(([x, y]) => pt(x, y)); |
| 24 | const result: Coordinate[] = []; |
| 25 | for (let i = 0; i < points.length - 1; i++) { |
| 26 | const p0 = points[Math.max(i - 1, 0)] as XY; |
| 27 | const p1 = points[i] as XY; |
| 28 | const p2 = points[i + 1] as XY; |
| 29 | const p3 = points[Math.min(i + 2, points.length - 1)] as XY; |
| 30 | for (let s = 0; s < samples; s++) { |
| 31 | const t = s / samples; |
| 32 | const t2 = t * t; |
| 33 | const t3 = t2 * t; |
| 34 | result.push( |
| 35 | pt( |
| 36 | 0.5 * |
| 37 | (2 * p1[0] + |
| 38 | (-p0[0] + p2[0]) * t + |
| 39 | (2 * p0[0] - 5 * p1[0] + 4 * p2[0] - p3[0]) * t2 + |
| 40 | (-p0[0] + 3 * p1[0] - 3 * p2[0] + p3[0]) * t3), |
| 41 | 0.5 * |
| 42 | (2 * p1[1] + |
| 43 | (-p0[1] + p2[1]) * t + |
| 44 | (2 * p0[1] - 5 * p1[1] + 4 * p2[1] - p3[1]) * t2 + |
| 45 | (-p0[1] + 3 * p1[1] - 3 * p2[1] + p3[1]) * t3) |
| 46 | ) |
| 47 | ); |
| 48 | } |
| 49 | } |
| 50 | const last = points[points.length - 1] as XY; |
| 51 | result.push(pt(last[0], last[1])); |
| 52 | return result; |
| 53 | }; |
| 54 | |
| 55 | // "TRUE" above — smaller scale, offset up |
| 56 | const TY = 1.3; |