# TikZ: Decorated paths without straight segment

When a path is decorated in TikZ a straight segment might be added at the end, depending on the length of the path. This is undesirable in some cases, and a resolution for the snake decoration has appeared in this question.

I would like to get an integer or half-integer number of wavelengths in a path for a snake and a coil decoration, with the wavelength calculated automatically so that there is no straight segment at the end. I would also like a switch for each of the endpoints that allows me to choose if the path at that endpoint points in one or the other direction.

-
Just to make sure I understand correctly: The behaviour of the snake decoration in the question you linked to is basically what you want, but in addition you would like to be able to decide whether the path should end on the up or down motion? (Note that you can already flip the decoration vertically by adding mirror to the decoration options). –  Jake Jun 21 '12 at 18:00
@Jake: Thanks for looking into this. That's exactly what I want. I think that being able to decide how the path begins and ends is needed in order to be able to avoid ugliness like the one where the three gluon propagators meet in texample.net/tikz/examples/feynman-diagram. –  AndyS Jun 21 '12 at 18:59

Here's an extended version of the complete sines decoration, which can now be controlled using start up/start down and end up/end down.

\documentclass[a4paper,12pt]{article}
\usepackage{tikz}
\usetikzlibrary{decorations}
\begin{document}

\newif\ifstartcompletesineup
\newif\ifendcompletesineup
\pgfkeys{
/pgf/decoration/.cd,
start up/.is if=startcompletesineup,
start up=true,
start up/.default=true,
start down/.style={/pgf/decoration/start up=false},
end up/.is if=endcompletesineup,
end up=true,
end up/.default=true,
end down/.style={/pgf/decoration/end up=false}
}
\pgfdeclaredecoration{complete sines}{initial}
{
\state{initial}[
width=+0pt,
next state=upsine,
persistent precomputation={
\ifstartcompletesineup
\pgfkeys{/pgf/decoration automaton/next state=upsine}
\ifendcompletesineup
\pgfmathsetmacro\matchinglength{
0.5*\pgfdecoratedinputsegmentlength / (ceil(0.5* \pgfdecoratedinputsegmentlength / \pgfdecorationsegmentlength) )
}
\else
\pgfmathsetmacro\matchinglength{
0.5 * \pgfdecoratedinputsegmentlength / (ceil(0.5 * \pgfdecoratedinputsegmentlength / \pgfdecorationsegmentlength ) - 0.499)
}
\fi
\else
\pgfkeys{/pgf/decoration automaton/next state=downsine}
\ifendcompletesineup
\pgfmathsetmacro\matchinglength{
0.5* \pgfdecoratedinputsegmentlength / (ceil(0.5 * \pgfdecoratedinputsegmentlength / \pgfdecorationsegmentlength ) - 0.4999)
}
\else
\pgfmathsetmacro\matchinglength{
0.5 * \pgfdecoratedinputsegmentlength / (ceil(0.5 * \pgfdecoratedinputsegmentlength / \pgfdecorationsegmentlength ) )
}
\fi
\fi
\setlength{\pgfdecorationsegmentlength}{\matchinglength pt}
}] {}
\state{downsine}[width=\pgfdecorationsegmentlength,next state=upsine]{
\pgfpathsine{\pgfpoint{0.5\pgfdecorationsegmentlength}{0.5\pgfdecorationsegmentamplitude}}
\pgfpathcosine{\pgfpoint{0.5\pgfdecorationsegmentlength}{-0.5\pgfdecorationsegmentamplitude}}
}
\state{upsine}[width=\pgfdecorationsegmentlength,next state=downsine]{
\pgfpathsine{\pgfpoint{0.5\pgfdecorationsegmentlength}{-0.5\pgfdecorationsegmentamplitude}}
\pgfpathcosine{\pgfpoint{0.5\pgfdecorationsegmentlength}{0.5\pgfdecorationsegmentamplitude}}
}
\state{final}{}
}

\begin{tikzpicture}

\draw [gray!30] (0,-7) grid [step=0.5] (2.5,0);
\node at (1.25cm,0) [align=center,anchor=south] {\texttt{start up}\\\texttt{end up}};
\begin{scope}[
every path/.style={
decoration={
complete sines,
segment length=0.5cm,
amplitude=0.5cm,
mirror,
start up,
end up
},
decorate,
thick
}]
\foreach \length [count=\n] in {1,1.25,...,2.5}
\draw [yshift=-\n cm + 0.5cm] (0,0) node [anchor=east] {\length cm} -- (\length cm,0);
\end{scope}

\begin{scope}[xshift=3cm]
\draw [gray!30] (0,-7) grid [step=0.5] (2.5,0);
\node at (1.25cm,0) [align=center,anchor=south] {\texttt{start up}\\\texttt{end down}};
\begin{scope}[
every path/.style={
decoration={
complete sines,
segment length=0.5cm,
amplitude=0.5cm,
mirror,
start up,
end down
},
decorate,
thick
}]
\foreach \length [count=\n] in {1,1.25,...,2.5}
\draw [yshift=-\n cm + 0.5cm] (0,0) -- (\length cm,0);
\end{scope}
\end{scope}

\begin{scope}[xshift=9cm]
\draw [gray!30] (0,-7) grid [step=0.5] (2.5,0);
\node at (1.25cm,0) [align=center,anchor=south] {\texttt{start down}\\\texttt{end up}};
\begin{scope}[
every path/.style={
decoration={
complete sines,
segment length=0.5cm,
amplitude=0.5cm,
mirror,
start down,
end up
},
decorate,
thick
}]
\foreach \length [count=\n] in {1,1.25,...,2.5}
\draw [yshift=-\n cm + 0.5cm] (0,0) -- (\length cm,0);
\end{scope}
\end{scope}

\begin{scope}[xshift=6cm]
\draw [gray!30] (0,-7) grid [step=0.5] (2.5,0);
\node at (1.25cm,0) [align=center,anchor=south] {\texttt{start down}\\\texttt{end down}};
\begin{scope}[
every path/.style={
decoration={
complete sines,
segment length=0.5cm,
amplitude=0.5cm,
mirror,
start down,
end down
},
decorate,
thick
}]
\foreach \length [count=\n] in {1,1.25,...,2.5}
\draw [yshift=-\n cm + 0.5cm] (0,0) -- (\length cm,0);
\end{scope}
\end{scope}
\end{tikzpicture}
\end{document}

-
This is absolutely great! Any luck with the coil decoration? I understand that \pgfpathsine helps a lot here, so the coil might be quite a bit harder. Regarding the endpoints, though, it should be easier, since the way the path starts defines the way it ends. –  AndyS Jun 22 '12 at 0:25