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

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

プログラミングについて
ホームページについて
キャドについて
電子カタログについて
書籍・雑誌
イベント
リンク集
CADを考える:ハッチング(7)
前頁は構造化要素のハッチング(塗り)について考えてみました。今回は、ハッチング(ユーザ定義)について考えてみます。
 
ハッチング要素データ(ユーザ定義)は、SXF仕様書では以下のように記載されています。
構造化要素|ハッチング(ユーザ定義)


※SXF Ver.3.1仕様書より
(※下の図は左上に不明な線が入っていたので除去しました)
パラメータ説明範囲
LayerIntレイヤコード 
hatch1_numberIntハッチング線のパターン数1≦数≦4
hatch1_colorIntハッチング線の色コード(配列)
hatch_typeIntハッチング線の線種コード(配列)
hatch_line_widthIntハッチング線の線幅コード(配列)
hatch_start_xdoubleハッチング線の通過点X座標(配列) double(64bits)の
範囲(有効桁15桁)
hatch_start_ydoubleハッチング線の通過点Y座標(配列) double(64bits)の
範囲(有効桁15桁)
hatch_spacingdoubleハッチング線の間隔(配列) double(64bits)の
範囲(有効桁15桁)
hatch_angledoubleハッチング線の角度(配列)0≦度<360
out_idInt外形の複合曲線のフィーチャコード 
NumberInt中抜きの閉領域数 0≦数<int(32bits)
の最大値
in_id CArray
<int,
int>
中抜きの複合曲線のフィーチャコード(配列) 
備考
・ハッチング線はユーザ定義パターンとする。
・角度は水平右側が0度、反時計廻りが正、単位は度とする。
・ハッチングの間隔は配置された用紙、部分図の座標系で解釈する。
 
という訳でハッチング(ユーザ定義)の表現方法はハッチング(既定義)と同じです。ハッチング(既定義)は色・線種・通過点・間隔・角度の指定が既に定義されてあるものを利用する、という風になっていますが、このハッチング(ユーザ定義)では、それらを要素データ毎に指定する、というだけです。
 
CADソフト上では、ユーザ定義ハッチングパターンとして予め設定しておいたものでハッチングを行う、という手法と、ハッチングコマンドを実行する際に各値を指定する事によって処理を行う手法、があるでしょう。同じようなハッチングを何度も行う場合には前者の方が利用しやすく、余り使わない特殊なハッチングの場合には後者、でしょうか?本数と角度だけは設定しておきたいという場合もあるかもしれません。また、前回指定値(履歴)で行いたいという場合も有り得ます。
 
ハッチング(既定義)とは異なり、ハッチング(ユーザ定義)は各指定値をデータ毎に登録する必要があるのでデータ量(=メモリ)を消費します。SXF仕様にこだわらずとも、SXFファイル出力の際に、SXFの既定義部分とを区分すれば別に構わないので、よく使用する独自ハッチングパターンもハッチング(既定義)として登録しておく、という手法も有りだと思われます。
 
まぁそれはともかく、ハッチング(ユーザ定義)のデータ構造です。
UnitData.pas
type
 ・・・
 TDataHatch3 = record    // 構造化要素|ハッチング(ユーザ定義)
  exf : Boolean ;     // 存在フラグ(True:有り False:無し)
  Layer : Integer ;    // レイヤ(1〜256)
  hatch1_number : integer ;         // パターン数(1-4)
  hatch1_color : array[0..3] of integer ;  // 線色コード
  hatch_type  : array[0..3] of integer ;  // 線種コード
  hatch_line_width:array[0..3] of integer ; // 線幅コード
  hatch_start_x : array[0..3] of double ;  // 通過点X座標
  hatch_start_y : array[0..3] of double ;  // 通過点Y座標
  hatch_spacing : array[0..3] of double ;  // 間隔
  hatch_angle  : array[0..3] of double ;  // 角度[°]
  out_id : Integer ;     // 外形の複合曲線のフィーチャコード
  Number : Integer ;     // 中抜の閉領域数(0〜)
  in_id : array of Integer; // 中抜の複合曲線のフィーチャコード
  hln : integer ;      // ハッチング線数
  hl : array of THatchLine; // ハッチング線
 end;
 ・・・
 
ハッチング(ユーザ定義)のデータ登録は下記のようにします。
UnitData.pas
// ハッチング(ユーザ定義) データ項目の追加登録
function TDataClass.AddDataHatch3(s:string;lay,hnum:integer;
 hcol,hltp,hwid:array of integer;hx,hy,hs,ha:array of double;
 oid,num:integer;iid:array of integer) : Boolean ;
 
実際のハッチング計算は手続き MakeHatch3 にて行うようにします。各値の指定方法が異なるだけで内容はほぼ MakeHatch1 と同じです。但し、通過点指定をハッチング領域外に指定した場合の処置を施しています。

ハッチング領域の対角中心点を通るハッチング角度分傾いた線を想定し、指定通過点からの距離・垂点を算出、距離はハッチング間隔を考慮して整合性をとった上で、新たな通過点を算出し、ハッチング線算出用の想定線分の長さも十分に大きくして、計算を行っています。
ここで算出したハッチング線を変数 zHLn,zHLnN を経由して hl,hln に登録し、実際のハッチング線の描画はこの hl,hln を参照するようにします。
UnitData.pas
// ハッチング(ユーザ定義) ハッチング線の算出
// hnum : ハッチング線のパターン数
//  hcol : 線色コード
//  hltp : 線種コード
//  hwid : 線幅コード
//  hx : 通過点X座標
//  hy : 通過点Y座標
//  hs : 間隔
//  ha : 角度[°]
// (ret)
// zHLn, zHLnN
procedure TDataClass.MakeHatch3(hnum:integer;hcol,hltp,hwid:
 array of integer;hx,hy,hs,ha:array of double) ;
var
 i,j,k : integer ;
 w1,w2,wx1,wy1,wx2,wy2,wx3,wy3 : double ;
 tl,cx,cy,tx,ty,ts,ta : double ;
 col,ltp,wid : integer ;
begin
 zHLn := nil ;
 zHLnN:= 0 ;
 // min,maxを取得
 with zHAr[0] do begin
  wx1 := a[0].x ;
  wy1 := a[0].y ;
  wx2 := wx1;
  wy2 := wy1;
  for i:=1 to an-1 do begin
   if (wx1 > a[i].x) then wx1 := a[i].x ;
   if (wy1 > a[i].y) then wy1 := a[i].y ;
   if (wx2 < a[i].x) then wx2 := a[i].x ;
   if (wy2 < a[i].y) then wy2 := a[i].y ;
  end;
 end;
 tl := 10000.0*Dist(wx1,wy1,wx2,wy2); // 対角長さ
 cx := (wx1+wx2)/2.0; // 対角中心点
 cy := (wy1+wy2)/2.0;
 //
 for k:=0 to (hnum-1) do begin
  tx := hx[k];  // 通過点
  ty := hy[k];
  ts := hs[k];  // ハッチング間隔
  ta := ha[k];  // ハッチング角度
  col:= hcol[k]; // 色
  ltp:= hltp[k]; // 線種
  wid:= hwid[k]; // 線幅
  // 通過点がハッチング領域外にある場合に対応するための処理
  wx1:= cx + 10.0*Cos(ta/180.0*Pi);
  wy1:= cy + 10.0*Sin(ta/180.0*Pi);
  wx2:= cx - 10.0*Cos(ta/180.0*Pi);
  wy2:= cy - 10.0*Sin(ta/180.0*Pi);
  w1 := GetCrossLP(wx1,wy1,wx2,wy2,tx,ty, wx3,wy3);
  w2 := Angle(wx3-tx,wy3-ty);
  tx := tx + Int(w1/ts)*ts * Cos(w2) ;
  ty := ty + Int(w1/ts)*ts * Sin(w2) ;
  // 通過点 及び 上方向へ走査
  j := 1 ;
  wx1:= tx ;
  wy1:= ty ;
  while (j > 0) do begin
   j := CalcHatch1Point(wx1,wy1,tl,ta); // 1ライン交点計算
   for i:=0 to (j div 2)-1 do begin
    try
     Inc(zHLnN);
     if ((zHLnN mod 100) = 1) then SetLength(zHLn, zHLnN+99);
     with zHLn[zHLnN-1] do begin
      Color := col ;
      Ltype := ltp ;
      line_width := wid ;
      x1 := zHCp[i*2 ].x ;
      y1 := zHCp[i*2 ].y ;
      x2 := zHCp[i*2+1].x ;
      y2 := zHCp[i*2+1].y ;
     end;
    except
     Dec(zHLnN);
     break ;
    end;
   end;
   wx1 := wx1 + ts*Cos((ta+90.0)/180.0*Pi);
   wy1 := wy1 + ts*Sin((ta+90.0)/180.0*Pi);
  end;
  // 下方向へ走査
  wx1:= tx ;
  wy1:= ty ;
  j := 1 ;
  while (j > 0) do begin
   wx1 := wx1 + ts*Cos((ta-90.0)/180.0*Pi);
   wy1 := wy1 + ts*Sin((ta-90.0)/180.0*Pi);
   j := CalcHatch1Point(wx1,wy1,tl,ta); // 1ライン交点計算
   for i:=0 to (j div 2)-1 do begin
    try
     Inc(zHLnN);
     if ((zHLnN mod 100) = 1) then SetLength(zHLn, zHLnN+99);
     with zHLn[zHLnN-1] do begin
      Color := col ;
      Ltype := ltp ;
      line_width := wid ;
      x1 := zHCp[i*2 ].x ;
      y1 := zHCp[i*2 ].y ;
      x2 := zHCp[i*2+1].x ;
      y2 := zHCp[i*2+1].y ;
     end;
    except
     Dec(zHLnN);
     break ;
    end;
   end;
  end;
 end;
 SetLength(zHLn, zHLnN);
 zHCp := nil;
 zHCpN:= 0;
end;
 
ハッチング(ユーザ定義)の描画はこれまで同様、UnitDataGraph.pas にて行いますが、ハッチング(既定義)の描画の手続き DisplayHatch1 がそのまま利用可能なのでそれを使います。
 
それでは、ハッチング(ユーザ定義)の登録・描画のテストです。
Unit1.pas
・・・
SetLength(lx,5);
SetLength(ly,5);
CData.AddCCurveDef(1,1,1,1,1);   // 複合曲線定義 #1
lx[0] := 40; ly[0] := 40 ;
lx[1] := 140; ly[1] := 40 ;
lx[2] := 140; ly[2] := 140 ;
lx[3] := 40; ly[3] := 140 ;
lx[4] := 40; ly[4] := 40 ;
CData.AddCCrvDataLines(1,5,lx,ly); // 折線
 
CData.AddCCurveDef(2,2,2,6,1);   // 複合曲線定義 #2
CData.AddCCrvDataArc(2,36,0, 90,130,8,0,180); // 円は円弧2つで形成
CData.AddCCrvDataArc(2,36,0, 90,130,8,180,0);
 
CData.AddCCurveDef(3,4,4,7,1);   // 複合曲線定義 #3
lx[0] := 60; ly[0] := 60 ;
lx[1] := 90; ly[1] := 90 ;
lx[2] := 60; ly[2] := 120 ;
lx[3] := 60; ly[3] := 60 ;
CData.AddCCrvDataSpline(3,3,10,4,0,lx,ly); // スプライン曲線
 
CData.AddCCurveDef(4,5,5,8,1);   // 複合曲線定義 #4
lx[0] := 120; ly[0] := 60 ;
lx[1] := 90; ly[1] := 90 ;
lx[2] := 120; ly[2] := 120 ;
lx[3] := 120; ly[3] := 60 ;
CData.AddCCrvDataSpline(4,3,10,4,0,lx,ly); // スプライン曲線
 
lx := nil;
ly := nil;
 
// ----- ハッチングテスト -----
// ユーザ定義
CData.AddDataHatch3('' , 1,
 1,[3],[1],[1],[40.0],[40.0],[4.0],[30.0], 1,3,[2,3,4]);
CData.AddDataHatch3('部分図A', 1,
 1,[3],[1],[1],[40.0],[40.0],[4.0],[30.0], 1,3,[2,3,4]);
 
DisplayAllData ; // 全データ表示
・・・
というような感じでハッチングデータの登録をして描画をすると下記のような感じになります。

少し拡大します

 
2本ずつのクロスハッチングの場合は下記のようにします。
Unit1.pas
・・・
// ユーザ定義
CData.AddDataHatch3('' , 1,
 2,[3,4],[1,2],[1,1],[0.0,0.0],[0.0,0.0],[4.0,4.0],[30.0,150.0],
 1,3,[2,3,4]);
CData.AddDataHatch3('部分図A', 1,
 2,[3,4],[1,2],[1,1],[0.0,0.0],[0.0,0.0],[4.0,4.0],[30.0,150.0],
 1,3,[2,3,4]);
 
DisplayAllData ; // 全データ表示
・・・
という感じで 30°・150°の2本パターンで作図するようにすると、下図のようになります。

 
それでは、ここまでのテストプログラムです。実行ファイル、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.