16

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.

2
  • 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
    Commented Jun 21, 2012 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
    Commented Jun 21, 2012 at 18:59

1 Answer 1

23

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}
2
  • 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
    Commented Jun 22, 2012 at 0:25
  • Can you perhaps comment on why the complete sines decoration falls apart when applied per segment? tex.stackexchange.com/a/604455/2113
    – Cactus
    Commented Jul 10, 2021 at 8:25

You must log in to answer this question.

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