This commit is contained in:
Garth Minette 2021-06-28 18:04:27 -07:00
parent 11b4151f74
commit 0fea590d0f

View file

@ -10,21 +10,20 @@
// Section: Partitioning // Section: Partitioning
_partition_cutpaths = [ function _partition_subpath(type) =
["flat", [[0,0],[1,0]]], type=="flat"? [[0,0],[1,0]] :
["sawtooth", [[0,-0.5], [0.5,0.5], [1,-0.5]]], type=="sawtooth"? [[0,-0.5], [0.5,0.5], [1,-0.5]] :
["sinewave", [for (a=[0:5:360]) [a/360,sin(a)/2]]], type=="sinewave"? [for (a=[0:5:360]) [a/360,sin(a)/2]] :
["comb", let(dx=0.5*sin(2)) [[0,0],[0+dx,0.5],[0.5-dx,0.5],[0.5+dx,-0.5],[1-dx,-0.5],[1,0]]], type=="comb"? let(dx=0.5*sin(2)) [[0,0],[0+dx,0.5],[0.5-dx,0.5],[0.5+dx,-0.5],[1-dx,-0.5],[1,0]] :
["finger", let(dx=0.5*sin(20)) [[0,0],[0+dx,0.5],[0.5-dx,0.5],[0.5+dx,-0.5],[1-dx,-0.5],[1,0]]], type=="finger"? let(dx=0.5*sin(20)) [[0,0],[0+dx,0.5],[0.5-dx,0.5],[0.5+dx,-0.5],[1-dx,-0.5],[1,0]] :
["dovetail", [[0,-0.5], [0.3,-0.5], [0.2,0.5], [0.8,0.5], [0.7,-0.5], [1,-0.5]]], type=="dovetail"? [[0,-0.5], [0.3,-0.5], [0.2,0.5], [0.8,0.5], [0.7,-0.5], [1,-0.5]] :
["hammerhead", [[0,-0.5], [0.35,-0.5], [0.35,0], [0.15,0], [0.15,0.5], [0.85,0.5], [0.85,0], [0.65,0], [0.65,-0.5],[1,-0.5]]], type=="hammerhead"? [[0,-0.5], [0.35,-0.5], [0.35,0], [0.15,0], [0.15,0.5], [0.85,0.5], [0.85,0], [0.65,0], [0.65,-0.5],[1,-0.5]] :
["jigsaw", concat( type=="jigsaw"? concat(
arc(N=6, r=5/16, cp=[0,-3/16], start=270, angle=125), arc(r=5/16, cp=[0,-3/16], start=270, angle=125),
arc(N=12, r=5/16, cp=[1/2,3/16], start=215, angle=-250), arc(r=5/16, cp=[1/2,3/16], start=215, angle=-250),
arc(N=6, r=5/16, cp=[1,-3/16], start=145, angle=125) arc(r=5/16, cp=[1,-3/16], start=145, angle=125)
) ) :
], assert(false, str("Unsupported cutpath type: ", type));
];
function _partition_cutpath(l, h, cutsize, cutpath, gap) = function _partition_cutpath(l, h, cutsize, cutpath, gap) =
@ -35,24 +34,26 @@ function _partition_cutpath(l, h, cutsize, cutpath, gap) =
assert(is_finite(cutsize) || is_vector(cutsize,2)) assert(is_finite(cutsize) || is_vector(cutsize,2))
assert(is_string(cutpath) || is_path(cutpath,2)), assert(is_string(cutpath) || is_path(cutpath,2)),
cutsize = is_vector(cutsize)? cutsize : [cutsize*2, cutsize], cutsize = is_vector(cutsize)? cutsize : [cutsize*2, cutsize],
cutpath = is_path(cutpath)? cutpath : ( cutpath = is_path(cutpath)? cutpath :
let(idx = search([cutpath], _partition_cutpaths)) _partition_subpath(cutpath),
idx==[[]]? assert(in_list(cutpath,_partition_cutpaths,idx=0)) :
_partition_cutpaths[idx.x][1]
),
reps = ceil(l/(cutsize.x+gap)), reps = ceil(l/(cutsize.x+gap)),
cplen = (cutsize.x+gap) * reps, cplen = (cutsize.x+gap) * reps,
path = deduplicate(concat( path = deduplicate(concat(
[[-l/2, cutpath[0].y*cutsize.y]], [[-l/2, cutpath[0].y*cutsize.y]],
[for (i=[0:1:reps-1], pt=cutpath) v_mul(pt,cutsize)+[i*(cutsize.x+gap)+gap/2-cplen/2,0]], [for (i=[0:1:reps-1], pt=cutpath) v_mul(pt,cutsize)+[i*(cutsize.x+gap)+gap/2-cplen/2,0]],
[[ l/2, cutpath[len(cutpath)-1].y*cutsize.y]] [[ l/2, cutpath[len(cutpath)-1].y*cutsize.y]]
)) )),
) path; stidxs = [for (i = idx(path)) if (path[i].x < -l/2) i],
enidxs = [for (i = idx(path)) if (path[i].x > +l/2) i],
stidx = stidxs? last(stidxs) : 0,
enidx = enidxs? enidxs[0] : -1,
trunc = select(path, stidx, enidx)
) trunc;
// Module: partition_mask() // Module: partition_mask()
// Usage: // Usage:
// partition_mask(l, w, h, [cutsize], [cutpath], [gap], [inverse], [spin], [orient]); // partition_mask(l, w, h, [cutsize], [cutpath], [gap], [inverse], [spin], [orient],);
// Description: // Description:
// Creates a mask that you can use to difference or intersect with an object to remove half of it, leaving behind a side designed to allow assembly of the sub-parts. // Creates a mask that you can use to difference or intersect with an object to remove half of it, leaving behind a side designed to allow assembly of the sub-parts.
// Arguments: // Arguments:
@ -65,6 +66,7 @@ function _partition_cutpath(l, h, cutsize, cutpath, gap) =
// inverse = If true, create a cutpath that is meant to mate to a non-inverted cutpath. // inverse = If true, create a cutpath that is meant to mate to a non-inverted cutpath.
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#spin). Default: `0` // spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#orient). Default: `UP` // orient = Vector to rotate top towards. See [orient](attachments.scad#orient). Default: `UP`
// $slop = The amount to shrink the mask by, to correct for printer-specific fitting.
// Examples: // Examples:
// partition_mask(w=50, gap=0, cutpath="jigsaw"); // partition_mask(w=50, gap=0, cutpath="jigsaw");
// partition_mask(w=50, gap=30, cutpath="jigsaw"); // partition_mask(w=50, gap=30, cutpath="jigsaw");
@ -79,17 +81,22 @@ function _partition_cutpath(l, h, cutsize, cutpath, gap) =
// partition_mask(w=20, cutpath="dovetail"); // partition_mask(w=20, cutpath="dovetail");
// partition_mask(w=20, cutpath="hammerhead"); // partition_mask(w=20, cutpath="hammerhead");
// partition_mask(w=20, cutpath="jigsaw"); // partition_mask(w=20, cutpath="jigsaw");
module partition_mask(l=100, w=100, h=100, cutsize=10, cutpath=undef, gap=0, inverse=false, spin=0, orient=UP) module partition_mask(l=100, w=100, h=100, cutsize=10, cutpath="jigsaw", gap=0, inverse=false, anchor=CENTER, spin=0, orient=UP)
{ {
cutsize = is_vector(cutsize)? point2d(cutsize) : [cutsize*2, cutsize]; cutsize = is_vector(cutsize)? point2d(cutsize) : [cutsize*2, cutsize];
path = _partition_cutpath(l, h, cutsize, cutpath, gap); path = _partition_cutpath(l, h, cutsize, cutpath, gap);
fullpath = concat(path, [[l/2,w*(inverse?-1:1)], [-l/2,w*(inverse?-1:1)]]); midpath = select(path,1,-2);
rot(from=UP,to=orient) { sizepath = concat([path[0]+[-$slop,0]], midpath, [last(path)+[$slop,0]], [[+(l/2+$slop), (w+$slop)*(inverse?-1:1)], [-(l/2+$slop), (w+$slop)*(inverse?-1:1)]]);
rotate(spin) { bnds = pointlist_bounds(sizepath);
linear_extrude(height=h, convexity=10) { fullpath = concat(path, [[last(path).x, w*(inverse?-1:1)], [path[0].x, w*(inverse?-1:1)]]);
attachable(anchor,spin,orient, size=point3d(bnds[1]-bnds[0],h)) {
linear_extrude(height=h, center=true, convexity=10) {
intersection() {
offset(delta=-$slop) polygon(fullpath); offset(delta=-$slop) polygon(fullpath);
square([l, w*2], center=true);
} }
} }
children();
} }
} }
@ -104,10 +111,11 @@ module partition_mask(l=100, w=100, h=100, cutsize=10, cutpath=undef, gap=0, inv
// w = The width of the part to be masked, back from the cut plane. // w = The width of the part to be masked, back from the cut plane.
// h = The height of the part to be masked. // h = The height of the part to be masked.
// cutsize = The width of the cut pattern to be used. // cutsize = The width of the cut pattern to be used.
// cutpath = The cutpath to use. Standard named paths are "flat", "sawtooth", "sinewave", "comb", "finger", "dovetail", "hammerhead", and "jigsaw". Alternatively, you can give a cutpath as a 2D path, where X is between 0 and 1, and Y is between -0.5 and 0.5. // cutpath = The cutpath to use. Standard named paths are "flat", "sawtooth", "sinewave", "comb", "finger", "dovetail", "hammerhead", and "jigsaw". Alternatively, you can give a cutpath as a 2D path, where X is between 0 and 1, and Y is between -0.5 and 0.5. Default: "jigsaw"
// gap = Empty gaps between cutpath iterations. Default: 0 // gap = Empty gaps between cutpath iterations. Default: 0
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#spin). Default: `0` // spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#orient). Default: `UP` // orient = Vector to rotate top towards. See [orient](attachments.scad#orient). Default: `UP`
// $slop = The width of the cut mask, to correct for printer-specific fitting. Min: 0.1.
// Examples: // Examples:
// partition_cut_mask(gap=0, cutpath="dovetail"); // partition_cut_mask(gap=0, cutpath="dovetail");
// partition_cut_mask(gap=30, cutpath="dovetail"); // partition_cut_mask(gap=30, cutpath="dovetail");
@ -121,15 +129,13 @@ module partition_mask(l=100, w=100, h=100, cutsize=10, cutpath=undef, gap=0, inv
// partition_cut_mask(cutpath="dovetail"); // partition_cut_mask(cutpath="dovetail");
// partition_cut_mask(cutpath="hammerhead"); // partition_cut_mask(cutpath="hammerhead");
// partition_cut_mask(cutpath="jigsaw"); // partition_cut_mask(cutpath="jigsaw");
module partition_cut_mask(l=100, h=100, cutsize=10, cutpath=undef, gap=0, spin=0, orient=UP) module partition_cut_mask(l=100, h=100, cutsize=10, cutpath="jigsaw", gap=0, anchor=CENTER, spin=0, orient=UP)
{ {
cutsize = is_vector(cutsize)? cutsize : [cutsize*2, cutsize]; cutsize = is_vector(cutsize)? cutsize : [cutsize*2, cutsize];
path = _partition_cutpath(l, h, cutsize, cutpath, gap); path = _partition_cutpath(l, h, cutsize, cutpath, gap);
rot(from=UP,to=orient) { attachable(anchor,spin,orient, size=[l,cutsize.y,h]) {
rotate(spin) { linear_extrude(height=h, center=true, convexity=10) {
linear_extrude(height=h, convexity=10) { stroke(path, width=max(0.1, $slop*2));
stroke(path, width=max(0.1, $slop*2));
}
} }
} }
} }
@ -160,7 +166,7 @@ module partition_cut_mask(l=100, h=100, cutsize=10, cutpath=undef, gap=0, spin=0
// partition(spread=12, cutpath="dovetail") cylinder(h=50, d=80, center=false); // partition(spread=12, cutpath="dovetail") cylinder(h=50, d=80, center=false);
// partition(spread=12, cutpath="hammerhead") cylinder(h=50, d=80, center=false); // partition(spread=12, cutpath="hammerhead") cylinder(h=50, d=80, center=false);
// partition(cutpath="jigsaw") cylinder(h=50, d=80, center=false); // partition(cutpath="jigsaw") cylinder(h=50, d=80, center=false);
module partition(size=100, spread=10, cutsize=10, cutpath=undef, gap=0, spin=0) module partition(size=100, spread=10, cutsize=10, cutpath="jigsaw", gap=0, spin=0)
{ {
size = is_vector(size)? size : [size,size,size]; size = is_vector(size)? size : [size,size,size];
cutsize = is_vector(cutsize)? cutsize : [cutsize*2, cutsize]; cutsize = is_vector(cutsize)? cutsize : [cutsize*2, cutsize];