algorithmic modeling for Rhino
Having ported a nearly ideal triangular remeshing program, OpenFlipper, to Grasshopper (http://www.grasshopper3d.com/forum/topics/best-uniform-remesher-for...), and taking the dual "mesh" of the result, to obtain mostly hexagonal surface divisions (along with only pentagons and septagons), I tried my Grasshopper Tetgen parser for 3D space filling tetrahedral meshing and its own dual, inside of mesh bodies that represented a pillow-like expansion of an initial flat single sided mesh. This is akin to a plaster cast on a broken limb, in character. But the tetrahedral mesh was too constrained by large and thus nicely open surface triangles, so the dual Voronoi-like polyhedra inside could not relax into a particularly isotropic/regular truss system. Short lines remained that destroyed strut fattening of mere lines.
So I developed a relatively fast culling method of transmembrane connecting struts, connected to the middle of each surface strut. This connectivity means all hubs have only three struts for both surface definition and inner bracing. This is profound since it means I can use *fast* IntraLattice to create 3D printable struts instead of impossibly slow and memory-exploding marching cubes (Cocoon/Monolith/Dodo/etc.) and then cleanly subdivide (Weaverbird Loop) as well, to remove crude mesh face faceting.
I lieu of iterative methods that Grasshopper requires plugins for or scripting, I just repeated the culling step five times. The hack is a "poor man's" clustering of creating polylines from many nearest connection lines, that have more than one connector strut going to each surface strut. I cull the longest line in those polylines and explode again and repeat the joined polyline process. Before these steps I cull very short lines which dominate edges of the pillow forms.
I used Ivy to quickly grab a dual of the OpenFlipper triangle mesh, from my input triangle mesh.
It mercifully skips non-flat-offset regions, and I'm not sure why. I created "test probe" lines, jutting in at the mesh normal at the surface strut midpoints, that then nearly touched the other surface in flat regions, and that's how I determined which was the "closest point" to create a link to. I end up with too many links though, with lots of "triangles" that IntraLattice cannot deal with without blowing up or causing ugly webbing effects because the convex hull hubs become bulbously askew.
I wish I had a more elegant culling routine, or script. I used probe lines jutting in from the surface strut midpoints at the mesh normal direction, to then find a nearest neighbor surface strut midpoint, at the other membrane. That left lots of "triangles." I couldn't just use nearest neighbor, without such a probe, since it then gets lots in it's own membrane instead of seeking out the other one.
Before culling shorts:
Ah, the reason the non-thin areas escape cross beams, that wouldn't order themselves naturally anyway between multiple membranes, is that my test "probe" wires jutting in from the middle of surface struts only find nearest neighbors on their own membrane, namely their own immediate next door neighbor so they don't show up visually in my test, and then they get culled out as shorts.
Thanks for posting in detail. This is really great work. I've been working extensively with the marching cubes method, in particular cocoon, and speed is definitely an issue as I'm sure you have experienced. However, I also found that interlace had too many issues with 'blowing up' as you describe. I used the remove duplicate lines component from either kangaroo or karamba to imporve those results, but its still hit and miss. It feels like the set of reasonable parameters for the meshing algorithm in cocoon is a little more flexible. I was wondering.. Do you have any method for zonal support or density control in these definitions? If you for example wanted one region for the mesh to be twice as dense, could you do that? Thanks again for the great work.
Meshwork, including 3D meshes, isn't a lot of math, just moving things around and making connecting lines. To change density you'd just use random numbers multiplied by a distance function from wherever you wanted to thin the herd and the result would still be relatively even due to randomness and smoothly transitioned due to distance being perhaps 1 over d squared or cubed in falloff factor. That would be a post processing step. I already have as many as I can cram in there with only one brace per surface wire though I may be missing a few due to the kludgy nature of my polyline "algorithm."
IntraLattice itself already has a shell filling system that even lets you define your own 3D unit cell, but the surface is always going to be rectangle-based because it uses such cells. It sadly lacks, so far, it's own Boolean to attach the lattice to a surface shell, for 3D printing, and Rhino is not behaving nicely when I try to Boolean a hollow ball that has two formally joined mesh surfaces, even when I carefully flip the inner mesh before manually joining them in Rhino. What IntraLattice won't do that tetrahedral meshing can achieve is link up to existing surface vertices.
IntraLattice has a tolerance bug that ruins its convex hulls. If this little piece of its 'X' style 3D struss unit cell is only 0.1" wide, then it destroys the integrity of the convex hull hub, whereas if I merely scale it up to 1" wide and scale the strut radius up to 0.1 instead of 0.01, it comes out fine:
I also note that IntraLattice slows way down when I tweak the Rhino tolerance setting from 0.001" to 0.0001", whereas 0.01" prevents any output, with my smaller model.