For 3D graphics, I truly don't think it's worth the effort to attempt exporting as vector graphics. The valiant attempts to keep at least the axes and labels as vector graphics are in my opinion not something an everyday user would consider.
With PDF for 3D graphics, you're fighting two problems: not just the file size but also the slow rendering when your PDF reader has to execute a huge computation whenever the page containing the graphic needs to be displayed. The argument for vector graphics is typically that it creates smaller files because the graphic is essentially a program that runs at the time of rendering. But if that program (the PDF) just stupidly enumerates zillions points or polygons to be drawn one by one, you get the worst of both worlds: inefficient data representation with lots of data.
So I would just say: retreat to bitmaps, as Szabolcs was saying. This isn't necessarily a bad thing. Consider the example plot
a = Show[ParametricPlot3D[{16 Sin[t/3], 15 Cos[t] + 7 Sin[2 t],
8 Cos[3 t]}, {t, 0, 8 \[Pi]}, PlotStyle -> Tube[.2],
AxesStyle -> Directive[Black, Thickness[.004]]],
TextStyle -> {FontFamily -> "Helvetica", FontSize -> 12},
DefaultBoxStyle -> {Gray, Thick}]
This takes up 200 MB when exported straight to PDF. If instead I export this with
Export["wiggle.png", Magnify[a, 4]]
the file size is a reasonable 170 KB. The pixelated axes can of course be discerned if you look closely -- but so can the imperfections in the 3D plot itself that will always be there due to limited number of polygons.
The actual question was how to export to PDF, so I guess I'll answer it this way:
Export["wiggles.pdf", Rasterize[Magnify[a, 4], "Image"]]
Edit:
Unfortunately, this isn't foolproof because Magnifiy
stops magnifying when the size exceeds the width of the notebook window! If the window isn't big enough to accomodate the desired magnification, the relative scaling of fonts and graphics will be messed up.
Edit 2:
As is discussed in this related question, Magnify
will work reliably provided that you specify an explicit value for the ImageSize
option of your 3D graphics.
Edit 3:
The remaining problem with Magnify
is that it doesn't scale up tick marks properly. So I asked myself how to make @Heike's method of rasterization work automatically for Graphics3D
without having to think about the resolution and image size every time.
Of course one could write a custom export function, but in some situations it would be convenient if one could modify the standard export behavior for the entire notebook. To do this, one only has to make sure that all Graphics3D
automatically contain some part that requires an advanced version of PDF
. In particular, this is the case for polygons with vertex colors.
So to achieve rasterization by default, one could initialize the notebook with a statement like this:
Map[SetOptions[#,
Prolog -> {{EdgeForm[], Texture[{{{0, 0, 0, 0}}}],
Polygon[#, VertexTextureCoordinates -> #] &[{{0, 0}, {1,
0}, {1, 1}}]}}] &, {Graphics3D, ContourPlot3D,
ListContourPlot3D, ListPlot3D, Plot3D, ListSurfacePlot3D,
ListVectorPlot3D, ParametricPlot3D, RegionPlot3D, RevolutionPlot3D,
SphericalPlot3D, VectorPlot3D}];
This adds an invisible 2D polygon as a Prolog
to every Graphics3D
that is created in the notebook (edit: I had to explicitly do this for various wrapper functions that create Graphics3D
, such as ParametricPlot3D
). My rationale is that Prolog
isn't likely to be needed for anything else in my 3D plots under normal circumstances. Now when I try the above plot a
in a simple export command such as
Export["a.pdf",a]
I get a high-resolution image that's ready for printing.