TikZ: Combining multiple paths in and outside foreach

I am trying to generate a path from a list of directions (as seen on the numpad). The coordinates are generated correctly, but because I use multiple call to \path the arrowheads are drawn on each segment. How do I change this code to only draw the starting arrowhead on the first segment and the ending arrowhead on the last segment? I have unsuccessfully tried to have one \path outside the \foreach and only coordinates inside.

edit: It should work for any arrow shape passed in the optional argument.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}

\newcommand{\directedPath}[5][]
{
\edef\start{#2}
\edef\stop{#3}
\edef\step{#4}
\edef\directions{#5}
\coordinate (c0) at (\start);
\foreach [var=\dir, count=\cur] in \directions
{
% current coordinate dx
\pgfmathparse{(1-(1-1/sqrt(2))*mod(\dir, 2))*\step*(mod(\dir-1, 3)-1)}
\edef\dx{\pgfmathresult}
% current coordinate dy
\pgfmathparse{(1-(1-1/sqrt(2))*mod(\dir, 2))*\step*(div(\dir-1, 3)-1)}
\edef\dy{\pgfmathresult}
% previous coordinate index
\pgfmathparse{int(\cur - 1)}
\xdef\prev{\pgfmathresult}
% current coordinate
\coordinate (c\cur) at ($(c\prev) + (\dx, \dy)$);
% draw partial path
\ifnum \cur>1
\path [#1] (c\prev) -- (c\cur);
\fi
}
\path [#1] (\start) -- (c1);
\path [#1] (c\cur) -- (\stop);
}

\begin{document}

\begin{tikzpicture}
\node [draw=green] (Start) at (0, 0) {Start};
\node [draw=red] (End) at (5, 2) {End};
\directedPath[draw=black, >->]{Start}{End}{1.0}{3,6,9,8,7,8,9,6,3}
\end{tikzpicture}

\end{document}

-
Quick fix would be removing >-> and using \path [#1,>-] (\start) -- (c1); \path [#1,->] (c\cur) -- (\stop); – percusse Jul 14 '13 at 19:00
While this solves the problem as stated, it is not what I intended. I should have been more specific. I want it to accept the arrow type as part of the optional argument, making it work for any type of arrowhead. – Linus Jul 14 '13 at 19:23
How about making the entire path a single \path command? Would that be an acceptable solution? – Loop Space Jul 14 '13 at 19:27
You can provide the start and end arrow types as separate keys. – percusse Jul 14 '13 at 19:46
@AndrewStacey Absolutely. That would probably be the best solution. – Linus Jul 14 '13 at 19:59

There is no question that this need to be done in one single path but you can do this quite easily with the turtle library.

Simply define a direction (and a factor) for every digit.

As the direction key only turns the “turtle”, also include the forward key which includes a to[/tikz/turtle/how] path to the relative coordinate in direction and the given distance, i.e.

to[/tikz/turtle/how] ++ (<direction>:<distance>)


The Start and End simply insert a move to to (Start) and a (final?) line to to (End) (or whatever the how style is currently).

Of course, you can use the math from your question in the setup of the digit styles, but this is just faster (for TikZ and to write up).

I opted for a grid-like output which needs the factor sqrt(2) for the diagonal directions. Set this factor to 1 to get the same distance as in your question. (I also changed the example a little bit to get a symmetrical result.)

I have created and used an auxiliary style for the setup, marked by an @. It may also preferable to simply define this style in a /aux path as we won’t use it again or really need it in the /tikz path.

This also makes it easy to set all factors to 1 by omitting the value of the forward key (the default is /tikz/turtle/distance anyway if no value is given), i.e.

@setup turtle digits/.style n args={3}{
/tikz/turtle/#1/.style={
/tikz/turtle/direction=#2,
/tikz/turtle/forward}}


(There is no real reason to set the value of the forward key to a fixed distance as it would be more consistent to change the distance value.)

If you suddenly feel that the keys shouldn’t be called 1, 2, … 9 but 1 step, 2 step, … 9 step you simply add  step after #1.

Code

\documentclass[tikz,convert]{standalone}
\usetikzlibrary{turtle}
\tikzset{
@setup turtle digits/.style n args={3}{
/tikz/turtle/#1/.style={
/tikz/turtle/direction=#2,
/tikz/turtle/forward={#3*\pgfkeysvalueof{/tikz/turtle/distance}}}},
@setup turtle digits={1}{south west}{1.41421},
@setup turtle digits={2}{south}     {1},
@setup turtle digits={3}{south east}{1.41421},
@setup turtle digits={4}{left}      {1},
@setup turtle digits={6}{right}     {1},
@setup turtle digits={7}{north west}{1.41421},
@setup turtle digits={8}{north}     {1},
@setup turtle digits={9}{north east}{1.41421},
turtle/.cd,
Start/.style={/tikz/insert path={(#1)}},
End/.style={/tikz/insert path={to[/tikz/turtle/how] (#1)}},
Start/.default=Start,
End/.default=End,
}
\begin{document}
\begin{tikzpicture}
\node [draw=green] (Start) at (0, 1) {Start};
\node [draw=red]   (End)   at (5, 2) {End};
\draw [draw=black, >->] [turtle={Start, 2, 3, 6, 9, 8, 7, 8, 9, 6, 3, End}];
\end{tikzpicture}
\end{document}


Output

without the factors

-
I actually like the grid-like path more, even though it doesn't behave exactly like in my example. I assume you have the source for that as well, could you possibly provide it? – Linus Jul 15 '13 at 11:02
@Linus I have updated my answer including the code for the grid-like approach. It is pretty much the same except for the factor. It shouldn’t be hard to customize this for different problems. – Qrrbrbirlbel Jul 15 '13 at 17:07
@Qrrbrirlbel Trying to understand how this example works. What exactly does "@setup" do? – Linus Jul 18 '13 at 22:30
@Linus I have updated my answer. @setup turtle digits is simply an auxiliary style that makes it possible to define the styles 1 through 9 consistently. You can check out two other answers of mine that uses the turtle library [1] or at least the basic principle behind it [2]. – Qrrbrbirlbel Jul 19 '13 at 4:00
Thief, thief! Qrrbrbirlbel! We hates it, we hates it forever!! (That's for stealing my green tick.) – Loop Space Jul 19 '13 at 11:54

Here's a single path version:

\documentclass{article}
%\url{http://tex.stackexchange.com/q/123997/86}
\usepackage{tikz}
\usetikzlibrary{calc}

\newcommand{\directedPath}[5][]
{
\coordinate (c0) at (#2);
\path (c0)
\foreach [var=\dir,count=\cur] in {#5}
{
++({(1-(1-1/sqrt(2))*mod(\dir, 2))*#4*(mod(\dir-1, 3)-1)},{(1-(1-1/sqrt(2))*mod(\dir, 2))*#4*(div(\dir-1, 3)-1)}) coordinate (c\cur)
};
\path[#1] (#2) -- (c1) \foreach [var=\dir,count=\cur] in {#5}
{
-- (c\cur)
} -- (#3);
}

\begin{document}

\begin{tikzpicture}
\node [draw=green] (Start) at (0, 0) {Start};
\node [draw=red] (End) at (5, 2) {End};
\directedPath[draw=black, >->]{Start}{End}{1.0}{3,6,9,8,7,8,9,6,3}
\end{tikzpicture}

\end{document}


The two foreach loops are because the path starts and ends at non-zero sized nodes, but the displacements are relative to the node centres. In the second path, there's an extra (c1) which is needed due to the issue raised at Draw a path between many nodes using foreach. For an alternative solution, see the answers there.

-