Merge branch 'master' into revarbat_dev

This commit is contained in:
Garth Minette 2021-01-07 19:21:45 -08:00
commit 729baada91
5 changed files with 59 additions and 60 deletions

View file

@ -419,7 +419,7 @@ module joiner_quad(spacing1=undef, spacing2=undef, xspacing=undef, yspacing=unde
// Module: dovetail() // Module: dovetail()
// //
// Usage: // Usage:
// dovetail(l|length, h|height, w|width, slope|angle, taper|back_width, [chamfer], [r|radius], [round], [$slop]) // dovetail(gender, w|width, h|height, slide, [slope|angle], [taper|back_width], [chamfer], [r|radius], [round], [$slop])
// //
// Description: // Description:
// Produces a possibly tapered dovetail joint shape to attach to or subtract from two parts you wish to join together. // Produces a possibly tapered dovetail joint shape to attach to or subtract from two parts you wish to join together.
@ -427,14 +427,16 @@ module joiner_quad(spacing1=undef, spacing2=undef, xspacing=undef, yspacing=unde
// it is fully closed, and then wedges tightly. You can chamfer or round the corners of the dovetail shape for better // it is fully closed, and then wedges tightly. You can chamfer or round the corners of the dovetail shape for better
// printing and assembly, or choose a fully rounded joint that looks more like a puzzle piece. The dovetail appears // printing and assembly, or choose a fully rounded joint that looks more like a puzzle piece. The dovetail appears
// parallel to the Y axis and projecting upwards, so in its default orientation it will slide together with a translation // parallel to the Y axis and projecting upwards, so in its default orientation it will slide together with a translation
// in the positive Y direction. The default anchor for dovetails is BOTTOM; the default orientation depends on the gender, // in the positive Y direction. The gender determines whether the shape is meant to be added to your model or
// with male dovetails oriented UP and female ones DOWN. // differenced, and it also changes the anchor and orientation. The default anchor for dovetails is BOTTOM;
// the default orientation depends on the gender, with male dovetails oriented UP and female ones DOWN.
// //
// Arguments: // Arguments:
// gender = A string, "male" or "female", to specify the gender of the dovetail. // gender = A string, "male" or "female", to specify the gender of the dovetail.
// l / length = Length of the dovetail (amount the joint slides during assembly)
// h / height = Height of the dovetail
// w / width = Width (at the wider, top end) of the dovetail before tapering // w / width = Width (at the wider, top end) of the dovetail before tapering
// h / height = Height of the dovetail (the amount it projects from its base)
// slide = Distance the dovetail slides when you assemble it (length of sliding dovetails, thickness of regular dovetails)
// ---
// slope = slope of the dovetail. Standard woodworking slopes are 4, 6, or 8. Default: 6. // slope = slope of the dovetail. Standard woodworking slopes are 4, 6, or 8. Default: 6.
// angle = angle (in degrees) of the dovetail. Specify only one of slope and angle. // angle = angle (in degrees) of the dovetail. Specify only one of slope and angle.
// taper = taper angle (in degrees). Dovetail gets narrower by this angle. Default: no taper // taper = taper angle (in degrees). Dovetail gets narrower by this angle. Default: no taper
@ -444,68 +446,66 @@ module joiner_quad(spacing1=undef, spacing2=undef, xspacing=undef, yspacing=unde
// round = true to round both corners of the dovetail and give it a puzzle piece look. Default: false. // round = true to round both corners of the dovetail and give it a puzzle piece look. Default: false.
// extra = amount of extra length and base extension added to dovetails for unions and differences. Default: 0.01 // extra = amount of extra length and base extension added to dovetails for unions and differences. Default: 0.01
// Example: Ordinary straight dovetail, male version (sticking up) and female version (below the xy plane) // Example: Ordinary straight dovetail, male version (sticking up) and female version (below the xy plane)
// dovetail("male", l=30, w=15, h=8); // dovetail("male", width=15, height=8, slide=30);
// right(20) dovetail("female", l=30, w=15, h=8); // right(20) dovetail("female", width=15, height=8, slide=30);
// Example: Adding a 6 degree taper (Such a big taper is usually not necessary, but easier to see for the example.) // Example: Adding a 6 degree taper (Such a big taper is usually not necessary, but easier to see for the example.)
// dovetail("male", l=30, w=15, h=8, taper=6); // dovetail("male", w=15, h=8, slide=30, taper=6);
// right(20) dovetail("female", l=30, w=15, h=8, taper=6); // right(20) dovetail("female", 15, 8, 30, taper=6); // Same as above
// Example: A block that can link to itself // Example: A block that can link to itself
// diff("remove") // diff("remove")
// cuboid([50,30,10]){ // cuboid([50,30,10]){
// attach(BACK) dovetail("male", length=10, width=15, height=8); // attach(BACK) dovetail("male", slide=10, width=15, height=8);
// attach(FRONT) dovetail("female", length=10, width=15, height=8,$tags="remove"); // attach(FRONT) dovetail("female", slide=10, width=15, height=8,$tags="remove");
// } // }
// Example: Setting the dovetail angle. This is too extreme to be useful. // Example: Setting the dovetail angle. This is too extreme to be useful.
// diff("remove") // diff("remove")
// cuboid([50,30,10]){ // cuboid([50,30,10]){
// attach(BACK) dovetail("male", length=10, width=15, height=8,angle=30); // attach(BACK) dovetail("male", slide=10, width=15, height=8, angle=30);
// attach(FRONT) dovetail("female", length=10, width=15, height=8,angle=30,$tags="remove"); // attach(FRONT) dovetail("female", slide=10, width=15, height=8, angle=30,$tags="remove");
// } // }
// Example: Adding a chamfer helps printed parts fit together without problems at the corners // Example: Adding a chamfer helps printed parts fit together without problems at the corners
// diff("remove") // diff("remove")
// cuboid([50,30,10]){ // cuboid([50,30,10]){
// attach(BACK) dovetail("male", length=10, width=15, height=8,chamfer=1); // attach(BACK) dovetail("male", slide=10, width=15, height=8, chamfer=1);
// attach(FRONT) dovetail("female", length=10, width=15, height=8,chamfer=1,$tags="remove"); // attach(FRONT) dovetail("female", slide=10, width=15, height=8,chamfer=1,$tags="remove");
// } // }
// Example: Rounding the outside corners is another option // Example: Rounding the outside corners is another option
// diff("remove") // diff("remove")
// cuboid([50,30,10]) { // cuboid([50,30,10]) {
// attach(BACK) dovetail("male", length=10, width=15, height=8, radius=1, $fn=32); // attach(BACK) dovetail("male", slide=10, width=15, height=8, radius=1, $fn=32);
// attach(FRONT, overlap=-0.1) dovetail("female", length=10, width=15, height=8, radius=1, $tags="remove", $fn=32); // attach(FRONT, overlap=-0.1) dovetail("female", slide=10, width=15, height=8, radius=1, $tags="remove", $fn=32);
// } // }
// Example: Or you can make a fully rounded joint // Example: Or you can make a fully rounded joint
// $fn=32; // $fn=32;
// diff("remove") // diff("remove")
// cuboid([50,30,10]){ // cuboid([50,30,10]){
// attach(BACK) dovetail("male", length=10, width=15, height=8,radius=1.5, round=true); // attach(BACK) dovetail("male", slide=10, width=15, height=8, radius=1.5, round=true);
// attach(FRONT,overlap=-0.1) dovetail("female", length=10, width=15, height=8,radius=1.5, round=true, $tags="remove"); // attach(FRONT,overlap=-0.1) dovetail("female", slide=10, width=15, height=8, radius=1.5, round=true, $tags="remove");
// } // }
// Example: With a long joint like this, a taper makes the joint easy to assemble. It will go together easily and wedge tightly if you get the tolerances right. Specifying the taper with `back_width` may be easier than using a taper angle. // Example: With a long joint like this, a taper makes the joint easy to assemble. It will go together easily and wedge tightly if you get the tolerances right. Specifying the taper with `back_width` may be easier than using a taper angle.
// cuboid([50,30,10]) // cuboid([50,30,10])
// attach(TOP) dovetail("male", length=50, width=18, height=4, back_width=15, spin=90); // attach(TOP) dovetail("male", slide=50, width=18, height=4, back_width=15, spin=90);
// fwd(35) // fwd(35)
// diff("remove") // diff("remove")
// cuboid([50,30,10]) // cuboid([50,30,10])
// attach(TOP) dovetail("female", length=50, width=18, height=4, back_width=15, spin=90,$tags="remove"); // attach(TOP) dovetail("female", length=50, width=18, height=4, back_width=15, spin=90, $tags="remove");
// Example: A series of dovetails // Example: A series of dovetails forming a tail board, with the inside of the joint up. A standard wood joint would have a zero taper.
// cuboid([50,30,10]) // cuboid([50,30,10])
// attach(BACK) xcopies(10,5) dovetail("male", length=10, width=7, height=4); // attach(BACK) xcopies(10,5) dovetail("male", slide=10, width=7, taper=4, height=4);
// Example: Mating pin board for a right angle joint. Note that the anchor method and use of `spin` ensures that the joint works even with a taper. // Example: Mating pin board for a half-blind right angle joint, where the joint only shows on the side but not the front. Note that the anchor method and use of `spin` ensures that the joint works even with a taper.
// diff("remove") // diff("remove")
// cuboid([50,30,10]) // cuboid([50,30,10])
// position(TOP+BACK) xcopies(10,5) dovetail("female", length=10, width=7, taper=4, height=4, $tags="remove",anchor=BOTTOM+FRONT,spin=180); // position(TOP+BACK) xcopies(10,5) dovetail("female", slide=10, width=7, taper=4, height=4, $tags="remove",anchor=BOTTOM+FRONT,spin=180);
module dovetail(gender, length, l, width, w, height, h, angle, slope, taper, back_width, chamfer, extra=0.01, r, radius, round=false, anchor=BOTTOM, spin=0, orient) module dovetail(gender, width, height, slide, h, w, angle, slope, taper, back_width, chamfer, extra=0.01, r, radius, round=false, anchor=BOTTOM, spin=0, orient)
{ {
radius = get_radius(r1=radius,r2=r); radius = get_radius(r1=radius,r2=r);
lcount = num_defined([l,length]);
hcount = num_defined([h,height]); hcount = num_defined([h,height]);
wcount = num_defined([w,width]); wcount = num_defined([w,width]);
assert(lcount==1, "Must define exactly one of l and length"); assert(is_def(slide), "Must define slide");
assert(wcount==1, "Must define exactly one of w and width");
assert(hcount==1, "Must define exactly one of h and height"); assert(hcount==1, "Must define exactly one of h and height");
assert(wcount==1, "Must define exactly one of w and width");
h = first_defined([h,height]); h = first_defined([h,height]);
w = first_defined([w,width]); w = first_defined([w,width]);
length = first_defined([l,length]);
orient = is_def(orient) ? orient : orient = is_def(orient) ? orient :
gender == "female" ? DOWN : UP; gender == "female" ? DOWN : UP;
count = num_defined([angle,slope]); count = num_defined([angle,slope]);
@ -522,7 +522,7 @@ module dovetail(gender, length, l, width, w, height, h, angle, slope, taper, bac
back_width = u_add(back_width, extra_slop); back_width = u_add(back_width, extra_slop);
front_offset = is_def(taper) ? -extra * tan(taper) : front_offset = is_def(taper) ? -extra * tan(taper) :
is_def(back_width) ? extra * (back_width-width)/length/2 : 0; is_def(back_width) ? extra * (back_width-width)/slide/2 : 0;
size = is_def(chamfer) && chamfer>0 ? chamfer : size = is_def(chamfer) && chamfer>0 ? chamfer :
is_def(radius) && radius>0 ? radius : 0; is_def(radius) && radius>0 ? radius : 0;
@ -533,7 +533,7 @@ module dovetail(gender, length, l, width, w, height, h, angle, slope, taper, bac
smallend_half = round_corners( smallend_half = round_corners(
move( move(
[0,-length/2-extra,0], [0,-slide/2-extra,0],
p=[ p=[
[0 , 0, height], [0 , 0, height],
[width/2-front_offset , 0, height], [width/2-front_offset , 0, height],
@ -544,13 +544,13 @@ module dovetail(gender, length, l, width, w, height, h, angle, slope, taper, bac
method=type, cut = fullsize, closed=false method=type, cut = fullsize, closed=false
); );
smallend_points = concat(select(smallend_half, 1, -2), [down(extra,p=select(smallend_half, -2))]); smallend_points = concat(select(smallend_half, 1, -2), [down(extra,p=select(smallend_half, -2))]);
offset = is_def(taper) ? -(length+extra) * tan(taper) : offset = is_def(taper) ? -(slide+extra) * tan(taper) :
is_def(back_width) ? (back_width-width) / 2 : 0; is_def(back_width) ? (back_width-width) / 2 : 0;
bigend_points = move([offset,length+2*extra,0], p=smallend_points); bigend_points = move([offset,slide+2*extra,0], p=smallend_points);
adjustment = $overlap * (gender == "male" ? -1 : 1); // Adjustment for default overlap in attach() adjustment = $overlap * (gender == "male" ? -1 : 1); // Adjustment for default overlap in attach()
attachable(anchor,spin,orient, size=[width+2*offset, length, height]) { attachable(anchor,spin,orient, size=[width+2*offset, slide, height]) {
down(height/2+adjustment) { down(height/2+adjustment) {
skin( skin(
[ [
@ -765,8 +765,7 @@ module snap_pin_socket(size, r, radius, l,length, d,diameter,nub_depth, snap, fi
{ {
down(lPin/2) down(lPin/2)
intersection() { intersection() {
if (fixed) cube([3 * (radius + snap), fixed ? radius * sqrt(2) : 3*(radius+snap), 3 * lPin + 3 * radius], center = true);
cube([3 * (radius + snap), radius * sqrt(2), 3 * lPin + 3 * radius], center = true);
union() { union() {
_pin_shaft(radius,lStraight,snap,1,1,nub_depth,pointed); _pin_shaft(radius,lStraight,snap,1,1,nub_depth,pointed);
if (fins) if (fins)

View file

@ -533,7 +533,7 @@ function _offset_region(
difference(_acc, [ difference(_acc, [
offset( offset(
paths[_i].y, paths[_i].y,
r=-r, delta=-delta, chamfer=chamfer, closed=closed, r=u_mul(-1,r), delta=u_mul(-1,delta), chamfer=chamfer, closed=closed,
maxstep=maxstep, check_valid=check_valid, quality=quality, maxstep=maxstep, check_valid=check_valid, quality=quality,
return_faces=return_faces, firstface_index=firstface_index, return_faces=return_faces, firstface_index=firstface_index,
flip_faces=flip_faces flip_faces=flip_faces
@ -547,11 +547,14 @@ function _offset_region(
// Function: offset() // Function: offset()
// // Usage:
// offsetpath = offset(path, [r|delta], [chamfer], [closed], [check_valid], [quality])
// path_faces = offset(path, return_faces=true, [r|delta], [chamfer], [closed], [check_valid], [quality], [firstface_index], [flip_faces])
// Description: // Description:
// Takes an input path and returns a path offset by the specified amount. As with the built-in // Takes an input path and returns a path offset by the specified amount. As with the built-in
// offset() module, you can use `r` to specify rounded offset and `delta` to specify offset with // offset() module, you can use `r` to specify rounded offset and `delta` to specify offset with
// corners. Positive offsets shift the path to the left (relative to the direction of the path). // corners. If you used `delta` you can set `chamfer` to true to get chamfers.
// Positive offsets shift the path to the left (relative to the direction of the path).
// . // .
// When offsets shrink the path, segments cross and become invalid. By default `offset()` checks // When offsets shrink the path, segments cross and become invalid. By default `offset()` checks
// for this situation. To test validity the code checks that segments have distance larger than (r // for this situation. To test validity the code checks that segments have distance larger than (r
@ -570,6 +573,7 @@ function _offset_region(
// value is a list: [offset_path, face_list]. // value is a list: [offset_path, face_list].
// Arguments: // Arguments:
// path = the path to process. A list of 2d points. // path = the path to process. A list of 2d points.
// ---
// r = offset radius. Distance to offset. Will round over corners. // r = offset radius. Distance to offset. Will round over corners.
// delta = offset distance. Distance to offset with pointed corners. // delta = offset distance. Distance to offset with pointed corners.
// chamfer = chamfer corners when you specify `delta`. Default: false // chamfer = chamfer corners when you specify `delta`. Default: false
@ -643,7 +647,7 @@ function offset(
maxstep=0.1, closed=false, check_valid=true, maxstep=0.1, closed=false, check_valid=true,
quality=1, return_faces=false, firstface_index=0, quality=1, return_faces=false, firstface_index=0,
flip_faces=false flip_faces=false
) = ) =
is_region(path)? ( is_region(path)? (
assert(!return_faces, "return_faces not supported for regions.") assert(!return_faces, "return_faces not supported for regions.")
let( let(
@ -687,23 +691,19 @@ function offset(
(len(sharpcorners)==2 && !closed) || (len(sharpcorners)==2 && !closed) ||
all_defined(select(sharpcorners,closed?0:1,-1)) all_defined(select(sharpcorners,closed?0:1,-1))
) )
assert(parallelcheck, "Path turns back on itself (180 deg turn)") assert(parallelcheck, "Path contains sequential parallel segments (either 180 deg turn or 0 deg turn")
let( let(
// This is a boolean array that indicates whether a corner is an outside or inside corner // This is a boolean array that indicates whether a corner is an outside or inside corner
// For outside corners, the newcorner is an extension (angle 0), for inside corners, it turns backward // For outside corners, the newcorner is an extension (angle 0), for inside corners, it turns backward
// If either side turns back it is an inside corner---must check both. // If either side turns back it is an inside corner---must check both.
// Outside corners can get rounded (if r is specified and there is space to round them) // Outside corners can get rounded (if r is specified and there is space to round them)
outsidecorner = [ outsidecorner = len(sharpcorners)==2 ? [false,false]
for(i=[0:len(goodsegs)-1]) let( :
prevseg=select(goodsegs,i-1) [for(i=[0:len(goodsegs)-1])
) ( let(prevseg=select(goodsegs,i-1))
(goodsegs[i][1]-goodsegs[i][0]) * (goodsegs[i][1]-goodsegs[i][0]) * (goodsegs[i][0]-sharpcorners[i]) > 0
(goodsegs[i][0]-sharpcorners[i]) > 0 && (prevseg[1]-prevseg[0]) * (sharpcorners[i]-prevseg[1]) > 0
) && ( ],
(prevseg[1]-prevseg[0]) *
(sharpcorners[i]-prevseg[1]) > 0
)
],
steps = is_def(delta) ? [] : [ steps = is_def(delta) ? [] : [
for(i=[0:len(goodsegs)-1]) for(i=[0:len(goodsegs)-1])
r==0 ? 0 : r==0 ? 0 :

View file

@ -37,7 +37,7 @@ function _parse_screw_name(name) =
let(val=str_num(type)) let(val=str_num(type))
val == floor(val) && val>=0 && val<=12 ? str("#",type) : val val == floor(val) && val>=0 && val<=12 ? str("#",type) : val
) )
["english", diam, thread, 25.4*length]; ["english", diam, thread, u_mul(25.4,length)];
// drive can be "hex", "phillips", "slot", "torx", or "none" // drive can be "hex", "phillips", "slot", "torx", or "none"
@ -165,7 +165,7 @@ function screw_info(name, head, thread="coarse", drive, drive_size=undef, oversi
is_def(type[3]) ? ["length",type[3]] : [], is_def(type[3]) ? ["length",type[3]] : [],
is_def(drive_info[1]) ? ["drive_size", drive_info[1]] : [], is_def(drive_info[1]) ? ["drive_size", drive_info[1]] : [],
["diameter", oversize+struct_val(screwdata,"diameter"), ["diameter", oversize+struct_val(screwdata,"diameter"),
"head_size", oversize+struct_val(screwdata,"head_size")] "head_size", u_add(oversize,struct_val(screwdata,"head_size"))]
) )
) )
struct_set(screwdata, over_ride); struct_set(screwdata, over_ride);
@ -307,7 +307,7 @@ function _screw_info_english(diam, threadcount, head, thread, drive) =
[2, [ 3, 1.5, undef, undef, undef]], [2, [ 3, 1.5, undef, undef, undef]],
], ],
entry = struct_val(UTS_socket, diam), entry = struct_val(UTS_socket, diam),
hexdepth = first_defined([entry[3], diam/2]), hexdepth = is_def(entry[3]) ? entry[3] : if_def(diam) ? diam/2 : undef,
drive_size = drive=="hex" ? [["drive_size",inch*entry[1]], ["drive_depth",inch*hexdepth]] : drive_size = drive=="hex" ? [["drive_size",inch*entry[1]], ["drive_depth",inch*hexdepth]] :
drive=="torx" ? [["drive_size",entry[2]],["drive_depth",inch*entry[4]]] : [] drive=="torx" ? [["drive_size",entry[2]],["drive_depth",inch*entry[4]]] : []
) )

View file

@ -808,8 +808,8 @@ module cyl(
vang = atan2(l, r1-r2)/2; vang = atan2(l, r1-r2)/2;
chang1 = 90-first_defined([chamfang1, chamfang, vang]); chang1 = 90-first_defined([chamfang1, chamfang, vang]);
chang2 = 90-first_defined([chamfang2, chamfang, 90-vang]); chang2 = 90-first_defined([chamfang2, chamfang, 90-vang]);
cham1 = first_defined([chamfer1, chamfer]) * (from_end? 1 : tan(chang1)); cham1 = u_mul(first_defined([chamfer1, chamfer]) , (from_end? 1 : tan(chang1)));
cham2 = first_defined([chamfer2, chamfer]) * (from_end? 1 : tan(chang2)); cham2 = u_mul(first_defined([chamfer2, chamfer]) , (from_end? 1 : tan(chang2)));
fil1 = first_defined([rounding1, rounding]); fil1 = first_defined([rounding1, rounding]);
fil2 = first_defined([rounding2, rounding]); fil2 = first_defined([rounding2, rounding]);
if (chamfer != undef) { if (chamfer != undef) {

View file

@ -6,7 +6,7 @@
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
BOSL_VERSION = [2,0,518]; BOSL_VERSION = [2,0,519];
// Section: BOSL Library Version Functions // Section: BOSL Library Version Functions