A program to link nodes of different radii using a cubic bezier spline.
Last active
December 3, 2017 21:37
-
-
Save wolfiex/b0d9c1fe301eec7cbcf1e57a27834b17 to your computer and use it in GitHub Desktop.
Bezier Trapezoid
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
license: gpl-3.0 | |
height: 300 | |
border: no |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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] | |
]; | |
}; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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