/** This renders a 3-D model to render a (center-only) doughnut/biscuit cutter to Wavefront .obj file format for 3-D printing. See: http://paulbourke.net/dataformats/obj/ */ // These can be altered and the model will be automatically recalculated. sides = 100 outerDiam = 1.2 cm stopDiam = outerDiam + .4 cm innerDiam = outerDiam - 1 mm cylHeight = 1.75 in cutterHeight = cylHeight + 3 mm stopHeight = 4 mm w = new Writer["DonutCutter" + format[outerDiam, cm, 2] + ".obj"] w.println["# Doughnut cutter by Frink\n"] w.println["o DoughnutCutter\n"] cylOutBottom = new array[sides] cylOutTop = new array[sides] cutterTop = new array[sides] cylInBottom = new array[sides] stopBottomOut = new array[sides] stopTopOut = new array[sides] z0 = 0 mm z1 = -stopHeight angleStep = circle/sides // The length unit u = mm for i = 0 to sides-1 { angle = i angleStep xcyl = outerDiam/2 cos[angle] ycyl = outerDiam/2 sin[angle] zt = cylHeight xcutter = innerDiam/2 cos[angle] ycutter = innerDiam/2 sin[angle] // cylOutBottom.push[[xcyl, ycyl, z0, i+1]] cylOutTop.push[[xcyl, ycyl, cylHeight, sides+i+1]] cutterTop.push[[xcutter, ycutter, cutterHeight, 2 sides+i+1]] cylInBottom.push[[xcutter, ycutter, z1, 3 sides+i+1]] xstop = stopDiam/2 cos[angle] ystop = stopDiam/2 sin[angle] stopBottomOut.push[[xstop, ystop, z1, 4 sides+i+1]] stopTopOut.push[[xstop, ystop, z0, 5 sides+i+1]] } w.println["# Vertex list \n"] w.println["\n# Cyl out bottom"] dumpVertices[cylOutBottom, w, u] w.println["\n# Cyl out top"] dumpVertices[cylOutTop, w, u] w.println["\n# Cutter top"] dumpVertices[cutterTop, w, u] w.println["\n# Cylinder inner"] dumpVertices[cylInBottom, w, u] w.println["\n# Stop top bottom"] dumpVertices[stopBottomOut, w, u] w.println["\n# Stop outer top"] dumpVertices[stopTopOut, w, u] w.println["# Face list\n"] //w.println["usemtl Default"] // Now output the faces. These should be output by vertex numbers in a // counterclockwise "out" fashion. topFace = "f" bottomFace = new array for i = 0 to sides-1 { // Cyl sides w.println["\n# Cyl sides"] [xt0, yt0, zt0, ovt0] = cylOutTop@i [xb0, yb0, zb0, ovb0] = cylOutBottom@i [xt1, yt1, zt1, ovt1] = cylOutTop@((i+1) mod sides) [xb1, yb1, zb1, ovb1] = cylOutBottom@((i+1) mod sides) w.println["f $ovt0 $ovb0 $ovb1 $ovt1"] // Cutter sides w.println["\n# Cutter sides"] [cutx0, cuty0, cutz0, cutv0] = cutterTop@i [cutx1, cuty1, cutz1, cutv1] = cutterTop@((i+1) mod sides) w.println["f $cutv0 $ovt0 $ovt1 $cutv1"] // Inner surface of cylinder w.println["\n# inner sides"] [xb0, yb0, zb0, ivb0] = cylInBottom@i [xb1, yb1, zb1, ivb1] = cylInBottom@((i+1) mod sides) w.println["f $cutv0 $cutv1 $ivb1 $ivb0"] // Bottom sides of stop. w.println["\n# Bottom sides of stop"] [xb0, yb0, zb0, sbo0] = stopBottomOut@i [xb1, yb1, zb1, sbo1] = stopBottomOut@((i+1) mod sides) w.println["f $ivb0 $ivb1 $sbo1 $sbo0"] // Sides of stop. w.println["\n# Sides of stop"] [xt0, yt0, zt0, sto0] = stopTopOut@i [xt1, yt1, zt1, sto1] = stopTopOut@((i+1) mod sides) w.println["f $sto0 $sbo0 $sbo1 $sto1"] // Upper surface of stop. w.println["\n# Upper Surface of stop"] w.println["f $sto0 $sto1 $ovb1 $ovb0"] } w.close[] /** Dump an array of vertices */ dumpVertices[array, writer, u] := { for [x,y,z] = array writer.println["v " + formatFix[x, u, 5] + " " + formatFix[y, u, 5] + " " + formatFix[z, u, 5]] }