Skip to content

Commit

Permalink
get_fn() and quant() is already in BOSL2. Fix round_path, add chamfer…
Browse files Browse the repository at this point in the history
…_path, lerp_index, rpath and path_sweep2d_fill
  • Loading branch information
lijon committed Feb 21, 2024
1 parent 32d0b5a commit 65d6c50
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 8 deletions.
56 changes: 51 additions & 5 deletions box.scad
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,62 @@ $box_inside_overlap = 0.0001;

$box_wall = undef;

function quant(val, q) = round(val/q)*q;

function get_fn(r, q=1) = $fn > 0 ? $fn : quant(max(min(360/$fa,r*2*PI/$fs),5),q);

// for any non-zero element b[i], return b[i] else a[i]
function v_replace_nonzero(a,b) =
assert( is_list(a) && is_list(b) && len(a)==len(b), "Incompatible input")
[for (i = [0:1:len(a)-1]) b[i] != 0 ? b[i] : a[i]];

function round_path(path, r, closed=true) = r==0 ? path : offset(offset(path,r,closed=closed),-r,closed=closed);
function round_path(path, r, or, ir, closed=true) =
let(
or = get_radius(r1=or, r=r, dflt=0),
ir = get_radius(r1=ir, r=r, dflt=0),
) or==0 && ir==0 ? path : offset(offset(offset(path,delta=ir,chamfer=true,closed=closed),-or-ir,closed=closed),or,closed=closed);

function chamfer_path(path, r, or, ir, closed=true) =
let(
or = get_radius(r1=or, r=r, dflt=0),
ir = get_radius(r1=ir, r=r, dflt=0),
) or==0 && ir==0 ? path : offset(offset(offset(path,delta=ir,chamfer=true,closed=closed),delta=-or-ir,chamfer=true,closed=closed),delta=or,chamfer=true,closed=closed);

function lerp_index(v,x) = let(i=floor(x), a = v[i], b = v[min(i+1,len(v)-1)], f = x-i) lerp(a,b,f);

// takes a list of [x,y,R] or [x,y,z,R] points and returns a rounded/chamfered path.
// where R is positive for circular and negative for chamfer.
function rpath(points, closed=true) =
let(
path = [for(p = points) slice(p,0,-2)],
r = [for(p = points) last(p)],
) [
for(i = idx(path)) each
let(
rr = r[i],
ra = abs(rr),
pt = select(path,i-1,i+1),
angle = vector_angle(pt)/2,
prev = unit(pt[0]-pt[1]),
next = unit(pt[2]-pt[1])
) rr < 0 ? [pt[1]+prev*ra, pt[1]+next*ra]
: rr > 0 ?
let(
d = ra/tan(angle),
center = ra/sin(angle) * unit(prev+next)+pt[1],
start = pt[1]+prev*d,
end = pt[1]+next*d
) (approx(angle,90) ? [start,end] : arc(max(3,ceil((90-angle)/180*segs(ra))), cp=center, points=[start,end]))
: [path[i]]
];

// like path_sweep2d for closed path, that fills the hole (bottom). for easy creation of boxes from side profile and top path.
module path_sweep2d_fill(profile, path) {
path_sweep2d(profile,path,closed=true) children();

fill = [
for(p=[profile[0],last(profile)])
up(p.y,path3d(offset(path,delta=p.x+0.001,closed=true)))
];
//skin(bot,slices=0);
vnf_polyhedron(vnf_vertex_array(fill,caps=true,col_wrap=true));
}

function vector_name(v) =
assert(is_vector(v))
Expand Down
2 changes: 1 addition & 1 deletion examples/laserbox.scad
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ module toggle_switch(anchor=BOTTOM,spin) {

//cut_inspect(LEFT,ofs=[-21.1,0,0]) // inspect only laser mount
//cut_inspect(BACK)
box_make(print=false, explode=0.1)
box_make(print=true, explode=30.1)
box_shell_base_lid(box_sz,rsides=6,wall_sides=1.6,wall_top=2,base_height=3,rim_height=2,rbot_inside=1,rtop_inside=1)
{
size = $parent_size;
Expand Down
2 changes: 2 additions & 0 deletions examples/snap_fit_test.scad
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ include <jl_scad/utils.scad>

$slop = 0.1;
$fn = $preview?16:48;
$attachable_dump_tree = true;


sz = [30,30,10];

Expand Down
4 changes: 2 additions & 2 deletions parts.scad
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,13 @@ module box_screw_clamp(h=2,od=8,od2,id=3,id2,head_d=6,head_depth=3,idepth=0,gap=
}

function keyhole(d1=3,d2=6,l,r) =
let(r=default(r,d1/2),l=d2,$fn=get_fn(d2/2,4)) // fn must be even by 4 for this to work!
let(r=default(r,d1/2),l=d2,$fn=quant(segs(d2/2),4)) // fn must be even by 4 for this to work!
assert(r<d1)
force_path(round_path(union([
circle(d=d1),
rect([d1,l],anchor=TOP),
move([0,-l],circle(d=d2)),
]),r));
]),-r));

module box_hole(d=1, rounding, chamfer, teardrop=false, teardrop_cap=true, depth=0, anchor=CENTER) {
p = teardrop ? teardrop2d(d=d,cap_h=teardrop_cap==true?d/2:teardrop_cap,spin=$box_half==TOP?180:0) : circle(d=d);
Expand Down

0 comments on commit 65d6c50

Please sign in to comment.