2013年10月27日
ベジェ曲線をかいてみた
2013年10月現在、俺は大学生である。ちなみに美大だ。
美大なので、俺を含めドロー系のソフトを使って絵を描いたり、デザイン作業を行っている方が多い。
そのドロー系のソフトによく使われる機能の一つにペンツールがある。
今回はあのペンツールによく使われるベジェ曲線について少々勉強してみた。
定義については本当は何と言うべきなのかはわからないのでテキトーに言っとくと、ベジェ曲線は始点といくつかの制御点と終点によって描画される数式だ。
さて、線というのは点の連なりによって画面上に描画される。
この点の座標位置をベジェ曲線の数式を用い、人間に分かりやすく数字で、ざっくばらんに表現する端末上のプチアプリを作ってみることにした。
以下が今回C言語で作ったプログラムのmain関数である。
ちなみに分かりやすくするため、”%0.1f”として小数点以下1位以降は表示されないようにした。
計算されないわけではないので、小数点以下の丸め誤差は発生します。気をつけようね。
これを実行すると、以下のような結果が出る。
t が 0.0 のとき
Point X は 1.000000
Point Y は 5.000000
t が 0.1 のとき
Point X は 1.329000
Point Y は 3.703000
t が 0.2 のとき
Point X は 1.712000
Point Y は 2.784000
t が 0.3 のとき
Point X は 2.143000
Point Y は 2.201000
t が 0.4 のとき
Point X は 2.616000
Point Y は 1.912000
t が 0.5 のとき
Point X は 3.125000
Point Y は 1.875000
t が 0.6 のとき
Point X は 3.664000
Point Y は 2.048000
t が 0.7 のとき
Point X は 4.227000
Point Y は 2.389000
t が 0.8 のとき
Point X は 4.808001
Point Y は 2.856000
t が 0.9 のとき
Point X は 5.401000
Point Y は 3.407001
t が 1.0 のとき
Point X は 6.000001
Point Y は 4.000001
結果から大体察してくださるだろうか。
tが0〜1までに至る間、点X,Yの座標位置を出力している。
この点の位置の情報を目に見える形で描画すればベジェ曲線の完成というわけだ。
物好きな方は上の点を、紙に鉛筆使って点をうち、線で結んでみると良いだろう。
(制御点も描くと理解が深まる。)
なんとなく、馬蹄形っぽいUの字をひっくり返したような曲線が描けるはずだ。
では、点XとYの位置を計算する関数getpointX()とgetpointY()を見てみよう。
引数は、(パラメータ、 始点位置、 1個目の制御点位置、 2個目の制御点位置、 終点位置)である。
上手い人はもっとまとめてスッキリ書けるんだろうけど、数学の難しさとコーディングの難しさをごっちゃにしてはいけないと思うし、出来ないのでこうなった。
アルゴリズムは難しい公式をくだくだ述べるより、ソースを見るのが分かりやすいと思います。
以上で一応、ベジェ曲線を学んだメモは終わり。
最後にQtのQPainterとQPainterPathを使ってさっきの曲線を画面に描画してみた。
始点は、moveTo()で、制御点と終点はcubicTo()で指定してあげます。
これをコンパイルすれば、やはりなんとなく馬蹄形っぽい形が現れるはずである。
詳しい話はQt本家のwebサイトでAPIを確認してくだされ。
美大なので、俺を含めドロー系のソフトを使って絵を描いたり、デザイン作業を行っている方が多い。
そのドロー系のソフトによく使われる機能の一つにペンツールがある。
今回はあのペンツールによく使われるベジェ曲線について少々勉強してみた。
定義については本当は何と言うべきなのかはわからないのでテキトーに言っとくと、ベジェ曲線は始点といくつかの制御点と終点によって描画される数式だ。
さて、線というのは点の連なりによって画面上に描画される。
この点の座標位置をベジェ曲線の数式を用い、人間に分かりやすく数字で、ざっくばらんに表現する端末上のプチアプリを作ってみることにした。
以下が今回C言語で作ったプログラムのmain関数である。
int main(void){
float f = 0.0f;
while(f <= 1.1f ){
printf(" t が %0.1f のとき\n", f);
printf("Point X は %f\n", getpointX(f, 1.0, 2.0, 4.0, 6.0));
printf("Point Y は %f\n", getpointY(f, 5.0, 1.0, 1.0, 4.0));
f = f + 0.1f;
}
return 0;
}
ちなみに分かりやすくするため、”%0.1f”として小数点以下1位以降は表示されないようにした。
計算されないわけではないので、小数点以下の丸め誤差は発生します。気をつけようね。
これを実行すると、以下のような結果が出る。
t が 0.0 のとき
Point X は 1.000000
Point Y は 5.000000
t が 0.1 のとき
Point X は 1.329000
Point Y は 3.703000
t が 0.2 のとき
Point X は 1.712000
Point Y は 2.784000
t が 0.3 のとき
Point X は 2.143000
Point Y は 2.201000
t が 0.4 のとき
Point X は 2.616000
Point Y は 1.912000
t が 0.5 のとき
Point X は 3.125000
Point Y は 1.875000
t が 0.6 のとき
Point X は 3.664000
Point Y は 2.048000
t が 0.7 のとき
Point X は 4.227000
Point Y は 2.389000
t が 0.8 のとき
Point X は 4.808001
Point Y は 2.856000
t が 0.9 のとき
Point X は 5.401000
Point Y は 3.407001
t が 1.0 のとき
Point X は 6.000001
Point Y は 4.000001
結果から大体察してくださるだろうか。
tが0〜1までに至る間、点X,Yの座標位置を出力している。
この点の位置の情報を目に見える形で描画すればベジェ曲線の完成というわけだ。
物好きな方は上の点を、紙に鉛筆使って点をうち、線で結んでみると良いだろう。
(制御点も描くと理解が深まる。)
なんとなく、馬蹄形っぽいUの字をひっくり返したような曲線が描けるはずだ。
では、点XとYの位置を計算する関数getpointX()とgetpointY()を見てみよう。
float getpointX(float t, float x1, float x2,float x3,float x4)
{
float tp = 1 - t;
float x = (t * t * t * x4) + (3 * t * t * tp * x3)
+ (3 * t * tp * tp * x2) + (tp * tp * tp *x1);
return x;
}
float getpointY(float t,float y1, float y2,float y3,float y4)
{
float tp = 1 - t;
float y = (t * t * t * y4) + (3 * t * t * tp * y3)
+ (3 * t * t * tp * y2) + (tp * tp * tp *y1);
return y;
}
引数は、(パラメータ、 始点位置、 1個目の制御点位置、 2個目の制御点位置、 終点位置)である。
上手い人はもっとまとめてスッキリ書けるんだろうけど、数学の難しさとコーディングの難しさをごっちゃにしてはいけないと思うし、出来ないのでこうなった。
アルゴリズムは難しい公式をくだくだ述べるより、ソースを見るのが分かりやすいと思います。
以上で一応、ベジェ曲線を学んだメモは終わり。
最後にQtのQPainterとQPainterPathを使ってさっきの曲線を画面に描画してみた。
void Dialog::paintEvent(QPaintEvent *e)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
QPainterPath path;
path.moveTo(100, 500);
path.cubicTo(200, 100, 400, 100, 600, 400);
painter.setPen(QPen(Qt::black, 8));
painter.drawPath(path);
}
始点は、moveTo()で、制御点と終点はcubicTo()で指定してあげます。
これをコンパイルすれば、やはりなんとなく馬蹄形っぽい形が現れるはずである。
詳しい話はQt本家のwebサイトでAPIを確認してくだされ。
taishudoor at 02:28│Comments(0)│大周