AFsoft WebSite(エーエフソフト・ウェブサイト)
 

オペレーティング・システムについて

プログラミングについて
ホームページについて
キャドについて
電子カタログについて
書籍・雑誌
イベント
リンク集
CADを考える:クロソイド
前頁までは、幾何要素/表記要素フィーチャのスプラインや各種スプライン曲線について見てみました。今回はクロソイドについて見てみます。
 
幾何要素/表記要素|クロソイド

※SXF Ver.3.1仕様書より
パラメータ説明範囲
LayerIntレイヤコード
ColorInt色コード
TypeInt線種コード
line_widthInt線幅コード
base_xdouble配置基点X座標 double(64bits)の
範囲(有効桁15桁)
base_ydouble配置基点Y座標 double(64bits)の
範囲(有効桁15桁)
parameterdoubleパラメータ0<パラメータ<1.0×1015
directionInt向きフラグ(0:反時計廻り,1:時計廻り)
angledouble回転角0≦回転角<360
start_lengthdouble開始曲線長0≦開始曲線長<1.0×1015
end_lengthdouble終了曲線長0≦終了曲線長<1.0×1015
備考
クロソイドとは、曲率が曲線長に比例して一様に増加する曲線のことである。螺旋の一種で、曲線半径をR、クロソイド曲線長をL、クロソイドのパラメータAとしたとき、その間に「R・L=A2=一定」の関係を持つ。
・回転角は配置基点を通過する接線の角度を示す。
・向きフラグを反時計廻りにすると接線に対して左側、時計廻りにすると右側のクロソイドを示す。
・開始曲線長および終了曲線長は配置基点からのクロソイドの長さを示す。
・開始曲線長から終了曲線長で示される区間を描画する。
・終了曲線長を開始曲線長よりも短くすると方向が逆になる。
・クロソイドの軌跡を示す座標は以下の式で導かれる。
とあります。
 
SXF仕様書では、以下の式で導かれる、とありますが、正直、何のことだかさっぱり分かりません。λ(u)って、一体どこから来たのだろうか?等。インターネットで検索をしてみると、Wikipediaでは、
x(l)=lcos(θ2/2) dθ
0
y(l)=lsin(θ2/2) dθ
0
    但し、l=L/A (L:曲線長さ A:パラメータ)
 
とあり、こちらの方が分かりやすいですが、どうも想定結果とはならないようです。値の扱い方がおそらく違うのでしょう。ですので上記を踏まえると
x(u)=A√πucos(πt2/2) dt
0
y(u)=A√πusin(πt2/2) dt
0
    但し、u=L/(A√π) (L:曲線長さ A:パラメータ)
 
という事になりそうです。∫=積分は、以下の式の面積値を示しますが、面積を算出するには、曲線式を何分割かして、それらの位置より、台形を想定して面積を加算していく台形公式、3点の放物線を想定して面積を加算していくシンプソン公式があり、精度的にはシンプソン公式の方が良い場合が多いようです。
シンプソン公式による積分近似値は
y=bf(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√πucos(πt2/2) dt
0
y(u)=A√πusin(π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
 
お問い合わせ 
本サイトはリンクフリーです
リンクバナー
(C)Copyright 1999-2015 By AFsoft All Rights Reserved.