`point(``x`, `y`, `z`)

# which will save the point into the list and return the index into this list.
# Most of the program then works using these indexes, rather than the actual point coordinates.
points = []
def point(x, y, z):
points.append( (x*SCALE,y*SCALE,z*SCALE) )
return len(points)-1
# ## Slicing the shape
# The first step is to slice the shape and get a list of squares.
# (OpenSCAD expects the points on a triangle to be clockwise when looking at them from the outside,
# so throughout the program I maintain this clockwise orientation.) Here's the square; line $\overline{P_2 P_3}$ is the part of the square that sits on the graph. The remainder of the square sits above it.
# I slice the shape into `SLICES`

slices, and output the above square for each slice.
# This is also where I convert the coordinates into point-list indexes as explained above.
def get_slices():
for x in scipy.arange(START, END, (END-START)/SLICES):
yield (
point(x, y1(x), y1(x)-y2(x)),
point(x, y2(x), y1(x)-y2(x)),
point(x, y2(x), 0),
point(x, y1(x), 0),
)
# ## Building the polyhedron
# All of these slices I have are *inside* the shape,
# which isn't the part that's visible.
# The next step is to get all of the faces of the polyhedron
# by connecting the edge of adjoining slices into quadrilaterals.
def get_faces():
slices = list(get_slices())
prev = slices[0]
# First, I make an "end cap" using the slice at the start of the shape.
# This is necessary because otherwise the end will be left 'open' if the first slice is not of size 0,
# and the shape [cannot be exported](https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/STL_Import_and_Export#STL_Export_2)
# because it is not a valid 2-manifold.
yield slices[0]
# Next I generate quadrilaterals conecting each of the sides of ajoining slices.
# Doing this is relatively simple:
# $$
# \mbox{Given slices}
# \substack {
# \square T_0 T_1 T_2 T_3 \\
# \square P_0 P_1 P_2 P_3
# }
# \mbox{, emit faces}
# \substack {
# \square T_0 P_0 P_1 T_1 \\
# \square T_1 P_1 P_2 T_2 \\
# \square T_2 P_2 P_3 T_3 \\
# \square T_3 P_3 P_0 T_0
# }.
# $$

# (Notice that they all go clockwise when facing outward.)
for this in slices[1:]:
def face(a, b): return (
this[a], prev[a],
prev[b], this[b],
)
yield face(0, 1)
yield face(1, 2)
yield face(2, 3)
yield face(3, 0)
prev = this
# The last step in making the polyhedron is to cap off the back end the same as I did with the front end (see above).
yield prev
# ## Convert quadrilaterals into triangles
# I now have a list of faces for the polyhedron. For newer versions of OpenSCAD I could just pass this list in to the `polyhedron()` function; unfortunately as I mentioned before my version of OpenSCAD only accepts a list of triangles.
# Therefore, I take each face (a quadrilateral $\square F_0 F_1 F_2 F_3$) and divide it into two triangles, $\triangle F_0 F_1 F_3$ and $\triangle F_1 F_2 F_3$. (Again, I'm being very careful to keep them in clockwise order.)
def get_triangles():
for face in get_faces():
yield (face[0], face[1], face[3])
yield (face[1], face[2], face[3])
# ## Write the file
# Finally, I print out the OpenSCAD file, which simply consists of a single call to `polyhedron()`:
print "polyhedron("
print " convexity = 1,"
print " triangles = ["
for triangle in get_triangles():
print " [{0}, {1}, {2}],".format(*triangle)
print " ],"
print " points = ["
for point in points:
print " [{0}, {1}, {2}],".format(*point)
print " ]"
print ");"
# And finally, here's what the shape looks like when it's printed out.
# In addition to the Python program linked at the top of this post,
# you can also download
# [the OpenSCAD file](shape.scad) and
# [the STL file](shape.stl).
#
#