[Tex/LaTex] Tikz: Avoiding line segments in snake path

diagramsfeynmangraphicspgf-decorationstikz-pgf

I am using tikz to draw Feynman diagrams, and I learned how to draw a curved snake path.

The problem is that in general line segments are present (I'd like to avoid them).

I found a couple of post with could help to solve the problem, but none of them is working properly for me. The post are:

The second method results in the figure below,

Diagram generated with the code below

\documentclass{beamer}


\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing,decorations.markings,snakes}
\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}{}
}
\tikzset{
  % style to apply some styles to each segment of a path
  on each segment/.style={
    decorate,
    decoration={
      show path construction,
      moveto code={},
      lineto code={
        \path [#1]
        (\tikzinputsegmentfirst) -- (\tikzinputsegmentlast);
      },
      curveto code={
        \path [#1] (\tikzinputsegmentfirst)
        .. controls
        (\tikzinputsegmentsupporta) and (\tikzinputsegmentsupportb)
        ..
        (\tikzinputsegmentlast);
      },
      closepath code={
        \path [#1]
        (\tikzinputsegmentfirst) -- (\tikzinputsegmentlast);
      },
    },
  },
  % style to add an arrow in the middle of a path
  mid arrow/.style={postaction={decorate,decoration={
        markings,
        mark=at position .5 with {\arrow[#1]{stealth}}
      }}},
}

\begin{document}
\begin{frame}
  \frametitle{Field and Mass Renormalization}
\begin{center}
      \begin{tikzpicture}[thick,scale=.6]
        \path [draw=blue,postaction={on each segment={mid arrow=blue}}]
        (-4,0) -- (-2,0) -- (2,0) -- (4,0);
        \draw[draw=blue,decorate, decoration=complete sines] (2,0) arc (0:180:2cm);
      \end{tikzpicture}
    \end{center}
\end{frame}
\end{document}

Any fresh ideas on this respect?

Best Answer

Here's a different approach that does not use a decoration, but rather a to path together with a plot statement that connects two points using a semicircle with a superimposed sine wave.

The number of complete periods to be drawn is specified using the key wave count. Another half period is added to this number so that the wave starts and ends on the outside (I think this looks better than starting on the inside or asymmetrically).

The amplitude of the wave is set using wave amplitude, and the semicircle can be flipped to the opposite side of the path using mirror semicircle=true.

This approach could reasonably easily be adapted to allow for circle sectors different from 180° (I don't know if that's ever needed in Feynman diagrams, though).

\documentclass[border=5mm]{standalone}


\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing,calc}

\newif\ifmirrorsemicircle

\tikzset{
    wave amplitude/.initial=0.2cm,
    wave count/.initial=8,
    mirror semicircle/.is if=mirrorsemicircle,
    mirror semicircle=false,
    wavy semicircle/.style={
        to path={
            let \p1 = (\tikztostart),
            \p2 = (\tikztotarget),
            \n1 = {veclen(\y2-\y1,\x2-\x1)},
            \n2 = {atan2(\y2-\y1,\x2-\x1))} in
            plot [
                smooth,
                samples=(\pgfkeysvalueof{/tikz/wave count}+0.5)*8+1, % Calculate the number of samples needed, so the samples are in sync with the wave and fall on the extrema
                domain=0:1,
                shift={($(\p1)!0.5!(\p2)$)}
            ] ({ % Polar coordinates: Angle...
                (\x*180-\n2 + 180 + \ifmirrorsemicircle 1 \else -1 \fi * 90%
            }:{ % ... and radius
                (%
                    \n1/2+\pgfkeysvalueof{/tikz/wave amplitude} * %
                    sin(
                        \x * 360 * (\pgfkeysvalueof{/tikz/wave count} + 0.5%
                    )%
                )%
            })
        } (\tikztotarget)
    }
}

\begin{document}
      \begin{tikzpicture}[thick,scale=.6]
        \draw [blue] (-4,0) -- (-2,0) -- (2,-1) -- (4,-2);
        \draw [red] (-2,0) to [wavy semicircle] (2,-1)
                to [
                    wavy semicircle,
                    wave amplitude=0.1cm,
                    wave count=15,
                    mirror semicircle
                ] (4,-2);
      \end{tikzpicture}
\end{document}