|
前頁では、通過点を通るベジェ曲線について考えました。次に、通過点を通るBスプライン曲線について、ですが、Bスプライン曲線はベジェ曲線を利用して滑らかな曲線を描画しようというものなので、通過点を通るBスプライン曲線のプログラムを作成しても、ベジェ曲線とほぼ同じ曲線になります。
3次ベジェ曲線は、始点+制御点1+制御点2+終点の4点で構成されますが、Jw_cadでのベジェ曲線では、制御点を2個以上指定する事が出来ますが、制御点が3つの場合=5点で構成される場合は4次のベジェ曲線、6点で構成される場合は5次のベジェ曲線、つまり、n次ベジェ曲線は(n+1)点で構成され、その式は下記のように表現されます。
|
| n |
|
|
| P(t)= | Σ | Bi,n(t)Qi | (0≦t≦1) |
|
| i=0 |
|
|
このときのQi(i=0,1,2,…,n)は制御点を示し、Bi,n(t)は、Bernstein(バーンスタイン)基底関数と呼ばれ、一般形式は
| Bi,n(t)= | ( | n | ) | ti・(1-t)n-i (0≦t≦1) |
i |
と表し、これは下記に同じです。
| Bi,n(t)= | n! | ti・(1-t)n-i (0≦t≦1) |
|
(n-i)!×i! |
なお、
| n |
|
|
| Σ | Bi,n(t) = 1 | (0≦t≦1) |
| i=0 |
|
|
となる、との事です。
例えば、3次のベジェ曲線の場合は、
3! | t0・(1-t)3-0・Q0+ | 3! | t1・(1-t)3-1・Q1+ |
|
|
(3-0)!×0! | (3-1)!×1! |
| 3! | t2・(1-t)3-2・Q2+ | 3! | t3・(1-t)3-3・Q3 |
|
|
(3-2)!×2! | (3-3)!×3! |
3!=3×2×1=6、2!=2、1!=1、0!=1、ですので、
(1-t)3・Q0 + 3t(1-t)2・Q1 + 3t2・(1-t)・Q2 + t3・Q3
となりますから、これまで出てきた式と同じであることが分かります。
これをプログラミングすれば簡単にn次ベジェ曲線の描画は出来るようになります。繰り返し(ループ)をすれば良いだけです。
上記はベジェ曲線ですが、Bスプライン曲線は、というと、
|
| n |
|
|
| P(t)= | Σ | Ni,M(t)Qi | (0≦t≦1) |
|
| i=0 |
|
|
のように記述します。Q0,Q1,…,Qn のn+1個の制御点からなるn次Bスプライン曲線((M-1)次Bスプライン曲線)で、Ni,M(t) をBスプライン基底関数と呼び、これは下記の式で求める事が出来ます。
|
| t−ti |
| ti+M−t |
|
| Ni,M(t)= |
| Ni,M-1(t)+ |
| Ni+1,M-1(t) |
|
| ti+M-1−ti |
| ti+M−ti+1 |
|
ただし
Ni,1(t)=1 (ti≦t<ti+1)
Ni,1(t)=0 (上記以外)
ti 、ti+M 等はノットと呼ばれ、これの集まりをノットベクトルTと呼びます。
T=[t0 t1 t2 ・・・ tM+N-1 ]
N:制御点数
M:階数(M-1次)
例えば3次Bスプライン曲線の場合は、n=3(次)、N=4(点)、M=4(階)、となりますので、ノットベクトルは
T=[t0 t1 t2 ・・・ t7 ]
となりノットの数は8個となります。
このノットベクトルを
T=[-3 -2 -1 0 1 2 3 4]
のように均一にした場合を、ユニフォームBスプライン曲線(均一Bスプライン曲線、一様Bスプライン曲線)と呼びます。また、
T=[0 0 0 0.5 0.5 1 1 1]
のように不均一にした場合を、ノンユニフォームBスプライン曲線(不均一Bスプライン曲線、非一様スプライン曲線)と呼びます。ノンユニフォームのほうが色々な指定が出来る事になるので、より柔軟性があるという事になります。
Bスプライン曲線、ユニフォーム/ノンユニフォームのBスプライン曲線では、円・円弧を表現することは出来ませんが、制御点に重みを指定する事によって実現させることが出来ます。これをレーショナルBスプライン曲線(有理Bスプライン曲線)と呼びます。式は下記のようになります。
|
| n |
|
|
| Σ | Ni,M(t)ωiQi |
|
| i=0 |
|
| P(t)= |
|
|
| n |
|
|
| Σ | Ni,M(t)ωi |
|
| i=0 |
|
ノットベクトルが均一な場合を、ユニフォームレーショナルBスプライン曲線(均一有理Bスプライン曲線、一様有理Bスプライン曲線)と呼び、ノットベクトルが不均一な場合を、ノンユニフォームレーショナルBスプライン曲線(不均一有理Bスプライン曲線、非一様有理Bスプライン曲線;NURBS)と呼びます。
ノットベクトルを
T=[-3 -2 -1 0 1 2 3 4]
とした4階のユニフォームBスプライン曲線を考えます。
|
| 3 |
|
|
| P(t)= | Σ | Ni,4(t)Qi | (0≦t≦1) |
|
| i=0 |
|
|
ですから、N0,4(t)、N1,4(t)、N2,4(t)、N3,4(t)、の値が分かれば良いのが分かります。
まずは、
N0,1(t)は、(t0≦t<t1)→(-3≦t<-2)で tは(0≦t≦1)の範囲ですからこの範囲を満足しないので、N0,1(t)=0 となります。同様に、
N1,1(t)=0 (t1≦t<t2 : -2≦t<-1 ×)
N2,1(t)=0 (t2≦t<t3 : -1≦t<0 ×)
N3,1(t)=1 (t3≦t<t4 : 0≦t<1 ○)
N4,1(t)=0 (t4≦t<t5 : 1≦t<2 ×)
N5,1(t)=0 (t5≦t<t6 : 2≦t<3 ×)
N6,1(t)=0 (t6≦t<t7 : 3≦t<4 ×)
となります。基底関数は
|
N3,1=1
/\
N2,2 N3,2
/\/\
N1,3 N2,3 N3,3
/\ /\ /\
N0,4 N1,4 N2,4 N3,4 | |
1階
2階
3階
4階 |
というピラミッド状となりますので、上記だけを計算すればよいです。他のものも計算しても構いませんが「0」になります。それでは2階の計算です。
|
| t−t2 |
| t4−t |
|
| N2,2(t)= |
| N2,1(t)+ |
| N3,1(t) |
|
| t3−t2 |
| t4−t3 |
|
|
| 1−t |
|
|
|
| = |
| N3,1(t) | = | 1−t |
|
| 1−0 |
|
|
|
|
| t−t3 |
| t5−t |
|
| N3,2(t)= |
| N3,1(t)+ |
| N4,1(t) |
|
| t4−t3 |
| t5−t4 |
|
|
| t−0 |
|
|
|
| = |
| N3,1(t) | = | t |
|
| 1−0 |
|
|
|
次に3階の計算です。
|
| t−t1 |
| t4−t |
|
| N1,3(t)= |
| N1,2(t)+ |
| N2,2(t) |
|
| t3−t1 |
| t4−t2 |
|
|
| 1−t |
|
| (1−t)2 |
| = |
| N2,2(t) | = |
|
|
| 1−(-1) |
|
| 2 |
|
| t−t2 |
| t5−t |
|
| N2,3(t)= |
| N2,2(t)+ |
| N3,2(t) |
|
| t4−t2 |
| t5−t3 |
|
|
| t−(-1) |
| 2−t |
|
| = |
| N2,2(t)+ |
| N3,2(t) |
|
| 1−(-1) |
| 2−0 |
|
|
| (t+1)(1−t) |
| (2−t)t |
| = |
| + |
|
|
| 2 |
| 2 |
|
| t−t3 |
| t6−t |
|
| N3,3(t)= |
| N3,2(t)+ |
| N4,2(t) |
|
| t5−t3 |
| t6−t4 |
|
|
| t−0 |
|
| t2 |
| = |
| N2,2(t) | = |
|
|
| 2−0 |
|
| 2 |
そして4階の計算です。
|
| t−t0 |
| t4−t |
|
| N0,4(t)= |
| N0,3(t)+ |
| N1,3(t) |
|
| t3−t0 |
| t4−t1 |
|
|
| 1−t |
|
| (1−t)3 |
| = |
| N1,3(t) | = |
|
|
| 1−(-2) |
|
| 6 |
|
| t−t1 |
| t5−t |
|
| N1,4(t)= |
| N1,3(t)+ |
| N2,3(t) |
|
| t4−t1 |
| t5−t2 |
|
|
| t−(-2) |
| 2−t |
|
| = |
| N1,3(t)+ |
| N2,3(t) |
|
| 1−(-2) |
| 2−(-1) |
|
|
| t+2 |
| (1−t)2 |
| 2−t |
| (t+1)(1−t)+(2−t)t |
| = |
| ・ |
| + |
| ・ |
|
|
| 3 |
| 2 |
| 3 |
| 2 |
|
| (t+2)(1−t)2+(2−t){(t+1)(1−t)+(2−t)t} |
| = |
|
|
| 6 |
|
| (t+2)(1−2t+t2)+(2−t)(1−t2)+(2−t)2t |
| = |
|
|
| 6 |
|
| (t+2−2t2-4t+t3+2t2)+(2-t−2t2+t3)+(4t-4t2+t3) |
| = |
|
|
| 6 |
|
| 3t3−6t2+4 |
| = |
|
|
| 6 |
|
| t−t2 |
| t6−t |
|
| N2,4(t)= |
| N2,3(t)+ |
| N3,3(t) |
|
| t5−t2 |
| t6−t3 |
|
|
| t−(-1) |
| 3−t |
|
| = |
| N2,3(t)+ |
| N3,3(t) |
|
| 2−(-1) |
| 3−0 |
|
|
| t+1 |
| (1−t2)+(2t-t2) |
| 3−t |
| t2 |
| = |
| ・ |
| + |
| ・ |
|
|
| 3 |
| 2 |
| 3 |
| 2 |
|
| (t+1){(1−t2)+(2t-t2)}+(3−t)t2 |
| = |
|
|
| 6 |
|
| (t+1)(1−t2)+(t+1)(2t-t2)+(3t2−t3) |
| = |
|
|
| 6 |
|
| (t+1−t3−t2)+(2t2+2t-t3-t2)+(3t2−t3) |
| = |
|
|
| 6 |
|
| −3t3+3t2+3t+1 |
| = |
|
|
| 6 |
|
| t−t3 |
| t7−t |
|
| N3,4(t)= |
| N3,3(t)+ |
| N4,3(t) |
|
| t6−t3 |
| t7−t4 |
|
|
| t−0 |
|
| = |
| N3,3(t) |
|
| 3−0 |
|
|
| t |
| t2 |
| = |
| ・ |
|
|
| 3 |
| 2 |
|
| t3 |
| = |
|
|
| 6 |
となります。
P(t)=N0,4(t)Q0 + N1,4(t)Q1 + N2,4(t)Q2 + N3,4(t)Q3
ですので、
先に記述した3次Bスプラインの式
P(t) = N0(t)*Q0 + N1(t)*Q1 + N2(t)*Q2 + N3(t)*Q3
N0(t)=1/6*(1-t)3
N1(t)=1/2*t3−t2+2/3
N2(t)=-1/2*t3+1/2*t2+1/2*t+1/6
N3(t)=1/6*t3
と同じであることが分かります。
それでは、ノンユニフォームBスプライン曲線の場合ですが、これは先に書いたように、ノットベクトルを不均一に指定する、という事になりますが、CADソフトの場合は、指定点間の距離を指定する場合が多いようです。4階(3次)Bスプラインの場合は、制御点4点でノットは8個になりますから
T=[0 0 0 d1 d2 d3 d3 d3]
d1:指定点1〜2の距離 d2:点1〜3の距離 d3:点1〜4の距離
のように指定します。
Bスプライン基底関数は上記の
|
| t−ti |
| ti+M−t |
|
| Ni,M(t)= |
| Ni,M-1(t)+ |
| Ni+1,M-1(t) |
|
| ti+M-1−ti |
| ti+M−ti+1 |
|
Ni,1(t)=1 (ti≦t<ti+1)
Ni,1(t)=0 (上記以外)
で算出出来ますが、前回に書いたように、隣り合う曲線との接線ベクトルが同じになる・開曲線の場合は曲率が0になる、という条件が必要になりますが、M階のBスプライン関数の微係数は
| ・ | { | Ni,M-1(t) |
| Ni+1,M-1(t) | } |
| Ni,M(t)=(M-1) |
| + |
|
|
| ti+M-1−ti |
| ti+M−ti+1 |
となり、更に、M階Bスプライン関数のr階微係数 N(r)i,M(t)は、
|
| { | N(r-1)i,M-1(t) |
| N(r-1)i+1,M-1(t) | } |
| N(r)i,M(t)=(M-1) |
| + |
|
|
| ti+M-1−ti |
| ti+M−ti+1 |
になるとの事です。
それらより連立方程式→行列式を組み立てて、解を出して、制御点を計算します。制御点が計算できれば、あとは、
P(t) = N0,4(t)*Q0 + N1,4(t)*Q1 + N2,4(t)*Q2 + N3,4*Q3
で、1区間ずつ、t値を変化させて補間点を計算し結んで行けば、ノンユニフォームBスプライン曲線を描画する事が出来ます。
UnitData.pas |
type
・・・
TDataSpline = record // 独自|スプライン曲線
exf : Boolean ; // 存在フラグ(True:有り False:無し)
Layer : Integer ; // レイヤ(1〜256)
Color : Integer ; // 色 (0:レイヤ色 1〜256)
Ltype : Integer ; // 線種 (0:レイヤ線種 1〜32)
line_width: Integer ; // 線幅 (0:レイヤ線幅 1〜16)
Stype : Integer ; // 曲線タイプ (1:C 2:ベジェ 3:NUBS)
Aval : double ; // CスプラインのA値
open_close : Integer; // 開閉区分:0:閉 1:開
sep : Integer ; // 頂点間分割数
Number : Integer ; // 頂点数
X : array of double ; // 頂点X座標
Y : array of double ; // 頂点Y座標
end;
TFukugoZukeiDef = record // 構造化要素|複合図形定義
exf : Boolean ; // 存在フラグ(True:有り False:無し)
name : string ; // 複合図形名
Flag : Integer ; // 種別フラグ
cnt : Integer ; // 配置数
・・・
mSpl : array of TDataSpline; // 幾何要素|スプライン曲線
mSplN : Integer ; // 数
mFzk : array of TDataFukugoZukei; // 構造化要素|複合図形配置
mFzkN : Integer ; // 数
end;
TDataClass = class
public
{ Public 宣言 }
・・・
dSpl : array of TDataSpline; // 表記要素|スプライン曲線
dSplN : Integer ; // 数
・・・ |
UnitData.pas |
// スプライン曲線 データ項目の追加登録
function TDataClass.AddDataSpline(s:string;lay,col,ltp,wid,stp,sp,num:integer;av:double;vx,vy:array of double) : Boolean;
var
m,i : integer ;
oc : integer ;
begin
Result := False;
if (lay < 1) or (lay > zLayN) then lay := 1 ;
if (col < 0) or (col > zColN) then col := 0 ;
if (ltp < 0) or (ltp > zLtpN) then ltp := 0 ;
if (wid < 0) or (wid > zWidN) then wid := 0 ;
if (stp < 1) or (stp > 3) then stp := 1 ;
if (sp < 1) then sp := 1 ;
if (sp > 1000) then sp := 1000 ;
if (num <= 2) then exit ;
・・・・
end; |
簡単なテストを Unit1.pas に記述して、再構築(コンパイル)し実行してみます。画面右側の「●」付近にある、点線で表示しているのは前々回のカーディナルスプライン、赤色の破線で表示しているのが前回のベジェ曲線補間、青色で表示しているのが今回のNUBS補間です。
それでは、ここまでのテストプログラムです。実行ファイル、gdiplus.dll、gdipフォルダは入っていません。ソースのみです。
|
|
CAD装置(1)
CAD装置(2)
メディア
AutoCADの
DIESELマクロ
CSV
DXF
PCES
IGES
STEP
数学とCAD
CAD作ろ!
CADを考える
▲PREV
▼NEXT
M7
Jw_cad
|