3D Printing “Spikey” Commemorative Coins with the Wolfram Language

March 14, 2019

Shenghui Yang, Developer, Wolfram|Alpha Localization Systems

I approached my friend Frederick Wu and suggested that we should make a physical Wolfram Spikey Coin (not to be confused with a Wolfram Blockchain Token!) for the celebration of the 30th anniversary of Mathematica. Frederick is a long-term Mathematica user and coin collector, and together, we challenged ourselves to design our own commemorative coin for such a special event.

The iconic Spikey is a life-long companion of Mathematica, coined (no pun intended) in 1988 with the release of Version 1. Now, we’ve reached a time in which Wolfram technologies and different 3D printing processes happily marry together to make this project possible!

Getting Started  Traditional coin-casting uses low-relief design with an orthographic projection, giving viewers the impression of a distinct 3D image with minimum model depth. Usually, the relief depth plane can be set between the front plane of the object and the vanishing plane. A low relief compresses the model in the axial direction (perpendicular to the background plane), with a scale ratio ranging from 0.02 to 0.1, a high relief from 0.1 to 0.2 and a super-high relief greater than 0.3.

I crafted a Wolfram Demonstrations Project Applet (Design Your Own Commemorative Coin) to illustrate some cool coin designs using the aforementioned orthogonal projection and 3D geometric scaling method. The user can freely set the view point, the level of relief plane and the scaling ratio.

The following image illustrates the visual effect of relief design; the gray impression on the left appears as though it were created by the Spikey punching through the coin (similar to aligning a palm with the impression after a face slap):

We can quantify the scaling effect graphically by comparing the outline of the original Spikey shape to that of the projection. Using SetOptions, we can give both shapes the same ViewPoint, PlotRange and ImageSize, additionally setting BaseStyle and Lighting so that only the 2D outline is displayed:

SetOptions[{Region},Boxed->False,ViewPoint->Top,BaseStyle->Gray,
Lighting->{"Directional",White},PlotRange->{{-2,2},{-2,2},{-2,2}},ImageSize->400];

Running the following code generates three graphics—a 2D projection of the “real” 3D Spikey object, a relief model with the same view point but “squeezed” along the central view point vector and the image pixel difference between the two shapes:

threeDim=PolyhedronData["Spikey","BoundaryMeshRegion"];
reliefDim=TransformedRegion[threeDim,ScalingTransform[.02,{0,0,1},{0,0,0}]];
Grid[{
{"real 3D object","relief model","image pixel difference"},
{#,diff=ColorNegate[ImageDifference@@#]}&[Rasterize[Region[#]]&/@{threeDim,reliefDim}]//Flatten}]

The accuracy of the model can also be analyzed numerically by measuring the pixel error in the boundary. For instance, a model compressed at scaling ratio 0.02 viewed from an angle less than 10° from the center vector produces only a 3.3% pixel error:

In other words, the relief model used 2% of the depth of the 3D object to create a 96.7% 3D effect.

Modeling the Coin  We have come a long way, but the job is not finished yet. There is some clearance between the Spikey and the coin body, so I need to fill the gap in geometry. First, I get the Spikey region model, rotating it a bit to create a non-symmetric pattern (for artistic reasons):

SetOptions[{Region},ViewPoint->Top,BaseStyle->{Pink,EdgeForm[None]},PlotRange->All,AspectRatio->1,Lighting->"Neutral",ImageSize->250];
SpikeyRegion=PolyhedronData["Spikey","BoundaryMeshRegion"];
SpikeyRegion3D=TransformedRegion[SpikeyRegion,Composition[
RotationTransform[E,{E,Pi,E}],ScalingTransform[12 {1,1,1},{0,0,0}]]];

Grid[{
{"Spikey Top View","Spikey Bottom View"},
Table[Region[SpikeyRegion3D,ViewPoint->v],{v,{Top,Bottom}}]},
BaseStyle->"Text"]

Using ConvexHullMesh, we can generate prism-like polyhedrons by stretching each triangular face along the z direction:

convexhullMesh=ConvexHullMesh[Join[#, Transpose[Transpose[#]+{0,0,50}]]]&/@MeshPrimitives[SpikeyRegion3D,2][[All,1]];
Multicolumn[convexhullMesh[[;;16]],8, ItemSize->{3,6}]

Now, use RegionUnion repeatedly to join the generated prism-like polyhedrons together. Since not all regions touch, we also need BoundaryDiscretizeRegion to help fill in the gaps. The result is a region with the front and back geometry of a Spikey, but stretched (extruded) in the z direction:

regionUnion1=Table[BoundaryDiscretizeRegion@RegionUnion@
Take[convexhullMesh,{3 (i-1)+1,3 i}],{i,20}];
regionUnion2=Table[RegionUnion@@Take[regionUnion1,{5 (i-1)+1,5 i}],{i,4}];
convexhullUnion=RegionUnion@@regionUnion2

Next we prepare a coin body with an outside protective ring. This is done by first multiplying an Annulus by a Line to get a tube-like shape:

{r1,r2}={21,23};
annulus=BoundaryDiscretizeGraphics[Graphics[Annulus[{0,0},{r1,r2}]],MaxCellMeasure->.1];
tube=BoundaryDiscretizeRegion[RegionProduct[annulus,Line[25+{{41.5},{-41.5}}]], MaxCellMeasure->Infinity]

Then we can fill the interior of the coin with a solid disk:

assembly=RegionUnion[BoundaryDiscretizeRegion[RegionProduct[
BoundaryDiscretizeGraphics@Graphics[Disk[{0,0},22.5]],
Line[25+{{7.5},{-7.5}}]], MaxCellMeasure->Infinity],tube]

Finally, we compress the 3D extruded Spikey into a relief model:

SpikeyRelief=TransformedRegion[convexhullUnion,ScalingTransform[.02,{0,0,1},{0,0,0}]]

Similarly, we compress the 3D pulled coin into a coin model. Usually, the coin ring is slightly thicker than the relief height so the outside ring can protect the relief patterns and resist abrasion. We set a slightly larger scaling factor of .03 to account for this:

Coin=TransformedRegion[assembly,ScalingTransform[0.03,{0,0,1},{0,0,0}]]

Finally, we combine the regions to make the Spikey coin model:

SpikeyCoinRegion=Show[{SpikeyRelief,Coin}]

Viewing in 3D  Let’s take a glance at the whole model. An important concept in coin design is “breakthrough” or “penetration,” i.e. the illusion that the Spikey breaks or travels through a coin plate in space and time. We can visualize this using the uncompressed convex hull data:

convexhullData=MeshPrimitives[#,2]&/@convexhullMesh;

Graphics3D[{convexhullData,Opacity[.5],Red,Cylinder[{{0,0,25-8},{0,0,25+8}},r1],Blue,Opacity[.2],EdgeForm[None],MeshPrimitives[tube,2]},Axes->True,ImageSize->{600,400}]

Using a scale ratio of 0.025, we can then compress the 3D components and combine them into a styled Graphics3D object:

scale=ScalingTransform[.025,{0,0,1}];
subject=GeometricTransformation[{convexhullData},scale];
body=GeometricTransformation[{Cylinder[{{0,0,17.5},{0,0,32.5}},r1]},scale];
ring=GeometricTransformation[{MeshPrimitives[tube,2]},scale];
coin3D=Graphics3D[
{EdgeForm[None],ColorData["Atoms"]["Au"],subject,White,body,ring},Lighting->Red,Boxed->False]

Viewing the coin from a few different angles shows the “breakthrough” effect in context. The two sides of the coin pattern look similar, but they are actually the top view {0, 0, ∞} and the bottom view {0, 0, -∞} of the same Spikey:

vp={{0,-10,4},{-10,0,4},{0,0,∞},{0,0,-∞},{-1,-.1,2},{-1,-.1,-2}};

Multicolumn[Table[Graphics3D[{EdgeForm[None],Specularity[Brown,100],ColorData["Atoms"]["Cu"],subject,LightBlue,Specularity[Red,100],body,Opacity[If[i==1||i==2,.01,0.9]],ring},
Axes->(i≤4),Boxed->(i≤4),PlotRange->Automatic,
AxesLabel->{"x","y","z"},ViewPoint->vp[[i]],ImageSize->220],{i,Length@vp}],2,Appearance->"Horizontal",Spacings->5,Alignment->Center]

3D Printing Methods and Materials To 3D print the coin, we need to start with a high-quality model. Although Graphics3D is convenient for visualizing the result, it doesn’t translate well to STL. When exporting with Printout3D, you can click to expand the “Report” element for information about the final model quality:

Printout3D[coin3D, "Coin.stl", RegionSize->Quantity[40, "Millimeters"]]

Errors in discretization can lead to a final print that looks distorted, with faces glued together:

Using Region (as outlined above) produces a more strictly defined object for higher-quality STL export:

Printout3D[SpikeyCoinRegion, "Coin.stl", RegionSize->Quantity[46, "Millimeters"]]

For a thin model, horizontal placement (i.e. with the background plane flat on the printing table) results in a poor print resolution. Vertical or tilted placement helps to increase printable layers and improve detail resolution in the relief:

FDM (Fused Deposition Modeling), the most widely used 3D printing technology, works by applying successive layers of thermoplastics. This method is low cost, but it also has a relatively low accuracy:

SLA (stereo lithography) is a 3D printing technique using ultraviolet light to cure photosensitive polymers, resulting in smoother, more accurate prints than FDM:

PBF (powder bed fusion) involves applying heat to fuse together successive layers of powdered material. This process is more accurate still—though also quite expensive—and it allows the use of metallic materials. I created a stainless steel powder print with the German EOS M 290, a million-dollar piece of equipment with advanced additive manufacturing technology:

The printed coin has a 40 mm outside diameter and a 3 mm thickness (with the thinnest region of the coin plate being only 0.5 mm), weighing about 15 grams:

As you can see from the images, the relief pattern is clearly distinguishable, with all faces achieving diffuse reflection:

Try It Yourself Although not everyone owns a 3D printer, many schools, libraries and makerspaces now offer 3D printing services at some level. The descriptions provided in this post should give you a good idea of what processes and materials will work for your print.

If you don't have access to a printer locally, you can still produce your own coin using one of the online printing services available through Printout3D:

Printout3D[SpikeyCoinRegion, "Sculpteo", RegionSize->Quantity[46, "Millimeters"]]

These services allow you to rescale your model and select from a range of printing processes and materials:

With the Wolfram Language, anyone can go from 3D model to shiny coin in no time. Give it a try—soon you could have your very own Spartan army of Spikeys: