From b12565f85cfa1606aa8fd83e66f99ded65f337b3 Mon Sep 17 00:00:00 2001
From: Adrian Mariano <avm4@cornell.edu>
Date: Wed, 6 Jan 2021 16:45:24 -0500
Subject: [PATCH 1/6] Fixed bug with snap_pin_socket, tweaked dovetail docs.
 Fixed offset bugs, one affecting regions and one affecting paths of length2.

---
 joiners.scad | 17 +++++++++--------
 regions.scad | 32 ++++++++++++++++----------------
 2 files changed, 25 insertions(+), 24 deletions(-)

diff --git a/joiners.scad b/joiners.scad
index a3cc636..3e18ae0 100644
--- a/joiners.scad
+++ b/joiners.scad
@@ -419,7 +419,7 @@ module joiner_quad(spacing1=undef, spacing2=undef, xspacing=undef, yspacing=unde
 // Module: dovetail()
 //
 // Usage:
-//   dovetail(l|length, h|height, w|width, slope|angle, taper|back_width, [chamfer], [r|radius], [round], [$slop])
+//   dovetail(gender, l|length, h|height, w|width, [slope|angle], [taper|back_width], [chamfer], [r|radius], [round], [$slop])
 //
 // Description:
 //   Produces a possibly tapered dovetail joint shape to attach to or subtract from two parts you wish to join together.
@@ -427,11 +427,13 @@ 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
 //   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
-//   in the positive Y direction.  The default anchor for dovetails is BOTTOM; the default orientation depends on the gender,
-//   with male dovetails oriented UP and female ones DOWN.  
+//   in the positive Y direction.  The gender determines whether the shape is meant to be added to your model or
+//   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:
-//   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
@@ -487,9 +489,9 @@ module joiner_quad(spacing1=undef, spacing2=undef, xspacing=undef, yspacing=unde
 //     diff("remove")
 //       cuboid([50,30,10])
 //         attach(TOP) dovetail("female", length=50, width=18, height=4, back_width=15, spin=90,$tags="remove");
-// Example: A series of dovtails
+// Example: A series of dovtails forming a tail board, with the inside of the joint up.  A standard wood joint would have a zero taper. 
 //   cuboid([50,30,10])
-//     attach(BACK) xcopies(10,5) dovetail("male", length=10, width=7, height=4);
+//     attach(BACK) xcopies(10,5) dovetail("male", length=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.
 //   diff("remove")
 //     cuboid([50,30,10])
@@ -765,8 +767,7 @@ module snap_pin_socket(size, r, radius, l,length, d,diameter,nub_depth, snap, fi
   {  
   down(lPin/2)
     intersection() {
-      if (fixed) 
-        cube([3 * (radius + snap), radius * sqrt(2), 3 * lPin + 3 * radius], center = true);
+      cube([3 * (radius + snap), fixed ? radius * sqrt(2) : 3*(radius+snap), 3 * lPin + 3 * radius], center = true);        
       union() {
         _pin_shaft(radius,lStraight,snap,1,1,nub_depth,pointed);
         if (fins) 
diff --git a/regions.scad b/regions.scad
index 7c4d773..f2e97e0 100644
--- a/regions.scad
+++ b/regions.scad
@@ -533,7 +533,7 @@ function _offset_region(
             difference(_acc, [
                 offset(
                     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,
                     return_faces=return_faces, firstface_index=firstface_index,
                     flip_faces=flip_faces
@@ -547,11 +547,14 @@ function _offset_region(
 
 
 // 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:
 //   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
-//   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
 //   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].
 // Arguments:
 //   path = the path to process.  A list of 2d points.
+//   ---
 //   r = offset radius.  Distance to offset.  Will round over corners.
 //   delta = offset distance.  Distance to offset with pointed corners.
 //   chamfer = chamfer corners when you specify `delta`.  Default: false
@@ -643,7 +647,7 @@ function offset(
     maxstep=0.1, closed=false, check_valid=true,
     quality=1, return_faces=false, firstface_index=0,
     flip_faces=false
-) =
+) = echo(path=path)
     is_region(path)? (
         assert(!return_faces, "return_faces not supported for regions.")
         let(
@@ -687,23 +691,19 @@ function offset(
             (len(sharpcorners)==2 && !closed) ||
             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(
         // 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
         // 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)
-        outsidecorner = [
-            for(i=[0:len(goodsegs)-1]) let(
-                prevseg=select(goodsegs,i-1)
-            ) (
-                (goodsegs[i][1]-goodsegs[i][0]) *
-                (goodsegs[i][0]-sharpcorners[i]) > 0
-            ) && (
-                (prevseg[1]-prevseg[0]) *
-                (sharpcorners[i]-prevseg[1]) > 0
-            )
-        ],
+        outsidecorner = len(sharpcorners)==2 ? [false,false]
+           :
+            [for(i=[0:len(goodsegs)-1])
+                 let(prevseg=select(goodsegs,i-1))
+                (goodsegs[i][1]-goodsegs[i][0]) * (goodsegs[i][0]-sharpcorners[i]) > 0
+                 && (prevseg[1]-prevseg[0]) * (sharpcorners[i]-prevseg[1]) > 0
+            ],
         steps = is_def(delta) ? [] : [
             for(i=[0:len(goodsegs)-1])
                         r==0 ? 0 :

From 00bbc3efe6997bc4b5c057ffc72a7185f4b00f21 Mon Sep 17 00:00:00 2001
From: Adrian Mariano <avm4@cornell.edu>
Date: Wed, 6 Jan 2021 19:59:31 -0500
Subject: [PATCH 2/6] removed echo

---
 regions.scad | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/regions.scad b/regions.scad
index f2e97e0..25a0bd7 100644
--- a/regions.scad
+++ b/regions.scad
@@ -647,7 +647,7 @@ function offset(
     maxstep=0.1, closed=false, check_valid=true,
     quality=1, return_faces=false, firstface_index=0,
     flip_faces=false
-) = echo(path=path)
+) = 
     is_region(path)? (
         assert(!return_faces, "return_faces not supported for regions.")
         let(

From 30d960bf6d695547e73662a3fc058891938a0a7a Mon Sep 17 00:00:00 2001
From: Adrian Mariano <avm4@cornell.edu>
Date: Wed, 6 Jan 2021 20:45:11 -0500
Subject: [PATCH 3/6] Changed dovetail interface to use slide, length and width
 and support more positional args.

---
 joiners.scad | 80 +++++++++++++++++++++++++---------------------------
 1 file changed, 39 insertions(+), 41 deletions(-)

diff --git a/joiners.scad b/joiners.scad
index 3e18ae0..1dafea7 100644
--- a/joiners.scad
+++ b/joiners.scad
@@ -419,7 +419,7 @@ module joiner_quad(spacing1=undef, spacing2=undef, xspacing=undef, yspacing=unde
 // Module: dovetail()
 //
 // Usage:
-//   dovetail(gender, l|length, h|height, w|width, [slope|angle], [taper|back_width], [chamfer], [r|radius], [round], [$slop])
+//   dovetail(gender, l|length, w|width, slide, [slope|angle], [taper|back_width], [chamfer], [r|radius], [round], [$slop])
 //
 // Description:
 //   Produces a possibly tapered dovetail joint shape to attach to or subtract from two parts you wish to join together.
@@ -432,11 +432,11 @@ module joiner_quad(spacing1=undef, spacing2=undef, xspacing=undef, yspacing=unde
 //   the default orientation depends on the gender, with male dovetails oriented UP and female ones DOWN.  
 //
 // Arguments:
-//   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
+//   gender = A string, "male" or "female", to specify the gender of the dovetail.
+//   l / length = Length of the dovetail (the amount it projects from its base)
 //   w / width = Width (at the wider, top end) of the dovetail before tapering
+//   slide = Distance the dovetail slides when you assemble it
+//   ---
 //   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.
 //   taper = taper angle (in degrees). Dovetail gets narrower by this angle.  Default: no taper
@@ -446,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.  
 //   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)
-//   dovetail("male", l=30, w=15, h=8);
-//   right(20) dovetail("female", l=30, w=15, h=8);
+//   dovetail("male", length=8, width=15, slide=30);
+//   right(20) dovetail("female", length=8, width=15, slide=30);
 // 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);
-//   right(20) dovetail("female", l=30, w=15, h=8, taper=6);
+//   dovetail("male", l=8, w=15, slide=30, taper=6);
+//   right(20) dovetail("female", 8, 15, 30, taper=6);  // Same as above
 // Example: A block that can link to itself
 //   diff("remove")
 //     cuboid([50,30,10]){
-//       attach(BACK) dovetail("male", length=10, width=15, height=8);
-//       attach(FRONT) dovetail("female", length=10, width=15, height=8,$tags="remove");
+//       attach(BACK) dovetail("male", slide=10, width=15, length=8);
+//       attach(FRONT) dovetail("female", slide=10, width=15, length=8,$tags="remove");
 //     }
 // Example: Setting the dovetail angle.  This is too extreme to be useful.  
 //   diff("remove")
 //     cuboid([50,30,10]){
-//       attach(BACK) dovetail("male", length=10, width=15, height=8,angle=30);
-//       attach(FRONT) dovetail("female", length=10, width=15, height=8,angle=30,$tags="remove");
+//       attach(BACK) dovetail("male", slide=10, width=15, length=8, angle=30);
+//       attach(FRONT) dovetail("female", slide=10, width=15, length=8, angle=30,$tags="remove");
 //     }
 // Example: Adding a chamfer helps printed parts fit together without problems at the corners
 //   diff("remove")
 //     cuboid([50,30,10]){
-//       attach(BACK) dovetail("male", length=10, width=15, height=8,chamfer=1);
-//       attach(FRONT) dovetail("female", length=10, width=15, height=8,chamfer=1,$tags="remove");
+//       attach(BACK) dovetail("male", slide=10, width=15, length=8, chamfer=1);
+//       attach(FRONT) dovetail("female", slide=10, width=15, length=8,chamfer=1,$tags="remove");
 //     }
 // Example: Rounding the outside corners is another option
 //   diff("remove")
 //   cuboid([50,30,10]) {
-//       attach(BACK)  dovetail("male", length=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(BACK)  dovetail("male", slide=10, width=15, length=8, radius=1, $fn=32);
+//       attach(FRONT, overlap=-0.1) dovetail("female", slide=10, width=15, length=8, radius=1, $tags="remove", $fn=32);
 //   }
 // Example: Or you can make a fully rounded joint
 //   $fn=32;
 //   diff("remove")
 //   cuboid([50,30,10]){
-//       attach(BACK) dovetail("male", length=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(BACK) dovetail("male", slide=10, width=15, length=8, radius=1.5, round=true);
+//       attach(FRONT,overlap=-0.1) dovetail("female", slide=10, width=15, length=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.  Note that "length" refers to the amount the joint projects from its base, which is a little counter-intuitive when the joint has a very long slide like these sliding dovetails.  
 //   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, length=4, back_width=15, spin=90);
 //   fwd(35)
 //     diff("remove")
 //       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", slide=50, width=18, length=4, back_width=15, spin=90,$tags="remove");
 // Example: A series of dovtails forming a tail board, with the inside of the joint up.  A standard wood joint would have a zero taper. 
 //   cuboid([50,30,10])
-//     attach(BACK) xcopies(10,5) dovetail("male", length=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.
+//     attach(BACK) xcopies(10,5) dovetail("male", slide=10, width=7, taper=4, length=4);
+// 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")
 //     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);
-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)
+//       position(TOP+BACK) xcopies(10,5) dovetail("female", slide=10, width=7, taper=4, length=4, $tags="remove",anchor=BOTTOM+FRONT,spin=180);
+module dovetail(gender, length, width, slide, l, 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);
     lcount = num_defined([l,length]);
-    hcount = num_defined([h,height]);
     wcount = num_defined([w,width]);
+    assert(is_def(slide), "Must define slide");
     assert(lcount==1, "Must define exactly one of l and length");
     assert(wcount==1, "Must define exactly one of w and width");
-    assert(hcount==1, "Must define exactly one of h and height");
-    h = first_defined([h,height]);
+    l = first_defined([l,length]);
     w = first_defined([w,width]);
-    length = first_defined([l,length]);
     orient = is_def(orient) ? orient :
         gender == "female" ? DOWN : UP;
     count = num_defined([angle,slope]);
@@ -520,11 +518,11 @@ module dovetail(gender, length, l, width, w, height, h, angle, slope, taper, bac
         is_def(angle) ? 1/tan(angle) :  6;
     extra_slop = gender == "female" ? 2*$slop : 0;
     width = w + extra_slop;
-    height = h + extra_slop;
+    length = l + extra_slop;
     back_width = u_add(back_width, extra_slop);
 
     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 :
         is_def(radius) && radius>0 ? radius : 0;
@@ -535,25 +533,25 @@ module dovetail(gender, length, l, width, w, height, h, angle, slope, taper, bac
 
     smallend_half = round_corners(
         move(
-            [0,-length/2-extra,0],
+            [0,-slide/2-extra,0],
             p=[
-                [0                     , 0, height],
-                [width/2-front_offset  , 0, height],
-                [width/2 - height/slope - front_offset, 0, 0 ],
-                [width/2 - front_offset + height, 0, 0]
+                [0                     , 0, length],
+                [width/2-front_offset  , 0, length],
+                [width/2 - length/slope - front_offset, 0, 0 ],
+                [width/2 - front_offset + length, 0, 0]
             ]
         ),
         method=type, cut = fullsize, closed=false
     );
     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;
-    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()
 
-    attachable(anchor,spin,orient, size=[width+2*offset, length, height]) {
-        down(height/2+adjustment) {
+    attachable(anchor,spin,orient, size=[width+2*offset, slide, length]) {
+        down(length/2+adjustment) {
             skin(
                 [
                     reverse(concat(smallend_points, xflip(p=reverse(smallend_points)))),

From 286eadd84b79358d5e08e6c222df4de5ffd20f8c Mon Sep 17 00:00:00 2001
From: Adrian Mariano <avm4@cornell.edu>
Date: Wed, 6 Jan 2021 21:31:40 -0500
Subject: [PATCH 4/6] parameter tweak

---
 joiners.scad | 66 ++++++++++++++++++++++++++--------------------------
 1 file changed, 33 insertions(+), 33 deletions(-)

diff --git a/joiners.scad b/joiners.scad
index 1dafea7..0f48a1a 100644
--- a/joiners.scad
+++ b/joiners.scad
@@ -419,7 +419,7 @@ module joiner_quad(spacing1=undef, spacing2=undef, xspacing=undef, yspacing=unde
 // Module: dovetail()
 //
 // Usage:
-//   dovetail(gender, l|length, w|width, slide, [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:
 //   Produces a possibly tapered dovetail joint shape to attach to or subtract from two parts you wish to join together.
@@ -433,9 +433,9 @@ module joiner_quad(spacing1=undef, spacing2=undef, xspacing=undef, yspacing=unde
 //
 // Arguments:
 //   gender = A string, "male" or "female", to specify the gender of the dovetail.
-//   l / length = Length of the dovetail (the amount it projects from its base)
 //   w / width = Width (at the wider, top end) of the dovetail before tapering
-//   slide = Distance the dovetail slides when you assemble it
+//   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.  
 //   angle = angle (in degrees) of the dovetail.  Specify only one of slope and angle.
@@ -446,65 +446,65 @@ 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.  
 //   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)
-//   dovetail("male", length=8, width=15, slide=30);
-//   right(20) dovetail("female", length=8, width=15, slide=30);
+//   dovetail("male", width=15, height=8, slide=30);
+//   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.)
-//   dovetail("male", l=8, w=15, slide=30, taper=6);
-//   right(20) dovetail("female", 8, 15, 30, taper=6);  // Same as above
+//   dovetail("male", w=15, h=8, slide=30, taper=6);
+//   right(20) dovetail("female", 15, 8, 30, taper=6);  // Same as above
 // Example: A block that can link to itself
 //   diff("remove")
 //     cuboid([50,30,10]){
-//       attach(BACK) dovetail("male", slide=10, width=15, length=8);
-//       attach(FRONT) dovetail("female", slide=10, width=15, length=8,$tags="remove");
+//       attach(BACK) dovetail("male", slide=10, width=15, height=8);
+//       attach(FRONT) dovetail("female", slide=10, width=15, height=8,$tags="remove");
 //     }
 // Example: Setting the dovetail angle.  This is too extreme to be useful.  
 //   diff("remove")
 //     cuboid([50,30,10]){
-//       attach(BACK) dovetail("male", slide=10, width=15, length=8, angle=30);
-//       attach(FRONT) dovetail("female", slide=10, width=15, length=8, angle=30,$tags="remove");
+//       attach(BACK) dovetail("male", slide=10, width=15, height=8, angle=30);
+//       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
 //   diff("remove")
 //     cuboid([50,30,10]){
-//       attach(BACK) dovetail("male", slide=10, width=15, length=8, chamfer=1);
-//       attach(FRONT) dovetail("female", slide=10, width=15, length=8,chamfer=1,$tags="remove");
+//       attach(BACK) dovetail("male", slide=10, width=15, height=8, chamfer=1);
+//       attach(FRONT) dovetail("female", slide=10, width=15, height=8,chamfer=1,$tags="remove");
 //     }
 // Example: Rounding the outside corners is another option
 //   diff("remove")
 //   cuboid([50,30,10]) {
-//       attach(BACK)  dovetail("male", slide=10, width=15, length=8, radius=1, $fn=32);
-//       attach(FRONT, overlap=-0.1) dovetail("female", slide=10, width=15, length=8, radius=1, $tags="remove", $fn=32);
+//       attach(BACK)  dovetail("male", slide=10, width=15, height=8, radius=1, $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
 //   $fn=32;
 //   diff("remove")
 //   cuboid([50,30,10]){
-//       attach(BACK) dovetail("male", slide=10, width=15, length=8, radius=1.5, round=true);
-//       attach(FRONT,overlap=-0.1) dovetail("female", slide=10, width=15, length=8, radius=1.5, round=true, $tags="remove");
+//       attach(BACK) dovetail("male", slide=10, width=15, height=8, radius=1.5, round=true);
+//       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.  Note that "length" refers to the amount the joint projects from its base, which is a little counter-intuitive when the joint has a very long slide like these sliding dovetails.  
+// 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])
-//     attach(TOP) dovetail("male", slide=50, width=18, length=4, back_width=15, spin=90);
+//     attach(TOP) dovetail("male", slide=50, width=18, height=4, back_width=15, spin=90);
 //   fwd(35)
 //     diff("remove")
 //       cuboid([50,30,10])
-//         attach(TOP) dovetail("female", slide=50, width=18, length=4, back_width=15, spin=90,$tags="remove");
+//         attach(TOP) dovetail("female", slide=50, width=18, height=4, back_width=15, spin=90,$tags="remove");
 // Example: A series of dovtails forming a tail board, with the inside of the joint up.  A standard wood joint would have a zero taper. 
 //   cuboid([50,30,10])
-//     attach(BACK) xcopies(10,5) dovetail("male", slide=10, width=7, taper=4, length=4);
+//     attach(BACK) xcopies(10,5) dovetail("male", slide=10, width=7, taper=4, height=4);
 // 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")
 //     cuboid([50,30,10])
-//       position(TOP+BACK) xcopies(10,5) dovetail("female", slide=10, width=7, taper=4, length=4, $tags="remove",anchor=BOTTOM+FRONT,spin=180);
-module dovetail(gender, length, width, slide, l, w, angle, slope, taper, back_width, chamfer, extra=0.01, r, radius, round=false, anchor=BOTTOM, spin=0, orient)
+//       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, 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);
-    lcount = num_defined([l,length]);
+    hcount = num_defined([h,height]);
     wcount = num_defined([w,width]);
     assert(is_def(slide), "Must define slide");
-    assert(lcount==1, "Must define exactly one of l and length");
+    assert(hcount==1, "Must define exactly one of h and height");
     assert(wcount==1, "Must define exactly one of w and width");
-    l = first_defined([l,length]);
+    h = first_defined([h,height]);
     w = first_defined([w,width]);
     orient = is_def(orient) ? orient :
         gender == "female" ? DOWN : UP;
@@ -518,7 +518,7 @@ module dovetail(gender, length, width, slide, l, w, angle, slope, taper, back_wi
         is_def(angle) ? 1/tan(angle) :  6;
     extra_slop = gender == "female" ? 2*$slop : 0;
     width = w + extra_slop;
-    length = l + extra_slop;
+    height = h + extra_slop;
     back_width = u_add(back_width, extra_slop);
 
     front_offset = is_def(taper) ? -extra * tan(taper) :
@@ -535,10 +535,10 @@ module dovetail(gender, length, width, slide, l, w, angle, slope, taper, back_wi
         move(
             [0,-slide/2-extra,0],
             p=[
-                [0                     , 0, length],
-                [width/2-front_offset  , 0, length],
-                [width/2 - length/slope - front_offset, 0, 0 ],
-                [width/2 - front_offset + length, 0, 0]
+                [0                     , 0, height],
+                [width/2-front_offset  , 0, height],
+                [width/2 - height/slope - front_offset, 0, 0 ],
+                [width/2 - front_offset + height, 0, 0]
             ]
         ),
         method=type, cut = fullsize, closed=false
@@ -550,8 +550,8 @@ module dovetail(gender, length, width, slide, l, w, angle, slope, taper, back_wi
 
     adjustment = $overlap * (gender == "male" ? -1 : 1);  // Adjustment for default overlap in attach()
 
-    attachable(anchor,spin,orient, size=[width+2*offset, slide, length]) {
-        down(length/2+adjustment) {
+    attachable(anchor,spin,orient, size=[width+2*offset, slide, height]) {
+        down(height/2+adjustment) {
             skin(
                 [
                     reverse(concat(smallend_points, xflip(p=reverse(smallend_points)))),

From db65b14410bab65f06f5dd12884d6140f88b888a Mon Sep 17 00:00:00 2001
From: Adrian Mariano <avm4@cornell.edu>
Date: Wed, 6 Jan 2021 22:08:54 -0500
Subject: [PATCH 5/6] fix undef bug in cyl()

---
 shapes.scad | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/shapes.scad b/shapes.scad
index 019f197..59083a2 100644
--- a/shapes.scad
+++ b/shapes.scad
@@ -808,8 +808,8 @@ module cyl(
                 vang = atan2(l, r1-r2)/2;
                 chang1 = 90-first_defined([chamfang1, chamfang, vang]);
                 chang2 = 90-first_defined([chamfang2, chamfang, 90-vang]);
-                cham1 = first_defined([chamfer1, chamfer]) * (from_end? 1 : tan(chang1));
-                cham2 = first_defined([chamfer2, chamfer]) * (from_end? 1 : tan(chang2));
+                cham1 = u_mul(first_defined([chamfer1, chamfer]) , (from_end? 1 : tan(chang1)));
+                cham2 = u_mul(first_defined([chamfer2, chamfer]) , (from_end? 1 : tan(chang2)));
                 fil1 = first_defined([rounding1, rounding]);
                 fil2 = first_defined([rounding2, rounding]);
                 if (chamfer != undef) {

From e87b9cd6f079cbb1dca641852dd57c1fbb4663c4 Mon Sep 17 00:00:00 2001
From: Adrian Mariano <avm4@cornell.edu>
Date: Wed, 6 Jan 2021 22:29:11 -0500
Subject: [PATCH 6/6] undef fixes for screws.scad

---
 screws.scad | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/screws.scad b/screws.scad
index 4368068..4596bde 100644
--- a/screws.scad
+++ b/screws.scad
@@ -37,7 +37,7 @@ function _parse_screw_name(name) =
                let(val=str_num(type))
                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"
@@ -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(drive_info[1]) ? ["drive_size", drive_info[1]] : [],
                         ["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);
@@ -307,7 +307,7 @@ function _screw_info_english(diam, threadcount, head, thread, drive) =
                [2,    [      3,   1.5, undef, undef, undef]],
             ],
             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=="torx" ? [["drive_size",entry[2]],["drive_depth",inch*entry[4]]] : []
             )