Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I'm trying to obtain this longitudinal wave with TikZ:

enter image description here

Here's my code

\documentclass{article}
\usepackage{tikz}

\begin{document}  

\usetikzlibrary{decorations.pathmorphing}

\begin{tikzpicture}[decoration={coil}]

\draw[decorate, decoration={aspect=0.3, segment length=3mm, amplitude=3mm}] (0,0) --(3,0);
\draw[decorate, decoration={aspect=0.3, segment length=0.5mm, amplitude=3mm}] (3,0) -- (3.5,0); 
\draw[decorate, decoration={aspect=0.3, segment length=3mm, amplitude=3mm}] (3.5,0) -- (5,0);

\end{tikzpicture}
\end{document}

but so there are the junctions between one line and the others that interrupt the continuity of the coil. How can improve it?

share|improve this question

2 Answers 2

up vote 10 down vote accepted

It seems that if there isn't room for a complete loop, the path will be finished with a straight line. By making a slight change in the endpoint for the first path, the result is better. Also, to make the loop continous, and not turn around at the midpoint, you can make the amplitude negative for the second and third path.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.pathmorphing}
\begin{document} 

\begin{tikzpicture}[decoration={coil}]

\draw[decorate, decoration={aspect=0.3, segment length=3mm, amplitude=3mm}] (0,0) --(3.03,0);
\draw[decorate, decoration={aspect=0.3, segment length=0.5mm, amplitude=-3mm}] (3.03,0) -- (3.49,0); 
\draw[decorate, decoration={aspect=0.3, segment length=3mm, amplitude=-3mm}] (3.48,0) -- (4.98,0);

\end{tikzpicture}
\end{document}

enter image description here

share|improve this answer
    
wow! thank you! the solution was simpler than I thought! –  Ale Jun 11 '11 at 15:49

Here's an alternative to using decorations which gives you a little more control (though I should say at the outset that I think that the more stylised version from the decoration actually looks neater). I recently found myself wanting to draw a helix and so adapted the code for arcs to allow for a transversal shift as it draws the arc. By varying the shift, I can get a longitudinal wave. The code looks a bit complicated, but it is a very simple adaptation of the code for arcs (and of course it could be hidden away in a package!).

Here's the result first:

longitudinal wave

If the horrible code were in a package, this is what you would write to get that:

\documentclass{standalone}
\usepackage{tikz}
\usepackage{helix}
\begin{document}
\def\gxhelix{0}
\begin{tikzpicture}
\foreach \sep in {0,10,...,360} {
\pgfmathsetmacro{\rsep}{3*cos(\sep)^2}
\helical[.3*\rsep]{\xhelix}{360}
\draw[blue,helix=.3*\rsep]
 (\gxhelix,0,0)
 arc[radius=1,
   start angle=90,
   delta angle=360,
   y={(0,1,0)},
   x={(0,0,-1)}];
\pgfmathsetmacro{\gxhelix}{\xhelix + \gxhelix}
\global\let\gxhelix=\gxhelix
}
\end{tikzpicture}
\end{document}

The helix key replaces the arc macro with the modified one and sets the shift factor in the helix. So by varying that, we can get the wave-like behaviour. The \helical macro is a shortcut for computing the shift factor so that each cycle starts at the right place from the previous.

The horrible code is the following:

\makeatletter
\pgfutil@tempdima=1cm
\pgfmathsetmacro{\pgf@helix@factor}{\the\pgfutil@tempdima}
\pgfkeys{
  /tikz/helix/.default={1},
  /tikz/helix/.code={
    \let\pgf@arc=\pgf@helix
    \pgfmathsetmacro{\pgf@helix@st}{#1*\pgf@helix@factor/360}
  }
}

% convert an angle into a helical distance
\newcommand{\helical}[3][1]{%
  \pgfmathsetmacro{#2}{#1*(#3)/360}%
}

\newdimen\pgf@helix@len
\def\pgf@helix{%
  {%
  \pgfutil@tempdima=\pgf@arc@radius@a pt%
  \pgfutil@tempdimb=\pgf@arc@radius@b pt%
  %
  \pgf@xa=\pgf@arc@local@angle@a\relax% 
  \pgf@xb=\pgf@arc@local@angle@b\relax%
  \advance\pgf@xb by-\pgf@xa\relax%
  \ifdim\pgf@xb<0pt\relax%
    \pgf@xb=-\pgf@xb\relax%
  \fi%
  \ifdim\pgf@xb=90.0pt%
    \def\pgfmathresult{0.55228475}%
  \else%
    \pgfmathparse{1.333333333*tan(.25*\pgf@sys@tonumber{\pgf@xb})}% many thanks to Ken Starks
  \fi%
    \pgf@helix@len=\pgf@helix@st\pgf@xb\relax
  \pgfutil@tempdima=\pgfmathresult\pgfutil@tempdima%
  \pgfutil@tempdimb=\pgfmathresult\pgfutil@tempdimb%
  %.. controls +(\pgf@xa+90:\pgfutil@tempdima) and +(\pgf@xb-90:\pgfutil@tempdima) .. +(-(#1:#3)+(#2:#3))%
  % store first support vector in xa/ya:
  \pgf@xa=\pgf@arc@local@angle@a\relax%
  \ifdim\pgf@arc@local@angle@b>\pgf@arc@local@angle@a\relax%
    \advance\pgf@xa by 90pt\relax%
  \else%
    \advance\pgf@xa by -90pt\relax%
  \fi%
  \edef\pgf@arc@angle{\pgf@sys@tonumber{\pgf@xa}}%  
  \pgfpointtransformed{\pgfpointpolar{\pgf@arc@angle}{\pgfutil@tempdima and \pgfutil@tempdimb}}%
  \advance\pgf@x by-\pgf@pt@x%
  \advance\pgf@y by-\pgf@pt@y%
  \pgf@xa=\pgf@path@lastx%
  \pgf@ya=\pgf@path@lasty%
  \advance\pgf@xa by \pgf@x%
  \advance\pgf@ya by \pgf@y%
  % store target in xb/yb:
  \pgfpointtransformed{\pgfpointpolar{\pgf@sys@tonumber{\pgf@arc@local@angle@a}}{\pgf@arc@radius@a pt and \pgf@arc@radius@b pt}}%
  \pgf@xb=\pgf@path@lastx%
  \pgf@yb=\pgf@path@lasty%
  \advance\pgf@xb by -\pgf@x%
  \advance\pgf@yb by -\pgf@y%
  \pgfpointtransformed{\pgfpointpolar{\pgf@sys@tonumber{\pgf@arc@local@angle@b}}{\pgf@arc@radius@a pt and \pgf@arc@radius@b pt}}%
  \advance\pgf@xb by \pgf@x%
  \advance\pgf@yb by \pgf@y%
  % store second support xc/yc:
  \ifdim\pgf@arc@local@angle@b>\pgf@arc@local@angle@a\relax%
    \advance\pgf@arc@local@angle@b by -90pt\relax%
  \else%
    \advance\pgf@arc@local@angle@b by 90pt\relax%
  \fi%
  \pgfpointtransformed{\pgfpointpolar{\pgf@sys@tonumber{\pgf@arc@local@angle@b}}{\pgfutil@tempdima and \pgfutil@tempdimb}}%
  \advance\pgf@x by-\pgf@pt@x%
  \advance\pgf@y by-\pgf@pt@y%
  \pgf@xc=\pgf@xb\relax%
  \pgf@yc=\pgf@yb\relax%
  \advance \pgf@xc by \pgf@x\relax%
  \advance \pgf@yc by \pgf@y\relax%
    \advance\pgf@xa by .3333333\pgf@helix@len\relax
    \advance\pgf@xc by .6666666\pgf@helix@len\relax
    \advance\pgf@xb by \pgf@helix@len\relax
  \pgfsyssoftpath@curveto{\the\pgf@xa}{\the\pgf@ya}{\the\pgf@xc}{\the\pgf@yc}{\the\pgf@xb}{\the\pgf@yb}%
  \global\pgf@path@lastx=\pgf@xb%
  \global\pgf@path@lasty=\pgf@yb%
  \pgf@protocolsizes{\pgf@xa}{\pgf@ya}%
  \pgf@protocolsizes{\pgf@xb}{\pgf@yb}%
  \pgf@protocolsizes{\pgf@xc}{\pgf@yc}%
  }%
}
\makeatother
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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