3

In this answer I saw that we can use [<new pgf key>/.code={...}, <new pgf key>] to smuggle in some code into the construction of a TikZ path. This approach works if all coordinates have a label because the standard arrays are comma-separated. I was thinking that the listofitems package could be used to process lists of coordinates without labels by changing the separator. However, the below code throws an error during path construction and I don't quite understand why.

The polyline simply serves as a means of illustration in an MWE. I am trying to understand more generally how to iterate over lists from the listofitems package in a Tikz environment.

\documentclass{standalone}
\usepackage{tikz, listofitems}
\usetikzlibrary{calc}

\newcommand{\polyline}[2][,]{
    \setsepchar{#1}
    \readlist*\inputlist{#2}
    [create coords/.code={
        \foreach \i in {1, ..., \inputlistlen} {
            \coordinate (coord\i) at (\inputlist[\i]);
        }
    }, create coords]
    (coord1)
    \foreach \i in {2, ..., \inputlistlen} {
        -- (coord\i)
    }
}

\begin{document}

\begin{tikzpicture}
\draw \polyline[:]{0,0: 1,0};
\end{tikzpicture}

\end{document}
0

2 Answers 2

1

If you follow this path, use the trick also to smuggle the macro into the path. And use styles.

\documentclass{standalone}
\usepackage{tikz, listofitems}

\newcommand{\polyline}[2][,]{
    \setsepchar{#1}
    \readlist*\inputlist{#2}
    \tikzset{insert path={foreach \i in {1, ..., \inputlistlen} 
    {({\inputlist[\i]}) coordinate (coord\i)}
    plot[samples at={1, ..., \inputlistlen}] (coord\x)}}
}
\tikzset{polyline/.code={\expandafter\polyline#1}}

\begin{document}

\begin{tikzpicture}
\draw [polyline={[:]{0,0: 1,0: 3,2}}];
\end{tikzpicture}

\end{document}

enter image description here

1

I am not versed in tikz, but by moving the \draw into the macro (as an argument), you can make it work.

\documentclass{standalone}
\usepackage{tikz, listofitems}
\usetikzlibrary{calc}

\newcommand{\polyline}[3][,]{
    \setsepchar{#1}
    \readlist*\inputlist{#3}
    [create coords/.code={
       \foreach \i in {1, ..., \inputlistlen} {
            \coordinate (coord\i) at (\inputlist[\i]);
        }
    }, create coords]
    #2 (coord1)
    \foreach \i in {2, ..., \inputlistlen} {
        -- (coord\i)
    }
}

\begin{document}

\begin{tikzpicture}
\polyline[:]\draw{0,1: 1,0};
\end{tikzpicture}

\end{document}

enter image description here

Clearly, though, the problem with the OP's MWE is that after the \draw command is issued, the \polyline is performing a bunch of setup code that the \draw macro is not expecting. So, an alternative would be to break it into two macros:

\documentclass{standalone}
\usepackage{tikz, listofitems}
\usetikzlibrary{calc}

\newcommand{\polylineinput}[2][,]{
    \setsepchar{#1}
    \readlist*\inputlist{#2}
    [create coords/.code={
       \foreach \i in {1, ..., \inputlistlen} {
            \coordinate (coord\i) at (\inputlist[\i]);
        }
    }, create coords]
}
\newcommand{\polyline}{
     (coord1)
    \foreach \i in {2, ..., \inputlistlen} {
        -- (coord\i)
    }
}

\begin{document}

\begin{tikzpicture}
\polylineinput[:]{0,1: 1,0}
\draw\polyline;
\end{tikzpicture}
\end{document}

A third approach would be to have a single macro \polylineinput that creates \thepolyline containing (coord1) -- (coord2), so that \draw\thepolyline could then be issued:

\documentclass{standalone}
\usepackage{tikz, listofitems}
\usetikzlibrary{calc}

\newcommand{\polylineinput}[2][,]{
    \setsepchar{#1}
    \readlist*\inputlist{#2}
    [create coords/.code={
       \foreachitem\z\in\inputlist[] {
            \coordinate (coord\zcnt) at (\z);
        }
    }, create coords]
    \xdef\thepolyline{}
    \foreach \i in {1, ..., \inputlistlen} {
        \ifnum\i>1\relax\xdef\thepolyline{\thepolyline--}\fi
        \xdef\thepolyline{\thepolyline(coord\i)}
    }
}
\begin{document}

\begin{tikzpicture}
\polylineinput[:]{0,1: 1,0}
\draw\thepolyline;
\end{tikzpicture}
\end{document}

You must log in to answer this question.

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