Programming:
Wave Espresso Cup
20th
July 2011
The latest 3D printing project that I've taken on
is to design a cup using Shapeways'
new food-safe glazed
ceramic material.
It's been an interesting process so far, but
unfortunately not a smooth one.
The cup is based on a simple design but I wanted
it to use the possibilities of 3D printing to create a product that
wouldn't be possible (or at least practical) any other way.
In Processing I adapted a simple solver for the 2D
wave equation
that I'd found in my old Uni notes & had previously used here.
It makes a rippled outer surface for the cup by reading the
disturbances when the solution is perturbed by randomly generated
oscillators "pulling" and "pushing" on the surface, I then joined the
top,
bottom and insides to this with a handle modelled (with difficulty) in
Blender.
The wave equation solver allows the ripples to
move all the way around the cup but causes them to reflect from the top
and bottom edges; the solution is allowed to run until it
looks nice.
The code for the wave equation is quite simple:
class Wave { float[] f; float[] df; float[] d; int x,y,offset,wide,high; float average,damp; Wave(int wide, int high, float damp) { this.wide=wide; this.high=high; this.damp=damp; f = new float[wide*high]; df = new float[wide*high]; d = new float[wide*high]; } void disrupt(int posn, float val) { d[posn] = val; } void reset() { d=new float[wide*high]; } void tick() { // f=f+df y=wide*high; while(y-->0) { f[y]+=df[y]; if (d[y]!=0) f[y]=d[y]; } reset(); // df=df+ddf y=high-1; while(y-->1) { x=wide-1; while(x-->1) { offset=wide*y+x; average=(f[offset-1]+f[offset+1]+f[offset-wide]+f[offset+wide])/4; df[offset]-=0.5*(f[offset]-average); df[offset] = df[offset] * damp; } } }
public float[][] write2D() { float[][] temp = new float[wide][high]; for (int i=0;ifor (int j=0;jint o=wide*j+i; temp[j][i] = f[o]; } } return temp; } }
This class handles the data and the solver for the wave equation, you
can write the results of the matrix (found using the write2D()
method or read directly into the pixels array from f
)
Calling the tick()
method each time the draw()
method runs will cause the solution to propagate.
The implementation above will cause the ripples to
reflect from all of the sides of the space you create, if you want it
to wrap around you need to adapt the way that the average
is calculated to include array elements on the other side of the array
when you're near the edge.
Creating the model went quite well and I ended up
with a design that I was quite happy with:
The ripples on one side are quite flat and subtle,
I didn't expect these to come out. On the other side the
ripples are larger and much more obvious.
Unfortunately the cup really didn't come out as
I'd hoped.
I ordered the cup from Shapeways in their trial glazed ceramic
material, the design was intended to be a good test of the process and
hopefully to get me another nice espresso cup. What I got was
this: The
printing process works by binding a ceramic powder into a fragile,
"green", state with glue printed layer-by-layer. This is fired
and glazed to produce the final product. The layers are easily
visible on some parts of the cup where the glaze is thinner, and the
ripples are only just about visible. The other side, which should
be smoother, is not much better and, while I'd expected the small
ripples not to come out, I didn't expect it not to be smooth at all. However, Shapeways' excellent customer service came to the rescue,
they've arranged for a re-print and their production manager was keen
to express that they've learned more through the trial and feel that
they can do better than this now - I'm waiting for the result and we'll
see what comes out in the end... Please feel free to use the code above in your sketches, I'd be fascinated to know what you make with it.
|