3

The following LaTeX code, which is modelled after this answer, was saved in ~/Test.tex.

\documentclass[tikz,border=1cm]{standalone}
\newcommand{\tikzcube}[2][1]{% scale, side length
   \begin{tikzpicture}[scale=#1]
      \foreach \x in {0,...,#2}
      {
         \draw (\x,0,#2) -- (\x,#2,#2);
         \draw (\x,#2,#2) -- (\x,#2,0);
      }
      \foreach \x in {0,...,#2}
      {
         \draw (#2,\x,#2) -- (#2,\x,0);
         \draw (0,\x,#2) -- (#2,\x,#2);
      }
      \foreach \x in {0,...,#2}
      {
         \draw (#2,0,\x) -- (#2,#2,\x);
         \draw (0,#2,\x) -- (#2,#2,\x);
      }
   \end{tikzpicture}%
}
\begin{document}
\tikzcube{3}
\end{document}

Then the following commands were executed in the Terminal.

> cd ~
> lualatex Test

Consequently the file ~/Test.pdf was created. When opened in a PDF viewer, the file displayed as follows.

A cube

Consider this cube to be built from three levels that are arranged in a tower, one on top of the other.

I'd like to be able to specify a color and a level, and for the corresponding level to be colored with the specified color.

The cube should be considered opaque, and therefore the color should only affect the external walls. Consequently, when the top level is specified, the color should affect the two visible sides as well as the "roof", however when one of the other levels is specified, the color should affect only the sides.

The cube needs not have 3 levels; it can have any number of them: 1, 2, 3, 4, 5, etc. No matter how many levels it has, it remains a cube.

Evan Aad
  • 11,066

2 Answers2

5

You can observe that a level is drawn in the second foreach loop: on the side the line (#2,\x,#2) -- (#2,\x,0) and in the front the line (0,\x,#2) -- (#2,\x,#2). You can color a level by filling the area between the line for \x and the line for \x+1 with zero-indexed levels, or the area between the lines for \x-1 and \x with one-indexed levels as I did in the MWE below.

The top is the polygon between the four corners (0,max,0), (0,max,max), (max,max,max) and (max,max,0).

MWE:

\documentclass{article}
\usepackage{tikz}
\newcommand{\tikzcube}[2][1]{% scale, side length
   \begin{tikzpicture}[scale=#1]
      \edef\lvprev{\numexpr\cllv-1}
      % side
      \fill[\lvcl] (#2,\lvprev,#2) -- (#2,\lvprev,0) -- (#2,\cllv,0) -- (#2,\cllv,#2) -- cycle;
      % front
      \fill[\lvcl] (0,\lvprev,#2) -- (#2,\lvprev,#2) -- (#2,\cllv,#2) -- (0,\cllv,#2) -- cycle;
      % top
      \ifnum\cllv=#2\relax
      \fill[\lvcl] (0,#2,0) -- (0,#2,#2) -- (#2,#2,#2) -- (#2,#2,0) -- cycle;
      \fi
      \foreach \x in {0,...,#2}
      {
         \draw (\x,0,#2) -- (\x,#2,#2);
         \draw (\x,#2,#2) -- (\x,#2,0);
      }
      \foreach \x in {0,...,#2}
      {
         \draw (#2,\x,#2) -- (#2,\x,0);
         \draw (0,\x,#2) -- (#2,\x,#2);
      }
      \foreach \x in {0,...,#2}
      {
         \draw (#2,0,\x) -- (#2,#2,\x);
         \draw (0,#2,\x) -- (#2,#2,\x);
      }
   \end{tikzpicture}%
}
\begin{document}
\def\lvcl{blue}
\def\cllv{2}
\tikzcube{3}
\def\lvcl{green}
\def\cllv{5}
\tikzcube{5}
\end{document}.

Result:

enter image description here

Marijn
  • 37,699
4

For drawings that are only in the planes orthogonal to the axes the simple 3d library and its canvas is ?? plane at ? styles make it rather easy to draw this cube since we can then use the rectangle path operation to draw each square without having to write down all four corners.

The following picture

  • iterates through all levels,
    • then iterates through all the three sides and
      • then finally iterates through all level squares on that side on that level.

We even use this for the top side but force it to use the style of the highest level.

Code

\documentclass[tikz]{standalone}
\usetikzlibrary{3d}
\newcommand*{\tikzOpaqueCube}[2][1]{%
\begin{tikzpicture}[
  l/.style args={##1:##2}{opaque cube/level ##1/.append style={fill=##2}},
  L/.style 2 args={
    /utils/temp/.style={opaque cube/level ####1/.append style={##2}},
    /utils/temp/.list={##1}},#1]
\foreach \level in {1,...,#2}{
  \foreach \xyz/\plane/\Level in {
    z/xy/\level, % the front side → uses style of current \level
    x/zy/\level, % the right side → uses style of current \level
    y/xz/#2}{    % the top side   → force style of top level
    \foreach \llevel in {1, ..., #2} {
      \draw[
        line join=round,
        canvas is \plane\space plane at \xyz={#2},
        opaque cube/level \Level/.try]
        (xyz cs: x=\llevel-1, y=\level-1) rectangle
        (xyz cs: x=\llevel,   y=\level  );
    }
  }
}
\end{tikzpicture}}
\begin{document}
\tikzOpaqueCube[
  l=1:red, l=3:green, l=5:blue,
  L={2,4}{rounded corners},
]{5}
\end{document}

Output

enter image description here

Qrrbrbirlbel
  • 119,821
  • 1
    There is a strange visual effect where the bottom of the cube looks wider than the top. – Simd Nov 27 '22 at 14:17