8

In defining a new shape with \pgfdeclareshape, I have problems to add many anchors with the \foreach statement. Each anchor is defined with three arguments. In the example, the argument #1 is OK but the program complains with #2 and #3. How can I generate so many anchors with different keys with \foreach?

\documentclass[a4paper,landscape]{article}
\usepackage{tikz}
\usetikzlibrary{calc,arrows}
\usepackage{amsmath}
\usepackage[left=1cm,right=1cm]{geometry}
\pagestyle{empty}

\begin{document}
\makeatletter
% Define shapes
\pgfdeclareshape{PE}{
  % Inherit from rectangle
  \inheritsavedanchors[from=rectangle]
  \inheritanchor[from=rectangle]{center}
  \inheritanchorborder[from=rectangle]

  % In the following I want to make many anchors with some loop. For example,
  %\foreach \x/\Y/\z in {een/1/.7,ee/1/0,ees/1/-1}
  %{\anchor{\x}{
  %  \pgf@process{\northeast}%
  %  \pgf@x=\y\pgf@x%
  %  \pgf@y=\z\pgf@y%
  %}}
  %However, while #1 is replaced but #2 and #2 are not. 
  %How can I use \foreach or TeX loop?        

  \anchor{een}{
    \pgf@process{\northeast}%
    \pgf@x=1\pgf@x%
    \pgf@y=.7\pgf@y%
  }
  \anchor{ee}{
    \pgf@process{\northeast}%
    \pgf@x=1\pgf@x%
    \pgf@y=0\pgf@y%
  }
  \anchor{ees}{
    \pgf@process{\northeast}%
    \pgf@x=1\pgf@x%
    \pgf@y=-.7\pgf@y%
  }
    \anchor{se}{
    \pgf@process{\northeast}%
    \pgf@x=1\pgf@x%
    \pgf@y=-1\pgf@y%
  }

  % Draw the rectangle box and the port labels
  \backgroundpath{
    % Rectangle box
    \pgfpathrectanglecorners{\southwest}{\northeast}
  %Add labels
  %The following code doesn't work.
  %\foreach \x/\y in {een,ee,ees}
  %  {
  %  \pgf@anchor@PE@\x
  %  \pgftext[at={\pgfpoint{\pgf@x}{\pgf@y}},x=-\pgfshapeinnerxsep,y=0]{\raisebox{-.75ex}{\y}}
  % }
  %\foreach \x/\y in {anchor@PE@een/een,\pgf@anchor@PE@ee/ee,\pgf@anchor@PE@ees/ees}
  %{
  %  \x
  %  \pgftext[at={\pgfpoint{\pgf@x}{\pgf@y}},x=-\pgfshapeinnerxsep,y=0]{\raisebox{-.75ex}{\y}}
  %}
}
\makeatother

\begin{tikzpicture}[>=stealth']
  \tikzset{PE/port labels/.style={font=\sffamily\scriptsize}}
  \tikzset{every PE node/.style={draw=blue,minimum width=2cm,minimum
    height=3cm,very thick,inner sep=1mm,outer sep=0pt,cap=round}}
  % Place PEs
  \foreach \m in {0,...,3}
    \node [shape=PE] (PE\m) at ($ 4*(\m,0)$) {};
\end{tikzpicture}
\end{document}
12

Expanding in foreach loops is always problematic so you need to make sure that macros are expanded properly (or some of them are nor expanded while the variables are expanded)

\documentclass[border=2mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc,arrows}

\makeatletter

\pgfdeclareshape{PE}{

  \inheritsavedanchors[from=rectangle]
  \inheritanchor[from=rectangle]{center}
  \inheritanchorborder[from=rectangle]

  \foreach \x/\z in {een/.7,ee/0,ees/-1}
  {
    \xdef\doanchor{
      \noexpand\anchor{\x}{
      \noexpand\northeast
      \noexpand\pgf@y=\z\noexpand\pgf@y%
      }
    }\doanchor
  }
  \backgroundpath{
    % Rectangle box
    \pgfpathrectanglecorners{\southwest}{\northeast}
  }
}
\makeatother

\begin{document}

\begin{tikzpicture}[>=stealth']
  \tikzset{PE/port labels/.style={font=\sffamily\scriptsize}}
  \tikzset{every PE node/.style={draw=blue,minimum width=2cm,minimum
    height=3cm,very thick,inner sep=1mm,outer sep=0pt,cap=round}}
  % Place PEs
  \foreach \m in {0,...,2}{    \node [shape=PE] (PE\m) at ($ 4*(\m,0.25*\m)$) {};}
    \draw (PE0.een) to[bend right] (PE1.ee) to[bend right] (PE2.ees);
    %\draw (PE0.ees) -|++(3cm,-2cm) -| (PE1.ees);
    \node at (PE2.een)  {a};
    \node at (PE2.ee)   {b};
    \node at (PE2.ees)  {c};
\end{tikzpicture}
\end{document}

enter image description here

2
  • Thanks percusse, it works great. Aftere creating the shape I want to add labels in \pgfdeclareshape. However it's a long list that must be simplified with \foreach again. (The code is added) How can I shorten this code for long listing? – gnoejh Jul 31 '12 at 5:26
  • @gnoejh You might better do it with a node style and using the option label=anchor:text instead of hardcoding into the shape. – percusse Jul 31 '12 at 22:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.