market/src/@utils/bezier-spline.ts

64 lines
1.5 KiB
TypeScript

/* bezier-spline.js
*
* computes cubic bezier coefficients to generate a smooth
* line through specified points. couples with SVG graphics
* for interactive processing.
*
* For more info see:
* http://www.particleincell.com/2012/bezier-splines/
*
* Lubos Brieda, Particle In Cell Consulting LLC, 2012
* you may freely use this algorithm in your codes however where feasible
* please include a link/reference to the source article
*/
/* computes control points given knots K, this is the brain of the operation */
export function computeControlPoints(K: number[]) {
const p1 = []
const p2 = []
const n = K.length - 1
/* rhs vector */
const a = []
const b = []
const c = []
const r = []
/* left most segment */
a[0] = 0
b[0] = 2
c[0] = 1
r[0] = K[0] + 2 * K[1]
/* internal segments */
for (let i = 1; i < n - 1; i++) {
a[i] = 1
b[i] = 4
c[i] = 1
r[i] = 4 * K[i] + 2 * K[i + 1]
}
/* right segment */
a[n - 1] = 2
b[n - 1] = 7
c[n - 1] = 0
r[n - 1] = 8 * K[n - 1] + K[n]
/* solves Ax=b with the Thomas algorithm (from Wikipedia) */
for (let i = 1; i < n; i++) {
const m: number = a[i] / b[i - 1]
b[i] = b[i] - m * c[i - 1]
r[i] = r[i] - m * r[i - 1]
}
p1[n - 1] = r[n - 1] / b[n - 1]
for (let i = n - 2; i >= 0; --i) p1[i] = (r[i] - c[i] * p1[i + 1]) / b[i]
/* we have p1, now compute p2 */
for (let i = 0; i < n - 1; i++) p2[i] = 2 * K[i + 1] - p1[i + 1]
p2[n - 1] = 0.5 * (K[n] + p1[n - 1])
return { p1: p1.map((p) => Math.floor(p)), p2: p2.map((p) => Math.floor(p)) }
}