# Improve perspective visualization in 3d plot

I'm trying to vizualize the computation of Euclidean distance in 3d using pgfplots. This is my current attempt:

\documentclass{article}
\usepackage{pgfplots}
\begin{document}
$\mathrm{dist}(p,q) = \sqrt{(p_x-q_x)^2+(p_y-q_y)^2+(p_z-q_z)^2}$

\begin{tikzpicture}
\begin{axis}[
xmin=9, xmax=51, ymin=9, ymax=51, zmin=25, zmax=85,
ytick={10,20,30,40,50}, ztick={30,40,50,60,70,80},
xlabel={$x$}, ylabel={$y$}, zlabel={$z$},
grid=major]
\addplot3[only marks,mark=*,nodes near coords={\mylabel},visualization depends on={value \thisrowno{3}\as\mylabel}]
table {
x  y  z  name
38 17 71 p
16 32 38 q
};
% some partial 3d grid lines
\draw[orange] (axis cs:38, 17, 71) -- (axis cs:9, 17, 71);
\draw[orange] (axis cs:38, 17, 71) -- (axis cs:38, 17, 25);
\draw[orange] (axis cs:38, 17, 71) -- (axis cs:38, 9, 71);
\draw[orange] (axis cs:38, 9, 71) -- (axis cs:9, 9, 71);
\draw[orange] (axis cs:38, 9, 71) -- (axis cs:38, 9, 25);
\draw[red] (axis cs:16, 32, 38) -- (axis cs:9, 32, 38);
\draw[red] (axis cs:16, 32, 38) -- (axis cs:16, 32, 25);
\draw[red] (axis cs:16, 32, 38) -- (axis cs:16, 9, 38);
\draw[red] (axis cs:16, 9, 38) -- (axis cs:9, 9, 38);
\draw[red] (axis cs:16, 9, 38) -- (axis cs:16, 9, 25);

% distances
\draw[->,blue] (axis cs:16, 17, 71) -- (axis cs:38, 17, 71); % x distance, base p
\draw[->,blue] (axis cs:16, 17, 71) -- (axis cs:16, 32, 71); % y distance, shifted base
\draw[->,blue] (axis cs:16, 32, 38) -- (axis cs:16, 32, 71); % z distance, base q
\draw[->,dashed,blue] (axis cs:16, 32, 71) -- (axis cs:38, 17, 71); % x and y distance
\draw[->,very thick,dashed,blue] (axis cs:16, 32, 38) -- (axis cs:38, 17, 71); % x, y and z distance
\end{axis}
\end{tikzpicture}
\end{document}

Result:

In the current graph it is rather difficult to perceive the distances in each dimension between the points themselves and between the points and the 'sides' of the cube (i.e., the axes). For example, it is hard to see that p is closer to the front (on the y axis) than q. It almost looks like p is on the 'back wall' and q is on the bottom left y axis, and that the z and y distance arrows are on the 'side wall'.

I have tried adding some partial 3d grid lines, which helps a bit but not much. What can I do to improve the look of perspective? I would very much like to keep the current numbers, because they represent a running example in my lecture. Possibly the rotation can be changed? I tried Rotating axes in 3D for better viewing planes but the rotate around option did not do anything. Or maybe fill the triangles or the grid rectangles with a (semi-transparent) surface, but I have no idea how to do that and if it would help to improve the perspective.

This question is a bit similar to draw direction cosines using tikz but also there the direction of the vector is not very clear. I am aware that it is difficult to visualize 3d space on a 2d paper/screen, but I am sure my current solution can be improved somehow.

Note that Wikimedia Commons has a visualization as well (https://commons.wikimedia.org/wiki/File:Euclidean_distance_3d_2_cropped.png) but that approach is a bit too complex in my opinion (except for the straight edge marks which I should probably add as well).

• I'd put the origin at the back and project onto the 3 planes, to have 3 right triangles. – Sigur Jan 15 '19 at 16:36

This is a quick writeup of something that projects the coordinates on the three planes. (This writeup can be improved and made much more user friendly if you signal this goes in the right direction.)

\documentclass[tikz,border=3.14mm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\usetikzlibrary{3d}
\newcommand{\TDNode}[6][]{
\begin{scope}[transform shape]
\begin{scope}[canvas is xy plane at z=\pgfkeysvalueof{/pgfplots/zmin}+0.01]
\node[circle,fill,inner sep=16pt,label={[scale=10]above:#3},opacity=0.5,#1] (#2-xy) at (#4,#5){};
\end{scope}
\begin{scope}[canvas is xz plane at y=\pgfkeysvalueof{/pgfplots/ymax}-0.01]
\node[circle,fill,inner sep=16pt,label={[scale=10]above:#3},opacity=0.5,#1] (#2-xz) at (#4,#6){};
\end{scope}
\begin{scope}[canvas is yz plane at x=\pgfkeysvalueof{/pgfplots/xmin}+0.01]
\node[circle,fill,inner sep=16pt,label={[scale=10]above:#3},opacity=0.5,#1] (#2-yz) at (#5,#6){};
\end{scope}
\end{scope}
\node[circle,fill,inner sep=1pt,label=above:#3,#1] (#2) at (#4,#5,#6){};
\draw[dashed,opacity=0.5] (#2.center) -- (#2-xy.center)
(#2.center) -- (#2-xz.center) (#2.center) -- (#2-yz.center);
}

\begin{document}

\begin{tikzpicture}
\begin{axis}[title={$\mathrm{dist}(p,q) = \sqrt{(p_x-q_x)^2+(p_y-q_y)^2+(p_z-q_z)^2}$},
grid = major,
grid style={ultra thin, gray!50},
xmin=9, xmax=51, ymin=9, ymax=51, zmin=25, zmax=85,
ytick={10,20,30,40,50}, ztick={30,40,50,60,70,80},
xlabel={$x$}, ylabel={$y$}, zlabel={$z$}]
\addplot3[only marks,mark=*,visualization depends on={value \thisrowno{3}\as\mylabel}]
table {
x  y  z  name
38 17 71 p
16 32 38 q
};
\TDNode{p}{$p$}{38}{17}{71}
\TDNode{q}{$q$}{16}{32}{38}
\begin{scope}[canvas is xy plane at z=\pgfkeysvalueof{/pgfplots/zmin}+0.01,
transform shape]
\draw[dashed,gray] (p-xy) |- (q-xy)
node[pos=0.25,scale=10,fill=white]{$q_y-p_y$}
node[pos=0.75,scale=10,fill=white]{$p_x-q_x$};
\end{scope}
\begin{scope}[canvas is xz plane at y=\pgfkeysvalueof{/pgfplots/ymax}-0.01,
transform shape]
\draw[dashed,gray] (p-xz) -| (q-xz)
node[pos=0.25,scale=10,fill=white]{$p_x-q_x$}
node[pos=0.75,scale=10,fill=white]{$p_z-q_z$};
\end{scope}
\begin{scope}[canvas is yz plane at x=\pgfkeysvalueof{/pgfplots/xmin}+0.01,
transform shape]
\draw[dashed,gray] (p-yz) -| (q-yz)
node[pos=0.25,scale=10,fill=white]{$q_y-p_y$}
node[pos=0.75,scale=10,fill=white]{$p_z-q_z$};
\end{scope}
\end{axis}
\end{tikzpicture}
\end{document}

Please note that, unless you use keys like axis equal or the like, pgfplots will rescale the directions, which may make it even harder to provide an intuition for the 3d locations of these points.

• I like this idea, in my attempt I tried to project the coordinates on the (invisible) front plane but this looks more clear. I'm not sure it needs the projections of the dimensional distances though, that might make it harder to express the idea that the xy diagonal and the z distance form two sides of the final triangle. – Marijn Jan 16 '19 at 15:34
• @Marijn Glad to hear you like the idea. I guess it is straightforward to leave those projections out which you do not like. Similarly, you may add diagonals (and I will be happy to add them if that causes problems). My take is that all three directions are on the same footing, which is why I added 3 projections. Of course, I were to use this in a presentation, I would switch on and off different projections. – user121799 Jan 16 '19 at 15:40