This is yet another way of doing it, albeit not as elegant as ybeltukov's.
My mind is simple and I try to do one step at the time. So, here is a unit spring with n
coils and 'aspect ratio' (width with respect to the unit length) h
:
unitSpringPoints[n_, h_] := Block[{dl, xlist, ylist},
dl = 1/(2 n + 1);
xlist = Flatten[{0, 1.5 dl, dl Table[k, {k, 2, 2 n - 1}], 1 - 1.5 dl, 1}];
ylist = Flatten[{0, 0, h/2 Table[(-1)^(k + 1), {k, 2, 2 n - 1}], 0, 0}];
Transpose[{xlist, ylist}]
]
This is a spring connecting {0,0}
and {1,0}
with two small horizontal segment at the end points (that is the reason for generating two separate lists).
To show the spring just wrap a Line around the generated points, like this
Show[Graphics[Line[unitSpringPoints[5, 0.25]]]]
Next I defined a function to transform coordinates in order to produce a spring between two given points {x0,y0}
and {x1,y1}
. Since this is very old code, I defined my own transformation matrix as in
coordinateTrasformMatrix[{x0_, y0_}, {x1_, y1_}] := Block[{theta},
theta = ArcTan[x1-x0,y1 - y0];
{{Cos[theta], -Sin[theta]}, {Sin[theta], Cos[theta]}}
]
(EDIT: I incorporated a suggestion received on MMA SE to use the two-arguments form of ArcTan
in orderd to avoid Indeterminate
results for the case x0==x1
).
And then I used it to transform the coordinates of the points of the the unit spring in those of the points of the spring between the given points
coordinateTransform[coords_List, {{x0_, y0_}, {x1_, y1_}}] := Block[{scale, mat},
scale = Sqrt[(x1 - x0)^2 + (y1 - y0)^2];
mat = coordinateTrasformMatrix[{x0, y0}, {x1, y1}];
({x0, y0} + mat .({scale, 1}*#)) & /@ coords
]
Then, a spring with n
coils and aspect ratio h
between points {x0,y0}
and {x1,y1}
would be given by
spring[{{x0_,y0_},{x1_,y1_}},n_:8, h_:.25]:=
Line[ coordinateTransform[ unitSpringPoints[n, h], {{x0, y0}, {x1, y1}}]]
For example:
Show[ Graphics[ spring[{{2, 2}, {3,3}}, 5, 0.25] ], AspectRatio -> Automatic]
Sample animation (not tested, adapted from old code):
Do[ Show[
Graphics[ spring[{ {2, 2}, {3 + .5Cos[t], 2 + .8Sin[t]} }] ],
AspectRatio -> Automatic, PlotRange -> {{1, 5}, {1, 5}}
], {t, 0, 6.3, .1}
]
Some wishing
Back then I planned to replicate the shape of the springs shown in Crawford's "Waves", the third volume of the Berkeley Physics series
(I really liked the way springs are drawn there). I planned to act on the unit spring to produce the minimal set of points required for a fast but smooth interpolation, but never found the time to complete it. Perhaps someone - who knows how springs are drawn in Craword's "Waves" has a more straightforward and (possibly) elegant solution for that.
And, since we are at it, here is another spring shape I find very visually appealing. Those from Alonso and Finn's "Fundamental University Physics"
It would be nice to turn this post (the OP's) in a resource of code to draw springs in various styles (from essential to stylish or presentation-ready) and computational load (because if one wants to model a series of say 40 coupled pendulums to see how an exponential wave develop, you need something fast to draw).
spring[{P1_,P2_}, styleOptions___]
, with P1 and P2 coordinates of the endpoints in 2D or 3D space (overloading can be used). Please keep your old solutions, some users might find them faster and thus more useful than others. $\endgroup$