33

I'm working on a figure where I need a 3D cube. My plan was to create a 2D set of nodes, then draw the top and right side of the cube, and lastly draw the missing lines. I got this far until I ran into trouble:

enter image description here

I can't get the side to align properly with the face of the cube. Also, I have a vague idea on how to draw the lines but I bet I will have problems with that, too.

Here's the code:

\documentclass[a4paper, 11pt]{article}

\usepackage[rgb]{xcolor}
\usepackage{tikz}
\usetikzlibrary{shapes,arrows}
\usetikzlibrary{positioning}
\usetikzlibrary{calc}

\definecolor{shade0}{named}{white}
\definecolor{shade1}{rgb}{0.9, 0.9, 0.9}
\definecolor{shade2}{rgb}{0.8, 0.8, 0.8}
\definecolor{shade3}{rgb}{0.65, 0.65, 0.65}
\definecolor{shade4}{rgb}{0.45, 0.45, 0.45}

\newlength{\gpgpuElemSize}
\setlength{\gpgpuElemSize}{8mm}
\newlength{\gpgpuElemSep}
\setlength{\gpgpuElemSep}{1mm}

\begin{document}
\begin{tikzpicture}[%
    auto,
    box/.style={%
      draw,
      rectangle,
      semithick,
    },
    thread-s/.style={
      draw,
      semithick,
      fill=shade1,
    },
    thread/.style={%
      box,
      thread-s,
      minimum size=0.5\gpgpuElemSize,
      inner sep=0,
      node distance=0pt,
    },
  ]

  % Draw boxes
  \foreach \i in {1, ..., 4} {%
    \foreach \j in {1, ..., 4} {%
      \ifnum \j=1
        \ifnum \i=1
          \node [thread] (thread\i-\j) {};
        \else
          \pgfmathtruncatemacro\prevI{\i-1}
          \node [thread, below=of thread\prevI-1, yshift=\pgflinewidth]
            (thread\i-\j) {};
        \fi
      \else
        \pgfmathtruncatemacro\prevJ{\j-1}
        \node [thread, right=of thread\i-\prevJ, xshift=-\pgflinewidth]
          (thread\i-\j) {};
      \fi
    }
  }

  % Create 3D perspective
  \path let \p1 = (thread4-4.south east),
            \p2 = (thread1-4.north east)
         in
           [thread-s]
           (thread1-4.north east) -- ++(30:0.5\gpgpuElemSize)
           -- ++(0, \y1-\y2-\pgflinewidth) -- (thread4-4.south east) --   
           cycle;
\end{tikzpicture}
\end{document}
2
  • 1
    Drawing a cube is a common TikZ task and there are several variants presented at this question: tex.stackexchange.com/q/12020/86. Try out some of those first. If nothing suits there then please edit your question to explain exactly what it is that doesn't fit for you. That'll help us focus on exactly what you're trying to achieve and so give you a better answer. Sep 29, 2011 at 8:21
  • 2
    As Tom's version is not on the question I linked to, this seems a good case for a merge since people who find either question might find any of the answers useful. I'm going to flag it as such and let the moderators decide. Sep 29, 2011 at 10:44

3 Answers 3

83

Using a single \foreach loop with different uses in the coordinates is much easier:

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
\foreach \x in{0,...,4}
{   \draw (0,\x ,4) -- (4,\x ,4);
    \draw (\x ,0,4) -- (\x ,4,4);
    \draw (4,\x ,4) -- (4,\x ,0);
    \draw (\x ,4,4) -- (\x ,4,0);
    \draw (4,0,\x ) -- (4,4,\x );
    \draw (0,4,\x ) -- (4,4,\x );
}
\end{tikzpicture}

\end{document}

enter image description here


Edit 1: I generalized it a little, now you can draw cuboids by simply specifying the diemnsions and the scale (and also cubes of size n):

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}

\newcommand{\tikzcuboid}[4]{% width, height, depth, scale
\begin{tikzpicture}[scale=#4]
\foreach \x in {0,...,#1}
{   \draw (\x ,0  ,#3 ) -- (\x ,#2 ,#3 );
    \draw (\x ,#2 ,#3 ) -- (\x ,#2 ,0  );
}
\foreach \x in {0,...,#2}
{   \draw (#1 ,\x ,#3 ) -- (#1 ,\x ,0  );
    \draw (0  ,\x ,#3 ) -- (#1 ,\x ,#3 );
}
\foreach \x in {0,...,#3}
{   \draw (#1 ,0  ,\x ) -- (#1 ,#2 ,\x );
    \draw (0  ,#2 ,\x ) -- (#1 ,#2 ,\x );
}
\end{tikzpicture}
}

\newcommand{\tikzcube}[2]{% length, scale
\tikzcuboid{#1}{#1}{#1}{#2}
}

\begin{document}

\tikzcuboid{11}{7}{5}{0.5}

\tikzcube{13}{0.25}

\end{document}

Furthermore one could improve upon this e.g. by:

  • specifying the density of lines for each dimension
  • rotating the cuboid
  • defining the coordinate axes (e.g. specify an angle for each)
  • use colored/thick/dashed lines
  • use it in a scope rather than a tikzpicture environment so it can be used together with other things
  • parameters for X- and Y-fhift (again for use along with other things in a tikzpicture)

Also one could probably:

  • use quadrilaterals instead of lines, so one can use fillings, shadings etc.
  • specify a shading pattern (either for whole faces or each individual quadrilateral)

Probably I will get to this, but don't bet on it ;)

enter image description here


Edit 2: Turns out I had some spare time today ;)

Done:

  • shiftx
  • shifty
  • dimx
  • dimy
  • dimz
  • scale
  • densityx
  • densityy
  • densityz
  • rotation

Remains:

  • anglex
  • angley
  • anglez
  • scalex
  • scaley
  • scalez
  • linefront
  • linetop
  • lineright
  • fillfront
  • filltop
  • fillright
  • newcoords
  • shaded

newcoords and shaded are switches (which are unused so far). Note that the densitys must fullfill K/densityA = dimensionA for natural numbers K, otherwise strange effects occur (basically this means that each face must be divided in a whole number of segments; for dimension=3 and density=0.5 one would draw a line every 2 centimeters, so it would be 1.5 segments, which is not good)

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm,landscape]{geometry}
\usepackage{tikz}
\usepackage{keyval}
\usepackage{ifthen}

\makeatletter
% Standard Values for Parameters
\newcommand{\tikzcuboid@shiftx}{0}
\newcommand{\tikzcuboid@shifty}{0}
\newcommand{\tikzcuboid@dimx}{4}
\newcommand{\tikzcuboid@dimy}{4}
\newcommand{\tikzcuboid@dimz}{4}
\newcommand{\tikzcuboid@scale}{1}
\newcommand{\tikzcuboid@densityx}{1}
\newcommand{\tikzcuboid@densityy}{1}
\newcommand{\tikzcuboid@densityz}{1}
\newcommand{\tikzcuboid@rotation}{0}
\newcommand{\tikzcuboid@anglex}{0}
\newcommand{\tikzcuboid@angley}{90}
\newcommand{\tikzcuboid@anglez}{225}
\newcommand{\tikzcuboid@scalex}{1}
\newcommand{\tikzcuboid@scaley}{1}
\newcommand{\tikzcuboid@scalez}{1}
\newcommand{\tikzcuboid@linefront}{}
\newcommand{\tikzcuboid@linetop}{}
\newcommand{\tikzcuboid@lineright}{}
\newcommand{\tikzcuboid@fillfront}{}
\newcommand{\tikzcuboid@filltop}{}
\newcommand{\tikzcuboid@fillright}{}
\newcommand{\tikzcuboid@newcoords}{N}
\newcommand{\tikzcuboid@filled}{N}
\newcommand{\tikzcuboid@shaded}{N}
% Definition of Keys
\define@key{tikzcuboid}{shiftx}[\tikzcuboid@shiftx]{\renewcommand{\tikzcuboid@shiftx}{#1}}
\define@key{tikzcuboid}{shifty}[\tikzcuboid@shifty]{\renewcommand{\tikzcuboid@shifty}{#1}}
\define@key{tikzcuboid}{dimx}[\tikzcuboid@dimx]{\renewcommand{\tikzcuboid@dimx}{#1}}
\define@key{tikzcuboid}{dimy}[\tikzcuboid@dimy]{\renewcommand{\tikzcuboid@dimy}{#1}}
\define@key{tikzcuboid}{dimz}[\tikzcuboid@dimz]{\renewcommand{\tikzcuboid@dimz}{#1}}
\define@key{tikzcuboid}{scale}[\tikzcuboid@scale]{\renewcommand{\tikzcuboid@scale}{#1}}
\define@key{tikzcuboid}{densityx}[\tikzcuboid@densityx]{\renewcommand{\tikzcuboid@densityx}{#1}}
\define@key{tikzcuboid}{densityy}[\tikzcuboid@densityy]{\renewcommand{\tikzcuboid@densityy}{#1}}
\define@key{tikzcuboid}{densityz}[\tikzcuboid@densityz]{\renewcommand{\tikzcuboid@densityz}{#1}}
\define@key{tikzcuboid}{rotation}[\tikzcuboid@rotation]{\renewcommand{\tikzcuboid@rotation}{#1}}
\define@key{tikzcuboid}{anglex}[\tikzcuboid@anglex]{\renewcommand{\tikzcuboid@anglex}{#1}}
\define@key{tikzcuboid}{angley}[\tikzcuboid@angley]{\renewcommand{\tikzcuboid@angley}{#1}}
\define@key{tikzcuboid}{anglez}[\tikzcuboid@anglez]{\renewcommand{\tikzcuboid@anglez}{#1}}
\define@key{tikzcuboid}{scalex}[\tikzcuboid@scalex]{\renewcommand{\tikzcuboid@scalex}{#1}}
\define@key{tikzcuboid}{scaley}[\tikzcuboid@scaley]{\renewcommand{\tikzcuboid@scaley}{#1}}
\define@key{tikzcuboid}{scalez}[\tikzcuboid@scalez]{\renewcommand{\tikzcuboid@scalez}{#1}}
\define@key{tikzcuboid}{linefront}[\tikzcuboid@linefront]{\renewcommand{\tikzcuboid@linefront}{#1}}
\define@key{tikzcuboid}{linetop}[\tikzcuboid@linetop]{\renewcommand{\tikzcuboid@linetop}{#1}}
\define@key{tikzcuboid}{lineright}[\tikzcuboid@lineright]{\renewcommand{\tikzcuboid@lineright}{#1}}
\define@key{tikzcuboid}{fillfront}[\tikzcuboid@fillfront]{\renewcommand{\tikzcuboid@fillfront}{#1}}
\define@key{tikzcuboid}{filltop}[\tikzcuboid@filltop]{\renewcommand{\tikzcuboid@filltop}{#1}}
\define@key{tikzcuboid}{fillright}[\tikzcuboid@fillright]{\renewcommand{\tikzcuboid@fillright}{#1}}
\define@key{tikzcuboid}{newcoords}[\tikzcuboid@newcoords]{\renewcommand{\tikzcuboid@newcoords}{#1}}
\define@key{tikzcuboid}{filled}[\tikzcuboid@filled]{\renewcommand{\tikzcuboid@filled}{#1}}
\define@key{tikzcuboid}{shaded}[\tikzcuboid@shaded]{\renewcommand{\tikzcuboid@shaded}{#1}}
% Commands
\newcommand{\tikzcuboid}[1]{
    \setkeys{tikzcuboid}{#1} % Process Keys passed to command
    \begin{scope}[xshift=\tikzcuboid@shiftx,yshift=\tikzcuboid@shifty,scale=\tikzcuboid@scale,rotate=\tikzcuboid@rotation]
    \pgfmathsetmacro{\steppingx}{1/\tikzcuboid@densityx}
    \pgfmathsetmacro{\steppingy}{1/\tikzcuboid@densityy}
    \pgfmathsetmacro{\steppingz}{1/\tikzcuboid@densityz}
    \newcommand{\dimx}{\tikzcuboid@dimx}
    \newcommand{\dimy}{\tikzcuboid@dimy}
    \newcommand{\dimz}{\tikzcuboid@dimz}
    \pgfmathsetmacro{\secondx}{2*\steppingx}
    \pgfmathsetmacro{\secondy}{2*\steppingy}
    \pgfmathsetmacro{\secondz}{2*\steppingz}
    \foreach \x in {\steppingx,\secondx,...,\dimx}
    {   \foreach \y in {\steppingy,\secondy,...,\dimy}
        {   \pgfmathsetmacro{\lowx}{(\x-\steppingx)}
            \pgfmathsetmacro{\lowy}{(\y-\steppingy)}
            \filldraw[fill=orange,draw=blue] (\lowx,\lowy,\dimz) -- (\lowx,\y,\dimz) -- (\x,\y,\dimz) -- (\x,\lowy,\dimz) -- cycle;

        }
    }
    \foreach \x in {\steppingx,\secondx,...,\dimx}
    {   \foreach \z in {\steppingz,\secondz,...,\dimz}
        {   \pgfmathsetmacro{\lowx}{(\x-\steppingx)}
            \pgfmathsetmacro{\lowz}{(\z-\steppingz)}
            \filldraw[fill=green,draw=red] (\lowx,\dimy,\lowz) -- (\lowx,\dimy,\z) -- (\x,\dimy,\z) -- (\x,\dimy,\lowz) -- cycle;
        }
    }
    \foreach \y in {\steppingy,\secondy,...,\dimy}
    {   \foreach \z in {\steppingz,\secondz,...,\dimz}
        {   \pgfmathsetmacro{\lowy}{(\y-\steppingy)}
            \pgfmathsetmacro{\lowz}{(\z-\steppingz)}
            \filldraw[fill=red!50!blue,draw=yellow] (\dimx,\lowy,\lowz) -- (\dimx,\lowy,\z) -- (\dimx,\y,\z) -- (\dimx,\y,\lowz) -- cycle;
        }
    }
    \end{scope}

    % Write parameters to log file, just for checking       
%   \typeout{=============================}
%   \typeout{*****************************}
%   \typeout{tikzcuboid shiftx = \tikzcuboid@shiftx}
%   \typeout{tikzcuboid shifty = \tikzcuboid@shifty}
%   \typeout{tikzcuboid dimx = \tikzcuboid@dimx}
%   \typeout{tikzcuboid dimy = \tikzcuboid@dimy}
%   \typeout{tikzcuboid dimz = \tikzcuboid@dimz}
%   \typeout{tikzcuboid scale = \tikzcuboid@scale}
%   \typeout{tikzcuboid densityx = \tikzcuboid@densityx}
%   \typeout{tikzcuboid densityy = \tikzcuboid@densityy}
%   \typeout{tikzcuboid densityz = \tikzcuboid@densityz}
%   \typeout{tikzcuboid rotation = \tikzcuboid@rotation}
%   \typeout{tikzcuboid anglex = \tikzcuboid@anglex}
%   \typeout{tikzcuboid angley = \tikzcuboid@angley}
%   \typeout{tikzcuboid anglez = \tikzcuboid@anglez}
%   \typeout{tikzcuboid scalex = \tikzcuboid@scalex}
%   \typeout{tikzcuboid scaley = \tikzcuboid@scaley}
%   \typeout{tikzcuboid scalez = \tikzcuboid@scalez}
%   \typeout{tikzcuboid linefront = \tikzcuboid@linefront}
%   \typeout{tikzcuboid linetop = \tikzcuboid@linetop}
%   \typeout{tikzcuboid lineright = \tikzcuboid@lineright}
%   \typeout{tikzcuboid fillfront = \tikzcuboid@fillfront}
%   \typeout{tikzcuboid filltop = \tikzcuboid@filltop}
%   \typeout{tikzcuboid fillright = \tikzcuboid@fillright}
%   \typeout{tikzcuboid newcoords = \tikzcuboid@newcoords}
%   \typeout{tikzcuboid filled = \tikzcuboid@filled}
%   \typeout{tikzcuboid shaded = \tikzcuboid@shaded}
%   \typeout{*****************************}
%   \typeout{=============================}
}

\makeatother

\begin{document}

\begin{tikzpicture}
    \tikzcuboid{shiftx=0cm,%
        shifty=0cm,%
        scale=1.00,%
        rotation=30,%
        densityx=1,%
        densityy=2,%
        densityz=3%
    }
    \tikzcuboid{%
        shiftx=0cm,%
        shifty=8cm,%
        scale=1.00,%
        rotation=60,%
        densityx=3,%
        densityy=2,%
        densityz=5%
    }
    \tikzcuboid{%
        shiftx=8cm,%
        shifty=8cm,%
        scale=1.00,%
        rotation=45,%
        densityx=0.5,%
        densityy=1,%
        densityz=2%
    }
    \tikzcuboid{%
        shiftx=8cm,%
        shifty=0cm,%
        scale=1.00,%
        rotation=75,%
        densityx=2,%
        densityy=7,%
        densityz=2%
    }
\end{tikzpicture}

\end{document}

And finally, some output (colors are just for showing off):

enter image description here


Edit 3: Now I have everythinh except for shading:

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm,landscape]{geometry}
\usepackage{tikz}
\usepackage{keyval}
\usepackage{ifthen}
%====================================
%emphasize vertices --> switch and emph style (e.g. thick,black)
%====================================
\makeatletter
% Standard Values for Parameters
\newcommand{\tikzcuboid@shiftx}{0}
\newcommand{\tikzcuboid@shifty}{0}
\newcommand{\tikzcuboid@dimx}{3}
\newcommand{\tikzcuboid@dimy}{3}
\newcommand{\tikzcuboid@dimz}{3}
\newcommand{\tikzcuboid@scale}{1}
\newcommand{\tikzcuboid@densityx}{1}
\newcommand{\tikzcuboid@densityy}{1}
\newcommand{\tikzcuboid@densityz}{1}
\newcommand{\tikzcuboid@rotation}{0}
\newcommand{\tikzcuboid@anglex}{0}
\newcommand{\tikzcuboid@angley}{90}
\newcommand{\tikzcuboid@anglez}{225}
\newcommand{\tikzcuboid@scalex}{1}
\newcommand{\tikzcuboid@scaley}{1}
\newcommand{\tikzcuboid@scalez}{sqrt(0.5)}
\newcommand{\tikzcuboid@linefront}{black}
\newcommand{\tikzcuboid@linetop}{black}
\newcommand{\tikzcuboid@lineright}{black}
\newcommand{\tikzcuboid@fillfront}{white}
\newcommand{\tikzcuboid@filltop}{white}
\newcommand{\tikzcuboid@fillright}{white}
\newcommand{\tikzcuboid@shaded}{N}
\newcommand{\tikzcuboid@shadecolor}{black}
\newcommand{\tikzcuboid@shadeperc}{25}
\newcommand{\tikzcuboid@emphedge}{N}
\newcommand{\tikzcuboid@emphstyle}{thick}

% Definition of Keys
\define@key{tikzcuboid}{shiftx}[\tikzcuboid@shiftx]{\renewcommand{\tikzcuboid@shiftx}{#1}}
\define@key{tikzcuboid}{shifty}[\tikzcuboid@shifty]{\renewcommand{\tikzcuboid@shifty}{#1}}
\define@key{tikzcuboid}{dimx}[\tikzcuboid@dimx]{\renewcommand{\tikzcuboid@dimx}{#1}}
\define@key{tikzcuboid}{dimy}[\tikzcuboid@dimy]{\renewcommand{\tikzcuboid@dimy}{#1}}
\define@key{tikzcuboid}{dimz}[\tikzcuboid@dimz]{\renewcommand{\tikzcuboid@dimz}{#1}}
\define@key{tikzcuboid}{scale}[\tikzcuboid@scale]{\renewcommand{\tikzcuboid@scale}{#1}}
\define@key{tikzcuboid}{densityx}[\tikzcuboid@densityx]{\renewcommand{\tikzcuboid@densityx}{#1}}
\define@key{tikzcuboid}{densityy}[\tikzcuboid@densityy]{\renewcommand{\tikzcuboid@densityy}{#1}}
\define@key{tikzcuboid}{densityz}[\tikzcuboid@densityz]{\renewcommand{\tikzcuboid@densityz}{#1}}
\define@key{tikzcuboid}{rotation}[\tikzcuboid@rotation]{\renewcommand{\tikzcuboid@rotation}{#1}}
\define@key{tikzcuboid}{anglex}[\tikzcuboid@anglex]{\renewcommand{\tikzcuboid@anglex}{#1}}
\define@key{tikzcuboid}{angley}[\tikzcuboid@angley]{\renewcommand{\tikzcuboid@angley}{#1}}
\define@key{tikzcuboid}{anglez}[\tikzcuboid@anglez]{\renewcommand{\tikzcuboid@anglez}{#1}}
\define@key{tikzcuboid}{scalex}[\tikzcuboid@scalex]{\renewcommand{\tikzcuboid@scalex}{#1}}
\define@key{tikzcuboid}{scaley}[\tikzcuboid@scaley]{\renewcommand{\tikzcuboid@scaley}{#1}}
\define@key{tikzcuboid}{scalez}[\tikzcuboid@scalez]{\renewcommand{\tikzcuboid@scalez}{#1}}
\define@key{tikzcuboid}{linefront}[\tikzcuboid@linefront]{\renewcommand{\tikzcuboid@linefront}{#1}}
\define@key{tikzcuboid}{linetop}[\tikzcuboid@linetop]{\renewcommand{\tikzcuboid@linetop}{#1}}
\define@key{tikzcuboid}{lineright}[\tikzcuboid@lineright]{\renewcommand{\tikzcuboid@lineright}{#1}}
\define@key{tikzcuboid}{fillfront}[\tikzcuboid@fillfront]{\renewcommand{\tikzcuboid@fillfront}{#1}}
\define@key{tikzcuboid}{filltop}[\tikzcuboid@filltop]{\renewcommand{\tikzcuboid@filltop}{#1}}
\define@key{tikzcuboid}{fillright}[\tikzcuboid@fillright]{\renewcommand{\tikzcuboid@fillright}{#1}}
\define@key{tikzcuboid}{shaded}[\tikzcuboid@shaded]{\renewcommand{\tikzcuboid@shaded}{#1}}
\define@key{tikzcuboid}{shadecolor}[\tikzcuboid@shadecolor]{\renewcommand{\tikzcuboid@shadecolor}{#1}}
\define@key{tikzcuboid}{shadeperc}[\tikzcuboid@shadeperc]{\renewcommand{\tikzcuboid@shadeperc}{#1}}
\define@key{tikzcuboid}{emphedge}[\tikzcuboid@emphedge]{\renewcommand{\tikzcuboid@emphedge}{#1}}
\define@key{tikzcuboid}{emphstyle}[\tikzcuboid@emphstyle]{\renewcommand{\tikzcuboid@emphstyle}{#1}}
% Commands
\newcommand{\tikzcuboid}[1]{
    \setkeys{tikzcuboid}{#1} % Process Keys passed to command
    \pgfmathsetmacro{\vectorxx}{\tikzcuboid@scalex*cos(\tikzcuboid@anglex)}
    \pgfmathsetmacro{\vectorxy}{\tikzcuboid@scalex*sin(\tikzcuboid@anglex)}
    \pgfmathsetmacro{\vectoryx}{\tikzcuboid@scaley*cos(\tikzcuboid@angley)}
    \pgfmathsetmacro{\vectoryy}{\tikzcuboid@scaley*sin(\tikzcuboid@angley)}
    \pgfmathsetmacro{\vectorzx}{\tikzcuboid@scalez*cos(\tikzcuboid@anglez)}
    \pgfmathsetmacro{\vectorzy}{\tikzcuboid@scalez*sin(\tikzcuboid@anglez)}
    \begin{scope}[xshift=\tikzcuboid@shiftx, yshift=\tikzcuboid@shifty, scale=\tikzcuboid@scale, rotate=\tikzcuboid@rotation, x={(\vectorxx,\vectorxy)}, y={(\vectoryx,\vectoryy)}, z={(\vectorzx,\vectorzy)}]
    \pgfmathsetmacro{\steppingx}{1/\tikzcuboid@densityx}
    \pgfmathsetmacro{\steppingy}{1/\tikzcuboid@densityy}
    \pgfmathsetmacro{\steppingz}{1/\tikzcuboid@densityz}
    \newcommand{\dimx}{\tikzcuboid@dimx}
    \newcommand{\dimy}{\tikzcuboid@dimy}
    \newcommand{\dimz}{\tikzcuboid@dimz}
    \pgfmathsetmacro{\secondx}{2*\steppingx}
    \pgfmathsetmacro{\secondy}{2*\steppingy}
    \pgfmathsetmacro{\secondz}{2*\steppingz}
    \foreach \x in {\steppingx,\secondx,...,\dimx}
    {   \foreach \y in {\steppingy,\secondy,...,\dimy}
        {   \pgfmathsetmacro{\lowx}{(\x-\steppingx)}
            \pgfmathsetmacro{\lowy}{(\y-\steppingy)}
            \filldraw[fill=\tikzcuboid@fillfront,draw=\tikzcuboid@linefront] (\lowx,\lowy,\dimz) -- (\lowx,\y,\dimz) -- (\x,\y,\dimz) -- (\x,\lowy,\dimz) -- cycle;

        }
    }
    \foreach \x in {\steppingx,\secondx,...,\dimx}
    {   \foreach \z in {\steppingz,\secondz,...,\dimz}
        {   \pgfmathsetmacro{\lowx}{(\x-\steppingx)}
            \pgfmathsetmacro{\lowz}{(\z-\steppingz)}
            \filldraw[fill=\tikzcuboid@filltop,draw=\tikzcuboid@linetop] (\lowx,\dimy,\lowz) -- (\lowx,\dimy,\z) -- (\x,\dimy,\z) -- (\x,\dimy,\lowz) -- cycle;
        }
    }
    \foreach \y in {\steppingy,\secondy,...,\dimy}
    {   \foreach \z in {\steppingz,\secondz,...,\dimz}
        {   \pgfmathsetmacro{\lowy}{(\y-\steppingy)}
            \pgfmathsetmacro{\lowz}{(\z-\steppingz)}
            \filldraw[fill=\tikzcuboid@fillright,draw=\tikzcuboid@lineright] (\dimx,\lowy,\lowz) -- (\dimx,\lowy,\z) -- (\dimx,\y,\z) -- (\dimx,\y,\lowz) -- cycle;
        }
    }
    \ifthenelse{\equal{\tikzcuboid@emphedge}{Y}}%
        {\draw[\tikzcuboid@emphstyle](0,\dimy,0) -- (\dimx,\dimy,0) -- (\dimx,\dimy,\dimz) -- (0,\dimy,\dimz) -- cycle;%
        \draw[\tikzcuboid@emphstyle] (0,0,\dimz) -- (0,\dimy,\dimz) -- (\dimx,\dimy,\dimz) -- (\dimx,0,\dimz) -- cycle;%
        \draw[\tikzcuboid@emphstyle](\dimx,0,0) -- (\dimx,\dimy,0) -- (\dimx,\dimy,\dimz) -- (\dimx,0,\dimz) -- cycle;%
        }%
        {}
    \end{scope}
}

\makeatother

\begin{document}

\begin{tikzpicture}
    \tikzcuboid{shiftx=0cm,%
        shifty=0cm,%
        scale=1.00,%
        rotation=30,%
        densityx=1,%
        densityy=2,%
        densityz=3,%
        dimx=4,%
        dimy=5,%
        dimy=2,%
        linefront=yellow!30!black,%
        linetop=red!30!black,%
        lineright=blue!30!black,%
        fillfront=yellow!30!white,%
        filltop=red!30!white,%
        fillright=blue!30!white%
    }
    \tikzcuboid{%
        shiftx=0cm,%
        shifty=8cm,%
        scale=1.00,%
        rotation=60,%
        densityx=3,%
        densityy=2,%
        densityz=5,%
        dimx=4,%
        dimy=4,%
        dimy=4,%
        linefront=orange!75!black,%
        linetop=green!75!black,%
        lineright=violet!75!black,%
        fillfront=orange!75!white,%
        filltop=green!75!white,%
        fillright=violet!75!white%
    }
    \tikzcuboid{%
        shiftx=8cm,%
        shifty=8cm,%
        scale=1.00,%
        rotation=45,%
        densityx=1,%
        densityy=(2/3),%
        densityz=2,%
        dimx=3,%
        dimy=3,%
        dimy=3,%
        linefront=white!15!black,%
        linetop=white!30!black,%
        lineright=white!45!black,%
        fillfront=black!15!white,%
        filltop=black!30!white,%
        fillright=black!45!white%
    }
    \tikzcuboid{%
        shiftx=8cm,%
        shifty=0cm,%
        scale=1.00,%
        rotation=75,%
        densityx=2,%
        densityy=3,%
        densityz=2,%
        dimx=6,%
        dimy=8,%
        dimy=1,%
        linefront=red!75!black,%
        linetop=red!50!black,%
        lineright=red!25!black,%
        fillfront=red!25!white,%
        filltop=red!50!white,%
        fillright=red!75!white%
    }
    \tikzcuboid{%
        shiftx=16cm,%
        shifty=8cm,%
        scale=1.00,%
        rotation=0,%
        densityx=2,%
        densityy=2,%
        densityz=2,%
        dimx=4,%
        dimy=4,%
        dimy=4,%
        linefront=green!75!black,%
        linetop=green!50!black,%
        lineright=green!25!black,%
        fillfront=green!25!white,%
        filltop=green!50!white,%
        fillright=green!75!white,%
        emphedge=Y,%
        emphstyle=very thick,
    }
    \tikzcuboid{%
        shiftx=16cm,%
        shifty=0cm,%
        scale=1.00,%
        rotation=0,%
        densityx=1,%
        densityy=1,%
        densityz=1,%
        dimx=4,%
        dimy=4,%
        dimy=4,%
        linefront=blue!75!black,%
        linetop=blue!50!black,%
        lineright=blue!25!black,%
        fillfront=blue!25!white,%
        filltop=blue!50!white,%
        fillright=blue!75!white,%
        anglex=15,%
        angley=135,%
        anglez=225,%
        scalex=1,%
        scaley=1,%
        scalez=1,%
        emphedge=N,%
    }
\end{tikzpicture}

\end{document}

And some samples:

enter image description here

Also, you can play around a little:

enter image description here

There are still some issues (certain axis transformations don't work, the emphstyle can only be passed one option...), and I'm not yet certain about how to do the shading, I'll experiment some more.


Edit 4: Finally I got everything, special thanks to Altermundus and Andrew Stacey for helping me with some issues. I finally incorporated all options and switched to pgfkeys, now I'm writing on a manual, CTAN package coming soon!

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm,landscape]{geometry}
\usepackage{tikz}

\newif\ifcuboidshade
\newif\ifcuboidemphedge

\tikzset{
  cuboid/.is family,
  cuboid,
  shiftx/.initial=0,
  shifty/.initial=0,
  dimx/.initial=3,
  dimy/.initial=3,
  dimz/.initial=3,
  scale/.initial=1,
  densityx/.initial=1,
  densityy/.initial=1,
  densityz/.initial=1,
  rotation/.initial=0,
  anglex/.initial=0,
  angley/.initial=90,
  anglez/.initial=225,
  scalex/.initial=1,
  scaley/.initial=1,
  scalez/.initial=0.5,
  front/.style={draw=black,fill=white},
  top/.style={draw=black,fill=white},
  right/.style={draw=black,fill=white},
  shade/.is if=cuboidshade,
  shadecolordark/.initial=black,
  shadecolorlight/.initial=white,
  shadeopacity/.initial=0.15,
  shadesamples/.initial=16,
  emphedge/.is if=cuboidemphedge,
  emphstyle/.style={thick},
}

\newcommand{\tikzcuboidkey}[1]{\pgfkeysvalueof{/tikz/cuboid/#1}}

% Commands
\newcommand{\tikzcuboid}[1]{
    \tikzset{cuboid,#1} % Process Keys passed to command
  \pgfmathsetlengthmacro{\vectorxx}{\tikzcuboidkey{scalex}*cos(\tikzcuboidkey{anglex})*28.452756}
  \pgfmathsetlengthmacro{\vectorxy}{\tikzcuboidkey{scalex}*sin(\tikzcuboidkey{anglex})*28.452756}
  \pgfmathsetlengthmacro{\vectoryx}{\tikzcuboidkey{scaley}*cos(\tikzcuboidkey{angley})*28.452756}
  \pgfmathsetlengthmacro{\vectoryy}{\tikzcuboidkey{scaley}*sin(\tikzcuboidkey{angley})*28.452756}
  \pgfmathsetlengthmacro{\vectorzx}{\tikzcuboidkey{scalez}*cos(\tikzcuboidkey{anglez})*28.452756}
  \pgfmathsetlengthmacro{\vectorzy}{\tikzcuboidkey{scalez}*sin(\tikzcuboidkey{anglez})*28.452756}
  \begin{scope}[xshift=\tikzcuboidkey{shiftx}, yshift=\tikzcuboidkey{shifty}, scale=\tikzcuboidkey{scale}, rotate=\tikzcuboidkey{rotation}, x={(\vectorxx,\vectorxy)}, y={(\vectoryx,\vectoryy)}, z={(\vectorzx,\vectorzy)}]
    \pgfmathsetmacro{\steppingx}{1/\tikzcuboidkey{densityx}}
  \pgfmathsetmacro{\steppingy}{1/\tikzcuboidkey{densityy}}
  \pgfmathsetmacro{\steppingz}{1/\tikzcuboidkey{densityz}}
  \newcommand{\dimx}{\tikzcuboidkey{dimx}}
  \newcommand{\dimy}{\tikzcuboidkey{dimy}}
  \newcommand{\dimz}{\tikzcuboidkey{dimz}}
  \pgfmathsetmacro{\secondx}{2*\steppingx}
  \pgfmathsetmacro{\secondy}{2*\steppingy}
  \pgfmathsetmacro{\secondz}{2*\steppingz}
  \foreach \x in {\steppingx,\secondx,...,\dimx}
  { \foreach \y in {\steppingy,\secondy,...,\dimy}
    {   \pgfmathsetmacro{\lowx}{(\x-\steppingx)}
      \pgfmathsetmacro{\lowy}{(\y-\steppingy)}
      \filldraw[cuboid/front] (\lowx,\lowy,\dimz) -- (\lowx,\y,\dimz) -- (\x,\y,\dimz) -- (\x,\lowy,\dimz) -- cycle;
    }
    }
  \foreach \x in {\steppingx,\secondx,...,\dimx}
  { \foreach \z in {\steppingz,\secondz,...,\dimz}
    {   \pgfmathsetmacro{\lowx}{(\x-\steppingx)}
      \pgfmathsetmacro{\lowz}{(\z-\steppingz)}
      \filldraw[cuboid/top] (\lowx,\dimy,\lowz) -- (\lowx,\dimy,\z) -- (\x,\dimy,\z) -- (\x,\dimy,\lowz) -- cycle;
        }
    }
    \foreach \y in {\steppingy,\secondy,...,\dimy}
  { \foreach \z in {\steppingz,\secondz,...,\dimz}
    {   \pgfmathsetmacro{\lowy}{(\y-\steppingy)}
      \pgfmathsetmacro{\lowz}{(\z-\steppingz)}
      \filldraw[cuboid/right] (\dimx,\lowy,\lowz) -- (\dimx,\lowy,\z) -- (\dimx,\y,\z) -- (\dimx,\y,\lowz) -- cycle;
    }
  }
  \ifcuboidemphedge
    \draw[cuboid/emphstyle] (0,\dimy,0) -- (\dimx,\dimy,0) -- (\dimx,\dimy,\dimz) -- (0,\dimy,\dimz) -- cycle;%
    \draw[cuboid/emphstyle] (0,\dimy,\dimz) -- (0,0,\dimz) -- (\dimx,0,\dimz) -- (\dimx,\dimy,\dimz);%
    \draw[cuboid/emphstyle] (\dimx,\dimy,0) -- (\dimx,0,0) -- (\dimx,0,\dimz);%
    \fi

    \ifcuboidshade
    \pgfmathsetmacro{\cstepx}{\dimx/\tikzcuboidkey{shadesamples}}
    \pgfmathsetmacro{\cstepy}{\dimy/\tikzcuboidkey{shadesamples}}
    \pgfmathsetmacro{\cstepz}{\dimz/\tikzcuboidkey{shadesamples}}
    \foreach \s in {1,...,\tikzcuboidkey{shadesamples}}
    {   \pgfmathsetmacro{\lows}{\s-1}
        \pgfmathsetmacro{\cpercent}{(\lows)/(\tikzcuboidkey{shadesamples}-1)*100}
        \fill[opacity=\tikzcuboidkey{shadeopacity},color=\tikzcuboidkey{shadecolorlight}!\cpercent!\tikzcuboidkey{shadecolordark}] (0,\s*\cstepy,\dimz) -- (\s*\cstepx,\s*\cstepy,\dimz) -- (\s*\cstepx,0,\dimz) -- (\lows*\cstepx,0,\dimz) -- (\lows*\cstepx,\lows*\cstepy,\dimz) -- (0,\lows*\cstepy,\dimz) -- cycle;
        \fill[opacity=\tikzcuboidkey{shadeopacity},color=\tikzcuboidkey{shadecolorlight}!\cpercent!\tikzcuboidkey{shadecolordark}] (0,\dimy,\s*\cstepz) -- (\s*\cstepx,\dimy,\s*\cstepz) -- (\s*\cstepx,\dimy,0) -- (\lows*\cstepx,\dimy,0) -- (\lows*\cstepx,\dimy,\lows*\cstepz) -- (0,\dimy,\lows*\cstepz) -- cycle;
        \fill[opacity=\tikzcuboidkey{shadeopacity},color=\tikzcuboidkey{shadecolorlight}!\cpercent!\tikzcuboidkey{shadecolordark}] (\dimx,0,\s*\cstepz) -- (\dimx,\s*\cstepy,\s*\cstepz) -- (\dimx,\s*\cstepy,0) -- (\dimx,\lows*\cstepy,0) -- (\dimx,\lows*\cstepy,\lows*\cstepz) -- (\dimx,0,\lows*\cstepz) -- cycle;
    }
    \fi 

  \end{scope}
}

\makeatother

\begin{document}

\begin{tikzpicture}
    \tikzcuboid{%
    shiftx=0cm,%
    shifty=8cm,%
    scale=1.00,%
    rotation=0,%
    densityx=2,%
    densityy=2,%
    densityz=2,%
    dimx=3,%
    dimy=3,%
    dimz=3,%
    scalex=1,%
    scaley=1,%
    scalez=1,%
    anglex=-30,%
    angley=90,%
    anglez=210,%
    front/.style={draw=green!50!black,fill=green!50!white},%
    top/.style={draw=green!50!black,fill=green!50!white},%
    right/.style={draw=green!50!black,fill=green!50!white},%
    emphedge,%
    emphstyle/.style={line width=1pt, green!12!black,densely dashed},
    shade,%
    shadesamples=64,%
    shadeopacity=0.15,%
    }
    \tikzcuboid{%
    shiftx=8cm,%
    shifty=8cm,%
    shadeopacity=0.30,%
    }   
    \tikzcuboid{%
    shiftx=16cm,%
    shifty=8cm,%
    shadeopacity=0.60,%
    }   
    \tikzcuboid{%
    shiftx=0cm,%
    shifty=0cm,%
    scale=1.00,%
    rotation=0,%
    densityx=1,%
    densityy=1,%
    densityz=1,%
    dimx=4,%
    dimy=4,%
    dimz=4,%
    front/.style={draw=blue!75!black,fill=blue!25!white},%
    right/.style={draw=blue!25!black,fill=blue!75!white},%
    top/.style={draw=blue!50!black,fill=blue!50!white},%
    anglex=-7,%
    angley=90,%
    anglez=221.5,%
    scalex=1,%
    scaley=1,%
    scalez=0.5,%
    emphedge=false,%
    shade,%
    shadeopacity=0.15,%
    }
    \tikzcuboid{%
    shiftx=8cm,%
    shifty=0cm,%
    shadeopacity=0.30,%
    }
    \tikzcuboid{%
    shiftx=16cm,%
    shifty=0cm,%
    shadeopacity=0.60,%
    }
\end{tikzpicture}

\end{document}

And some examples: first line is isometric, the second is simetric projection, from left to right the shading opacity is 0.15, 0.30 and 0.60

enter image description here

8
  • 5
    This isn't at the other "cube" question so I'm going to recommend that these two questions be merged to get all the possible ways of drawing a cube in one place! Nice answer, by the way. Sep 29, 2011 at 10:45
  • 6
    I love it when an easy answer becomes its own tikz library!! Sep 30, 2011 at 15:50
  • 4
    Since you're packaging this excellent answer, maybe you would like to add it to the From Answers to Packages project. I've added this answer to the list at What are your favourite TikZ/PGF answers?
    – Jake
    Oct 7, 2011 at 0:13
  • 14
    Did this become a package? If so, which one? I hope the answer to the first question is 'yes'!
    – cfr
    May 11, 2015 at 15:43
  • 2
    Great job! Has this become a package? If so, what is it called?
    – Evan Aad
    Nov 26, 2022 at 18:34
8

Here is a fixed version of Bombadil's code for dimensions equal to 1.

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm,landscape]{geometry}
\usepackage{tikz}
\usepackage{ifthen}
%-------------------
\newif\ifcuboidshade
\newif\ifcuboidemphedge

\tikzset{
  cuboid/.is family,
  cuboid,
  shiftx/.initial=0,
  shifty/.initial=0,
  dimx/.initial=3,
  dimy/.initial=3,
  dimz/.initial=3,
  scale/.initial=1,
  densityx/.initial=1,
  densityy/.initial=1,
  densityz/.initial=1,
  rotation/.initial=0,
  anglex/.initial=0,
  angley/.initial=90,
  anglez/.initial=225,
  scalex/.initial=1,
  scaley/.initial=1,
  scalez/.initial=0.5,
  front/.style={draw=black,fill=white},
  top/.style={draw=black,fill=white},
  right/.style={draw=black,fill=white},
  shade/.is if=cuboidshade,
  shadecolordark/.initial=black,
  shadecolorlight/.initial=white,
  shadeopacity/.initial=0.15,
  shadesamples/.initial=16,
  emphedge/.is if=cuboidemphedge,
  emphstyle/.style={thick},
}

\newcommand{\tikzcuboidkey}[1]{\pgfkeysvalueof{/tikz/cuboid/#1}}

% Commands
\newcommand{\tikzcuboid}[1]{
    \tikzset{cuboid,#1} % Process Keys passed to command
  \pgfmathsetlengthmacro{\vectorxx}{\tikzcuboidkey{scalex}*cos(\tikzcuboidkey{anglex})*28.452756}
  \pgfmathsetlengthmacro{\vectorxy}{\tikzcuboidkey{scalex}*sin(\tikzcuboidkey{anglex})*28.452756}
  \pgfmathsetlengthmacro{\vectoryx}{\tikzcuboidkey{scaley}*cos(\tikzcuboidkey{angley})*28.452756}
  \pgfmathsetlengthmacro{\vectoryy}{\tikzcuboidkey{scaley}*sin(\tikzcuboidkey{angley})*28.452756}
  \pgfmathsetlengthmacro{\vectorzx}{\tikzcuboidkey{scalez}*cos(\tikzcuboidkey{anglez})*28.452756}
  \pgfmathsetlengthmacro{\vectorzy}{\tikzcuboidkey{scalez}*sin(\tikzcuboidkey{anglez})*28.452756}
  \begin{scope}[xshift=\tikzcuboidkey{shiftx}, yshift=\tikzcuboidkey{shifty}, scale=\tikzcuboidkey{scale}, rotate=\tikzcuboidkey{rotation}, x={(\vectorxx,\vectorxy)}, y={(\vectoryx,\vectoryy)}, z={(\vectorzx,\vectorzy)}]
    \pgfmathsetmacro{\steppingx}{1/\tikzcuboidkey{densityx}}
  \pgfmathsetmacro{\steppingy}{1/\tikzcuboidkey{densityy}}
  \pgfmathsetmacro{\steppingz}{1/\tikzcuboidkey{densityz}}
  \newcommand{\dimx}{\tikzcuboidkey{dimx}}
  \newcommand{\dimy}{\tikzcuboidkey{dimy}}
  \newcommand{\dimz}{\tikzcuboidkey{dimz}}
  \pgfmathsetmacro{\secondx}{2*\steppingx}
  \pgfmathsetmacro{\secondy}{2*\steppingy}
  \pgfmathsetmacro{\secondz}{2*\steppingz}
  \ifthenelse{\equal{\dimx}{1}}
    {\foreach \x in {\steppingx,...,\dimx}}
    {\foreach \x in {\steppingx,\secondx,...,\dimx}}
  {     \ifthenelse{\equal{\dimy}{1}}
    {\foreach \y in {\steppingy,...,\dimy}}
    {\foreach \y in {\steppingy,\secondy,...,\dimy}}
    {   \pgfmathsetmacro{\lowx}{(\x-\steppingx)}
      \pgfmathsetmacro{\lowy}{(\y-\steppingy)}
      \filldraw[cuboid/front] (\lowx,\lowy,\dimz) -- (\lowx,\y,\dimz) -- (\x,\y,\dimz) -- (\x,\lowy,\dimz) -- cycle;
    }
    }
    \ifthenelse{\equal{\dimx}{1}}
    {\foreach \x in {\steppingx,...,\dimx}}
    {\foreach \x in {\steppingx,\secondx,...,\dimx}}
  { \ifthenelse{\equal{\dimz}{1}}
    {\foreach \z in {\steppingz,...,\dimz}}
    {\foreach \z in {\steppingz,\secondz,...,\dimz}}
    {   \pgfmathsetmacro{\lowx}{(\x-\steppingx)}
      \pgfmathsetmacro{\lowz}{(\z-\steppingz)}
      \filldraw[cuboid/top] (\lowx,\dimy,\lowz) -- (\lowx,\dimy,\z) -- (\x,\dimy,\z) -- (\x,\dimy,\lowz) -- cycle;
        }
    }
    \ifthenelse{\equal{\dimy}{1}}
    {\foreach \y in {\steppingy,...,\dimy}}
    {\foreach \y in {\steppingy,\secondy,...,\dimy}}
  { \ifthenelse{\equal{\dimz}{1}}
    {\foreach \z in {\steppingz,...,\dimz}}
    {\foreach \z in {\steppingz,\secondz,...,\dimz}}
    {   \pgfmathsetmacro{\lowy}{(\y-\steppingy)}
      \pgfmathsetmacro{\lowz}{(\z-\steppingz)}
      \filldraw[cuboid/right] (\dimx,\lowy,\lowz) -- (\dimx,\lowy,\z) -- (\dimx,\y,\z) -- (\dimx,\y,\lowz) -- cycle;
    }
  }
  \ifcuboidemphedge
    \draw[cuboid/emphstyle] (0,\dimy,0) -- (\dimx,\dimy,0) -- (\dimx,\dimy,\dimz) -- (0,\dimy,\dimz) -- cycle;%
    \draw[cuboid/emphstyle] (0,\dimy,\dimz) -- (0,0,\dimz) -- (\dimx,0,\dimz) -- (\dimx,\dimy,\dimz);%
    \draw[cuboid/emphstyle] (\dimx,\dimy,0) -- (\dimx,0,0) -- (\dimx,0,\dimz);%
    \fi

    \ifcuboidshade
    \pgfmathsetmacro{\cstepx}{\dimx/\tikzcuboidkey{shadesamples}}
    \pgfmathsetmacro{\cstepy}{\dimy/\tikzcuboidkey{shadesamples}}
    \pgfmathsetmacro{\cstepz}{\dimz/\tikzcuboidkey{shadesamples}}
    \foreach \s in {1,...,\tikzcuboidkey{shadesamples}}
    {   \pgfmathsetmacro{\lows}{\s-1}
        \pgfmathsetmacro{\cpercent}{(\lows)/(\tikzcuboidkey{shadesamples}-1)*100}
        \fill[opacity=\tikzcuboidkey{shadeopacity},color=\tikzcuboidkey{shadecolorlight}!\cpercent!\tikzcuboidkey{shadecolordark}] (0,\s*\cstepy,\dimz) -- (\s*\cstepx,\s*\cstepy,\dimz) -- (\s*\cstepx,0,\dimz) -- (\lows*\cstepx,0,\dimz) -- (\lows*\cstepx,\lows*\cstepy,\dimz) -- (0,\lows*\cstepy,\dimz) -- cycle;
        \fill[opacity=\tikzcuboidkey{shadeopacity},color=\tikzcuboidkey{shadecolorlight}!\cpercent!\tikzcuboidkey{shadecolordark}] (0,\dimy,\s*\cstepz) -- (\s*\cstepx,\dimy,\s*\cstepz) -- (\s*\cstepx,\dimy,0) -- (\lows*\cstepx,\dimy,0) -- (\lows*\cstepx,\dimy,\lows*\cstepz) -- (0,\dimy,\lows*\cstepz) -- cycle;
        \fill[opacity=\tikzcuboidkey{shadeopacity},color=\tikzcuboidkey{shadecolorlight}!\cpercent!\tikzcuboidkey{shadecolordark}] (\dimx,0,\s*\cstepz) -- (\dimx,\s*\cstepy,\s*\cstepz) -- (\dimx,\s*\cstepy,0) -- (\dimx,\lows*\cstepy,0) -- (\dimx,\lows*\cstepy,\lows*\cstepz) -- (\dimx,0,\lows*\cstepz) -- cycle;
    }
    \fi 

  \end{scope}
}

\makeatother
%-------------------
\begin{document}   
\begin{tikzpicture}   

\tikzcuboid{dimx=1,dimy=1,dimz=1};
\tikzcuboid{dimx=1,dimy=2,dimz=3,shiftx=100};
\tikzcuboid{dimx=3,dimy=1,dimz=2,shiftx=0,shifty=80};
\tikzcuboid{dimx=2,dimy=3,dimz=1,shiftx=100,shifty=80};

\end{tikzpicture}
\end{document}

Here is the output

Dimension equal to 1 example

The main changes are ifthenelse hacks that check if dim{x,y,z} is equal to 1 and in that case cancel foreach stepping.

  \ifthenelse{\equal{\dimx}{1}}
    {\foreach \x in {\steppingx,...,\dimx}}
    {\foreach \x in {\steppingx,\secondx,...,\dimx}}
5
  • Welcome to TeX.SX! Please add a full compilable answer. Helpfull is always: How do I write a good answer?.
    – Bobyandbob
    Aug 21, 2017 at 16:42
  • Is it ok now? Thanks for the tip! Aug 21, 2017 at 17:00
  • If its work yes, but i can't produce an solution with the code (maybe my mistake). Please check it. An image of the solution is also often welcome.
    – Bobyandbob
    Aug 21, 2017 at 17:06
  • Does it compile now? I also added an image to show that it works in my environment. Aug 21, 2017 at 17:38
  • (+1) Yes now everything works. Perfect. Maybe you could explain your changes refer to Bombadil answer. Thank you, you are welcome.
    – Bobyandbob
    Aug 21, 2017 at 20:50
3

Starting from Stefan Kottwitz's "Sudoku 3D cube" example (http://www.texample.net/tikz/examples/sudoku-3d-cube/ the idea of using yslant and xslant to achieve a 3D like appearance), I have developed an alternative visualization for Pasigraphy Rhapsody, https://gitlab.com/nbatfai/pasigraphy-rhapsody/blob/master/para/docs/prelpara.lua I think it can be used easily for the purpose in question by the following:

enter image description here

\begin{tikzpicture}[thick, scale=2, every node/.style={scale=2}]
\prelparaIIID{1}{"1:3:3:0:1:2:2:3:4:10:2:0:9:9:0:1:0"}
\end{tikzpicture}

enter image description here

 \begin{tikzpicture}[thick, scale=2, every node/.style={scale=2}]
 \prelparaIIID{1}{"1:3:3:0:1:2:2:3:4:10:2:0:9:9:0:8:2:1:6:6:1"}
 \end{tikzpicture}

enter image description here

 \begin{tikzpicture}[thick, scale=2, every node/.style={scale=2}]
 \prelparaIIID{1}{"3:4:3:0:1:2:2:3:4:10:2:0:9:9:0:8:2:1:6:6:1:6:2:1:5:5:1:8:2:1:7:7:1:4:2:1:3:3:1:4:2:1:3:3:1:10:2:1:7:7:1:6:2:1:5:5:1"}
 \prelparaIIID{2} {"4:4:3:1:2:2:2:3:4:10:2:0:9:9:0:8:2:1:6:6:1:6:2:1:5:5:1:8:2:1:7:7:1:4:2:1:3:3:1:4:2:1:3:3:1:2:1:1:1:6:2:1:5:5:1:4:1:1:1:8:2:2:2:4:4:2:1:1:1"}
 \prelparaIIID{1}{"3:4:3:0:1:2:2:3:4:10:2:0:9:9:0:8:2:1:6:6:1:6:2:1:5:5:1:8:2:1:7:7:1:4:2:1:3:3:1:4:2:1:3:3:1:10:2:1:7:7:1:6:2:1:5:5:1"}
 \end{tikzpicture}

At @siracusa suggestion, I have attached a full example

demo.tex

\documentclass[a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage{t1enc}
\usepackage{luacode}
\directlua{require('prelpara')}
\usepackage{tikz}

\newcommand\N[1]{\directlua{N(#1) }} 
\newcommand\D[3]{\directlua{D(#1,#2,#3) }} 
\newcommand\prelparaIID[1]{\directlua{para2D(#1)}}
\newcommand\prelparaIIID[2]{\directlua{para3D(#1,#2)}}

\begin{document}

\begin{tikzpicture}[thick, scale=2, every node/.style={scale=2}]
\prelparaIIID{1}{"3:4:3:0:1:2:2:3:4:10:2:0:9:9:0:8:2:1:6:6:1:6:2:1:5:5:1:8:2:1:7:7:1:4:2:1:3:3:1:4:2:1:3:3:1:10:2:1:7:7:1:6:2:1:5:5:1"}
\prelparaIIID{2} {"4:4:3:1:2:2:2:3:4:10:2:0:9:9:0:8:2:1:6:6:1:6:2:1:5:5:1:8:2:1:7:7:1:4:2:1:3:3:1:4:2:1:3:3:1:2:1:1:1:6:2:1:5:5:1:4:1:1:1:8:2:2:2:4:4:2:1:1:1"}
\prelparaIIID{1}{"3:4:3:0:1:2:2:3:4:10:2:0:9:9:0:8:2:1:6:6:1:6:2:1:5:5:1:8:2:1:7:7:1:4:2:1:3:3:1:4:2:1:3:3:1:10:2:1:7:7:1:6:2:1:5:5:1"}
\end{tikzpicture}

\end{document}

prelpara.lua

--[[

% Esport Language (PaRa) , first experiments 
% This is a rapid prototype for planning Pasigraphy Rhapsody (Paszigráfia Rapszódia, PaRa)
%
% prelpara.lua
%
% Copyright (C) 2019 Norbert Bátfai, [email protected], [email protected]
%
%  This program is free software: you can redistribute it and/or modify
%  it under the terms of the GNU General Public License as published by
%  the Free Software Foundation, either version 3 of the License, or
%  (at your option) any later version.
%
%  This program is distributed in the hope that it will be useful,
%  but WITHOUT ANY WARRANTY; without even the implied warranty of
%  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%  GNU General Public License for more details.
%
%  You should have received a copy of the GNU General Public License
%  along with this program.  If not, see <https://www.gnu.org/licenses/>.
%
% Version history
%
% Initial hack
%
% for vis_prel_para.tex
% Working title: Visualization of the Language of the Esports Culture: A Preliminary Study
% 
% A LuaLaTeX based visualization experiment for Pasigraphy Rhapsody
%
% The idea of using yslant and xslant to achieve a 3D effect like appearance 
% comes from Stefan Kottwitz's example http://www.texample.net/tikz/examples/sudoku-3d-cube/
% 
%
--]]
function para2D(fmts)
        local sntnc = fmts:split(":")
        r=sntnc[1]
        fmts_shift = 1
        for i = 0, r-1 do
            fmts_shift = fmts_shift +1
            n=sntnc[fmts_shift]
            fmts_shift = fmts_shift +1
            nod=sntnc[fmts_shift]
            tex.sprint(
                    "\\tikzstyle{shifting}=[xshift=", i,"cm]"                   
                    ,"\\shade[shifting, left color=gray!10, right color=black!80] (0,0) rectangle +(1,1);"
                    ,"\\draw[shifting, step=\\N{",n,"}cm, cyan] (0,0) grid (1,1);")     
            for j = 1, nod do
                fmts_shift = fmts_shift +1
                x=sntnc[fmts_shift]
                fmts_shift = fmts_shift +1
                y=sntnc[fmts_shift]+1
                tex.sprint(
                    "\\node[shifting, fill=orange, anchor=north west,  inner sep=0pt,minimum size=\\N{",n,"}cm-\\pgflinewidth] at \\D{",n,"}{",x,"}{",y,"} {};")
            end
        end
    end

function para3D(direct, fmts)
        dir=tonumber(direct)
        d={{2,1,2,-1,1,-1}, {1,0,1,-1,0,-1}}
        local sntnc = fmts:split(":")
        r=sntnc[1]
        fmts_shift = 1
        for i = 0, r-1 do
            fmts_shift = fmts_shift +1
            n=sntnc[fmts_shift]
            fmts_shift = fmts_shift +1
            nod=sntnc[fmts_shift]
            tex.sprint(
            "\\tikzstyle{leftslant}=[yslant=-.5, xshift=",-1+i*d[dir][1],"cm, yshift=",-1+i*d[dir][2],"cm]"
            ,"\\tikzstyle{rightslant}=[yslant=0.5, xshift=",i*d[dir][3],"cm, yshift=",-1+i*d[dir][4],"cm]"
            ,"\\tikzstyle{topslant}=[yslant=0.5, xslant=-1, xshift=", i*d[dir][5],"cm, yshift=", i*d[dir][6],"cm]"
            ,"\\shade[leftslant, right color=gray!10,left color=black!80] (0,0) rectangle +(1,1);"
            ,"\\draw[leftslant, step=\\N{",n,"}cm, cyan] (0,0) grid (1,1);")
            for j = 1, nod do
                fmts_shift = fmts_shift +1
                x=sntnc[fmts_shift]
                fmts_shift = fmts_shift +1
                y=sntnc[fmts_shift]+1
                tex.sprint(
                "\\node[leftslant, fill=orange, anchor=north west,  inner sep=0pt,minimum size=\\N{",n,"}cm-\\pgflinewidth] at \\D{",n,"}{",x,"}{",y,"-.5*",x,"} {};")
            end    
            fmts_shift = fmts_shift +1    
            n=sntnc[fmts_shift]
            fmts_shift = fmts_shift +1
            nod=sntnc[fmts_shift]
            tex.sprint(
                "\\shade[rightslant, right color=black!70,left color=gray!20] (0,0) rectangle +(1,1);",
                "\\draw[rightslant, step=\\N{",n,"}cm, pink](0,0) grid (1,1);")
            for j = 1, nod do
                fmts_shift = fmts_shift +1
                x=sntnc[fmts_shift]
                fmts_shift = fmts_shift +1
                y=sntnc[fmts_shift]
                tex.sprint(
                    "\\node[rightslant, fill=cyan, anchor=south west,  inner sep=0pt,minimum size=\\N{",n,"}cm-\\pgflinewidth] at \\D{",n,"}{",x,"}{",y,"+.5*",x,"} {};")
            end    
            fmts_shift = fmts_shift +1
            n=sntnc[fmts_shift]
            fmts_shift = fmts_shift +1
            nod=sntnc[fmts_shift]       
            tex.sprint(
                "\\shade[topslant, bottom color=gray!10,top color=black!80] (0,0) rectangle +(1,1);",
                "\\draw[topslant, step=\\N{",n,"}cm, orange] (0,0) grid (1,1);")
            for j = 1, nod do
                fmts_shift = fmts_shift +1
                x=sntnc[fmts_shift]
                fmts_shift = fmts_shift +1
                y=sntnc[fmts_shift]     
                tex.sprint(
                    "\\node[topslant, fill=yellow, anchor=south west,  inner sep=0pt,minimum size=\\N{",n,"}cm-\\pgflinewidth] at \\D{",n,"}{",y,"-",x,"}{",tonumber(y)/2,"+.5*",x,"} {};")
           end    
    end
end

function N(n) 
            tex.sprint(1/n)
end 

function D(n, x, y) 
            tex.sprint("(",       (1/n)*x,     ", ",   (1/n)*y,       ")")
end 
1
  • Welcome to TeX.SX! On this site self-contained answers are preferred, so it would be nice if you could make your example a full, compilable document that doesn't depend on code from another website.
    – siracusa
    Jul 30, 2019 at 8:38

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .