# How to color several transparent planes in a cube?

I'm trying to reproduce the following two figures in TikZ.

My attempted code for Fig 1 is

\documentclass{minimal}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\draw [fill=black, ultra thick, red]  (0.0,0.0) -- (0.5, 0.5) -- (0.5, 1.5) -- (0.0, 1.0) -- cycle;
\draw [fill=black, ultra thick, blue] (1.0,0.0) -- (1.5, 0.5)-- (1.5, 1.5)--(1.0, 1.0)--cycle;
\draw  (0.0,0.0)  -- (1.0, 0.0)-- (1.5, 0.5)--(0.5, 0.5)--cycle;
\draw  (0.0,1.0) -- (1.0, 1.0)-- (1.5, 1.5)--(0.5, 1.5)--cycle;
\end{tikzpicture}
\end{document}


and for the second figure the code is

\documentclass{minimal}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\draw [fill=black, ultra thick, red]  (1.0,0.0) -- (1.0, 1.0) -- (0.5, 1.5) -- (0.5, 0.5) -- cycle;
\draw [fill=black, ultra thick, blue] (0.0,0.0) -- (0.0, 1.0)-- (1.5, 1.5)--(1.5, 0.5)--cycle;
\draw  (0.0,0.0)  -- (1.0, 0.0)-- (1.5, 0.5)--(0.5, 0.5)--cycle;
\draw  (0.0,1.0) -- (1.0, 1.0)-- (1.5, 1.5)--(0.5, 1.5)--cycle;
\draw  (1.0, 0.0) -- (1.0, 1.0)  (0.5, 0.5) -- (0.5, 1.5);
\end{tikzpicture}
\end{document}


I'm a TikZ newbie and have troubles to produce exactly the same figures with more efficient code. I've a problem with overlays and exact coordinates. I'd highly appreciate if you could help me to fix these problems and get similar figures with more robust code.

• I think that you need to take a look at the outer sep option on page 176 in the tikz manual. -and use \draw [draw=black, ultra thick, fill=blue]. -and read chapter 20 about transparency. – hpekristiansen Feb 21 '12 at 5:16
• Thanks @Hans-PeterE.Kristiansen for your pointer. I almost rosoved the issue of transparency. Thanks again. – MYaseen208 Feb 21 '12 at 5:23
• @Hans-PeterE.Kristiansen: Can you give me more pointer about outer sep? – MYaseen208 Feb 21 '12 at 5:36
• I do not know how make it work myself - I just guessed that setting outer sep = 0 would help to make the lines join nicely. -but I do not know enough. – hpekristiansen Feb 21 '12 at 5:41

It is often forgotten that tikZ also has an xyz coordinate system. I think it lets you express the coordinates in a more natural way. (I also added the circles.)

\documentclass{minimal}
\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}
\begin{tikzpicture}[scale=4,fill opacity=0.4,thick,
line cap=round,line join=round]
%% Define coordinate labels.
% t(op) and b(ottom) layers
\path \foreach \layer/\direction in {b/{0,0,0},t/{0,1,0}} {
(\direction)
\foreach \point/\label in {{0,0,0}/ll,{1,0,0}/lr,{1,0,-1}/ur,{0,0,-1}/ul} {
+(\point) coordinate (\layer\label)
}
($(\layer ll)!0.5!(\layer ur)$) coordinate (\layer md)
};

% Put text next to the labels as requested.
% Funilly enough we need to set fill opacity to 1.
\draw \foreach \text/\label/\anchor in {%
one/bll/east,
two/bul/east,
three/tll/east,
four/tul/east,
five/blr/west,
six/bur/west,
seven/tlr/west,
eight/tur/west} {
(\label) node[anchor=\anchor,fill opacity=1] {\text}
};

% Draw left cube.
\fill (0,0,-1) circle (0.5pt);
\foreach \direction in {(0,0,1),(0,1,0),(1,0,0)} {
\draw[dashed,black] (bul) -- + \direction;
}
\fill[blue!60] (bmd) -- (bur) -- (tur) -- (tmd);
\fill[red!60]  (blr) -- (tlr) -- (tul) -- (bul);
\fill[blue!60] (bll) -- (bmd) -- (tmd) -- (tll);
\draw (bll) -- (blr) -- (tlr) -- (tll) -- cycle;
\draw (blr) -- (bur) -- (tur) -- (tlr) -- cycle;
\draw (tll) -- (tlr) -- (tur) -- (tul) -- cycle;
\foreach \point in {bll,blr,bur,tll,tlr,tul,tur} {
\fill[fill opacity=1] (\point) circle (0.75pt);
}

% Draw right cube.
\path (blr) + (0.65,0) coordinate (pos);
\foreach \direction in {(0,0,1),(0,1,0),(1,0,0)} {
\draw[dashed] (pos) ++ (bul) -- + \direction;
}
\fill[blue!60] (pos) +(blr) -- +(bur) -- +(tur) -- +(tlr);
\fill[red!60]  (pos) +(bll) -- +(bul) -- +(tul) -- +(tll);
\draw (pos) +(tll) -- +(tlr) -- +(tur) -- +(tul) -- cycle
+(tll) -- +(bll) -- +(blr) -- +(bur) -- +(tur)
+(blr) -- +(tlr);
\end{tikzpicture}
\end{document}


• Yes and No. Yes it's more easy to see where are the points. No because you have the same calculus to place the points, No because you have a lot of coordinates to write. The better way is to name the coordinates with the 3D library. Each side is a plan, and you can work with only 2 coordinates. After getting the coordinates, you can working without problem. (see my update) – Alain Matthes Feb 21 '12 at 9:06
• I understand and in my HD, half of the 3D examples used your method and the other half the 3D library. But I think it's preferable to name the coordinates. The code will be easier to modify and read. – Alain Matthes Feb 21 '12 at 9:44
• (+1): Thanks @MarcvanDongen for such a formidable answer. I'd highly appreciate if you let me how to put some text (like A, B, etc...) close to every circle. Thanks again for all your help. Much appreciated. – MYaseen208 Feb 21 '12 at 16:12
• @MarcvanDongen: Nice answer. One minor problem is that the lines does not match up nicely - it can only be seen on the right figure, where there is no circles in the corners to hide the problem. (If you do not know what I mean, then try setting the line width to ultra thich.) – hpekristiansen Feb 26 '12 at 5:38

Your options are not fine. When you write \draw[fill=black, ultra thick, red], as you can see fill=black doesn't work. Your last option red is used for drawing and filling. to fill with red and to draw with black, you need to write \draw[color=black,fill=red, ultra thick]. Surface and line are red and the line width is important so you the result is not fine. Now in a first time, you can use \draw and \fill separately. The order is important because some options have some effects on the first drawings. There are other methods (ways) to create this picture but I give you the codes later. For the circles at each vertex is interesting to use variables instead of "raw" coordinates and you can use \foreach. Comments are in the code.

Figure

My code update

I keep the code initial to show what is wrong and what is right

\documentclass{minimal}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}

\tikzset{vertex/.style={shape=circle, % style for a vertex
minimum size=3pt,
fill=black,
inner sep = 0pt}}
\begin{tikzpicture}[scale=4]
% define the points
\path  (0,0)     coordinate (A)  (1,0)     coordinate (B) % bottom
(1.5,0.5) coordinate (C)  (0.5,0.5) coordinate (D)
(0,1)     coordinate (E)  (1,1)     coordinate (F) % top  add 1 for y
(1.5,1.5) coordinate (G)  (0.5,1.5) coordinate (H)
($(A)!0.5!(C)$) coordinate (O)   % middle of A--C
($(E)!0.5!(G)$) coordinate (P);%

\draw (A) -- (E) (B) -- (F) (C) -- (G) ; % lateral
\draw[gray,dashed]  (D) -- (H) (D) -- (C) (D) -- (A) (D) -- (B) (A) -- (C);
\fill [blue!50,fill opacity=.5] (P) -- (O) -- (C) -- (G) -- cycle;
\fill [red!50, fill opacity=.5] (H) -- (D) -- (B) -- (F) -- cycle;
\fill [blue!50,fill opacity=.5] (A) -- (O) -- (P) -- (E) -- cycle;
\draw (A) -- (B) -- (C) (F) -- (H); % bottom
\draw (E) -- (F) -- (G) -- (H) -- (E) -- (G); % top
% vertex
\foreach \vertex in {A,...,C} {\node[vertex] at (\vertex) {};}
\foreach \vertex in {E,...,H} {\node[vertex] at (\vertex) {};}
\node[vertex,fill=gray] at (D) {};
\end{tikzpicture}
\end{document}


version 3D

I think it's the better way. With canvas is xy plane at z=0, you are on a plan (xy). I used some negative values to respect my first solution and to use the same code,. The code looks better with only positive values. To use other side, you just need to write for example canvas is xz plane at y=0 and you get a plan (lateral) axis are x and z. The result is exactly the same and you need no calculus but you need some orientation in space !

I added yellow color to show how to use other plans Be careful, I used canvas is yx plane and not canvas is xy plane.

\documentclass[12pt,a4paper]{article}
\usepackage{tikz}
\usetikzlibrary{calc,3d}

\begin{document}
\thispagestyle{empty}

\tikzset{vertex/.style={shape=circle, % style for a vertex
minimum size=3pt,
fill=gray,
inner sep = 0pt}}

\begin{tikzpicture}
[x={(-0.5cm,-0.5cm)}, y={(1cm,0cm)}, z={(0cm,1cm)}, scale=4]
\draw[thick](0,0,0)--(1.2,0,0) node[below right]{x} ;
\draw[thick](0,0,0)--(0,1.2,0) node[below right]{y} ;
\draw[thick](0,0,0)--(0,0,1.2) node[below right]{z} ;
% face  bottom
\begin{scope}[canvas is xy plane at z=0,very thin]
\coordinate  (A) at (0,0);   \coordinate (C) at (-1,1);
\coordinate  (B) at (-1,0);  \coordinate  (D) at (0,1);
\coordinate (O) at  ($(A)!0.5!(C)$); % middle of A--C
\end{scope}
% face  top
\begin{scope}[canvas is xy plane at z=1,very thin]
\coordinate  (E) at (0,0);  \coordinate (G) at (-1,1);
\coordinate  (F) at (-1,0); \coordinate (H) at (0,1);
\coordinate (P) at  ($(E)!0.5!(G)$); % middle of A--C
\end{scope}

\begin{scope}[canvas is yx plane at z=0]
\path[fill = yellow] (0,0) rectangle (1,-1);
\end{scope}

\foreach \vertex in {A,...,H} {\node[vertex] at (\vertex) {};}
\draw (A) -- (B) -- (C) -- (D) -- cycle; % bottom
\draw (E) -- (F) -- (G) -- (H) -- cycle; % top
\draw (A) -- (E) (B) -- (F) (C) -- (G) (D)--(H); % lateral
\fill [blue!50,fill opacity=.5] (P) -- (O) -- (C) -- (G) -- cycle;
\fill [red!50, fill opacity=.5] (H) -- (D) -- (B) -- (F) -- cycle;
\fill [blue!50,fill opacity=.5] (A) -- (O) -- (P) -- (E) -- cycle;
\end{tikzpicture}
\end{document}


For fun

I would like to avoid maximum of coordinates

\documentclass[12pt,a4paper]{article}
\usepackage{tikz}
\usetikzlibrary{calc,3d}

\begin{document}
\thispagestyle{empty}

\tikzset{vertex/.style={shape=circle, % style for a vertex
minimum size=8pt,
ball color=gray,
inner sep = 0pt}}

\begin{tikzpicture}
[x={(-0.5cm,-0.5cm)}, y={(1cm,0cm)}, z={(0cm,1cm)}, scale=4]
\foreach \z in {0,1}  \foreach \y in {0,1}  \foreach  \x in {0,1}
{\coordinate (\x\y\z) at  (\x,\y,\z) ;}

\coordinate (O) at  ($(000)!0.5!(110)$);
\coordinate (P) at  ($(001)!0.5!(111)$);

\fill[fill opacity=.5,blue!30] (O)
\foreach \pt in {P,011,010}{--(\pt.center)}--cycle;%

\fill[fill opacity=.5,red!30] (000)
\foreach \pt in {110,111,001}{--(\pt.center)}--cycle;%

\fill[fill opacity=.5,blue!30] (O)
\foreach \pt in {P,101,100}{--(\pt.center)}--cycle;%

\draw[thick,double] (000.center)
\foreach \pt in {010,011,001}{--(\pt.center)}--cycle;%

\foreach \y in {0,1}  \foreach  \z in {0,1}
{\node[vertex] (0\y\z) at  (0\y\z) {};}

\draw[thick,double] (100.center)
\foreach \pt in {110,111,101}{--(\pt.center)}--cycle;%

\foreach \y in {0,1}  \foreach  \z in {0,1}
{\draw[thick,double] (0\y\z) -- (1\y\z);
\node[vertex] (1\y\z) at  (1\y\z) {};}
\end{tikzpicture}
\end{document}


• Thanks @Altermundus for your help. This is awesome. Would you mind to make little circle on every vertex? Thanks – MYaseen208 Feb 21 '12 at 6:49
• No problem but I need before explain some of the problems – Alain Matthes Feb 21 '12 at 7:18
• Okay. If you see the original figures, you can find small circles at very vertices, e.g. circles at (0, 0), (0, 1), etc. Thanks again for all your help. – MYaseen208 Feb 21 '12 at 7:21
• @Altermundus Just one minor comment about the first code exmple (there are so many:-). Redefing the labels using copy-and-paste sort of defeats the purpose of using the labels. It would be nicer if you could reuse the label commands. This can be done using incremental coordinates (or shifts). The second cube in my example reuses the coordinate labels. – user10274 Feb 21 '12 at 14:04
• I have another one because I have the beginning of a package that I made for my students. I don't understand exactly what you mean by "Redefing the labels using copy-and-paste". Is it the fact to use node after coordinate at the same position? What do you understand by "label commands". Sorry but my english is not very good! – Alain Matthes Feb 21 '12 at 15:03

Just for fun: a version that draws the planes in a 3D-like order, i.e. planes in the foreground are drawn last. This is a rather small modification of this answer. In both of the posts, it is rather straightforward to do the ordering because the normal vectors of all planes lie in a plane. Therefore, one only has to distinguish between 4 cases (at most).

\documentclass[tikz,border=3.14mm]{standalone}
\usepackage{tikz}
\usepackage{tikz-3dplot}
\usetikzlibrary{calc}
\newcommand{\DrawRectangularPlane}[4][]{\draw[#1]
#2 -- ++  #3 --++ #4 -- ++ ($-1*#3$) -- cycle;}
\newcommand{\DrawSinglePlane}[2][]{\ifcase#2
\or % 1 xz plane at y=-1
\DrawRectangularPlane[fill=red,#1]{({-2*cos(45)*\PlaneScale},{-2*sin(45)*\PlaneScale},-\PlaneScale)}
{(2*\PlaneScale,0,0)}{(0,0,2*\PlaneScale)}
\or% 2 xz plane at y=1
\DrawRectangularPlane[fill=blue,#1]{({-2*cos(45)*\PlaneScale},{2*sin(45)*\PlaneScale},-\PlaneScale)}
{(2*\PlaneScale,0,0)}{(0,0,2*\PlaneScale)}
\or% 3 yz plane at x=-1
\DrawRectangularPlane[fill=red,#1]{({-2*cos(45)*\PlaneScale},{-2*sin(45)*\PlaneScale},-\PlaneScale)}
{(0,2*\PlaneScale,0)}{(0,0,2*\PlaneScale)} %
\or% 4 yz plane at x=1
\DrawRectangularPlane[fill=blue,#1]{({2*cos(45)*\PlaneScale},{-2*sin(45)*\PlaneScale},-\PlaneScale)}
{(0,2*\PlaneScale,0)}{(0,0,2*\PlaneScale)} %
\or% 5 diagonal upper right quadrant
\DrawRectangularPlane[fill=blue,#1]{({2*cos(45)*\PlaneScale},{2*sin(45)*\PlaneScale},-\PlaneScale)}
{({-2*cos(45)*\PlaneScale},{-2*sin(45)*\PlaneScale},0)}{(0,0,2*\PlaneScale)}
\or% 6 diagonal upper left quadrant
\DrawRectangularPlane[fill=red,#1]{({-2*cos(45)*\PlaneScale},{2*sin(45)*\PlaneScale},-\PlaneScale)}
{({2*cos(45)*\PlaneScale},{-2*sin(45)*\PlaneScale},0)}{(0,0,2*\PlaneScale)}
\or% 7 diagonal lower right quadrant
\DrawRectangularPlane[fill=red,#1]{({2*cos(45)*\PlaneScale},{-2*sin(45)*\PlaneScale},-\PlaneScale)}
{({-2*cos(45)*\PlaneScale},{2*sin(45)*\PlaneScale},0)}{(0,0,2*\PlaneScale)}
\or %d iagonal lower left quadrant
\DrawRectangularPlane[fill=blue,#1]{({-2*cos(45)*\PlaneScale},{-2*sin(45)*\PlaneScale},-\PlaneScale)}
{({2*cos(45)*\PlaneScale},{2*sin(45)*\PlaneScale},0)}{(0,0,2*\PlaneScale)}
\fi
}
\begin{document}
\foreach \X in {0,5,...,355} % {70}
{\tdplotsetmaincoords{90+40*sin(\X)}{\X} % the first argument cannot be larger than 90
\pgfmathsetmacro{\PlaneScale}{1}
\begin{tikzpicture}
\path[use as bounding box] (-4*\PlaneScale,-4*\PlaneScale) rectangle (4*\PlaneScale,4*\PlaneScale);
\begin{scope}[tdplot_main_coords]
\pgfmathtruncatemacro{\xproj}{sign(cos(\tdplotmainphi-45))}
\pgfmathtruncatemacro{\zproj}{sign(sin(\tdplotmainphi-45))}
\ifnum\xproj=1
\ifnum\zproj=1
\foreach \X in {5,6,7,8}
{\DrawSinglePlane{\X}}
\else
\foreach \X in {8,6,7,5}
{\DrawSinglePlane{\X}}
\fi
\else
\ifnum\zproj=1
\foreach \X in {5,7,6,8}
{\DrawSinglePlane{\X}}
\else
\foreach \X in {6,5,8,7}
{\DrawSinglePlane{\X}}
\fi
\fi
% \draw[thick,->] (0,0,0) -- (2,0,0) node[anchor=north east]{$x$};
% \draw[thick,->] (0,0,0) -- (0,2,0) node[anchor=north west]{$y$};
% \draw[thick,->] (0,0,0) -- (0,0,1.5) node[anchor=south]{$z$};
\end{scope}
\end{tikzpicture}}
\end{document}


The case of two parallel planes is even simpler. One can the do the ordering with

\pgfmathtruncatemacro{\xproj}{sign(sin(\tdplotmainphi))}
%\node[anchor=north west] at (current bounding box.north west) {\tdplotmainphi,\xproj};
\ifnum\xproj=1
\foreach \X in {3,4}
{\DrawSinglePlane{\X}}
\else
\foreach \X in {4,3}
{\DrawSinglePlane{\X}}
\fi