quadratic splines
Log in to post a comment.
// You can find the Turtle API reference here: https://turtletoy.net/syntax Canvas.setpenopacity(0.2); // Global code will be evaluated once. const turtle = new Turtle(); turtle.penup(); // Cardinal Splines ref: https://stackoverflow.com/questions/7054272/how-to-draw-smooth-curve-through-n-points-using-javascript-html5-canvas turtle.drawSpline = (pts, tension = 0.5, isClosed = false, numOfSegments = 16) => { const res = []; // clone array const _pts = pts.slice(0); // The algorithm require a previous and next point to the actual point array. // Check if we will draw closed or open curve. // If closed, copy end points to beginning and first points to end // If open, duplicate first points to befinning, end points to end if (isClosed) { _pts.unshift(pts[pts.length - 1]); _pts.unshift(pts[pts.length - 2]); _pts.unshift(pts[pts.length - 1]); _pts.unshift(pts[pts.length - 2]); _pts.push(pts[0]); _pts.push(pts[1]); } else { _pts.unshift(pts[1]); //copy 1. point and insert at beginning _pts.unshift(pts[0]); _pts.push(pts[pts.length - 2]); //copy last point and append _pts.push(pts[pts.length - 1]); } // ok, lets start.. // 1. loop goes through point array // 2. loop goes through each segment between the 2 pts + 1e point before and after for (let i = 2; i < (_pts.length - 4); i += 2) { for (let t = 0; t <= numOfSegments; t++) { // calc tension vectors const t1x = (_pts[i+2] - _pts[i-2]) * tension; const t2x = (_pts[i+4] - _pts[i]) * tension; const t1y = (_pts[i+3] - _pts[i-1]) * tension; const t2y = (_pts[i+5] - _pts[i+1]) * tension; // calc step const st = t / numOfSegments; // calc cardinals const c1 = 2 * Math.pow(st, 3) - 3 * Math.pow(st, 2) + 1; const c2 = -(2 * Math.pow(st, 3)) + 3 * Math.pow(st, 2); const c3 = Math.pow(st, 3) - 2 * Math.pow(st, 2) + st; const c4 = Math.pow(st, 3) - Math.pow(st, 2); // calc x and y cords with common control vectors const x = c1 * _pts[i] + c2 * _pts[i+2] + c3 * t1x + c4 * t2x; const y = c1 * _pts[i+1] + c2 * _pts[i+3] + c3 * t1y + c4 * t2y; //store points in array res.push(x); res.push(y); } } // draw turtle.goto(res[0], res[1]); turtle.down(); for(let i = 2; i < res.length - 1; i += 2) turtle.goto(res[i], res[i+ 1]); turtle.up(); return res; } ////////////////////////////////////////// const points = []; const velocities = []; for (let i = 0; i < 30; i++) { points.push(i * (200 / 30) - 100, 0.25 * 100 * (Math.random() - Math.random())); velocities.push(0, 0); } // The walk function will be called until it returns false. function walk(i) { for (let y = 0; y < 60; y++) { velocities[y] += 0.1 * (Math.random() - Math.random()); points[y] += velocities[y]; } turtle.drawSpline(points); return i < 200; }