mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-01 09:49:45 +00:00
Added attachment support to all modules, and bug fixed rounded_prism
(problem introduced by error checking in det2), and fixed broken example in rounding.
This commit is contained in:
parent
2e2465ca4e
commit
2ff93f34cd
2 changed files with 208 additions and 141 deletions
168
rounding.scad
168
rounding.scad
|
@ -458,10 +458,10 @@ function smooth_path(path, tangents, size, relsize, splinesteps=10, uniform=fals
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Module: offset_sweep()
|
// Function&Module: offset_sweep()
|
||||||
//
|
//
|
||||||
// Description:
|
// Description:
|
||||||
// Takes a 2d path as input and extrudes it upwards and/or downward. Each layer in the extrusion is produced using `offset()` to expand or shrink the previous layer.
|
// Takes a 2d path as input and extrudes it upwards and/or downward. Each layer in the extrusion is produced using `offset()` to expand or shrink the previous layer. When invoked as a function returns a VNF; when invoked as a module produces geometry.
|
||||||
// You can specify a sequence of offsets values, or you can use several built-in offset profiles that are designed to provide end treatments such as roundovers.
|
// You can specify a sequence of offsets values, or you can use several built-in offset profiles that are designed to provide end treatments such as roundovers.
|
||||||
// The path is shifted by `offset()` multiple times in sequence
|
// The path is shifted by `offset()` multiple times in sequence
|
||||||
// to produce the final shape (not multiple shifts from one parent), so coarse definition of the input path will degrade
|
// to produce the final shape (not multiple shifts from one parent), so coarse definition of the input path will degrade
|
||||||
|
@ -543,8 +543,12 @@ function smooth_path(path, tangents, size, relsize, splinesteps=10, uniform=fals
|
||||||
// angle = default angle for chamfers. Default: 45
|
// angle = default angle for chamfers. Default: 45
|
||||||
// joint = default joint value for smooth roundover.
|
// joint = default joint value for smooth roundover.
|
||||||
// k = default curvature parameter value for "smooth" roundover
|
// k = default curvature parameter value for "smooth" roundover
|
||||||
// convexity = convexity setting for use with polyhedron. Default: 10
|
// convexity = convexity setting for use with polyhedron. (module only) Default: 10
|
||||||
//
|
// anchor = Translate so anchor point is at the origin. (module only) Default: "origin"
|
||||||
|
// spin = Rotate this many degrees around Z axis after anchor. (module only) Default: 0
|
||||||
|
// orient = Vector to rotate top towards after spin (module only)
|
||||||
|
// extent = use extent method for computing anchors. (module only) Default: false
|
||||||
|
// cp = set centerpoint for anchor computation. (module only) Default: object centroid
|
||||||
// Example: Rounding a star shaped prism with postive radius values
|
// Example: Rounding a star shaped prism with postive radius values
|
||||||
// star = star(5, r=22, ir=13);
|
// star = star(5, r=22, ir=13);
|
||||||
// rounded_star = round_corners(star, cut=flatten(repeat([.5,0],5)), $fn=24);
|
// rounded_star = round_corners(star, cut=flatten(repeat([.5,0],5)), $fn=24);
|
||||||
|
@ -650,19 +654,12 @@ function smooth_path(path, tangents, size, relsize, splinesteps=10, uniform=fals
|
||||||
// up(1)
|
// up(1)
|
||||||
// offset_sweep(offset(rhex,r=-1), height=9.5, bottom=os_circle(r=2), top=os_teardrop(r=-4));
|
// offset_sweep(offset(rhex,r=-1), height=9.5, bottom=os_circle(r=2), top=os_teardrop(r=-4));
|
||||||
// }
|
// }
|
||||||
module offset_sweep(
|
|
||||||
path, height, h, l,
|
|
||||||
top=[], bottom=[],
|
|
||||||
offset="round", r=0, steps=16,
|
|
||||||
quality=1, check_valid=true,
|
|
||||||
offset_maxstep=1, extra=0,
|
|
||||||
cut=undef, chamfer_width=undef, chamfer_height=undef,
|
|
||||||
joint=undef, k=0.75, angle=45,
|
|
||||||
convexity=10
|
|
||||||
) {
|
|
||||||
// This function does the actual work of repeatedly calling offset() and concatenating the resulting face and vertex lists to produce
|
// This function does the actual work of repeatedly calling offset() and concatenating the resulting face and vertex lists to produce
|
||||||
// the inputs for the polyhedron module.
|
// the inputs for the polyhedron module.
|
||||||
function make_polyhedron(path,offsets, offset_type, flip_faces, quality, check_valid, maxstep, offsetind=0, vertexcount=0, vertices=[], faces=[] )=
|
function _make_offset_polyhedron(path,offsets, offset_type, flip_faces, quality, check_valid, maxstep, offsetind=0,
|
||||||
|
vertexcount=0, vertices=[], faces=[] )=
|
||||||
offsetind==len(offsets)? (
|
offsetind==len(offsets)? (
|
||||||
let(
|
let(
|
||||||
bottom = list_range(n=len(path),s=vertexcount),
|
bottom = list_range(n=len(path),s=vertexcount),
|
||||||
|
@ -675,7 +672,6 @@ module offset_sweep(
|
||||||
r = offset_type=="round"? this_offset : undef,
|
r = offset_type=="round"? this_offset : undef,
|
||||||
do_chamfer = offset_type == "chamfer"
|
do_chamfer = offset_type == "chamfer"
|
||||||
)
|
)
|
||||||
assert(num_defined([r,delta])==1,"Must set `offset` to \"round\" or \"delta")
|
|
||||||
let(
|
let(
|
||||||
vertices_faces = offset(
|
vertices_faces = offset(
|
||||||
path, r=r, delta=delta, chamfer = do_chamfer, closed=true,
|
path, r=r, delta=delta, chamfer = do_chamfer, closed=true,
|
||||||
|
@ -685,7 +681,7 @@ module offset_sweep(
|
||||||
flip_faces=flip_faces
|
flip_faces=flip_faces
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
make_polyhedron(
|
_make_offset_polyhedron(
|
||||||
vertices_faces[0], offsets, offset_type,
|
vertices_faces[0], offsets, offset_type,
|
||||||
flip_faces, quality, check_valid, maxstep,
|
flip_faces, quality, check_valid, maxstep,
|
||||||
offsetind+1, vertexcount+len(path),
|
offsetind+1, vertexcount+len(path),
|
||||||
|
@ -698,6 +694,16 @@ module offset_sweep(
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
function offset_sweep(
|
||||||
|
path, height, h, l,
|
||||||
|
top=[], bottom=[],
|
||||||
|
offset="round", r=0, steps=16,
|
||||||
|
quality=1, check_valid=true,
|
||||||
|
offset_maxstep=1, extra=0,
|
||||||
|
cut=undef, chamfer_width=undef, chamfer_height=undef,
|
||||||
|
joint=undef, k=0.75, angle=45
|
||||||
|
) =
|
||||||
|
let(
|
||||||
argspec = [
|
argspec = [
|
||||||
["r",r],
|
["r",r],
|
||||||
["extra",extra],
|
["extra",extra],
|
||||||
|
@ -714,54 +720,52 @@ module offset_sweep(
|
||||||
["joint",joint],
|
["joint",joint],
|
||||||
["k", k],
|
["k", k],
|
||||||
["points", []],
|
["points", []],
|
||||||
];
|
],
|
||||||
|
path = check_and_fix_path(path, [2], closed=true),
|
||||||
|
clockwise = polygon_is_clockwise(path),
|
||||||
|
|
||||||
path = check_and_fix_path(path, [2], closed=true);
|
top = struct_set(argspec, top, grow=false),
|
||||||
clockwise = polygon_is_clockwise(path);
|
bottom = struct_set(argspec, bottom, grow=false),
|
||||||
|
|
||||||
top = struct_set(argspec, top, grow=false);
|
// This code does not work. It hits the error in _make_offset_polyhedron from offset being wrong
|
||||||
bottom = struct_set(argspec, bottom, grow=false);
|
// before this code executes. Had to move the test into _make_offset_polyhedron, which is ugly since it's in the loop
|
||||||
|
offsetsok = in_list(struct_val(top, "offset"),["round","delta"])
|
||||||
|
&& in_list(struct_val(bottom, "offset"),["round","delta"])
|
||||||
|
)
|
||||||
|
assert(offsetsok,"Offsets must be one of \"round\" or \"delta\"")
|
||||||
|
let(
|
||||||
|
offsets_bot = _rounding_offsets(bottom, -1),
|
||||||
|
offsets_top = _rounding_offsets(top, 1),
|
||||||
|
dummy = offset == "chamfer" && (len(offsets_bot)>5 || len(offsets_top)>5)
|
||||||
|
? echo("WARNING: You have selected offset=\"chamfer\", which leads to exponential growth in the vertex count and requested more than 5 layers. This can be slow or run out of recursion depth.")
|
||||||
|
: 0,
|
||||||
|
|
||||||
// This code does not work. It hits the error in make_polyhedron from offset being wrong
|
|
||||||
// before this code executes. Had to move the test into make_polyhedron, which is ugly since it's in the loop
|
|
||||||
//offsetsok = in_list(struct_val(top, "offset"),["round","delta"]) &&
|
|
||||||
// in_list(struct_val(bottom, "offset"),["round","delta"]);
|
|
||||||
//assert(offsetsok,"Offsets must be one of \"round\" or \"delta\"");
|
|
||||||
|
|
||||||
|
|
||||||
offsets_bot = _rounding_offsets(bottom, -1);
|
|
||||||
offsets_top = _rounding_offsets(top, 1);
|
|
||||||
|
|
||||||
if (offset == "chamfer" && (len(offsets_bot)>5 || len(offsets_top)>5)) {
|
|
||||||
echo("WARNING: You have selected offset=\"chamfer\", which leads to exponential growth in the vertex count and requested many layers. This can be slow or run out of recursion depth.");
|
|
||||||
}
|
|
||||||
// "Extra" height enlarges the result beyond the requested height, so subtract it
|
// "Extra" height enlarges the result beyond the requested height, so subtract it
|
||||||
bottom_height = len(offsets_bot)==0 ? 0 : abs(select(offsets_bot,-1)[1]) - struct_val(bottom,"extra");
|
bottom_height = len(offsets_bot)==0 ? 0 : abs(select(offsets_bot,-1)[1]) - struct_val(bottom,"extra"),
|
||||||
top_height = len(offsets_top)==0 ? 0 : abs(select(offsets_top,-1)[1]) - struct_val(top,"extra");
|
top_height = len(offsets_top)==0 ? 0 : abs(select(offsets_top,-1)[1]) - struct_val(top,"extra"),
|
||||||
|
|
||||||
height = get_height(l=l,h=h,height=height,dflt=bottom_height+top_height);
|
height = get_height(l=l,h=h,height=height,dflt=bottom_height+top_height),
|
||||||
assert(height>=0, "Height must be nonnegative");
|
middle = height-bottom_height-top_height
|
||||||
|
)
|
||||||
middle = height-bottom_height-top_height;
|
assert(height>=0, "Height must be nonnegative")
|
||||||
assert(
|
assert(middle>=0, str("Specified end treatments (bottom height = ",bottom_height,
|
||||||
middle>=0, str(
|
|
||||||
"Specified end treatments (bottom height = ",bottom_height,
|
|
||||||
" top_height = ",top_height,") are too large for extrusion height (",height,")"
|
" top_height = ",top_height,") are too large for extrusion height (",height,")"
|
||||||
)
|
)
|
||||||
);
|
)
|
||||||
initial_vertices_bot = path3d(path);
|
let(
|
||||||
|
initial_vertices_bot = path3d(path),
|
||||||
|
|
||||||
vertices_faces_bot = make_polyhedron(
|
vertices_faces_bot = _make_offset_polyhedron(
|
||||||
path, offsets_bot, struct_val(bottom,"offset"), clockwise,
|
path, offsets_bot, struct_val(bottom,"offset"), clockwise,
|
||||||
struct_val(bottom,"quality"),
|
struct_val(bottom,"quality"),
|
||||||
struct_val(bottom,"check_valid"),
|
struct_val(bottom,"check_valid"),
|
||||||
struct_val(bottom,"offset_maxstep"),
|
struct_val(bottom,"offset_maxstep"),
|
||||||
vertices=initial_vertices_bot
|
vertices=initial_vertices_bot
|
||||||
);
|
),
|
||||||
|
|
||||||
top_start_ind = len(vertices_faces_bot[0]);
|
top_start_ind = len(vertices_faces_bot[0]),
|
||||||
initial_vertices_top = zip(path, repeat(middle,len(path)));
|
initial_vertices_top = zip(path, repeat(middle,len(path))),
|
||||||
vertices_faces_top = make_polyhedron(
|
vertices_faces_top = _make_offset_polyhedron(
|
||||||
path, move(p=offsets_top,[0,middle]),
|
path, move(p=offsets_top,[0,middle]),
|
||||||
struct_val(top,"offset"), !clockwise,
|
struct_val(top,"offset"), !clockwise,
|
||||||
struct_val(top,"quality"),
|
struct_val(top,"quality"),
|
||||||
|
@ -769,21 +773,40 @@ module offset_sweep(
|
||||||
struct_val(top,"offset_maxstep"),
|
struct_val(top,"offset_maxstep"),
|
||||||
vertexcount=top_start_ind,
|
vertexcount=top_start_ind,
|
||||||
vertices=initial_vertices_top
|
vertices=initial_vertices_top
|
||||||
);
|
),
|
||||||
middle_faces = middle==0 ? [] : [
|
middle_faces = middle==0 ? [] : [
|
||||||
for(i=[0:len(path)-1]) let(
|
for(i=[0:len(path)-1]) let(
|
||||||
oneface=[i, (i+1)%len(path), top_start_ind+(i+1)%len(path), top_start_ind+i]
|
oneface=[i, (i+1)%len(path), top_start_ind+(i+1)%len(path), top_start_ind+i]
|
||||||
) !clockwise ? reverse(oneface) : oneface
|
) !clockwise ? reverse(oneface) : oneface
|
||||||
];
|
]
|
||||||
up(bottom_height) {
|
)
|
||||||
polyhedron(
|
[up(bottom_height, concat(vertices_faces_bot[0],vertices_faces_top[0])), // Vertices
|
||||||
concat(vertices_faces_bot[0],vertices_faces_top[0]),
|
concat(vertices_faces_bot[1], vertices_faces_top[1], middle_faces)]; // Faces
|
||||||
faces=concat(vertices_faces_bot[1], vertices_faces_top[1], middle_faces),
|
|
||||||
convexity=convexity
|
|
||||||
);
|
module offset_sweep(path, height, h, l,
|
||||||
|
top=[], bottom=[],
|
||||||
|
offset="round", r=0, steps=16,
|
||||||
|
quality=1, check_valid=true,
|
||||||
|
offset_maxstep=1, extra=0,
|
||||||
|
cut=undef, chamfer_width=undef, chamfer_height=undef,
|
||||||
|
joint=undef, k=0.75, angle=45,
|
||||||
|
convexity=10,anchor="origin",cp,
|
||||||
|
spin=0, orient=UP, extent=false)
|
||||||
|
{
|
||||||
|
vnf = offset_sweep(path=path, height=height, h=h, l=l, top=top, bottom=bottom, offset=offset, r=0, steps=steps,
|
||||||
|
quality=quality, check_valid=true, offset_maxstep=1, extra=0, cut=cut, chamfer_width=chamfer_width,
|
||||||
|
chamfer_height=chamfer_height, joint=joint, k=k, angle=angle);
|
||||||
|
|
||||||
|
attachable(anchor=anchor, spin=spin, orient=orient, vnf=vnf, extent=extent, cp=is_def(cp) ? cp : vnf_centroid(vnf))
|
||||||
|
{
|
||||||
|
vnf_polyhedron(vnf,convexity=convexity);
|
||||||
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function os_circle(r,cut,extra,check_valid, quality,steps, offset_maxstep, offset) =
|
function os_circle(r,cut,extra,check_valid, quality,steps, offset_maxstep, offset) =
|
||||||
assert(num_defined([r,cut])==1, "Must define exactly one of `r` and `cut`")
|
assert(num_defined([r,cut])==1, "Must define exactly one of `r` and `cut`")
|
||||||
_remove_undefined_vals([
|
_remove_undefined_vals([
|
||||||
|
@ -924,7 +947,6 @@ function os_profile(points, extra,check_valid, quality, offset_maxstep, offset)
|
||||||
// joint = default joint value for smooth roundover.
|
// joint = default joint value for smooth roundover.
|
||||||
// k = default curvature parameter value for "smooth" roundover
|
// k = default curvature parameter value for "smooth" roundover
|
||||||
// convexity = convexity setting for use with polyhedron. Default: 10
|
// convexity = convexity setting for use with polyhedron. Default: 10
|
||||||
//
|
|
||||||
// Example: Chamfered elliptical prism. If you stretch a chamfered cylinder the chamfer will be uneven.
|
// Example: Chamfered elliptical prism. If you stretch a chamfered cylinder the chamfer will be uneven.
|
||||||
// convex_offset_extrude(bottom = os_chamfer(height=-2), top=os_chamfer(height=1), height=7)
|
// convex_offset_extrude(bottom = os_chamfer(height=-2), top=os_chamfer(height=1), height=7)
|
||||||
// xscale(4)circle(r=6,$fn=64);
|
// xscale(4)circle(r=6,$fn=64);
|
||||||
|
@ -1364,8 +1386,6 @@ module offset_stroke(path, width=1, rounded=true, start, end, check_valid=true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function _rp_compute_patches(top, bot, rtop, rsides, ktop, ksides, concave) =
|
function _rp_compute_patches(top, bot, rtop, rsides, ktop, ksides, concave) =
|
||||||
let(
|
let(
|
||||||
N = len(top),
|
N = len(top),
|
||||||
|
@ -1395,8 +1415,8 @@ function _rp_compute_patches(top, bot, rtop, rsides, ktop, ksides, concave) =
|
||||||
let(
|
let(
|
||||||
prev_corner = prev_offset + abs(rtop_in)*in_prev,
|
prev_corner = prev_offset + abs(rtop_in)*in_prev,
|
||||||
next_corner = next_offset + abs(rtop_in)*in_next,
|
next_corner = next_offset + abs(rtop_in)*in_next,
|
||||||
prev_degenerate = is_undef(ray_intersection([far_corner, far_corner+prev], [prev_offset, prev_offset+in_prev])),
|
prev_degenerate = is_undef(ray_intersection(path2d([far_corner, far_corner+prev]), path2d([prev_offset, prev_offset+in_prev]))),
|
||||||
next_degenerate = is_undef(ray_intersection([far_corner, far_corner+next], [next_offset, next_offset+in_next]))
|
next_degenerate = is_undef(ray_intersection(path2d([far_corner, far_corner+next]), path2d([next_offset, next_offset+in_next])))
|
||||||
)
|
)
|
||||||
[ prev_degenerate ? far_corner : prev_corner,
|
[ prev_degenerate ? far_corner : prev_corner,
|
||||||
far_corner,
|
far_corner,
|
||||||
|
@ -1452,6 +1472,11 @@ function _rp_compute_patches(top, bot, rtop, rsides, ktop, ksides, concave) =
|
||||||
// splinesteps = number of segments to use for curved patches. Default: 16
|
// splinesteps = number of segments to use for curved patches. Default: 16
|
||||||
// debug = turn on debug mode which displays illegal polyhedra and shows the bezier corner patches for troubleshooting purposes. Default: False
|
// debug = turn on debug mode which displays illegal polyhedra and shows the bezier corner patches for troubleshooting purposes. Default: False
|
||||||
// convexity = convexity parameter for polyhedron(), only for module version. Default: 10
|
// convexity = convexity parameter for polyhedron(), only for module version. Default: 10
|
||||||
|
// anchor = Translate so anchor point is at the origin. (module only) Default: "origin"
|
||||||
|
// spin = Rotate this many degrees around Z axis after anchor. (module only) Default: 0
|
||||||
|
// orient = Vector to rotate top towards after spin (module only)
|
||||||
|
// extent = use extent method for computing anchors. (module only) Default: false
|
||||||
|
// cp = set centerpoint for anchor computation. (module only) Default: object centroid
|
||||||
// Example: Uniformly rounded pentagonal prism
|
// Example: Uniformly rounded pentagonal prism
|
||||||
// rounded_prism(pentagon(3), height=3, joint_top=0.5, joint_bot=0.5, joint_sides=0.5);
|
// rounded_prism(pentagon(3), height=3, joint_top=0.5, joint_bot=0.5, joint_sides=0.5);
|
||||||
// Example: Maximum possible rounding.
|
// Example: Maximum possible rounding.
|
||||||
|
@ -1500,15 +1525,21 @@ function _rp_compute_patches(top, bot, rtop, rsides, ktop, ksides, concave) =
|
||||||
// rounded_prism(apply(yrot(95),path3d(hexagon(3))), apply(yrot(95), path3d(hexagon(3),3)), joint_top=2, joint_bot=1, joint_sides=1);
|
// rounded_prism(apply(yrot(95),path3d(hexagon(3))), apply(yrot(95), path3d(hexagon(3),3)), joint_top=2, joint_bot=1, joint_sides=1);
|
||||||
|
|
||||||
module rounded_prism(bottom, top, joint_bot, joint_top, joint_sides, k_bot, k_top, k_sides,
|
module rounded_prism(bottom, top, joint_bot, joint_top, joint_sides, k_bot, k_top, k_sides,
|
||||||
k=0.5, splinesteps=16, h, length, l, height, convexity=10, debug=false)
|
k=0.5, splinesteps=16, h, length, l, height, convexity=10, debug=false,
|
||||||
|
anchor="origin",cp,spin=0, orient=UP, extent=false)
|
||||||
{
|
{
|
||||||
result = rounded_prism(bottom=bottom, top=top, joint_bot=joint_bot, joint_top=joint_top, joint_sides=joint_sides,
|
result = rounded_prism(bottom=bottom, top=top, joint_bot=joint_bot, joint_top=joint_top, joint_sides=joint_sides,
|
||||||
k_bot=k_bot, k_top=k_top, k_sides=k_sides, k=k, splinesteps=splinesteps, h=h, length=length, height=height, l=l,debug=debug);
|
k_bot=k_bot, k_top=k_top, k_sides=k_sides, k=k, splinesteps=splinesteps, h=h, length=length, height=height, l=l,debug=debug);
|
||||||
|
vnf = debug ? result[1] : result;
|
||||||
|
attachable(anchor=anchor, spin=spin, orient=orient, vnf=vnf, extent=extent, cp=is_def(cp) ? cp : vnf_centroid(vnf))
|
||||||
|
{
|
||||||
if (debug){
|
if (debug){
|
||||||
vnf_polyhedron(result[1], convexity=convexity);
|
vnf_polyhedron(vnf, convexity=convexity);
|
||||||
trace_bezier_patches(result[0], showcps=true, splinesteps=splinesteps, $fn=16, showdots=false, showpatch=false);
|
trace_bezier_patches(result[0], showcps=true, splinesteps=splinesteps, $fn=16, showdots=false, showpatch=false);
|
||||||
}
|
}
|
||||||
else vnf_polyhedron(result,convexity=convexity);
|
else vnf_polyhedron(vnf,convexity=convexity);
|
||||||
|
children();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1880,7 +1911,7 @@ function _circle_mask(r) =
|
||||||
// $fn=128;
|
// $fn=128;
|
||||||
// difference(){
|
// difference(){
|
||||||
// tube(or=r, wall=2, h=45);
|
// tube(or=r, wall=2, h=45);
|
||||||
// bent_cutout_mask(r-1, 2.1, apply(back(15),subdivide_path(round_corners(star(n=7,ir=5,or=10), cut=flatten(repeat([0.5,0],7))),14*15,closed=true)));
|
// bent_cutout_mask(r-1, 2.1, apply(back(15),subdivide_path(round_corners(star(n=7,ir=5,or=10), cut=flatten(repeat([0.5,0],7)),$fn=32),14*15,closed=true)));
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// Example(2D): Cutting a slot in a cylinder is tricky if you want rounded corners at the top. This slot profile has slightly angled top edges to blend into the top edge of the cylinder.
|
// Example(2D): Cutting a slot in a cylinder is tricky if you want rounded corners at the top. This slot profile has slightly angled top edges to blend into the top edge of the cylinder.
|
||||||
|
@ -1944,6 +1975,7 @@ function _circle_mask(r) =
|
||||||
|
|
||||||
module bent_cutout_mask(r, thickness, path, convexity=10)
|
module bent_cutout_mask(r, thickness, path, convexity=10)
|
||||||
{
|
{
|
||||||
|
no_children($children);
|
||||||
assert(is_path(path,2),"Input path must be a 2d path")
|
assert(is_path(path,2),"Input path must be a 2d path")
|
||||||
assert(r-thickness>0, "Thickness too large for radius");
|
assert(r-thickness>0, "Thickness too large for radius");
|
||||||
assert(thickness>0, "Thickness must be positive");
|
assert(thickness>0, "Thickness must be positive");
|
||||||
|
|
59
skin.scad
59
skin.scad
|
@ -16,7 +16,8 @@ include <vnf.scad>
|
||||||
|
|
||||||
// Function&Module: skin()
|
// Function&Module: skin()
|
||||||
// Usage: As module:
|
// Usage: As module:
|
||||||
// skin(profiles, [slices], [refine], [method], [sampling], [caps], [closed], [z]);
|
// skin(profiles, [slices], [refine], [method], [sampling], [caps], [closed], [z], [convexity],
|
||||||
|
// [anchor],[cp],[spin],[orient],[extent]);
|
||||||
// Usage: As function:
|
// Usage: As function:
|
||||||
// vnf = skin(profiles, [slices], [refine], [method], [sampling], [caps], [closed], [z]);
|
// vnf = skin(profiles, [slices], [refine], [method], [sampling], [caps], [closed], [z]);
|
||||||
// Description:
|
// Description:
|
||||||
|
@ -117,6 +118,12 @@ include <vnf.scad>
|
||||||
// caps = true to create endcap faces when closed is false. Can be a length 2 boolean array. Default is true if closed is false.
|
// caps = true to create endcap faces when closed is false. Can be a length 2 boolean array. Default is true if closed is false.
|
||||||
// method = method for connecting profiles, one of "distance", "tangent", "direct" or "reindex". Default: "direct".
|
// method = method for connecting profiles, one of "distance", "tangent", "direct" or "reindex". Default: "direct".
|
||||||
// z = array of height values for each profile if the profiles are 2d
|
// z = array of height values for each profile if the profiles are 2d
|
||||||
|
// convexity = convexity setting for use with polyhedron. (module only) Default: 10
|
||||||
|
// anchor = Translate so anchor point is at the origin. (module only) Default: "origin"
|
||||||
|
// spin = Rotate this many degrees around Z axis after anchor. (module only) Default: 0
|
||||||
|
// orient = Vector to rotate top towards after spin (module only)
|
||||||
|
// extent = use extent method for computing anchors. (module only) Default: false
|
||||||
|
// cp = set centerpoint for anchor computation. (module only) Default: object centroid
|
||||||
// Example:
|
// Example:
|
||||||
// skin([octagon(4), circle($fn=70,r=2)], z=[0,3], slices=10);
|
// skin([octagon(4), circle($fn=70,r=2)], z=[0,3], slices=10);
|
||||||
// Example: Rotating the pentagon place the zero index at different locations, giving a twist
|
// Example: Rotating the pentagon place the zero index at different locations, giving a twist
|
||||||
|
@ -315,11 +322,15 @@ include <vnf.scad>
|
||||||
// stroke(zrot(30, p=yscale(0.5, p=circle(d=120))),width=10,closed=true);
|
// stroke(zrot(30, p=yscale(0.5, p=circle(d=120))),width=10,closed=true);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
module skin(profiles, slices, refine=1, method="direct", sampling, caps, closed=false, z, convexity=10,
|
||||||
|
anchor="origin",cp,spin=0, orient=UP, extent=false)
|
||||||
module skin(profiles, slices, refine=1, method="direct", sampling, caps, closed=false, z, convexity=10)
|
|
||||||
{
|
{
|
||||||
vnf_polyhedron(skin(profiles, slices, refine, method, sampling, caps, closed, z), convexity=convexity);
|
vnf = skin(profiles, slices, refine, method, sampling, caps, closed, z);
|
||||||
|
attachable(anchor=anchor, spin=spin, orient=orient, vnf=vnf, extent=extent, cp=is_def(cp) ? cp : vnf_centroid(vnf))
|
||||||
|
{
|
||||||
|
vnf_polyhedron(vnf,convexity=convexity);
|
||||||
|
children();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -803,6 +814,12 @@ function associate_vertices(polygons, split, curpoly=0) =
|
||||||
// transformations = list of 4x4 matrices to apply
|
// transformations = list of 4x4 matrices to apply
|
||||||
// closed = set to true to form a closed (torus) model. Default: false
|
// closed = set to true to form a closed (torus) model. Default: false
|
||||||
// caps = true to create endcap faces when closed is false. Can be a singe boolean to specify endcaps at both ends, or a length 2 boolean array. Default is true if closed is false.
|
// caps = true to create endcap faces when closed is false. Can be a singe boolean to specify endcaps at both ends, or a length 2 boolean array. Default is true if closed is false.
|
||||||
|
// convexity = convexity setting for use with polyhedron. (module only) Default: 10
|
||||||
|
// anchor = Translate so anchor point is at the origin. (module only) Default: "origin"
|
||||||
|
// spin = Rotate this many degrees around Z axis after anchor. (module only) Default: 0
|
||||||
|
// orient = Vector to rotate top towards after spin (module only)
|
||||||
|
// extent = use extent method for computing anchors. (module only) Default: false
|
||||||
|
// cp = set centerpoint for anchor computation. (module only) Default: object centroid
|
||||||
// Example: This is the "sweep-drop" example from list-comprehension-demos.
|
// Example: This is the "sweep-drop" example from list-comprehension-demos.
|
||||||
// function drop(t) = 100 * 0.5 * (1 - cos(180 * t)) * sin(180 * t) + 1;
|
// function drop(t) = 100 * 0.5 * (1 - cos(180 * t)) * sin(180 * t) + 1;
|
||||||
// function path(t) = [0, 0, 80 + 80 * cos(180 * t)];
|
// function path(t) = [0, 0, 80 + 80 * cos(180 * t)];
|
||||||
|
@ -839,8 +856,15 @@ function sweep(shape, transformations, closed=false, caps) =
|
||||||
assert(!closed || !caps, "Cannot make closed shape with caps")
|
assert(!closed || !caps, "Cannot make closed shape with caps")
|
||||||
_skin_core([for(i=[0:len(transformations)-(closed?0:1)]) apply(transformations[i%len(transformations)],path3d(shape))],caps=fullcaps);
|
_skin_core([for(i=[0:len(transformations)-(closed?0:1)]) apply(transformations[i%len(transformations)],path3d(shape))],caps=fullcaps);
|
||||||
|
|
||||||
module sweep(shape, transformations, closed=false, caps, convexity=10) {
|
module sweep(shape, transformations, closed=false, caps, convexity=10,
|
||||||
vnf_polyhedron(sweep(shape, transformations, closed, caps), convexity=convexity);
|
anchor="origin",cp,spin=0, orient=UP, extent=false)
|
||||||
|
{
|
||||||
|
vnf = sweep(shape, transformations, closed, caps);
|
||||||
|
attachable(anchor=anchor, spin=spin, orient=orient, vnf=vnf, extent=extent, cp=is_def(cp) ? cp : vnf_centroid(vnf))
|
||||||
|
{
|
||||||
|
vnf_polyhedron(vnf,convexity=convexity);
|
||||||
|
children();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -906,8 +930,13 @@ module sweep(shape, transformations, closed=false, caps, convexity=10) {
|
||||||
// tangent = a list of tangent vectors in case you need more accuracy (particularly at the end points of your curve)
|
// tangent = a list of tangent vectors in case you need more accuracy (particularly at the end points of your curve)
|
||||||
// relaxed = set to true with the "manual" method to relax the orthogonality requirement of cross sections to the path tangent. Default: false
|
// relaxed = set to true with the "manual" method to relax the orthogonality requirement of cross sections to the path tangent. Default: false
|
||||||
// caps = Can be a boolean or vector of two booleans. Set to false to disable caps at the two ends. Default: true
|
// caps = Can be a boolean or vector of two booleans. Set to false to disable caps at the two ends. Default: true
|
||||||
// convexity = convexity parameter for polyhedron(). Only accepted by the module version. Default: 10
|
|
||||||
// transforms = set to true to return transforms instead of a VNF. These transforms can be manipulated and passed to sweep(). Default: false.
|
// transforms = set to true to return transforms instead of a VNF. These transforms can be manipulated and passed to sweep(). Default: false.
|
||||||
|
// convexity = convexity parameter for polyhedron(). Only accepted by the module version. Default: 10
|
||||||
|
// anchor = Translate so anchor point is at the origin. (module only) Default: "origin"
|
||||||
|
// spin = Rotate this many degrees around Z axis after anchor. (module only) Default: 0
|
||||||
|
// orient = Vector to rotate top towards after spin (module only)
|
||||||
|
// extent = use extent method for computing anchors. (module only) Default: false
|
||||||
|
// cp = set centerpoint for anchor computation. (module only) Default: object centroid
|
||||||
//
|
//
|
||||||
// Example(2D): We'll use this shape in several examples
|
// Example(2D): We'll use this shape in several examples
|
||||||
// ushape = [[-10, 0],[-10, 10],[ -7, 10],[ -7, 2],[ 7, 2],[ 7, 7],[ 10, 7],[ 10, 0]];
|
// ushape = [[-10, 0],[-10, 10],[ -7, 10],[ -7, 2],[ 7, 2],[ 7, 7],[ 10, 7],[ 10, 0]];
|
||||||
|
@ -1121,13 +1150,19 @@ module sweep(shape, transformations, closed=false, caps, convexity=10) {
|
||||||
// outside = [for(i=[0:len(trans)-1]) trans[i]*scale(lerp(1,1.5,i/(len(trans)-1)))];
|
// outside = [for(i=[0:len(trans)-1]) trans[i]*scale(lerp(1,1.5,i/(len(trans)-1)))];
|
||||||
// inside = [for(i=[len(trans)-1:-1:0]) trans[i]*scale(lerp(1.1,1.4,i/(len(trans)-1)))];
|
// inside = [for(i=[len(trans)-1:-1:0]) trans[i]*scale(lerp(1.1,1.4,i/(len(trans)-1)))];
|
||||||
// sweep(shape, concat(outside,inside),closed=true);
|
// sweep(shape, concat(outside,inside),closed=true);
|
||||||
|
|
||||||
module path_sweep(shape, path, method="incremental", normal, closed=false, twist=0, twist_by_length=true,
|
module path_sweep(shape, path, method="incremental", normal, closed=false, twist=0, twist_by_length=true,
|
||||||
symmetry=1, last_normal, tangent, relaxed=false, caps, convexity=10)
|
symmetry=1, last_normal, tangent, relaxed=false, caps, convexity=10,
|
||||||
|
anchor="origin",cp,spin=0, orient=UP, extent=false)
|
||||||
{
|
{
|
||||||
vnf_polyhedron(path_sweep(shape, path, method, normal, closed, twist, twist_by_length,
|
vnf = path_sweep(shape, path, method, normal, closed, twist, twist_by_length,
|
||||||
symmetry, last_normal, tangent, relaxed, caps), convexity=convexity);
|
symmetry, last_normal, tangent, relaxed, caps);
|
||||||
|
attachable(anchor=anchor, spin=spin, orient=orient, vnf=vnf, extent=extent, cp=is_def(cp) ? cp : vnf_centroid(vnf))
|
||||||
|
{
|
||||||
|
vnf_polyhedron(vnf,convexity=convexity);
|
||||||
|
children();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function path_sweep(shape, path, method="incremental", normal, closed=false, twist=0, twist_by_length=true,
|
function path_sweep(shape, path, method="incremental", normal, closed=false, twist=0, twist_by_length=true,
|
||||||
symmetry=1, last_normal, tangent, relaxed=false, caps, transforms=false) =
|
symmetry=1, last_normal, tangent, relaxed=false, caps, transforms=false) =
|
||||||
|
|
Loading…
Reference in a new issue