globals [ p1x p1y p2x p2y c1x c1y c2x c2y ep1 ep2 cp1 cp2 steps inc dragged ] breed [ links link ] breed [ cplinks cplink ] breed [ waypoints waypoint ] breed [ endpoints endpoint ] waypoints-own [ index t u t2u t3 u2t u3] endpoints-own [ newx newy next-move target ] to startup setup end to setup ca ask patches [ checkers ] set steps 10 set p1x random-xcor set p1y min-pycor + 3 set p2x random-xcor set p2y max-pycor - 3 set c1x random-xcor set c2x random-xcor set c1y random-ycor set c2y random-ycor cct-endpoints 1 [ set ep1 self set label 0 setxy p1x p1y set color blue set shape "circle" __set-line-thickness .1 set size 2 set label-color black ] set inc 1 / steps let windex 1 let prevpoint ep1 cct-waypoints steps - 1 [ set index windex set t (inc * index) set shape "circle" set color 3 + windex * 10 set u (1 - t) set u2t u * u * t set u3 u * u * u set t2u t * t * u set t3 t * t * t set-waypoint-xy set windex windex + 1 create-link prevpoint set prevpoint self set hidden? hide-dots? ] cct-endpoints 1 [ set ep2 self set label 3 setxy p2x p2y set color blue set shape "circle" __set-line-thickness .1 set size 2 create-link prevpoint set label-color black ] cct-endpoints 1 [ set cp1 self setxy c1x c1y set label 1 set size 2 set shape "circle" __create-cplink-to ep1 [ set shape "cplink" set color green set label "x" set label-color black ] set label-color black ] cct-endpoints 1 [ set cp2 self setxy c2x c2y set label 2 set shape "circle" set size 2 __create-cplink-to ep2 [ set shape "cplink" set color green set label "x" set label-color black ] set label-color black ] ask endpoints [ set newx xcor set newy ycor set next-move int timer ] display end to create-link [ agent ] __create-link-with agent [ set color (blue - 2) __set-line-thickness .5 ] end to go no-display ifelse animate? [ ;; animate? = true, so move automatically ;; every few seconds, pick a new set of endpoints, ;; and cause the control point turtles to ;; gradually slide into the new control point positions ask endpoints [ ;; is the current location too far from the desired location? if abs (xcor - newx) > .1 or abs ( ycor - newy) > .1 [ ;; interpolate between the current location ;; and the desired location set xcor .99 * xcor + .01 * newx set ycor .99 * ycor + .01 * newy ] ;; is it time to pick a new location? if timer > next-move [ if is-patch? target [ ask target [ checkers ] ] set newx random-xcor set newy random-ycor set target patch (round newx) (round newy) ask target [ set pcolor red + 30 * label-of myself] ;; next move time is 2 to 5 seconds from now set next-move int (timer + 2 + random 4) ] ] ] [ ;; animate? = false, so read mouse for user input ;; read mouse, allow dragging of endpoints with mouse if mouse-inside? [ ;; mouse is inside view ifelse mouse-down? [ ;; mouse button is down ;; record mouse pointer position let mx mouse-xcor let my mouse-ycor ;; if the variable dragged is a turtle, and an endpoint ;; then an endpoint is being dragged ;; move the endpoint to the mouse position ifelse is-turtle? dragged [ ask dragged [ if breed = endpoints [ ;;; ;; if endpoint is one of the line endpoints ;;; ;; then moving the endpoint moves the attached control point, too! ;;; if label = 3 or label = 0 ;;; [ let .my-cplink one-of __my-in-cplinks ;;; let new-end-x limitx (mx - value-from .my-cplink [ dx * size ]) ;;; let new-end-y limity (my - value-from .my-cplink [ dy * size ]) ;;; ask .my-cplink ;;; [ ask __other-end ;;; [ setxy new-end-x new-end-y ;;; ] ;;; ] ;;; ] ;; finally, move the endpoint setxy mx my ] if breed = cplinks [ let endx dx * size * .5 let endy dy * size * .5 ask __end1 [ setxy limitx value-from myself [ mx - endx ] limity value-from myself [ my - endy ] ] ask __end2 [ setxy limitx value-from myself [ mx + endx ] limity value-from myself [ my + endy ] ] ] ] ] [ ;; dragged is not an endpoint or link, so maybe ;; there is an endpoint nearby? let draggable value-from patch-at mx my [ endpoints in-radius 1 ] if not any? draggable [ ;; no, no endpoint nearby, maybe a control point link? set draggable value-from patch-at mx my [ cplinks in-radius 1 ] ] if any? draggable [ ;; there is an endpoint or link near the mouse click. ;; make that the dragged endpoint set dragged min-one-of draggable [ who ] ] ] ] [ ;; mouse is up, so end drag set dragged nobody ] ] ] let points [ "ep1" "ep2" "cp1" "cp2" ] let epx [ "p1x" "p2x" "c1x" "c2x" ] let epy [ "p1y" "p2y" "c1y" "c2y" ] (foreach points epx epy [ run (word "set " ?2 " xcor-of " ?1 "\n" "set " ?3 " ycor-of " ?1 "\n" ) ] ) ask waypoints [ set-waypoint-xy ] ;; update the display on a seperate schedule. ;; this makes using the speed slider to slow down the model ;; *also* appear to increase the resolution of the model ;; even though the only difference is that when the model ;; is moving quickly, fewer screen updates occur ;; this probably sort of simulates netlogo's own ;; screen-update scheduling every .02 [ ;; at this time, see if the value of the hide-dots? switch has changed if any? waypoints with [ hidden? != hide-dots? ] [ ask waypoints [ set hidden? hide-dots? ] ] if any? links with [ hidden? != hide-line? ] [ ask links [ set hidden? hide-line? ] ] display ] end to set-waypoint-xy set xcor p1x * u3 + 3 * c1x * u2t + 3 * c2x * t2u + p2x * t3 set ycor p1y * u3 + 3 * c1y * u2t + 3 * c2y * t2u + p2y * t3 ; set xcor p1x * u + p2x * t ; set ycor p1y * u + p2y * t end to checkers set pcolor sky + 4.5 - .5 * ((pxcor + pycor ) mod 2) end to-report limitx [ xx ] report max (list min-pxcor min (list max-pxcor xx)) end to-report limity [ yy ] report max (list min-pycor min (list max-pycor yy)) end @#$#@#$#@ GRAPHICS-WINDOW 122 10 442 351 15 15 10.0 1 18 1 1 1 0 0 0 1 -15 15 -15 15 CC-WINDOW 5 365 451 460 Command Center 0 BUTTON 9 10 64 43 NIL setup NIL 1 T OBSERVER T NIL BUTTON 10 46 65 79 NIL go T 1 T OBSERVER NIL NIL SWITCH 9 82 107 115 hide-dots? hide-dots? 0 1 -1000 SWITCH 8 156 113 189 animate? animate? 0 1 -1000 SWITCH 8 119 102 152 hide-line? hide-line? 0 1 -1000 TEXTBOX 9 199 114 340 To use: Press go. With "animate?" off, you can use the mouse to drag the endpoints, control points or connectors (at x), changing the shape of the spline. @#$#@#$#@ WHAT IS IT? ----------- A model that produces a Bézier Curve, a kind of Spline. HOW IT WORKS ------------ A spline is generated between endpoints ep1 and ep1, influenced by control points cp1 and cp2, and interpolated among "steps" waypoints. As U varies from 1 to 0, the spline is interpolated from ep1 to ep2. At each step n that is 1/steps of the way along the curve, a waypoint calculates the interpolated value of the bezier function for UsubN EXTENDING THE MODEL ------------------- Encapsulate the spline generator for general purpose use Generate other kinds of splines, such as cubic Generate splines with more than 2 control points Generate smoothly connected multiple splines Enable dragging of the link between the control- and end- points to modify the spline. Use splines to define smooth paths for agents in a simulation NETLOGO FEATURES ---------------- ==Mouse Dragging== The mouse- primitives are used to enable dragging of the endpoints, control points, and connectors. Programming different drag behaviors is interesting. For endpoints, (and control points) just changing the coordinates automatically moves the connector (cplinks). But to drag the connector, we can't just setxy on it and be done, as the endpoints will not follow. So, we have to calculate the new position of the endpoints, and move them there, they will cause the link to move automatically. As a technical note: since we are moving both endpoints, that causes TWO automatic moves of the link, and thus two view refreshes. The netlogo LINKS features are used to generate the automatically updating lines between the endpoints no-display and display are used to speed up graphics rendering every is used to speed up graphics rendering timer is used to time the changes of location the technique of iterated interpolation is used to shift the location from the current location to the new location CREDITS AND REFERENCES ---------------------- Inspired, long ago, by an old Byte magazine that I can't find anymore that talked about bezier curves (or was it Compute!'s Gazzette, or Scientific American?) http://mathworld.wolfram.com/BezierCurve.html http://mathworld.wolfram.com/Spline.html http://en.wikipedia.org/wiki/Spline_(mathematics) @#$#@#$#@ default true 0 Polygon -7500403 true true 150 5 40 250 150 205 260 250 link true 0 Line -7500403 true 150 0 150 300 link direction false 6 circle false 6 Circle -13840069 false true 15 15 268 cplink true 6 Line -13840069 true 150 30 150 0 Line -13840069 true 150 45 150 75 Line -13840069 true 150 90 150 120 Line -13840069 true 150 180 150 210 Line -13840069 true 150 225 150 255 Line -13840069 true 150 270 150 300 Line -13840069 true 150 135 150 165 dot false 0 Circle -7500403 true true 90 90 120 ex false 6 Line -13840069 true 0 0 300 300 Line -13840069 true 0 300 300 0 @#$#@#$#@ NetLogo 3.1.3 @#$#@#$#@ @#$#@#$#@ @#$#@#$#@ @#$#@#$#@