How to make hollow polyhedra?
I'm not sure if this will print, but to get a thick wall, you could create a new graphics complex with offset and reversed faces. The surface normal is defined by the traversal direction, so reversing the order flips the normal.
base = Normal[PolyhedronData["MathematicaPolyhedron", "Faces"]];
spikey = Join[base , base /. Polygon[a_List] :> Polygon[Reverse[a] 0.9]];
Export["spikey.stl", Graphics3D[spikey]]
If you need to do some special editing around the base or top, it might be easier to do it manually, but you could also play around with doing it through mathematica prior to exporting it. The method used here (radial expansion) won't work in all cases, but you could properly make a face to wall rule that would work more generally.
Here's a procedure I use:
(* barycenter of a polygon *)
averagepoints[points_?MatrixQ] :=
Mean[If[TrueQ[First[points] == Last[points]], Most, Identity][points]]
(* Newell's algorithm for face normals *)
newellNormals[pts_?MatrixQ] := Module[{tp = Transpose[pts]}, Normalize[MapThread[Dot,
{RotateLeft[ListConvolve[{{-1, 1}}, tp, {-1, -1}]],
RotateRight[ListConvolve[{{1, 1}}, tp, {-1, -1}]]}]]]
thickenaux[points_, outer_, thick_] := Module[{center = averagepoints[points],
nrm = newellNormals[points], outerpoints, radialpoints},
outerpoints = Map[(center - thick nrm + outer (# - center)) &, points];
radialpoints = MapThread[Join[Reverse[#1], #2] &,
Map[Partition[#, 2, 1, 1] &, {points, outerpoints}]];
Flatten[{Polygon[points], Polygon /@ radialpoints, Polygon[Reverse[outerpoints]]}]]
ThickenPolygons[shape_, outer_: 0.8, thick_: 0.04] :=
shape /. Polygon[p_?MatrixQ] :> thickenaux[p, outer, thick]
The procedure is more or less a modification of the old (undocumented) package function OutlinePolygons[]
in Graphics`Shapes`
.
Let's try it out on a simpler case:
Graphics3D[{FaceForm[Cyan, Red], ThickenPolygons[
Delete[Cases[Normal[PolyhedronData["Tetrahedron"]], _Polygon, Infinity], 3]]},
Boxed -> False, Lighting -> "Neutral"]
Note that both the interior and exterior are colored with Cyan
; this is due to the code ensuring that all the polygons generated are oriented properly.
I don't know how to cut a hole in the manner shown in the Shapeways model, so I'll go for a spikey with a simpler cutaway:
Needs["PolyhedronOperations`"];
spikeyCut = Cases[Normal[Stellate[
MapAt[Delete[#, {1, 4}] &, PolyhedronData["Icosahedron"], {1, 2}],
1 + 2 Sqrt[7 - 3 Sqrt[5]]]], _Polygon, Infinity];
Graphics3D[{Directive[EdgeForm[], ColorData["Legacy", "SpringGreen"]],
ThickenPolygons[spikeyCut]}, Boxed -> False]
I set the defaults in ThickenPolygons[]
to work for tetrahedra; for other polyhedra or for parametrically-defined surfaces, you might need to play around with the values for the parameters outer
and thick
.
Here's an alternate version, which might be more suitable for polyhedra than the previous version:
thickenaux[points_, outer_, fac_] :=
Module[{center = averagepoints[points], nrm = newellNormals[points], n, outerpoints,
radialpoints, thick},
n = Length[points] - Boole[TrueQ[First[points] == Last[points]]];
thick = fac (1 - outer) Mean[Norm[# - center] & /@ points];
outerpoints = Map[(center - thick nrm + outer (# - center)) &, points];
radialpoints = MapThread[Join[Reverse[#1], #2] &,
Map[Partition[#, 2, 1, {1, 1}] &, {points, outerpoints}]];
Flatten[{Polygon[points], Polygon /@ radialpoints, Polygon[Reverse[outerpoints]]}]]
ThickenPolygons[shape_, outer_: 0.8, fac_: Sqrt[2]/4] :=
shape /. Polygon[p_?MatrixQ] :> thickenaux[p, outer, fac]
If you run this version of ThickenPolygons[]
on spikeyCut
and carefully inspect the coordinates, you'll see that the points in the inner walls match up perfectly; there are neither gaps nor unintentional polygon intersections.
The proper value of fac
to use will depend on the polyhedron being considered. For the Platonic solids ($\phi$ denotes the golden ratio),
\begin{array}{c|c} \text{polyhedron}&\class{code}{\text{fac}}\\\hline \text{cube}&\frac1{\sqrt 2}\\ \text{dodecahedron}&\frac{1+\phi}{2}\\ \text{icosahedron}&\frac{1+\phi}{2}\\ \text{octahedron}&\frac1{\sqrt 2}\\ \text{tetrahedron}&\frac1{2\sqrt 2} \end{array}
The default value used for fac
works for the tetrahedron and the spikey.
In version 11, one has ShellRegion[]
that is supposedly useful for 3D printers who want to save on material. Its performance on the spikey leaves something to be desired, tho:
Show[ShellRegion[PolyhedronData["Spikey", "BoundaryMeshRegion"], 1/20],
BaseStyle -> Opacity[0.5]]
The easiest way I have found to do this is to create the solid model in Mathematica, export it as an STL file, then hollow it out in OpenSCAD. The way you do that is with code like this:
difference() {
import("spikey.stl");
scale([.9,.9,.9]) import("spikey.stl");
}
You could then cut a hole in the shell with another difference command.