9

I'm trying to draw a cube where the faces are labeled with full perspective. I saw this question but I was looking for more perspective. Any help is greatly appreciated. Below is my attempt: Cube

\documentclass[border=5mm,tikz]{standalone}
\usepackage{mwe}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\draw[thick](2,2,0)--(0,2,0)--(0,2,2)--(2,2,2)--(2,2,0)--(2,0,0)--(2,0,2)--(0,0,2)--(0,2,2);
\draw[thick](2,2,2)--(2,0,2);
\draw[gray](2,0,0)--(0,0,0)--(0,2,0);
\draw[gray](0,0,0)--(0,0,2);
\draw(1,1,2) node{$Mol_{jl}$};
\draw(1,2,1) node{$Mol_{ijkl}$};
\draw(2,1,1) node[rotate=90] {$Mol_{kl}$};
\pgflowlevelscope{\pgftransformxscale{-1}}
\draw[gray!20](0.6,1,1) node[rotate=90]{$Mol_{ij}$};
\endpgflowlevelscope ;
 \pgflowlevelscope{\pgftransformxscale{-1}}
 \draw[gray!20](-1,1,0) node{$Mol_{ik}$};
\endpgflowlevelscope ;
 \end{tikzpicture}
 \end{document}
cheyne
  • 207
  • Welcome! What do you mean by more perspective exactly? – cfr Apr 04 '16 at 23:46
  • Cheers. I added the image finally. I mean that on the top face, the perspective is "slanted" so it would be great to "slant" the label. Similarly, the left face needs a mirror imaging and a slanting. – cheyne Apr 04 '16 at 23:50
  • Related/duplicate: http://tex.stackexchange.com/questions/254010/placing-text-on-face-of-3d-cube. It is isometric, not perspective labeling. – Steven B. Segletes Apr 05 '16 at 00:12
  • Any suggestions on the back sides? I guess I need to use a contour shadowing plus slanting plus mirror plus rotation? There isn't a more pre-designed way to deal with labeling cubes? – cheyne Apr 05 '16 at 00:24
  • 1
    If you look at my answer at the cited question, backward looking text can be obtained by a redefinition of \newcommand\rotslant[3]{\scalebox{-1}[1]{\rotatebox{#1}{\slbox{#2}{#3}}}}. – Steven B. Segletes Apr 05 '16 at 00:52

2 Answers2

7

TikZ is not great for 3D. For best results in complex cases, you should use software designed for 3D drawing. The best you can do with TikZ is to fake 3D in 2D. For simple drawings, tikz-3dplot can help with the faking by doing much of the calculation for you.

For example, here's a version of your cube done with this package:

cube

Uncomment lines to see where the axes and coordinates used to construct the drawing are placed.

\documentclass[border=5pt,tikz,multi]{standalone}
\usepackage{tikz-3dplot}
\begin{document}
\tdplotsetmaincoords{45}{135}
\begin{tikzpicture}[tdplot_main_coords, my label/.style={midway, sloped}]
%   \draw [->, help lines] (0,0,0) -- (4,0,0) node[anchor=north east]{$x$};
%   \draw [->, help lines] (0,0,0) -- (0,4,0) node[anchor=north west]{$y$};
%   \draw [->, help lines] (0,0,0) -- (0,0,4) node[anchor=south]{$z$};
  \path (1,-1,1) coordinate (a) -- (1,1,1) coordinate (b) -- (-1,1,1) coordinate (c) -- (-1,-1,1) coordinate (d) -- cycle (a) -- (1,-1,-1) coordinate (e) -- (1,1,-1) coordinate (f) -- (-1,1,-1) coordinate (g) -- (-1,-1,-1) coordinate (h) -- (e);
  \path [fill=magenta, fill opacity=.125] (a) -- (d) -- (h) -- (e) -- cycle;
  \path [fill=blue, fill opacity=.125] (c) -- (d) -- (h) -- (g) -- cycle;
  \path [fill=cyan, fill opacity=.125]   (e) -- (f) -- (g) -- (h) -- cycle;
  \path [fill=blue, fill opacity=.25] (a) -- (b) -- (f) -- (e) -- cycle;
  \path [fill=magenta, fill opacity=.25] (c) -- (b) -- (f) -- (g) -- cycle;
  \path [fill=cyan, fill opacity=.25] (a) -- (d) -- (c) -- (b) -- cycle;
  \draw [gray] (e) -- (h) edge (g) -- (d);
  \path  (1,-1,0) coordinate (i) -- (1,1,0) coordinate (j) node [my label]  {$Mol_{jl}$}
  (0,-1,1) coordinate (k) -- (0,1,1) coordinate (l) node [my label]  {$Mol_{ijkl}$}
  (0,1,-1) coordinate (m) -- (l) node [my label] {$Mol_{kl}$}
  (-1,1,0) coordinate (n) -- (-1,-1,0) coordinate (o) node [my label, gray, xscale=-1] {$Mol_{jk}$}
  (0,-1,-1) coordinate (p) -- (k)  node [my label, gray, yscale=-1] {$Mol_{ij}$}
  (m) -- (p) node [my label, gray, scale=-1] {$Mol_{??}$}
  ;
  \draw [thick, line join=round] (a) -- (b) -- (f) -- (e) -- cycle (a) -- (d) -- (c) -- (b) -- cycle (b) -- (c) -- (g) -- (f) -- cycle;
%   \foreach \i in {a,b,...,p} \node [red,font=\tiny] at (\i) {\i};
\end{tikzpicture}
\end{document}
cfr
  • 198,882
  • Very cool! So that sloped style is included in the 3d path package? – cheyne Apr 05 '16 at 01:09
  • No. The sloped style is supplied by standard TikZ. You can use it to make labels align with the lines they are placed on, for example. The tikz-3dplot package is just for the 3D stuff - the rotation, perspective etc. – cfr Apr 05 '16 at 01:11
  • You're welcome! I find the tikz-3d package a bit mind-boggling, but I can now draw simple things (cubes and cuboids, basically e.g. I can do a house as a cuboid with a roof ;) ). You can do much more with it but I haven't. Yet, anyway. – cfr Apr 05 '16 at 01:16
  • @cheyne I think the effect on the text is a combination of tikz-3dplot and sloped. The sloped makes the text go 'along the path' but tikz-3d is responsible for the rotation of that path which gets the perspective effect. I hope that makes sense. – cfr Apr 05 '16 at 01:21
  • @cheyne I tidied up the corners a bit as they looked somewhat jagged. (Just changing the line cap for the thick lines.) – cfr Apr 05 '16 at 01:37
  • Thanks, @cfr The below answer has a nice way of compressing the text as well. These are all really nice features. – cheyne Apr 05 '16 at 17:44
6

As I had indicated in a comment, one must slant and rotate text to produce an isometric viewpoint (though I realize the OP's drawing is actually true perspective, not isometric). The OP's code had already accounted for the text rotation, so all I did here was to slant it by +/-45 degrees, which was the approximate isometric sense adopted by the OP's image.

EDITED OP's code to place black objects in foreground; gray behind.

\documentclass[border=5mm,tikz]{standalone}
\usepackage{fp,amssymb}
\newsavebox\foobox
\newcommand\slbox[2]{%
  \FPdiv{\result}{#1}{57.296}% CONVERT deg TO rad
  \FPtan{\result}{\result}%
  \slantbox[\result]{#2}%
}%
\newcommand{\slantbox}[2][30]{%
        \mbox{%
        \sbox{\foobox}{#2}%
        \hskip\wd\foobox
        \pdfsave
        \pdfsetmatrix{1 0 #1 1}%
        \llap{\usebox{\foobox}}%
        \pdfrestore
}}
\newcommand\rotslant[3]{\rotatebox{#1}{\slbox{#2}{#3}}}
\usepackage{mwe}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\pgflowlevelscope{\pgftransformxscale{-1}}
\draw[gray!20](0.8,.9,1) node[rotate=90]{\rotslant{0}{45}{\textcolor{gray!20}{$Mol_{ij}$}}};
\endpgflowlevelscope ;
 \pgflowlevelscope{\pgftransformxscale{-1}}
 \draw[gray!20](-1,1,0) node{$Mol_{ik}$};
\endpgflowlevelscope ;
\draw[gray](2,0,0)--(0,0,0)--(0,2,0);
\draw[gray](0,0,0)--(0,0,2);
\draw[thick](2,2,0)--(0,2,0)--(0,2,2)--(2,2,2)--(2,2,0)--(2,0,0)--(2,0,2)--(0,0,2)--(0,2,2);
\draw[thick](2,2,2)--(2,0,2);
\draw(1,1,2) node{$Mol_{jl}$};
\draw(1,2,1) node{\rotslant{0}{45}{$Mol_{ijkl}$}};
\draw(2,1,1) node[rotate=90] {\rotslant{0}{-45}{$Mol_{kl}$}};
 \end{tikzpicture}
 \end{document}

enter image description here

In this revision, I try to more properly account for the perspective by vertically compressing the slanted text on the side/top faces (by introducing a \scalebox{1}[.75]{} into the \slantbox definition). Of course, this screws up the slant angles, which must be manually modified to recapture the proper look. Printing a \square on a facet face gives an indication of whether the slant angles have been properly selected.

\documentclass[border=5mm,tikz]{standalone}
\usepackage{fp,amssymb}
\newsavebox\foobox
\newcommand\slbox[2]{%
  \FPdiv{\result}{#1}{57.296}% CONVERT deg TO rad
  \FPtan{\result}{\result}%
  \slantbox[\result]{#2}%
}%
\newcommand{\slantbox}[2][30]{%
        \scalebox{1}[.7]{\mbox{%
        \sbox{\foobox}{#2}%
        \hskip\wd\foobox
        \pdfsave
        \pdfsetmatrix{1 0 #1 1}%
        \llap{\usebox{\foobox}}%
        \pdfrestore
}}}
\newcommand\rotslant[3]{\rotatebox{#1}{\slbox{#2}{#3}}}
\usepackage{mwe}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\pgflowlevelscope{\pgftransformxscale{-1}}
\draw[gray!20](0.8,.9,1) node[rotate=90]{\rotslant{0}{40}{\textcolor{gray!20}{$Mol_{ij}$}}};
\endpgflowlevelscope ;
 \pgflowlevelscope{\pgftransformxscale{-1}}
 \draw[gray!20](-1,1,0) node{$Mol_{ik}$};
\endpgflowlevelscope ;
\draw[gray](2,0,0)--(0,0,0)--(0,2,0);
\draw[gray](0,0,0)--(0,0,2);
\draw[thick](2,2,0)--(0,2,0)--(0,2,2)--(2,2,2)--(2,2,0)--(2,0,0)--(2,0,2)--(0,0,2)--(0,2,2);
\draw[thick](2,2,2)--(2,0,2);
\draw(1,1,2) node{$Mol_{jl}$};
\draw(1,2,1) node{\rotslant{0}{35}{$Mol_{ijkl}$}};
\draw(2,1,1) node[rotate=90] {\rotslant{0}{-40}{$Mol_{kl}$}};

 \end{tikzpicture}
 \end{document}

enter image description here

  • It took me a minute to realize what extra bit you had added here. This is great, I will try to use your compression bits added to the overlay bits from the other answer. Thanks! – cheyne Apr 05 '16 at 17:43
  • Shouldn't the grey letters and lines be behind the black ones? – cfr Apr 05 '16 at 19:26
  • @cfr Yes they should. But I don't know tikz beyond a smattering. I used the OP's code (which had the same issue). My main point was to show how slanted letters was a key part of writing in perspective. – Steven B. Segletes Apr 05 '16 at 19:34
  • @cfr Now fixed for both cases shown. – Steven B. Segletes Apr 05 '16 at 19:46
  • 1
    (+1) I took the 'perspective' rather too literally, it seems ;). I probably noticed the grey/black only because I noticed it when drawing mine. – cfr Apr 05 '16 at 20:16
  • I seem to have misused the "answer" button? I mean, both of you supplied nice answers which together, I thought gave the full picture. I clicked the check mark for both but I think it only allows one answer? Sorry if I didn't close the question properly. Thanks again for all of your help. I'm writing my PhD thesis and there are lots of pictures involving cubes, squares, etc. @cfr – cheyne Apr 06 '16 at 15:54
  • @cheyne Yes, you can only accept one answer. You may not have sufficient reputation yet but, when you do, you can up-vote several answers (to other people's questions or your own) so it gets a bit easier because you can vote for two or more helpful answers even though you can only accept one. Sometimes it is hard to choose, though ;). – cfr Apr 06 '16 at 16:52
  • @cheyne To "upvote" means to click the uparrow above the place where the "check" icon is. You can do that to multiple answers, indicating that they were useful answers. However, as cfr notes, only one answer can be "accepted" with the check mark. – Steven B. Segletes Apr 06 '16 at 17:02