3

I'll start with a bit of context — I have a couple of 2D points that I'd like to visualise as e.g. circles, and in addition, I'd like to connect these 2D points in some manner (e.g. connect subsequent points using straight line segments). Rather than specifying the coordinates of the 2D points twice, I'd like to do so only once, and then use them for both purposes. Enter arrays of 2D points.

Now, visualising the 2D points as circles is straightforward. First, I'll define a pic:

\tikzset{dot/.pic={\draw[fill, black!60] circle[radius=3pt];}}

Followed by either

% Using curly brackets (cb)
\def\ptscb{{0,0}, {1,2}, {1,4}, {3,5}, {2,2}, {3,1}, {5,2}}

\begin{tikzpicture}
\foreach \p [count=\k] in \ptscb {
    \pic at (\p) {dot};
    \node[above right, black!40!green] at (\p) {\k};
}
\end{tikzpicture}

or

% Using round brackets (rb)
\def\ptsrb{(0,0), (1,2), (1,4), (3,5), (2,2), (3,1), (5,2)}

\begin{tikzpicture}
\foreach \q [count=\l] in \ptsrb {
    \pic at \q {dot};
    \node[above right, black!40!red] at \q {\l};
}
\end{tikzpicture}

Note the difference in 'inner' brackets (respectively curly and round brackets) in the two snippets above.

Next, rather than using plot or something similar, I would like to 'manually' connect the 2D points (i.e. draw the edge segments). My initial attempt was to use \draw \ptscb[0] -- \ptscb[1]; or \draw \ptsrb[0] -- \ptsrb[1];. Unfortunately, these don't work. As it turns out, the definition of the array requires an additional layer of curly brackets:

% Using two curly brackets (ccb)
\def\ptsccb{{{0,0}, {1,2}, {1,4}, {3,5}, {2,2}, {3,1}, {5,2}}}

\begin{tikzpicture}
\draw (\ptsccb[0][0], \ptsccb[0][1]) -- (\ptsccb[1][0], \ptsccb[1][1]);
\end{tikzpicture}

This works (though unfortunately it seems that \foreach cannot handle these additional brackets), but I don't like the use of double indices. I expected that the following would work, but alas:

% Using curly and round brackets (crb)
\def\ptscrb{{(0,0), (1,2), (1,4), (3,5), (2,2), (3,1), (5,2)}}

\begin{tikzpicture}
\draw \ptscrb[0] -- \ptscrb[1];
\end{tikzpicture}

Going back to the array definition using two curly brackets, the following does also not return what I would expect — \node at (0,0) {\ptsccb[2]}; does not show the actual second element, but rather just the entire array followed by [2]. Some digging brought up \node at (0,0) {\pgfmathparse{array(\ptsccb,2)}\pgfmathresult}; which does show the second element (though shown as 14 rather than {1,4}).

Ultimately, my question is whether there is a more elegant way to pull off the above, i.e. connecting 2D points stored in an array without having to use double indices. I'm aware of the option to first define every 2D point as an 'indexed' coordinate as illustrated here, but apart from that, I'm not aware of nice alternatives.

2 Answers 2

3

it is not entirely clear (to me, at least) what is your problem. Anyway, your second example of code I would write on the following way:

\documentclass[border=3.141592]{standalone}
\usepackage{tikz}

\begin{document}
\def\ptsrb{(0,0), (1,2), (1,4), (3,5), (2,2), (3,1), (5,2)}

\begin{tikzpicture}[
dot/.style = {circle, fill=black!60, minimum size=6pt, inner sep=0pt},
every label/.append style = {inner sep=1pt, text= black!40!red}
                    ]
\foreach \q [count=\l] in \ptsrb 
    \node (n\l) [dot, label=above right:\l] at \q {};
\end{tikzpicture}
\end{document}

which produce the following result:

enter image description here

3
  • Apologies for being unclear, I've added some emphasis to some parts of my post. It boils down to finding an elegant way to specify a bunch of 2D points only once (e.g. as an array) and then using those 2D points more than once (using indices to access individual elements in the array of 2D points).
    – Ailurus
    Commented Apr 27, 2021 at 10:26
  • 1
    @Ailurus, this is enabled by my answer. For example, you can draw lines between dot 3 and 7 as \draw (n3) -- (n7);.
    – Zarko
    Commented Apr 27, 2021 at 10:28
  • I see, this way one could skip defining each 2D point as \coordinate before actually using it. However, this approach affects the drawing order (i.e. the circles are drawn before anything else using the 2D points).
    – Ailurus
    Commented Apr 27, 2021 at 10:49
2

Although this is not exactly what I'm after (as it still uses double indexing under the hood), I thought I would add it as it might be useful for someone else.

\documentclass{article}
\usepackage{tikz}
\begin{document}

\tikzset{dot/.pic={\draw[fill, black!60] circle[radius=3pt];}}

% Using two curly brackets (ccb)
\def\ptsccb{{{0,0}, {1,2}, {1,4}, {3,5}, {2,2}, {3,1}, {5,2}}}

\newcommand{\arr}[2]{(#1[#2][0], #1[#2][1])}

\begin{tikzpicture}
\foreach \k in {0, ..., 6} {
    \ifnum\k < 6
        \draw \arr{\ptsccb}{\k} -- \arr{\ptsccb}{\k+1};
    \fi
    \pic at \arr{\ptsccb}{\k} {dot};
    \node[above right, black!40!green] at \arr{\ptsccb}{\k} {\k};
}
\end{tikzpicture}

\end{document}

This yields

enter image description here

You must log in to answer this question.

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