102 lines
2.6 KiB
Factor
102 lines
2.6 KiB
Factor
! Copyright (C) 2008 Eduardo Cavazos.
|
|
! Copyright (C) 2011 Anton Gorenko.
|
|
! See http://factorcode.org/license.txt for BSD license.
|
|
USING: accessors arrays combinators.short-circuit kernel
|
|
locals math math.vectors random sequences ;
|
|
IN: boids.simulation
|
|
|
|
CONSTANT: width 512
|
|
CONSTANT: height 512
|
|
|
|
TUPLE: behaviour
|
|
{ weight float }
|
|
{ radius float }
|
|
{ angle-cos float } ;
|
|
|
|
TUPLE: boid
|
|
{ pos array }
|
|
{ vel array } ;
|
|
|
|
C: <boid> boid
|
|
|
|
: vsum ( vecs -- v )
|
|
{ 0.0 0.0 } [ v+ ] reduce ; inline
|
|
|
|
: vavg ( vecs -- v )
|
|
[ vsum ] [ length ] bi v/n ; inline
|
|
|
|
: in-radius? ( self other radius -- ? )
|
|
[ [ pos>> ] bi@ distance ] dip <= ; inline
|
|
|
|
: angle-between ( u v -- angle )
|
|
[ normalize ] bi@ v. ; inline
|
|
|
|
: relative-position ( self other -- v )
|
|
swap [ pos>> ] bi@ v- ; inline
|
|
|
|
:: relative-angle ( self other -- angle )
|
|
self other relative-position
|
|
self vel>> angle-between ; inline
|
|
|
|
: in-view? ( self other angle-cos -- ? )
|
|
[ relative-angle ] dip >= ; inline
|
|
|
|
:: within-neighborhood? ( self other behaviour -- ? )
|
|
self other {
|
|
[ eq? not ]
|
|
[ behaviour radius>> in-radius? ]
|
|
[ behaviour angle-cos>> in-view? ]
|
|
} 2&& ; inline
|
|
|
|
:: neighbors ( boid boids behaviour -- neighbors )
|
|
boid boids [ behaviour within-neighborhood? ] with filter ;
|
|
|
|
|
|
GENERIC: force ( neighbors boid behaviour -- force )
|
|
|
|
:: (force) ( boid boids behaviour -- force )
|
|
boid boids behaviour neighbors
|
|
[ { 0.0 0.0 } ] [ boid behaviour force ] if-empty ;
|
|
|
|
: wrap-pos ( pos -- pos )
|
|
width height [ 1 - ] bi@ 2array
|
|
[ [ + ] keep mod ] 2map ;
|
|
|
|
:: simulate ( boids behaviours dt -- boids )
|
|
boids [| boid |
|
|
boid boids behaviours
|
|
[ [ (force) ] keep weight>> v*n ] with with map vsum :> a
|
|
|
|
boid vel>> a dt v*n v+ normalize :> vel
|
|
boid pos>> vel dt v*n v+ wrap-pos :> pos
|
|
|
|
pos vel <boid>
|
|
] map ;
|
|
|
|
: random-boids ( count -- boids )
|
|
[
|
|
width height [ random ] bi@ 2array
|
|
2 [ 0 1 normal-random-float ] replicate
|
|
<boid>
|
|
] replicate ;
|
|
|
|
TUPLE: cohesion < behaviour ;
|
|
TUPLE: alignment < behaviour ;
|
|
TUPLE: separation < behaviour ;
|
|
|
|
C: <cohesion> cohesion
|
|
C: <alignment> alignment
|
|
C: <separation> separation
|
|
|
|
M: cohesion force ( neighbors boid behaviour -- force )
|
|
drop [ [ pos>> ] map vavg ] [ pos>> ] bi* v- normalize ;
|
|
|
|
M: alignment force ( neighbors boid behaviour -- force )
|
|
2drop [ vel>> ] map vsum normalize ;
|
|
|
|
M:: separation force ( neighbors boid behaviour -- force )
|
|
behaviour radius>> :> r
|
|
boid pos>> neighbors
|
|
[ pos>> v- [ normalize ] [ r v/n ] bi v- ] with map vsum ;
|
|
|