Skip to content

Instantly share code, notes, and snippets.

@queuebit
Last active August 31, 2017 15:22
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 queuebit/b7c5cbee6558a1ce14f1036a2e9798d0 to your computer and use it in GitHub Desktop.
Save queuebit/b7c5cbee6558a1ce14f1036a2e9798d0 to your computer and use it in GitHub Desktop.
Bezier test harness
<!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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment