概要
Boids 2.2では、分離(Separation)に加えて「結合(Cohesion)」のルールを導入する。結合行動の考え方は、ここでは以下の通りとした。
- 前方視角内に個体が存在する場合、それらの重心位置を求める
- 進行方向を、重心の方へ向けて少し変更する
結合のアルゴリズム
重心の算出
次図において、進行方向に直角な直線hより前方側の個体が存在する場合、それらの重心位置gを計算する。
なお、視野角の前方判定はベクトルの前後判定によって行っている。
進路変更
先の図のように、自身の進行方向に対する群の重心の位置によって、以下の手順で進路を変更する。
- 重心位置が自身の進行方向に対して左右どちら側にあるかを判定
- 重心位置がが進行方向より右側にあるなら右へ、左側にあるなら左へ方向を少し変化させる。
これらの考え方はBoids 2.1の分離行動における回避動作と同じ。
コード内容
初期パラメータ定義
HTMLで定義する初期パラメータに、結合に関する以下の変数を追加する。
- 結合の進行方向の変化(
BD22_COHESION_ANGLE
)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<script> //<![CDATA[ BD22_V_MAX = 100; BD22_CREATURE_SIZE = 10; BD22_WALL_DETECTION_LENGTH = 100; BD22_WALL_REPULSION_PARAM = 16; BD22_VIEW_FIELD_LENGTH = 50; BD22_SEPARATION_ANGLE = 10 * Math.PI / 180; // Boids 2.2で追加:結合行動の速度の向きを変更する角 BD22_COHESION_ANGLE = 5 * Math.PI / 180; BD22_INTERVAL_SEC = 0.05; //]]> </script> |
クラス変数
初期パラメータの保存のため、Creature
クラスのクラス変数を追加する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class Creature extends MovingAgent # private staticなクラス・プロパティ # 最大速度 @_vMax: 100 # 描画の基本となるサイズ @_drawSize: 8 # 壁の衝突回避を認識する距離 @_wallDetectionLength: 100 # 反発力パラメータ @_wallRepulsionParam: 4 # 視野の長さ(奥行) @_viewFieldLength: 100 # 分離行動の回避角 @_separationAngle: 0 # 結合行動の回避角 @_cohesionAngle: 0 |
パラメータのセッター
Controler
クラスに、Creature
クラス変数へのセッターを定義する。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class Controler ..... # 定数として扱うクラス変数を設定するメソッド群 setVMax: (vMax) -> Creature._vMax = vMax setCreatureSize: (size) -> Creature._drawSize = size setWallDetectionLength: (pix) -> Creature._wallDetectionLength = pix setWallRepulsionParam: (param) -> Creature._wallRepulsionParam = param setViewFieldLength: (length) -> Creature._viewFieldLength = length setSeparationAngle: (angle) -> Creature._separationAngle = angle setCohesionAngle: (angle) -> Creature._cohesionAngle = angle setIntervalSec: (@interval_sec) -> |
パラメータのセット
HTMLで定義されたパラメータをControler
オブジェクトのセッターによってセットする。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# スクリプトが読み込まれた時の実行部分 jQuery ($) -> # Controlerを作成し、canvasオブジェクトを渡す canvas = $("#Boids22_canvas")[0] controler = new Boids22.Controler(canvas) # 固定パラメータのセット # パラメータの値は、Javascript形式でHTMLに埋め込まれている想定 controler.setVMax(BD22_V_MAX) controler.setCreatureSize(BD22_CREATURE_SIZE) controler.setWallDetectionLength(BD22_WALL_DETECTION_LENGTH) controler.setWallRepulsionParam(BD22_WALL_REPULSION_PARAM) controler.setViewFieldLength(BD22_VIEW_FIELD_LENGTH) controler.setSeparationAngle(BD22_SEPARATION_ANGLE) controler.setCohesionAngle(BD22_COHESION_ANGLE) controler.setIntervalSec(BD22_INTERVAL_SEC) ..... |
Ceatureクラスの変更 – cohesion()メソッドの追加
Creature
クラスのmove()
メソッドがcohesion()
メソッドを呼び出すようにする。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class Creature extends MovingAgent ..... move: (interval_sec) -> # 壁を避ける @wallAvoidance() # 分離行動(separation) @separation() # 結合行動(cohesion) @cohesion() ..... |
coheion()
メソッドを新たに定義する。
- 速度の方向を変化させる回転行列のcos、sinに対応したローカル変数
cs
、sn
を定義している - 重心位置への参照が
clusterCenter
プロパティに保存されるが、視野内に個体が存在しないときはnullとなる - 速度の回転方向は、右がマイナス方向、左がプラス方向となることに注意
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# Boids2.2 # 結合行動(cohesion) # 前方視角180度以内の全個体の重心に向かって速度を少し変更する cohesion: -> # 群のうち認識した個体の数とそのグループの重心 n = 0 clusterCenter = null # 結合行動の方向転換計算用cos/sin cs = Math.cos(Creature._cohesionAngle) sn = Math.sin(Creature._cohesionAngle) # 自分以外の群のすべての個体についてサーチ for other in @cluster.creatures if other != this # 相手が自身の前方にいるなら、その位置を考慮 if other.isInFrontOf(this) n++ if clusterCenter? clusterCenter.plusEq(other.pos) else clusterCenter = new Vector(other.pos.x, other.pos.y) # 前方の相手が1つでも存在すれば、結合行動をとる if clusterCenter? clusterCenter.divEq(n) # 重心が自分の右にあれば左に、自分の左にあれば右に進路を変更 if clusterCenter.isOnTheRightOf(this) vx = @v.x * cs + @v.y * sn vy = -@v.x * sn + @v.y * cs else vx = @v.x * cs - @v.y * sn vy = @v.x * sn + @v.y * cs @v.x = vx @v.y = vy |