I am working on a Grasshopper script to generate physical terrain layers for laser cutting. I am stuck on filtering the correct surfaces.
The Workflow:
I have a base bounding rectangle (“Curve”).
I have topography contour curves positioned at various Z-levels.
I create a planar surface from the bounding rectangle at each Z-level.
I use the Surface Split component to cut these rectangular surfaces with the contour curves.
The Problem:
The Surface Split component outputs all fragments: the “terrain islands” (inside the contours) and the “waste” (the rest of the bounding rectangle). I need to remove the “waste” part and keep only the terrain.
What I have tried (and why it failed):
Sorting by Area: I tried sorting the fragments by Area and culling the largest one. This fails because at certain elevations (e.g., z=350 in my file), the terrain area is actually larger than the waste border, so the script deletes the wrong geometry.
List Item: I cannot simply select index 0 or 1, because some levels have multiple contour islands, resulting in a variable number of surfaces per branch.
The Question:
What is the most robust way to filter the Surface Split results to keep only the surfaces that represent the interior of the contour curves?
I have attached a simplified definition with the data. Any help would be appreciated!
Thanks for the suggestion, but I am afraid relying on X/Y coordinates or the “bottom-left” logic won’t be robust enough for this definition.
The main issue is that the terrain geometry varies significantly across different Z-levels:
Multiple Islands: Some levels have multiple disconnected terrain islands. In these cases, the Surface Split results in 3 or more fragments. Removing just one based on position would either leave waste behind or delete valid terrain parts.
Shape complexity: The terrain isn’t always centered. A strict coordinate filter might fail if the terrain shape is concave or positioned near the “waste” edge.
In my experience, trying to determine which curves are which is a losing game. Instead, I do it the dumb way: Make a brep of the terrain and slice it to reveal flat surfaces.
(If it’s dumb and it works, it ain’t dumb, right? )
This uses Patch to make the terrain surface. Increase the Spans for better accuracy.
It also uses Planar to tease out the result, which is quite slow. There may be a faster way, but this is reliable.
EDIT: I see @Artstep had the same intuition, but you can’t check for surface centres. A C-shaped surface would have a centre outside its boundary. Pop Geo might work to get a testing point, but I can imagine some edge cases slipping through at the edge of tolerance.
Thank you all for the incredible support and the variety of approaches. It seems that a flawless, “universal” vector-based solution using Surface Split—one that handles every edge case (like coincident boundaries) without complex data management—is quite elusive.
Here is a summary of the results for my specific case:
@Tom_Newsom
Thank you for the mesh-based approach. While I was initially hesitant to switch from exact NURBS curves to a Mesh approximation (due to the slight deviation in the final laser path), I have to admit this is the most robust solution. It handles islands, holes, and complex topologies without breaking. I will likely proceed with this method for production.
@Fabio_Franchetti
Your definition is extremely close to a perfect exact solution! The logic is elegant. However, I found that it fails in specific edge cases where the contour curves touch or coincide with the boundary of the working area. If those edge conditions were resolved, it would be the perfect vector solution.
I have to say though, if you’re laser cutting and you’re not overly concerned with wastage, why not just separate each Z-level’s curves into an array and cut them all next to each other? Then use your clever human eyes to figure out which bits are solid and which are void during assembly.
I understand your logic and in this specific case it would be the way. But this case is just for the testing. For the laser cut the final model is much more complex with much more layers.
Can you test or is there a way for you to share the actual contours so we can test ideas on that instead? I guess I’d be concerned about overall orientation of your actual file. The example I share uses BoundingBox, for which specific ‘local’ planes might be needed if you’re not parallel to Rhino XY.
Understood. Some advice from experience: Make sure each “peak” has at least two, preferably more, registration holes cut into it, from the second-highest layer all the way to the bottom, so you can thread the layers onto rods for perfect alignment.
Ok, the scale of this data makes things quite a bit more difficult. My patch surface method is going to choke to death on it, and the mesh version is likewise going to struggle. The mesh version also won’t adequately capture all the vertical detail.
I’ll see what I can come up with but this looks very challenging!
Also these contours are more problematic, some of them do not really intersect the provided ‘plane’, so splitting won’t work, each contour might require its own ‘local’ bounding rectangle.