Introduction: [computational Fabrication] Parametric Surfaces & Turning Refitted Household Objects Into Vases
The goal of this project is to augment a household item -- examples include a lampshade and a votive candle holder by designing surfaces.
As I do not own a lamp, my goal is to design vase inserts. I love flower arrangements but I don’t like using foam to shape them. Often using larger vases means it’s difficult to control the degree which stems disperse after I’ve arranged them. Also simple vases aren’t as dramatic. Another thought I have is that I can design an insert that fits into an ordinary glass to make it more usable as a small vase.
Also my class had a good discussion (thanks Philip) around the design process. Personally I felt I’d been limited to thinking in code and as a result felt like I wasn’t generating visually interesting outcomes. After our discussion I’m encouraged to think about using Grasshopper and python to create tools specific to my project and desired outcomes… let’s see if that framing helps!
This is the third project for a course I’m taking this quarter (Spring 2020) on computational fabrication taught by Prof. Jennifer Jacobs at the Media, Arts & Technology program at the University of California Santa Barbara. The idea behind the course is that digital fabrication can be combined with computational design to create complex and functional physical forms.
Tools I used for this work include
- Rhinoceros (Rhino), a commercial NURBS-based computer-aided design (CAD) tool
- Grasshopper, a visual programming language based on a data flow paradigm that lets you parametrize the geometry you create in Rhino Pufferfish, a plug-in for Grasshopper that you can download at [food4Rhino]
- Ultimaker CURA, an open source 3D printer slicing application
- Creality Ender 3D Pro, a commercially available 3D printer supplied by UCSB
- Calipers although a tape measure should suffice
Step 1: STEP ONE [Measuring the Object & Designing Lip]
I’m using two objects for this project: (1) vase and (2) glass. The outer diameter for both objects was 84.05 and 83.55 mm respectively.
Next, I need to design a lip that rests on these. In Rhino, I created a circle centered at the origin with the diameters noted above. Then I decided to create this geometry in grasshopper instead using a circle component that takes in a center (origin), vector (e2 = <0, 0, 1>), and a radius.
Then, I created a manually drawn curve to be the edge of the lip. I tried to revolve it around the circle only to find the geometry was fixed whereas my goal was to construct a dynamic lip. So I strung together some components in Grasshopper to decompose the curve into a set of points that could then be manipulated via a python script that used the radius above as an input and exposed other parameters like the height of the lip (h1 = how thick the base will be to support my final structure), the inner width of the overhang (w1 = extending on the inside of the vase), the outer width of the overhang (w2 = extending outside the vase) and the height of the hook (h2 = how far down the hook extends).
- It took me a long time to figure out I needed to enable list access to manipulate individual points (right click on the input to the python script).
- Note you can access my in progress scripts and models here https://github.com/SoniaHashim/compfab/blob/master/week3/sandbox.gh
Lastly, I thought it would be a good idea to do a test print to check for fit! I experimented with changing the infill density and pattern to reduce the printing time as well as flipping it… it will still take approximately 3 hours. I guess I can use that time to work on designing the surface!
My printer seems like there’s a filament jam in the nozzle so I need to disassemble and clean out the material so I can feed in new material….
Step 2: STEP TWO [Developing a Surface]
This week I want to start from a place of concrete design. My goal is to create a floral shape with a pinched neck that would let me control the inner radius of the neck to create a more restricted opening. I might want to tilt the opening too -- I’m not sure yet!
We had a class demo using fully parameterized surfaces but there were some issues closing the surface and attaching the geometry to the base. So I’m going to loft a surface starting with the circle I use to determine the lip size and then use another circle as the basis for the curve at the neck and another one as the opening.
The first step is to use a Python script to output the curves I’m going to loft. To first test the full pipeline I just used three circles (the base, the pinch, and the opening) to define a neck shape.
Note: It would be convenient if there was a way to control UI element values via script (e.g. if I wanted to constrict the pinch height to be within the total height).
Note: Again, I found it helpful to use small helper functions to handle affine transformations. The Transform class in Rhino requires anchor points or using Euler angles etc. [Transform Structure] and I found it simpler to just write my own.
Next, I have to loft the curves to create a surface that I can then offset to create a printable 3d geometry. This is what one possible result looks like using the simple circle curves.
I want to add more complexity (because let’s be honest that’s the fun part) and have been a little frustrated just grappling pipeline issues. I want the opening to have a floral shape (as discussed above). I used the function
z = sin(xy) and let the user control the leaf amplitude. My python script generates control points for a set of lofted curves where the opening is a parametrized curve.
Here is an example of the result along with the script I wrote. I wrote a small function that constructs closed curves to loft from a series of points. Please note all my code is available at the links indicated above.
I wanted to twist the curves around to create a more interesting effect at the pinch but I had trouble converting between the base / pinch / open objects represented are GUIDs and accessing the underlying geometry to transform… after spending quite a while on this step, I realized that I could accomplish the same task either through Rhino.Common or the Rhino.Python rhinoscriptsyntax API but using both is not a great idea. I ended up using the rhinoscriptsyntax API for this project. Figuring how to toggle between the GUID and the underlying geometry would let a user use both APIs at the same time.
Step 3: STEP THREE [Combining Base and Neck]
To print a single reliable object, I have to combine the geometry of the completed neck and base. I’ve been stuck at this step for several hours so I reached out to Jennifer for some help.
She pointed out a few issues in my representation!
- I had open breps (boundary representations). This was due to the fact that I was switching between representations and when I generated a curve using a list of points in python I wasn’t closing my curve since I wasn’t including the first point as the last point to create a circular list. Fixing this generated a closed brep for my rail revolution and the base of my structure.
- The geometry ended in a point for my original lip curve. This lead to an edge with the thickness of a point that would only be very challenging to fabricate but could also contribute to the boolean union operation silently failing. Fixed this too.
- I was using the offset surface component to create a puffed out surface from my lofted curve. This was a very complex shape that had two issues. First the union could be failing due to the overall complexity of the shape. Jennifer came up with a solution that involved scaling down the curve and creating two lofted curves, capping them, and then using a solid difference to create a solid shape.
- As I mentioned there was one more issue. Jennifer pointed out that simple intersections are better for performing a union operation and suggested doubling the base to create a flat edge on the neck to intersect the base. This looked a little like a smooth bevel.
- At this point we were able to union the simple version of the object! Very exciting. However this was just a toy design to test the pipeline… I’ll get into issues with that in the next step…
Step 4: STEP FOUR [Troubleshooting & Takeaways]
I still need to troubleshoot my printer but I wanted to finish the design component (I realize this might also be a personal choice due to experience and comfort working on my computer as opposed to troubleshooting physical production). In any case, I thought I didn’t have far to go with fixing up my design and getting it ready to print (that was not the case).
Because I was using an undulating hyperbolic curve as my opening, scaling the object down led to two lofted curves that intersected each other. I thought I could solid union the two curves twice to create a top and bottom part. The result however was a 1 point thick intersection that could not support the upper structure or intersect to create a single solid object using a solid union.
Next I tried to create two lofted curves that would slope gracefully towards the same edge. This did result in a solid but again there was an edge (the opening) with a 1 point thickness. My model looked great but opening it up in Cura showed that it wouldn’t be fabricated (you can see an image of how it sliced to check out the outcome).
So then I thought it might be possible to just use the loft command to create a surface by wrapping the curve around itself going from the start (this was the added lip to create a flat intersection surface) to the base to the pinch to the top to a raised top back to the small pinch back to a small base back to a smaller start and then capping the result to create a solid. This worked! However at this point the union failed again (not sure why).
Slicing this in Cura revealed another issue. Because of the Cap component (or of course the way I was using it), the hole for the stems did not persist and was filled in. Also another issue presented itself -- I was using a new model with the pinch height above the opening (see image). This created an overhang structure that was unsupported in the print (you can check out the images of the slicing to see this for yourself). So I tried to generate a support structure but the support looked very dense to the point of not being able to remove the object itself.
Going back into Rhino and Grasshopper I removed the cap component so that the hole would persist and modified the design with the pinch below the opening so that it might rest on itself. The final result (model and slicing) is also shown. This is not a single geometric object but I think it will still print.
At this point I am out of time and still need to fix my printer. My plan is to tinker with it this evening and hopefully have a print to share later in the week.
Even though this week’s assignment might be considered a null result, I still feel that I have some important takeaways to share
Going between representations is challenging and it’s important to make sure you’re not introducing bugs by checking the desired input and output.
- Learning new tools is challenging and using strictly rhinoscriptsyntax or the Rhino.Common API will be helpful going forwards. This feels like the steep part of the learning curve where things feel a bit futile and then suddenly they click (e.g. using loft to create the solid wrapped around itself).
- The slicer is very helpful for visualizing and understanding the geometry in a way that is hard to eyeball in Rhino.
- This week I was pretty adamant about designing according to a preconceived idea. As a result, I developed a pipeline that ended up not really panning out for the final design and also spent a lot of time troubleshooting rather than adapting and exploring new possibilities that might have been easier to fabricate.
- The feedback cycle is a bit more involved for 3d printing. I think working more incrementally and focusing on modifying printable outputs could lead to a productive workflow where the outcomes would better match the affordances of the tools and would likely, as a result, be more aesthetically compelling.
Step 5: STEP FIVE [Physical Production]
I went back (of course). I revisited this project because I really wanted to get a print out of it. I tried to design a much smaller version of the vase insert for a cool looking shot glass / votive holder that I found. The radius was about half the size of the object shown above.
In designing the object I immediately had a couple issues. First, the inner ring of the neck went beyond the outer lip of the base so the geometry would not be fabricated. I adjusted this by creating an offset in the python component used to generate the neck. Second, I discovered I had a bug! I had to again create an edge with the thickness of a line (the base of the neck) that was hard to see until the scale had changed. Fixing this led to a successful solid union of the base and the neck!! This was a moment to celebrate.
Then in fabrication I realized I had not been mindful of the resolution of the printer! The first object had a shell that was too thin. The result was a nerve-wracking print wondering if the neck would snap in on itself (the lower part of the neck was so thin that there wasn’t a solid shell filled in).
It printed! I’m impressed with how well the geometry was handled since it is quite an organic shape. I like objects that reveal the process that was used to make them and to some extent that is clear in the imperfects and visible shell outline that shows the direction of the print. I think the picture with the glass object, 3d printed vase insert, and flowers is a cool spatial composition that shows a compelling contrast of materials, processes and durability.
I’m reprinting after adjusting my parameters. I’m making a slightly different shape with thicker walls for a larger glass. I adjusted the design so that the base hopefully will be better incorporated into the neck. I also changed out my filament to use a lighter color so hopefully the undulating surface will be more visible in the photos.
There are still issues with the prints. The overhang extrudes in air… maybe I can use a support structure or make sure the curvature is not too aggressive. Or I can create my own gcode that specifies the paths so the print better adheres to itself... maybe something to try this weekend! In any case, I’m happy with the outcomes!