ねこでじ(Nekodigi)

Nekodigi’s diary

学習中の気づきをまとめています。応援よろしくお願いします

【Processing】等積変形するゴムを作る。

成果物

www.youtube.com
自然界のゴムは全部等積変形するので、なかなか見慣れた動きに近いと思います。ゴムが引っ張られていく動きもよりリアルになった気がします。猫に見せると結構ついてくるかもしれませんね(笑)

仕組み

初めに長さと太さから体積を求め、その後各フレーム、体積を長さを割ることでその時の太さを求めています。ただし、余りにも極端な値になると変になってしまうので、最大値内に丸めています。それ以外は普通のSpringと同じ仕組みです。

コード

Isovolumetric Springという名前で追加しています。
github.com

【Processing】Hyperbolic Tilingを実装する。

成果物

Animation

www.youtube.com
Hyperbolic Plane上(Poincare Disk上)に、正多角形を敷き詰めることができました。正p角形をq個隣接するように並べる場合、平面上では(p-2)(q-2)=4になりますが、Hyperbolic Plane上に敷き詰める時は(p-2)(q-2)>4になります。

仕組み

今回はこちらのTutorialを参考にして作成しました。
www.youtube.com
ただ、どこが何に対応しているのか分かりにくかったので、Processingを使って視覚化してみることにしました。

Visualization1

www.youtube.com
大まかには、普通の多角形を中心に作成し、Mobius Transformを使い、鏡に映していくようにPoincare Disk上でどんな形になるのかを求めています。
まず、中心、Poincare Disk上の点を渡して、hypCircleと書いてある二つの円を作成します。そして、その二つの円の交点を求めます。交点の一つをPoincare Diskを中心にMobius Transformで変換してinvipを求めます。そして、二つの交点とinvPを通る円を求めます。この円を中心に普通の多角形にMobius Transformをかけると、Poincare Disk上での多角形の頂点の位置がわかります。Poincare Diskを中心に先ほどの頂点にMobius Transformをかけると、カーブしている辺を計算するために後で使う、invposが求められます。

Visualization2

www.youtube.com
2つの頂点と対応するinvposを通る円の一部が、多角形の辺になります。

Tiling

Tutorialでは、先に辺を求めていました。しかし、距離でマージや環状になっている辺に面を張る部分は、コードが複雑になってしまいそうなので、一番最初にベースの多角形を作っておき、それを毎回転写するという方法をとっています。転写は意外と簡単で、辺(弧)を選んで、その弧のもとになっている円を中心に、全ての辺をMobius Transformにかけると完了です。重複を削除すればさらに良いのですが、今回は行っていません。

コード

こちらのリポジトリにHyperbolic Tilingという名前で追加しています。
仕組みを視覚化したものは、Mechanism of Hyperbolic Tilingという名前で追加しています。
github.com

【Processing】円と、四角形の弾性衝突を計算できる物理エンジンを実装する。

成果物

www.youtube.com
数学友達が物理エンジンを作りたいって言ったので、さっそく調べてみることにしました。昔やろうとして挫折したのですが、今回はうまくいきました。

仕組み

物体が衝突したときに、速度を再計算し、次のフレームでぶつかってしまわないように、位置を調整するという仕組みです。使われている数式は、高校物理で出てくるような一般的なものです。
今回は、こちらのTutorialの1ページ目を見ながら作りました。最後まで行くと回転や、摩擦も扱えるようになりますが、結構重たいので、余裕ができたら進めていきたいです。
How to Create a Custom Physics Engine - Envato Tuts+ Game Development Tutorials

コード

sketch_1_0_3_Utilsという名前で追加しています。
github.com

【Processing】画像を円の中に反転する

成果物

www.youtube.com
Houdini TutorialのHyperbolic TilingでMobiusInverseという名前の関数として定義されていたものが気になったので、調べてみたところ、Inversion in circleというものであることがわかりました。メビウス変換というものでもあるそうです。
こちらのサイトで、よい視覚化が紹介されているので、ぜひ見てみてください。
Non-Euclidean Geometry: Inversion in Circle

仕組み

 \begin{array}{l}
円の中心x_{0} ,円の半径k ,変換対象のx,yを与えると、変換後のx',y'が得られます。\\
x'\ \ =\ \ x_{0} +\frac{k^{2}( x-x_{0})}{( x-x_{0})^{2} +( y-y_{0})^{2}}\\
y'\ \ =\ \ y_{0} +\frac{k^{2}( y-y_{0})}{( x-x_{0})^{2} +( y-y_{0})^{2}}\\
画像を変形するためには、逆変換を行う必要があります。\\
この式は、数学友達にたのんで解いてもらいました。\\
x-x_{0} =X,\ y-y_{0} =Yとおくと、\\
x'-x_{0} =\frac{k^{2} X}{X^{2} +Y^{2}} ,y'-x_{0} =\frac{k^{2} Y}{X^{2} +Y^{2}}\\
( x'-x_{0})^{2} +( y'-y_{0})^{2} =\frac{k^{4}\left( X^{2} +Y^{2}\right)}{\left( X^{2} +Y^{2}\right)^{2}} =\frac{k^{4}}{X^{2} +Y^{2}}\\
X^{2} +Y^{2} =\frac{k^{4}}{( x'-x_{0})^{2} +( y'-y_{0})^{2}}\\
x'-x^{0} =\frac{( x'-x_{0})^{2} +( y'-y_{0})^{2}}{k^{4}} \cdot k^{2} X=\frac{( x'-x_{0})^{2} +( y'-y_{0})^{2}}{k^{2}} \cdot ( x-x_{0})\\
x-x_{0} =\frac{k^{2}( x'-x_{0})}{( x'-x_{0})^{2} +( y'-y_{0})^{2}} より\\
\\
x=x_{0} +\frac{k^{2}( x'-x_{0})}{( x'-x_{0})^{2} +( y'-y_{0})^{2}}  yでも同様に、\\
y=y_{0} +\frac{k^{2}( y'-y_{0})}{( x'-x_{0})^{2} +( y'-y_{0})^{2}}\\
実は、逆変換の数式は元とほとんど同じ形をしていて、\\
同じ関数を使いまわすことができます。
\end{array}
画像の補完についてはこちらページをご覧ください。
nekodigi.hatenablog.com

コード

github.com

【Processing】白を透明度に変換して、白黒画像に塗り絵を行う。

成果物

f:id:Nekodigi:20200613201653p:plain

仕組み

白との差を求め、その数値に従って、元画像と塗った色をブレンドすることで、塗り絵を実現してます。

コード

github.com

【Houdini】0004 Reaction Diffusionの動作原理についての考察

成果物

www.youtube.com
Reaction Diffusionと聞いて、Karl SimsさんのTutorialで紹介されていた数式を連想したのですが、実際は、ボリュームをぼかして引き算するというシンプルなものだったので、その動作原理について考察してみました。実験として、画像にガウシアンぼかしをかけて引き算すると、理にかなった結果が得られたので、そちらを紹介していきたいと思います。

仕組み

Reaction Diffusionの動作を実現するためには、何もない場所では成長し、他のボリュームとぶつかる場所では退行するという動作をする必要があります。それでは、2Dの場合でどのような動きをするのか見ていきましょう。
HoudiniのTutorialと同じような感じで、20pxのガウシアンぼかしをかけたものから、50pxのガウシアンぼかしをかけたものを引くという処理を行っています。

ボリューム1つの場合

f:id:Nekodigi:20200612230527p:plain
まず、ボリュームが一つ真ん中にある場合を考えます。処理を行うと…
f:id:Nekodigi:20200612230752p:plain
予想通り、外側に成長しています。
小さいぼかしから、大きいぼかしを引いたのに外側に成長する理由は、大きいぼかしは広く薄く分布している一方、小さいぼかしは、狭く濃く分布しているからです。
f:id:Nekodigi:20200612231907p:plain
もとのボリュームを引いて成長分を見てみると、これだけ成長したことがわかります。

ボリューム2つの場合

f:id:Nekodigi:20200612232021p:plain
このようなボリュームを考えます。先ほどと同じように処理を施すと…
f:id:Nekodigi:20200612232223p:plain
予想通り、周りに何もない場所では成長し、他のボリュームとぶつかる場所では退行しています。これは、隣の大きいぼかしが自分の所まで影響を及ぼしたため、削られたと考えることができます。
f:id:Nekodigi:20200612232904p:plain
成長分を見てみると、周りに何もない場所では成長し、他のボリュームとぶつかる場所では退行していることがはっきりとわかります。

ファイル

GIMPファイルを配布するので、いろいろ試してみてください。
github.com

【Houdini】様々な成長アルゴリズムの実装

成果物

Reaction Diffusion (Gray Scott)

www.youtube.com
今回は、チュートリアルを見ながら作った様々な成長アルゴリズムの仕組みと比較を行っていこうと思います。Remeshなど、いくつかのノードはバージョン変更がされているため、opaddなどを使ってバージョン指定して取り出す必要があります。
サルにもわかる Houdini: Node Versions
これは、Processingでも実装したGray Scottアルゴリズムです。前回はBz反応のパターンを再現する方法が分からなかったのですが。こちらのサイトで紹介されている。Waves(Xi)というものが近かったので、そちらのパラメーターを試してみました。
WebGL Gray-Scott Explorer at MROB
立体の表面上で反応させたり、3Dで反応させるパターンもあるので、今後実装していきたいと思います。

Tutorial

www.youtube.com

Coral Growth

www.youtube.com
どのようにあのひだが作られているのかと思っていたら、Relaxノードが使われていました。Relaxノードは頂点をある大きさの球だと見なして、ぶつからないように移動させるというものです。ポイントのサンプリングと、Relaxノードを繰り返していくだけで、お互いに交差しないあのひだを作ることができます。

Tutorial

www.youtube.com

Recursive Growth (Volume advection)

www.youtube.com
ボリュームの曲率の強さに応じて、渦巻くベクトル、膨張する方向のベクトルに移動させるとこの様な結果が得られます。パラメーターによって、キノコのような結果が得られたり、腫瘍のような結果が得られたりします。

Tutorial

www.youtube.com
全部で4回のシリーズになっています。第3回まで見るとこの動画を作ることができます。

Project File

このチュートリアルは、サンプルがダウンロード出来ないので、私がリメイクしたものでよければお使いください。
VDB-Advectionというなまえで追加しています。
github.com

【Arduino】 Youtubeを足で操作する。

成果物

www.youtube.com
YoutubeのTutorialを見ているときに、分からないところですぐに止めることができずにとても困っていたので、足で操作するデバイスを作ってみました。ボタンを踏んでいる間だけ止まるので、とても便利です。ちなみに、Youtube以外の動画再生ソフトもコントロールできます。

仕組み

100均の手押しランプが足で踏むのにぴったりだと思ってふたを開けてみたら、基盤までぴったり入ってしまいました。
後は、スイッチのケーブルをGND、D15に接続し、LEDをGND、A0~A2につなげば回路の方は完成です。
f:id:Nekodigi:20200607085548j:plain
f:id:Nekodigi:20200607085604j:plain

コード

HID-Projectというライブラリの、Consumer-APIという部分に、MEDIA関係のコードが格納されているので、そのコードを使ってYoutubeを操作しています。

【数学】迎えが到着する前に出発したときの、時間短縮量を求める。

成果物

f:id:Nekodigi:20200523210139g:plain
 \begin{array}{l}
車をa( km/h) ,人間をb( km/h) ,車が到着するt( h) 前に出発し鉢合わせた時点で車に乗る\\
早くなった時間( h) =t+\frac{t( b-a)}{a+b}
\end{array}
この式は自力で導き出したものです。一応先生などに確認してもらっています。
早まる時間が始点と終点の距離に依らず同じというところがこの問題の面白い点です。
グラフにするといいという指摘をいただいたのですが、ひとまず、買ったGANの本を進めていきたいので、次回からにさせて頂きたいと思います。

導出

 \begin{array}{l}
atは人間が出発した時の車までの距離\\
これをを合成速度で割り、出発してから鉢合わせるまでの時間を求める。\\
\frac{at}{a+b} =t'\\
行きの短縮時間は元々かかるはずだったtを実際にかかったt'で引いたt-t'\\
t'bは、鉢合わせるまでに人間が進んだ距離で、この分だけ車の帰りの距離が短くなる\\
よって、車の速度のxで割った\frac{t'b}{x} が帰りの短縮時間。\\
e=t-t'+\frac{t'b}{a}\\
これを整理して\\
e=t-\frac{at}{a+b} +\frac{abt}{a( a+b)}\\
e=t-\frac{at}{a+b} +\frac{bt}{a+b}\\
e=t+\frac{( b-a) t}{a+b}
\end{array}

コード

Transfar time reductionという名前で追加しています。
github.com

【タイピング】typing.comのアバターが最大レベルに達する。

成果物

f:id:Nekodigi:20200517215045p:plain
先生は寿司打で5000円もの黒字を出しているのに自分は1000円しか黒字にならなかったので、普段からほぼ英語しか打っていない私は英語入力を極めることにしました。そこで、英語タイピング界再王手と思われるtyping.comで練習することにしました。プログラムタイピングに特化したtyping.ioもありますが、そちらは既にクリアしました。
typing.comはここ最近コツコツ進めていたのですが、今日になって急にスイッチが入ってしまい一日に2万文字も入力してしまいました。明日から遠隔授業が始まるのに腱鞘炎になりそうで怖いですw。ちなみに、ローマ字タイピングも一応進めていてmyTypingというサイトで練習しています。どちらも初めて1週間程ですが、結構効果を感じています。

【Processing】スパイク状のメンガーのスポンジを作る。

成果物

トゲトゲバージョン

www.youtube.com
単純に各面に一つずつ再帰的に載せていくとこのようになります。

フルバージョン

www.youtube.com
各面に、フラクタルになるように何度も載せていくとこうなります。立方体の時は正八面体に、正四面体の時は立方体に近づいて行っている気がします。正四面体の方は作るのが非常に難しかったのですが、思ったよりも地味な見た目になってしまって残念です。

仕組み

特に難しい正四面体の場合に絞って説明します。正四面体は子と親が正反対の向きになっています。また、面上の基底ベクトルを計算し、親の中心から子の中心がどれだけ離れているか指定すると、親オブジェクトの面にちょうど乗る位置を求めることができます。
nekodigi.hatenablog.com
また、正四面体のフルバージョンは、各面に子を前回の逆シェルピンスキーのギャスケットのように並べていくことで、実装しています。
nekodigi.hatenablog.com

コード

Menger Spikeという名前で追加しています。
github.com

【Processing】逆シェルピンスキーのギャスケット

成果物

f:id:Nekodigi:20200516083040p:plain
スパイク状のメンガーのスポンジを作るために、逆シェルピンスキーのギャスケットが必要なのではと思ったので、作ってみました。

仕組み

f:id:Nekodigi:20200516083412p:plain:w300
外接円の半径がrの三角形にn列配置したいときは、普通白い位置に置くようになるのですが、それをr*3/2/n*2/3だけ下にずらすと、ちょうど三角形の中心の黒い位置に移動します。この性質を利用して三角形を並べていくとシェルピンスキーのギャスケットの空洞部分のみに三角形をおいていくことができます。また、列の数はn=pow(2, x)にするのですが、初めにxを大きい数値からスタートさせると、重複している部分が上手に隠されます。

コード

逆シェルピンスキーのギャスケットはInverse Sierpinski_Gasketという名前で追加しています。
github.com
三角形の中心においていくデモはTriangle_Centerという名前で追加しています。
github.com

【Processing】正四面体の面上の基底ベクトル

成果物

www.youtube.com
正四面体で逆メンガーのスポンジを作ろうとしたのはいいのですが、面上に複数の正四面体を綺麗に配置しなければならないことが分かったので、面上に配置するための基底ベクトルを求めてみました。

仕組み

基底ベクトルは、頂点座標三つの辺の中点抱けで求めることができます。
まず、面上の直交するベクトルを求め、外積を使って先ほどの二つのベクトルに直交する座標を求めるとx,y,zに対応する3つの基底ベクトルが揃います。これを各面に行っていけば完成です。

コード

Tetrahedron UVWという名前で追加しています。
github.com

【Processing】重力で引きあっているのにぶつからない三つの物体(三体問題)

成果物

www.youtube.com
8の字を書いて動いているのが特徴です。ありえないほど綺麗な軌道をしているので、本当に動くのか気になって実装してみました。今回は、定数を入力して見ただけに過ぎないので、時間があれば論文を読んで詳しい仕組みについて知りたいです。

仕組み

 \begin{array}{l}
三つの物体それぞれの加速度はこのようにあらわされます。\\
{\displaystyle \begin{aligned}
\ddot{\mathbf{r}}_{\mathbf{1}} & =-Gm_{2}\frac{\mathbf{r_{1}} -\mathbf{r_{2}}}{|\mathbf{r_{1}} -\mathbf{r_{2}} |^{3}} -Gm_{3}\frac{\mathbf{r_{1}} -\mathbf{r_{3}}}{|\mathbf{r_{1}} -\mathbf{r_{3}} |^{3}} ,\\
\ddot{\mathbf{r}}_{\mathbf{2}} & =-Gm_{3}\frac{\mathbf{r_{2}} -\mathbf{r_{3}}}{|\mathbf{r_{2}} -\mathbf{r_{3}} |^{3}} -Gm_{1}\frac{\mathbf{r_{2}} -\mathbf{r_{1}}}{|\mathbf{r_{2}} -\mathbf{r_{1}} |^{3}} ,\\
\ddot{\mathbf{r}}_{\mathbf{3}} & =-Gm_{1}\frac{\mathbf{r_{3}} -\mathbf{r_{1}}}{|\mathbf{r_{3}} -\mathbf{r_{1}} |^{3}} -Gm_{2}\frac{\mathbf{r_{3}} -\mathbf{r_{2}}}{|\mathbf{r_{3}} -\mathbf{r_{2}} |^{3}} .
\end{aligned}}
\end{array}
次の初期速度を与えてやると、ぶつからずに回り始めます。
 \begin{array}{l}
r1( 0) \ =\ -\ r3( 0) \ =\ ( -0.97000436,\ 0.24308753) ;\ \\
r2( 0) \ =\ ( 0,0) ;\ \\
v1( 0) \ =\ v3( 0) \ =\ ( 0.4662036850,\ 0.4323657300) ;\\
\ v2( 0) \ =\ ( -0.93240737,\ -0.86473146) .\ 
\end{array}
こちらのサイトを参考にしています。
Three-body problem - Wikipedia

コード

Three body Problemという名前で追加しています。
github.com

【Processing】三点を通る円を求める

成果物

www.youtube.com
三点を入力すると、それを通る円の方程式を求めてくれます。そして、その方程式から、円の中心と半径を求め、Processingに表示しています。

仕組み

   \begin{array}{l}
三点でのx,yを代入すると、連立方程式を解くことでl,m,nが求められます。\\
\begin{cases}
lx_{0} +my_{0} +n= & -\left( x_{0}^{2} +y_{0}^{2}\right)\\
lx_{1} +my_{1} +n= & -\left( x_{1}^{2} +y_{1}^{2}\right)\\
lx_{2} +my_{2} +n= & -\left( x_{2}^{2} +y_{2}^{2}\right)
\end{cases}
\end{array}
 \begin{array}{l}
円の方程式\\
x^{2} +y^{2} +lx+my+n=0\\
cx=-\frac{l}{2}\\
cy=-\frac{m}{2}\\
rは中心と三点の距離と同じです。
\end{array}
※追記
よりシンプルに解くことが出来るようにコードを追加しました。Horikawa JunitiroさんのHyperbolic Tilingに良いコードがあるのですが、出典が分からないので別のものを参考にしました。より良いコードを知っている方は教えてください。
www.geeksforgeeks.org

コード

Circle passing through 3 pointsという名前で追加しています。
github.com