Using Mathematica for 3D Printing

Construct3D 2018

matsumoto.gatech.edu

Introduction

Today we will be working with built-in Mathematica graphics functions: Graphics[] and RegionPlot[] (and their 3D counterparts Graphics3D[] and RegionPlot3D[]). Graphics3D[] is the main Mathematica format for 3D graphics. It has a series of built-in primitives for objects such as spheres, cones, tubes, etc. For more information go to the Documentation Center, click Visualization and Graphics, then select Symbolic Graphics Language. This contains a list of functions that work with Graphics[] and Graphics3D[]. RegionPlot[] and RegionPlot3D[] use Boolean operations to determine which part of the plane will be colored and which will be left blank.

Graphics3D[] primitives

Let’s begin with the native Mathematica graphics language and Graphics3D[].

First, we’ll have a look at some of the default functions in Graphics3D[]. Primitives in Graphics3D[] and its 2D analog Graphics[] include Line[], Point[], Polygon[]. There are some 2D only graphics primitives as Disk[], Circle[] and Rectangle[]. Some have 3D analogues, eg. Sphere[] and Cuboid[]. As an input, Graphics3D[] takes a list of graphics primitives. We will explore the graphics primitives in the following examples in detail.

If you would like to change the orientation of the 3D view, you can click the graphics and rotate the orientation of the bounding box.

Sphere[] and Cuboid[]

Sphere[] works the same way as Circle[], where center and radius must be specified. However, there are a few differences between the two functions. Sphere[{(Subscript[pt, 1]),(Subscript[pt, 2]),...},r] gives a collection of spheres located at points {(Subscript[pt, 1]),(Subscript[pt, 2]),...}. Ellipsoid[pt,{(Subscript[r, 1]),(Subscript[r, 2]),(Subscript[r, 3])}] is the function that gives an ellipsoid with semiaxes r(Subscript[, i]).

The following code gives 5 pseudo-randomly placed spheres of radius r=0.1

Graphics3D[Sphere[Table[{RandomReal[{-1,1}],RandomReal[{-1,1}],RandomReal[{-1,1}]},{i,5}],0.1]]

Ellipsoid[] and Ball[] also represent n-dimensional ellipsoids and balls for computational geometry. Note: In 2D, Ball[{x,y},r] is equivalent to Disk[{x,y},r].

Graphics3D[{Ball[{0,0,1},.5],Ellipsoid}]

Graphics[{Ball[{0,0},.5],Disk[{1,0},.5]}]

Ellipsoid[]

Cuboid[{(Subscript[p, min]),(Subscript[p, max])}] gives a d-dimensional, axis aligned box with lower corner (Subscript[p, min]) and upper corner (Subscript[p, min]).

Graphics3D[Cuboid[{-1,-1,-1},{1,1,1}]]

Graphics[Cuboid[{-1,-1},{1,1}]]

Line[]

In Graphics3D[], Line[] is a 1D object, but Tube[] is a 3D version of the same object. Tube[] creates the union of a series of cylinders around each line segment. Tube[pts,r] takes two inputs, a list of points, pts, and the tube radius, r.

Graphics3D[Tube[{{1,1,-1},{2,2,1},{3,3,-1},{4,4,1}},0.1]]

Default options in Tube are to have spherical caps and spherical joins between line segments. You can change these to having a different cap styles (eg. CapForm[“Butt”], CapForm[None] would produce flat disk caps or no caps, respectively) or join styles (eg. JoinForm[“Bevel”], JoinForm[“Miter”], JoinForm[“Round”].

The radius of the tube can also be changed along the length of the line. It uses a cone to interpolate between points with different radii.

Graphics3D[Tube[{{1, 1, -1}, {2, 2, 1}, {3, 3, -1}, {4, 4, 1}},{0.1,0.2,0.3,0.4}]]

Arrow[] is also a wrapper of Tube[]. And the Arrowhead will default to a cone.

Exercise: Using Tube[], create a closed circle in the y-z plane.

The points can be generated programmatically instead of typed explicitly. To do this we will use the function Table[]. To start with, let’s treat a set of points as a regular line plot {x,y=f(x)}. Table uses the following syntax: Table[f[i],{i,(Subscript[i, min]),(Subscript[i, max])}], which creates a list {f[(Subscript[i, min])],f[(Subscript[i, min])+1],f[(Subscript[i, min])+2],...,f[(Subscript[i, max])-1],f[(Subscript[i, max])]}. If you want a step size that is different than 1, say δi, this is specified by Table[f[i],{i,(Subscript[i, min]),(Subscript[i, max]),δi}].

The following creates two plots of y=(x^2) at different resolutions:

pts=Table[{i,(i^2)/4,0},{i,0,4}];
Graphics[Line[pts]]

pts=Table[{i,(i^2)/4,0},{i,0,4,0.1}];
Graphics[Line[pts]]

Note: the semicolon suppresses printing the results of pts. You can print the answer by deleting the ;.

Try changing the function y=f[x] to see how the functions vary. What happens with Sin[i] and Cos[i]? Does the step size matter? Can you think of a way to modify the functions so that you capture an entire period of each function?

Arrow[] is a wrapper for Line[]. It takes the same inputs, but adds a graphical arrow at the end. Try changing Line[] to Arrow in the above examples.

The following creates two plots of y=(x^2), z = sin[π x] at different resolutions:

pts=Table[{i,(i^2)/4,Sin[π i]},{i,0,4}];
Graphics[Line[pts]]

pts=Table[{i,(i^2)/4,Sin[π/i]},{i,0,4,0.1}];
Graphics[Line[pts]]

Polygon[]

Next we will use Polygon[]. Polygon[] takes the same input as Line[], but converts it to a solid object by joining the first and last elements of the list of points.

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

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

As with Line[] the order of points matters. The following is the same as the last with the 2nd and 3rd points switched.

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

Turn the butterfly into an hourglass. Can you create a set of coordinate for Polygon[] that switches the black and white triangles in the previous example?

Polygon[] in Graphics3D[] behaves exactly as it does in 2D. For example, a regular tetrahedron can be given by:

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

Exercise: Make a square pyramid using Polygon[].

GraphicsComplex[]

My favorite graphics primitive is GraphicsComplex[]. This is the basic unit that almost all built-in Mathematica 2D and 3D function graphing objects are based upon. This is extremely useful for 3D printing, because automatically generated mesh objects are computationally challenging and frequently contain problems. GraphicsComplex[] contains the information necessary to export a successful mesh.

GraphicsComplex[] takes as input a list of points and applies a series of graphics primitives to them -- referencing them by the order the point appears in the list.

pts=Table[15{Cos[t],Sin[t],0},{t,0,4π,4π/5}];
Graphics3D[GraphicsComplex[pts,{Green,Thick,Line[{1,2,3,4,5,6}],PointSize[Large],Red,Point[{1,2,3,4,5}]}]]

GraphicsComplex[]

Exercise: Consider the 8 vertices of a cube pts={{0,0,0},{1,0,0},{0,1,0},{0,0,1},{1,1,0},{1,0,1},{0,1,1},{1,1,1}}. Using GraphicsComplex[], create the skeleton of a cube using Line[] and fill in the faces using Polygon[].

There are many ways of creating a simple cubic lattice in Mathematica. One way is to create a single sphere at the origin and translate it to integer coordinates {x,y,z}. To do this we will use Table[] and Translate[].

Graphics3D[Table[Translate[Sphere[{0,0,0},.1],{i,j,k}],{i,0,2},{j,0,2},{k,0,2}]]

Exercise: Use GraphicsComplex[], to place spheres of radius r=0.1 at the same values as in the previous example. (Hint: GraphicsComplex[] only takes a single list of points (with three numeric values). If you use Table[] to generate these points, you will likely end up with a 3×3×3 array of points. Look up Flatten[] in the Help directory to get a list of points that has the right array shape.)

Exercise: Using the same points for GraphicsComplex[] you generated in the previous example, use Tube[] to join the nearest neighbor spheres together, creating a ball-and-sphere model of a molecular crystal with simple cubic symmetry.

3D Transformations

3D affine transformations exactly the way 2D ones do (the only exceptions are rotations, which we will go into detail in the next slide):
M=(({{a, b, c, (Subscript[x, 0])}, {d, e, f, (Subscript[y, 0])}, {g, h, i, (Subscript[z, 0])}, {0, 0, 0, 1}}))

m={{1,0,0},{0,1,0},{0,0,1}};
v={1,0,0};
Graphics3D[{{ExampleData[{"Geometry3D","Triceratops"}][[1,2]]},{Green,GeometricTransformation[ExampleData[{"Geometry3D","Triceratops"}][[1,2]],{m,v}]}}]

The above is an example that shows the original mesh in white (Mathematica Phong shading) and the transformed Triceratops in green.

Exercise: experiment with the above transformations. Can you figure out how to do rotations? Try concatenating transformations to see their overall effect on the object.

More Mathematica transformations

Mathematica has simplified several of the transformations. I find that the most useful are Rotate[] and Translate[] when working with mechanisms.

Translate[g,v] takes in a graphic g and translates it by the vector v. (Note: in Graphics3D[], v needs 3 components and in Graphics[], v needs 2.)

Exercise: Try substituting Translate[] for the v vector in GeometricTransformation[] in the previous example. You should be able to achieve the same results using either function.

Rotation matrices behave slightly differently in 2 and 3 dimensions. 
In 2D, a rotation matrix R=(({{cos(θ), -sin(θ)}, {sin(θ), cos(θ)}})) takes a planar object and rotates it anticlockwise by θ radians.
In 3D, we need to specify an axis about which to rotate.

Rotations about the x-, y- and z-axes are given by:
(Subscript[R, x])=(({{1, 0, 0}, {0, Cos[θ], -Sin[θ]}, {0, Sin[θ], Cos[θ]}}))
(Subscript[R, y])=(({{Cos[θ], 0, -Sin[θ]}, {0, 1, 0}, {Sin[θ], 0, Cos[θ]}}))
(Subscript[R, z])=(({{Cos[θ], -Sin[θ], 0}, {Sin[θ], Cos[θ], 0}, {0, 0, 1}}))

Rotate[] makes rotations in 2D and 3D easy, compared with manipulations directly with the matrices. The syntax is as follows:
Rotate[g,θ] gives a 2D rotation of the graphic g by θ radians about the origin.
Rotate[g,θ,{x,y}] gives a 2D rotation of the graphic g by θ radians about the point {x,y}.
Rotate[g,θ,w] gives a 3D rotation of the graphic g by θ radians about the vector w anchored at the origin.
Rotate[g,θ,w,{x,y,z}] gives a 3D rotation of the graphic g by θ radians about the vector w anchored at the point {x,y,z}.

RotationMatrix[] returns the rotation matrix for the above transformations. (It’s syntax is the same, except that the graphic g is omitted.)

Exercise: Use Rotation[] to manipulate the triceratops graphics.

Boolean Operations and Graphics

Boolean operations in logic use the operations And[] (&&) Or[] (||) and Not[] (!) to create complex logic statements. In vector graphics and CAD programs there are a series of operations that take two shapes as inputs and return a variety of new shapes.

In CAD, Union is the same as the logical operation A or B -- or in shorthand: A || B. Intersection is equivalent to A and B -- or in shorthand: A && B. Subtract is A and not B -- or in shorthand: A && !B. In Mathematica, this is equivalent to the function !Implies[A,B]. Difference is (A And Not[B]) or (B and Not[A]) -- or in shorthand: (A && !B) || (B && !A). In Mathematica, this can be simplified to the function Xor[A,B]. (To look up the conversion between built-in Mathematica functions and Boolean operations, you can use the function BooleanConvert[BuiltInFunction[A,B]].)

RegionPlot[]

To create a half-plane using RegionPlot, write the equation of a line (eg. x=0) and convert it to an inequality (eg. x>0). RegionPlot[f[x,y],{x,(Subscript[x, min]),(Subscript[x, max])},{y,(Subscript[y, min]),(Subscript[y, max])}] takes two inputs, the set of inequalities f[x,y] and the variables and range over which the plot will be drawn.

RegionPlot[x>0,{x,-1,1},{y,-1,1}]

Experiment with changing the domain of the plot. How does this change the plot? What happens if you switch {x,-1,1} with {y,-1,1}?

Try turning equations for a line of the form (y = m x + b) or y-(Subscript[y, 0])=m(x-(Subscript[x, 0])) into inequalities. Combine these together using And[], Or[], and Not[] to create complex regions. Note: the order of these operations can matters!

RegionPlot[(y<x&&y>x-1)||y>x+1,{x,-1,1},{y,-1,1}]

Exercise: Create a square of side length 2 centered at the origin.

Exercise: What is the implicit equation for a circle? How can you turn that into a solid disk of thickness = 0.1using RegionPlot[]?

Exercise: Recreate the four CAD Boolean operations in RegionPlot.

RegionPlot3D[]

RegionPlot3D[] is the 3D analog of RegionPlot[].

RegionPlot3D[(x^2)+(y^2)<1&&-1<z<1,{x,-1,1},{y,-1,1},{z,-1,1}]

In the previous example, the corners of the cylinder aren’t smooth. The detail in the model can be increased by increasing the number of boxes RegionPlot3D[] searches for a solution. This can be done by adding the option PlotPoints->n in RegionPlot3D[]. Note: this will also increase the run time dramatically.

RegionPlot3D[(x^2)+(y^2)<1&&-1<z<1,{x,-1,1},{y,-1,1},{z,-1,1},PlotPoints->150]

Exercise: Create a cube using RegionPlot3D[].

Exercise: Suppose you wanted to round the corners of the cube. What set of logical operations would you use? Try this in 2D to see if you can round the corner of a square.

RegionPlot3D[] Project

Exercise: Use RegionPlot3D[] along with equations for planes, spheres and cylinders to create a Jack-o-Lantern face.

Parametric Plots

There are many ways to define graphics using mathematical functions in CAD programs. 
(1) Explicit: y=f(x) (e.g. a line y=m x+b)
(2) Implicit: f(x,y)=0 (e.g. a circle (((x-a))^2)+(((y-b))^2)=r)
(3) Parametric: {x=f(t), y=g(t)} (e.g. a line {x=(Subscript[x, 0])+a t, y=(Subscript[y, 0])+b t}, or a circle {x=a+r Cos[t], y=b+r Sin[t]})

Parametric functions are great for use in CAD because they do not depend explicitly on choice of coordinates. Curves defined using explicit or implicit functions do not lend themselves to geometric transformations: translations, rotations and scaling. These are very easy using parametric equations. (Note: it is always possible to write an explicit function as a parametric function using {x=t,y=f(t)}.)

ParametricPlot[]

In Mathematica, ParametricPlot[{f[t],g[t]},{t,(Subscript[t, o]),t(Subscript[, f])}] takes as inputs functions for x=f[t] and y=g[t]. It also asks for the range of t’s over which the plot is evaluated.

For example, Lissajous figures are a family of curves given by {x=a Cos[l t], y= b Sin[m t+p],c Sin[n t+q]}, where n and m are constants that describe the number of lobes of the figures.

ParametricPlot3D[{3 Cos[3 t],2 Sin[2t+.25],2Sin[6t+.75]},{t,0,2 π}]

Experiment with changing the values of {l, m,n},{a,b} and {p,q}. What happens if n is a multiple of m?

ParametricPlot3D[] - Curves

ParametricPlot3D[] can create two types of 3D objects. A 3D curve and a 3D surface.

For 3D curves, specify three coordinates for a curve (OverVector[γ])(t)={x(t),y(t),z(t)}. 
For example: a helix can be written as (OverVector[γ])(t)={r Cos[2π t],r Sin[2π t],t}, where r is the radius.

ParametricPlot3D[{1.5 Cos[2 π t],1.5 Sin[2 π t],t},{t,0,4}]

Experiment with these functions. What modifications would you make to orient the helix along the x-axis? What happens if the radius is different for the two values? How would you change the period of repeats? Note: this will become important later when we work with screws and other mechanisms.

ParametricPlot3D[] - Surfaces

ParametricPlot3D[] can also plot parametric surfaces. A simple example would be a height function of the xy-plane, for example, the hyperbolic paraboloid.

ParametricPlot3D[{x,y,x y},{x,-1,1},{y,-1,1}]

Other surfaces might have multiple height values for the same {x,y} values and cannot be written as height functions. These can be written using parametric functions with the appropriate coordinate choice.

The helicoid is an example of such a surface. Let us modify the equation for a helix to see how this works. Imagine creating many helices with differing radii.

ParametricPlot3D[Table[{r Cos[2 π t],r Sin[2 π t],t},{r,.1,1,.1}],{t,0,4}]

Imagine making the change in radii infinitesimally small and you arrive at the equation for a helicoid
(OverVector[γ])(t,r)={r Cos[2π t],r Sin[2π t],t}

Try to plot this structure now. Let the value of r range from [0,1] and from [-1,1]. How does that change the surface.

Geometry in CAD

In order to 3D print something, it needs to be a closed mesh that has a finite volume. Previously, we’ve played with the function Tube[] in Graphics3D[]. This is an effective way to turn 1D lines into 3D closed objects. However, it often fails.

In Mathematica, using Tube[] in Graphics3D sometimes does not create a closed mesh when exporting to an STL file. There are several things you can do to fix this. One option is to add in a sphere at every vertex in your Graphics3D[Tube[]] object.

Using ParametricPlot3D[] lets Mathematica use its analytical ability to create a smooth plot. To do this, you will use the syntax, ParametricPlot3D[curve[u],{u,(Subscript[u, 0]),(Subscript[u, f])},PlotStyle->Tube[rad]].

ParametricPlot3D[{1.5 Cos[2 π t],1.5 Sin[2 π t],t},{t,0,4},PlotStyle->Tube[.1]]

You’ll note that there are now some places where the bounding box is cutting through the graphic. You can add the option PlotRange->All to fix this.

In order to thicken up surfaces, there is a secret option called Extrusion. It isn’t in the documentation, and you’ll notice that the command turns red when you type in. But this is very useful for 3D printing.

Let’s try to thicken a strip around the edge of our helicoid.

ParametricPlot3D[{r Cos[2 π t],r Sin[2 π t],t},{t,0,4},{r,.8,1},Extrusion->.2,Mesh->False]

Note that this may look a bit angular and chunky in places. You can improve this by adding the option PlotPoints->n, where n is an integer. Try n=10,20,50,100 to see how the output varies.

Try this with the hyperbolic paraboloid or any other parametric surface you like. What happens as you change the Extrusion thickness?

Lists, Tables and Part[]

If you have some extra time, play around with the Part[] function, which can be implemented using Part[array,element], array[[element]], or array[[element]].  We will be using this on Wednesday to look at how Mathematica uses Graphics[] and Graphics3D[] as a wrapper for all of its Graphics functionality.

First lets make an array:

array=Table[(Subscript[a, i,j]),{i,1,3},{j,1,3}]
array//MatrixForm

This creates a 2x2 matrix. (The latter expression shows it in standard matrix form, but this is just a wrapper.)

If we’d like to extract different components of array. To extract element (Subscript[a, i,j]), evaluate any of the following expressions:

Part[array,1,2]
array[[2,3]]
array[[3,1]]

The (i^th) row vector is given by array[[i]]:

array[[1]]

There are several ways to extract just the last two elements of the previous array.  Extracting parts m through n of an list is given by list[[m;;n]]. So apply this to an array:

array[[1,2;;3]]
array[[1,2;;]]

And the (j^th) column vector is given by array[[;;,j]]. The notation ;; means without an m or n takes all elements at that level. You can also use the word All.

array[[;;,2]]
array[[All,2]]

If you have a long or non-rectangular array, you can use Length[] or Dimensions[] to find out about the

The Part[] notation works on functions as well as arrays and lists. Let’s use GraphicsComplex from last class as an example. The following is code for the outline of a cube using GraphicsComplex[] and Tube[]. (You can check by adding Graphics3D[] around the following expression.)

cube=GraphicsComplex[{{0,0,0},{1,0,0},{0,1,0},{0,0,1},{1,1,0},{1,0,1},{0,1,1},{1,1,1}},{Tube[{{1,2,5,3,1},{4,6,8,7,4},{1,4},{2,6},{5,8},{3,7}},.1],Polygon[{{1,2,5,3},{4,6,8,7},{1,2,6,4},{1,3,7,4},{2,5,8,6},{3,5,8,7}}]}]

Extract the list of points using the following:

cube[[1]]

The graphics primitives using:

cube[[2]]

Exercise: Make a three lists that contain only the x-, y- or z-components of the list of points.

Exercise: Select all of the numbers inside the Polygon[] primitive inside the cube function.

Inside Mathematica graphics

We’ve previously used ParametricPlot3D[] and RegionPlot3D[] to generate 3D objects using mathematical functions. However, all of Mathematica’s 3D graphics objects are based upon Graphics3D[]. To see this we will explore the insides of graphics objects using the Part command.

The Part command extracts specified parts of expressions or lists. As with the Boolean operations And (&&), Or (||) and Not (!), Part has a simplified form that takes the following syntax:
expr[[i]], which extracts the (i^th) part of the expression expr. It can also be used in the following ways:
expr[[-i]] -- counts from the end
expr[[i,j,k]] -- is equivalent to expr[[i]][[j]][[k]] (which takes the (k^th) part of the (j^th) part of the (i^th) part of expr)
expr[[m;;n]] -- takes parts m through n
expr[[m;;n;;s]] -- takes parts m through n in step sizes of s (Note: if you leave m or n blank or both, it will count from the beginning or end at the end or count all elements, respectively.

Let’s use Part to play around with the inner workings of Mathematica graphics. After you evaluate the following expression, you will see a grayed out box that begins with GraphicsComplex[...] and has some undecipherable numbers in it. Click “show all”. This will print all of the commands that Mathematica uses to create the image. Scroll past the first (long) list of vertices to see this.

helicoid = ParametricPlot3D[{r Cos[2 π θ],r Sin[2 π θ],θ},{r,-1,1},{θ,-1,1}]
helicoid[[1]]

Try adding the wrapper Graphics3D[] to helicoid[[1]]. This will reproduce the original graphic.

Exercise: Change the Options in the helicoid command to see how the internals of Graphics3D[] behave. Try adding the options: Mesh->None, changing how many points are plotted, changing the color or PlotStyle.

Note: At the very end, there will be a very long list of vectors that are “VertexNormals”. These are necessary for rendering smooth looking graphics, but will not effect the mesh for printing.

Exporting (and Importing)

Most 3D printers can take either OBJ (extension .obj) or STL (aka stereolithography file, extension .stl) flies. However, it is quite common for there to be mesh errors when exporting graphics. Mathematica usually does a decent job of exporting STL files, but will not reliably export OBJs.

I've written code that should export graphics made using ParametricPlot3D[] and RegionPlot3D[]. This works only on mesh objects, which means that curves generated by ParametricPlot3D[] (even using the option Tube[]) will not work. It also will not work on Graphics3D primitives like Sphere[] or Cuboid[]. Evaluate the following function.

ObjExport[filename_String,image3D_,graphicsq_:False]:=Module[{plot=image3D,pts,polygons,npg,tri,ptsnum,ptsbyobj,tribyobj,vlist,flist,text,p},If[BooleanQ[graphicsq],pts=plot[[1,1]];polygons=Table[If[Evaluate[And@@((SameQ[Head[#],Polygon])&/@#[[i]])],#[[i,;;,1]],#[[i,1,;;,1]]],{i,Length[#]}]&[Select[Flatten[plot[[1,2]]],Head[#]==GraphicsGroup||Head[#]==Polygon&][[;;,1]]];tri=Flatten[#,2]&/@(Table[{#[[1]],#[[i]],#[[i+1]]},{i,2,Length[#]-1}]&/@#&/@#&/@polygons);ptsnum=Sort[DeleteDuplicates[Flatten[#]]]&/@tri;ptsbyobj=pts[[#]]&/@Sort[DeleteDuplicates[Flatten[#]]]&/@tri;tribyobj=Table[tri[[k]]/.Thread[ptsnum[[k]]->Table[i+If[Length[ptsnum]>1&&k>1,Length[ptsnum[[k-1]]],0],{i,Length[ptsnum[[k]]]}]],{k,Length[ptsnum]}];vlist=(StringJoin@@("v "<>ToString[#[[1]]]<>" "<>ToString[#[[2]]]<>" "<>ToString[#[[3]]]<>"\n"&/@(If[Abs[#]<(10^(-5)),0,#]&/@#&/@#)))&/@ptsbyobj;flist=(StringJoin@@("f "<>StringJoin[ToString[#]<>" "&/@#]<>"\n"&/@#))&/@tribyobj;text=StringJoin@@Join[{"# Mathematica export to .obj by Elisabetta Matsumoto\n\n"},#]&[Table["g object"<>ToString[i]<>"\n"<>vlist[[i]]<>flist[[i]],{i,Length[flist]}]];If[graphicsq==True,Export[filename,text,"Text"];Graphics3D[GraphicsComplex[Flatten[ptsbyobj,1],Polygon[#]&/@tribyobj]],Export[filename,text,"Text"]],Print[Null]]]

The function ObjExport[] now takes the following syntax:

ObjExport[filename,graphics] will export an the graphics object as an OBJ file to the specified filename. File names are strings, which means they need quotation marks around them and the file extension included. (The default is to export to the directory the notebook lives in.)

ObjExport[filename,graphics,True] will show you a graphical version of the mesh you are exporting.

helicoid = ParametricPlot3D[{r Cos[2 π θ],r Sin[2 π θ],θ},{r,-1,1},{θ,-1,1}]
ObjExport["helicoid_obj.obj",helicoid,True]

If you would like to export graphics primitives, like Sphere[] or Cuboid[], you can use the Printout3D[] command. This will enable you to export .stl and .obj files and load files directly to 3D print services, including iMaterialize, Shapeways, Sculpteo and 3D Hubs. This is a much more reliable way of exporting .obj files than directly using the Export[] command.

Note that Tube[] still does NOT export properly. It will create a hollow cylindrical region around the center line of the tube (and this only works for piecewise linear curves).

model=ExampleData[{"Geometry3D","StanfordBunny"}];
Printout3D[model,NotebookDirectory[]<>"bunny.stl"]

Printout3D[model,"Shapeways"]

Aside: Importing STL and OBJ files

Mathematica can also import .obj files. In order to use them as 3D graphics objects, you will need to use the property “Graphics3D”. If you don’t, you won’t be able to access the internal graphics structure.

img=Import[NotebookDirectory[]<>"augmented_dodecahedron.stl","Graphics3D"]
Graphics3D[{Red,img[[1]]}]