|
前頁では、幾何要素/表記要素フィーチャの楕円について見ましたので今回は楕円弧について見てみます。
幾何要素/表記要素|楕円弧 |
|
パラメータ | 型 | 説明 | 範囲 |
Layer | Int | レイヤコード |
|
Color | Int | 色コード |
|
Type | Int | 線種コード |
|
line_width | Int | 線幅コード |
|
Center_x | double | 中心X座標 |
double(64bits)の
範囲(有効桁15桁) |
Center_y | double | 中心Y座標 |
double(64bits)の
範囲(有効桁15桁) |
Radius_x | double | X方向半径 | 0<半径<1.0×1015 |
Radius_y | double | Y方向半径 | 0<半径<1.0×1015 |
Direction | Int | 向きフラグ(0:反時計廻り,1:時計廻り) |
|
rotation_angle | double | 回転角 | 0≦回転角<360 |
start_angle | double | 始角 | 0≦始角<360 |
end_angle | double | 終角 | 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
|