10

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?

2
  • Welcome to TeX.sx! We usually do not include greetings or thanks in the questions. Please visit the faq and meta.tex.stackexchange.com/q/1436/19384 for more information on the site. Commented Jan 2, 2013 at 17:52
  • 2
    Ah yes, I'd like to see this solved as well!
    – Jake
    Commented Jan 2, 2013 at 18:16

1 Answer 1

14

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}
1
  • 1
    Man you totally rule! It is a marvellous solution to the problem. Thank you so much. :-)
    – Dox
    Commented Jan 3, 2013 at 12:36

You must log in to answer this question.

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