diff --git a/masks3d.scad b/masks3d.scad
index 0774217..aebbf60 100644
--- a/masks3d.scad
+++ b/masks3d.scad
@@ -249,20 +249,6 @@ module chamfer_cylinder_mask(r, chamfer, d, ang=45, from_end=false, anchor=CENTE
 //               rounding_edge_mask(l=p.z, r=25);
 //       }
 //   }
-// Example: Acute angle 
-//   ang=60;
-//   difference() {
-//       pie_slice(ang=ang, h=50, r=100);
-//       zflip_copy(z=25)
-//          #rounding_corner_mask(r=20, ang=ang);
-//   }
-// Example: Obtuse angle 
-//   ang=120;
-//   difference() {
-//       pie_slice(ang=ang, h=50, r=30);
-//       zflip_copy(z=25)
-//          #rounding_corner_mask(r=20, ang=ang);
-//   }
 
 function rounding_edge_mask(l, r, ang=90, r1, r2, d, d1, d2, excess=0.1, anchor=CENTER, spin=0, orient=UP, h,height,length) = no_function("rounding_edge_mask");
 module rounding_edge_mask(l, r, ang=90, r1, r2, excess=0.01, d1, d2,d,r,length, h, height, anchor=CENTER, spin=0, orient=UP,
@@ -274,7 +260,7 @@ module rounding_edge_mask(l, r, ang=90, r1, r2, excess=0.01, d1, d2,d,r,length,
     dummy = assert(all_nonnegative([r1,r2]), "radius/diameter value(s) must be nonnegative")
             assert(all_positive([length]), "length/l/h/height must be a positive value")
             assert(is_finite(ang) && ang>0 && ang<180, "ang must be a number between 0 and 180");
-    steps = ceil(segs(r)*(180-ang)/360);
+    steps = ceil(segs(max(r1,r2))*(180-ang)/360);
     function make_path(r) =
         let(
              arc = r==0 ? repeat([0,0],steps+1)
@@ -383,8 +369,21 @@ module rounding_edge_mask(l, r, ang=90, r1, r2, excess=0.01, d1, d2,d,r,length,
 //       corner_mask(TOP)
 //           #rounding_corner_mask(r=20);
 //   }
-// Example: Acute angle mask
-// 
+// Example(VPR=[71.8,0,345.8],VPT=[57.0174,43.8496,24.5863],VPD=263.435,NoScales): Acute angle 
+//   ang=60;
+//   difference() {
+//       pie_slice(ang=ang, h=50, r=100);
+//       zflip_copy(z=25)
+//          #rounding_corner_mask(r=20, ang=ang);
+//   }
+// Example(VPR=[62.7,0,5.4],VPT=[6.9671,22.7592,20.7513],VPD=192.044): Obtuse angle 
+//   ang=120;
+//   difference() {
+//       pie_slice(ang=ang, h=50, r=30);
+//       zflip_copy(z=25)
+//          #rounding_corner_mask(r=20, ang=ang);
+//   }
+
 function rounding_corner_mask(r, ang, d, style="octa", excess=0.1, anchor=CENTER, spin=0, orient=UP) = no_function("rounding_corner_mask");
 module rounding_corner_mask(r, ang=90, d, style="octa", excess=0.1, anchor=CENTER, spin=0, orient=UP)
 {
diff --git a/walls.scad b/walls.scad
index a188a9c..ca0a467 100644
--- a/walls.scad
+++ b/walls.scad
@@ -16,7 +16,7 @@
 // Synopsis: Makes an open cross-braced rectangular wall.
 // SynTags: Geom
 // Topics: FDM Optimized, Walls
-// See Also: sparse_wall(), corrugated_wall(), thinning_wall(), thinning_triangle(), narrowing_strut()
+// See Also: corrugated_wall(), thinning_wall(), thinning_triangle(), narrowing_strut()
 //
 // Usage:
 //   sparse_wall(h, l, thick, [maxang=], [strut=], [max_bridge=]) [ATTACHMENTS];
@@ -30,9 +30,9 @@
 //   l = length of strut wall.
 //   thick = thickness of strut wall.
 //   ---
-//   maxang = maximum overhang angle of cross-braces.
-//   strut = the width of the cross-braces.
-//   max_bridge = maximum bridging distance between cross-braces.
+//   maxang = maximum overhang angle of cross-braces, measured down from vertical.  Default: 30 
+//   strut = the width of the cross-braces. Default: 5
+//   max_bridge = maximum bridging distance between cross-braces.  Default: 20
 //   anchor = Translate so anchor point is at origin (0,0,0).  See [anchor](attachments.scad#subsection-anchor).  Default: `CENTER`
 //   spin = Rotate this many degrees around the Z axis after anchor.  See [spin](attachments.scad#subsection-spin).  Default: `0`
 //   orient = Vector to rotate top towards, after spin.  See [orient](attachments.scad#subsection-orient).  Default: `UP`
@@ -87,6 +87,75 @@ module sparse_wall(h=50, l=100, thick=4, maxang=30, strut=5, max_bridge=20, anch
 }
 
 
+// Module: sparse_cuboid()
+// Synopsis: Makes an open cross-braced cuboid
+// SynTags: Geom
+// Topics: FDM Optimized, Walls
+// See Also: sparse_wall(), corrugated_wall(), thinning_wall(), thinning_triangle(), narrowing_strut(), cuboid()
+// Usage:
+//   sparse_cuboid(size, [dir], [maxang=], [struct=]
+// Description:
+//   Makes an open rectangular cuboid with X-shaped cross-bracing to reduce the need for material in 3d printing.
+//   The direction of the cross bracing can be aligned with the X, Y or Z axis.  This module can be
+//   used as a drop-in replacement for {{cuboid()}} if you belatedly decide that your model would benefit from
+//   the sparse construction.  
+// Arguments:
+//   size = The size of sparse wall, a number or length 3 vector.
+//   dir = direction of holes through the cuboid, must be a vector parallel to the X, Y or Z axes, or one of "X", "Y" or "Z".  Default: "Y"
+//   ---
+//   maxang = maximum overhang angle of cross-braces, measured down from vertical.  Default: 30 
+//   strut = the width of the cross-braces. Default: 5
+//   max_bridge = maximum bridging distance between cross-braces.  Default: 20
+//   chamfer = Size of chamfer, inset from sides.  Default: No chamfering.
+//   rounding = Radius of the edge rounding.  Default: No rounding.
+//   edges = Edges to mask.  See [Specifying Edges](attachments.scad#section-specifying-edges).  Default: all edges.
+//   except = Edges to explicitly NOT mask.  See [Specifying Edges](attachments.scad#section-specifying-edges).  Default: No edges.
+//   trimcorners = If true, rounds or chamfers corners where three chamfered/rounded edges meet.  Default: `true`
+//   teardrop = If given as a number, rounding around the bottom edge of the cuboid won't exceed this many degrees from vertical.  If true, the limit angle is 45 degrees.  Default: `false`
+//   anchor = Translate so anchor point is at origin (0,0,0).  See [anchor](attachments.scad#subsection-anchor).  Default: `CENTER`
+//   spin = Rotate this many degrees around the Z axis.  See [spin](attachments.scad#subsection-spin).  Default: `0`
+//   orient = Vector to rotate top towards.  See [orient](attachments.scad#subsection-orient).  Default: `UP`
+// Examples:
+//   sparse_cuboid([10,20,30], strut=1);
+//   sparse_cuboid([10,20,30], "Y", strut=1);
+//   sparse_cuboid([10,20,30], UP, strut=1);
+//   sparse_cuboid(30, FWD, strut=2, rounding=2);
+module sparse_cuboid(size, dir=RIGHT, strut=5, maxang=30, max_bridge=20,
+    chamfer,
+    rounding,
+    edges=EDGES_ALL,
+    except=[],
+    except_edges,
+    trimcorners=true,
+    teardrop=false,
+    anchor=CENTER, spin=0, orient=UP)
+{
+  size = scalar_vec3(size);
+  dummy1=assert(in_list(dir,["X","Y","Z"]) || is_vector(dir,3), "dir must be a 3-vector or one of \"X\", \"Y\", or \"Z\"");
+  count = len([for(d=dir) if (d!=0) d]);
+  dummy2=assert(is_string(dir) || (count==1 && len(dir)<=3), "vector valued dir must have exactly one non-zero component");
+  dir = is_string(dir) ? dir
+      : dir.x ? "X"
+      : dir.y ? "Y"
+      : "Z";
+  attachable(anchor,spin,orient,size=size){
+    intersection(){
+      if (dir=="X")
+         sparse_wall(size.z,size.y,size.x,strut=strut,maxang=maxang, max_bridge=max_bridge);
+      else if (dir=="Y")
+         zrot(90)
+           sparse_wall(size.z,size.x,size.y,strut=strut,maxang=maxang, max_bridge=max_bridge);
+      else
+         yrot(90)
+           sparse_wall(size.x,size.y,size.z,strut=strut,maxang=maxang, max_bridge=max_bridge);
+      cuboid(size=size, chamfer=chamfer, rounding=rounding,edges=edges, except=except, except_edges=except_edges,
+           trimcorners=trimcorners, teardrop=teardrop);
+    }
+    children();
+  }    
+}
+
+
 // Module: corrugated_wall()
 // Synopsis: Makes a corrugated rectangular wall.
 // SynTags: Geom