animated-spring_2009


Information

Created with NetLogo version NetLogo 4.1beta1
Running with NetLogoLite.jar version 411.


SUMMARY


A demonstration of the use of extra turtles for display enhancement.

HOW TO USE IT


Click |GO| (click reset first, if needed)
You can use the mouse to grab the handles to move or stretch the spring.

Controls


Automated Movement



  • spin?| turns automatic rotation on or off

  • stretch?| turns automatic expand / compress on or off

  • squash| controls how much force the automatic compression exerts

  • frequency| controls the speed of automatic movement
  • Physical Properties



  • spring-force| how much the spring resists compression or extension

  • friction| how much mechanical friction affects the spring

  • gravity| how much gravity is present

  • gravity?| turns gravity on or off
  • Display Controls



  • display-spring-shape| select a shape for the spring

  • no-twist?| the spring shapes do not change angle with stretching

  • hide-handles?| turns display of the handles on or off

  • hide-spring-turtle?| turns display of the actual spring turtle on or off
  • HOW IT WORKS


    In this demo, extra turtles are used to create the illusion that a spring is stretching.
    Usually, springs are depicted using lines. This is because NetLogo scales shapes uniformly, so only a single line will not change width as well as length. If one used a drawing of a spring, the spring shape would change length AND width when resized...it would NOT appear to stretch along one axis, as one would expect a spring to do.
    So, here we have a hidden turtle that is used to model the spring, and we overlay the spring turtle with a set of display-only turtles (that is, they are there only for display purposes, and their locations and behaviors are not part of the system being modeled). These turtles provide the illusion of a spring compressing and expanding.
    This method uses multiple turtles placed perpendicular to the line of the spring. The length of the turtles is constant, but the spacing between them and the angle of the turtles varies.
    Alternatively, the angle can remain constant, changing only the spacing. This provides an adequate illusion, with a slightly lesser processing overhead. In this case, just the density of the lines shows the degree of stretch.
    As additional eye-candy, a pair of handles, held in little hands, are also shown.

    Procedures

    NetLogo Version: NetLogo 4.1beta1

    globals
    [ d-spring-spacing ; the "constant" of the spacing of the "turns" of springs at rest
                       ; used to calculate the number of display turtles (d-springs) for a spring
      click?           ; use for robust mouse dragging
      down?
      force-heading
      force-mag
      old-shape        ; used to monitor shape changes for the demo
      spring-width
    ]
    
    breed [ springs ] ;; the entitiy that actually acts as a spring
    breed [ d-springs ] ;; used to display the animated spring shapes
    breed [ d-handles ] ;; the handles on the spring
    
    
    springs-own
    [ at-rest-length
      min-length ;; length when fully compressed
      max-length ;; length when fully stretched
      ;; at-rest-width ;; not used here... 
      ;; expanded model could use springs of different widths, using spring-width to
      ;; show relative resistance to compression/expansion?
      
      vv  ;; vector velocity ;; the speed that the end point is moving towards/away from the other endpoint
      vdv ;; vector delta velocity ;; the current change in speed
      av  ;; angular velocity
      adv ;; angular delta velocity
    ]
    
    d-springs-own
    [ d-n ;; from 0.0 to 1.0, the position of the display turtle on the spring.
      my-spring ; the "real" spring 
      min-length
      max-length
      d-turn
     ]
    
    d-handles-own
    [ side
      my-spring
    ]
    
    to startup
       setup
    end   
    
    to setup
       display
       ca
       setup-springs
       setup-d-springs
       setup-d-handles
       ask patches with [ abs pxcor > 1 ] [ set pcolor gray - 3 ]
    end
    
    to go
       every .05
       [ if not any? springs [ setup ]
         no-display
         tick-advance frequency
         ask springs
         [ display-springs  ]
         ask d-springs
         [ display-d-springs ]
         ask d-handles
         [ display-d-handles ]
       ]  
       display
    end
    
    to setup-springs
       set-default-shape springs "line"
       set d-spring-spacing .5 ;; two turns per unit
       set spring-width 2
       create-springs 1
       [ set at-rest-length max-pxcor * .5
         set min-length spring-width
         set max-length max-pxcor
         set vv 0
         set vdv 0
         set size at-rest-length
         set heading 0
         jump size * 0.5
         set color white
       ]
    end
    
    to setup-d-handles
       set-default-shape d-handles "d-handle-with-hand"
       let a-side 1
       ask springs
       [ hatch 2
         [ set breed d-handles
           set my-spring myself
           set side a-side
           set color 95 + 10 * side
           set a-side a-side * -1
         ]
       ]
       display-d-handles
    end
    
         
    
    to setup-d-springs
       ;; assumes real springs are already setup
       set-default-shape d-springs display-spring-shape
       let a-side 1
       ask springs
       [ let turn-count 13 ; int( .5 + (size / d-spring-spacing)) 
         let d-inc 1 / (turn-count + 1) 
         let d-index 0.0
         let d-tindex 1
         let d-count 0
         hatch turn-count + 2 
         [ set breed d-springs
           set my-spring myself
           set min-length [min-length] of myself
           set max-length [max-length] of myself
           set d-turn d-tindex
           set d-tindex -1 * d-tindex
           ;; ensure that final d-n = 1
           set d-count d-count + 1
           if d-count = turn-count + 2 [ set d-index 1.0 ]
           set d-n d-index
           set d-index d-index + d-inc
         ]
       ]
       display-d-springs
    end
    
    to display-springs
         ;; calculate position of spring
         ;; if the mouse is down and on the spring handle, the mouse positions the spring
         let gg ifelse-value (gravity?) [ gravity ] [ 0 ]
         let new-size size
         let new-heading heading
         let mx 0 ;; freeze mouse coordinates, save typing
         let my 0
         let hx 0 ;; handle coordinates
         let hy 0
         ;; first, see if the user has grabbed the handle with the mouse
         ifelse mouse-down? 
         [ set down? true
           set mx mouse-xcor ;; freeze mouse position and save some typing!
           set my mouse-ycor
           set hx xcor + dx * size * .5
           set hy ycor + dy * size * .5
           if click? != true and ((abs (mx - hx)) <= spring-width) and ((abs (my - hy)) <= spring-width)
           [ set click? true  set down? false ]
         ] 
         [ set click? false
           set down? false
         ]
         
         ;; if user is dragging with mouse, set new position from mouse
         if click? = true or down? = true
         [ let nh new-heading
           ifelse click? = true
           [ set new-size sqrt (mx * mx + my * my)
             set vv 0
             if new-size > max-length [ set new-size max-length ]
             if new-size < min-length
             [ set new-size min-length ]
             if mx != 0 or my != 0 
             [ set nh atan mx my ]
           ]
           [ if mx != 0 or my != 0 
             [ set nh 180 + atan mx my ]
           ]
           ifelse nh != new-heading
           [ set av friction * subtract-headings nh  new-heading
             set new-heading new-heading + .25 * subtract-headings nh new-heading
           ]
           [ set av 0 ]
         ]
         if click? != true
         [ ;; otherwise, set position using automated movement.
           let return-force (at-rest-length - size) * spring-force
           let distort-force 0
           let gravity-stretch-force (- cos new-heading) * gg
           if stretch? [ set distort-force ((.25 * max-pxcor * sin ticks * squash)) ]
           set vdv (return-force + gravity-stretch-force + distort-force) * friction
           set vv vv * .94 + vdv
           set new-size new-size + vv
           if new-size < min-length [ set new-size min-length set vv vv * -.5 ]
           if new-size > max-length [ set new-size max-length set vv vv * -.5 ]
    
           if down? != true
           [
           ;; simulate gravity by making the spring prefer to be pointing down
           let gravity-force (subtract-headings 180 new-heading ) 
           if abs gravity-force > 90 [ set gravity-force (180 * (abs gravity-force / gravity-force)) - gravity-force ]
           set gravity-force gravity-force * gg * .5
           let spin-force 0
           ; if spin? [ set spin-force subtract-headings new-heading (180 * sin tick)  ]
           ;; conserv angular momentum... (ie shortening increases ang. vel.)
           ;; how? the following is wrong
           set adv (gravity-force  + spin-force * 1 ) / (size * .5)
           ; if vdv != 0 [ set av av * (1 + vdv * .5) ]
           set av (av * friction ) + adv 
           set new-heading new-heading + av
           if spin? [ set new-heading heading + 10 * sin ticks ]
           ]
           
         ]
         ;; apply new position and size
         if size != new-size or heading != new-heading
         [ ;; jump back to origin
           jump size * -.5
           ;; apply new-size and heading
           set size new-size
           set heading new-heading
           ;; jump out to put endpoint at center
           jump size * .5 
           ;; all that jump in, jump out, stuff positions the spring to create the
           ;; illusion that the spring is stretching from the endpoint, and not from the center.
         ]
        if hidden? != hide-spring-turtle? [ set hidden? hide-spring-turtle? ]
        
    end
    
    to display-d-springs
       ;; assumes that spring(s) have been positioned and sized
       ask d-springs
       [ let my-stuff [ endpoints-and-heading ] of my-spring 
         let my-x0 item 0 my-stuff
         let my-y0 item 1 my-stuff
         let my-x1 item 2 my-stuff
         let my-y1 item 3 my-stuff
         let my-head item 4 my-stuff
         set xcor my-x0 + d-n * (my-x1 - my-x0)
         set ycor my-y0 + d-n * (my-y1 - my-y0)
         if size != .5 * spring-width + .001 [ set size .5 * spring-width + .001 ]
         ;; adding .001 above prevents NetLogo from using "pre-drawn" bit-map shapes.
         ;; there is some evidence that pre-drawn shapes (meant to speed up rendering)
         ;; may actually be rendered more slowly on some systems
         let span (max-length - min-length)
         let stretch 0 let twist 0
         if not no-twist?
         [ set stretch ( [size] of my-spring - min-length * .5) / span 
           set twist 45 * stretch * d-turn
         ] 
         set heading (90 + (my-head) + twist  )
       ]
       if old-shape != display-spring-shape
       [ ask d-springs
         [ ifelse d-n = 0.0 [ set shape (word display-spring-shape "-half-a") ][
           ifelse d-n = 1.0 [ set shape (word display-spring-shape "-half-b") ][
                              set shape display-spring-shape              ]]
         ]
         set old-shape display-spring-shape
       ]
    end      
    
    to display-d-handles
       ask d-handles
       [ if size != spring-width + .001 [ set size spring-width + .001 ]
         ;; adding .001 above prevents NetLogo from using "pre-drawn"
         ;; bit-map shapes. predrawn shapes are clipped to the patch-box edges
         ;; and for these over-size hand shapes, that is not desired.
    
         if hidden? != hide-handles? [ set hidden? hide-handles? ]
         let dist [size] of my-spring
         let head [heading] of my-spring
         set xcor [xcor] of my-spring + dist * .5 * sin head * side
         set ycor [ycor] of my-spring + dist * .5 * cos head * side
         set heading [heading] of my-spring + 90 - 90 * side
       ]
    end
    
    to-report endpoints-and-heading
       let dx-span dx * size * .5
       let dy-span dy * size * .5
       report (list (xcor - dx-span)
                    (ycor - dy-span)
                    (xcor + dx-span)
                    (ycor + dy-span)
                     heading
              )
    end
         
    
                        


    Download Link

    View or download the complete model file (to download: right-click, save-link-as):
    -- Download animated-spring_2009 --