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

nannou

前回、

で、クロソイド曲線を描きました。前回のは、ellipseで小さい円をいっぱい描いて線のように描いていました。

今回は、polylineで同じものを描いていきます。さらに、カラー化もしていきます。

polylineって何?って思う方は、rust nannouのpolylineを使うを見てください。描き方を解説してます。

まぁ、pathのデータを送ってそれを線でつないでくれるっていう感じです。

ではやっていきましょう。

polylineでクロソイド曲線を描く

クロソイド曲線のおさらいですが

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

これをグラフに書いていく感じです。

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

今回はpolylineでクロソイド曲線を描く方法を解説ます。

polylineで描画するときは、pathを作ってそれを描画していきます。

pathを作っていく

polylineで描画するときは、pathを使います。pathは、一個一個の座標をベクタ型にして記録しておきます。

相手に渡すときはイテレーターね。

なので、まずは、Struct Modelの中にVector2のベクタを作ります。

my_point: Vec<Vector2>,

次にmodel関数の中で、my_pointを初期化します。

let mut my_point = Vec::new();
model.my_point.push(pt2(0.0,0.0));
Model{
my_point,
}

こんな感じね。

次にupdate関数に行って、クロソイド曲線の計算結果を毎回、座標pt2(x,y)の形をmy_pointに追加するようにします。

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();
//polylineのためのベクタに追加
   model.my_point.push(pt2(model.x,model.y));
 }

これで、pathのデータづくりは完了です。

polylineの描画をしていく

データができたので、あとは描画を描いていきます。

これは簡単

draw.polyline()
    .weight(5.0)//線の太さ
    .points(model.my_point.clone())//ここでパスを渡す
    .color(RED);//色の指定

こんな感じね。

これで、polylineによるクロソイド曲線の完成

このサイズでパッと見た目は変わりませんが、ellipseの場合は無数に点を打って線っぽく描いているのに対して、polylineは点を線でつないで描いています。

polylineをカラー化する

ここまでで、まずはpolylineで描くことができました。ここからは、さらにこれをカラー化してきます。

カラー化?すでに赤いじゃん?って思うかもしれませんが、これは、全体に赤っていう指定をしただけです。

カラー化するってのはこういうことです。

右上がカラー化したpolylineのクロソイド曲線
まるでカメレオンのようですね。

これをどうやるかですが、polylineに渡すpath情報でpoints_coloredっていう色情報をセットで渡す方法があります。

draw.polyline()
    .weight(5.0)//線の太さ
    .points_colored(色情報付きのpath情報);

データとしては(p,c)ポイントとカラーをこんな感じにしたイテレーター使えるデータ形式で渡すことになります。

ではこれを作っていきましょう。

色情報を作る

色情報をセットで渡すんですが、そのための色情報を作ります。

もちろんですけど、色情報もイテレータにするので、その場所と初期化をチャチャっとしちゃいましょう

struct Model{
...
...
my_color:Vec<Hsl>,
}

色情報を持ったベクタを作る。HslじゃなくてRgbとかHsvとか好きなものでOK

fn model(.....){
....
....
let mut my_color = Vec::new();
my_color.push(hsl(0.5, 1.0, 0.3));//適当な色で初期化
Model{
.....
.....
my_color,
}

適当な色で初期化しておく

fn update(......){
.....
.....
model.my_color.push(hsl(...,...,...,));
}

色の作り方は自由です。

これで、色情報は完成

座標と色を一つにまとめる

座標情報(my_point)と色情報(my_color)ができたので、これをcolored_pointに渡すために(p,c)っていう形のベクタにしていきます。

let cp = (0..model.my_point.len())
         .map(|i|{
            let points = model.my_point[i];
            let colors = model.my_color[i];
            (points,colors)
         });

最後にこれをpolylineに渡します

draw.polyline()
    .weight(5.0)//線の太さ
    .points_colored(cp);

これで完成!

まとめ

polylineによる描画とさらにカラー化

データをどういう風に調理していくのかがポイントでした。

僕も結構苦労したんだけど、適当に?やったら意外とできちゃって

他にも方法があるかもしれませんが、僕は今回のようにやりました。

ではまた!

コメント

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