15

I'm trying to reproduce in like the following picture:

Actually I would like to slightly modifies it as I would like all the spring to be connected to a common wall at the top. I have begin it with the following code:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{patterns,snakes}
\begin{document}
\begin{tikzpicture}{every node/.style={draw,outer sep=0pt,thick}}
\node (ground) [fill,gray, pattern=north east lines,minimum width=5cm,%
minimum height=.3cm,anchor=north,draw=none] {};
\node (M1) [draw,minimum width=0.1cm,minimum height=0.1cm] at (-2,-2) {m};
\draw [ snake=coil, segment amplitude=5pt, segment length=5pt] (ground.south) -- (M1);
\node (M2) [draw,minimum width=0.1cm,minimum height=0.1cm] at (-1.5,-2.5) {m};
\draw [ snake=coil, segment amplitude=5pt, segment length=5pt] (ground.south) -- (M2);
\end{tikzpicture}
\end{document}

The first problem I've encountered is that the ground pattern is filled and do not exhibit the pattern with oblique lines. The second problem I do not know how to position correctly the different masses. By the wave the distances and elongation of the masses follows a sinusoidal shape so I think there should be a way to place them automatically.

Martin Scharrer
  • 262,582
Nicola Vianello
  • 645
  • 7
  • 15
  • Welcome to TeX.sx! Please always add a full, but minimal working example (MWE) that illustrates your problem. It's not necessary to begin your posts with a greeting or closing. Please make sure that all images are uploaded using the official stackexchange interface, i.e. the image icon on top of the text field (shortcut: CTRL+G). This ensures that all images are always accessible and do not expire. – Martin Scharrer Nov 07 '11 at 11:07

1 Answers1

24

Updated answer

A first attempt with coil springs (need to be improved to take care of the natural length of the spring).

enter image description here

\documentclass[tikz]{standalone}

\usetikzlibrary{decorations.pathmorphing,calc,patterns}

\makeatletter

\def\pgfdecorationspringstraightlinelength{.5cm}
\def\pgfdecorationspringnumberofelement{8}
\def\pgfdecorationspringnaturallength{5cm}
\pgfkeys{%
  /pgf/decoration/.cd,
  spring straight line length/.code={%
    \pgfmathsetlengthmacro\pgfdecorationspringstraightlinelength{#1}},
  spring natural length/.code={%
    \pgfmathsetlengthmacro\pgfdecorationspringnaturallength{#1}},
  spring number of element/.store in=\pgfdecorationspringnumberofelement
}

\pgfdeclaredecoration{coil spring}{straight line}{%
  \state{straight line}[%
    persistent precomputation = {%
      % Compute the effective length of the spring (without the length
      % of the two straight lines): \pgfdecorationspringeffectivelength
      \pgfmathsetlengthmacro{\pgfdecorationspringeffectivelength}%
        {\pgfdecoratedpathlength-2*\pgfdecorationspringstraightlinelength}
      % Compute the effective length of one coil pattern:
      % \pgfdecorationspringeffectivelengthofonecoil
      \pgfmathsetlengthmacro{\pgfdecorationspringeffectivelengthofonecoil}%
        {\pgfdecorationspringeffectivelength/\pgfdecorationspringnumberofelement}
    },
    width = \pgfdecorationspringstraightlinelength,
    next state = draw spring]{%
      \pgfpathlineto{%
        \pgfqpoint{%
          \pgfdecorationspringstraightlinelength}{0pt}}
  }
  \state{draw spring}%
    [width=\pgfdecorationspringeffectivelengthofonecoil,
     repeat state=\pgfdecorationspringnumberofelement-1,next state=final]{%
       \pgfpathcurveto
         {\pgfpoint@onspringcoil{0    }{ 0.555}{1}}
         {\pgfpoint@onspringcoil{0.445}{ 1    }{2}}
         {\pgfpoint@onspringcoil{1    }{ 1    }{3}}
       \pgfpathcurveto
         {\pgfpoint@onspringcoil{1.555}{ 1    }{4}}
         {\pgfpoint@onspringcoil{2    }{ 0.555}{5}}
         {\pgfpoint@onspringcoil{2    }{ 0    }{6}}
       \pgfpathcurveto
         {\pgfpoint@onspringcoil{2    }{-0.555}{7}}
         {\pgfpoint@onspringcoil{1.555}{-1    }{8}}
         {\pgfpoint@onspringcoil{1    }{-1    }{9}}
       \pgfpathcurveto
         {\pgfpoint@onspringcoil{0.445}{-1    }{10}}
         {\pgfpoint@onspringcoil{0    }{-0.555}{11}}
         {\pgfpoint@onspringcoil{0    }{ 0    }{12}}
  }
  \state{final}{%
    \pgfpathlineto{\pgfpointdecoratedpathlast}
  }
}

\def\pgfpoint@onspringcoil#1#2#3{%
  \pgf@x=#1\pgfdecorationsegmentamplitude%
  \pgf@x=.5\pgf@x%
  \pgf@y=#2\pgfdecorationsegmentamplitude%
  \pgfmathparse{0.083333333333*\pgfdecorationspringeffectivelengthofonecoil}%
  \pgf@xa=\pgfmathresult pt
  \advance\pgf@x by#3\pgf@xa%
}


\makeatother

\tikzset{%
  Spring/.style = {%
    decoration = {%
      coil spring,
      spring straight line length = .5cm,
      % To be added
      spring natural length = #1,
      spring number of element = 8,
      amplitude=3mm},
    decorate,
    very thick},
  Spring/.default = {4cm}}


\begin{document}

\begin{tikzpicture}
  \def\SpringNaturalLength{4cm}%
  \def\xMax{10}%
  \pgfmathdeclarefunction{wave}{1}{%
    \pgfmathparse{\SpringNaturalLength*(1+.5*cos(\x*40))}}
  \filldraw[gray,pattern=north east lines] (0,0) -| (\xMax,.2) -| (0,0);
  \foreach \x in {0,0.75,...,\xMax}{%
    \draw[Spring] (\x,0) -- node[at end,fill=red,circle] {} (\x,{-wave(\x)});}
\end{tikzpicture}
\end{document}

Original answer

Something like that (sorry, I do not use a coil to represent a spring).

Wave spring

\documentclass[tikz]{standalone}

\usetikzlibrary{decorations.pathmorphing,calc,patterns}

\makeatletter

\def\pgfdecorationspringstraightlinelength{.5cm}
\def\pgfdecorationspringnumberofelement{8}
\def\pgfdecorationspringnaturallength{5cm}
\pgfkeys{%
  /pgf/decoration/.cd,
  spring straight line length/.code={%
    \pgfmathsetlengthmacro\pgfdecorationspringstraightlinelength{#1}},
  spring natural length/.code={%
    \pgfmathsetlengthmacro\pgfdecorationspringnaturallength{#1}},
  spring number of element/.store in=\pgfdecorationspringnumberofelement
}

\pgfdeclaredecoration{zig zag spring}{straight line}{%
  \state{straight line}[%
    persistent precomputation = {%
      % Compute the effective length of the spring (without the length
      % of the two straight lines): \pgfdecorationspringeffectivelength
      \pgfmathsetlengthmacro{\pgfdecorationspringeffectivelength}%
        {\pgfdecoratedpathlength-2*\pgfdecorationspringstraightlinelength}
      % Compute the effective length of one zigzag pattern:
      % \pgfdecorationspringeffectivelengthofonezigzag
      \pgfmathsetlengthmacro{\pgfdecorationspringeffectivelengthofonezigzag}%
        {\pgfdecorationspringeffectivelength/\pgfdecorationspringnumberofelement}
      % Compute the effective length of one forth of zigzag pattern:
      % \pgfdecorationspringeffectivelengthofoneforthofzigzag
      \pgfmathsetlengthmacro{%
        \pgfdecorationspringeffectivelengthofoneforthofzigzag}%
        {\pgfdecorationspringeffectivelengthofonezigzag/4}
      % Compute the length of a forth of one zigzag (fixed by spring
      % constants)
      % 4=1/4
      % 0.707=cos(45°)
      \pgfmathsetlengthmacro{\pgfdecorationspringlengthofaforthzigzag}%
        {\pgfdecorationspringnaturallength 
          /(\pgfdecorationspringnumberofelement*4*0.707)}
      % Compute the (semi) heigth
      \pgfmathsetlengthmacro{\pgfdecorationspringeffectivesemiheigth}%
        {sqrt(abs(\pgfdecorationspringlengthofaforthzigzag^2-
          \pgfdecorationspringeffectivelengthofoneforthofzigzag^2))}%
    },
    width = \pgfdecorationspringstraightlinelength,
    next state = draw spring]{%
      \pgfpathlineto{%
        \pgfqpoint{%
          \pgfdecorationspringstraightlinelength}{0pt}}
  }
  \state{draw spring}%
    [width=\pgfdecorationspringeffectivelengthofonezigzag,
     repeat state=\pgfdecorationspringnumberofelement-1,next state=final]{%
      \pgfpathlineto{%
        \pgfqpoint{%
          \pgfdecorationspringeffectivelengthofoneforthofzigzag}{%
          \pgfdecorationspringeffectivesemiheigth}}
       \pgfpathlineto{%
        \pgfpoint{%
          3*\pgfdecorationspringeffectivelengthofoneforthofzigzag}{%
          -\pgfdecorationspringeffectivesemiheigth}}
       \pgfpathlineto{%
        \pgfpoint{%
          4*\pgfdecorationspringeffectivelengthofoneforthofzigzag}{0pt}}
  }
  \state{final}{%
    \pgfpathlineto{\pgfpointdecoratedpathlast}
  }
}

\makeatother

\tikzset{%
  Spring/.style = {%
    decoration = {%
      zig zag spring,
      spring straight line length = .5cm,
      spring natural length = #1,
      spring number of element = 5},
    decorate,
    very thick},
  Spring/.default = {4cm}}


\begin{document}

\begin{tikzpicture}
  \def\SpringNaturalLength{4cm}%
  \def\xMax{10}%
  \pgfmathdeclarefunction{wave}{1}{%
    \pgfmathparse{\SpringNaturalLength*(1+.5*cos(\x*40))}}
  \filldraw[gray,pattern=north east lines] (0,0) -| (\xMax,.2) -| (0,0);
  \foreach \x in {0,0.75,...,\xMax}{%
    \draw[Spring] (\x,0) -- node[at end,fill=red,circle] {} (\x,{-wave(\x)});}
\end{tikzpicture}

\end{document}
cjorssen
  • 10,032
  • 4
  • 36
  • 126
  • Thank you very much, very nice realization. In order to reproduce exactly the figure I think I've to change from sin to cos in \SpringRestLength(1+.5cos(\x*40))} in order to have the first and last spring at rest. Is that correct? – Nicola Vianello Nov 07 '11 at 12:28
  • Yes, change to cos(\x*36). – cjorssen Nov 07 '11 at 12:34
  • thanks very nice. I will go through your code in order to understand how to enlarge the number of sines (if you look at the figure it has more than 1 period) – Nicola Vianello Nov 07 '11 at 12:40
  • Just change \xMax to a higher value or change the "period", that is the factor in the argument of the cosine. – cjorssen Nov 07 '11 at 12:44