Skip to content

Instantly share code, notes, and snippets.

@cmargroff
Last active April 4, 2022 16:34
Show Gist options
  • Select an option

  • Save cmargroff/c7d57dda2be4944843c918a530712fcf to your computer and use it in GitHub Desktop.

Select an option

Save cmargroff/c7d57dda2be4944843c918a530712fcf to your computer and use it in GitHub Desktop.
"use strict";
class Spline{
constructor(points){
if(points.length % 2 !== 0 || points.length < 6){
return undefined;
}
this.x = [];
this.y = [];
for(var i=0; i < points.length; i+=2){
this.x.push(points[i]);
this.y.push(points[i+1]);
}
this.s = this.x.length-1;
this.tl = 1/this.s;
this.cpx = this.computeControlPoints(this.x);
this.cpy = this.computeControlPoints(this.y);
}
computeControlPoints(K){
var cp1= [], cp2= [], n = K.length-1;
/*rhs vector*/
var a= [], b= [], c= [], r= [];
/*left most segment*/
a[0]=0;
b[0]=2;
c[0]=1;
r[0] = K[0]+2*K[1];
/*internal segments*/
for (var 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 (i = 1; i < n; i++) {
var m = a[i]/b[i-1];
b[i] = b[i] - m * c[i - 1];
r[i] = r[i] - m*r[i-1];
}
cp1[n-1] = r[n-1]/b[n-1];
for (i = n - 2; i >= 0; --i)
cp1[i] = (r[i] - c[i] * cp1[i+1]) / b[i];
/*we have p1, now compute p2*/
for (i=0;i<n-1;i++)
cp2[i]=2*K[i+1]-cp1[i+1];
cp2[n-1]=0.5*(K[n]+cp1[n-1]);
return [cp1, cp2];
}
curve(n){
if(n < this.s){
return [this.x[n], this.y[n], this.cpx[0][n], this.cpy[0][n], this.cpx[1][n], this.cpy[1][n], this.x[n+1], this.y[n+1]];
}
return false;
}
point(t){
t = t / this.tl;
var r = t % 1;
var s = t - r;
var c = this.curve(s);
return {
x: Math.pow(1-r,3)*c[0]+3*Math.pow(1-r,2)*r*c[2]+3*(1-r)*Math.pow(r,2)*c[4]+Math.pow(r,3)*c[6],
y: Math.pow(1-r,3)*c[1]+3*Math.pow(1-r,2)*r*c[3]+3*(1-r)*Math.pow(r,2)*c[5]+Math.pow(r,3)*c[7]
};
}
tangent(t){
t = t / this.tl;
var r = t % 1;
var s = t - r;
var c = this.curve(s);
return Math.atan2(
3*Math.pow(1-r,2)*(c[3]-c[1])+6*(1-r)*r*(c[5]-c[3])+3*Math.pow(r,2)*(c[7]-c[5]),
3*Math.pow(1-r,2)*(c[2]-c[0])+6*(1-r)*r*(c[4]-c[2])+3*Math.pow(r,2)*(c[6]-c[4])
);
}
normal(t){
t = t / this.tl;
var r = t % 1;
var s = t - r;
var c = this.curve(s);
return [
6*(1-r)*(c[4]-2*c[2]+c[0])+6*r*(c[6]-2*c[4]+c[2]),
6*(1-r)*(c[5]-2*c[3]+c[1])+6*r*(c[7]-2*c[5]+c[3])
];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment