58 lines
1.6 KiB
Ruby
58 lines
1.6 KiB
Ruby
Shoes.app(:width => 320, :height => 200) do
|
|
@centerX = 160
|
|
@centerY = 25
|
|
@length = 150
|
|
@diameter = 15
|
|
|
|
@Theta = 45.0
|
|
@dTheta = 0.0
|
|
|
|
stroke gray
|
|
strokewidth 3
|
|
line 0,25,320,25
|
|
oval 155,20,10
|
|
|
|
stroke black
|
|
@rod = line(@centerX, @centerY, @centerX, @centerY + @length)
|
|
@bob = oval(@centerX - @diameter, @centerY + @length - @diameter, 2*@diameter)
|
|
|
|
animate(24) do |i|
|
|
recompute_angle
|
|
show_pendulum
|
|
end
|
|
|
|
def show_pendulum
|
|
angle = (90 + @Theta) * Math::PI / 180
|
|
x = @centerX + (Math.cos(angle) * @length).to_i
|
|
y = @centerY + (Math.sin(angle) * @length).to_i
|
|
|
|
@rod.remove
|
|
strokewidth 3
|
|
@rod = line(@centerX, @centerY, x, y)
|
|
@bob.move(x-@diameter, y-@diameter)
|
|
end
|
|
|
|
def recompute_angle
|
|
scaling = 3000.0 / (@length **2)
|
|
# first estimate
|
|
firstDDTheta = -Math.sin(@Theta * Math::PI / 180) * scaling
|
|
midDTheta = @dTheta + firstDDTheta
|
|
midTheta = @Theta + (@dTheta + midDTheta)/2
|
|
# second estimate
|
|
midDDTheta = -Math.sin(midTheta * Math::PI / 180) * scaling
|
|
midDTheta = @dTheta + (firstDDTheta + midDDTheta)/2
|
|
midTheta = @Theta + (@dTheta + midDTheta)/2
|
|
# again, first
|
|
midDDTheta = -Math.sin(midTheta * Math::PI / 180) * scaling
|
|
lastDTheta = midDTheta + midDDTheta
|
|
lastTheta = midTheta + (midDTheta + lastDTheta)/2
|
|
# again, second
|
|
lastDDTheta = -Math.sin(lastTheta * Math::PI/180) * scaling
|
|
lastDTheta = midDTheta + (midDDTheta + lastDDTheta)/2
|
|
lastTheta = midTheta + (midDTheta + lastDTheta)/2
|
|
# Now put the values back in our globals
|
|
@dTheta = lastDTheta
|
|
@Theta = lastTheta
|
|
end
|
|
end
|