Created
March 14, 2019 22:57
-
-
Save thehans/2da9f7c608f4a689456e714eaa2189e6 to your computer and use it in GitHub Desktop.
Bezier curve function for OpenSCAD (any order curve, any dimension points)
This file contains 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
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