(controlPoints, numSamples)
| 24 | } |
| 25 | |
| 26 | function interpolateSpline(controlPoints, numSamples) { |
| 27 | if (controlPoints.length === 0) return []; |
| 28 | if (controlPoints.length === 1) { |
| 29 | return Array.from({ length: numSamples }, () => ({ ...controlPoints[0] })); |
| 30 | } |
| 31 | if (controlPoints.length === 2) { |
| 32 | const [a, b] = controlPoints; |
| 33 | return Array.from({ length: numSamples }, (_, i) => { |
| 34 | const t = i / (numSamples - 1); |
| 35 | return { x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t }; |
| 36 | }); |
| 37 | } |
| 38 | // Pad with phantom endpoints for Catmull-Rom |
| 39 | const pts = [ |
| 40 | controlPoints[0], |
| 41 | ...controlPoints, |
| 42 | controlPoints[controlPoints.length - 1], |
| 43 | ]; |
| 44 | const nSeg = pts.length - 3; |
| 45 | const result = []; |
| 46 | for (let i = 0; i < numSamples; i++) { |
| 47 | const gT = (i / (numSamples - 1)) * nSeg; |
| 48 | const seg = Math.min(Math.floor(gT), nSeg - 1); |
| 49 | const lT = gT - seg; |
| 50 | result.push(catmullRom(pts[seg], pts[seg + 1], pts[seg + 2], pts[seg + 3], lT)); |
| 51 | } |
| 52 | return result; |
| 53 | } |
| 54 | |
| 55 | // --------------------------------------------------------------------------- |
| 56 | // Visual constants |
no test coverage detected