


 
 
 
 
 
 
 |
前頁までは、幾何要素/表記要素フィーチャのスプラインや各種スプライン曲線について見てみました。今回はクロソイドについて見てみます。
幾何要素/表記要素|クロソイド |
※SXF Ver.3.1仕様書より |
パラメータ | 型 | 説明 | 範囲 |
Layer | Int | レイヤコード |
|
Color | Int | 色コード |
|
Type | Int | 線種コード |
|
line_width | Int | 線幅コード |
|
base_x | double | 配置基点X座標 |
double(64bits)の
範囲(有効桁15桁) |
base_y | double | 配置基点Y座標 |
double(64bits)の
範囲(有効桁15桁) |
parameter | double | パラメータ | 0<パラメータ<1.0×1015 |
direction | Int | 向きフラグ(0:反時計廻り,1:時計廻り) |
|
angle | double | 回転角 | 0≦回転角<360 |
start_length | double | 開始曲線長 | 0≦開始曲線長<1.0×1015 |
end_length | double | 終了曲線長 | 0≦終了曲線長<1.0×1015 |
備考
クロソイドとは、曲率が曲線長に比例して一様に増加する曲線のことである。螺旋の一種で、曲線半径をR、クロソイド曲線長をL、クロソイドのパラメータAとしたとき、その間に「R・L=A2=一定」の関係を持つ。
・回転角は配置基点を通過する接線の角度を示す。
・向きフラグを反時計廻りにすると接線に対して左側、時計廻りにすると右側のクロソイドを示す。
・開始曲線長および終了曲線長は配置基点からのクロソイドの長さを示す。
・開始曲線長から終了曲線長で示される区間を描画する。
・終了曲線長を開始曲線長よりも短くすると方向が逆になる。
・クロソイドの軌跡を示す座標は以下の式で導かれる。
|
とあります。
SXF仕様書では、以下の式で導かれる、とありますが、正直、何のことだかさっぱり分かりません。λ(u)って、一体どこから来たのだろうか?等。インターネットで検索をしてみると、Wikipediaでは、
 | x(l)= | ∫ | l | cos(θ2/2) dθ |
0 |
 | y(l)= | ∫ | l | sin(θ2/2) dθ |
0 |
但し、l=L/A (L:曲線長さ A:パラメータ)
とあり、こちらの方が分かりやすいですが、どうも想定結果とはならないようです。値の扱い方がおそらく違うのでしょう。ですので上記を踏まえると
 | x(u)=A√π | ∫ | u | cos(πt2/2) dt |
0 |
 | y(u)=A√π | ∫ | u | sin(πt2/2) dt |
0 |
但し、u=L/(A√π) (L:曲線長さ A:パラメータ)
という事になりそうです。∫=積分は、以下の式の面積値を示しますが、面積を算出するには、曲線式を何分割かして、それらの位置より、台形を想定して面積を加算していく台形公式、3点の放物線を想定して面積を加算していくシンプソン公式があり、精度的にはシンプソン公式の方が良い場合が多いようです。
シンプソン公式による積分近似値は
 | y= | ∫ | b | f(x)dx |
a |
とした場合、分割数をN(※偶数)とすると、
H=(b−a)/N
S≒H/3×{y0+4(y1+y3+y5+ … +yN-1)+2(y2+y4+y6+ … +yN-2)+yN}
になるとの事です。
それではクロソイド曲線のデータ構造を決めます。
UnitData.pas |
type
・・・
TDataClothoid = 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)
base_x: double ; // 配置基点X座標
base_y: double ; // 配置基点Y座標
Aval : double ; // パラメータ クロソイドのA値
Direction: Integer ; // 向き (0:反時計廻り,1:時計廻り)
Angle : double ; // 回転角[°]
start_length : double; // 開始曲線長 (0以上)
end_length : double; // 終了曲線長 (0以上)
sep : Integer ; // 分割数 (1〜1000)
end;
TFukugoZukeiDef = record // 構造化要素|複合図形定義
exf : Boolean ; // 存在フラグ(True:有り False:無し)
name : string ; // 複合図形名
Flag : Integer ; // 種別フラグ
cnt : Integer ; // 配置数
・・・
mClo : array of TDataClothoid; // 幾何要素|クロソイド
mCloN : Integer ; // 数
mFzk : array of TDataFukugoZukei; // 構造化要素|複合図形配置
mFzkN : Integer ; // 数
end;
TDataClass = class
public
{ Public 宣言 }
・・・
dClo : array of TDataClothoid; // 表記要素|クロソイド
dCloN : Integer ; // 数
・・・ |
データ追加用の関数は
function AddDataClothoid(s:string;lay,col,ltp,wid,dir,sp:integer;
bx,by,av,an,l1,l2:double) : Boolean; |
のようにします。線分・折線等と同様、最初に「データ追加先の複合図形名(幾何要素) null:用紙へ追加(表記要素)」を指定するようにしています。
UnitData.pas |
// クロソイド曲線 データ項目の追加登録
function TDataClass.AddDataClothoid(s:string;lay,col,ltp,wid,dir,sp:integer;bx,by,av,an,l1,l2:double) : Boolean;
var
m : 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 (dir <> 0) then dir := 1 ;
if (sp < 1) then sp := 1 ;
if (sp > 10000) then sp := 10000 ;
if (av <= 0.0) then exit ; // パラメータA値は 0より大
an := SetAngle(an);
if (l1 < 0.0) then l1 := 0.0 ;
if (l2 < 0.0) then l2 := 0.0 ;
if (Abs(l1-l2) < LIMIT10) then exit ; // 開始長さ = 終了長さ
if (s = '') then begin
// 用紙へ追加
if (AddDataOrder(-1,12,dCloN)) then begin
try
Inc(dCloN);
if ((dCloN mod 100) = 1) then SetLength(dClo, dCloN+99);
with dClo[dCloN-1] do begin
exf := True ;
Layer := lay ;
Color := col ;
Ltype := ltp ;
line_width := wid ;
base_x := bx ;
base_y := by ;
Aval := av ;
Direction := dir ;
Angle := an ;
start_length:= l1 ;
end_length := l2 ;
sep := sp ;
end;
Result := True ;
AddLayerCnt(lay,col,ltp,wid,-1);
except
Dec(dCloN);
Dec(dOrdN);
end;
end;
end
else begin
m := FZukeiNameCheck(0,s);
if (m = 0) then exit ; // 追加先の複合図形名は無いのでエラー
with fDef[m-1] do begin
if (AddDataOrder(m,12,mCloN)) then begin
try
Inc(mCloN);
if ((mCloN mod 100) = 1) then SetLength(mClo, mCloN+99);
with mClo[mCloN-1] do begin
exf := True ;
Layer := lay ;
Color := col ;
Ltype := ltp ;
line_width := wid ;
base_x := bx ;
base_y := by ;
Aval := av ;
Direction := dir ;
Angle := an ;
start_length:= l1 ;
end_length := l2 ;
sep := sp ;
end;
Result := True ;
AddLayerFCnt(lay,col,ltp,wid,-1);
except
Dec(mCloN);
Dec(mOrdN);
end;
end;
end;
end;
end; |
これでクロソイド曲線データの登録は出来るようになりました。
次にクロソイド曲線の描画についてです。上記で述べた通り、クロソイド曲線の式は
 | x(u)=A√π | ∫ | u | cos(πt2/2) dt |
0 |
 | y(u)=A√π | ∫ | u | sin(πt2/2) dt |
0 |
但し、u=L/(A√π) (L:曲線長さ A:パラメータ)
ですが、これに、回転・向き・配置基点、及び、変換行列を考慮せねばなりません。向きが時計回りの場合は単純にy座標にマイナスを掛ければ良いでしょう。シンプソン公式での分割数は 定数 CALC_SEP=100 として計算する事とします。また、計算誤差で線長が短くなってしまうため、最後の分割線の長さを補正して|end_length−start_length|になるようにしています。
UnitDataGraph.pas |
// クロソイド曲線の表示 サブ1
procedure DisplayClothoidSub1(var x,y:double;p:double);
begin
x := Cos(Pi*p*p/2.0);
y := Sin(Pi*p*p/2.0);
end;
// クロソイド曲線の表示 サブ2
procedure DisplayClothoidSub2(var x,y:double;A,l:double);
const
CALC_SEP = 100 ; // 計算時の分割数
var
aa,u,h,sx1,sy1,sx2,sy2,p,w1,w2,w3,w4 : double ;
i : integer ;
begin
aa := A*Sqrt(Pi);
u := l/aa ;
h := u/CALC_SEP;
sx1:= 0.0;
sy1:= 0.0;
sx2:= 0.0;
sy2:= 0.0;
i := 1;
while(i <= (CALC_SEP-1)) do begin
p := i*h ;
DisplayClothoidSub1(w1,w2,p);
sx1 := sx1 + 4.0*w1 ;
sy1 := sy1 + 4.0*w2 ;
i := i + 2;
end;
i := 2;
while(i <= (CALC_SEP-2)) do begin
p := i*h ;
DisplayClothoidSub1(w1,w2,p);
sx2 := sx2 + 2.0*w1 ;
sy2 := sy2 + 2.0*w2 ;
i := i + 2;
end;
DisplayClothoidSub1(w1,w2,0.0);
DisplayClothoidSub1(w3,w4,u);
x := aa*h*(w1 + sx1 + sx2 + w3)/3.0 ;
y := aa*h*(w2 + sy1 + sy2 + w4)/3.0 ;
end;
// クロソイド曲線の表示
procedure DisplayClothoid(lay,col,ltp,wid,dir,sp:integer;bx,by,av,an,l1,l2:double;t:TMatrix);
var
tr,tr1 : TMatrix ;
c,cc,l,w, i,k : integer ;
ww, d1 : double ;
fl : Boolean ;
ls,lt,ll,x1,y1,x2,y2,mx1,my1,mx2,my2,aa : double ;
begin
MtxRotD(tr, an);
MtxMove(tr1, bx,by);
tr := MtxMult(tr,tr1) ;
t := MtxMult(tr,t) ;
DisplayLayCol2(lay,col,ltp,wid, c,cc,l,w,ww); // 色・線種・線幅
//
fl := False ;
if (CData.zLtp[l-1].Segment = 0)
or(CData.zLtp[l-1].SpaceMax * mm_dot < 2.0)
or(CData.zLtp[l-1].SpaceMax * mm_dot < ww ) then
fl := True ;
k := 0 ;
d1:= 0.0 ;
ls:= (l2-l1)/sp ;
lt:= l1 ;
ll:= 0.0;
DisplayClothoidSub2(x1,y1,av,lt);
if (dir = 1) then y1 := -y1;
MtxXY(mx1,my1, x1,y1, t);
for i:=1 to sp do begin
lt := lt + ls;
DisplayClothoidSub2(x2,y2,av,lt);
if (dir = 1) then y2 := -y2;
if (i = sp) then begin
// 最終線の長さの補正
ll := Abs(l2-l1) - ll ;
aa := Angle(x2-x1,y2-y1);
x2 := x1 + ll*Cos(aa);
y2 := y1 + ll*Sin(aa);
end;
MtxXY(mx2,my2, x2,y2, t);
if (fl) then
DisplayLineSub1(mx1,my1,mx2,my2)
else
DisplayLineSub2(l,k,d1, mx1,my1,mx2,my2) ;
ll := ll + Dist(x1,y1,x2,y2);
x1 := x2 ;
y1 := y2 ;
mx1:= mx2 ;
my1:= my2 ;
end;
end; |
全体のクリッピングはどのような状態になるのか分かりませんので入れていません。また、パラメータや長さにおかしな値を入れると描画状態が乱れますので注意が必要です。

それでは、ここまでのテストプログラムです。実行ファイル、gdiplus.dll、gdipフォルダは入っていません。ソースのみです。
|
|
CAD装置(1)
CAD装置(2)
メディア
AutoCADの
DIESELマクロ
CSV
DXF
PCES
IGES
STEP
数学とCAD
CAD作ろ!
CADを考える
▲PREV
▼NEXT
M7
Jw_cad
|