R12 形式の DXF ファイルを作る (2016/ 8/19, 2018/12/13)
2018/12/13
・PLOYLINE (直線のみ)の作成を追加
・Variant 型からの変換を追加
・TEXT 作成の不具合を修正
■R12 形式の DXF ファイルは、ハンドル番号、ハンドル数、クラス名が不要なので、作りやすいです。
ただし、R12 時代に無い図形は作成できません。例えば、LWPOLYLINE は、POLYLINE で作成します。
※ファイルを挿入するとき、ファイル名の前に "*" を付けると、分解挿入されます。
分解挿入の時、尺度指定の S オプションが使えなくなり、X, Y の尺度を指定する必要があります。
{ 2018/12/13 ・Variant -> TAcadPoint 変換を追加 ・POLYLINE 作成(直線のみ)を追加 ・TEXT 作成の不具合を修正 } unit MakeR12Dxf_V; interface uses Windows, //for TPoint System.UITypes, System.Variants, //for OleVariant; SysUtils, Graphics, Classes; //for TStrings type TAcadPoint = Record x, y, z :Extended; end; function V3ToAcPt(vpt : OleVariant): TAcadPoint; function VptsToAcPts(vpts : OleVariant; var acpts: array of TAcadPoint): boolean; procedure MakeR12DxfHead(sl: TStrings); procedure AddR12DxfEntHead(sl: TStringList); procedure AddR12DxfLineEnt(sl: TStrings; p1, p2: TAcadPoint; const Layer: string; const LType: string; LColor: integer); procedure AddR12DxfTextEnt(sl: TStrings; const Txt: string; pt10, pt11: TAcadPoint; Takasa, Haba, Kakudo: double; code72, code73: integer; const Kiten: string; const Lay: string; color: integer); procedure AddR12DxfCircleEnt(sl: TStrings; Center: TAcadPoint; hankei: double; const Layer: string; const LType: string; LColor: integer); procedure AddR12DxfArcEnt(sl: TStrings; Center: TAcadPoint; hankei, StDeg, EdDeg: double; const Layer: string; const LType: string; LColor: integer); procedure AddR12DxfPolylineEnt(sl: TStrings; pts : array of TAcadPoint; closed : boolean ; const Layer: string; const LType: string; LColor: integer); procedure AddR12DxfTerm(sl: TStrings); procedure AddR12DxfLtypeHidden2(sl: TStrings); procedure AddR12DxfLtypeDummy(sl: TStrings); implementation //{$R *.dfm} // バリアントの3D配列を TAcadPoint に function V3ToAcPt(vpt : OleVariant): TAcadPoint; begin result.x := vpt[0]; result.y := vpt[1]; result.z := vpt[2]; end; // バリアントの1次元配列(2D座標)を TAcadPoint に // vpts は、x1, y1, x2, y2, .... // acpt は、acpt[0], acpt[1], ... function VptsToAcPts(vpts : OleVariant; var acpts: array of TAcadPoint): boolean; var n, m, i :integer; begin // 一次元配列の数 n := VarArrayHighBound(vpts, 1) + 1; m := Length(acpts); if n div 2 = m then begin for i := 0 to n div 2 -1 do begin acpts[i].x := vpts[i * 2]; acpts[i].y := vpts[i * 2 + 1]; acpts[i].z := 0.0; end; end; result := n div 2 =m; end; procedure MakeR12DxfHead(sl: TStrings); begin sl.Clear; sl.Add(' 0' + #13#10 + 'SECTION' + #13#10 + ' 2' + #13#10 + 'HEADER' + #13#10 + ' 9' + #13#10 + '$ACADVER' + #13#10 + ' 1' + #13#10 + 'AC1009' + #13#10 + ' 9' + #13#10 + '$CELTYPE' + #13#10 + ' 6' + #13#10 + 'BYLAYER' + #13#10 + ' 9' + #13#10 + '$CECOLOR' + #13#10 + ' 62' + #13#10 + '256' + #13#10 + ' 0' + #13#10 + 'ENDSEC'); sl.Add(' 0' + #13#10 + 'SECTION' + #13#10 + ' 2' + #13#10 + 'TABLES'); end; procedure AddR12DxfTerm(sl: TStrings); begin sl.Add(' 0' + #13#10 + 'ENDSEC'); sl.Add(' 0' + #13#10 + 'EOF'); end; procedure AddR12DxfLtypeDummy(sl: TStrings); begin with sl do begin // TABLESセクションのうちLTYPEだけを追加 Add(' 0' + #13#10 + 'TABLE'); Add(' 2' + #13#10 + 'LTYPE'); Add(' 70' + #13#10 + ' 2' + #13#10 + ' 0' + #13#10 + 'LTYPE'); Add(' 2' + #13#10 + 'CONTINUOUS' + #13#10 + ' 70' + #13#10 + ' 0' + #13#10 + ' 3' + #13#10 + 'Solid line'); Add(' 72' + #13#10 + ' 65' + #13#10 + ' 73' + #13#10 + ' 0' + #13#10 + ' 40' + #13#10 + '0.0'); Add(' 0' + #13#10 + 'ENDTAB'); end end; procedure AddR12DxfLtypeHidden2(sl: TStrings); begin with sl do begin // TABLESセクションのうちLTYPEだけを追加 Add(' 2' + #13#10 + 'LTYPE'); Add(' 0' + #13#10 + 'LTYPE' + #13#10 + ' 2' + #13#10 + 'HIDDEN2' + #13#10 + ' 70' + #13#10 + ' 0'); Add(' 3' + #13#10 + 'Hidden (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _'); Add(' 72' + #13#10 + ' 65' + #13#10 + ' 73' + #13#10 + ' 2'); Add(' 40' + #13#10 + '4.7625' + #13#10 + ' 49' + #13#10 + '3.175' + #13#10 + ' 49' + #13#10 + '-1.5875'); Add(' 0' + #13#10 + 'ENDTAB'); end end; procedure AddR12DxfEntHead(sl: TStringList); begin with sl do begin Add(' 0' + #13#10 + 'ENDSEC'); Add(' 0' + #13#10 + 'SECTION' + #13#10 + ' 2' + #13#10 + 'ENTITIES'); end; end; // R12形式なので、TTFは設定できない // すでに存在するSTYLEの場合は、フォント名は適当で良い procedure AddR12DxfTextStyle(sl: TStrings; const style, font1, font2: string); begin with sl do begin Add(' 0' + #13#10 + 'TABLE' + #13#10 + ' 2' + #13#10 + 'STYLE' + #13#10 + ' 70' + #13#10 + ' 1'); Add(' 0' + #13#10 + 'STYLE' + #13#10 + ' 2' + #13#10 + style + #13#10 + ' 70' + #13#10 +' 0'); Add(' 40' + #13#10 + '0.0' + #13#10 + ' 41' + #13#10 + '1.0' + #13#10 + ' 50' + #13#10 + '0.0'); Add(' 71' + #13#10 + ' 0' + #13#10 + ' 42' + #13#10 + '2.5' + #13#10 + ' 3' + #13#10 + font1); Add(' 4' + #13#10 + font2 + #13#10 + ' 0' + #13#10 + 'ENDTAB'); end; end; procedure AddR12DxfLineEnt(sl: TStrings; p1, p2: TAcadPoint; const Layer: string; const LType: string; LColor: integer); begin with sl do begin Add(' 0' + #13#10 + 'LINE'); Add(' 8' + #13#10 + Layer + #13#10 + ' 6' + #13#10 + LType + #13#10 + ' 62' + #13#10 + IntToStr(LColor) + #13#10 + ' 48' + #13#10 + '1.0'); Add(' 10' + #13#10 + FloatToStr(p1.x) + #13#10 + ' 20' + #13#10 + FloatToStr(p1.y) + #13#10 + ' 30' + #13#10 + FloatToStr(p1.z)); Add(' 11' + #13#10 + FloatToStr(p2.x) + #13#10 + ' 21' + #13#10 + FloatToStr(p2.y) + #13#10 + ' 31' + #13#10 + FloatToStr(p2.z)); end; end; procedure AddR12DxfCircleEnt(sl: TStrings; Center: TAcadPoint; hankei: double; const Layer: string; const LType: string; LColor: integer); begin with sl do begin Add(' 0' + #13#10 + 'CIRCLE'); Add(' 8' + #13#10 + Layer + #13#10 + ' 6' + #13#10 + LType + #13#10 + ' 62' + #13#10 + IntToStr(LColor) + #13#10 + ' 48' + #13#10 + '1.0'); Add(' 10' + #13#10 + FloatToStr(Center.x) + #13#10 + ' 20' + #13#10 + FloatToStr(Center.y) + #13#10 + ' 30' + #13#10 + FloatToStr(Center.z)); Add(' 40' + #13#10 + FloatToStr(Hankei)); end; end; procedure AddR12DxfArcEnt(sl: TStrings; Center: TAcadPoint; hankei, StDeg, EdDeg: double; const Layer: string; const LType: string; LColor: integer); begin with sl do begin Add(' 0' + #13#10 + 'ARC'); Add(' 8' + #13#10 + Layer + #13#10 + ' 6' + #13#10 + LType + #13#10 + ' 62' + #13#10 + IntToStr(LColor) + #13#10 + ' 48' + #13#10 + '1.0'); Add(' 10' + #13#10 + FloatToStr(Center.x) + #13#10 + ' 20' + #13#10 + FloatToStr(Center.y) + #13#10 + ' 30' + #13#10 + FloatToStr(Center.z)); Add(' 40' + #13#10 + FloatToStr(Hankei) + #13#10 + ' 50' + #13#10 + FloatToStr(StDeg) + #13#10 + ' 51' + #13#10 + FloatToStr(EdDeg)); end; end; procedure AddR12DxfPolylineEnt(sl: TStrings; pts : array of TAcadPoint; closed : boolean ; const Layer: string; const LType: string; LColor: integer); var i : integer; begin with sl do begin Add(' 0' + #13#10 + 'POLYLINE'); Add(' 8' + #13#10 + Layer + #13#10 + ' 6' + #13#10 + LType + #13#10 + ' 62' + #13#10 + IntToStr(LColor) + #13#10 + ' 48' + #13#10 + '1.0'); Add(' 66' + #13#10 + '1'); Add(' 10' + #13#10 + '0.0' + #13#10 + ' 20' + #13#10 + '0.0' + #13#10 + ' 30' + #13#10 + '0.0'); if closed then Add(' 70' + #13#10 + '1') else Add(' 70' + #13#10 + '0'); for i := 0 to Length(pts) - 1 do begin Add(' 0' + #13#10 + 'VERTEX'); Add(' 8' + #13#10 + Layer); Add(' 10' + #13#10 + FloatToStr(pts[i].x) + #13#10 + ' 20' + #13#10 + FloatToStr(pts[i].y) + #13#10 + ' 30' + #13#10 + '0.0'); end; Add(' 0' + #13#10 + 'SEQEND'); end; end; // 201812/13 修正 procedure AddR12DxfTextEnt(sl: TStrings; const Txt: string; pt10, pt11: TAcadPoint; Takasa, Haba, Kakudo: double; code72, code73: integer; const Kiten: string; const Lay: string; color :Integer); var n: integer; s: string; begin if kiten <> '' then begin s := Kiten; n := Length(s); if (n = 2) then begin if (s[1] = 'M') then code73 := 2 else if (s[1] = 'T') then code73 := 3 else if (s[1] = 'B') then code73 := 1; if (s[2] = 'L') then code72 := 0 else if (s[2] = 'C') then code72 := 1 else if (s[2] = 'R') then code72 := 2; end else if n = 1 then begin if (s[1] = 'L') then code72 := 0 else if (s[1] = 'C') then code72 := 1 else if (s[1] = 'R') then code72 := 2 else if (s[1] = 'A') then code72 := 3 else if (s[1] = 'M') then code72 := 4 else if (s[1] = 'F') then code72 := 5; end; end; with sl do begin Add(' 0' + #13#10 + 'TEXT'); Add(' 8' + #13#10 + Lay + #13#10 + ' 62' + #13#10 + IntToStr(color)); Add(' 10' + #13#10 + FloatToStr(pt10.x) + #13#10 + ' 20' + #13#10 + FloatToStr(pt10.y) + #13#10 + ' 30' + #13#10 + FloatToStr(pt10.z)); Add(' 11' + #13#10 + FloatToStr(pt11.x) + #13#10 + ' 21' + #13#10 + FloatToStr(pt11.y) + #13#10 + ' 31' + #13#10 + FloatToStr(pt11.z)); Add(' 1' + #13#10 + Txt); Add(' 40' + #13#10 + FloatToStr(takasa)); Add(' 41' + #13#10 + FloatToStr(Haba)); Add(' 50' + #13#10 + FloatToStr(Kakudo)); Add(' 72' + #13#10 + IntToStr(code72) + #13#10 +' 73' + #13#10 + IntToStr(code73)); end; end; end. //----------------------------------------------------- // 使い方 // ※ Variant 型は、他の CAD 用のプログラムを流用するために追加しています // 通常は、TAcadPoint を使います //----------------------------------------------------- procedure TForm1.Button1Click(Sender: TObject); var sl: TStringList; p1, p2 : TAcadPoint; DxfName : TFileName; vpt1, vpt2 : OleVariant; vpts : OleVariant; acpts : array of TAcadPoint; begin // 通常はこちら // LINE 用テストデータ p1.x := 100; p1.y := 200; p1.z := 0; p2.x := 200; p2.y := 100; p2.z := 0; // バリアントを使う場合はこちら // LINE 用テストデータ // Variant To TAcadPoint の変換が必要 vpt1 := VarArrayCreate([0, 2], VarDouble); vpt2 := vpt1; vpt1[0] := 100; vpt1[1] := 200; vpt1[2] := 0; vpt2[0] := 300; vpt2[1] := 400; vpt2[2] := 0; // POLYLINE 用テストデータ vpts := VarArrayCreate([0, 7], VarDouble); vpts[0] := 100; vpts[1] := 100; vpts[2] := 200; vpts[3] := 100; vpts[4] := 200; vpts[5] := 50; vpts[6] := 100; vpts[7] := 50; SetLength(acpts, 4); // Variant To TAcadPoint の変換 VptsToAcPts(vpts , acpts); sl := TStringList.Create; try // ヘッダー MakeR12DxfHead(sl); // TABLESセクションのうちLTYPEだけを追加 AddR12DxfLtypeDummy(sl); // ENTITIES 開始 AddR12DxfEntHead(sl); // LINE を追加 AddR12DxfLineEnt(sl, V3ToAcPt(vpt1), V3ToAcPt(vpt2), '0', 'BYLAYER', 256); // TEXT を追加 AddR12DxfTextEnt(sl, 'TEST', V3ToAcPt(vpt1), V3ToAcPt(vpt2), 10, 1, 0, 0, 0, 'ML', '0', 256); // POLYLINE を追加 AddR12DxfPolylineEnt(sl, acpts, True, '0', 'BYLAYER', 256); // ENDSEC AddR12DxfTerm(sl); // DXFファイルを追加 DxfName := ChangeFileExt(ParamStr(0), '.dxf'); // ファイルに保存 sl.SaveToFile(DxfName); // Memo に表示 Memo1.Lines.Assign(sl); finally sl.Free; end; end;