L2: "Stacking Up"
- Joelle McDonald

- Mar 5, 2025
- 7 min read
In this blog post I undertake a project to use 3D Parametric Design and Slicing to create a Laser Cut assembly. This project involves using Grasshopper to create a parametric design, then adding more functionality by building a slicer and arraying those slices across a plane to prepare them for laser cutting. Once cut, I assembled the pieces to fabricate two of the designs I created.
Tools and Materials Used: Grasshopper, Rhino, Laser Cutter, Cardboard, Elmer's Glue
Task 1: Parametric 3D Designs

Below is a snapshot of the code I used to generate these designs. In the snapshot the parameters are set to those used to create Iteration 4. To view the original code I used to generate these designs in Grasshopper, please visit this GitHub link. If you want to recreate a designs I have included in Figure 1, input the parameters in the associated Iteration column in Figure 2.

Parameters used in the designs pictured in Figure 1

Task 2: Creating a 3D-to-2D Slicer
In this task I will take the first two designs I created in the previous task and code a slicer that will take cross sections of the design at parametric intervals. Once I have broken the 3D shape into slices, I lay them out on the XY plane and etch numbers onto their surfaces so that I will finish with a laser-cuttable file. The cross-section distances will be determined my the thickness of the material I am laser cutting. I chose to use corrugated cardboard with a thickness of 3.9mm. I therefore set the slicer to make a cross section every 3.9mm. To get myself started, I referenced this YouTube video by Daniel Christev.
Creating the Slicer
Step 1: Creating the Bounding Box
The first set to creating my slicer was to create a bounding box around my 3D design. I manually created this bounding box, but I could have simplified the process by using the "Bounding Box" command in grasshopper. Instead I created a base rectangle centered around the design and set the box to match the height of my tallest polygon.

Step 2: Creating Contours, Offsets, and a Solid Base
Once my bounding box was created, I moved on to creating slices of my 3D design. I used the contour command to achieve this, feeding it my 3D object, the thickness of my material, and a starting point at the center of the object's base. My intention was for my design to create vase-like vessels, so I needed to hollow out my shape. To achieve this I used offsets of each contour to cut out all but the external 4mm from each slice. This command, however, would have resulted in a laser cut tube because the bottom-most layer also had a offset removed. To resolve this I replaced the branch responsible for the bottom-most offset so that that offset was instead applied only to excess shapes generated by the code; If there are 23 layers in a design, the first layer's offset would be moved from the first layer to the 24th layer, creating a solid-bottomed shape).

Step 3: Creating a Grid to Array the Slices
Once the bounding box and slices were created, I needed to spread each slice out along the XY plane without overlapping so they could be laser cut. I defined my rectangular grid by combining the size of bounding box and number of contours needed to be arrayed. I also have a parameter for padding to increase the space between grid squares as needed.

Step 4: Arraying the Slices Across the Grid
With my grid and slices created I can now easily arrange my slices into an XY plane. To do this I simply oriented the centroid of each slice to a grid intersection.

Step 5: Numbering Each Slice
Finally, with all the slices arrayed I only needed to number each slice so that once cut, it would be clear the order in which the pieces should be assembled. This is important given the complexity of the objects. I created a grafted series to identify the number that each layer should bear, counting based on the tree created by the "Contours" command. To identify the surface and location for each number, I had to create a surface between the space of each shape and its offset to use as the "Base Surface" input. Because each slice was so narrow due to the offset, I had to create an input for "Base Line" by creating a point of each of the curves, then using a polyline to connect those vertices. One benefit of this method is that each number was etched along the same vertical axis. This means that during assembly, to cope with lining up rotating layers I will simply need to match up the number placement on each layer.

Slicing Design 1
To slice my first design, I simply input the parameters for "Iteration 1" as identified above on Figure 2. This created the left-most design pictured in Figure 1. I then exported the resulting Rhino output as a pdf, which can be seen below. You will notice that though the design is 23 layers, there are 25 shapes outputted. This is because once all contours for the shape are mapped onto the grid, the remaining grid spaces generate the offset associated with the first layer of the design. This is a result of the "Replace" function I used to ensure the bottom layer of the output is solid. You may also notice that the bottom layer is not marked with it's layer number "0". This is because the "Base Line" input is based on the vertices of the exterior shape and the offset. Because that layer has no offset, it is unlabeled. As the only unlabeled layer, however, it is clear what its position is in assembly.

Grasshopper Code
Below is a snapshot of the code used to create, slice, array, and number Design 1 in preparation for its fabrication. To view to code in grasshopper, visit this GitHub link.

Design 2
To slice my second design, I simply input the parameters for "Iteration 2" as identified above on Figure 2. This created the second-from-left design pictured in Figure 1. The same observations named above for Design 1 are true in this output as well, where the solid bottom layer is unnumbered and its offset is passed onto the array's excess grid slots. In this output there was one complete row of excess offsets traced, which I manually deleted from the laser-ready pdf you see below.

Grasshopper Code
Below is a snapshot of the code used to create, slice, array, and number Design 2 in preparation for its fabrication. To view to code in grasshopper, visit this GitHub link.

Task 3: Exporting and Fabricating my Design
As stated in Task 2, I chose to use PDF exports of the Rhino rendering of my Grasshopper code to create a fabricate-able file. I changed all lines to a hairline print width and adjusted the display colors to match the laser cutter's color coding for vector etch and vector cut cues.
Fabrication of Design 1

To view the file Rhino file I used to laser cut the output of my slicer for Design 1, visit this GitHub Link. Once I had my cardboard laser cut and etched with layer numbers, I laid out each piece in order for gluing. I applied glue to the bottom layer of each odd-numbered piece and adhered it to the even numbered piece below it, aligning the etched numbers to maintain proper orientation. With even-odd pairs created, I began gluing pairs together. This technique allowed glue to dry more before I handled it for the next attachment.

Fabrication of Design 2

To view the file Rhino file I used to laser cut the output of my slicer for Design 2, visit this GitHub Link. Once I had my cardboard laser cut and etched with layer numbers, I laid out each piece in order for gluing. This time I glued consecutive layers rather than using a paired approach. While this allowed less time for glue to dry between layers, it made it easier to view each number to correctly orient it to the one below it.

Conclusion
In the execution of this project many steps went smoothly, but I faced particular challenges in hollowing out my designs and adding number labels to the surfaces. I had no experience with the "Offset"function previously so attempted to hollow out the objects with simple cylinders. That ultimately proved more challenging than imaginable and discovering the offset feature eased the process immensely.
It took perhaps the most persistence to work out how to number each surface. My first hurdle was identifying that my arrayed curves were not surfaces so they could not interface with the "Text on Surface" function. Once I resolved that problem I faced the issue of every number in the contour tree printing onto each layer. After much trial and error, I resolved this by simply grafting the tree. Finally, because the shapes are hollowed out, I had a very narrow and specific space on which to fit each number. I ensured the numbers were printed in that space using point of curve to create vertices for a polyline from outer edge to inner edge. That solution came about from a great deal of trial and error.
Before this project, I had never used Grasshopper. I gained a huge amount of skill and confidence in the software through the evolution of this output. I appreciate what a powerful tool Grasshopper to create objects in Rhino.


Comments