等速円運動を三角関数により位置と速度のふたつの方程式で表す

等速円運動は、三角関数で表すのがお約束です。その場合、運動の式を位置座標の動きで立てるほかに、速度ベクトルの変化で扱う考え方があります。後者を導く式がもとづくのは、数学の「微分」です。解説では先にJavaScriptコードを示し、数学の考え方は興味ある読者のためにあとでご説明します。

# 01 三角関数sinとcosの定義にもとづく式

等速円運動をアニメーションで見せたいときは、三角関数の$\sin$と$\cos$を使うのが便利です。$\sin$と$\cos$は半径1の「単位円」で定義されます。単位円の円周上の点$P$と原点$O(0, 0)$を結ぶ線分が$x$軸の正方向となす角を$\theta$としたとき、点$P$の座標は$(\cos\theta, \sin\theta)$と定められているのです(図001)。

#### 図001■単位円上の座標は原点と結ぶ線分がx軸となす角をθとするとき(cosθ, sinθ)
![Creators_MeetUp_141115_002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128949/727af56e-6e4d-33d9-3d43-5091cae861ed.png)

すると、中心座標を$(o_x, o_y)$とする半径$r$の円周上の座標$(x, y)$は、つぎの式で表されます。

```math
x = o_x + r\cos\theta \\
y = o_y + r\sin\theta
```

そこで上記の方程式にもとづいて、円運動をJavaScriptコードの関数(`rotate()`)で書いてみます。中心座標は`(centerX, centerY)`、円の半径を`angle`という変数でもちます。動かすオブジェクトが`instance`で、`x`と`y`は位置座標のプロパティです。なお、関数は一定間隔で呼出されるものとし[^1]、回す角速度を`speed`としています。

```js
function rotate() {
	angle += speed;
	instance.x = centerX + radius * Math.cos(angle);
	instance.y = centerY + radius * Math.sin(angle);
}
```

[^1]: 関数を`window.setTimeout()`や`window.setInterval()`メソッドから呼出すか、CreateJS(EaselJS)なら`Ticker.tick`イベントのリスナーに定めればよいでしょう。

#02 速度ベクトルから式を導く
同じ三角関数の$\sin$と$\cos$を使いつつ、また違った方程式で等速円運動を表すことができます。運動の速度のベクトル$(x', y')$を、位置ベクトル(座標)に加えるのです。円運動の速度の$(x', y')$成分は、つぎの式で表されます。なお、経過時間を$t$とし、一定の角速度は$\omega$(オメガ)としています。

```math
x' = -r\omega\sin(\omega t) \\
y' = r\omega\cos(\omega t)
```
前掲JavaScriptコードと同じ等速円運動を、この方程式で書き替えたのがつぎの計算式です。方程式で導かれる速度$(x', y')$は、位置座標$(x, y)$に加えます。そのため、初めに位置決めしてしまえば、円の中心座標$(o_x, o_y)$は使わずに済むのです。ふたつの方程式の円運動が同じ動きになることは、以下に掲げたサンプル001のCodePenのコードから確かめられるでしょう。

```js
instance.x = centerX + radius;
instance.y = centerY;
function rotate() {
	angle += speed;
	instance.x -= radius * speed * Math.sin(angle);
	instance.y += radius * speed * Math.cos(angle);
}
```

#### サンプル001■CreateJS 1.0.0: Equations of the uniform circular motion
<p class="codepen" data-height="380" data-theme-id="0" data-default-tab="js,result" data-user="FumioNonaka" data-slug-hash="poowPRj" style="height: 380px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="poowPRj">
  <span>See the Pen <a href="https://codepen.io/FumioNonaka/pen/poowPRj">
  poowPRj</a> by Fumio Nonaka (<a href="https://codepen.io/FumioNonaka">@FumioNonaka</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>


# 03 位置と速度の数学的な関係
前述項01の方程式は、円運動の位置座標を表しました。それに対して、速度を一定間隔で位置座標に加えることにより計算したのが前項02の方程式です。これらふたつの方程式の関係について、興味ある読者のために数学的な説明を加えます。

まず、単純な等速直線運動で考えます。初めの位置を$(x_0, y_0)$として、時間$t$が経過した位置座標$(x, y)$を求めたのが、つぎの方程式です。$a$は時間あたりに$x$座標が動く大きさ、$b$は直線の傾きを示す係数です(「[直線の式(方程式)](http://www.fumiononaka.com/TechNotes/Flash/FN0603001.html)」参照)。

```math
x = at + x_0 \\
y = bx + y_0 = abt + bx_0 + y_0
```

けれど、等速直線運動は位置座標で扱うと煩わしくなりがちです。ほとんどの場合、速度を位置座標に加えて、アニメーションさせます。一般に、位置の方程式を時間($t$)で微分すれば、速度の方程式が導かれます。上記の方程式を$t$で微分すると、$xy$方向ともに定数になります。

```math
x' = a \\
y' = ab
```

> つぎのような$n$次関数$f(x)$を考えます。なお、各項の係数$k_0～k_n$は定数とします。

> $f(x) = k_nx^n + k_{n-1}x^{n-1}+ … + k_2x^2 + k_1x + k_0$

> すると、この関数を微分して得られる関数(「導関数」と呼ばれます)$f'(x)$は、つぎのとおりです(Wikibooks「高等学校数学II 微分・積分の考え」1「[微分・積分の考え](https://ja.wikibooks.org/wiki/%E9%AB%98%E7%AD%89%E5%AD%A6%E6%A0%A1%E6%95%B0%E5%AD%A6II/%E5%BE%AE%E5%88%86%E3%83%BB%E7%A9%8D%E5%88%86%E3%81%AE%E8%80%83%E3%81%88#%E5%BE%AE%E5%88%86%E3%83%BB%E7%A9%8D%E5%88%86%E3%81%AE%E8%80%83%E3%81%88)」参照)。

> $f'(x) = nk_nx^{n-1} + (n-1)k_{n-1}x^{n-2} + … + 2k_2x + k_1$

そして、速度の方程式は積分すると、位置の方程式になるのです(「[微分積分学の基本定理](https://ja.wikipedia.org/wiki/%E5%BE%AE%E5%88%86%E7%A9%8D%E5%88%86%E5%AD%A6%E3%81%AE%E5%9F%BA%E6%9C%AC%E5%AE%9A%E7%90%86)」)。さらに、微分・積分などというむずかしいことは考えなくて構いません。短い単位時間であれば、速度を位置に足し込んでいくだけで近似値として運動が表せるのです(「[微分の考え方を使う ー オイラー法](https://qiita.com/FumioNonaka/items/399f7f43c84a7380bb2f#%E5%BE%AE%E5%88%86%E3%81%AE%E8%80%83%E3%81%88%E6%96%B9%E3%82%92%E4%BD%BF%E3%81%86-%E3%83%BC-%E3%82%AA%E3%82%A4%E3%83%A9%E3%83%BC%E6%B3%95)」参照)。

等速直線運動がつぎのようなJavaScriptコードで定められることは、よく知られています。初めの位置は`(startX, startY)`で、関数が呼ばれるごとに水平方向に`speedX`、垂直方向には`speedY`動きます。なお、直線軌道の傾きは`speedY/speedX`となります。

```js
instance.x = startX;
instance.y = startY;
function move() {
	instance.x += speedX;
	instance.y += speedY;
}
```

等速円運動でも考え方は同じです。項01のひとつ目の方程式は、円運動の位置座標を表しています。

```math
x = o_x + r\cos\theta \\
y = o_y + r\sin\theta
```

この方程式を$\theta = \omega t$として、$t$で微分するとつぎのようになります。これがまさに、項02で示した円運動の速度の方程式なのです(Wikipedia「[等速円運動の運動方程式](https://ja.wikipedia.org/wiki/%E5%86%86%E9%81%8B%E5%8B%95#%E7%AD%89%E9%80%9F%E5%86%86%E9%81%8B%E5%8B%95%E3%81%AE%E9%81%8B%E5%8B%95%E6%96%B9%E7%A8%8B%E5%BC%8F)」参照)。

```math
x' = -r\omega\sin(\omega t) \\
y' = r\omega\cos(\omega t)
```

> 三角関数の$\sin$と$\cos$について、角度$\theta$で微分した導関数はつぎのとおりです(Wikipedia「三角関数の公式の一覧」17「[微積分](http://ja.wikipedia.org/wiki/%E4%B8%89%E8%A7%92%E9%96%A2%E6%95%B0%E3%81%AE%E5%85%AC%E5%BC%8F%E3%81%AE%E4%B8%80%E8%A6%A7#.E5.BE.AE.E7.A9.8D.E5.88.86)」参照)。

> $f(\theta) = \sin\theta\, →\, f'(\theta) = \cos\theta$
> $f(\theta) = \cos\theta\, →\, f'(\theta) = -\sin\theta$

> けれど、本文では$\theta=\omega t$として、時間$t$で微分したいのです。$\theta$を$t$で微分すると導関数$\theta '$($t$で微分したことを示すときは$\frac{d\theta}{dt}$で表す)はつぎのようになります。

> $\frac{d\theta}{dt} = \omega$

>「合成関数の微分」は、ふたつの導関数を掛け合わせます。そこで、$\sin$と$\cos$を角速度$\omega$における経過時間$t$で微分すると、導関数はつぎのように導けます。

> $f(t) = \cos(\omega t)\, →\, f'(t) = f'(\theta)\frac{d\theta}{dt} = -\omega \sin(\omega t)$
> $f(t) = \sin(\omega t)\, →\, f'(t) = f'(\theta)\frac{d\theta}{dt} = \omega \cos(\omega t)$


# 04 応用例 ー ランダムなパーティクルの円運動
速度を用いた円運動の応用例が、以下に掲げたCodePenのサンプル002です。クラス(`Particle`)に定めたメソッド(`_move()`)により円運動のアニメーションを行っています。プロパティ`speedX`と`speedY`は、円運動するオブジェクトごとの定数です。ふたつの値(の絶対値)が異なると、軌道が楕円になります。速度を操作することで、速さだけでなく軌道もランダムにできるのです。なお、つぎに抜書きしたコードは、一部簡略化ししました。

```js
_move(advance) {
	const angle = this.angle + advance;
	const velocityX = this.speedX * Math.sin(angle);
	const velocityY = this.speedY * Math.cos(angle);
	this.x += velocityX;
	this.y += velocityY;
	this.angle = angle;
};
```

#### サンプル002■EaselJS 1.0.2: Randomized Particles
<p class="codepen" data-height="400" data-default-tab="js,result" data-slug-hash="PoBMWgo" data-user="FumioNonaka" style="height: 400px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/FumioNonaka/pen/PoBMWgo">
  EaselJS 1.0.2: Randomized Particles</a> by Fumio Nonaka (<a href="https://codepen.io/FumioNonaka">@FumioNonaka</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


円運動以外も含めて微分の考え方がアニメーションにどう使えるか、興味のある方は「[Flashで学んでいた数学『追うのは微分が役に立つ』](https://qiita.com/FumioNonaka/items/399f7f43c84a7380bb2f)」もぜひ併せてお読みください。