# Incomplete cube

I want to draw an incomplete cube, as in the following figure.

But, I can only draw a complete cube, see below.

\documentclass[12pt]{article}
\usepackage{tikz}
\usepackage{verbatim}
\usetikzlibrary{positioning}
\begin{document}
\begin{tikzpicture}[on grid][scale=1.4]
(0,0) rectangle +(3,3);
\draw[yslant=-0.5] (0,0) grid (3,3);
(3,-3) rectangle +(3,3);
\draw[yslant=0.5] (3,-3) grid (6,0);
top color=white] (6,3) rectangle +(-3,-3);
\draw[yslant=0.5,xslant=-1] (3,0) grid (6,3);
\end{tikzpicture}
\end{document}


I would like to argue that one should use orthographic projections and write it in such a way that one can change the view angle. There are already many posts on this, perhaps most impressingly this one. The idea to use pics for the unit cubes to draw 3d cubes with some little cubes missing is also not new, it has been used here, where the cubes are rotatable in 3d. I just recycled the code to get

\documentclass[tikz,border=3.14mm]{standalone}
\usepackage{tikz-3dplot}
\usetikzlibrary{calc}
\tikzset{plane/.style n args={3}{insert path={%
#1 -- ++ #2 -- ++ #3 -- ++ ($-1*#2$) -- cycle}},
unit xy plane/.style={plane={#1}{(1,0,0)}{(0,1,0)}},
unit xz plane/.style={plane={#1}{(1,0,0)}{(0,0,1)}},
unit yz plane/.style={plane={#1}{(0,1,0)}{(0,0,1)}},
get projections/.style={insert path={%
let \p1=(1,0,0),\p2=(0,1,0)  in
[/utils/exec={\pgfmathtruncatemacro{\xproj}{sign(\x1)}\xdef\xproj{\xproj}
\pgfmathtruncatemacro{\yproj}{sign(\x2)}\xdef\yproj{\yproj}
\pgfmathtruncatemacro{\zproj}{sign(cos(\tdplotmaintheta))}\xdef\zproj{\zproj}}]}},
pics/unit cube/.style={code={
\path[get projections];
\draw (0,0,0) -- (1,1,1);
\ifnum\zproj=-1
\path[3d cube/every face,3d cube/xy face,unit xy plane={(0,0,0)}];
\fi
\ifnum\yproj=1
\path[3d cube/every face,3d cube/yz face,unit yz plane={(1,0,0)}];
\else
\path[3d cube/every face,3d cube/yz face,unit yz plane={(0,0,0)}];
\fi
\ifnum\xproj=1
\path[3d cube/every face,3d cube/xz face,unit xz plane={(0,0,0)}];
\else
\path[3d cube/every face,3d cube/xz face,unit xz plane={(0,1,0)}];
\fi
\ifnum\zproj>-1
\path[3d cube/every face,3d cube/xy face,unit xy plane={(0,0,1)}];
\fi
}},
3d cube/.cd,
xy face/.style={fill=gray!20},
xz face/.style={fill=gray!50},
yz face/.style={fill=gray!90},
every face/.style={draw,very thick}
}
\begin{document}
\foreach \Angle in {5,15,...,355}
{\tdplotsetmaincoords{60}{\Angle} % the first argument cannot be larger than 90
\begin{tikzpicture}[line join=round]
\pgfmathtruncatemacro{\NumCubes}{7}
\path[use as bounding box] (-\NumCubes/2-3,-\NumCubes/2-2)
rectangle (\NumCubes/2+3,\NumCubes/2+4);
\begin{scope}[tdplot_main_coords]
\pgfmathtruncatemacro{\NextToLast}{\NumCubes-1}
\path[get projections];
\ifnum\yproj=1
\def\LstX{1,2,3}
\else
\def\LstX{3,2,1}
\fi
\ifnum\xproj=-1
\def\LstY{1,2,3}
\else
\def\LstY{3,2,1}
\fi
\foreach \X in \LstX
{\foreach \Y in \LstY
{\ifnum\Y=3
\pgfmathtruncatemacro{\Zmax}{5-max(\X,2)}
\else
\pgfmathtruncatemacro{\Zmax}{4-\X}
\fi
\foreach \Z in {1,...,\Zmax}
{\path (\X-2,\Y-2,\Z-1) pic{unit cube};}}
}
\end{scope}
\end{tikzpicture}}
\end{document}


• "I would like to argue that one should use orthographic projections". Spoken like a true engineer! +1 Apr 1, 2019 at 14:13

You can define a single cube as pic and place it where you want (starting from bottom back to top front).

\documentclass[tikz,border=7pt]{standalone}
\tikzset{
cube/.pic={
\draw[fill=black!20] (0,1,0) -- (0,1,1) -- (1,1,1) -- (1,1,0);
\draw[fill=black!50] (1,0,0) -- (1,0,1) -- (1,1,1) -- (1,1,0);
\draw[fill=white] (0,0,0) rectangle (1,1,0);
}
}
\begin{document}
\tikz[z={(.4,.3)}]\path\pgfextra{\def~{pic{cube}}} % <--- to make the code shorter
(2,0,2)~(2,0,1)~(0,0,0)~(1,0,0)~(2,0,0)~
(2,1,2)~(1,1,1)~(0,1,0)~(1,1,0)~
(0,2,2)~(1,2,2)~(0,2,1)~(0,2,0)~;
\end{document}


• ...better to use the redefined ~ version inside a group, even if it's just to shorten your code. As in, \begingroup \def~{pic{code}} \begin{tikzpicture} ... \end{tikzpicture}.
– Werner
Apr 1, 2019 at 19:22
• @Werner Agree, thanks. Done.
– Kpym
Apr 1, 2019 at 19:30
• The \pgfextra and {...} only to avoid { and }?  \tikz[z={(.4,.3)}]{\def~{pic{cube}} \path (2,0,2)~(2,0,1)~(0,0,0)~(1,0,0)~(2,0,0)~ (2,1,2)~(1,1,1)~(0,1,0)~(1,1,0)~ (0,2,2)~(1,2,2)~(0,2,1)~(0,2,0)~;}
– user121799
Apr 1, 2019 at 20:23
• @marmot I never avoid shorter code in general ;) But here, as redefining ~ is not a good practice, I decided to follow the comment of @Werner and to make its definition as local as possible : so local to the path is better to local for the entire tikz.
– Kpym
Apr 1, 2019 at 20:49
• If that's your aim:\documentclass[tikz,border=7pt]{standalone} \tikzset{ cube/.pic={ \draw[fill=black!20] (0,1,0) -- (0,1,1) -- (1,1,1) -- (1,1,0); \draw[fill=black!50] (1,0,0) -- (1,0,1) -- (1,1,1) -- (1,1,0); \draw[fill=white] (0,0,0) rectangle (1,1,0); },icube/.style={insert path={#1 pic{cube}}} } \begin{document} \tikz[z={(.4,.3)}]\path[icube/.list={(2,0,2),(2,0,1),(0,0,0),(1,0,0),(2,0,0), (2,1,2),(1,1,1),(0,1,0),(1,1,0), (0,2,2),(1,2,2),(0,2,1),(0,2,0)}]; \end{document}
– user121799
Apr 1, 2019 at 20:59

Just for fun: everything is in 2D

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}
\draw (0,0) rectangle (1,1) (1,1) rectangle (2,2) (0,1) rectangle (1,2) (0,2) rectangle (1,3) (1,0) rectangle (2,1) (2,0) rectangle (3,1);
\draw (3.6,1.6)--(3.6,.6)--(3,0)--(3,1)--cycle--(3.6,2.6)--(2.6,2.6)--(2.6,3.6)--(.6,3.6)--(0,3);
\draw (2,1)--(2.4,1.4) (2,2)--(2.6,2.6) (1,2)--(1.4,2.4) (1,3)--(1.6,3.6) (2.4,3.4)--(2.6,3.6) (3.4,2.4)--(3.6,2.6);
\draw (2.4,1.4) rectangle (3.4,2.4) (1.4,2.4) rectangle (2.4,3.4);
\draw (.4,3.4)--(1.4,3.4) (3.4,1.4)--(3.4,.4) (.2,3.2)--(1.2,3.2)--(1.2,2.2)--(2.2,2.2)--(2.2,1.2)--(3.2,1.2)--(3.2,.2);
\end{tikzpicture}
\end{document}


With colors

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}
\fill[black!70] (3,0)--(3.6,.6)--(3.6,2.6)--(3.4,2.4)--(3.4,1.4)--(3,1)--cycle (2.4,2.4)--(2.6,2.6)--(2.6,3.6)--(2.4,3.4)--(2.4,1.4)--(2,1)--(2,2)--cycle (1,2)--(1.4,2.4)--(1.4,3.4)--(1,3)--cycle;
\fill[black!30] (0,3)--(.6,3.6)-_(2.6,3.6)--(2.4,3.4)--(1.4,3.4)--(1,3)--cycle (2.4,2.4)--(2.6,2.6)--(3.6,2.6)--(3.4,2.4)--(1.4,2.4)--(1,2)--(2,2)--cycle (2,1)--(2.4,1.4)--(3.4,1.4)--(3,1)--cycle;
\draw (0,0) rectangle (1,1) (1,1) rectangle (2,2) (0,1) rectangle (1,2) (0,2) rectangle (1,3) (1,0) rectangle (2,1) (2,0) rectangle (3,1);
\draw (3.6,1.6)--(3.6,.6)--(3,0)--(3,1)--cycle--(3.6,2.6)--(2.6,2.6)--(2.6,3.6)--(.6,3.6)--(0,3);
\draw (2,1)--(2.4,1.4) (2,2)--(2.6,2.6) (1,2)--(1.4,2.4) (1,3)--(1.6,3.6) (2.4,3.4)--(2.6,3.6) (3.4,2.4)--(3.6,2.6);
\draw (2.4,1.4) rectangle (3.4,2.4) (1.4,2.4) rectangle (2.4,3.4);
\draw (.4,3.4)--(1.4,3.4) (3.4,1.4)--(3.4,.4) (.2,3.2)--(1.2,3.2)--(1.2,2.2)--(2.2,2.2)--(2.2,1.2)--(3.2,1.2)--(3.2,.2);
\end{tikzpicture}
\end{document}