| | |
| | |
| | |
| | |
| |
|
| | if {![info exists widgetDemo]} { |
| | error "This script should be run from the \"widget\" demo." |
| | } |
| |
|
| | package require Tk |
| |
|
| | set w .pendulum |
| | catch {destroy $w} |
| | toplevel $w |
| | wm title $w "Pendulum Animation Demonstration" |
| | wm iconname $w "pendulum" |
| | positionWindow $w |
| |
|
| | label $w.msg -font $font -wraplength 4i -justify left -text "This demonstration shows how Tcl/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." |
| | pack $w.msg |
| |
|
| | |
| | set btns [addSeeDismiss $w.buttons $w] |
| | pack $btns -side bottom -fill x |
| |
|
| | |
| | pack [panedwindow $w.p] -fill both -expand 1 |
| | $w.p add [labelframe $w.p.l1 -text "Pendulum Simulation"] |
| | $w.p add [labelframe $w.p.l2 -text "Phase Space"] |
| |
|
| | |
| | |
| | canvas $w.c -width 320 -height 200 -background white -bd 2 -relief sunken |
| | $w.c create text 5 5 -anchor nw -text "Click to Adjust Bob Start Position" |
| | |
| | $w.c create line 0 25 320 25 -tags plate -fill grey50 -width 2 |
| | $w.c create oval 155 20 165 30 -tags pivot -fill grey50 -outline {} |
| | $w.c create line 1 1 1 1 -tags rod -fill black -width 3 |
| | $w.c create oval 1 1 2 2 -tags bob -fill yellow -outline black |
| | pack $w.c -in $w.p.l1 -fill both -expand true |
| |
|
| | |
| | |
| | |
| | canvas $w.k -width 320 -height 200 -background white -bd 2 -relief sunken |
| | $w.k create line 160 200 160 0 -fill grey75 -arrow last -tags y_axis |
| | $w.k create line 0 100 320 100 -fill grey75 -arrow last -tags x_axis |
| | for {set i 90} {$i>=0} {incr i -10} { |
| | |
| | $w.k create line 0 0 1 1 -smooth true -tags graph$i -fill grey$i |
| | } |
| |
|
| | $w.k create text 0 0 -anchor ne -text "\u03b8" -tags label_theta |
| | $w.k create text 0 0 -anchor ne -text "\u03b4\u03b8" -tags label_dtheta |
| | pack $w.k -in $w.p.l2 -fill both -expand true |
| |
|
| | |
| | set points {} |
| | set Theta 45.0 |
| | set dTheta 0.0 |
| | set pi 3.1415926535897933 |
| | set length 150 |
| | set home 160 |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | proc showPendulum {canvas {at {}} {x {}} {y {}}} { |
| | global Theta dTheta pi length home |
| | if {$at eq "at" && ($x!=$home || $y!=25)} { |
| | set dTheta 0.0 |
| | set x2 [expr {$x - $home}] |
| | set y2 [expr {$y - 25}] |
| | set length [expr {hypot($x2, $y2)}] |
| | set Theta [expr {atan2($x2, $y2) * 180/$pi}] |
| | } else { |
| | set angle [expr {$Theta * $pi/180}] |
| | set x [expr {$home + $length*sin($angle)}] |
| | set y [expr {25 + $length*cos($angle)}] |
| | } |
| | $canvas coords rod $home 25 $x $y |
| | $canvas coords bob [expr {$x - 15}] [expr {$y - 15}] \ |
| | [expr {$x + 15}] [expr {$y + 15}] |
| | } |
| | showPendulum $w.c |
| |
|
| | |
| | |
| | |
| | proc showPhase {canvas} { |
| | global Theta dTheta points psw psh |
| | lappend points [expr {$Theta + $psw}] [expr {-20*$dTheta + $psh}] |
| | if {[llength $points] > 100} { |
| | set points [lrange $points end-99 end] |
| | } |
| | for {set i 0} {$i<100} {incr i 10} { |
| | set list [lrange $points end-[expr {$i-1}] end-[expr {$i-12}]] |
| | if {[llength $list] >= 4} { |
| | $canvas coords graph$i $list |
| | } |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | bind $w.c <Destroy> { |
| | after cancel $animationCallbacks(pendulum) |
| | unset animationCallbacks(pendulum) |
| | } |
| | bind $w.c <Button-1> { |
| | after cancel $animationCallbacks(pendulum) |
| | showPendulum %W at %x %y |
| | } |
| | bind $w.c <B1-Motion> { |
| | showPendulum %W at %x %y |
| | } |
| | bind $w.c <ButtonRelease-1> { |
| | showPendulum %W at %x %y |
| | set animationCallbacks(pendulum) [after 15 repeat [winfo toplevel %W]] |
| | } |
| | bind $w.c <Configure> { |
| | %W coords plate 0 25 %w 25 |
| | set home [expr {%w/2}] |
| | %W coords pivot [expr {$home - 5}] 20 [expr {$home + 5}] 30 |
| | } |
| | bind $w.k <Configure> { |
| | set psh [expr {%h/2}] |
| | set psw [expr {%w/2}] |
| | %W coords x_axis 2 $psh [expr {%w - 2}] $psh |
| | %W coords y_axis $psw [expr {%h - 2}] $psw 2 |
| | %W coords label_dtheta [expr {$psw - 4}] 6 |
| | %W coords label_theta [expr {%w - 6}] [expr {$psh + 4}] |
| | } |
| |
|
| | |
| | |
| | |
| | proc recomputeAngle {} { |
| | global Theta dTheta pi length |
| | set scaling [expr {3000.0/$length/$length}] |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | set firstDDTheta [expr {-sin($Theta * $pi/180)*$scaling}] |
| | set midDTheta [expr {$dTheta + $firstDDTheta}] |
| | set midTheta [expr {$Theta + ($dTheta + $midDTheta)/2}] |
| | |
| | set midDDTheta [expr {-sin($midTheta * $pi/180)*$scaling}] |
| | set midDTheta [expr {$dTheta + ($firstDDTheta + $midDDTheta)/2}] |
| | set midTheta [expr {$Theta + ($dTheta + $midDTheta)/2}] |
| | |
| | |
| | set midDDTheta [expr {-sin($midTheta * $pi/180)*$scaling}] |
| | set lastDTheta [expr {$midDTheta + $midDDTheta}] |
| | set lastTheta [expr {$midTheta + ($midDTheta + $lastDTheta)/2}] |
| | |
| | set lastDDTheta [expr {-sin($lastTheta * $pi/180)*$scaling}] |
| | set lastDTheta [expr {$midDTheta + ($midDDTheta + $lastDDTheta)/2}] |
| | set lastTheta [expr {$midTheta + ($midDTheta + $lastDTheta)/2}] |
| | |
| | set dTheta $lastDTheta |
| | set Theta $lastTheta |
| | } |
| |
|
| | |
| | |
| | proc repeat w { |
| | global animationCallbacks |
| |
|
| | |
| | recomputeAngle |
| |
|
| | |
| | showPendulum $w.c |
| | showPhase $w.k |
| |
|
| | |
| | set animationCallbacks(pendulum) [after 15 [list repeat $w]] |
| | } |
| | |
| | set animationCallbacks(pendulum) [after 500 [list repeat $w]] |
| |
|