Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Bezier curve function for OpenSCAD (any order curve, any dimension points)
BezierExample();
//BezierCircleApprox(10);
// cubic bezier circle approximation example
module BezierCircleApprox(r) {
$fn=1000;
c = 0.551915024494;
points = BezierPath([
[ 0, 1], [ c, 1], [ 1, c], [ 1, 0],
[ 1,-c], [ c,-1], [ 0,-1],
[-c,-1], [-1,-c], [-1, 0],
[-1, c], [-c, 1], [ 0, 1]
], index=0, n=3);
echo(len(points));
polygon(r*points);
}
module BezierExample() {
points = [
[0,0, 1],
[1,1, -1],
[3,-1, 1],
[4,0, -1],
[5,4, 1],
[5,5, -1],
[0,6, 1],
[10,6, -1],
[0,0,10],
[0,0,5]
];
$fn=1000;
size = 0.02;
//echo(len(BezierPath(points,n=7)));
%showPoints(points, size*3);
//*
color("red") showPoints(BezierPath(points,n=1), size);
color("green") showPoints(BezierPath(points,n=2), size);
color("blue") showPoints(BezierPath(points,n=3), size);
color("yellow") showPoints(BezierPath(points,n=4), size);
color("magenta") showPoints(BezierPath(points,n=5), size);
color("cyan") showPoints(BezierPath(points,n=6), size);
color("white") showPoints(BezierPath(points,n=7), size);
//*/
}
module showPoints(points, size=0.02) {
for (c = points) translate(c) cube(size, center=true);
}
// return point along curve at position "t" in range [0,1]
// use ctlPts[index] as the first control point
// Bezier curve has order == n
function BezierPoint(ctlPts, t, n, index=0) = (n > 1) ?
_BezierPoint([for (i = [index:index+n-1]) ctlPts[i] + t * (ctlPts[i+1] - ctlPts[i])], t, n-1) :
ctlPts[index] + t * (ctlPts[index+1] - ctlPts[index]);
// slightly optimized version takes less parameters
function _BezierPoint(ctlPts, t, n) = (n > 1) ?
_BezierPoint([for (i = [0:n-1]) ctlPts[i] + t * (ctlPts[i+1] - ctlPts[i])], t, n-1) :
ctlPts[0] + t * (ctlPts[1] - ctlPts[0]);
// n sets the order of the Bezier curves that will be stitched together
// if no parameter n is given, points will be generated for a single curve of order == len(ctlPts) - 1
// Note: $fn is number of points *per segment*, not over the entire path.
function BezierPath(ctlPts, n, index=0) =
let (
l1 = $fn > 3 ? $fn : 200,
l2 = len(ctlPts),
n = (n == undef || n > l2-1) ? l2 - 1 : n
)
//assert(n > 0)
[for (segment = [index:n:l2-1-n], i = [0:l1-1])
BezierPoint(ctlPts, i / l1, n, segment), ctlPts[l2-1]];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.