Test out some bezier curve matching based on @jasondavies animated bezier example.
Super powerful example of how a computer draws bezier curves moving from A to B.
Test out some bezier curve matching based on @jasondavies animated bezier example.
Super powerful example of how a computer draws bezier curves moving from A to B.
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: #000; | |
shape-rendering: crispEdges; | |
} | |
.svg-bezier { | |
fill: none; | |
stroke: blue; | |
stroke-width: 2px; | |
stroke-dasharray: 5 5; | |
} | |
.curve, .line { | |
fill: none; | |
stroke-width: 1px; | |
} | |
.curve { | |
stroke: green; | |
stroke-width: 3px; | |
} | |
.control { | |
fill: #ccc; | |
stroke: #000; | |
stroke-width: .5px; | |
cursor: move; | |
} | |
.sample { | |
fill: red; | |
} | |
.path.interpolated { | |
fill: none; | |
stroke: red; | |
stroke-width: 1px; | |
} | |
</style> | |
<div id='vis'> | |
</div> | |
</script> | |
<script src="//d3js.org/d3.v3.min.js"></script> | |
<script src="https://rawgit.com/soswow/fit-curve/master/lib/fit-curve.js"></script> | |
<script> | |
var margin = {top: 20, right: 20, bottom: 30, left: 40}, | |
width = 960 - margin.left - margin.right, | |
height = 500 - margin.top - margin.bottom; | |
var xR = d3.scale.linear() | |
.range([0, width]); | |
var yR = d3.scale.linear() | |
.range([height, 0]); | |
var w = 220, | |
h = 400, | |
padding = 10, | |
bezier = {}, | |
n = 4, // cubic | |
stroke = d3.scale.category20b(), | |
line = d3.svg.line().x(pX).y(pY), | |
orders = d3.range(n, n+1); | |
var points = [ | |
{x: 100, y: 346}, | |
{x: 0, y: 175}, | |
{x: 100, y: 175}, | |
{x: 120, y: 200} | |
]; | |
var xOrigin = -100; | |
var yOrigin = 320; | |
var fx = 8; | |
var sample_data = [[8, -1.45], [7.89,-1.3], [8.08,-0.16], [7.57,1.86], [6.05,3.91], [5.69,5.07], [7.16,5.05], [9.07, 4.97]]; | |
var sample_points = sample_data.map( function (d) { return { x: d[0], y: d[1] }}); | |
// https://github.com/soswow/fit-curve | |
var bPoints = [[0, 0], [10, 10], [10, 0], [20, 0]]; | |
var error = 50; // The smaller the number - the much closer spline should be | |
var bezierCurves = fitCurve(sample_data, error); | |
points = bezierCurves[0].map( function (d) { return { x: d[0], y: d[1] }}); | |
console.log("CPs"); | |
console.log(points); | |
var sampleFit = d3.svg.line().x(pX).y(pY).interpolate('basis'); | |
var data = [ { x: 19.2, y: 10 }, { x: -19.2, y: -10} ] | |
// Compute the scales’ domains. | |
xR.domain(d3.extent(data, function(d) { return d.x; })).nice(); | |
yR.domain(d3.extent(data, function(d) { return d.y; })).nice(); | |
var bezierCurveD = function (points) { | |
var b1, c1, c2, b2; | |
var mx, my, x1, y1, x2, y2, x, y; | |
[b1, c1, c2, b2] = points; | |
[mx, x1, x2, x] = [b1, c1, c2, b2].map(pX); | |
[my, y1, y2, y] = [b1, c1, c2, b2].map(pY); | |
return `M ${mx} ${my} C ${x1} ${y1}, ${x2} ${y2}, ${x} ${y}` | |
} | |
var vis = d3.select("#vis").selectAll("svg") | |
.data(orders) | |
.enter().append("svg") | |
.attr("width", width + margin.left + margin.right) | |
.attr("height", height + margin.top + margin.bottom) | |
.append("g") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
// Add the x-axis. | |
vis.append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(0," + height + ")") | |
.call(d3.svg.axis().scale(xR).orient("bottom")); | |
// Add the y-axis. | |
vis.append("g") | |
.attr("class", "y axis") | |
.call(d3.svg.axis().scale(yR).orient("left")); | |
// Add the cubic bezier curve. | |
vis.append("path") | |
.attr("class", "svg-bezier") | |
.attr("d", bezierCurveD(points)); | |
vis.selectAll("circle.control") | |
.data(function(d) { return points.slice(0, d) }) | |
.enter().append("circle") | |
.attr("class", "control") | |
.attr("r", 7) | |
.attr("cx", pX) | |
.attr("cy", pY); | |
// draw interpolated path and points for sample | |
vis.selectAll("circle.play") | |
.data(sample_points) | |
.enter().append("circle") | |
.attr("class", "sample") | |
.attr("r", 2) | |
.attr("cx", pX) | |
.attr("cy", pY) | |
vis.append('path') | |
.attr({ | |
class: 'path interpolated', | |
d: sampleFit(sample_points) | |
}); | |
function pX(d) { return xR(d.x); } | |
function pY(d) { return yR(d.y); } | |
</script> |