BOSL2 icon indicating copy to clipboard operation
BOSL2 copied to clipboard

Sparse shapes beyond wall

Open jdanders opened this issue 1 year ago • 10 comments

Is your feature request related to a problem? Please describe. I love the strength and efficiency of the sparse wall, but not everything I do is oriented as a wall. Usually I start my design using cuboids and then realize I am wasting too much material and convert them to sparse walls. It drives me crazy to get the orientation and parameters right in the conversion from

cuboid([10,20,30]);

to

sparse_wall(h=10, l=20, thick=30);

Usually the holes end up the wrong direction, then all my anchors and positions get messed up when I try to tweak orientation of the wall.

Describe the solution you'd like At this point, I'd like to see a sparse cuboid, but if it makes sense, this could be expanded to other 3d shapes. A sparse_cuboid takes the same parameters as a cuboid, but adds the cutouts of the sparse_wall and puts the cutouts in the right orientation.

Describe alternatives you've considered Here's my lame version of a sparse cuboid. It assumes the holes should align with the shortest dimension. A more elegant version might have a parameter that chooses hole orientation. I would love it if all the features of cuboids were available, like rounding.

Example Code

include <BOSL2/std.scad>
include <BOSL2/walls.scad>
module sparse_cuboid(size, maxang=30, strut=5, max_bridge=20, anchor=CENTER, spin=0, orient=UP) {
  if (size[0] <= size[1] && size[0] <= size[2]) // x skinny
    attachable(anchor=anchor, spin=spin, orient=orient, size=size) {
      sparse_wall(h=size[2], l=size[1], thick=size[0], maxang=maxang, strut=strut,
                  max_bridge=max_bridge);
      children();
    }
  else if (size[1] <= size[0] && size[1] <= size[2]) // y skinny
    attachable(anchor=anchor, spin=spin, orient=orient, size=size) {
      zrot(90) sparse_wall(h=size[2], l=size[0], thick=size[1], maxang=maxang, strut=strut,
                           max_bridge=max_bridge);
      children();
    }
  else if (size[2] <= size[0] && size[2] <= size[1]) // z skinny
    attachable(anchor=anchor, spin=spin, orient=orient, size=size) {
      xrot(90) zrot(90) sparse_wall(h=size[0], l=size[1], thick=size[2], maxang=maxang, strut=strut,
                           max_bridge=max_bridge);
      children();
    }
  else echo("Failed sparse cuboid");
}

Here's what three cuboids look like when converted to sparse_wall. image

Here's what I would like it to look like: image

sparse_cuboid([10,20,30], strut=1);
fwd(30) sparse_cuboid([30,20,10], strut=1);
fwd(60) sparse_cuboid([20,10,30], strut=1);

Yes, these are the same three shapes with different orientation, but I can never figure out how to fix the orientation without major side-effects.

jdanders avatar Apr 04 '24 21:04 jdanders

sparse_wall(h=30, l=20, thick=10, strut=1);
Screenshot 2024-04-04 at 3 30 31 PM

I think I'm confused. Is this proposal just an interface change to use a size=[X,Y,Z] triplet, with the holes through the skinny axis?

revarbat avatar Apr 04 '24 22:04 revarbat

It's to use the triplet and manage the orientation of the holes (and ideally, the other cuboid parameters like rounding).

The rightmost shape in my example is the shape you reproduced, and is the shape oriented correctly for the sparse_wall. The other two shapes have suboptimal holes cut compared to my ideal results.

My full request would be for any 3d shape to be sparseable.

jdanders avatar Apr 04 '24 22:04 jdanders

Making cylinders sparseable along their axis is doable, but I'm unclear that spheres or arbitrary 3D shapes would be practical.

revarbat avatar Apr 04 '24 23:04 revarbat

Agreed on arbitrary shapes, that would be too broad. Prismoids, wedges, and octahedrons would be the other shapes from the library that could be practical.

I would imagine a sphere would be something like this, assuming someone smarter than me figured out how to size the holes correctly. And maybe instead of circular holes, you could do cutout so that the remaining material was essentially the lat/long lines of the sphere. image

jdanders avatar Apr 04 '24 23:04 jdanders

Probably would get better results with a phi spiral a la sphere_copies().

difference() {
    sphere(d=100);
    sphere(d=80);
    sphere_copies(d=100, n=50, cone_ang=180) cyl(d=10, h=20, anchor=CTR);
}
Screenshot 2024-04-04 at 5 08 59 PM

revarbat avatar Apr 05 '24 00:04 revarbat

Wireframed icosahedrons could be useful too. Screenshot 2024-04-05 at 5 46 07 PM

vnf_wireframe(spheroid(d=100, style="icosa", $fn=5), width=5, $fn=24);

This can, of course be increased in sides by upping the first $fn= in increments of 5.

revarbat avatar Apr 06 '24 00:04 revarbat

would a "sparse_wall_mask" that could be constrained take a polygon address some of these issues? Then it could be attached with diff() to faces of any object.

adrianVmariano avatar Apr 10 '24 00:04 adrianVmariano

module sparse_cuboid(size, dir, 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)
{
  dummy1=assert(is_vector(dir,3), "dir must be a 3-vector");
  count = len([for(d=dir) if (d!=0) d]);
  dummy2=assert(count==1 && len(dir)<=3, "dir must have exactly one non-zero component");
  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();
  }    
}  


sparse_cuboid([10,20,30], strut=1, dir=RIGHT, rounding=3);
fwd(30) sparse_cuboid([30,20,10], strut=1, dir=UP, chamfer=1);
fwd(60) sparse_cuboid([20,10,30], strut=1, dir=FWD);

So something like the above? Seems like you can get into trouble with roundings. And also what you really want is for all the bracing to be rounded as well, which unlike the above, is nontrivial.

adrianVmariano avatar May 11 '24 18:05 adrianVmariano

I agree with jdanders comment "but I can never figure out how to fix the orientation without major side-effects", and in my case at least, it applies in other parts of BOSL2. (e.g. linear_sweep()). Hence our discussion recently on Gitter about having a "reset" for the reference frame.

RAMilewski avatar May 13 '24 19:05 RAMilewski

If you've built a model with objects that have children and change the orientation of an object it will screw up everything downstream. But a "reset" will only help if the object in question has enough symmetry that it's anchors don't change when you change the orientation. Otherwise you'll have trouble with positioning.

adrianVmariano avatar May 13 '24 21:05 adrianVmariano