Need help creating a 3D cube from a 2D set of nodes in TikZ
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}
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 ;)
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 density
s 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):
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:
Also, you can play around a little:
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
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
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}}