I would like to draw a diagram of a wave penetrating a body, well several bodies. Or in some cases appear to go through a hollow cylinder. Since all of this is projected onto a 2d plane, this effect is drawn practically as just stopping the drawing of the wave at a certain point.

I've been using the snake decoration to do this, but it seems that if distance between the two points that I want to draw between is not and integer number times the frequency of the wave, a straight segment appears at the end of the snake.

There have been several questions and solutions about this problem, but all of the given solutions involve changing the frequency of the wave to stretch or squish the wave so that $n$ cycles of wave fit in the gap. (here, here, here, and here, for example.)

Technically, the wave I'm drawing should have a constant frequency throughout, so what I'd really like is a way of truncating the wave regardless of the point in the cycle the wave ends at. I've tried to illustrate this below:

% straight line at end of snake
\draw [decorate, decoration=snake] (0,0) -- (1.2,0);
% changing the frequency to fit wave path length:
\draw [decorate, decoration=snake, segment length=13] (0,-1) -- (1.2,-1); 
% the effect I'm after, truncated snake at any amplitude:
\draw [decorate, decoration=snake] (0,-2) -- (2,-2);
\fill [white] (1.2,-2.2) rectangle (2.1,-1.8);

I hope I've made myself clear, please ask for further clarification if needed.

  • 1
    Snake decoration stitches quarter and halves of sine curves not a continuous curve. So you have to write a new decoration or clip the path. – percusse Nov 3 '16 at 14:24
  • @percusse thanks for the info, useful to know what's going on underneath. – thosphor Nov 3 '16 at 14:31

You can actually plot a wave as sine function that it is. Then you can set the exact function you want to display and plot it. A wave can be described as

y(x) = A*sin(w*x + b)

So you plot it like \draw[domain=C:D] plot (\x,{A*sin(w*\x r + br)});, where the r's stand for radians. Heck, you can even make a command for that, which translates everything to radians out of the box:

\newcommand{\sinewave}[4][]{\draw[#1]  plot (\x,{#2*sin((#4*pi/180)r + 2*pi*#3*\x r)})}

Here you get a cmd like \sinewave[tikz options]{Amplitude}{Frequency, in Hz}{Phase angle, in degrees}. The domain option set the start and end of the sine wave and samples sets the 'smoothness' of the wave.

Here's a complete MWE:


\newcommand{\sinewave}[4][]{\draw[#1]  plot (\x,{#2*sin((#4*pi/180)r + 2*pi*#3*\x r)})}

\begin{tikzpicture}[domain=0:1.2, samples=120]
\draw plot (\x,{0.1*sin(10*\x r)});
\draw[yshift=-1cm] plot (\x,{0.15*sin(13*\x r)});

Compilation result

  • Thanks for the answer. I had a feeling I would end up doing something like this but I wanted confirmation that I couldn't do it with snake. – thosphor Nov 3 '16 at 14:35
  • As the matter of fact you can. But not in a straightfoward way. You'd have to do as percusse said, clip the path or use the shorten key (although you'd have to guess the sorten value) orr... you could also draw a bounding box on top of the snakes hiding their ends, pretty much like you did in your example. – Guilherme Zanotelli Nov 3 '16 at 14:40
  • But as since you said you wanted to control the frequency of the wave I assumed you wanted to get a specific result, to rely on. For that reason I think plotting a sine wave is the best way to go. – Guilherme Zanotelli Nov 3 '16 at 14:42
  • I would've used segment length to control the frequency with snake, sorry for the confusion. Out of interest, do you know of a way to make the cut off from this plot always be vertical? – thosphor Nov 3 '16 at 17:28
  • I know you meant to use the segment length, but the use of the word 'frequency' inspires academic thoughts. You can either use tikz option rotate and rotate around or switch the coordinates: instead of (\x , {A*sin(w*\x r)}) use ({A*sin(w*\x r)} , \x), to make the wave vertical, if I understood your correctly that is want you want, right? – Guilherme Zanotelli Nov 3 '16 at 17:43

Guilherme's answer is nice. An alternate solution is to use the shorten >= key:

\usetikzlibrary{shapes.geometric, snakes}


\draw[snake=coil, segment aspect=0, color=red, semithick]%
     (0.5in,2in) -- ++(0.375in,-0.75in);

\draw[snake=coil, segment aspect=0, color=blue, semithick, shorten >= 5pt]%
     (1in,2in) -- ++(0.375in,-0.75in);


It does require fiddling with the exact value you use for that key though.

enter image description here

  • snake=coil ?? – percusse Nov 3 '16 at 14:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.