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> |