ベクトルの内積

ベクトルの内積の表現には、要素表示を用いたものと幾何的なものの2つがある。

    $$ {\bf a} \cdot {\bf b} = a_x b_x + a_y b_y + a_z b_z = | {\bf a} | | {\bf b} | \cos \theta $$

2つの表現が等価であることを証明するのに、下図のように2つのベクトルで張られた三角形の\oberline{AB}の長さを考える。

math_vector_innerprod_1

まずベクトルの成分で計算した場合は、

    $$ \begin{align*} \overline{AB}^2 &= (a_x - b_x)^2 + (a_y - b_y)^2 + (a_z - b_z)^2 \\ &= a_x^2 + a_y^2 + a_z^2 + b_x^2 + b_y^2 + b_z^2 - 2 a_x b_x - 2 a_y b_y - 2 a_z b_z \end{align} $$

また余弦定理を用いて計算した場合は、a = | {\bf a} | , \: b = | {\bf b} |として以下のようになる。

    $$ \begin{align*} \overline{AB}^2 &= a^2 + b^2 - 2ab \cos \theta \\ &= a_x^2 + a_y^2 + a_z^2 + b_x^2 + b_y^2 + b_z^2 - 2ab \cos \theta \end{align} $$

上記2つが等しいことから、以下が得られる。

    $$ a_x b_x + a_y b_y + a_z b_z = ab \cos \theta $$

2次元の場合は、z成分を0とおいてx成分とy成分のみについて考えればよい。

 

三角関数 – 余弦定理

概要

三角形の2辺a、bとそのなす角θが与えられたとき、3つ目の辺cの長さは以下で求められる。

    $$ c^2 = a^2 + b^2 - 2ab \cos \theta $$

鋭角の場合

下図のように、辺a、bとそのなす角θが与えられているとき、3つ目の辺cとそれらとの関係を考える。

math_cosine_formula_1

辺cは上図右の直角三角形の斜辺なので、以下の式が成り立つ。

    $$ \begin{align*} c^2 &= ( b \sin \theta )^2 + ( a - b \cos \theta )^2 \\ &= b^2 \sin ^2 \theta + a^2 + b^2 \cos ^2 \theta - 2ab \cos \theta \\ &= a^2 + b^2 - 2ab \cos \theta \end{align} $$

鈍角の場合

下図のようになす角が鈍角の場合を考える。

math_cosine_formula_2

    $$ \begin{align*} c^2 &= \left[ b \sin ( \pi - \theta ) \right]^2 + \left[ b \cos ( \pi - \theta ) + a \right]^2 \\ &= (b \sin \theta )^2 + (-b \cos \theta + a)^2 \\ &= b^2 \sin ^2 \theta + b^2 \cos ^2 \theta + a^2 - 2ab \cos \theta \\ &= a^2 + b^2 - 2ab \cos \theta \end{align} $$

 

前後左右の判定

前後の判定

ある点が運動しているとき、着目する他の点が進行方向の前方にあるのか、後方にあるのかを判定したい時があるが、2次元の場合は、ベクトルの内積を使うとこの判定が簡単にできる。

以下の図で、点sがvの方向に進んでいるとき、点pが前方/後方のいずれにあるかを判定する。

math_linear_tool_ahead_behind

sを起点としたベクトルvと、sから見たpの相対的な位置ベクトルの内積を考えると、

    $$ {\bf v} \cdot ( {\bf p} - {\bf s} ) = | {\bf v} | | {\bf p} - {\bf s} | \cos \theta $$

上式で0≤θ≤90度の範囲であればpはsの前方にあり、このときcosθ≥0。また90度<θ≤180度の範囲ならpはsの後方にあり、cosθ<0となる。
内積を計算する角は、ベクトルvとpのなす角なので、pがsの左右どちらにあるかは問わない。

以上のことから、進行方向のベクトルvと、自身から見た相対的な着目点の位置ベクトルの内積が正なら着目点は前方に、負なら後方にあることになる(ゼロならば真横)。

    $$ {\bf v} \cdot ( {\bf p} - {\bf s} ) \left\{ \begin{align*} &> 0 \: \rightarrow \: {\rm front} \\ &= 0 \: \rightarrow \: {\rm side} \\ &< 0 \: \rightarrow \: {\rm behind} \end{align} \right. $$

左右の判定

方向ベクトルvを90度回転させた上で上記の前後判定を行うことで左右判定が可能になる。

ベクトルを90度回転させる方法はこちら

右へ回転させたベクトルに対して前方なら元の方向ベクトルの右、後方なら元の方向ベクトルの左と判定できる。

 

2つのベクトルが平行かどうか確かめる

2次元の場合

2次元の場合、2つのベクトルが平行かどうかを確かめるには、いずれか一方を90度回転させて、それが他のベクトルと直角であるかどうかを確かめるとよい(→ベクトルを90度回転させる方法)。

以下の2つのベクトルが平行かどうかを確認するには、

    $$ \begin{align*} {\boldsymbol u} = (u_x , u_y) \\ {\boldsymbol v} = (v_x , v_y) \end{align} $$

たとえば{\boldsymbol v}を90度回転させて内積がゼロかどうかを確認する。

    $$ (u_x , u_y) \cdot (v_y , -v_x) = 0? $$

なお、この式は、2つのベクトルの外積のx-y平面に垂直な成分(z成分)を計算していることになる。

    $$ {\boldsymbol u} \times {\boldsymbol v} = \left| \begin{array}{ccc} {\boldsymbol i} & {\boldsymbol j} & {\boldsymbol k} \\ u_x & u_y & u_z \\ v_x & v_y & v_z \end{array} \right| = (u_y v_z - u_z v_y , u_z v_x - u_x v_z , u_x v_y - u_y v_x) $$

この2次元の2つのベクトルの場合、外積の絶対値はz成分の大きさにほかならず、その値は\sin \thetaに対応することから、この値がゼロの場合は\theta = 0すなわち平行を意味する。

なお数値計算上は、内積値の絶対値がある小さな値より小さいかどうかを判定することになる。

一般的な方法

2つのベクトルが平行な時、そのなす角がゼロとなることから以下が成り立つ。

(1)    \begin{equation*} | {\boldsymbol a} \cdot {\boldsymbol b | = | {\boldsymbol a} | \cdot | {\boldsymbol b} | \cos \theta = | {\boldsymbol a} | \cdot | {\boldsymbol b} | \end{equation*}

この等式についても、小さな値との比較で判定する。

 

直角なベクトルを作り出す

下図のように互いに直交する2つのベクトルを考える。

math_linear_tool_1

これらのベクトルが直角であるためには、内積がゼロとなればよい。

    $$ {\bf v} \cdot {\bf u} = | {\bf v} | | {\bf u} | cos \frac{\pi}{2} = 0 $$

成分表示すれば

    $$ {\bf v} \cdot {\bf u} = v_x u_x + v_y u_y = 0 $$

これを満足する最もわかりやすいベクトル{\bf u}は、{\bf v}の要素を入れ替えて、何れか片方をマイナスとしたもの。

    $$ {\bf u} = (v_y , -v_x) \ {\rm or} \ (-v_y , v_x) $$

ここで要素を入れ替えた後のy成分をマイナスとしたベクトルは、元のベクトルを90度右に回転させたもので、x成分をマイナスとしたベクトルは、元のベクトルを90度左に回転させたもの。

math_linear_tool_right_angle2

これは回転行列を使って確かめることもできる。ただし以下の式で、+は左回り、-は右回りの回転であることに注意。

    $$ \left[ \begin{array}{rr} \cos \left( \pm \frac{\pi}{2} \right) & -\sin \left( \pm \frac{\pi}{2} \right)\\ \sin \left( \pm \frac{\pi}{2} \right) & \cos \left( \pm \frac{\pi}{2} \right) \end{array} \right] \left[ \begin{array}{c} v_x & v_y \end{array} \right] = \left[ \begin{array}{rr} 0 & \mp 1 \\ \pm 1 & 0 \end{array} \right] \left[ \begin{array}{c} v_x & v_y \end{array} \right] = \left[ \begin{array}{c} \mp v_y & \pm v_x \end{array} \right] $$

 

 

WP QuickLaTex – 数式の記述

概要

WordPressで整った数式を表示したいとき、MS-Officeの数式エディタの表示を画像として張り付けることを考えたが、探してみると”MathJax-LaTeX”というプラグインがよく紹介されていた。LaTexの書式で書いた数式が整形されて画像として張り付けられるらしい。

MathJax-LaTexはプラグインをインストール後、記事の冒頭にショートコード[mathjax]を書き、そのページ内でLaTexの記述が可能になという手軽なものなので、一度導入して試してみた。

ところが、ショートコードを入れたると$$マークや$マークが数式整形のための記号として認識されてしまう。たとえばjQueryに関する記事中やスクリプトコードで$マークを使うとややこしいことになる。また数式をインラインで書けないとか、テキストモードで複数行にわたる数式を書けないとか、いろいろ制約があるようだ。

そこでほかにもプラグインはないかと探して、以下のサイトに辿り着いた。

WordPress の数式整形プラグイン

WP QuickLaTex“というプラグインがあるそうで、試しにインストールしてみたところ悪くない。

導入手順

  1. プラグイン”WP QuickLaTex”をインストールし、有効化
  2. QuickLaTexの設定でインライン記述の$…$を無効化
  3. 数式を表示したい記事に以下のショートコードを書く(これにより、latexの$$記号が有効化される)

    あるいは、ショートコードなしで記事中でのショートコードで囲んだ部分はQuickLaTexの認識対象になる。
  4. LaTex形式で数式を記述

インラインスタイル

インラインスタイル(a=1のような書き方)の場合は、以下のようにショートコードで囲む。

この機能は、冒頭にショートコードを書かなくても使える。

ディスプレイスタイル

式を別段落で表示させるディスプレイスタイルの書き方には、以下の2つの方法がある。

latexpageショートコードを書く場合

この場合、ショートコード以前の$$マークは無視されるが、ショートコードを書くと記事中の$$マークはQuickLaTexが数式解釈に使う。

latexpageショートコードを書かない場合

ディスプレイスタイルでは、上記いずれの書き方でも、テキストモードで改行して複数行にわたって記述可能。

結局現在は、ディスプレイスタイルも単に[latex]...[/latex]記号のみで書いている。

 

注意点

  • $マークを設定で無効化した場合ショートコード以降の記事の中に直接$マークは書ける
  • latexpageショートコード書くと記事中のの$$マークが数式解釈に使われる
  • 改行文字(\\)は機能しないが、\begin{align}~\end{align}\begin{array}{...}\end[array]で括ると改行される
  • 以下のケースではうまく表示されない
    • ドルマーク2つで数式を書いた直後の行が<pre></pre>の場合、表示されない

記述例

WP QuickLaTexでLaTex形式の記述がどのように表示されるか列挙する。

記号

文字

{\rm }で斜体を通常書体に、{bf }と\mathbf{}は同じで太字、{\boldmath }は機能しない。いずれもギリシャ文字(小文字)には効かない。

     \begin{align*} &abcABC \alpha \beta \gamma \\ &{\rm abcABC \alpha \beta \gamma} \\ &{\bf abcABC \alpha \beta \gamma} \\ &\mathbf{abcABC \alpha \beta \gamma} \\ &{\boldmath abcABC \alpha$ \beta \gamma} \end{align*}

その後、\boldsymbolでアルファベットの大文字・小文字、ギリシャ文字を斜体太字にできることがわかった。

     \begin{gather*} \boldsymbol{abcABC \alpha \beta \gamma} \end{gather}

等号・不等号

    $$ \begin{align} &a = 1 \\ &a \neq 2 \\ &a \leq 2 , \: a \leqq 2 \\ &a \geq 0 . \: a \geqq 0 \\ &a \sim 1.1 , \: a \simeq 1.1 , \: a \approx 1.1 , \:a \fallingdotseq 1.1 \end{align} $$

加減乗除

普通の記号

    $$a + b \times c \div d$$

分数

分数の記述は\fracで(分子・分母で\fracを使うと小さくなるので、元のままのサイズにしたいときは\dfracを使う

\frac{\frac{1}{2} + \frac{1}{2}}{\dfrac{1}{3} + \dfrac{1}{3}}

括弧

分数などに対して背の高い括弧を使うときは、\left(、\right)などを使う。

    $$ \left( \frac{1}{2} + \frac{1}{3} \right) \times 6 = 5 $$

ドット表記

    $$z = x \cdot y$$

プラス/マイナス

    $$ \begin{align} a \pm b \\ a \mp b \end{align} $$

多項省略・ドット表記

    $$ \begin{align} S &= 1 + 2 + \cdots + 100 \\ S &= 1 + 2 + \ldots + 100 \\ &\vdots \\ &\ddots \end{align} $$

矢印

    $$ \begin{align} &\leftarrow \: \Leftarrow \: \longleftarrow \: \Longleftarrow \\ &\rightarrow\ \: \Rightarrow \: \longrightarrow \: \Longrightarrow \\ &\leftrightarrow \: \Leftrightarrow \: \longleftrightarrow \: \Longleftrightarrow \\ &\uparrow \: \Uparrow \: \downarrow \: \Downarrow \\ &\nearrow \; \searrow \; \swarrow \: \nwarrow \end{align} $$

    $$\angle R = 90^\circ$$

基本形

latexショートコードだけで囲むと、数式が左詰めになり、式番号なしで数式が表示される。

     \begin{equation*} z = x + y \end{equation*}

equation環境では、数式がセンタリングされ、式番号が付けられる。

     \begin{equation*} z = x + y \end{equation}

複数行の数式

eqnarray環境では、複数式を一つにまとめて扱える。

     \begin{eqnarray*} (a + b)^2 &=& a(a + b) + b(a + b) \\ &=& a^2 + b^2 + 2ab \\ (a + b)(a - b) &=& a(a - b) + b(a - b) \\ &=& a^2 - b^2 \end{eqnarray}

  • 改行位置に”\\”を記述
  • 等号などで縦位置を揃えたいときは、’&’で囲む

方程式の左を中括弧で囲いたい場合、\left\{とするが、eqnarray環境ではうまくいかない。array環境を使えばよいが、若干の注意点がある。

  • 全体をequation環境で囲う(行番号が不要の場合にはequation*)
  • 中括弧の場合は\{とエスケープする
  • 右側の括弧を省略する場合は\right.

     \begin{equation*} \left\{ \begin{array}{lll} x + y & = & c \\ x ^2 + y^2 & = & r^2 \right. \end{array} \end{equation}

単に中央ぞろえで複数行の式を書きたい場合はgather環境が手軽。式番号は自動でつけてくれる(以下の例ではgather*として式番号を抑止している)。

     \begin{gather*} a x^2 + bx + c = 0 \\ a \left( x + \frac{b}{2a} \right) ^2 - \frac{b^2}{4a} + c = 0\\ x + \frac{b}{2a} = \pm \sqrt{\frac{1}{a} \frac{b^2 - 4ac}{4a}} \\ x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a} \end{gather}

式中の任意の位置でそろえるにはalign環境と&記号を使う。たとえば全体をセンタリングしながらその中で式を左揃えにしたい場合、全ての式の先頭に&記号を置けばけばよい(もちろん、式ごとの揃える位置を変えることもできる)。

     \begin{align*} & x^2 + y^2 = r^2 \\ & x = r \cos \theta , y = r \sin \theta \\ & r^2 \cos ^2 \theta + r^2 \sin ^2 \theta = r^2 \end{align}

スペース

1文字、2文字分のスペース(quad, qquad)

\quad x \quad y
\qquad x \qquad y

任意長のスペース(hspace)

\hspace{12pt} x \hspace{12pt} y
\hspace{1pc} x \hspace{1pc} y
\hspace{12mm} x \hspace{12mm} y
\hspace{1.2cm} x \hspace{1.2cm} y

短いスペース

\! x \! y
\, x \, y
\: x \: y
\; x \; y

\!は負のスペースで、後ろの文字を前へ詰める。

A \! \! \! B(AとBの間に\!が4つ)

任意の文字分のスペース

\phantom{} 1+1\phantom{-}1

分数・括弧

    $$ \left| \frac{c+d}{a+b} \right| ^2 = \left( \frac{c+d}{a+d} \right) ^2 = \left\{ \frac{c+d}{a+d} \right\} ^2 $$

平方根・n乗根

    $$ \begin{align} &l = \sqrt{x^2 + y^2} \\ &\sqrt[n]{x} \end{align} $$

\sqrtのn乗根のnは”[n]”と大括弧で、数値xは”{x}”と中括弧で書いている点に注意。

指数表現・添字表現

    $$z_i^n = x_i^n + y_i^n$$

関数

三角関数

    $$ \begin{align} &\sin x , \cos x , \tan x \\ &\sec x , \csc x , \cot x \\ &\arcsin x , \arccos x , \arctan x \end{align} $$

対数

    $$\log_2 x ,\: \log x ,\: \ln x$$

総和・総積

    $$ \begin{align} &S = \sum_{n=1}^{10} n \\ &P = \prod_{m=1}^{10} m \end{align} $$

順列・組み合わせ

順列・組み合わせのように、記号の前にプレフィックスが付く場合は、ダミーに対してサフィックスを付ける。

     \begin{align*} {}_n P_k \quad {}_n C_k \end{align}

組み合わせを二項係数の形で書く場合は\binomを使う。使い方は\fracと同じで、分数などの中で小さくなるのを避ける場合には\dbinomを使う。

     \begin{align*} \binom nk \quad \binom {n-k}k \quad \frac{\binom{n-k}k}{\dbinom k{k-r}} \end{align}

ベクトル・行列

ベクトル

列ベクトルはarray環境でn行1列とする。{c}は各要素を中央ぞろえで、左揃えならl、右揃えならr。

    $$\vec{a} =  (a_1, \cdots , a_n)$$

    $${\bf a} = \left( \begin{array}{c} a_1\\ \vdots\\ a_n \end{array} \right)$$

行列

行列はarray環境で

    $$ {\bf A} = \left[ \begin{array}{cccc} a_{11} & a_{12} & \cdots & a_{1n}\\ a_{21} & a_{22} & \cdots & a_{2n}\\ \vdots & \vdots & \ddots & \vdots\\ a_{n1} & a_{n2} & \cdots & a_{nn} \end{array} \right]$$

ベクトル・行列の太字表記

QuickLatexでベクトル・行列を太字で表記する方法。

    $$ \boldsymbol{Ax} = \lambda \boldsymbol{x} $$

ノルム・垂直・平行

     \begin{gather*} \| \boldsymbol{a} \| \\ \boldsymbol{a} \perp \boldsymbol{b} \\ \boldsymbol{a} \parallel \boldsymbol{b} \end{gather}

行列の転置

二通りの転置行列の記述方法。

 

     \begin{gather*} {}^t \boldsymbol{A} \\ \boldsymbol{A} ^{\rm T} \end{gather}

微分・積分

    $$ \frac{dy}{dx} = f'(x) $$

 

    $$ \Delta f = \nabla^2 f = \frac{\partial^2 f}{\partial x^2} + \frac{\partial^2 f}{\partial y^2} $$

    $$ \int_a^b f(x) dx $$

上括弧・下括弧

    $$ \overbrace{1, 2, 3, 4,}^{\rm over} \underbrace{5, 6, 7, 8}_{\rm under} $$

筆算

簡単な筆算は、arrayブロックで\hlineを使う。

    $$ \begin{array}{rr} & 12345 \\ + & 678 \\ \hline & 13023 \end{array} $$

多項式の和になるとちょっとややこしい。

    $$ \begin{array}{rcccccc} A_n &= &a_1 &+ &\cdots &+ &a_n \\ B_n &= &b_1 &+ &\cdots &+ &b_n \\ \hline A_n + B_n &= &(a_1 + b_1) &+ &\cdots &+ &(a_n + b_n) \end{array} $$

 

CS/JS – Mathクラスメソッドの実行速度

概要

2点間の距離を比較するときに、sqrtといった関数で距離を求める汎用メソッド/関数を使うのに対して、距離の2乗のままで比較して計算スピードを上げることが考えられる。

昔の大型計算機で大きな規模の方程式を解くときなどは、計算スピードを上げるために距離の2乗のままで比較をしていたりしたが、簡単なシミュレーションやアニメーションなどで、それがどれくらい効いてくるのかがよくわからなかった。

そこで、他の関数も含めて、Mathクラスのクラスメソッドとして定義されている浮動小数点系の関数群の実行時間を計ってみた。

結果概要

加減乗除算の間では実行時間にあまり差はなく、これらを1としたときの各関数の実行時間程度は以下のようになった。

+-*/ 1
abs、sqrt、exp、log、random 1
sin、cos 2~3
tan、atan 4~5
atan2 5~6
asin、acos 6~7
pow(**) 7~8

一般的な方針

先の結果から、浮動小数点の計算を含むコードに関して、以下のようにまとめられる。

  • 距離の計算などにsqrtを気軽に使ってもよい(足し算を一つ増やす程度)
  • exp、logも気軽に使ってよい
  • 累乗計算はコストが高い
    • 距離計算などで自乗項が出てくる場合、乗算に変更した方がよい
  • 三角関数は、加減乗除の2~5倍のコスト
  • 逆三角関数は、加減乗除の5~7倍のコスト

参考

実行環境1

  • mouse製ノートPC
  • Celeron-325U/1.70GHz
  • RAM 8GB
  • Windows 10 Home(64bit)

コンソールからテストコードを実行。

ここでa = 1.1、b = -2.2で、各関数の繰り返し回数は100万回。時間の単位はミリ秒。

a+b 17 17 17
a-b 26 26 28
a*b 20 18 20
a/b 16 17 18
a**b 156 157 157
abs(a) 29 27 30
abs(b) 30 29 30
sqrt(a) 29 30 31
sin(a) 71 71 71
cos(a) 59 61 61
tan(a) 83 84 84
asin(a) 125 128 128
acos(a) 124 127 125
atan(a) 85 84 87
atan2(a) 138 140 146
exp(a) 15 17 17
log(a) 15 17 18
random(a) 26 27 27

実行環境2

  • 自作PC
  • Intel Core i5-4670/3.40GHz
  • RAM 4.00GB
a+b  9  10  9
a-b 12 11 12
a*b 7 9 7
a/b 7 7 7
a**b 72 71 72
abs(a) 11 12 17
abs(b) 12 17 12
sqrt(a) 13 13 13
sin(a) 27 25 23
cos(a) 24 25 25
tan(a) 43 43 42
asin(a) 53 53 54
acos(a) 53 50 51
atan(a) 41 41 41
atan2(a) 61 62 58
exp(a) 7 7 8
log(a) 6 7 7
random(a) 12 13 12

テストコード

 

CS/JS – Math.signが使えない話

CoffeeScriptで書いたコードが、ローカルでもネット上のWordPressでも動くことを確認したが、Android端末で動かないという事象が発生した。

同じ症状がWindowsマシンのExplorerでも起こったので、開発ツールで確認したところ、”Math.signはサポートされていない”とのこと。

調べてみると、JavaScript | MDN(Mozilla Developer Network)のMath.sign()のところでブラウザ実装状況を見ると、

  • デスクトップでは、Chrome38、FireFox(Gecko)25、Opera25はサポート、IEとSafariは未サポート
  • モバイルでは、Firefox Mobile(Gecko)25のみサポートで、あとは全滅

当分、この関数は利用できそうにないので、以下のように値を絶対値で割って取り出すのが手っ取り早い(可読性は悪くなるが)。

 

Boids 1.x – コード説明

Boids 0.5

全体構成

Boidsを構築していくために、以下のような全体構成とした。

HTML
WordPressのテキストエディタで、入力やボタン、canvasなどの必要な要素を書き込む。
外部スクリプトファイル
各バージョンのBoidsを実行するための外部スクリプトファイルを用意する。バージョンごとにパッケージ化する。

HTML

個体数をセットするためのinput要素のタイプは”number”とした。こうすることにより、ボックスの右側に値をコントロールする矢印が出たり、最小値の指定などができる。

ボタンはWordPressでonclickを使うと問題が生じるので、HTMLでは単にボタンを表示させるだけとし、リスナについてはコード側で対応する。

canvas要素は書き方によってWordPressで勝手に変更されてしまうので注意。

input要素とcanvasについては、コード側から参照するためのidを付与している。

スクリプトについては、jQueryはWordPress側で読み込まれるとのこと。外部スクリプトファイルは、</body>タグの直前あたりを想定して、WordPressのテキストモードで最後尾にscript要素を書いた。<script type="..." src="..."></script>とテキストモードで書いても、ビジュアルモードを経由すると以下のように書き換えられてしまう。

  1. 勝手にCDATAのパターンが挿入され、間に改行が入ってしまう
  2. srcとtypeの指定順序が逆になってしまう

クラス構成

クラスは以下の4つを準備

  • Boidsの活動領域となるFieldクラス
  • 個々の個体を表現するCreatureクラス
  • 複数のCreatureが集まった群を表現するClusterクラス
  • 各オブジェクトを生成し、ボタン操作に対応してアニメーションをコントロールするControlerクラス

パッケージ

異なるバージョンのBoidsを同じページで動かすため、バージョンごとのパッケージに上記4つのクラスを入れることとした。

初めのバージョンに対応したパッケージ名はboids05で、グローバルにアクセスするのはControlerオブジェクトだけとし、Boids05.Controlerを定義している。

そして最後に、このスクリプトファイルが読み込まれたときにボタンに対するリスナを登録するための処理を記述している。

各ブロックとクラスの説明

リスナ登録

jQueryの構文を用いている。WordPressでjQueryを用いる場合、”$”が別のエイリアスに定義されているらしいので、1行目のように書くとのこと。

1つ目のブロックではcanvas要素のDOMオブジェクトを取得し、controlerオブジェクトを生成して初期値をセットしている。

この段階では速度関係は必要ないが、次のステップの前にとりあえず実装したため、Controler.setVMax()メソッドを読んでいる。

2つ目のブロックでは、ボタンが押されたときの処理を記述しており、numberボックスから値を読み込み、それに基づいて個体生成の指令を出している。

Controlerクラス

ブラウザ側からの指令と、スクリプト内の各クラスとの仲立ちを一手に引き受けるクラスで、この段階では以下の機能を提供する。

constructor
canvasオブジェクトを渡してControlerオブジェクトを生成する。
constructor(canvas)
canvasオブジェクトを渡してConstructorオブジェクトを生成する。
setVMax(vMax)
ランダムに生成する速さの最大値をConstructorオブジェクトにセットする。
createCreature()
位置と速度(速さと方向)をランダムに与えて個体を生成する。
generate(population)
指定した数の個体を生成し、Clusterオブジェクトに格納する。

Fieldクラス

将来の拡張も考慮して、一つのクラスとした。現時点では単なる矩形で、上下左右の座標値をプロパティに持つ。

Clusterクラス

Creatureオブジェクトを1~複数保持する「群」のクラス。提供する機能は以下の通り。

constructor(canvas)
個体を描画するcanvasを渡してClusterオブジェクトを生成。
clearCreatures()
群の個体を空にする。
addCreature(creature)
Creatureオブジェクトを渡し、群に追加する。
draw()
群の全ての個体を描画する。実際には、保持している個体のdraw()メソッドを呼び出しているだけ。

Creatureクラス

個々のクラスを表現するクラス。このバージョンでは運動はさせないが、速度関係のプロパティや初期化は行っている。

constructor(canvas)
Fieldオブジェクトを指定してCreatureオブジェクトを生成。
setPosition(x, y)
個体が存在する座標を指定。
setVelocity(vx, vy)
速度の成分をセット。このバージョンでは必要ないが実装。
draw(context)
描画コンテキストを指定して、個体を描画する。このバージョンでは単純な円を描いている。

Boids 1.0

HTML

Boids 1.0用のボックスやボタンを用意し、外部スクリプトファイルを読み込んでいる。

このバージョンから個体の運動をさせるので、Start/Stopボタンを追加している。

パッケージとクラスの変更

パッケージ構成

パッケージについては、パッケージ名やエイリアスを変更。

また、個体の運動を追加するため、以下のメソッドを追加。

  • Creature.move(interval_sec)
  • Cluster.move()
  • Controler.setIntervalSec(interva._sec)
  • Controler.startAndStop()

Creature.move()

秒単位のフレームタイムを指定して呼び出される。

  • 各個体の速度で等速度運動
  • 壁に当たった場合は全反射

Cluster.move()

秒単位のフレームタイムを指定し、群の個体の数の分だけCreature.move()メソッドを呼び出す。

Controlerクラス

変更内容は以下の通り。

プロパティ追加
アニメーションをコントロールするプロパティとして以下を追加。

  1. 運動中かどうかを保持するisRunningフラグ
  2. 作動中のintervalタイマを保持するtimer
  3. 秒単位のフレームタイムを保持するinterval_sec
setIntervalSec(interval_sec)
アニメーションのフレームタイムをセット。
startAndStop()
Start/Stopボタンを押すごとに、作動状態と停止状態を切り替え。特にリスナにコールバック関数を無名関数で登録するときに、thisをバインドするためのファットアローを使っていることと、無名関数で引数を表示する記法に留意。

 

Boids 1.1

このバージョンでは、個体を壁にぶつかってから全反射させるのではなく、壁が近づくとともに斥力を感じるように壁を避けようとする動作を導入する。

HTML

Boids 1.0用のボックスやボタンを用意し、外部スクリプトファイルを読み込んでいる。

パッケージとクラスの変更

パッケージ構成

クラス構成は特に変わらず、パッケージ名とエイリアスを本バージョンにあったものとする。以下のバージョンでも同じ。

Creatureのクラスプロパティ

このバージョンから、速度の最大値をControlerからCreatureのクラスプロパティに変更(6行目)。

また、壁の接近を認識する距離(_detectionLength)と回避加速度計算時のパラメータ(_repulsionParam)を定義。

Creature.move

認識距離以内に壁に近づき始めると、壁からの斥力を想定した加速度を計算し、速度を変更。

加速度は重力加速度をイメージし、距離の2乗に反比例させた。

boids11_wall_avoidance

そもそもピクセル単位の計算では最小でも距離の値が”1″となるため、重力モデルでは大きな加速度が出ない。ここでは_detectionLengthを長さの基準としたが、壁との距離に応じて自然に避けるような運動をさせるためにパラメータ(_repulsionParam)を導入しなければならなかった。

なお、速度ベクトルの値のキャップを判定する際に速度成分の符号を用いているが、Math.sign()はほとんどのブラウザで使えないため、「値/絶対値」で符号を得ている。

Controlerクラス

vMaxの変更のみ。

Boids 1.2

このバージョンで、以下の点を変更している。

  1. 座標単位のプロパティ定義・計算を、独自クラスgeom2d.Vectorで書き換え
  2.  描画サイズなど各種パラメータをHTMLで設定できるようにする
    • 各種パラメータをstaticなクラス変数とする
    • HTMLでグローバルな変数としてパラメータ群を設定
    • 実行時にControlerオブジェクトのセッターでパラメータ群を設定
  3. Creatureオブジェクトの形状を自由に設定可能にする

HTML

独自クラスパッケージファイルの読み込み

本体のスクリプトファイルに先立って、独自クラスのパッケージファイル(taustation_geom2d.js)を読み込ませている。

パラメータ群の設定

HTMLのscript要素でパラメータ用のグローバル変数を定義する。これらはその後に読み込まれたスクリプトで利用される。

script要素内の変数定義はJavascriptで書くため、行末にコロン(;)をつけている。

script要素をWordPressのテキストモードで書くと、ビジュアルモードを経由したときに//<![CDATA[~改行~//]]>が挿入される。

また、Javascriptをscript要素に直接書くと、改行が除かれて一行になってしまう。

パッケージの準備とクラスの変更

Vectorクラスの利用

独自クラスgeom2d.Vectorを使って、位置・速度・加速度のコーディングを見やすくした。

各オブジェクトの生成と計算時にVectorオブジェクトを生成するnew演算子が介在するが、400個体程度の計算でもパフォーマンスの問題は見られなかった。

個体の形

これまではdraw()メソッドの中で直接円を描いていたが、今回はヘルパーメソッドdrawShape()を実装。

パラメータ設定

HTML内のスクリプト要素で定義されたグローバル変数を参照し、パラメータとしてクラス変数に格納。

この操作はControlerクラスに集約した。

変更に関係する箇所

Creatureクラスのクラス変数

@var: valの形式でクラス変数として定義。

Creatureの基本メソッド

これまでx, y, vx, vyのように個別の座標値で扱っていたプロパティを、Vectorクラスで置き換える。

 Creature.draw()

単純な円ではなく、方向を持った細長い三角形を描くように変更。

下図のように、基準点(x, y)から速度ベクトルの方向に頂点を、速度ベクトルと直角な報告に底辺を描く。ここで0 < p < 1で、これによって三角形の細長さが決まる。

boids12_shape1

ここでs_x = s(v_x / v) , \: s_y = s(v_y /v)と置くと下図のようになる。

boids12_shape3

コードは以下の通り。

Creature.move()

Vectorオブジェクトの導入に対応して書き直した。

斥力加速度計算のパラメータ(Creature._wallRepulsionParam)は()の外に出した。

Clusterクラス

変更箇所はない。

Controlerクラスのセッター

以下のメソッド群で整理。Creatureのクラス変数をセットしている。

実行部分

Controlerオブジェクトのセッター群を呼び出している。

 

CoffeeScript – Boids 1.x – 準備

Boids構築の準備

ここでは、以下のバージョンに沿って、Boidsの準備段階のコードを組み立てていく。

  1. Boids 0.5~ブラウザ上で指定した数の個体を表示させる
  2. Boids 1.0~個体を運動させる
  3. Boids 1.1~各個体が壁との衝突を避けるようにする
  4. Boids 1.2~個体の形をそれらしくする(内部的には独自クラスを導入)

Boids 0.5~個体の発生と表示

概要

まずスタートアップとして、指定された数の個体を発生・表示させるという簡単な枠組みを作る。

仕様は以下の通り。

  • numberボックスで個体数を指定
  • “GENERATE”ボタンを押すとcanvasに指定した数の個体が表示される
    • 個体の位置はその都度ランダムに設定される

デモンストレーション




コード詳細

Boids 0.5のコード説明へ

Boids 1.0~個体を動かす

概要

発生させた個体を表示させると同時に運動させる。

仕様は以下の通り

  • Numberボックスで個体数を指定
  • GENERATEボタンを押すとcanvasに指定した数の個体が表示される
    • 個体の位置はランダム
  • START/STOPボタンを押すたびに、各個体の運動と停止が切り替わる
    • 個体のスピードは一定の範囲内でランダムに設定され、スピードは変化しない
    • 壁に当たった場合は全反射する

デモンストレーション


 

コード詳細

Boids 1.0のコード説明へ

Boids 1.1~壁を避ける

概要

各個体が壁をよける動作を導入。壁からの距離に応じた斥力を想定し、それに応じた加速度を計算している。

操作方法はこれまでのものと同じ。

デモンストレーション


 

コード詳細

Boids 1.1のコード説明へ

Boids 1.2~Vectorの利用と個体の形

概要

このバージョンでは2つのことを導入している。

  • 一つは独自クラスのgeom2d.Vectorを利用していること
  • 今一つは個体の形を単純な円から任意の形とできるよう変更したこと

操作方法はこれまでのものと同じ。

デモンストレーション


 

コード詳細

Boids 1.2のコード説明へ