Skip to content

Instantly share code, notes, and snippets.

@harold
Last active April 28, 2020 14:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save harold/e6fa40799b9a6f9acc43ca4a32af3edf to your computer and use it in GitHub Desktop.
Save harold/e6fa40799b9a6f9acc43ca4a32af3edf to your computer and use it in GitHub Desktop.
terse-js-spline
license: mit
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
</style>
</head>
<body>
<script>
function makeSpline(pts) {
let n = pts.length
let [d, u, w] = [[],[],[]]
for(let i=1; i<n-1; i++) d[i]=2*(pts[i+1].x-pts[i-1].x)
for(let i=0; i<n-1; i++) u[i]=pts[i+1].x-pts[i].x
for(let i=1; i<n-1; i++)
w[i]=6*((pts[i+1].y-pts[i].y)/u[i]-(pts[i].y-pts[i-1].y)/u[i-1])
let p = []
p[0]=p[n-1]=0
for(let i=1; i<n-2; i++) {
w[i+1]=w[i+1]-w[i]*u[i]/d[i]
d[i+1]=d[i+1]-u[i]*u[i]/d[i]
}
for(let i=n-2; i>=1; i--)
p[i]=(w[i]-u[i]*p[i+1])/d[i]
return (x) => {
let f = (v) => {return v*v*v-v}
let i=-1
do { i++ } while(x>=pts[i+1].x)
let t = (x-pts[i].x)/u[i]
return t*pts[i+1].y+(1-t)*pts[i].y+u[i]*u[i]*(f(t)*p[i+1]+f(1-t)*p[i])/6
}
}
let spline = makeSpline([{x: 1, y: 0},
{x: 2, y: 1},
{x: 5, y: -1},
{x: 8, y: 0},
{x:10, y: 2}])
var svg = d3.select("body").append("svg").attr("width",800).attr("height",450)
let ptCount = 40
for(let i=0;i<ptCount;i++) {
let x = 1 + (10-1)/ptCount*i
let y = spline(x)
svg.append("circle")
.attr("cx",x*50)
.attr("cy",225-y*50).attr("r",2)
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment