3D Graphics in Mathematica

Christopher Hanusa (chanusa@qc.cuny.edu)
10 October 2017

Graphics3D objects

Since we’re discussing 3D printing, we will focus on 3D graphics objects.  2D graphics work similarly but are slightly different.

Syntax

When you are constructing graphics, you build them piece by piece by creating a list of Graphics primitives.  There are many primitives.  When you want to generate a visual representation of your primitives, wrap the list in a Graphics3D command.

Geometry

To make your graphics, it will take quite a bit of thinking and strategizing.  The most important thing to understand is that we will be placing 3D objects using Cartesian coordinates.  [Think: (x,y) in 2D or (x,y,z) in 3D.]  You will need to plan out the positions of all the points.  I have found that I have needed to use trigonometry more than I expected.  For example, this is helpful for placing points on a circle.

Modifying primitives

There are many many properties, settings, and options available for graphics Objects.  We’ll cover a few, but use the Documentation Center to learn more.

Show

If you have multiple graphics that you’d like to combine together, use the Show command to display them all at the same time.  The most important aspect of the Show command is that the combined object inherits the settings of the first graphic.

0D objects in 3D: Points

A point is a zero-dimensional object; generate one using the Point command.

Point[{0,0,0}]

Remember that all graphics primitives need to be included in a Graphics3D command to be displayed.

Graphics3D[Point[{0,0,0}]]

Graphics3D only takes as an input ONE object, so when you have more than one primitive to display, put them in a list.

Graphics3D[{Point[{0,0,0}],Point[{1,1,1}]}]

The Map command may come in handy.
Here we use Map to apply Point to many coordinate pairs.

pointlist={{0,0,0},{1,1,0},{2,0,0},{3,1,0},{4,0,0},{5,1,0},{6,0,0},{7,1,0},{8,0,0}};
Graphics3D[Map[Point,pointlist]]

Color!

Certain colors are predefined in Mathematica like Red, Orange, Yellow, etc.  
Furthermore, you can create any color using, among others, Hue, RGBColor, and Blend. 
And you make colors lighter and darker using Lighter and Darker.
You can see the colors that are available in guide/Colors.

You change color by putting the color’s name before the primitive.

Graphics3D[{Red,Point[{0,0,0}]},ImageSize->Tiny]

I suggest using braces to delimit where the color applies.  
Here I have included the option PointSize, which specifies the size of the point.

Graphics3D[{PointSize[.2],
{Lighter[Red],Point[{0,0,0}]},
{Orange,Point[{1,0,0}]},
{Darker[Yellow], Point[{2,0,0}]}
},ImageSize->Small]

You can use the command Hue is to make a rainbow of colors.

?Hue

Hue takes as input any number from zero to one.
Here you can see that we place a point at {i,0} with color Hue[i/7].

Graphics3D[{PointSize[.05],
Table[{Hue[i/7],Point[{i,0,0}]},{i,0,7}]
}]

We can also change how transparent the shape is using the Opacity command.

Graphics3D[{PointSize[.05],
Table[{Hue[i/20],Opacity[i/20],Point[{i,0,0}]},{i,0,20}]
}]

1D objects in 3D: Line segments

To create line segments, use the Line command.  The input is a list of coordinates of initial, intermediate, and terminal vertices of the sequence of line segments you wish to display.
Remember that all graphics objects need to be included in a Graphics3D command to be displayed.

Line[{{0,0,0},{1,1,1}}]

Graphics3D[Line[{{0,0,0},{1,1,1}}]]

Using a list of points as the input to Line creates a path of line segments.

Graphics3D[Line[pointlist]]

PlotRange

By default, the line segments are displayed without axes or identifying markers.  So if you display the line segment from (0,0) to (1,1) it looks the same as the segment from (1,0) to (2,1).

{Graphics3D[Line[{{0,0,0},{1,1,1}}]],Graphics3D[Line[{{1,0,0},{2,1,1}}]]}

To rectify that, use the PlotRange and Axes options.
Here is some code that will display a line segment in the window [-2,2]×[-2,2]×[-2,2], displaying axes:

{
Graphics3D[Line[{{0,0,0},{1,1,1}}],PlotRange->{{-2,2},{-2,2},{-2,2}},Axes->True],
Graphics3D[Line[{{1,0,0},{2,1,1}}],PlotRange->{{-2,2},{-2,2},{-2,2}},Axes->True]
}

3D Primitives for Points and Lines

Let’s turn these 0D and 1D objects into 3D objects so we can print them!

Spheres

To display a point in space, you can use the Point command, but instead you probably want to use the Sphere command.

?Sphere

Graphics3D[Table[Sphere[{i,0,0},.2],{i,0,10}]]

Tube

To display a line in space, we can use the Cylinder command or the Tube command.

?Tube

zigzag=Graphics3D[Tube[pointlist,.2]]

Export-Import. Bank!

Exporting is easy.

It is very easy to export from Mathematica into many different file types.  Use the command Export!

?Export

Because I’ve named the object above, I can just include it in this command here.

Export[NotebookDirectory[]<>"zigzag.png",zigzag]

The extension of the file that you use tells Mathematica which file format you want to export to.

And then you can see what you’ve exported using Import.

Import[NotebookDirectory[]<>"zigzag.png"]

Exporting is not easy.

When you want to create a 3D-printable model, you will want to export it to one of the 3D model types, such as STL.

Export[NotebookDirectory[]<>"zigzag.stl",zigzag]

Import[NotebookDirectory[]<>"zigzag.stl"]

Notice anything?

Notice this

What Mathematica exports doesn’t match with its visualization.  We’ll need to manually add the spheres.  (Use Map!)

To add the spheres, recognize that we want to add spheres of the same radius as the radius of our tube.

spheres=Map[Sphere[#,.2]&,pointlist]
segments=Tube[pointlist,.2]
newZig=Graphics3D[{spheres,segments}]

Export[NotebookDirectory[]<>"newZig.stl",newZig]

Import[NotebookDirectory[]<>"newZig.stl"]

Exporting in color

The STL format does not support color, so we’ll want to use another format (like X3D or WRL) if we want to have a 3D model with some color.

colorZig=Graphics3D[{Red,segments,Blue, spheres}]

Export[NotebookDirectory[]<>"colorZig.x3d",colorZig]

Export[NotebookDirectory[]<>"colorZig.wrl",colorZig]

Import[NotebookDirectory[]<>"colorZig.x3d"]
Import[NotebookDirectory[]<>"colorZig.wrl"]

I like to upload my models to Sketchfab.

Take Home: Hypercube

Today we will make a hypercube to take home.
Build it piece by piece!

Vertices

First let’s figure out the coordinates of the corners.

outervertices=Tuples[{-1,1},3]

ratio=.7
innervertices=ratio*outervertices

radius=.1;
Graphics3D[{
{Blue,Map[Sphere[#,radius]&,outervertices]},
{Green,Map[Sphere[#,radius]&,innervertices]}
}]

Connecting Edges

edgethickness=.05;
connectors=Map[Tube[#,edgethickness]&,Transpose[{outervertices,innervertices}]]

Graphics3D[{
{Blue,Map[Sphere[#,radius]&,outervertices]},
{Green,Map[Sphere[#,radius]&,innervertices]},
{Blend[{Blue,Green}],connectors}
}]

Outer Edges

outeredges=Table[Tube[{{-1,i,j},{1,i,j}},edgethickness],{i,-1,1,2},{j,-1,1,2}]

Graphics3D[{
{Blue,Map[Sphere[#,radius]&,outervertices]},
{Green,Map[Sphere[#,radius]&,innervertices]},
{Blend[{Blue,Green}],connectors},
{Yellow,outeredges}
}]

outeredges={
Table[Tube[{{-1,i,j},{1,i,j}},edgethickness],{i,-1,1,2},{j,-1,1,2}],
Table[Tube[{{i,-1,j},{i,1,j}},edgethickness],{i,-1,1,2},{j,-1,1,2}],
Table[Tube[{{i,j,-1},{i,j,1}},edgethickness],{i,-1,1,2},{j,-1,1,2}]
}

Graphics3D[{
{Blue,Map[Sphere[#,.1]&,outervertices]},
{Green,Map[Sphere[#,.1]&,innervertices]},
{Blend[{Blue,Green}],connectors},
{Yellow,outeredges}
}]

Inner Edges

inneredges={
Table[Tube[ratio{{-1,i,j},{1,i,j}},edgethickness],{i,-1,1,2},{j,-1,1,2}],
Table[Tube[ratio{{i,-1,j},{i,1,j}},edgethickness],{i,-1,1,2},{j,-1,1,2}],
Table[Tube[ratio{{i,j,-1},{i,j,1}},edgethickness],{i,-1,1,2},{j,-1,1,2}]
}

Graphics3D[{
{Blue,Map[Sphere[#,radius]&,outervertices]},
{Green,Map[Sphere[#,radius]&,innervertices]},
{Blend[{Blue,Green}],connectors},
{Yellow,outeredges},
{Blend[{Yellow,Orange}],inneredges}
}]

All together

ratio=.5;
radius=.2;
edgethickness=.05;
outervertices=Tuples[{-1,1},3];
innervertices=ratio*outervertices;
connectors=Map[Tube[#,edgethickness]&,Transpose[{outervertices,innervertices}]];
outeredges={
Table[Tube[{{-1,i,j},{1,i,j}},edgethickness],{i,-1,1,2},{j,-1,1,2}],
Table[Tube[{{i,-1,j},{i,1,j}},edgethickness],{i,-1,1,2},{j,-1,1,2}],
Table[Tube[{{i,j,-1},{i,j,1}},edgethickness],{i,-1,1,2},{j,-1,1,2}]
};
inneredges={
Table[Tube[ratio{{-1,i,j},{1,i,j}},edgethickness],{i,-1,1,2},{j,-1,1,2}],
Table[Tube[ratio{{i,-1,j},{i,1,j}},edgethickness],{i,-1,1,2},{j,-1,1,2}],
Table[Tube[ratio{{i,j,-1},{i,j,1}},edgethickness],{i,-1,1,2},{j,-1,1,2}]
};
hypercube=Graphics3D[{
{Blue,Map[Sphere[#,radius]&,outervertices]},
{Green,Map[Sphere[#,radius]&,innervertices]},
{Blend[{Blue,Green}],connectors},
{Yellow,outeredges},
{Blend[{Yellow,Orange}],inneredges}
}]

Export it!

Export[NotebookDirectory[]<>"hypercube.stl",hypercube]

Import["C:\\Users\\Chris\\Dropbox\\Research\\talks\\1710_3DDesign\\hypercube.stl"]

Bonus take home: A polyhedron of your choice.

PolyhedronData

A polyhedron can be thought of as the three-dimensional analog of a polygon.  (And the plural of polyhedron is polyhedra!!)  The corners are called vertices, line segments connecting vertices are called edges, and the 2-D polygons are called faces.  Mathematica has a large number of built-in polyhedra, accessible using the command PolyhedronData.

Length[PolyhedronData[All]]

For example, here is a visualization of the 20-sided polyhedron called an icosohedron.

Graphics3D[{PolyhedronData["Icosahedron","GraphicsComplex"]}]

Copied directly from the Mathematica Documentation Center, here is an explorer of the polyhedra that Mathematica has built in along with their properties:

Manipulate[Column[{PolyhedronData[g],PolyhedronData[g,p]}],{g,PolyhedronData[All]},{p,Complement@@PolyhedronData/@{"Properties","Classes"}}]

We can use the information from Mathematica to make our own 3D model of a polyhedron.

outervertices=PolyhedronData["CubeTwoCompound","Vertices"]

polyedges=PolyhedronData["CubeTwoCompound","Edges"]

polyedges[[1]]

outervertices[[polyedges[[1]]]]

Tube[outervertices[[polyedges[[1]]]],edgethickness]

Map[Tube[outervertices[[#]],edgethickness]&,polyedges]

ratio=.5;
radius=.1;
edgethickness=.05;
(* We've changed how we get our outervertices. *)
outervertices=PolyhedronData["CubeTwoCompound","Vertices"];
innervertices=ratio*outervertices;
connectors=Map[Tube[#,edgethickness]&,Transpose[{outervertices,innervertices}]];
(* We've changed how we get our outer edges, and our inner edges. *)
outeredges=Map[Tube[outervertices[[#]],edgethickness]&,polyedges];
inneredges=Map[Tube[innervertices[[#]],edgethickness]&,polyedges];
hyperpoly=Graphics3D[{
{Blue,Map[Sphere[#,radius]&,outervertices]},
{Green,Map[Sphere[#,radius]&,innervertices]},
{Blend[{Blue,Green}],connectors},
{Yellow,outeredges},
{Blend[{Yellow,Orange}],inneredges}
}]

Export[NotebookDirectory[]<>"hyperpoly.stl",hyperpoly]

Import[NotebookDirectory[]<>"hyperpoly.stl"]

Challenge Question

Recall from the previous section that the following code that makes a 3D grid of balls

coords=Flatten[Table[{i,j,k},{i,0,3},{j,0,3},{k,0,3}],2];
balls=Map[Sphere[#,.2]&,coords];
Graphics3D[balls,ImageSize->Tiny]

Add in the necessary lines to make it into a grid.