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

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

プログラミングについて
ホームページについて
キャドについて
電子カタログについて
書籍・雑誌
イベント
リンク集
CADを考える:矢印
前頁は、シンボル、構造化要素の「既定義シンボル」について述べました。SXF仕様書の次は構造化要素の「直線寸法」となっていますが、その前に、寸法線等で利用する矢印について考えておきます。
 
SXF仕様書では、矢印データ要素というものはありません。寸法線データ要素でも「矢印コード」とあるだけです。矢印の形状は固定化されていますが。しかしながら幾つかのCADソフトでは、矢印データ要素というものを実装しているものはあります。例えば、Jw_cadでは点マーカとして実装しています。またAutoCADでは、ブロック図形として実装しているようです。矢印形状は寸法線だけで使う訳ではありません。単なる矢印の線というのは、例えば、フローチャートやグラフ等でよく利用します。
 
例えば、矢印線作図コマンドを作った場合、線分と先端の矢印を作図させる事になりますが、矢印が「<」であるとすれば、線分2本を作図すれば可能です。「○」の場合には円を作図すれば可能です。が、最初から矢印データ要素というものがあれば、それを利用したほうが遥かに簡単です。また、矢印を使うコマンドが他にも幾つかある場合には、プログラミングの省力化や、仕様の統一化を図れます。
 
という訳で、SXF仕様とは独自に、表記要素/幾何要素と同じレベルで矢印データ要素というのを実装する事にします。ただ、SXFファイル等として保存する場合には、線分・円・円弧・ハッチング(塗り)に分解され、それを開いた場合には、矢印データ要素として認識出来なくなるであろう、という事は想定しておきます。複合図形化するとしても同様です。
 
SXF仕様書では下図のように記載されています。

※SXF Ver.3.1仕様書より
 
矢印コードは上記の1〜11をそのまま使います。矢印の大きさは SXF仕様の直線寸法等の備考で
・矢印の大きさは、用紙座標系で解釈する。
とありますのでこれを考慮します。
矢印の角度は「<」の状態を角度0°とします(上図は角度180°状態)。
独自に定義するのだから、上記以外の矢印も利用出来るようにする、というパターンもありますが、それをすると直線寸法等での矢印の利用がSXF仕様ネイティブ的に出来なくなります。矢印を無し状態にして、別途、拡張した矢印を作図させるという手法も有り得ますが、寸法線と矢印がバラバラ状態になってしまうので、それは避けたい、というのがあるかもしれません。また、何らかの関連付けを行い、バラバラにならないようにする、という手法もあるかもしれません。
色々と考えられますが、ここではシンプルに行きます。
 
それでは矢印のデータ構造を決めます。
UnitData.pas
type
 ・・・
 TDataArrow = record    // 独自|幾何要素/表記要素|矢印
  exf : Boolean ;     // 存在フラグ(True:有り False:無し)
  Layer : Integer ;    // レイヤ(1〜256)
  Color : Integer ;    // 色 (0:レイヤ色 1〜256)
  start_x : double ;    // 配置点X座標
  start_y : double ;    // 配置点Y座標
  arrow_code : Integer ;  // 矢印コード
  rotate_angle : double ; // 回転角[°]
  Scale : double ;     // 尺度
 end;
 
データ追加用の関数は
function AddDataArrow(s:string;lay,col,ac:integer;
 px,py,an,sc:double) : Boolean;
のようにします。線分・折線等と同様、最初に「データ追加先の複合図形名(幾何要素) null:用紙へ追加(表記要素)」を指定するようにしています。点マーカの登録用関数を少し修正すれば出来上がりです。
 
UnitData.pas
// 矢印 データ項目の追加登録
function TDataClass.AddDataArrow(s:string;lay,col,ac:integer;px,py,an,sc: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 (ac < 1) or (ac > 11) then ac := 9 ; // open arrow
 an := SetAngle(an);
 if (sc < LIMIT8) then sc := 1.0;
 
 if (s = '') then begin
  // 用紙へ追加
  if (AddDataOrder(0,13,dArwN)) then begin
   try
    Inc(dArwN);
    if ((dArwN mod 200) = 1) then SetLength(dArw, dArwN+199);
    with dArw[dArwN-1] do begin
     exf := True ;
     Layer := lay ;
     Color := col ;
     start_x := px ;
     start_y := py ;
     arrow_code := ac ;
     rotate_angle:= an ;
     Scale := sc ;
    end;
    Result := True ;
    AddLayerCnt(lay,col,-1,-1,-1);
   except
    Dec(dArwN);
    Dec(dOrdN);
   end;
  end;
 end
 else begin
  m := FZukeiNameCheck(0,s);
  if (m > 0) then begin
   with fDef[m-1] do begin
    if (AddDataOrder(m,13,mArwN)) then begin
     try
      Inc(mArwN);
      if ((mArwN mod 200)=1) then SetLength(mArw, mArwN+199);
      with mArw[mArwN-1] do begin
       exf := True ;
       Layer := lay ;
       Color := col ;
       start_x := px ;
       start_y := py ;
       arrow_code := ac ;
       rotate_angle:= an ;
       Scale := sc ;
      end;
      Result := True ;
      AddLayerFCnt(lay,col,-1,-1,-1);
     except
      Dec(mArwN);
      Dec(mOrdN);
     end;
    end;
   end;
  end
  else if (m < 0) then begin
   with sDef[-m-1] do begin
    if (AddDataOrder(m,13,mArwN)) then begin
     try
      Inc(mArwN);
      if ((mArwN mod 200)=1) then SetLength(mArw, mArwN+199);
      with mArw[mArwN-1] do begin
       exf := True ;
       Layer := lay ;
       Color := col ;
       start_x := px ;
       start_y := py ;
       arrow_code := ac ;
       rotate_angle:= an ;
       Scale := sc ;
      end;
      Result := True ;
     except
      Dec(mArwN);
      Dec(mOrdN);
     end;
    end;
   end;
  end;
 end;
end;
 
これで矢印データの登録は出来るようになりましたので次は矢印の描画についてです。UnitClipping.pas に大まかなクリッピングテストをするための関数 Clip1xyaPoint() を追加しています。また、塗り潰し図形の描画のために、UnitGraph.pasに G_Polygon()手続きを追加しています。本来はこの手続きで描画する前にクリッピング処理を施さないといけないのですが今回は省略しています。
 
円の塗り潰しは、24分割の内接正多角形として描画をするようにしています。
 
UnitDataGraph.pas
// 矢印の表示
// an : 回転角[rad]
procedure DisplayArrow(lay,col,ac:integer;px,py,an,sc:double);
var
 sx,sy : double ;
 c,cc : integer ;
 w1,w2,w3,w4,w5,w6 : double ;
 pt : array of TPointD ;
 i : integer ;
begin
 // クリッピングチェック
 w1 := px ;
 w2 := py ;
 sx := 2.5*sc ;
 sy := sx ;
 if (ac = 1)or(ac = 6)or(ac = 9)or(ac = 11) then begin
  w1 := px + 7.5/2.0*sc*Cos(an);
  w2 := py + 7.5/2.0*sc*Sin(an);
  sx := 7.5*sc ;
 end
 else if (ac = 8)or(ac = 10) then begin
  sx := 2.5*Sqrt(2.0);
  sy := sx ;
 end;
 if (Clip1xyaPoint(w1,w2,sx,sy,an, WndX1,WndY1,WndX2,WndY2) = 2) then exit;
 //
 DisplayLayCol1(lay,col,c,cc); // 色
 gp.G_SetWidth(1);
 //
 case(ac)of
  1: begin // blanked arrow
    SetLength(pt,4);
    pt[0].x := px ;
    pt[0].y := py ;
    w5 := px + 7.5 *sc ;
    w6 := py + 1.25*sc ;
    Rev(pt[1].x,pt[1].y, w5,w6, px,py, an);
    w5 := px + 7.5 *sc ;
    w6 := py - 1.25*sc ;
    Rev(pt[2].x,pt[2].y, w5,w6, px,py, an);
    pt[3].x := pt[0].x ;
    pt[3].y := pt[0].y ;
    gp.G_SetPen(BackCol);
    DisplayPolygon(3,pt);
    gp.G_SetPen(cc);
    for i:=0 to 2 do
     DisplayLineSub1(pt[i].x,pt[i].y, pt[i+1].x,pt[i+1].y);
    pt := nil;
   end;
  2: begin // blanked box
    SetLength(pt,5);
    w5 := px - 1.25*sc ;
    w6 := py - 1.25*sc ;
    Rev(pt[0].x,pt[0].y, w5,w6, px,py, an);
    w5 := px + 1.25*sc ;
    w6 := py - 1.25*sc ;
    Rev(pt[1].x,pt[1].y, w5,w6, px,py, an);
    w5 := px + 1.25*sc ;
    w6 := py + 1.25*sc ;
    Rev(pt[2].x,pt[2].y, w5,w6, px,py, an);
    w5 := px - 1.25*sc ;
    w6 := py + 1.25*sc ;
    Rev(pt[3].x,pt[3].y, w5,w6, px,py, an);
    pt[4].x := pt[0].x ;
    pt[4].y := pt[0].y ;
    gp.G_SetPen(BackCol);
    DisplayPolygon(4,pt);
    gp.G_SetPen(cc);
    for i:=0 to 3 do
     DisplayLineSub1(pt[i].x,pt[i].y, pt[i+1].x,pt[i+1].y);
    pt := nil;
   end;
  3: begin // blanked dot
    SetLength(pt,25);
    w1 := 2.0*Pi/24 ;
    for i:=0 to 24 do begin
     pt[i].x := px + 1.25*sc*Cos(i*w1);
     pt[i].y := py + 1.25*sc*Sin(i*w1);
    end;
    gp.G_SetPen(BackCol);
    DisplayPolygon(23,pt);
    gp.G_SetPen(cc);
    for i:=0 to 23 do
     DisplayLineSub1(pt[i].x,pt[i].y, pt[i+1].x,pt[i+1].y);
    pt := nil;
   end;
  4: begin // dimension origin
    SetLength(pt,25);
    w1 := 2.0*Pi/24 ;
    for i:=0 to 24 do begin
     pt[i].x := px + 1.25*sc*Cos(i*w1);
     pt[i].y := py + 1.25*sc*Sin(i*w1);
    end;
    for i:=0 to 23 do
     DisplayLineSub1(pt[i].x,pt[i].y, pt[i+1].x,pt[i+1].y);
    pt := nil;
   end;
  5: begin // filled box
    SetLength(pt,5);
    w5 := px - 1.25*sc ;
    w6 := py - 1.25*sc ;
    Rev(pt[0].x,pt[0].y, w5,w6, px,py, an);
    w5 := px + 1.25*sc ;
    w6 := py - 1.25*sc ;
    Rev(pt[1].x,pt[1].y, w5,w6, px,py, an);
    w5 := px + 1.25*sc ;
    w6 := py + 1.25*sc ;
    Rev(pt[2].x,pt[2].y, w5,w6, px,py, an);
    w5 := px - 1.25*sc ;
    w6 := py + 1.25*sc ;
    Rev(pt[3].x,pt[3].y, w5,w6, px,py, an);
    pt[4].x := pt[0].x ;
    pt[4].y := pt[0].y ;
    DisplayPolygon(4,pt);
    for i:=0 to 3 do
     DisplayLineSub1(pt[i].x,pt[i].y, pt[i+1].x,pt[i+1].y);
    pt := nil;
   end;
  6: begin // filled arrow
    SetLength(pt,4);
    pt[0].x := px ;
    pt[0].y := py ;
    w5 := px + 7.5 *sc ;
    w6 := py + 1.25*sc ;
    Rev(pt[1].x,pt[1].y, w5,w6, px,py, an);
    w5 := px + 7.5 *sc ;
    w6 := py - 1.25*sc ;
    Rev(pt[2].x,pt[2].y, w5,w6, px,py, an);
    pt[3].x := pt[0].x ;
    pt[3].y := pt[0].y ;
    DisplayPolygon(3,pt);
    for i:=0 to 2 do
     DisplayLineSub1(pt[i].x,pt[i].y, pt[i+1].x,pt[i+1].y);
    pt := nil;
   end;
  7: begin // filled dot
    SetLength(pt,25);
    w1 := 2.0*Pi/24 ;
    for i:=0 to 24 do begin
     pt[i].x := px + 1.25*sc*Cos(i*w1);
     pt[i].y := py + 1.25*sc*Sin(i*w1);
    end;
    DisplayPolygon(23,pt);
    for i:=0 to 23 do
     DisplayLineSub1(pt[i].x,pt[i].y, pt[i+1].x,pt[i+1].y);
    pt := nil;
   end;
  8: begin // integral symbol
    SetLength(pt,25);
    w1 := Pi/2.0/12 ;
    for i:=0 to 12 do begin
     w5 := px-sx/2.0 + sx/2.0*Cos(1.5*Pi+i*w1);
     w6 := py    + sx/2.0*Sin(1.5*Pi+i*w1);
     Rev(pt[i].x,pt[i].y, w5,w6, px,py, an);
    end;
    for i:=1 to 12 do begin
     w5 := px+sx/2.0 + sx/2.0*Cos(Pi-i*w1);
     w6 := py    + sx/2.0*Sin(Pi-i*w1);
     Rev(pt[i+12].x,pt[i+12].y, w5,w6, px,py, an);
    end;
    for i:=0 to 23 do
     DisplayLineSub1(pt[i].x,pt[i].y, pt[i+1].x,pt[i+1].y);
    pt := nil;
   end;
  9: begin // open arrow
    w1 := px ;
    w2 := py ;
    w5 := px + 7.5 *sc ;
    w6 := py + 1.25*sc ;
    Rev(w3,w4, w5,w6, px,py, an);
    DisplayLineSub1(w1,w2, w3,w4);
    w5 := px + 7.5 *sc ;
    w6 := py - 1.25*sc ;
    Rev(w3,w4, w5,w6, px,py, an);
    DisplayLineSub1(w1,w2, w3,w4);
   end;
 10:begin // slash
    w5 := px - sx/2.0 ;
    w6 := py - sx/2.0 ;
    Rev(w1,w2, w5,w6, px,py, an);
    w5 := px + sx/2.0 ;
    w6 := py + sx/2.0 ;
    Rev(w3,w4, w5,w6, px,py, an);
    DisplayLineSub1(w1,w2, w3,w4);
  end;
 11:begin // unfilled arrow
    SetLength(pt,4);
    pt[0].x := px ;
    pt[0].y := py ;
    w5 := px + 7.5 *sc ;
    w6 := py + 1.25*sc ;
    Rev(pt[1].x,pt[1].y, w5,w6, px,py, an);
    w5 := px + 7.5 *sc ;
    w6 := py - 1.25*sc ;
    Rev(pt[2].x,pt[2].y, w5,w6, px,py, an);
    pt[3].x := pt[0].x ;
    pt[3].y := pt[0].y ;
    for i:=0 to 2 do
     DisplayLineSub1(pt[i].x,pt[i].y, pt[i+1].x,pt[i+1].y);
    pt := nil;
  end;
 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.