6

I am using TikZ to draw some graph drawings (with nodes and directed edges/paths). I have two nodes and an arrow pointing from one node to another. I have made a macro called \pathedge so I can use these arrows repeatedly, but its giving me some trouble. Whenever I put an xshift or a yshift option before any of the nodes on the \draw command it gives me an error. I am pretty sure it has something to do with using brackets '[' ']' in a \def macro but I don't know how to fix it. Here's the minimal code example:

\documentclass{article}

\usepackage{etoolbox}
\usepackage{tikz}

\def\conn{\draw[arrows=->, black!50, thick]}
\newcommand{\pathedge}[4]{
  \def\startn{#1}
  \def\endn{#2}
  \def\startnopts{}
  \def\endnopts{}

  \ifstrequal{#4}{NE_TO_SW} {
    \def\startn{[yshift=-1ex]#1.west} 
    \def\endn{[xshift=1ex]#2.north}
  } {}

  \conn (\startn) to node[shape=circle, fill=white, inner sep=0.5pt, font=\sffamily\footnotesize]{#3} (\endn);
}

\begin{document}
\begin{tikzpicture}[scale=1,innode/.style={draw, shape=circle,ultra thick,black}]
\node[innode] (1) at (2,2) {1};
\node[innode] (2) at (4,4) {2};

\pathedge{2}{1}{A}{NE_TO_SW}
\end{tikzpicture}
\end{document}
6

If I understand you correctly (and this is what the error messages suggest) you want a path from ([yshift=-1ex]#1.west) to ([xshift=1ex]#2.north). The error messages are

! Package pgf Error: No shape named [yshift=-1ex]2 is known.
! Package pgf Error: No shape named [xshift=1ex]1 is known.

The problem is expansion that is done by TikZ but too late. The TikZ path parser needs to see a literal [ which can be solved for the start coordinate with \expandafter(\startn) but that doesn’t work for the target node (because TikZ allows only nodes, coordinates, cycle and plot after -- as well as of course a coordinate).

Though, you can do

\newcommand{\pathedge}[4]{
  \def\startn{#1}
  \def\endn{#2}
  \def\startnopts{}
  \def\endnopts{}

  \ifstrequal{#4}{NE_TO_SW} {
    \def\startn{#1.west} 
    \def\endn{#2.north}
    \def\startnopts{yshift=-1ex}
    \def\endnopts{xshift=1ex}
  } {}
  \conn ([style/.expand once=\startnopts]\startn)
    to node[shape=circle, fill=white, inner sep=0.5pt, font=\sffamily\footnotesize]{#3}
      ([style/.expand once=\endnopts]\endn);
}

(Why don’t you use the .north east and .south west anchors directly?)

But to be honest, I would do this entirely different.

Code

\documentclass[tikz]{standalone}
\tikzset{
  conn/.style={arrows=->, black!50, thick,
    every to/.append style={edge node={
      node[shape=circle, fill=white, inner sep=0.5pt, font=\sffamily\footnotesize]{#1}}}},
  ne to sw/.style={
    to path={([yshift=-1ex]\tikztostart.west) --
             ([xshift=1ex]\tikztotarget.north)\tikztonodes}}}
\makeatletter
\tikzset{% from CVS version
  edge node/.code={\expandafter\def\expandafter\tikz@tonodes\expandafter{\tikz@tonodes #1}}}
\makeatother
\begin{document}
\begin{tikzpicture}[innode/.style={draw,shape=circle,ultra thick}]
\node[innode] (1) at (2,2) {1};
\node[innode] (2) at (4,4) {2};
\draw[conn=A] (2) to (1);
\end{tikzpicture}

\begin{tikzpicture}[innode/.style={draw,shape=circle,ultra thick}]
\node[innode] (1) at (2,2) {1};
\node[innode] (2) at (4,4) {2};
\draw[conn=A, ne to sw] (2) to (1);
\end{tikzpicture}
\end{document}
  • I really like the second solution ... thanks :) – ahmadh Sep 29 '13 at 22:10
  • Can you explain to me the \makeatletter part? – ahmadh Sep 29 '13 at 22:16
  • @ahmadh For \makeatletter and \makeatother, see What do \makeatletter and \makeatother do? The edge node key simply adds the code for a node to the internal macro that collects the nodes on an edge so that you can add nodes with a key. – Qrrbrbirlbel Sep 29 '13 at 22:19

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.