# Drawing a 3D commutative diagram

I was drawing a commutative-diagram when I had the (questionable?) idea of drawing a tetrahedral version of it. I used Asymptote in the hope of getting good-looking thumbnail and a nice embedded 3D model at the same time. This is what I got so far:

After activating the diagram and rotating around freely, I realized that my 3D model doesn't really look pleasant:

I would like to make the following improvements:

1. Arrow start and end positions are automatically calculated like in tikz-cd such that I don't need to use Fill on the labels or use the convexcomb routine.
2. Allow arrows in the front to cross over the ones in the back, analogous to the tikz-cd option crossing over.
3. Arrows look good without activating the model.
4. Arrows look good in 3D with camera rotation.

I don't really know how to do 1 & 2. Moreover, 3 & 4 seem to be contradictory goals. What should my realistic goal be and what improvements should I make? Source:

settings.render = 0;
import solids;
import three;
size(240,120);
defaultpen(basealign);

real side = 1;
triple origin = (0,0,0);
triple voa = (0,0,sqrt(6)/3*side);
triple vob = (sqrt(3)/4*side,-.5*side,0);
triple voc = (sqrt(3)/4*side,.5*side,0);
triple vod = (-sqrt(3)/3*side,0,0);

triple convexcomb(triple a, triple b, real x)
{
return (1-x) * a + x * b;
}

// A: U
// B: V1x...xVn
// C: W
// D: V

draw(convexcomb(vob,voa,.15)--convexcomb(vob,voa,.85),L=Label("$\varphi$",align=NW)         ,Arrow3(TeXHead2(normal=O)));
draw(convexcomb(vob,voc,.15)--convexcomb(vob,voc,.85),L=Label("$\psi$"   ,align=unit(4*S+W)),Arrow3(TeXHead2(normal=X)));
draw(convexcomb(vob,vod,.15)--convexcomb(vob,vod,.85),L=Label("$\phi$"   ,align=unit(4*N+E)),Arrow3(TeXHead2(normal=O)));
draw(convexcomb(voa,voc,.15)--convexcomb(voa,voc,.85),L=Label("$T_{0}$"  ,align=E)          ,Arrow3(TeXHead2(normal=O)));
draw(convexcomb(voa,vod,.15)--convexcomb(voa,vod,.85),L=Label("$\Pi$"    ,align=unit(E+NE)) ,Arrow3(TeXHead2(normal=O)));
draw(convexcomb(vod,voc,.15)--convexcomb(vod,voc,.85),L=Label("$T$"      ,align=unit(E+SE)) ,Arrow3(TeXHead2(normal=O)));

label(Label("$U$",Fill(white)),voa);
label(Label("$V_{1}\times\cdots\times V_{n}$",Fill(white)),vob);
label(Label("$W$",Fill(white)),voc);
label(Label("$V$",Fill(white)),vod);

• For 1. the draw command has a Margin3(number,number) parameter. But it is not automatic with respect to the Label. For an automatic command, a routine should be written.
– O.G.
Jun 21, 2018 at 8:33
• For 2., in 3D such a crossing over is difficult to implement, it depends on the projection and cannot be interactive. (in 2D it should be possible to have such a crossing over). For the arrows question, the projection of TeXHead2 is not interactive. Try 3D version ?
– O.G.
Jun 21, 2018 at 8:42
• @O.G. Thanks for the Margin3. I'm thinking about having the cross over only on the thumbnail but not the 3D. Do I have to manage two scripts, if I want the thumbnail to have TeXHead2 arrows and crossover and the 3D to have Arrow3 and no crossover? Jun 21, 2018 at 8:45
• Even though I really love asymptote, I am wondering if you are willing to also consider a TikZ solution here. After all you do not seem to really need a 3D engine, i.e. hide certain elements behind surfaces.
– user121799
Jun 21, 2018 at 16:03
• I guess that this would be very simple to do with tikz-cd. This is "secretly" using a matrix of node, and you could shift nodes into the "z-direction" simply by adding something like |[xshift=-1cm,yshift=-1cm]| to the matrix, ah, sorry, diagram.
– user121799
Jun 23, 2018 at 1:45

Here is a proposal for a pseudo-3D tikz-cd diagram.

\documentclass[border=2pt]{standalone}
\usepackage{amssymb,amsmath}
\usepackage{tikz-cd}
\usetikzlibrary{arrows}

\usepackage{tikz}

\begin{document}
\tikzset{zshift/.style={xshift={-0.3*#1},yshift={-0.9*#1}}}

\begin{tikzcd}[row sep=2cm,column sep=2cm,inner sep=1ex]
& U \arrow{d}{T_0} \arrow{dr}{\Pi} & \\
V_1\times\cdots V_n \arrow{ur}{\varphi}
\arrow{r}{\phi} \arrow{rr}{\psi}&
|[zshift=-1.5cm]| V \arrow{r}{T}& |[zshift=1cm]|W
\end{tikzcd}

\end{document}


• This is fantastic. I tweaked the settings to \tikzset{zshift/.style={xshift={0},yshift={-.8*#1}}} to get this. Much appreciated! Jun 23, 2018 at 2:39
• @FrenzyLi Looks great! (Most likely one could tweak the matrix in such a way that one does not have to put in the zshift by hand, but this would be perhaps too much effort and also perhaps more fragile than it should be, so I leave that for now. ;-)
– user121799
Jun 23, 2018 at 3:34

Here are similarly-shaped diagrams taken from another context; maybe they are helpful:

\begin{tikzcd}[row sep={7.2em,between origins}, column sep={9.0em,between origins}, background color=backgroundColor, ampersand replacement=\&,execute at end picture={
\foreach \Number in  {A,B,...,D}
{\coordinate (\Number) at (\Number.center);}
\begin{pgfonlayer}{background}
\fill[left color=grey!98!black, right color=grey!80!white, shading angle=60] (A) -- (C) -- (B) -- cycle;
\fill[left color=grey!85!black, right color=grey!85!white, shading angle=-60] (D) -- (C) -- (B) -- cycle;
\fill[left color=grey!80!black, right color=grey!98!white, shading angle=180] (A) -- (B) -- (D) -- cycle;
\draw[dashed, dash pattern=on 3.0pt off 3.0pt] (B) -- (A);
\draw[dashed, dash pattern=on 3.0pt off 3.0pt] (B) -- (C);
\draw[dashed, dash pattern=on 3.0pt off 3.0pt] (B) -- (D);
\end{pgfonlayer}
\filldraw[black!30!white] (A) circle (6pt) node[black,align=center] {$A$};
\filldraw[black!30!white] (B) circle (6pt) node[black,align=center] {$B$};
\filldraw[black!30!white] (C) circle (6pt) node[black,align=center] {$C$};
\filldraw[black!30!white] (D) circle (6pt) node[black,align=center] {$D$};
}]
\&
|[alias=C]|C
\arrow[rdd, "h"]
\&\\[4.5em]\&
|[alias=B]|B
\arrow[u, dashed, "\textcolor{white}{\phantom{g}}"{description,background color=grey,opacity=0.75}, dash pattern=on 3.0pt off 3.0pt]
\arrow[u, phantom, "\textcolor{white}{g}"]
\arrow[dr, dashed, "\textcolor{white}{\phantom{h\circ g}}"{description,background color=grey,opacity=0.5}, dash pattern=on 3.0pt off 3.0pt]
\arrow[dr, dashed, "\textcolor{white}{h\circ g}", phantom]
\&\\[-1.85em]
|[alias=A]|A
\arrow[ruu, "g\circ f"]
\arrow[rr, "h\circ g\circ f"']
\arrow[ru, dashed, "\textcolor{white}{\phantom{f}}"{description,background color=grey,opacity=0.75}, dash pattern=on 3.0pt off 3.0pt]
\arrow[ru, dashed, "\textcolor{white}{f}", phantom]
\&\&
|[alias=D]|D\mathrlap{.}
\end{tikzcd}

1. (Ignore the 2-morphisms):

\begin{tikzcd}[row sep={7.2em,between origins}, column sep={9.0em,between origins}, background color=backgroundColor, ampersand replacement=\&]
\&
A_{2}
\arrow[rdd, "f_{23}", bend left=20]
\&\\\&
A_{1}
\arrow[u, "f_{12}"{description}, dash pattern=on 4.0pt off 4.0pt]
\arrow[rd, "f_{13}"'{description,name=f13}, dash pattern=on 4.0pt off 4.0pt]
\&\\
A_{0}
\arrow[ruu, "f_{02}"{name=f02}, bend left=20]
\arrow[rr, "f_{03}"'{name=f03}, bend right=20]
\arrow[ru, "f_{01}"{description}, dash pattern=on 4.0pt off 4.0pt]
\&\&
A_{3}
% 2-Arrows
\arrow[from=2-2, to=f02, Rightarrow, shorten=1.0em, "\theta_{012}"description, pos=0.475]
\arrow[from=1-2, to=f13, Rightarrow, yshift=-0.25em, xshift=0.75em, shorten=3.5em, "\theta_{123}"description, pos=0.475]
\arrow[from=2-2, to=f03, Rightarrow, shorten=2.5em, "\theta_{013}"description, pos=0.475]
\arrow[from=1-2, to=f03, bend left=20, yshift=+0.0em, xshift=0.0em, crossing over, Rightarrow, shorten=2.0em, "\hspace{+0.625em}\theta_{023}"description, pos=0.425, crossing over clearance=1.5ex]
\end{tikzcd}