http://rpen.blogspot.jp/2007/05/blog-post.html
まず、上記のソースコードを参考に作ってみました。
制御点が4個の場合は正常に動くのですが10個にすると形がおかしくなります。
そもそもベジェ線とはそういうものなのか、単純に作り方が悪いのか。
#module #deffunc 曲線計算 array x,array y,int s,double 平均化係数,array arr 制御点数=length(x) 制御点数_1=制御点数-1;終点は含めない。 制御点数_2=制御点数-2;端点は含めない。 定数=double(制御点数)-1.0 arr.0.0=double(x.0) arr.1.0=double(y.0) ct=1.0/s t=ct k=1.0 終点x=double(x.(制御点数_1)) 終点y=double(y.(制御点数_1)) repeat s, 1 t +ct k -ct lx=double(x.0) ly=double(y.0) 一時x=終点x 一時y=終点y repeat 制御点数_1 lx*k ly*k 一時x*t 一時y*t loop lx+一時x ly+一時y repeat 制御点数_2,1;端点は含めない。 一時=定数 repeat 制御点数_1-cnt 一時*k loop repeat cnt 一時*t loop lx+(一時*x.cnt) ly+(一時*y.cnt) loop arr.0.cnt=lx arr.1.cnt=ly loop return #global #uselib "winmm.dll" #cfunc timeGetTime "timeGetTime" screen 0,1000,500 制御点数=105;曲線を制御する支点の数 品質=200;曲線の品質 平均化係数=0.25;どの程度平均化するか 試行回数=100;時間測定の精度 円半径=5;描画用 ddim arr,2,品質;曲線の計算結果を代入する変数 ;とりあえずランダムに作る。 repeat 制御点数 x.cnt=(1000/制御点数)*cnt y.cnt=rnd(480)+10 loop ;処理時間を測定。 開始時間=timeGetTime() repeat 試行回数 曲線計算 x,y,品質,平均化係数,arr loop title "1回あたり"+(double(timeGetTime()-開始時間)/試行回数)+"ms" repeat getkey k mx=mousex my=mousey redraw 0 ;ここから描画やドラッグの処理。 color 255,255,255:boxf color 0,0,0 if k=1 &k_bac=0:フラグ=0 repeat 制御点数 circle x.cnt-円半径,y.cnt-円半径,x.cnt+円半径,y.cnt+円半径 if limit(mx,x.cnt-円半径*4,x.cnt+円半径*4)=mx & limit(my,y.cnt-円半径*4,y.cnt+円半径*4)=my & k=1 &k_bac=0:クリックct=cnt:フラグ=1 loop if k=1&フラグ=1:{ x.クリックct=mx y.クリックct=my } ;ここまで。 曲線計算 x,y,品質,平均化係数,arr;曲線を計算 ;描画 pos arr.0.0,arr.1.0 repeat 品質 line arr.0.cnt,arr.1.cnt loop redraw 1 k_bac=k await loop
もう1種類、独自にやってみたのですが処理に時間がかかります。
2段階にわけて処理をしているのが原因だと思いますが、
これをまとめるにはどうすればいいか・・・
#module #deffunc 曲線計算 array x,array y,int s,double 平均化係数,array arr 制御点数=length(x) 制御点数_1=制御点数-1 平均化範囲=int(平均化係数*s) t=double(制御点数)/s ddim arr2,2,s ;間を直線的に補完して一時変数にいれる。 repeat s ct_0=t*cnt ct_1=int(ct_0) ct_2=ct_0-ct_1 ct_3=1.0-ct_2 arr2.0.cnt=(ct_3*x.ct_1)+(ct_2*x.limit(ct_1+1,0,制御点数_1)) arr2.1.cnt=(ct_3*y.ct_1)+(ct_2*y.limit(ct_1+1,0,制御点数_1)) loop ;端点だけ平均化を適用させない。 arr.0.0=double(x.0) arr.1.0=double(y.0) arr.0.(s-1)=double(x.制御点数_1) arr.1.(s-1)=double(y.制御点数_1) ;一時変数の値を平均化してarrに代入。 repeat s-2,1 ct=cnt arr.0.ct=0.0 arr.1.ct=0.0 repeat 平均化範囲 arr.0.ct+arr2.0.limit(ct-cnt,0,s-1)+arr2.0.limit(ct+cnt,0,s-1) arr.1.ct+arr2.1.limit(ct-cnt,0,s-1)+arr2.1.limit(ct+cnt,0,s-1) loop arr.0.ct/(平均化範囲*2) arr.1.ct/(平均化範囲*2) ;dialog ""+arr.0.ct+","+arr.1.ct+"" loop return #global #uselib "winmm.dll" #cfunc timeGetTime "timeGetTime" screen 0,1000,500 制御点数=4;曲線を制御する支点の数 品質=200;曲線の品質 平均化係数=0.25;どの程度平均化するか 試行回数=100;時間測定の精度 円半径=5;描画用 ddim arr,2,品質;曲線の計算結果を代入する変数 ;とりあえずランダムに作る。 repeat 制御点数 x.cnt=(1000/制御点数)*cnt y.cnt=rnd(480)+10 loop ;処理時間を測定。 開始時間=timeGetTime() repeat 試行回数 曲線計算 x,y,品質,平均化係数,arr loop title "1回あたり"+(double(timeGetTime()-開始時間)/試行回数)+"ms" repeat getkey k mx=mousex my=mousey redraw 0 ;ここから描画やドラッグの処理。 color 255,255,255:boxf color 0,0,0 if k=1 &k_bac=0:フラグ=0 repeat 制御点数 circle x.cnt-円半径,y.cnt-円半径,x.cnt+円半径,y.cnt+円半径 if limit(mx,x.cnt-円半径*4,x.cnt+円半径*4)=mx & limit(my,y.cnt-円半径*4,y.cnt+円半径*4)=my & k=1 &k_bac=0:クリックct=cnt:フラグ=1 loop if k=1&フラグ=1:{ x.クリックct=mx y.クリックct=my } ;ここまで。 曲線計算 x,y,品質,平均化係数,arr;曲線を計算 ;描画 pos arr.0.0,arr.1.0 repeat 品質 line arr.0.cnt,arr.1.cnt loop redraw 1 k_bac=k await loop
1つめのソースコードを改良してキレイなベジェ線を書くのが理想的なのですが、
自分では間違いを見つけることができませんでした。
申し訳ありませんが、皆様の知恵をお貸しいただけないでしょうか。
宜しくお願いします。