Skip to content

Instantly share code, notes, and snippets.

@wolfiex
Last active December 3, 2017 21:37
Show Gist options
  • Save wolfiex/b0d9c1fe301eec7cbcf1e57a27834b17 to your computer and use it in GitHub Desktop.
Save wolfiex/b0d9c1fe301eec7cbcf1e57a27834b17 to your computer and use it in GitHub Desktop.
Bezier Trapezoid
license: gpl-3.0
height: 300
border: no

A program to link nodes of different radii using a cubic bezier spline.

function bezier(x, y, r, x1, y1, r1) {
var a = x;
var b = y + 0.3 * (y1 - y);
var c = x1;
var d = y + 0.6 * (y1 - y);
var string = "M " + x + "," + y;
//rotation coords
var dx = x1 - x;
var dy = y1 - y;
var max = d3.max([Math.abs(dx), Math.abs(dy)]);
dx /= max;
dy /= max;
sign = Math.cos(dx / dy) > 0;
sn = -1 / Math.sqrt(dx * dx + dy * dy);
fn = interpolateCubicBezier(
[x + dx * r * sn, y - dy * r * sn],
[a, b],
[c, d],
[x1 + dx * r1 * sn, y1 + sign * (dy * r1 * sn)]
);
d3.range(100).forEach((d, i, a) => {
t = d / (a.length - 1);
string += " L" + fn(t)[0] + "," + fn(t)[1];
});
sn *= -1;
fn = interpolateCubicBezier(
[x + dx * r * sn, y + sign * (dy * r * sn)],
[a, b],
[c, d],
[x1 + dx * r1 * sn, y1 - sign * (dy * r1 * sn)]
);
d3.range(100).forEach((d, i, a) => {
t = 1 - d / (a.length - 1);
string += " L" + fn(t)[0] + "," + fn(t)[1];
});
return string;
}
//Cubic Bezier by Peter Beshai
// B(t) = (1 - t)^3P0 + 3(1 - t)^2tP1 + 3(1 - t)t^2P2 + t^3P3
function interpolateCubicBezier(start, control1, control2, end) {
// 0 <= t <= 1
return function interpolator(t) {
return [
Math.pow(1 - t, 3) * start[0] +
3 * Math.pow(1 - t, 2) * t * control1[0] +
3 * (1 - t) * Math.pow(t, 2) * control2[0] +
Math.pow(t, 3) * end[0],
Math.pow(1 - t, 3) * start[1] +
3 * Math.pow(1 - t, 2) * t * control1[1] +
3 * (1 - t) * Math.pow(t, 2) * control2[1] +
Math.pow(t, 3) * end[1]
];
};
}
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="./bezierTrapezoid.js"></script>
<script>
// Usage is free, but please attribute back to D.Ellis if used in project
var width = 300;
var height = 300;
var svg = d3.select("body").append("svg");
svg.attr("width", width);
svg.attr("height", height);
var points = [[20, 20, 10], [100, 200, 50]];
//The line SVG Path we draw
svg
.append("path")
.attr(
"d",
bezier(
points[0][0],
points[0][1],
points[0][2],
points[1][0],
points[1][1],
points[1][2]
)
)
.attr("stroke", "blue")
.attr("stroke-width", 2)
.attr("fill", "red");
var circles = svg
.append("g")
.selectAll("circle")
.data(points)
.enter()
.append("circle")
.style("stroke", "gray")
.style("fill", "white")
.attr("r", d => d[2])
.attr("cx", d => d[0])
.attr("cy", d => d[1]);
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment