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

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

プログラミングについて
ホームページについて
キャドについて
電子カタログについて
書籍・雑誌
イベント
リンク集
CADを考える:楕円弧
前頁では、幾何要素/表記要素フィーチャの楕円について見ましたので今回は楕円弧について見てみます。
 
幾何要素/表記要素|楕円弧
パラメータ説明範囲
LayerIntレイヤコード
ColorInt色コード
TypeInt線種コード
line_widthInt線幅コード
Center_xdouble中心X座標 double(64bits)の
範囲(有効桁15桁)
Center_ydouble中心Y座標 double(64bits)の
範囲(有効桁15桁)
Radius_xdoubleX方向半径0<半径<1.0×1015
Radius_ydoubleY方向半径0<半径<1.0×1015
DirectionInt向きフラグ(0:反時計廻り,1:時計廻り)
rotation_angledouble回転角0≦回転角<360
start_angledouble始角0≦始角<360
end_angledouble終角0≦終角<360
備考
 
SXF Ver.3.1実装規約では線分等同様、楕円弧について何も無さそうです。
 
それでは楕円弧のデータ構造を決めます。
UnitData.pas
type
 ・・・
 TDataEllipseArc = 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)
  Center_x : double ;   // 中心点X座標
  Center_y : double ;   // 中心点Y座標
  Radius_x : double ;   // X方向半径
  Radius_y : double ;   // Y方向半径
  Direction : Integer ;  // 向き (0:反時計廻り,1:時計廻り)
  rotation_angle:double ; // 回転角[°]
  start_angle : double ;  // 始角[°]
  end_angle : double ;   // 終角[°]
 end;
 
 TFukugoZukeiDef = record  // 構造化要素|複合図形定義
  exf : Boolean ;     // 存在フラグ(True:有り False:無し)
  name : string ;     // 複合図形名
  Flag : Integer ;     // 種別フラグ
  cnt : Integer ;     // 配置数
  ・・・
  mEAr : array of TDataEllipse;   // 幾何要素|楕円弧
  mEArN : Integer ;         // 数
  mFzk : array of TDataFukugoZukei; // 構造化要素|複合図形配置
  mFzkN : Integer ;         // 数
 end;
 
 TDataClass = class
  public
  { Public 宣言 }
  ・・・
  dEAr : array of TDataEllipse;   // 表記要素|楕円弧
  dEArN: Integer ;         // 数
  ・・・
 
データ追加用の関数は
function AddDataEllipseArc(s:string;lay,col,ltp,wid,dir:integer;cx,cy,rx,ry,ra,sa,ea:double) : Boolean;
のようにします。線分等と同様、最初に「データ追加先の複合図形名(幾何要素) null:用紙へ追加(表記要素)」を指定するようにしています。
 
UnitData.pas
// 楕円 データ項目の追加登録
function TDataClass.AddDataEllipseArc(s:string;lay,col,ltp,wid,dir:integer;cx,cy,rx,ry,ra,sa,ea: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 (rx < LIMIT10)or(ry < LIMIT10) then exit ; // 半径が <= 0
 if (dir <> 0) then dir := 1 ;
 ra := SetAngle(ra);
 sa := SetAngle(sa);
 ea := SetAngle(ea);
 if (Abs(ea-sa) < LIMIT10) then exit ; // 始角 = 終角
 
 if (s = '') then begin
  // 用紙へ追加
  if (AddDataOrder(-1,7,dEArN)) then begin
   try
    Inc(dEArN);
    if ((dEArN mod 200) = 1) then SetLength(dEAr, dEArN+199);
    with dEAr[dEArN-1] do begin
     exf := True ;
     Layer := lay ;
     Color := col ;
     Ltype := ltp ;
     line_width := wid ;
     Center_x := cx ;
     Center_y := cy ;
     Radius_x := rx ;
     Radius_y := ry ;
     Direction := dir ;
     rotation_angle := ra ;
     start_angle := sa ;
     end_angle := ea ;
    end;
    Result := True ;
    AddLayerCnt(lay,col,ltp,wid,-1);
   except
    Dec(dEArN);
    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,7,mEArN)) then begin
    try
     Inc(mEArN);
     if ((mEArN mod 200) = 1) then SetLength(mEAr, mEArN+199);
     with mEAr[mEArN-1] do begin
      exf := True ;
      Layer := lay ;
      Color := col ;
      Ltype := ltp ;
      line_width := wid ;
      Center_x := cx ;
      Center_y := cy ;
      Radius_x := rx ;
      Radius_y := ry ;
      Direction := dir ;
      rotation_angle := ra ;
      start_angle := sa ;
      end_angle := ea ;
     end;
     Result := True ;
     AddLayerFCnt(lay,col,ltp,wid,-1);
    except
     Dec(mEArN);
     Dec(mOrdN);
    end;
   end;
  end;
 end;
end;
 
さて、これで楕円弧データの登録は出来るようになりました。
 
次は、楕円弧の描画についてです。
楕円弧は、円弧の描画・楕円の描画を組み合わせたようなものです。楕円における始角・終角は、楕円が円を垂直方向に伸縮変形(扁平)したようなものだと想定した時の、円の始角・終角となります。これは、
楕円式
  x=cx+rx*Cosθ
  y=cy+ry*Sinθ (θ:0〜2π)
でのθの値に等しいので、円弧のロジックがそのまま利用出来ます。
 
UnitDataGraph.pas
// 楕円弧の表示
procedure DisplayEllipseArc(lay,col,ltp,wid,dir:integer;px,py,rx,ry,ra,sa,ea:double;t:TMatrix);
const
 ARC_LENGTH = 15.0 ; // 補間線分長さ[dot相当値]
 ARC_MIN = 8 ;
 ARC_MAX = 360 ;
var
 c,cc,l,w, i,j : integer ;
 ww, d1, a,aa,n, x1,y1,x2,y2,x3,y3,x4,y4 : double ;
 fl : Boolean ;
 tr,tr1 : TMatrix ;
begin
 // 楕円・クリッピングチェック
 MtxMove(tr, -px,-py);
 MtxRotD(tr1,ra);
 tr := MtxMult(tr,tr1) ;
 MtxMove(tr1, px,py);
 tr := MtxMult(tr,tr1) ;
 t := MtxMult(tr,t) ;
 x1 := px-rx; y1 := py-ry; MtxXY(x1,y1, x1,y1, t);
 x2 := px+rx; y2 := py-ry; MtxXY(x2,y2, x2,y2, t);
 x3 := px+rx; y3 := py+ry; MtxXY(x3,y3, x3,y3, t);
 x4 := px-rx; y4 := py+ry; MtxXY(x4,y4, x4,y4, t);
 if (Clip4Point(x1,y1,x2,y2,x3,y3,x4,y4, WndX1,WndY1,WndX2,WndY2) = 2) then exit;
 
 if (dir <> 0) then swapD(sa,ea);
 aa := ea - sa ;
 if (aa < 0.0) then aa := aa + 360.0 ;
 if (dir <> 0) then begin
  swapD(sa,ea);
  aa := -aa ;
 end;
 
 x1 := 0.0 ;
 y1 := 0.0 ;
 x2 := rx*Cos(0.25*Pi) ;
 y2 := ry*Sin(0.25*Pi) ;
 MtxXY(x1,y1, x1,y1, t);
 MtxXY(x2,y2, x2,y2, t);
 d1 := Dist(x1,y1,x2,y2);
 a := ARC_LENGTH / (d1 * mm_dot) ;
 n := Int(Abs(aa)/180.0*Pi/a) ;
 if (n < ARC_MIN) then n := ARC_MIN ;
 if (n > ARC_MAX) then n := ARC_MAX ;
 a := aa/180.0*Pi / n ;
 
 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 ;
 
 i := 0 ;
 d1 := 0.0 ;
 aa := sa/180.0*Pi;
 x1 := px + rx*Cos(aa);
 y1 := py + ry*Sin(aa);
 MtxXY(x1,y1, x1,y1, t);
 for j:=1 to Round(n) do begin
  aa := aa + a;
  x2 := px + rx*Cos(aa);
  y2 := py + ry*Sin(aa);
  MtxXY(x2,y2, x2,y2, t);
  if (fl) then
   DisplayLineSub1(x1,y1,x2,y2)
  else
   DisplayLineSub2(l,i,d1, x1,y1,x2,y2) ;
  x1 := x2 ;
  y1 := y2 ;
 end;
end;
円弧の表示は、以前は向きが時計回りの場合には始角と終角を入れ替えて終角から描画開始していましたが、今回は、入れ替えを元に戻して始角から描画開始するようにしました。楕円弧の表示も同じです。
 
では簡単な楕円描画のテストをしてみます。
Unit1.pas
・・・
// 楕円弧データ登録テスト
col := 1 ;
ltp := 1 ;
wid := 1 ;
for i:=1 to 10 do begin
 lx1 := i*10 ;
 ly1 := i*5 ;
 CData.AddDataEllipseArc('', 1,col,ltp,wid,0, 200.0,00.0,lx1,ly1,30.0,0.0,180.0);
 CData.AddDataEllipseArc('部分図A', 1,col,ltp,wid,1, 200.0,0.0,lx1,ly1,30.0,0.0,180.0);
 Inc(col);
 if (col > CData.zColN) then col := 1 ;
 Inc(ltp);
 if (ltp > CData.zLtpN) then ltp := 1 ;
 Inc(wid);
 if (wid > CData.zWidN) then wid := 1 ;
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.