NetLogo version NetLogo 4.1beta1
Running with NetLogoLite.jar version 411.
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
View or download the complete model file (to download: right-click, save-link-as):
-- Download animated-spring_2009 --