mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-01 09:49:45 +00:00
Updated bezier code to support N-point beziers.
This commit is contained in:
parent
453ebcb83f
commit
2d9fa565b3
3 changed files with 62 additions and 48 deletions
88
beziers.scad
88
beziers.scad
|
@ -33,40 +33,46 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
include <math.scad>
|
include <math.scad>
|
||||||
include <paths.scad>
|
include <paths.scad>
|
||||||
|
include <transforms.scad>
|
||||||
|
|
||||||
|
|
||||||
// Formulae to calculate points on a cubic bezier curve.
|
// Formulae to calculate points on an N-point bezier curve.
|
||||||
function bez_B0(curve,u) = curve[0]*pow((1-u),3);
|
function bez_point(curve,u)=
|
||||||
function bez_B1(curve,u) = curve[1]*(3*u*pow((1-u),2));
|
(len(curve) <= 1) ?
|
||||||
function bez_B2(curve,u) = curve[2]*(3*pow(u,2)*(1-u));
|
curve[0] :
|
||||||
function bez_B3(curve,u) = curve[3]*pow(u,3);
|
bez_point(
|
||||||
function bez_point(curve,u) = bez_B0(curve,u) + bez_B1(curve,u) + bez_B2(curve,u) + bez_B3(curve,u);
|
[for(i=[0:len(curve)-2]) curve[i]*(1-u)+curve[i+1]*u],
|
||||||
|
u
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
// Takes an array of bezier points and converts it into a 3D polyline.
|
// Takes an array of bezier points and converts it into a 3D polyline.
|
||||||
function bezier_polyline(bezier, splinesteps=16) = concat(
|
function bezier_polyline(bezier, splinesteps=16, N=3) = concat(
|
||||||
[
|
[
|
||||||
for (
|
for (
|
||||||
b = [0 : 3 : len(bezier)-4],
|
b = [0 : N : len(bezier)-N-1],
|
||||||
l = [0 : splinesteps-1]
|
l = [0 : splinesteps-1]
|
||||||
) let (
|
) let (
|
||||||
crv = [bezier[b+0], bezier[b+1], bezier[b+2], bezier[b+3]],
|
crv = [for (i=[0 : N]) bezier[b+i]],
|
||||||
u = l / splinesteps
|
u = l / splinesteps
|
||||||
) bez_point(crv, u)
|
) bez_point(crv, u)
|
||||||
],
|
],
|
||||||
[bez_point([bezier[len(bezier)-4], bezier[len(bezier)-3], bezier[len(bezier)-2], bezier[len(bezier)-1]], 1.0)]
|
[bez_point([for (i=[-(N+1) : -1]) bezier[len(bezier)+i]], 1.0)]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// Takes a closed 2D bezier path, and creates a 2D polygon from it.
|
// Takes a closed 2D bezier path, and creates a 2D polygon from it.
|
||||||
module bezier_polygon(bezier, splinesteps=16) {
|
// bezier = array of 2D bezier path points
|
||||||
polypoints=bezier_polyline(bezier, splinesteps);
|
// splinesteps = number of straight lines to split each bezier segment into
|
||||||
|
// N = number of points in each bezier segment. Cubic = 3
|
||||||
|
module bezier_polygon(bezier, splinesteps=16, N=3) {
|
||||||
|
polypoints=bezier_polyline(bezier, splinesteps, N);
|
||||||
polygon(points=slice(polypoints, 0, -1));
|
polygon(points=slice(polypoints, 0, -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Generate bezier curve to fillet 2 line segments between 3 points.
|
// Generate bezier curve to fillet 2 line segments between 3 points.
|
||||||
// Returns two path points with surrounding cubic bezier control points.
|
// Returns two path points with surrounding cubic (N=3) bezier control points.
|
||||||
function fillet3pts(p0, p1, p2, r) = let(
|
function fillet3pts(p0, p1, p2, r) = let(
|
||||||
v0 = normalize(p0-p1),
|
v0 = normalize(p0-p1),
|
||||||
v1 = normalize(p2-p1),
|
v1 = normalize(p2-p1),
|
||||||
|
@ -82,7 +88,7 @@ function fillet3pts(p0, p1, p2, r) = let(
|
||||||
) [tp0, tp0, cp0, cp1, tp1, tp1];
|
) [tp0, tp0, cp0, cp1, tp1, tp1];
|
||||||
|
|
||||||
|
|
||||||
// Takes a 3D polyline path and fillets it into a 3d cubic bezier path.
|
// Takes a 3D polyline path and fillets it into a 3d cubic (N=3) bezier path.
|
||||||
function fillet_path(pts, fillet) = concat(
|
function fillet_path(pts, fillet) = concat(
|
||||||
[pts[0], pts[0]],
|
[pts[0], pts[0]],
|
||||||
(len(pts) < 3)? [] : [
|
(len(pts) < 3)? [] : [
|
||||||
|
@ -98,6 +104,7 @@ function fillet_path(pts, fillet) = concat(
|
||||||
// Takes a closed 2D bezier and rotates it around the X axis, forming a solid.
|
// Takes a closed 2D bezier and rotates it around the X axis, forming a solid.
|
||||||
// bezier = array of points for the bezier path to rotate.
|
// bezier = array of points for the bezier path to rotate.
|
||||||
// splinesteps = number of segments to divide each bezier segment into.
|
// splinesteps = number of segments to divide each bezier segment into.
|
||||||
|
// N = number of points in each bezier segment. Cubic = 3
|
||||||
// Example:
|
// Example:
|
||||||
// path = [
|
// path = [
|
||||||
// [ 0, 10], [ 50, 0], [ 50, 40],
|
// [ 0, 10], [ 50, 0], [ 50, 40],
|
||||||
|
@ -107,35 +114,36 @@ function fillet_path(pts, fillet) = concat(
|
||||||
// [ 0, 10]
|
// [ 0, 10]
|
||||||
// ];
|
// ];
|
||||||
// revolve_bezier(path, splinesteps=32, $fn=180);
|
// revolve_bezier(path, splinesteps=32, $fn=180);
|
||||||
module revolve_bezier(bezier, splinesteps=16) {
|
module revolve_bezier(bezier, splinesteps=16, N=3) {
|
||||||
yrot(90) rotate_extrude(convexity=10) {
|
yrot(90) rotate_extrude(convexity=10) {
|
||||||
xrot(180) zrot(-90) bezier_polygon(bezier, splinesteps);
|
xrot(180) zrot(-90) bezier_polygon(bezier, splinesteps, N);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Takes a bezier path and closes it to the X axis.
|
// Takes a 2D bezier path and closes it to the X axis.
|
||||||
function bezier_close_to_axis(bezier) =
|
function bezier_close_to_axis(bezier, N=3) =
|
||||||
let(bezend = len(bezier)-1)
|
let(
|
||||||
concat(
|
bezend = len(bezier)-1
|
||||||
[ [bezier[0][0], 0], [bezier[0][0], 0], bezier[0] ],
|
) concat(
|
||||||
|
[for (i=[0:N-1]) lerp([bezier[0][0], 0], bezier[0], i/N)],
|
||||||
bezier,
|
bezier,
|
||||||
[ bezier[bezend], [bezier[bezend][0], 0], [bezier[bezend][0], 0] ]
|
[for (i=[1:N]) lerp(bezier[bezend], [bezier[bezend][0], 0], i/N)],
|
||||||
|
[for (i=[1:N]) lerp([bezier[bezend][0], 0], [bezier[0][0], 0], i/N)]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// Takes a bezier curve and closes it with a matching path that is
|
// Takes a bezier curve and closes it with a matching path that is
|
||||||
// lowered by a given amount towards the X axis.
|
// lowered by a given amount towards the X axis.
|
||||||
function bezier_offset(inset, bezier) =
|
function bezier_offset(inset, bezier, N=3) =
|
||||||
let(backbez = reverse([ for (pt = bezier) [pt[0], pt[1]-inset] ]))
|
let(
|
||||||
concat(
|
backbez = reverse([ for (pt = bezier) [pt[0], pt[1]-inset] ]),
|
||||||
|
bezend = len(bezier)-1
|
||||||
|
) concat(
|
||||||
bezier,
|
bezier,
|
||||||
[bezier[len(bezier)-1]],
|
[for (i=[1:N-1]) lerp(bezier[bezend], backbez[0], i/N)],
|
||||||
[backbez[0]],
|
|
||||||
backbez,
|
backbez,
|
||||||
[backbez[len(backbez)-1]],
|
[for (i=[1:N]) lerp(backbez[bezend], bezier[0], i/N)]
|
||||||
[bezier[0]],
|
|
||||||
[bezier[0]]
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
@ -145,8 +153,8 @@ function bezier_offset(inset, bezier) =
|
||||||
// Example:
|
// Example:
|
||||||
// path = [ [0, 10], [33, 10], [66, 40], [100, 40] ];
|
// path = [ [0, 10], [33, 10], [66, 40], [100, 40] ];
|
||||||
// revolve_bezier_solid_to_axis(path, splinesteps=32, $fn=72);
|
// revolve_bezier_solid_to_axis(path, splinesteps=32, $fn=72);
|
||||||
module revolve_bezier_solid_to_axis(bezier, splinesteps=16) {
|
module revolve_bezier_solid_to_axis(bezier, splinesteps=16, N=3) {
|
||||||
revolve_bezier(bezier=bezier_close_to_axis(bezier), splinesteps=splinesteps);
|
revolve_bezier(bezier=bezier_close_to_axis(bezier), splinesteps=splinesteps, N=N);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -157,8 +165,8 @@ module revolve_bezier_solid_to_axis(bezier, splinesteps=16) {
|
||||||
// Example:
|
// Example:
|
||||||
// path = [ [0, 10], [33, 10], [66, 40], [100, 40] ];
|
// path = [ [0, 10], [33, 10], [66, 40], [100, 40] ];
|
||||||
// revolve_bezier_offset_shell(path, offset=1, splinesteps=32, $fn=72);
|
// revolve_bezier_offset_shell(path, offset=1, splinesteps=32, $fn=72);
|
||||||
module revolve_bezier_offset_shell(bezier, offset=1, splinesteps=16) {
|
module revolve_bezier_offset_shell(bezier, offset=1, splinesteps=16, N=3) {
|
||||||
revolve_bezier(bezier=bezier_offset(offset, bezier), splinesteps=splinesteps);
|
revolve_bezier(bezier=bezier_offset(offset, bezier), splinesteps=splinesteps, N=N);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -169,8 +177,8 @@ module revolve_bezier_offset_shell(bezier, offset=1, splinesteps=16) {
|
||||||
// path = [ [0, 0, 0], [33, 33, 33], [66, -33, -33], [100, 0, 0] ];
|
// path = [ [0, 0, 0], [33, 33, 33], [66, -33, -33], [100, 0, 0] ];
|
||||||
// extrude_2d_shapes_along_bezier(path, splinesteps=32)
|
// extrude_2d_shapes_along_bezier(path, splinesteps=32)
|
||||||
// circle(r=10, center=true);
|
// circle(r=10, center=true);
|
||||||
module extrude_2d_shapes_along_bezier(bezier, splinesteps=16) {
|
module extrude_2d_shapes_along_bezier(bezier, splinesteps=16, N=3) {
|
||||||
pointslist = slice(bezier_polyline(bezier, splinesteps), 0, -1);
|
pointslist = slice(bezier_polyline(bezier, splinesteps, N), 0, -1);
|
||||||
ptcount = len(pointslist);
|
ptcount = len(pointslist);
|
||||||
for (i = [0 : ptcount-2]) {
|
for (i = [0 : ptcount-2]) {
|
||||||
pt1 = pointslist[i];
|
pt1 = pointslist[i];
|
||||||
|
@ -218,13 +226,15 @@ module extrude_2d_shapes_along_bezier(bezier, splinesteps=16) {
|
||||||
// path = Array of points of a bezier path, to extrude along.
|
// path = Array of points of a bezier path, to extrude along.
|
||||||
// pathsteps = number of steps to divide each path segment into.
|
// pathsteps = number of steps to divide each path segment into.
|
||||||
// bezsteps = number of steps to divide each bezier segment into.
|
// bezsteps = number of steps to divide each bezier segment into.
|
||||||
|
// bezN = number of points in each extruded bezier segment. Cubic = 3
|
||||||
|
// pathN = number of points in each path bezier segment. Cubic = 3
|
||||||
// Example:
|
// Example:
|
||||||
// bez = [ [-15, 0], [25, -15], [-5, 10], [0, 10], [5, 10], [10, 5], [15, 0], [10, -5], [5, -10], [0, -10], [-5, -10], [-10, -5], [-15, 0] ];
|
// bez = [ [-15, 0], [25, -15], [-5, 10], [0, 10], [5, 10], [10, 5], [15, 0], [10, -5], [5, -10], [0, -10], [-5, -10], [-10, -5], [-15, 0] ];
|
||||||
// path = [ [0, 0, 0], [33, 33, 33], [66, -33, -33], [100, 0, 0] ];
|
// path = [ [0, 0, 0], [33, 33, 33], [66, -33, -33], [100, 0, 0] ];
|
||||||
// extrude_bezier_along_bezier(bez, path, pathsteps=64, bezsteps=32);
|
// extrude_bezier_along_bezier(bez, path, pathsteps=64, bezsteps=32);
|
||||||
module extrude_bezier_along_bezier(bezier, path, pathsteps=16, bezsteps=16) {
|
module extrude_bezier_along_bezier(bezier, path, pathsteps=16, bezsteps=16, bezN=3, pathN=3) {
|
||||||
bez_points = simplify2d_path(bezier_polyline(bezier, bezsteps));
|
bez_points = simplify2d_path(bezier_polyline(bezier, bezsteps, bezN));
|
||||||
path_points = simplify3d_path(path3d(bezier_polyline(path, pathsteps)));
|
path_points = simplify3d_path(path3d(bezier_polyline(path, pathsteps, pathN)));
|
||||||
extrude_2dpath_along_3dpath(bez_points, path_points);
|
extrude_2dpath_along_3dpath(bez_points, path_points);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,10 @@ function quantup(x,y) = ceil(x/y)*y;
|
||||||
function segs(r) = $fn>0?($fn>3?$fn:3):(ceil(max(min(360.0/$fa,abs(r)*2*Cpi()/$fs),5)));
|
function segs(r) = $fn>0?($fn>3?$fn:3):(ceil(max(min(360.0/$fa,abs(r)*2*Cpi()/$fs),5)));
|
||||||
|
|
||||||
|
|
||||||
|
// Interpolate between two values or vectors. 0.0 <= u <= 1.0
|
||||||
|
function lerp(a,b,u) = (b-a)*u + a;
|
||||||
|
|
||||||
|
|
||||||
// Calculate hypotenuse length of 2D triangle.
|
// Calculate hypotenuse length of 2D triangle.
|
||||||
function hypot(x,y) = sqrt(x*x+y*y);
|
function hypot(x,y) = sqrt(x*x+y*y);
|
||||||
|
|
||||||
|
|
|
@ -189,7 +189,7 @@ function points_along_path3d(
|
||||||
// Example:
|
// Example:
|
||||||
// shape = [ [-15, 0], [0, 0], [-5, 10], [0, 10], [5, 10], [10, 5], [15, 0], [10, -5], [5, -10], [0, -10], [-5, -10], [-10, -5], [-15, 0] ];
|
// shape = [ [-15, 0], [0, 0], [-5, 10], [0, 10], [5, 10], [10, 5], [15, 0], [10, -5], [5, -10], [0, -10], [-5, -10], [-10, -5], [-15, 0] ];
|
||||||
// path = [ [0, 0, 0], [100, 33, 33], [200, -33, -33], [300, 0, 0] ];
|
// path = [ [0, 0, 0], [100, 33, 33], [200, -33, -33], [300, 0, 0] ];
|
||||||
// extrude_2dpath_along_3dpath(shape, path, tilt=false);
|
// extrude_2dpath_along_3dpath(shape, path);
|
||||||
module extrude_2dpath_along_3dpath(polyline, path, convexity=10) {
|
module extrude_2dpath_along_3dpath(polyline, path, convexity=10) {
|
||||||
pline_count = len(polyline);
|
pline_count = len(polyline);
|
||||||
path_count = len(path);
|
path_count = len(path);
|
||||||
|
|
Loading…
Reference in a new issue