diff options
author | shyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-07-07 07:38:25 +0000 |
---|---|---|
committer | shyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-07-07 07:38:25 +0000 |
commit | 9ff1e787f915539b1980654e3d3d2013ff5c81d2 (patch) | |
tree | 8d0fc9ca5b4dbfa9885dc56862292d55091bcaac /ruby_1_8_6/ext/tk/sample/demos-en/pendulum.rb | |
parent | 441546edcfbb1b346c87b69c5f578d1a0e522e06 (diff) |
wrong commit; sorryv1_8_6_269
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/tags/v1_8_6_269@17938 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ruby_1_8_6/ext/tk/sample/demos-en/pendulum.rb')
-rw-r--r-- | ruby_1_8_6/ext/tk/sample/demos-en/pendulum.rb | 223 |
1 files changed, 0 insertions, 223 deletions
diff --git a/ruby_1_8_6/ext/tk/sample/demos-en/pendulum.rb b/ruby_1_8_6/ext/tk/sample/demos-en/pendulum.rb deleted file mode 100644 index 36bb44edec..0000000000 --- a/ruby_1_8_6/ext/tk/sample/demos-en/pendulum.rb +++ /dev/null @@ -1,223 +0,0 @@ -# -# This demonstration illustrates how Tcl/Tk can be used to construct -# simulations of physical systems. -# (called by 'widget') -# -# based on Tcl/Tk8.5a2 widget demos - -# destroy toplevel widget for this demo script -if defined?($pendulum_demo) && $pendulum_demo - $pendulum_demo.destroy - $pendulum_demo = nil -end - -# create toplevel widget -$pendulum_demo = TkToplevel.new {|w| - title("Pendulum Animation Demonstration") - iconname("pendulum") - positionWindow(w) -} - -# create label -msg = TkLabel.new($pendulum_demo) { - font $font - wraplength '4i' - justify 'left' - text 'This demonstration shows how Ruby/Tk can be used to carry out animations that are linked to simulations of physical systems. In the left canvas is a graphical representation of the physical system itself, a simple pendulum, and in the right canvas is a graph of the phase space of the system, which is a plot of the angle (relative to the vertical) against the angular velocity. The pendulum bob may be repositioned by clicking and dragging anywhere on the left canvas.' -} -msg.pack('side'=>'top') - -# create frame -TkFrame.new($pendulum_demo) {|frame| - TkButton.new(frame) { - text 'Dismiss' - command proc{ - tmppath = $pendulum_demo - $pendulum_demo = nil - tmppath.destroy - } - }.pack('side'=>'left', 'expand'=>'yes') - - TkButton.new(frame) { - text 'See Code' - command proc{showCode 'pendulum'} - }.pack('side'=>'left', 'expand'=>'yes') - -}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m') - -# animated wave -class PendulumAnimationDemo - def initialize(frame) - # Create some structural widgets - pane = TkPanedWindow.new(frame).pack(:fill=>:both, :expand=>true) - pane.add(@lf1 = TkLabelFrame.new(pane, :text=>'Pendulum Simulation')) - pane.add(@lf2 = TkLabelFrame.new(pane, :text=>'Phase Space')) - - # Create the canvas containing the graphical representation of the - # simulated system. - @c = TkCanvas.new(@lf1, :width=>320, :height=>200, :background=>'white', - :borderwidth=>2, :relief=>:sunken) - TkcText.new(@c, 5, 5, :anchor=>:nw, - :text=>'Click to Adjust Bob Start Position') - # Coordinates of these items don't matter; they will be set properly below - @plate = TkcLine.new(@c, 0, 25, 320, 25, :width=>2, :fill=>'grey50') - @rod = TkcLine.new(@c, 1, 1, 1, 1, :width=>3, :fill=>'black') - @bob = TkcOval.new(@c, 1, 1, 2, 2, - :width=>3, :fill=>'yellow', :outline=>'black') - TkcOval.new(@c, 155, 20, 165, 30, :fill=>'grey50', :outline=>'') - - # pack - @c.pack(:fill=>:both, :expand=>true) - - # Create the canvas containing the phase space graph; this consists of - # a line that gets gradually paler as it ages, which is an extremely - # effective visual trick. - @k = TkCanvas.new(@lf2, :width=>320, :height=>200, :background=>'white', - :borderwidth=>2, :relief=>:sunken) - @y_axis = TkcLine.new(@k, 160, 200, 160, 0, :fill=>'grey75', :arrow=>:last) - @x_axis = TkcLine.new(@k, 0, 100, 320, 100, :fill=>'grey75', :arrow=>:last) - - @graph = {} - 90.step(0, -10){|i| - # Coordinates of these items don't matter; - # they will be set properly below - @graph[i] = TkcLine.new(@k, 0, 0, 1, 1, :smooth=>true, :fill=>"grey#{i}") - } - - # labels - @label_theta = TkcText.new(@k, 0, 0, :anchor=>:ne, - :text=>'q', :font=>'Symbol 8') - @label_dtheta = TkcText.new(@k, 0, 0, :anchor=>:ne, - :text=>'dq', :font=>'Symbol 8') - - # pack - @k.pack(:fill=>:both, :expand=>true) - - # Initialize some variables - @points = [] - @theta = 45.0 - @dTheta = 0.0 - @length = 150 - - # init display - showPendulum - - # animation loop - @timer = TkTimer.new(15){ repeat } - - # binding - @c.bindtags_unshift(btag = TkBindTag.new) - btag.bind('Destroy'){ @timer.stop } - btag.bind('1', proc{|x, y| @timer.stop; showPendulum(x, y)}, '%x %y') - btag.bind('B1-Motion', proc{|x, y| showPendulum(x, y)}, '%x %y') - btag.bind('ButtonRelease-1', - proc{|x, y| showPendulum(x, y); @timer.start }, '%x %y') - - btag.bind('Configure', proc{|w| @plate.coords(0, 25, w, 25)}, '%w') - - @k.bind('Configure', proc{|h, w| - @psh = h/2; - @psw = w/2 - @x_axis.coords(2, @psh, w-2, @psh) - @y_axis.coords(@psw, h-2, @psw, 2) - @label_theta.coords(@psw-4, 6) - @label_dtheta.coords(w-6, @psh+4) - }, '%h %w') - - # animation start - @timer.start(500) - end - - # This procedure makes the pendulum appear at the correct place on the - # canvas. If the additional arguments x, y are passed instead of computing - # the position of the pendulum from the length of the pendulum rod and its - # angle, the length and angle are computed in reverse from the given - # location (which is taken to be the centre of the pendulum bob.) - def showPendulum(x=nil, y=nil) - if x && y && (x != 160 || y != 25) - @dTheta = 0.0 - x2 = x - 160 - y2 = y - 25 - @length = Math.hypot(x2, y2) - @theta = Math.atan2(x2,y2)*180/Math::PI - else - angle = @theta*Math::PI/180 - x = 160 + @length*Math.sin(angle) - y = 25 + @length*Math.cos(angle) - end - - @rod.coords(160, 25, x, y) - @bob.coords(x-15, y-15, x+15, y+15) - end - - # Update the phase-space graph according to the current angle and the - # rate at which the angle is changing (the first derivative with - # respect to time.) - def showPhase - @points << @theta + @psw << -20*@dTheta + @psh - if @points.length > 100 - @points = @points[-100..-1] - end - (0...100).step(10){|i| - first = - i - last = 11 - i - last = -1 if last >= 0 - next if first > last - lst = @points[first..last] - @graph[i].coords(lst) if lst && lst.length >= 4 - } - end - - # This procedure is the "business" part of the simulation that does - # simple numerical integration of the formula for a simple rotational - # pendulum. - def recomputeAngle - scaling = 3000.0/@length/@length - - # To estimate the integration accurately, we really need to - # compute the end-point of our time-step. But to do *that*, we - # need to estimate the integration accurately! So we try this - # technique, which is inaccurate, but better than doing it in a - # single step. What we really want is bound up in the - # differential equation: - # .. - sin theta - # theta + theta = ----------- - # length - # But my math skills are not good enough to solve this! - - # 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 - # Now we do a double-estimate approach for getting the final value - # first estimate - midDDTheta = -Math.sin(midTheta * Math::PI/180) * scaling - lastDTheta = midDTheta + midDDTheta - lastTheta = midTheta + (midDTheta+ lastDTheta)/2 - # second estimate - 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 - - # This method ties together the simulation engine and the graphical - # display code that visualizes it. - def repeat - # Simulate - recomputeAngle - - # Update the display - showPendulum - showPhase - end -end - -# Start the animation processing -PendulumAnimationDemo.new($pendulum_demo) |