# Pass several comma separated TikZ options to a single keyval key

I'm still improving my answer to Need help creating a 3D cube from a 2D set of nodes in TikZ. One of the options should be to emphasize the edges of the cuboid. This would mean e.g.

\draw[red, very thick, dashed] <some coordinates>


I'm using keyval to define parameters for the cuboid. Now my quesrion is, how can I pass all these commands to a single key? I would do this:

\tikzcuboid{%
emphedge=Y,%
emphstyle=very thick,
}


I can only pass one option (here very thick), as further commas (e.g. very thick, red, dashed) are interpreted as delimiters for keys by keyval. I tried several things, like

emphstyle={very thick, red, dashed}
emphstyle=style={very thick, red, dashed}
emphstyle=(very thick, red, dashed)


So my question basically is: are there some kind of special delimiters for keyval that I can put a list of comma separated arguments in? These special delimiters should however not be passed on, since this would probably cause problems with TikZ.

-
Why are you using keyval and not pgfkeys? Having two different key/value packages used together just causes troubles. You don't provide a MWE so I can't test anything, but when wrapping the comma separated list in { } doesn't protect the commas try two sets of braces, e.g. emphstyle={{very thick, red, dashed}}. One might be already removed by keyval. –  Martin Scharrer Oct 4 '11 at 12:31
Have a look at the linked question, you find an (almost) MWE there (under Edit 3), after the definitions there are 6 examples. Thanks for the hint about double braces, I'll try that. –  Tom Bombadil Oct 4 '11 at 13:02
Unfortunately, that did not work. And I used keyval as I had an old .tex file where I used it and thus had a starting point. To be honest, I didn't know pgfkeys existed. –  Tom Bombadil Oct 4 '11 at 13:06
Imho one layer of braces should be enough to protect the commas in the value. So if emphstyle={very thick, red, dashed} doesn't work the problem is somewhere in the definition/processing/code of the emphstyle-key. –  Ulrike Fischer Oct 4 '11 at 13:23
Like Martin, I prefer pgfkeys but xkeyvalis a solution because during a period, in the sources of Tikz, xkeyval and pgfkeys worked together. Now I'm not sure If xkeyval is not faster than pgfkeys. –  Alain Matthes Oct 4 '11 at 14:48

To protect the commas in your code you can do this

\ifthenelse{\equal{\tikzcuboid@emphedge}{Y}}%
{\protected@edef\cube@temp{%
\noexpand\draw[\tikzcuboid@emphstyle](0,\dimy,0) -- (\dimx,\dimy,0) -- (\dimx,\dimy,\dimz) -- (0,\dimy,\dimz) -- cycle;
\noexpand\draw[\tikzcuboid@emphstyle] (0,\dimy,\dimz) -- (0,0,\dimz) -- (\dimx,0,\dimz) -- (\dimx,\dimy,\dimz);
\noexpand\draw[\tikzcuboid@emphstyle](\dimx,\dimy,0) -- (\dimx,0,0) -- (\dimx,0,\dimz);
}\cube@temp
}%
{}


the result with

\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, red, dashed}
}


and the picture

-
Nice, it works! However, you wrote the dirst \draw twice. Furthermore I noticed that drawing three cycles is not good, as e.g. dashed lines are overwritten, my bad. So I'll take the liberty to edit your post. –  Tom Bombadil Oct 4 '11 at 21:07
@Tom: no problem for the code ! –  Alain Matthes Oct 5 '11 at 3:50

If you'd be willing to switch to using \pgfkeys then this is quite simple. It's possible to declare a key to be an alias to a list of keys. This is done via:

\tikzset{my key/.style={list,of,other,keys}}


Then the key my key expands to list,of,other,keys in the proper way.

Here's an example of how to do it, based on your code at the linked question. I've added some spaces into the key names to make them easier (which meant that I saw some errors: you had dimy in place of dimz a couple of times). I've replaced the \ifthenelse by a boolean key. I've also condensed the line and fill keys to one single style which gives greater flexibility. You could replace the \filldraw by a simple \path for maximum flexibility here, then the grids could be filled or not filled at leisure.

Here's the code:

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm,landscape]{geometry}
\usepackage{tikz}
%====================================
%emphasize vertices --> switch and emph style (e.g. thick,black)
%====================================

\newif\ifcuboidemphedge

\tikzset{
cuboid/.is family,
cuboid,
shift x/.initial=0,
shift y/.initial=0,
dim x/.initial=3,
dim y/.initial=3,
dim z/.initial=3,
scale/.initial=1,
density x/.initial=1,
density y/.initial=1,
density z/.initial=1,
rotation/.initial=0,
angle x/.initial=0,
angle y/.initial=90,
angle z/.initial=225,
scale x/.initial=1,
scale y/.initial=1,
scale z/.initial=sqrt(0.5),
front/.style={draw=black,fill=white},
top/.style={draw=black,fill=white},
right/.style={draw=black,fill=white},
emph edge/.is if=cuboidemphedge,
emph style/.style={thick},
}

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

% Commands
\newcommand{\tikzcuboid}[1]{
\tikzset{cuboid,#1} % Process Keys passed to command
\pgfmathsetmacro{\vectorxx}{\tikzcuboidkey{scale x}*cos(\tikzcuboidkey{angle x})}
\pgfmathsetmacro{\vectorxy}{\tikzcuboidkey{scale x}*sin(\tikzcuboidkey{angle x})}
\pgfmathsetmacro{\vectoryx}{\tikzcuboidkey{scale y}*cos(\tikzcuboidkey{angle y})}
\pgfmathsetmacro{\vectoryy}{\tikzcuboidkey{scale y}*sin(\tikzcuboidkey{angle y})}
\pgfmathsetmacro{\vectorzx}{\tikzcuboidkey{scale z}*cos(\tikzcuboidkey{angle z})}
\pgfmathsetmacro{\vectorzy}{\tikzcuboidkey{scale z}*sin(\tikzcuboidkey{angle z})}
\begin{scope}[xshift=\tikzcuboidkey{shift x}, yshift=\tikzcuboidkey{shift y}, scale=\tikzcuboidkey{scale}, rotate=\tikzcuboidkey{rotation}, x={(\vectorxx,\vectorxy)}, y={(\vectoryx,\vectoryy)}, z={(\vectorzx,\vectorzy)}]
\pgfmathsetmacro{\steppingx}{1/\tikzcuboidkey{density x}}
\pgfmathsetmacro{\steppingy}{1/\tikzcuboidkey{density y}}
\pgfmathsetmacro{\steppingz}{1/\tikzcuboidkey{density z}}
\newcommand{\dimx}{\tikzcuboidkey{dim x}}
\newcommand{\dimy}{\tikzcuboidkey{dim y}}
\newcommand{\dimz}{\tikzcuboidkey{dim z}}
\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/emph style] (0,\dimy,0) -- (\dimx,\dimy,0) -- (\dimx,\dimy,\dimz) -- (0,\dimy,\dimz) -- cycle;%
\draw[cuboid/emph style] (0,\dimy,\dimz) -- (0,0,\dimz) -- (\dimx,0,\dimz) -- (\dimx,\dimy,\dimz);%
\draw[cuboid/emph style] (\dimx,\dimy,0) -- (\dimx,0,0) -- (\dimx,0,\dimz);%
\fi
\end{scope}
}

\makeatother

\begin{document}

\begin{tikzpicture}
\tikzcuboid{shift x=0cm,%
shift y=0cm,%
scale=1.00,%
rotation=30,%
density x=1,%
density y=2,%
density z=3,%
dim x=4,%
dim y=5,%
dim z=2,%
front/.style={draw=yellow!30!black,fill=yellow!30!white},%
top/.style={draw=red!30!black,fill=red!30!white},%
right/.style={draw=blue!30!black,fill=blue!30!white}%
}
\tikzcuboid{%
shift x=0cm,%
shift y=8cm,%
scale=1.00,%
rotation=60,%
density x=3,%
density y=2,%
density z=5,%
dim x=4,%
dim y=4,%
dim z=4,%
front/.style={draw=orange!75!black,fill=orange!75!white},%
top/.style={draw=green!75!black,fill=green!75!white},%
right/.style={draw=violet!75!black,fill=violet!75!white}%
}
\tikzcuboid{%
shift x=8cm,%
shift y=8cm,%
scale=1.00,%
rotation=45,%
density x=1,%
density y=(2/3),%
density z=2,%
dim x=3,%
dim y=3,%
dim y=3,%
front/.style={draw=white!15!black,fill=black!15!white},%
top/.style={draw=white!30!black,fill=black!30!white},%
right/.style={draw=white!45!black,fill=black!45!white}%
}
\tikzcuboid{%
shift x=8cm,%
shift y=0cm,%
scale=1.00,%
rotation=75,%
density x=2,%
density y=3,%
density z=2,%
dim x=6,%
dim y=8,%
dim z=1,%
front/.style={draw=red!75!black,fill=red!25!white},%
top/.style={draw=red!50!black,fill=red!50!white},%
right/.style={draw=red!25!black,fill=red!75!white}%
}
\tikzcuboid{%
shift x=16cm,%
shift y=8cm,%
scale=1.00,%
rotation=0,%
density x=2,%
density y=2,%
density z=2,%
dim x=4,%
dim y=4,%
dim y=4,%
front/.style={draw=green!75!black,fill=green!25!white},%
top/.style={draw=green!50!black,fill=green!50!white},%
right/.style={draw=green!25!black,fill=green!75!white},%
emph edge,%
emph style/.style={very thick},
}
\tikzcuboid{%
shift x=16cm,%
shift y=0cm,%
scale=1.00,%
rotation=0,%
density x=1,%
density y=1,%
density z=1,%
dim x=4,%
dim y=4,%
dim z=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},%
angle x=15,%
angle y=135,%
angle z=225,%
scale x=1,%
scale y=1,%
scale z=1,%
emph edge=false,%
}
\end{tikzpicture}

\end{document}

-
Hey, thanks for the effort, it works fine. I think I'll switch to pgfkeys, however I will still write keys as dimx (things like verythick instead of very thick constantly break my neck, I really don't like spaces in keys or variables). I also spotted the errors in the other post, I will correct them with my next edit. I'm sorry I can award only one "accepted answer", yours would deserve it as well –  Tom Bombadil Oct 4 '11 at 21:28
Oh, and as I pointed out below Altermundus' post, drawing three cycles for emphasizing is only fine for slid lines, but not for e.g. dashed ones, so I changed it there. –  Tom Bombadil Oct 4 '11 at 21:36
As an alternative to the spaces, you could define them hierarchically. Then you have a directory called dim with three subkeys dim/x, dim/y, and dim/z. (I'm not saying you should do this, just saying that it's possible.) –  Loop Space Oct 5 '11 at 8:42
And as penance for not accepting my answer, you should make a proper package out of your code and upload it to CTAN. –  Loop Space Oct 5 '11 at 8:42
Okay, will do :D –  Tom Bombadil Oct 5 '11 at 11:07