;; SUMMARY ;;;; A demonstration of using multiple turtles to enhance the display of springs. ;; COPYRIGHT & LICENSE ;;;; Copyright (C) 2005 James P. Steiner ;;;; Some Rights Reserved. ;;;; Creative Commons Attribution-NonCommercial-ShareAlike License v. 2.0. ;;;; Visit http://creativecommons.org/licenses/by-nc-sa/2.0/ for more information. ;; globals [ tick 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 ] breeds [ springs ;; the real springs d-springs ;; the display springs d-handles ;; handles on end of 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 set tick tick + 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 cct-springs 1 [ set at-rest-length screen-edge-x * .5 set min-length spring-width set max-length screen-edge-x 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 * screen-edge-x * sin tick * 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 tick ] ] ] ;; 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 value-from my-spring [ endpoints-and-heading ] 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 display-spring-shape + "-half-a" ][ ifelse d-n = 1.0 [ set shape 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 @#$#@#$#@ GRAPHICS-WINDOW 219 47 649 498 10 10 20.0 1 10 1 1 1 0 0 0 1 CC-WINDOW 5 536 658 631 Command Center 0 BUTTON 74 10 129 43 NIL go T 1 T OBSERVER NIL NIL SWITCH 74 49 164 82 spin? spin? 1 1 -1000 SLIDER 74 125 180 158 squash squash 0.1 0.9 0.4 0.1 1 NIL SWITCH 73 451 187 484 hide-handles? hide-handles? 1 1 -1000 SLIDER 74 162 180 195 frequency frequency 0.1 5 2.0 0.1 1 NIL SWITCH 73 489 212 522 hide-spring-turtle? hide-spring-turtle? 0 1 -1000 CHOOSER 73 364 187 409 display-spring-shape display-spring-shape "curve" "line" "line-double" "line-fat" "line-multi" 0 BUTTON 9 10 64 43 reset setup NIL 1 T OBSERVER T NIL SWITCH 74 88 164 121 stretch? stretch? 1 1 -1000 SLIDER 74 211 188 244 spring-force spring-force 0 1 0.3 0.01 1 NIL SLIDER 74 248 188 281 friction friction 0 1 0.83 0.01 1 NIL SLIDER 74 285 188 318 gravity gravity 0 1 0.7 0.01 1 NIL SWITCH 98 322 188 355 gravity? gravity? 0 1 -1000 TEXTBOX 11 51 66 104 Activate automatic movement TEXTBOX 10 130 71 187 Control character of movement TEXTBOX 10 211 62 240 Physical properties\n TEXTBOX 18 363 58 392 Display controls TEXTBOX 197 10 619 38 You can click and drag the handles with the mouse to move the spring, or use automatic movement controls. SWITCH 73 413 182 446 no-twist? no-twist? 1 1 -1000 @#$#@#$#@ = WHAT IS IT? = 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. @#$#@#$#@ default true 0 Polygon -7500403 true true 150 5 40 250 150 205 260 250 curve true 0 Polygon -7500403 true true 180 225 165 300 135 300 150 210 150 75 135 0 165 0 180 45 180 150 curve-half-a true 0 Rectangle -7500403 true true 135 135 165 300 curve-half-b true 0 Rectangle -7500403 true true 135 0 165 165 d-handle true 1 Polygon -2674135 true true 0 180 60 135 135 120 135 75 105 45 105 15 135 -15 165 -15 195 15 195 45 165 75 165 120 240 135 300 180 150 150 d-handle-with-hand true 1 Polygon -2674135 true true 0 180 60 135 135 120 135 75 105 45 105 15 135 -15 165 -15 195 15 195 45 165 75 165 120 240 135 300 180 150 150 Polygon -6459832 true false 120 75 105 90 75 30 75 0 105 -45 120 -90 195 -75 180 -45 225 0 225 45 195 75 180 60 195 30 180 0 150 0 135 30 150 60 135 75 105 30 line true 1 Line -2674135 true 150 0 150 300 line-double true 1 Line -2674135 true 135 0 135 300 Line -2674135 true 165 0 165 300 line-double-half-a true 1 Line -2674135 true 135 150 135 300 Line -2674135 true 165 150 165 300 line-double-half-b true 1 Line -2674135 true 135 0 135 150 Line -2674135 true 165 0 165 150 line-fat true 1 Rectangle -2674135 true true 135 0 165 300 line-fat-half-a true 1 Rectangle -2674135 true true 135 150 165 300 line-fat-half-b true 1 Rectangle -2674135 true true 135 0 165 150 line-half-a true 1 Line -2674135 true 150 150 151 298 line-half-b true 1 Line -2674135 true 150 0 151 148 line-multi true 1 Line -2674135 true 90 15 150 15 Line -2674135 true 90 45 150 45 Line -2674135 true 90 75 150 75 Line -2674135 true 90 105 150 105 Line -2674135 true 90 135 150 135 Line -2674135 true 90 165 150 165 Line -2674135 true 90 195 150 195 Line -2674135 true 90 225 150 225 Line -2674135 true 90 255 150 255 Line -2674135 true 90 285 150 285 line-multi-half-a true 1 Line -2674135 true 90 285 150 285 Line -2674135 true 90 255 150 255 Line -2674135 true 90 225 150 225 Line -2674135 true 90 195 150 195 Line -2674135 true 90 165 150 165 line-multi-half-b true 1 Line -2674135 true 90 15 150 15 Line -2674135 true 90 45 150 45 Line -2674135 true 90 75 150 75 Line -2674135 true 90 105 150 105 Line -2674135 true 90 135 150 135 @#$#@#$#@ NetLogo 3.0.2 @#$#@#$#@ @#$#@#$#@ @#$#@#$#@ @#$#@#$#@