# Tikz key code: defaults for several arguments?

I want to run some tikz code with multiple arguments in a key, but I want some of the arguments to have defaults. I think I understand how to do this when the code has one argument, but is there a way when it has multiple arguments?

Here's the idea:

\documentclass{article}

\usepackage{tikz}

\tikzset{
weird/.code n args={4}{
\draw #1 -- #2 -- #3 --#4;
},
% weird/.default#3={(0,0)},  %want my third default to be "(0,0)"
% weird/.default#4={cycle}   %want my fourth default to be "cycle"
}

\begin{document}
$\begin{tikzpicture} \node[weird={(1,0)}{(2,1)}{(3,0)}{(1,0)}] {}; % \node[weird={(2,0)}{(3,1)}{(4,0)}] {}; %want this to use cycle % \node[weird={(2,0)}{(3,1)}] {}; %want this to use (0,0) and cycle \end{tikzpicture}$
\end{document}


Thanks!

• Are you aware of this answer? (I'm not saying that your question is a duplicate, I am just warning you that the answer you'll get may be a bit lengthy....) – user121799 Mar 9 '18 at 21:47

The tikz interface is not really designed to cope with optional arguments in this sense. If you want it to deal with optional arguments the recommended approach is to define some pgfkeys and then use key-value pairs; for example see How can I create a parent node in tikz with parts of the node designated for pointers?.

In your case you just want to loop over a set of points, and do different things when given a different number of points. Rather than trying to make weird accept four arguments, with two of them optional, I would have weird accept one argument, which is a comma separated list of points, which you then loop over and process using tex commands.

The code below accepts the following input:

    \node[weird={(1,0),(2,1),(3,0),(1,0)}]  {};
\node[weird={(2,0),(3,1),(4,0)}]  {};     %want this to use cycle
\node[weird={(2,0),(3,1)}]  {};           %want this to use (0,0)
% and now for something completely different
\node[weird={(0:1cm),(60:1cm),(120:1cm),(180:1cm),(240:1cm),(300:1cm),(360:1cm)}]{};


which is marginally simpler than suggested in the OP. As the last example shows, the code also accepts more than four points and these points don't need to use Cartesian coordinates. The code loops over the list of points given to weird and, at the same time, counts the number of points and builds a cycle \mycycle that will be given to \draw. I then use \ifcase to add in your missing "default" points. The output of the code is:

I have drawn the different triangles, for different numbers of points, in different colours to help distinguish them and I have printed the x-coordinates underneath to show that the triangles are in the right place.

Here is the full code:

\documentclass{article}

\usepackage{tikz}
\usepackage{etoolbox}

\tikzset{
weird/.code = {
\def\mycycle{}% will be the cycle code given to \draw
\foreach \pt [count=\c, remember=\c] in {#1} {
% count the number of points and build \mycycle
\ifnum\c=1\xappto\mycycle{\pt}\else\xappto\mycycle{ -- \pt}\fi
}
% use \ifcase to treat 2, 3, 4, .. point differently
\ifcase\c\or% ignore 0 and 1
\or \draw[red](0,0)--\mycycle--cycle;  % 2 arguments
\or \draw[blue]\mycycle--cycle;  % 3 arguments
\else\draw\mycycle;               % 4 or more
\fi
},
}

\begin{document}
$\begin{tikzpicture} \node[weird={(1,0),(2,1),(3,0),(1,0)}] {}; \node[weird={(2,0),(3,1),(4,0)}] {}; %want this to use cycle \node[weird={(2,0),(3,1)}] {}; %want this to use (0,0) and cycle % and now for something completely different \node[weird={(0:1cm),(60:1cm),(120:1cm),(180:1cm),(240:1cm),(300:1cm),(360:1cm)}]{}; \foreach \x in {0,1,2,3,4} { \node at (\x,-1) {\x}; } \end{tikzpicture}$
\end{document}


Of course, it may well be that this approach solves the question in your MWE but then completely fails with what you really want to do. If so then I suggest giving a better MWE and probably using a pgfkeys key-value approach:)