２点間の線形補間、イージング関数、ベジェ曲線

#概要
２点間の線形補間とは,空間上の2点A,Bを端点とする線分AB上の任意の点を計算することである.
この考えを用いることによって,直線上に限るがUIなんかを動かすことが出来る.
また線形補間から発展して,イージングやベジェ曲線の話もしたいと思う.

以下の順序で話していく.

1.[２点間の線形補間入門](#1２点間の線形補間入門)
2.[実際に補間してみよう](#2実際に補間してみよう)
3.[イージングで気持ちいい動きに](#3イージングで気持ちいい動きに)
4.[ベジェ曲線](#4ベジェ曲線)
#1.２点間の線形補間入門
まず内分の公式について述べよう.
線分$AB$を$m:n$に内分する点$P$とは,線分$AB$上にあって$AP:PB=m:n$となる点のことをいう.
２次元上の点$P$の座標は次の式で求めることができる.
$(Aの座標)=(x_a,y_a),(Bの座標)=(x_b,y_b)$,とするとき,
$(Pの座標)=(\frac{nx_a+mx_b}{m+n},\frac{ny_a+my_b}{m+n}).$
![33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402530/ebc55ae8-a055-72b9-c60f-32786a0abef7.png)


証明(読みたい人だけ)

$x$座標と$y$座標を別々に計算していることから,$x$軸上,$y$軸上でそれぞれ考えればよい.
$x$成分に関して示せば$y$成分に関しても同様である.$x$成分に関して示す.
点$P$の座標=$(x_p,y_p)$とおく.線分$AP$の$x$成分の長さは,$|x_p-x_a|.$
また線分$PB$の$x$成分の長さは,$|x_b-x_p|$である.
今,$AP:PB=m:n$なので,
$|x_p-x_a|:|x_b-x_p|=m:n$,より比の計算から,$m|x_b-x_p|=n|x_p-x_a|.$
ここで,$x_p$は$x_a$と$x_b$の間にある,つまり$x_a<x_b$のときは,$x_a<x_p<x_b.$
$x_b<x_a$のときは,$x_b<x_p<x_a$,となるので,
$x_a<x_b$のとき,
$|x_p-x_a|=x_p-x_a,$
$|x_b-x_p|=x_b-x_p.$
$x_b<x_a$のとき,
$|x_p-x_a|=-(x_p-x_a),$
$|x_b-x_p|=-(x_b-x_p).$
となり,$m|x_b-x_p|=n|x_p-x_a|$の絶対値が外せて,$m(x_b-x_p)=n(x_p-x_a)$とできる.
$mx_p+nx_p=nx_a+mx_b$
$x_p(m+n)=nx_a+mx_b$
$x_p=\frac{nx_a+mx_b}{m+n}$
を得る.■

この証明により,この公式が任意の次元に拡張できることも分かる.

さて,$m=t,n=1-t,\,(0\le t \le 1)$とおこう.$m+n=1$より,
$(点Pの座標)=((1-t)x_a+tx_b,(1-t)y_a+ty_b).$
分母を消すことができた.
$t=0$のとき,
$((1-0)x_a+0x_b,(1-0)y_a+0y_b)=(x_a,y_a)=(点Aの座標).$つまり点Aと点Pは一致する.
$t=1のとき,$
$((1-1)x_a+1x_b,(1-1)y_a+1y_b)=(x_b,y_b)=(点Bの座標).$つまり点Bと点Pは一致する.

$0<t<1$のとき,$P$は内分点になる.

（証明）
任意の内分が$t:1-t$でかけることを示す.
$P$を線分$AB$を$a:b$に内分する点とする.$(\forall a,b\in \mathbb{N})$
比に同じ数をかけても変わらないので,$\frac{1}{a+b}$をかけて,
$a:b=\frac{a}{a+b}:\frac{b}{a+b}$となる.
$t=\frac{a}{a+b}$とおけば,$a>0,b>0$だから,$0<t<1$.
また,$\frac{b}{a+b}=\frac{a+b}{a+b}-\frac{a}{a+b}=1-t$.
よって,$0<t<1$がとれて,$a:b=t:1-t$とかけることが示せた.■

例えば,$t=0.1$とすると,点$P$は$AB$を$1:9$に内分する点となる.
($t<0,1<t$では外分点を表現できる.)

この議論から,$t$を$0$から$1$まで変化させることによって,2点間の線形補間ができることをイメージしてくれると嬉しい.
#2.実際に補間してみよう

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">２点間の線形補間(Qiita記事用) <a href="https://t.co/lAbFvcs1xL">pic.twitter.com/lAbFvcs1xL</a></p>&mdash; みるきーさいとう (@milky_saitou) <a href="https://twitter.com/milky_saitou/status/1177515869917696000?ref_src=twsrc%5Etfw">September 27, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

```Lua:Lua
t = obj.time / obj.totaltime
obj.ox = (1 - t) * (-192) + t * 217
obj.oy = (1 - t) * 70 + t * (-79)
```
非常に単純な線形補間移動をAviUtl上で再現してみた.
現在のフレーム番号を移動に使う総フレーム数で割ったものを$t$とすれば,$0\le t \le 1$,を得ることが出来る.
UIアニメーションとして見れば直線的で固い動きである.

#3.イージングで気持ちいい動きに
イージング関数の明確な定義を見つけることはできなかったが,閉区間[0,1]上の数値を良い感じに加工できる関数のことである.
UIアニメーションなどで視覚効果を得るために使える.4で述べるベジェ曲線を用いれば簡単にイージング関数が作れる（かもしれない）.

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">２点間の線形補間 -EaseOut- (Qiita記事用) <a href="https://t.co/oOLP9BqoYn">pic.twitter.com/oOLP9BqoYn</a></p>&mdash; みるきーさいとう (@milky_saitou) <a href="https://twitter.com/milky_saitou/status/1177534327816458240?ref_src=twsrc%5Etfw">September 27, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

```Lua:Lua
s = obj.time / obj.totaltime
t = -(1 / 4)^(s * 10) + 1
obj.ox = (1 - t) * (-192) + t * 217
obj.oy = (1 - t) * 70 + t * (-79)
```
![988.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402530/870ba6ec-1965-b081-3da8-fdc80fd9f84a.png)
$t = -(1/4)^{10s}+1のグラフ$

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">２点間の線形補間 -EaseIn-(Qiita記事用) <a href="https://t.co/EBY1vspUtQ">pic.twitter.com/EBY1vspUtQ</a></p>&mdash; みるきーさいとう (@milky_saitou) <a href="https://twitter.com/milky_saitou/status/1177576503179018240?ref_src=twsrc%5Etfw">September 27, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

```Lua:Lua
s = obj.time / obj.totaltime
t = s^5
obj.ox = (1 - t) * (-192) + t * 217
obj.oy = (1 - t) * 70 + t * (-79)
```

![999.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402530/d53706ee-b545-9e86-6b5c-53696a750b29.png)
$t=s^5$のグラフ

上記２つは以下のようにUIで使用可能である.

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">２点間の線形補間 -Easing UI応用-(Qiita記事用) <a href="https://t.co/n4tZtrTxyl">pic.twitter.com/n4tZtrTxyl</a></p>&mdash; みるきーさいとう (@milky_saitou) <a href="https://twitter.com/milky_saitou/status/1177580044996079617?ref_src=twsrc%5Etfw">September 27, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
この他にも様々なイージング関数があるが,ここでは紹介しない.
#4.ベジェ曲線
内分の応用としてベジェ曲線があげられる.ベジェ曲線はコンピュータ上で曲線を描く際にしばしば用いられる.

###2次ベジェ曲線
$2次ベジェ曲線は2点A,Bと1つの制御点Qで作ることができる.$
![vegie.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402530/01e65193-5358-aceb-3f6c-a06e434808c2.png)

線分$AQ$を$t:1-t$に内分する点を$P_1$,線分$QB$を$t:1-t$に内分する点を$P_2$とする.線分$P_1P_2$を$t:1-t$に内分する点を$P$として,点$P$の軌跡を２次ベジェ曲線と定義する.
点$A$の座標を$(x_0,y_0)$,点$Q$の座標を$(x_1,y_1)$,点$B$の座標を$(x_2,y_2)$とする.
内分の公式から,
点$P_1$の座標は$((1-t)x_0+tx_1,(1-t)y_0+ty_1),$
点$P_2$の座標は$((1-t)x_1+tx_2,(1-t)y_1+ty_2),$となる.
したがって,Pの座標も内分の公式から求められて,
$(t^2(x_2-2x_1+x_0)+2t(x_1-x_0)+x_0,$
　　$t^2(y_2-2y_1+y_0)+2t(y_1-y_0)+y_0),$となる.
(計算略　物好きな人はやってみるとよい.)

$t=0$のとき,
$(0^2(x_2-2x_1+x_0)+2\cdot0(x_1-x_0)+x_0,$
　　$0^2(y_2-2y_1+y_0)+2\cdot0(y_1-y_0)+y_0)$
$=(x_0,y_0).$

$t=1$のとき,
$(1^2(x_2-2x_1+x_0)+2\cdot1(x_1-x_0)+x_0,$
　　$1^2(y_2-2y_1+y_0)+2\cdot1(y_1-y_0)+y_0)$
$=(x_2-2x_1+x_0+2x_1-2x_0+x_0,$
　　$y_2-2y_1+y_0+2y_1-2y_0+y_0)$
$=(x_2,y_2).$
となる.
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">2次ベジェ曲線　点Pの軌跡(Qiita記事用) <a href="https://t.co/j6nbtC8I7w">pic.twitter.com/j6nbtC8I7w</a></p>&mdash; みるきーさいとう (@milky_saitou) <a href="https://twitter.com/milky_saitou/status/1177608726301134850?ref_src=twsrc%5Etfw">September 27, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
###3次ベジェ曲線
3次ベジェ曲線は2点$A,B$と2つの制御点$Q_1,Q_2$で作ることが出来る.
線分$AQ_1$を$t:1-t$に内分する点を$P_1$,線分$Q_1Q_2$を$t:1-t$に内分する点を$P_2$,線分$Q_2B$を$t:1-t$に内分する点を$P_3$とする.
さらに,線分$P_1P_2$を$t:1-t$に内分する点を$P_4$,線分$P_2P_3$を$t:1-t$に内分する点を$P_5$とする.
さらに,線分$P_4P_5$を$t:1-t$に内分する点を$P$として,点$P$の軌跡を3次のベジェ曲線と定義する.
$A$の座標を$(x_0,y_0)$,$Q_1$の座標を$(x_1,y_1)$,$Q_2$の座標を$(x_2,y_2)$,$B$の座標を$(x_3,y_3)$とすると,
内分の公式を用いて順番に点の座標を計算していけば,最終的に点$P$の座標,
$(t^3(x_3-3x_2+3x_1-x_0)+t^2(3x_2-6x_1+3x_0)+t(3x_1-3x_0)+x_0,$
　　　　　　$t^3(y_3-3y_2+3y_1-y_0)+t^2(3y_2-6y_1+3y_0)+t(3y_1-3y_0)+y_0),$を得る.

これも$t=0$のとき,$(x_0,y_0)$,$t=1$のとき,$(x_3,y_3)$となる.

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">3次ベジェ曲線　点Pの軌跡(Qiita記事用) <a href="https://t.co/abXs5bwPHM">pic.twitter.com/abXs5bwPHM</a></p>&mdash; みるきーさいとう (@milky_saitou) <a href="https://twitter.com/milky_saitou/status/1177617730981134336?ref_src=twsrc%5Etfw">September 27, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

###n次ベジェ曲線
任意の次数のベジェ曲線を描きたくなることもあるだろう.私の予想を書いておく.
$A(x_0,y_0),B(x_n,y_n),Q_k(x_k,y_k)\,\,(k=1,2,\cdots,n-1)$と各々座標をおくと,$n$次ベジェ曲線の点$P$の軌跡は,

```math
(\sum_{l=0}^n(_nC_lt^l(\sum_{k=0}^l(-1)^k\,_lC_kx_{l-k})),\sum_{l=0}^n(_nC_lt^l(\sum_{k=0}^l(-1)^k\,_lC_ky_{l-k})))
```
$で与えられる(かもね).$
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ｎ次ベジェ曲線を描くプログラム（1000分割18次くらいで計算時間が膨大になる模様） <a href="https://t.co/ZE8iJmHK5J">pic.twitter.com/ZE8iJmHK5J</a></p>&mdash; みるきーさいとう (@milky_saitou) <a href="https://twitter.com/milky_saitou/status/1127224712591884288?ref_src=twsrc%5Etfw">May 11, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

#おわりに
ベジェ曲線を用いてイージング関数を生成するなんてのも面白いかもしれないですね.