[Tex/LaTex] Nicer wavy line with TikZ

feynmanfeynmftikz-pgf

My question is inspired by Feynman Diagrams with tikz.

The photon line (TikZ snake) in the answer does not look like it usually looks on a Feynman diagram: in the "reference" look, which may be obtained using the feynmp package, waves start and finish in the middle of the "wave" (one may check the difference compiling the answer given). Inside the metapost code this is realized in a dumb but effective way: it takes a line and adds "waves" based on the line length. First it computes the (integer) number of waves to put on a line to make length of one as close as possible to some given number, then it computes the length of one wave and finally draws them. The Metapost code is rather short and simple.

Is there a way to fully reproduce this feynmp behaviour in TikZ?

Best Answer

Here's a new decoration, complete sines, that does what you describe: It computes the number of full waves that would fit into a given path with a specified wavelength, and then stretches the wavelength so that the path can be completely filled:

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

\pgfdeclaredecoration{complete sines}{initial}
{
    \state{initial}[
        width=+0pt,
        next state=sine,
        persistent precomputation={\pgfmathsetmacro\matchinglength{
            \pgfdecoratedinputsegmentlength / int(\pgfdecoratedinputsegmentlength/\pgfdecorationsegmentlength)}
            \setlength{\pgfdecorationsegmentlength}{\matchinglength pt}
        }] {}
    \state{sine}[width=\pgfdecorationsegmentlength]{
        \pgfpathsine{\pgfpoint{0.25\pgfdecorationsegmentlength}{0.5\pgfdecorationsegmentamplitude}}
        \pgfpathcosine{\pgfpoint{0.25\pgfdecorationsegmentlength}{-0.5\pgfdecorationsegmentamplitude}}
        \pgfpathsine{\pgfpoint{0.25\pgfdecorationsegmentlength}{-0.5\pgfdecorationsegmentamplitude}}
        \pgfpathcosine{\pgfpoint{0.25\pgfdecorationsegmentlength}{0.5\pgfdecorationsegmentamplitude}}
}
    \state{final}{}
}

\begin{tikzpicture}[
    every path/.style={
        decoration={
            complete sines,
            segment length=1cm,
            amplitude=1cm
        },
        decorate
    }]
\draw (0,0) -- (2,0);
\draw [yshift=-1.2cm] (0,0) -- (2.5,0);
\draw [yshift=-2.4cm] (0,0) -- (3,0);
\end{tikzpicture}
\end{document}

Here's an example of three paths, 2 cm, 2.5 cm and 3 cm in length, with a nominal wavelength of 1 cm. In the first case, there are two full waves with a wavelength of 1 cm, in the second there are two full waves with a wavelength of 1.25 cm, and in the third there are three full waves with a wavelength of 1 cm.

If you'd use it in the example you linked to, like this:

gluon/.style={decorate, draw=black,
        decoration={complete sines,amplitude=8pt, segment length=11pt}}
     }

it would yield this