Рубрики

drawing

Drawing tips for spring elements

I would like to draw a spring in a HTML5 canvas, and show if that spring is at its rest length or not. My spring is attached to a rectangular shape to some X-Y coordinates and defined as follows:


“Brilliant, learned loads. As a complete beginner I was apprehensive, but it was even better than I’d hoped.”

This has been an amazing course to teach and support students to grow and develop as artists. All the students have given so much of thir enthusiasm and dedication on all the exercises and tasks and homework as well. One of the most enjoyable aspects for me is seeing people’s confidence grow in our Show + Share sessions where we all share our work and exchange ideas, reflections and feeback on the completed work. All students have been supportive of each other and celebrated the different style of artwork and inteersts. Many have progressed to the next term about Material Techniques.

Read further to find out what the students thought of their experience.

Student Comments

“The course has exceeded my expectations. [I’ve learned] the 5-step drawing process, composition, form… how to see.”
Anthony S

“Really enjoyed learning the basics of drawing from mark-making to colour and composition as well as all the other elements required to create a picture. Have learnt how to apply line, tone, form, colour, texture, shape and pattern and how these relate. I feel much more confident in starting a project as a result. Jeff H

“My first experience of taught drawing and painting. I enjoyed and learned from the information given. I’ve learned ways of seeing and understanding how to capture that on paper. I think that will give me more choices and structure my preferences into the future. It’s a broad introduction and its hard to assimilate – those who did more drawing and painting outside the sessions [homework] gained more. Its still quite a confusing blur but I need to draw and practice. Thank you”
Seona O

“It lays down the foundations for drawing in a step-by-step process in a relaxed way. [I have learnt] a lot. Regarding techniques for drawing and how to be a better at measuring, etc. [Has the course met your expectations?] Yes +++ thank you so much.”
Sarah H

“Brilliant, learned loads – drawing, materials – still lives. [My course highlights were] all of it. As a complete beginner I was apprehensive, but it was even better than I’d hoped.”
Helen E

“Well informed, step by step description method and flow of object. Good understanding of colour, lines. Overall this is a good choice to take part in. [I have learned about] drawing methodology, object placing with shading, the light elements in objects to make an interesting painting with full of statement. Colour planning, balancing with background. [My course highlights were to] fully understand yourself in drawing, by expressing in shade and colours. What I had expected the course has met beyond. I am totally happy with what I had learnt.”
Shabana J

“Well informed, lots of directional assistance where required, freedom to work at own competency. [I have learned] spatial awareness, tonal balancing has been a key takeaway and something I’m going to continue to progress. [My course highlights were] oil pastels and inks and longer periods of time to work on set pieces. Practical time shorter than anticipated, however I hadn’t considered how fast 2.5 hours go . All points content-wise has been really helpful and digestible. Thank you”
Vicky F

“I’ve really enjoyed the course. It’s definitely helped me improve my drawing skills but also has encouraged me to explore a wider range of art materials. I have found the teaching on Art Elements and Art principles and composition very helpful. [I have learned] drawing methodology has been particularly helpful. I’ve also enjoyed looking at examples of art works (from both art history and work of other participants on the course). [My course highlights] have been the opportunity and encouragement to work with a wider range of art materials. The course has more than met my expectations. I’ve learnt lots and found it very stimulating and given me lots of ideas and topics I want to investigate further.”
Bernie M


How to draw a spring?

I am new to Mathematica and have recently been exploring graphical animations. So I was experimenting with simple concepts in periodic motion and hence wondered how can I draw a simple spring? Is there an easier/better way to do this? The solution I arrived at was a simple function to draw a spring between two $x$ and $y$ coordinates.

hspring[a0_, x10_, x20_] := Module[, h = (x2 - x1)/n; xvalues = Table[k, ]; yvalues = Table[a Sin[m Pi/2], ]; Line[Transpose @ ] ]; vspring[a0_, y10_, y20_] := Module[, h = (y2 - y1)/n; yvalues = Table[k, ]; xvalues = Table[a Sin[m Pi/2], ]; Line[Transpose @ ] ]; Manipulate[ Graphics[]>, PlotRange -> , >], ] 

Follow
411 4 4 silver badges 14 14 bronze badges
asked Nov 17, 2013 at 13:31
David McHarg David McHarg
1,633 1 1 gold badge 15 15 silver badges 28 28 bronze badges
$endgroup$
$begingroup$ Look here demonstrations.wolfram.com/SimpleHarmonicMotionOfASpring $endgroup$
Nov 17, 2013 at 13:57
$begingroup$ or here: demonstrations.wolfram.com/SimpleSpringMassDamping $endgroup$
Nov 17, 2013 at 14:38

$begingroup$ I was surprised that there is no Spring[] build in function in Mathematica Graphics actually. There should be form 3D and 2D. For dynamics and mechanical demos, it will be useful to have one with many options to use. $endgroup$

Nov 17, 2013 at 22:20

$begingroup$ It would be nice to have procedures that can take the spring’s endpoints as a parameter. So that they can be used as ‘graphics primitives’ to draw complex pictures or animations. Something in the form: spring[, 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$

Nov 18, 2013 at 9:53

$begingroup$ With this number of beautiful solutions it is possible to start a “Miss Spring 2014” competition. $endgroup$

Jan 8, 2014 at 8:47

9 Answers 9

Sorted by: Reset to default
$begingroup$

A textbook-like animation

turns = 10; aa = Table[Framed@ Show[ParametricPlot3D[ Piecewise[, x , <, 0 < x , , x > r>>], , PlotStyle -> , Lighting -> "Neutral", PlotPoints -> 100, MaxRecursion -> 3, PlotRange -> , , >, Axes -> None, Boxed -> False, Method -> 30>, ViewPoint -> ] /. Line[pts_, rest___] :> Tube[pts, 0.2, rest], Graphics3D[Sphere[, 1.25]]], ]>]; Export["C:\test.gif", Join[aa, Reverse@aa]] 

Follow
answered Nov 17, 2013 at 19:30
Dr. belisarius Dr. belisarius
115k 13 13 gold badges 201 201 silver badges 449 449 bronze badges
$endgroup$

$begingroup$ +1, With PlotPoints -> 4 turns + 1, MaxRecursion -> 0 it looks better, especially for a big number of turns 🙂 $endgroup$

Nov 17, 2013 at 19:53
$begingroup$ Line join should be rounded to make it looks better. $endgroup$
Nov 17, 2013 at 20:36
$begingroup$ Finally something that looks like a spring! 🙂 $endgroup$
Nov 18, 2013 at 4:28
$begingroup$ Now it even has SHM.+1 $endgroup$
Jan 7, 2014 at 19:18
$begingroup$

In 3D you can use a spiral:

spring3D[height_, n_, opts___] := ParametricPlot3D[ , , Boxed -> False, Axes -> False, opts] 

Follow
answered Nov 17, 2013 at 14:25
ssch ssch
16.5k 2 2 gold badges 53 53 silver badges 87 87 bronze badges
$endgroup$

$begingroup$ A tubular variant can be seen here: davidaltherr.net/mathematics/notebooks/mass_spring_one_d/… . Is it me or your version is highly non-uniform? I mean the coils at the moving end are unwinding much faster then those at the fixed end. $endgroup$

Nov 17, 2013 at 21:46
$begingroup$ @Peltio Strange perspective I suppose, projected version $endgroup$
Nov 17, 2013 at 21:54
$begingroup$ of course, it is in a 3D box! (Facepalm) $endgroup$
Nov 17, 2013 at 22:40
$begingroup$

I propose a bit more compact solution:

spring[r_: , n_: 20, w_: 1] := Line@Transpose[.<(# - 1)/(2 n), Re[I^#] w/Norm[r]>] &@Range[2 n + 1]; 

Here r is the vector of the spring. The default value corresponds to the horizontal unit-length spring. n is the number of half-waves and w is the width of the spring.

You can play with it with Locator :

Manipulate[Graphics[spring[r], PlotRange -> 5], >, Locator>] 

enter image description here

  1. Cross[r] rotates r by 90 degrees.
  2. is the rotation transform.
  3. Instead of Re[I^#] you can use Sin , TriangleWave , etc.

Follow
answered Nov 17, 2013 at 14:13
ybeltukov ybeltukov
43.5k 5 5 gold badges 107 107 silver badges 210 210 bronze badges
$endgroup$
$begingroup$

The drawings by @Peltio reminded me of the way my high school teacher drew coils so I have opted for faking the 3d effect. Essentially, a squinted cycloid curve loos like a coil under perspective:

With[, ParametricPlot[, ]] 

coil

which is OK, but the lines crossing ruins the 3D effect. A way to amend that is by generating a set of allowed ranges for the parameter along the cycloid and wrapping the whole thing in a function:

 coilFunc[revs_, stretch_, t_] := Block[, range = >~Join~ Table[, ]; range = range/revs; If[Or @@ ((#1 < t < #2) & @@@ range), ] ] 

the values of the parameters gap and gapPos are what I found aesthetically pleasing. Now, you can play with it:

Manipulate[ Show[, PlotStyle -> Thick, PlotRange -> , All>]>] , ] 

enter image description here

but to properly fake 3d, one needs to amend the ColorFunction appropriately. So the following is the above code with the added option ColorFunction -> ] . I call it "the psychedelic spring":

Follow
answered Nov 22, 2013 at 17:04
gpap gpap
9,626 3 3 gold badges 23 23 silver badges 66 66 bronze badges
$endgroup$

$begingroup$ +1 Beautiful. And the Psychedelic spring actually fits well in the '60s era that gave birth to those books :-). Can you give a version that accepts general 2D points for the extremes? $endgroup$

Nov 22, 2013 at 17:34

$begingroup$ I might be a couple of days but yep, I'll edit in an improved version when I find the time. $endgroup$

Nov 22, 2013 at 17:37
$begingroup$

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 = 1/(2 n + 1); xlist = Flatten[], 1 - 1.5 dl, 1>]; ylist = Flatten[], 0, 0>]; Transpose[] ] 

This is a spring connecting and 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 and . Since this is very old code, I defined my own transformation matrix as in

coordinateTrasformMatrix[, ] := Block[, theta = ArcTan[x1-x0,y1 - y0]; , > ] 

(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, , >] := Block[, scale = Sqrt[(x1 - x0)^2 + (y1 - y0)^2]; mat = coordinateTrasformMatrix[, ]; ( + mat .(*#)) & /@ coords ] 

Then, a spring with n coils and aspect ratio h between points and would be given by

spring[,>,n_:8, h_:.25]:= Line[ coordinateTransform[ unitSpringPoints[n, h], , >]] 
Show[ Graphics[ spring[, >, 5, 0.25] ], AspectRatio -> Automatic] 

Sample animation (not tested, adapted from old code):

Do[ Show[ Graphics[ spring[< , >] ], AspectRatio -> Automatic, PlotRange -> , > ], ] 

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

Crawford's springs

(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"

Alonso Finn's springs

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).

2 Answers 2

Sorted by: Reset to default

Rather than use bezier curves which do not actually fit the curve of a spring (but close) I just use a simple path and use trig functions to draw each winding. the function has a start x1,y1 and end x2, y2, windings (should be an integer), width of spring, the offset (bits at ends), Dark colour, and light colour, and the stroke width (width of the wire).

The demo draws an extra highlight to give the spring a little more depth. It can easily be removed.

The code came from this answer that has a simpler version of the same function

 function drawSpring(x1, y1, x2, y2, windings, width, offset, col1, col2, lineWidth) < var x = x2 - x1; var y = y2 - y1; var dist = Math.sqrt(x * x + y * y); var nx = x / dist; var ny = y / dist; ctx.strokeStyle = col1 ctx.lineWidth = lineWidth; ctx.lineJoin = "round"; ctx.lineCap = "round"; ctx.beginPath(); ctx.moveTo(x1,y1); x1 += nx * offset; y1 += ny * offset; x2 -= nx * offset; y2 -= ny * offset; var x = x2 - x1; var y = y2 - y1; var step = 1 / (windings); for(var i = 0; i > ctx.lineTo(x2, y2); ctx.lineTo(x2 + nx * offset, y2 + ny * offset) ctx.stroke(); ctx.strokeStyle = col2 ctx.lineWidth = lineWidth - 4; var step = 1 / (windings); ctx.beginPath(); ctx.moveTo(x1 - nx * offset, y1 - ny * offset); ctx.lineTo(x1, y1); ctx.moveTo(x2, y2); ctx.lineTo(x2 + nx * offset, y2 + ny * offset) for(var i = 0; i else < ctx.lineTo(xx,yy); >> > ctx.stroke(); > function display() < ctx.setTransform(1, 0, 0, 1, 0, 0); // reset transform ctx.globalAlpha = 1; // reset alpha ctx.clearRect(0, 0, w, h); ctx.lineWidth = 8; drawSpring(canvas.width / 2,10, mouse.x,mouse.y,8,100,40,"green","#0C0",15); >// Boiler plate code from here down and not part of the answer var w, h, cw, ch, canvas, ctx, mouse, globalTime = 0, firstRun = true; ;(function() < const RESIZE_DEBOUNCE_TIME = 100; var createCanvas, resizeCanvas, setGlobals, resizeCount = 0; createCanvas = function () < var c, cs; cs = (c = document.createElement("canvas")).style; cs.position = "absolute"; cs.top = cs.left = "0px"; cs.zIndex = 1000; document.body.appendChild(c); return c; >resizeCanvas = function () < if (canvas === undefined) < canvas = createCanvas(); >canvas.width = innerWidth; canvas.height = innerHeight; ctx = canvas.getContext("2d"); if (typeof setGlobals === "function") < setGlobals(); >if (typeof onResize === "function") < if(firstRun)< onResize(); firstRun = false; >else < resizeCount += 1; setTimeout(debounceResize, RESIZE_DEBOUNCE_TIME); >> > function debounceResize() < resizeCount -= 1; if (resizeCount > setGlobals = function () < cw = (w = canvas.width) / 2; ch = (h = canvas.height) / 2; >mouse = (function () < function preventDefault(e) < e.preventDefault(); >var mouse = < x : 0, y : 0, w : 0, alt : false, shift : false, ctrl : false, buttonRaw : 0, over : false, bm : [1, 2, 4, 6, 5, 3], active : false, bounds : null, crashRecover : null, mouseEvents : "mousemove,mousedown,mouseup,mouseout,mouseover,mousewheel,DOMMouseScroll".split(",") >; var m = mouse; function mouseMove(e) < var t = e.type; m.bounds = m.element.getBoundingClientRect(); m.x = e.pageX - m.bounds.left; m.y = e.pageY - m.bounds.top; m.alt = e.altKey; m.shift = e.shiftKey; m.ctrl = e.ctrlKey; if (t === "mousedown") < m.buttonRaw |= m.bm[e.which - 1]; >else if (t === "mouseup") < m.buttonRaw &= m.bm[e.which + 2]; >else if (t === "mouseout") < m.buttonRaw = 0; m.over = false; >else if (t === "mouseover") < m.over = true; >else if (t === "mousewheel") < m.w = e.wheelDelta; >else if (t === "DOMMouseScroll") < m.w = -e.detail; >if (m.callbacks) < m.callbacks.forEach(c =>c(e)); > if ((m.buttonRaw & 2) && m.crashRecover !== null) < if (typeof m.crashRecover === "function") < setTimeout(m.crashRecover, 0); >> e.preventDefault(); > m.addCallback = function (callback) < if (typeof callback === "function") < if (m.callbacks === undefined) < m.callbacks = [callback]; >else < m.callbacks.push(callback); >> > m.start = function (element) < if (m.element !== undefined) < m.removeMouse(); >m.element = element === undefined ? document : element; m.mouseEvents.forEach(n => < m.element.addEventListener(n, mouseMove); >); m.element.addEventListener("contextmenu", preventDefault, false); m.active = true; > m.remove = function () < if (m.element !== undefined) < m.mouseEvents.forEach(n =>< m.element.removeEventListener(n, mouseMove); >); m.element.removeEventListener("contextmenu", preventDefault); m.element = m.callbacks = undefined; m.active = false; > > return mouse; >)(); // Clean up. Used where the IDE is on the same page. var done = function () < window.removeEventListener("resize", resizeCanvas) mouse.remove(); document.body.removeChild(canvas); canvas = ctx = mouse = undefined; >function update(timer) < // Main update loop if(ctx === undefined)< return; >globalTime = timer; display(); // call demo code if (!(mouse.buttonRaw & 2)) < requestAnimationFrame(update); >else < done(); >> setTimeout(function()< resizeCanvas(); mouse.start(canvas, true); mouse.crashRecover = done; window.addEventListener("resize", resizeCanvas); requestAnimationFrame(update); >,0); >)(); /** SimpleFullCanvasMouse.js end **/

Colin Wynn
the authorColin Wynn

Leave a Reply