# 3d Brillouin Zone with Asymptote: Draw outline of surface AND Bring labels to the front

I am struggling with my attempts of an fcc Brillouin zone similar to Wikipedia Brillouin zone. They have brought me to

In the code below I used polygons to draw the large surfaces. There are still many improvements I could think of (if only time and skill permitted).

One thing I would still like to add are black lines to all edges. I would be happy to do that by adding fine black lines to the borders of the hexagons (similar to \filldraw in TikZ). Defining a separate hexagonal path seems rather tedious to me...

The closest topic I could find is Draw border of a line.

By the way I will also try to bring the red lables that are still partly covered by the body to front. This can of course be done by changing their positions. But isn't there an alternative way by anything like "layers"?

My code:

\documentclass[10pt,a4paper]{standalone}

% Use this form to include EPS (latex) or PDF (pdflatex) files:
%\usepackage{asymptote}
% Use this form with latex or pdflatex to include inline LaTeX code by default:
\usepackage[inline]{asymptote}
% Use this form with latex or pdflatex to create PDF attachments by default:
%\usepackage[attach]{asymptote}

% Enable this line to support the attach option:
%\usepackage[dvips]{attachfile2}

\begin{document}

% Optional subdirectory for latex files (no spaces):
%\def\asylatexdir{}
% Optional subdirectory for asy files (no spaces):
%\def\asydir{}

\begin{asydef}
// Global Asymptote definitions can be put here.
usepackage("fixmath");
import three;
import solids;
import patterns;
settings.toolbar=false;
\end{asydef}

\begin{asy}
size(22cm, 22cm);
currentprojection=orthographic(-6,-2,1);
currentlight=light(gray(0.4),specularfactor=3,viewport=false,
(-0.5,-0.25,0.45),
(0.5,-0.5,0.5),(0.5,0.5,0.75));

triple O=(0,0,0), X=(1,0,0), Y=(0,1,0), Z=(0,0,1);
draw(O--(-2.2,0,0),black,Arrow3);
draw(O--(0,-2.2,0),black,Arrow3);
draw(O--(0,0,2.2),black,Arrow3);
label("\huge$x$",scale3(1.1)*(-2.2,0,0),black);
label("\huge$y$",scale3(1.1)*(0,-2.2,0),black);
label("\huge$z$",scale3(1.1)*(0,0,2.05),black);

//material unterfl=material(white+opacity(1),ambientpen=white);
material oberfl=material(white+opacity(0.6),ambientpen=white);

for (int n = -1; n <=1; n=n+2) {
for (int l = 1; l <=1; l=l+2) {
for (int m = -1; m <=1; m=m+2) {
draw(rotate(90*l+45*(m+1),Z)*shift(1,1,n)*rotate(aTan(sqrt(2))*n,Y-X)*rotate(15,Z)*scale3(sqrt(2))*surface(polygon(6)), surfacepen=oberfl);
}
}
}

draw(shift(-2,0,0)*rotate(45,X)*rotate(90,Y)*scale3(sqrt(2))*shift(-0.5,-0.5,0)*unitplane, surfacepen=oberfl,black+linewidth(0.2));
draw(shift(0,-2,0)*rotate(45,Y)*rotate(90,X)*scale3(sqrt(2))*shift(-0.5,-0.5,0)*unitplane, surfacepen=oberfl,black+linewidth(0.2));
draw(shift(0,0,2)*rotate(45,Z)*scale3(sqrt(2))*shift(-0.5,-0.5,0)*unitplane, surfacepen=oberfl,black+linewidth(0.2));

draw(O--(-1,-1,1),red + linewidth(2.0pt) + linetype(new real[] {2,2}));
draw(O--(0,-2,0),red + linewidth(2.0pt) + linetype(new real[] {2,2}));
draw((0,-2,0)--(-1,-2,0),red + linewidth(2.0pt));
draw((-1,-2,0)--(-1.5,-1.5,0),red + linewidth(2.0pt));
draw((-1.5,-1.5,0)--O,red + linewidth(2.0pt) + linetype(new real[] {2,2}));

label("\Huge$\Gamma$",(0,0,-0.15),red);
label("\Huge$L$",(-0.9,-1.1,1),red);
label("\Huge$X$",(0,-2,-0.15),red);
label("\Huge$W$",(-1,-2,-0.15),red);
label("\Huge$K$",(-1.5,-1.5,-0.15),red);
\end{asy}
\end{document}

• Note that the site works best when you ask one question per ... well, per question, basically. For example, I can answer the second question you ask but not the first. So either I don't bother answering (and somebody else who can only answer the first may feel the same way) or I answer part of it (and now your question has an answer, which may reduce views and which will you accept if somebody now answers the first without providing a better answer to the second?). – cfr Aug 20 '16 at 22:48
• Layers in 3d is a feature request for Asymptote, but not currently implemented. (Unless you want to use settings.render=0;, which allows you to do this because it basically gets rid of the native hidden surface removal altogether.) – Charles Staats Aug 20 '16 at 23:14
• I believe the lines of code you have for drawing hexagons can be modified slightly to draw outlines instead. Simply replace surface(polygon(6)) by polygon(6) and surfacepen=oberf1 by black+linewidth(0.2) (since that seems to be your preferred grid pen): draw(rotate(90*l+45*(m+1),Z)*shift(1,1,n)*rotate(aTan(sqrt(2))*n,Y-X)*rotate(15,Z)*scale3(sqrt(2))*polygon(6), black + linewidth(0.2)); I haven't tested this, so I could be mistaken. And I don't think you can draw the surface and the outline in the same line of code. – Charles Staats Aug 20 '16 at 23:21
• Adding path3 to your suggestions, @CharlesStaats, did the trick: draw(rotate(90*l+45*(m+1),Z)*shift(1,1,n)*rotate(aTan(sqrt(2))*n,Y-X)*rotate(15,Z)*scale3(sqrt(2))*path3(polygon(6)),black+linewidth(0.2)); Thanks very much for this and your great tutorial! – dasausTeR Aug 21 '16 at 18:47

Note that I am dabbling in Asymptote in the most superficial possible way, so this may be an entirely wrong-headed approach. On the other hand, it is from a tutorial which seems to be very well-regarded, so hopefully it is not that wrong-headed.

# Caveat emptor ...

You can use a trick from Charles Staats's Asymptote tutorial (86) to move the labels nearer to the camera, avoiding obscuring them.

\documentclass[border=10pt,multi]{standalone}
\usepackage[inline]{asymptote}
\standaloneenv{asy}
\begin{document}
\begin{asydef}
// Global Asymptote definitions can be put here.
usepackage("fixmath");
import three;
import solids;
import patterns;
settings.toolbar=false;
\end{asydef}
\begin{asy}
size(22cm, 22cm);
currentprojection=orthographic(-6,-2,1);
currentlight=light(gray(0.4), specularfactor=3, viewport=false, (-0.5,-0.25,0.45), (0.5,-0.5,0.5),(0.5,0.5,0.75));

triple O=(0,0,0), X=(1,0,0), Y=(0,1,0), Z=(0,0,1);
draw(O--(-2.2,0,0), black, Arrow3);
draw(O--(0,-2.2,0), black, Arrow3);
draw(O--(0,0,2.2), black, Arrow3);
label("\huge$x$", scale3(1.1)*(-2.2,0,0), black);
label("\huge$y$", scale3(1.1)*(0,-2.2,0), black);
label("\huge$z$", scale3(1.1)*(0,0,2.05), black);

//material unterfl=material(white+opacity(1), ambientpen=white);
material oberfl=material(white+opacity(0.6), ambientpen=white);

for (int n = -1; n <=1; n=n+2) {
for (int l = 1; l <=1; l=l+2) {
for (int m = -1; m <=1; m=m+2) {
draw(rotate(90*l+45*(m+1),Z)*shift(1,1,n)*rotate(aTan(sqrt(2))*n,Y-X)*rotate(15,Z)*scale3(sqrt(2))*surface(polygon(6)), surfacepen=oberfl);
}
}
}

draw(shift(-2,0,0)*rotate(45,X)*rotate(90,Y)*scale3(sqrt(2))*shift(-0.5,-0.5,0)*unitplane, surfacepen=oberfl, black+linewidth(0.2));
draw(shift(0,-2,0)*rotate(45,Y)*rotate(90,X)*scale3(sqrt(2))*shift(-0.5,-0.5,0)*unitplane, surfacepen=oberfl, black+linewidth(0.2));
draw(shift(0,0,2)*rotate(45,Z)*scale3(sqrt(2))*shift(-0.5,-0.5,0)*unitplane, surfacepen=oberfl, black+linewidth(0.2));

draw(O--(-1,-1,1), red + linewidth(2.0pt) + linetype(new real[] {2,2}));
draw(O--(0,-2,0), red + linewidth(2.0pt) + linetype(new real[] {2,2}));
draw((0,-2,0)--(-1,-2,0), red + linewidth(2.0pt));
draw((-1,-2,0)--(-1.5,-1.5,0), red + linewidth(2.0pt));
draw((-1.5,-1.5,0)--O, red + linewidth(2.0pt) + linetype(new real[] {2,2}));

% Charles Staats's Asymptote tutorial, 86
label("\Huge$\Gamma$", shift(0,0,-0.15)*(currentprojection.camera), red);
label("\Huge$L$", shift(-0.9,-1.1,1)*(currentprojection.camera), red);
label("\Huge$X$", shift(0,-2,-0.15)*(currentprojection.camera), red);
label("\Huge$W$", (-1,-2,-0.15), red);
label("\Huge$K$", (-1.5,-1.5,-0.15), red);
\end{asy}
\end{document}


This moves the specified labels closer:

Presumably, you don't want to move the axes or lines closer as that would look odd, but I'm assuming you could probably use a similar trick if you did.

• I have no idea about the other question, thus demonstrating the wisdom of the advice to ask one question per question. – cfr Aug 20 '16 at 22:45
• Agreed, @cfr. I tried to mend my inaccuracy by editing the thread title. And thanks for your reply! – dasausTeR Aug 21 '16 at 19:03