Skip to content

Instantly share code, notes, and snippets.

@OndrejSlamecka
Created October 23, 2021 14:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save OndrejSlamecka/6401a6c6747968886204d29142859094 to your computer and use it in GitHub Desktop.
Save OndrejSlamecka/6401a6c6747968886204d29142859094 to your computer and use it in GitHub Desktop.
Animation of connected springs
using Luxor
using Colors
const height = 80
const lw = height / 10
mutable struct Spring
k::Float64 # spring constant
equilibrium_length::Float64
current_length::Float64
turns::Float64
end
transparent(c::RGB) = RGBA(c.r, c.g, c.b, 0.5)
function draw_front_line(colour, pitch, from)
f = Point(from, -height/2)
t = Point(from + pitch, height/2)
setcolor(colour)
setline(lw)
line(f, t, :stroke)
circle(f, lw/2, :fill)
circle(t, lw/2, :fill)
end
function draw_rear_line(colour, pitch, from)
f = Point(from, height/2)
t = Point(from + pitch, -height/2)
setcolor(transparent(colour))
setline(lw)
line(f, t, :stroke)
setcolor(colour)
circle(f, lw/2, :fill)
circle(t, lw/2, :fill)
end
function draw_spring(colour, turns, width, start)
pitch = width / (2 * turns)
pos = start
for i = 1:turns
draw_front_line(colour, pitch, pos)
pos += pitch
draw_rear_line(colour, pitch, pos)
pos += pitch
end
end
function draw_springs(springs)
background("black")
start = -sum(s.equilibrium_length for s in springs)/2
for (ix, spring) in enumerate(springs)
draw_spring(colours[ix], spring.turns, spring.current_length, start)
start += spring.current_length
end
end
hooke_F(s::Spring) = s.k * (s.equilibrium_length - s.current_length)
function frame(scene::Scene, framenumber::Int64)
draw_springs(springs)
if framenumber < 30
# stand still in initial position for the first second
return
end
# a pretty arbitrary way to translate force into something that's relative to size
scaler = maximum(max(s.equilibrium_length, s.current_length) for s in springs)
for s in springs
s.current_length += hooke_F(s) / scaler
end
end
springs = [Spring(20, 160, 100, 5), Spring(25, 120, 270, 4), Spring(30, 120, 110, 4), Spring(200, 260, 180, 8)]
@assert sum(s.equilibrium_length for s in springs) == sum(s.current_length for s in springs)
colours = distinguishable_colors(length(springs), [RGB(1,1,1), RGB(0,0,0)], dropseed=true)
mymovie = Movie(sum(s.equilibrium_length for s in springs)+120, height+50, "mymovie")
animate(mymovie, [Scene(mymovie, frame, 1:90)], creategif=true, pathname="springs.gif")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment