blog

Pythonアニメーションによる2次のBessel曲線のデモ

Bessel曲線の話をするとき、最初に思い浮かぶのは次のような人です:図1. 名前は伏せますが、実はこのDavid Beckhamというイギリス人選手のことではなく、別の人、つまりPierre Béz...

May 12, 2020 · 6 min. read
シェア

ベイズ曲線といえば、下の男性が真っ先に思い浮かぶのではないでしょうか:

しかし、話題になっているのは実はこのベッカムというイギリス人男性ではなく、下の「」というフランス人男性なのです:

1962年、ベッセルは、彼がルノーで働いていたとき、ベッセル曲線の理論的研究を発表し、主に自動車設計のためのベッセル曲線を使用しています。ここで言ったことは、まだ多くの人々が最終的にベジェ曲線を理解していないかもしれませんが、次のグラフを見てみましょう、我々は理解するでしょう。

Photoshopや他のデザインソフトウェアでは、描画曲線は、主に使用されているベッセル曲線は、この曲線の上図に似ている、デザイナーは曲線の独自のニーズを描画する制御点の真ん中を制御することができます。以前のデザイナーは、直線灰色の非常に単純な描画するためにコンピュータを使用したいが、滑らかな曲線を描くことは非常に困難であり、ベッセル曲線の誕生は、自宅でコンピュータが滑らかな曲線を描くことが現実となっているように、ベッセル曲線の最大の用途です。

そして今日は、最も簡単な2次のベッセル曲線の導出について話し、それを使って示します。

まず、2次ベッセル曲線の原理を理解しましょう。2本の線分ABとBCを結んだものが下図だとします:

ここで、下図のようにAD/AB=BE/BCとなるAB上の点DとBC上の点Eをとります:

また、DF/DE=AD/AB=BE/BCとなるような点Fが線分DE上に必要です:

そして、DがAB上を動き続け、EがBC上を動き続けたとき、できる点Fの軌跡は曲線になり、その曲線は2次のBessel曲線です。これが今日導き出され、実証される曲線です。

Pythonのコードで直接デモンストレーションしてみましょう。まず、まだ様々なパッケージがインポートされています:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation

デモには matplotlib が使われているので、matplotlib のバックエンド、つまり表示を設定することが重要です。このコードの行は単独で使用するのが最善で、そうしないと失敗する傾向があるので、別に記載します:

%matplotlib

元のウィンドウがアニメーションを表示することはできませんので、これは非常に重要なステップは、このステップは、新しいウィンドウのポップアップの描画ではなく、直接描画する元のウィンドウでmatplotlibを可能にする、ここではipythonのマジックコマンドで、つまり、コマンドの前に"%"です。ここで説明するために、私はWin7のシステムを使用して、Anacondaの最新バージョンの開発ツールは、直接ダウンロードするAnacondaのウェブサイトに行くことができます。

点Aの座標はx1とy1、点Bはx2とy2、点Cはx3とy3、そして区間dots_numに点の数を設定します、このdots_numについては後で説明します。これらの変数の値はすべて任意に設定することができますが、いくつかの要件があります、作者は100で図面の座標系を設定したため、つまり、X軸とY軸の範囲は0〜100であるため、上記の3点の座標は、範囲よりも多くなく、できるだけ大きなdots_numの数は、アニメーションがより首尾一貫しているので、上記のパラメータを行います。そこで、これらのパラメータを次のように設定します:

x1=10
y1=80
x2=50
y2=10
x3=90
y3=80
dots_num=100

次の機能は、ベジェ曲線の軌跡を求めることです:

def two_degree_bc(x1=10, y1=80, x2=50, y2=10, x3=90, y3=80, dots_num=100): #bezier curve
 global xt, yt, x_dots12, x_dots23, y_dots12, y_dots23
 xt = [] #目標点のx座標
 yt = [] #目標点のy座標
 x_dots12 = np.linspace(x1, x2, dots_num) #線分ABのx座標
 y_dots12 = np.linspace(y1, y2, dots_num) #線分ABのy座標
 x_dots23 = np.linspace(x2, x3, dots_num) #直線BCのx座標
 y_dots23 = np.linspace(y2, y3, dots_num) #直線BCのy座標
 for i in range(dots_num): #目標点の軌跡を得る
 x = x_dots12[i] + (x_dots23[i]-x_dots12[i])*i / (dots_num-1)
 y = y_dots12[i] + (y_dots23[i]-y_dots12[i])*i / (dots_num-1)
 xt.append(x)
 yt.append(y)

x_dots12とy_dots12は線分ABのx座標とy座標、x_dots23とy_dots23は線分BCのx座標とy座標で、これらはnumpyの配列形式の4つで、これらのデータはすべてグローバル変数として設定されています。そして、上記のコードから、変数dots_numの役割は、線分ABとBC上に非常に多くの点を取り、これらの点を使って目標点の座標を導き出すことであり、点の数が多ければ多いほど、目標点の座標が多くなり、滑らかな曲線が描かれることがわかります。

次にアニメーション機能です:

def run(i):
 art1.set_data(x_dots12[i], y_dots12[i])
 art2.set_data(x_dots23[i], y_dots23[i])
 art3.set_data([x_dots12[i], x_dots23[i]], [y_dots12[i], y_dots23[i]])
 art4.set_data(xt[i], yt[i])
return art1,art2,art3,art4

最後にアニメーションを描きます:

two_degree_bc() #1次ベッセル曲線の目標点への軌跡
fig, ax = plt.subplots(figsize=(8,8))
ax.set_aspect(1) #2つの軸を等比にする
plt.xlim([0,100]) #軸の範囲を設定する
plt.ylim([0,100])
ax.plot([x1, x2], [y1, y2], color='#3e82fc') #AB線分を描く
ax.plot([x2, x3], [y2, y3], color='#3e82fc') #BC線分を描く
ax.plot(xt,yt,color='orange') #目標曲線をプロットする
art1, = ax.plot(x_dots12[0], y_dots12[0], color='green', marker='o') #scatterは使えない。なぜなら、得られるオブジェクトはリストではなく、オブジェクトだからだ。
art2, = ax.plot(x_dots23[0], y_dots23[0], color='green', marker='o')
art3, = ax.plot([x_dots12[0], x_dots23[0]], [y_dots12[0], y_dots23[0]], color = 'purple') #plot得られた結果は、ただ1つの要素、Shapeオブジェクトを含むリストである。
art4, = ax.plot(xt[0], yt[0], color='red', marker='o')
 
ani = animation.FuncAnimation(
 fig, run, frames=range(100), interval=2, save_count=50)
plt.show()

ここでは、まずtwo_degree_bc()関数を実行してターゲットポイントの軌跡を取得し、ABとBCの線分とターゲットカーブをプロットします。次に、変数art1からアニメーション部分を描画します。この部分はより複雑で、4つの変数のart1、art2、art3、art4の合計で、線分AB、BC、DEとターゲット曲線の軌跡に対応し、アニメーションを形成するために移動する4つの軌跡の点。アニメーションを生成するために、我々はいくつかのパラメータを含むアニメーションメソッドFuncAnimationを使用する必要があります、figはキャンバスの描画であり、runは関数が実行されたときにアニメーションを生成することです、framesはフレームであり、各フレームは、静的マップ内の点に対応するこれらの移動軌跡のいずれかを含み、これらの点の軌跡はまた、すべてのフレームに接続されています。フレームは、一般的にシーケンスである、つまり、変数の数が含まれており、各変数は、実行関数に割り当てられている、実行関数は、静的マップを生成するために、このパラメータを使用するので、多くの静的マップは、映画やテレビで見られるアニメーションと同じであるアニメーションに接続されている同じ理由です。save_count=50は、再生のためにフレームをキャッシュすることです、キャッシュされたフレームの数が多いほど、再生がスムーズに、これはあまり影響を与えません、任意に設定します。

ここで再び関数runアニメーションの役割を実行するには、コードの最初の4行は、プロットコードであり、最後のパラメータコードを返すことである、各行の最初の4行は、先に述べた点の軌跡を表し、art1は、ラインAB上の点であり、上のset_data(x_dot12[i]、y_dot12[i])メソッドと、対応するフレームが生成され、変数iは、前述のフレームのパラメータであり、生成されたフレームは、連続再生に使用するFuncAnimationに返されます。対応するフレームが生成され、変数iは前述のフレームのパラメータで、生成されたフレームはFuncAnimationに返され、連続再生に使用され、アニメーションが形成されます。art2、art3、art4の理由も同じです。生成されたアニメーション効果の静的スクリーンショットは以下の通りです:

そして最後に、この話題を深いV字の動きで締めくくる動画を:

フルコードがアップロードされました:

必要なら自分でダウンロードしてください。

------

他にもあります共に学び、遠くへ

Read next

Spring BootでAOPを正しく使う

AOPの良いところは、正しいことをするだけで、他のことはやってくれることです。多分ある日、あなたは裸で走り回りたい、服を着たくない、そして、あなたは解雇された使用人Aを置きます。ある日、あなたは外に出てお金を持って行きたいと思うかもしれないので、あなたはお金を得るのを助けるために別の使用人、Eを雇います。それがAOPです。AOPでは、すべての人が役割を持ち、柔軟に組み合わせることで、構成可能でプラグイン可能なプログラム構造を実現することができます。...

May 11, 2020 · 4 min read