# Drawing 3D crystal lattice with tikz/pstricks

I need to draw 3D lattice of DO3 type (Ni-Mn-Al, DO3) and more complex ones. Both TiKZ and PSTricks packages draw following objects on top of previously drawn disregarding "real" 3D position. For example, on this picture 2 red atoms on the right cover white ones, when they shouldn't.

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}[->]
\draw (0,0) -- (4,0,0);
\draw (0,0) -- (0,4,0);
\draw (0,0) -- (0,0,4);
\foreach \x in {1,2,3}
\foreach \y in {1,2,3}
\foreach \z in {1,2,3}
\draw (\x,\y,\z) circle (2pt);
\foreach \x in {1.5,2.5}
\foreach \y in {1.5,2.5}
\foreach \z in {1,2,3}
\draw[gray,very thin] (\x,\y,\z) +(-.5,-.5) rectangle ++(.5,.5);
\foreach \x in {1,2,3}
\draw (\x,1,1) -- (\x,1,3) (\x,2,1) -- (\x,2,3) (\x,3,1) -- (\x,3,3)  ;

\foreach \x in {1.5,2.5}
\foreach \y in {1.5,2.5}
\foreach \z in {1.5,2.5}
\filldraw[red] (\x,\y,\z) circle (2pt);
\end{tikzpicture}
\end{document}


It is possible, to obtain right behavior with layers or certain order of the drawing. However for complex lattices it is very difficult and depends on view angle.

• AFAIK, TikZ doesn't support a complete spatial model such as you need. You may get better results from ray-tracing software, maybe POVRay. – Brent.Longborough Feb 7 '13 at 22:53
• Another option is Asymptote. It can embed 3D models into PDFs, i.e., you could rotate the lattice when viewing the document with acroread. – Alex Feb 8 '13 at 15:54

Here's an Asymptote solution:

\documentclass{standalone}
\usepackage{asymptote}

\begin{document}

\begin{asy}[width=10cm,height=10cm]
import three;

currentprojection=perspective(300,-650,500,center=true);

// define two types of ions
surface iona = scale3(20)*unitsphere;
surface ionb = scale3(25)*unitsphere;

// surface properties and color of the ions
material White = material(diffusepen=gray(0.4),emissivepen=gray(0.6));
material Red = material(diffusepen=red,emissivepen=lightred);

// style of lines connecting ions
pen thick=linewidth(2);

for(int x=-1; x<2; ++x) {
for(int y=-1; y<2; ++y) {
for(int z=-1; z<2; ++z) {
draw(shift(100*(x,y,z))*iona,White);
}
}
}

for(int x=-1; x<2; ++x) {
for(int y=-1; y<2; ++y) {
for(int z=-1; z<2; ++z) {
if(x<1) draw(100*(x,y,z)--100*(x+1,y,z),thick);
if(y<1) draw(100*(x,y,z)--100*(x,y+1,z),thick);
if(z<1) draw(100*(x,y,z)--100*(x,y,z+1),thick);
}
}
}

for(int x=-1; x<2; x+=2) {
for(int y=-1; y<2; y+=2) {
for(int z=-1; z<2; z+=2) {
draw(shift(50*(x,y,z))*ionb,Red);
}
}
}
\end{asy}

\end{document}


To compile, first run pdflatex on the file, then asy on the generated .asy file, finally pdflatex once or twice again.

• Nice solution, but sadly I get a segmentation fault, when I try to compile your example with asy <filename>.asy. However if I use the -noprc option, i.e. asy -noprc <filename>.asy, everything goes fine. I'm using Windows 7 (64bit) and Asymptote 2.23. Is there something wrong with the code or is it my system? – Philipp Jul 2 '13 at 11:32
• @Philipp Strange, could be some bug in Asymptote 2.2x or its interplay with the asymptote LaTeX package (which adds a few lines to the above asy code). With TeXLive 2012 and Asymptote 2.15 it works fine, with 2.20 and 2.23 I also get segfaults (on Linux). Needs further investigation... – Alex Jul 2 '13 at 15:08
• Should I report it to the Asympotote people? – Philipp Jul 2 '13 at 15:21
• @Philipp Yes, this doesn't seem to be a LaTeX problem. The segfault occurs for pdf with prc, other output formats work as expected. – Alex Jul 2 '13 at 16:06
• I reported the bug and it has been fixed recently. With Asymptote version 2.24 everything should be fine again. – Philipp Jul 14 '13 at 2:36