3

I use a loop to place a list of pics, each of which has a bounding box. Then I refer to one of these bounding boxes, but tikz does not seem to get names generated by the for-loop. This is the code:

\documentclass[tikz]{standalone}
\usepackage{tikz}

\begin{document}

\tikzset{
 pics/circle/.style args={#1}{
   code = { 
        \node[circle, draw, color=red] at (0, 0){#1};
   }   
 },
}

\begin{tikzpicture}

\foreach \ind in {1,2,3,4}
{
    \pic [local bounding box=circ\ind] at (\ind, 0) {circle};
}

%% This one does not work
%\draw (0, 2) -- (circ2);

%% (3, 1) should connect to the second circle only, but it connects all 
\foreach \ind in {1,2,3,4}
    \draw(3, 1) -- (circ2);

\end{tikzpicture}
\end{document}

enter image description here

UPDATE: Eventually, I figured out a way of using fit box, so I don't need to modify my pic (my own pic is somewhat complex).

\documentclass[tikz]{standalone}
\usepackage{tikz}
\usetikzlibrary{fit}

\begin{document}

\tikzset{
 pics/circle/.style args={#1}{
   code = {
        \node[circle, draw, color=red] at (0, 0){#1};
   }
 },
}

\begin{tikzpicture}

\foreach \ind in {1,2,3,4}
{
    \pic [local bounding box=pic\ind] at (\ind, 0) {circle};
    %%% This is the trick
    \node [inner sep=0, fit=(pic\ind)] (circ\ind) {};
}

% This line works now
\draw (0, 2) -- (circ2);

%% (3, 1) should connect to the second circle only, but it connects all
\foreach \ind in {1,2,3,4}
    \draw(3, 1) -- (circ2);

\end{tikzpicture}
\end{document}

2 Answers 2

3

It's the usual problem that \foreach performs each cycle of the loop inside a group and the settings done in the cycle are lost as soon as the group ends.

I can offer a \listloop macro, where the loop index is denoted by #1 and not grouping is used, because there is no risk to redefine commands (such as \ind).

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

\tikzset{
  pics/circle/.style args={#1}{
    code = { 
      \node[circle, draw, color=red] at (0, 0){#1};
    }
  },
}

\ExplSyntaxOn
\NewDocumentCommand{\listloop}{mm}
 {
  \clist_map_inline:nn { #1 } { #2 }
 }
\ExplSyntaxOff

\begin{document}

\begin{tikzpicture}

\listloop{1,2,3,4}{
    \pic [local bounding box=circ#1] at (#1, 0) {circle};
}

\draw (0, 2) -- (circ2);

\foreach \ind in {1,2,3,4}
    \draw(3, 1) -- (circ2);

\end{tikzpicture}
\end{document}

enter image description here

2

If I understand what you want, I think you can solve adding a \coordinate inside the pic description, with the same (or another) argument. And you probably don't need the las \foreach.

\documentclass[tikz]{standalone}
\usepackage{tikz}

\begin{document}
\tikzset{
  pics/circle/.style args={#1}%
  {
    code =
    {
      \coordinate (circ#1) at (#1,0);
      \node[circle, draw, color=red] at (#1,0){#1};
    }   
  }
}

\begin{tikzpicture}
\foreach\ind in {1,2,3,4}
{
  \pic [local bounding box=outer box] {circle=\ind};
}

\draw (0, 2) -- (circ2);
% (3, 1) should connect to the second circle only, but it connects all 
% Then you probably don't need the following foreach
%\foreach \ind in {1,2,3,4}
\draw(3, 1) -- (circ2);
\end{tikzpicture}
\end{document}

With the above code you get:

enter image description here

1
  • Thank you! Did not think about using names within a pic -- tikz is definitely different with many programs :-)
    – John Liu
    Jan 5, 2021 at 23:51

You must log in to answer this question.

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