rust nannouでクロソイド曲線を描く

nannou

今回は、クロソイド曲線を描いていきます。

クロソイド曲線って何!?って話ですがオイラー螺旋やコルニュ螺旋とも呼ばれる曲線です。

$$x(l)=\int_0^l cos(\frac{\theta^2}{2}) d\theta$$
$$y(l)=\int_0^l sin(\frac{\theta^2}{2}) d\theta$$

であらわされる曲線です。

道路や線路の設計やローラーコースターの設計などに使われているそうです。

クロソイド曲線を描いていく!

では、クロソイド曲線を描いていきましょう。

このクロソイド曲線の式、

$$x(l)=\int_0^l cos(\frac{\theta^2}{2}) d\theta$$
$$y(l)=\int_0^l sin(\frac{\theta^2}{2}) d\theta$$

いつもと違って、積分であらわされていますよね。

積分ってどういうことだったかな?っていうと

少し乱暴に言うと、インテグラルの中の式を微細に変化させて足し合わせたら、積分の結果でしたね。

というわけで、今回は、この\(\theta\)を微細に変化(⇒\(d\theta\)分変化)して、計算した結果を足し合わせていきましょう。

準備 modelの定義

今回は、微細量を変化させてそれを足し合わせていくっていうことをするので、それを記憶していく場所を準備します。

プログラムでいうと、インクリメントしていくってことです。

x座標とy座標、シータをmodelに定義しましょう。

struct Model{
   x:f32,
   y:f32,
   theta:f32,
}

初期値はそれぞ0.0でOKです。model関数の中でゼロに初期化します。

微細量を足していく

微細量をインクリメントしていくのは、update関数で行います。ここが、クロソイド曲線の心臓部。計算のアルゴリズムの部分です。

もう一度式を見てみましょう。

$$x(l)=\int_0^l cos(\frac{\theta^2}{2}) d\theta$$
$$y(l)=\int_0^l sin(\frac{\theta^2}{2}) d\theta$$

シータの二乗を2で割る、それを積分(足し合わせる)これを素直にプログラムにしちゃいます。

fn update(_app: &App, model: &mut Model, _update: Update) {
  let delta_theta = 0.01;
  model.theta += delta_theta;
  model.x += (model.theta * model.theta * 0.5).cos();
  model.y += (model.theta * model.theta * 0.5).sin();
}

こんな感じです。

描画しましょう

update関数が完成したら、あとはview関数に描画するようにプログラムしていきましょう。

今回は、点はellipseで行います。

draw.ellipse()
    .x_y(model.x,model.y)
    .radius(1.0)
    .color(WHITE);

今回は、軌跡を残すのでdraw.background()は毎回処理しないように注意してください。

これで、右上の方に向かってクルクルクルクルっとした、クロソイド曲線が描けます。

まとめ

今回は、クロソイド曲線を描きました。

このプログラムだと、右側にだけの描画になります。

左側のを描画するには、update関数の中のx、y座標をデクリメントすればOKです。

それに合わせてあとは、描画の方も整えればいいですね。

積分は、乱暴にいうと微細変化を足していくことです。高校で習う積分の定義でもシグマ記号を使った定義も習います。インテグラルがついてるから無理~ではなくて、それをどういうアルゴリズムで実現するか考えてみる、そしてチャレンジしてみる。失敗を恐れずどんどんチャレンジです。

ではまた!

コメント

  1. […] 前回、rust nannouでクロソイド曲線を描くで、クロソイド曲線を描きました。前回のは、ellipseで小さい円をいっぱい描いて線のように描いていました。 […]

  2. […] 詳しい値の計算方法は、前回のrust nannouでクロソイド曲線を描くで解説していますので、そちらをお願いします。 […]

タイトルとURLをコピーしました