<第14回目:’04年1月7日>
dxf ファイルを読み込むテストプログラムを作成する
前回はqcadの出力したdxfファイルの内容を調べました。これに基づき、dxfファイルを読み込み各エンティティを動的メモリに取り込むテストプログラムを作成しました。
dxfファイルを読みこむための構造体は以下のようなものです。2種類あり、円弧、直線、点、テキスト、円の図形を構成するエンティティ用とそれ以外のレイヤ情報テキスト用です。
//
エンティティオブジェト
(arc,line,point,circle,text)の構造体
struct OBJ {
int index;
// 連番
int type;
// タイプ
int
cw;
// 切削方向
int
block; // 接続ブロック
double
x1;
// DXFの端点1
double y1;
double
x2; // DXFの端点2
double y2;
int
style; // DXFのスタイル
int
layer; // DXFのレイヤ
int
color;
// DXFの色
int
width;
// DXFの線幅
double
cx; // DXFのARC,CIRCLEの中心点
double cy;
double
cr;
// DXFのARC,CIRCLEの半径
double
sa;
// DXFのARC,CIRCLEのスタートアングル
double
ea;
// DXFのARC,CIRCLEのエンドアングル
struct OBJ
*prev_obj_ptr;
// 前のオブジェクトへのポインタ
struct OBJ
*next_obj_ptr;
// 次のオブジェクトへのポインタ
};
// レイヤ情報textの構造体
struct TEXT_OBJ {
struct OBJ
*obj_ptr; // オブジェクトへのポインタ
int
layer;
// レイヤ
int
cw;
// 切削方向
float
depth; // 切削厚
float
step;
// 切削厚ステップ
int speed;
// 切削速度
char
text_str[256]; // テキスト本体
struct TEXT_OBJ *prev_text_obj_ptr; // 前のオブジェクトへのポインタ
};
次にのエンティティを解析する部分は以下のようにしました。qcadのdxfファイルの読み込み部分のフローを参考にしています。ARC(円弧)のエンティティ部分を解析する部分を抜粋しました。
// DXFファイルをオープンして〜
// 各ポインタを初期化して〜
while (!feof(rfp))
{
// ファイルの終りが来るまで
strcpy(val_str,
get_line());
// 1行入力(value)
// *******
// Arc
// *******
if (!strncmp(val_str, "ARC", 3))
{
// ARCなら
obj_ptr = (OBJ
*)malloc(sizeof(OBJ));
// メモリを取得する
if (!obj_ptr) {
fprintf(stderr, "Can't
malloc\n");
// メモリが取得できなかった
exit(1);
}
do {
code=atoi(get_line());
// 1行入力(code)
if (code) {
if (code
&& code!=0)
{
// codeが有効なら
strcpy(val_str,
get_line());
// 1行入力(設定値)
if
(val_str)
{
// 内容が有効なら
switch (code)
{
// codeで処理を分岐
case 6: // Style
obj_ptr->style = atoi(val_str);
break;
case 8: // Layer
obj_ptr->layer = get_layer(val_str);
if (obj_ptr->layer > 0)
layer_f = 1;
// フラグが立っていれば時計周り
if (obj_ptr->layer >= LAYER_CW_FLAG) {
obj_ptr->obj_cw = 1;
obj_ptr->layer = LAYER_CW_MASK & obj_ptr->layer;
}
else obj_ptr->obj_cw = 0;
break;
case 10:
// Centre X
obj_ptr->cx = atof(val_str);
break;
case 20:
// Centre Y
obj_ptr->cy = atof(val_str);
break;
case 40:
// Radius
obj_ptr->cr = atof(val_str);
break;
case 50:
// Start Angle
obj_ptr->sa = atof(val_str);
break;
case 51:
// End Angle
obj_ptr->ea = atof(val_str);
break;
case 39:
// Thickness
obj_ptr->width = atoi(val_str);
break;
case
62:
// Color
obj_ptr->color = atoi(val_str);
break;
default:
break;
}
}
}
}
} while(!!code &&
code!=0);
// コードが無くなるまでループ
obj_ptr->obj_type = OBJ_ARC;
obj_ptr->obj_index = obj_index;
obj_ptr->block = -1;
// ARCは中心、半径、スタート、エンドアングルで定義されるため、端点を計算する
obj_ptr->x1 = obj_ptr->cx +
cos(obj_ptr->sa/A_RAD) * obj_ptr->cr;
obj_ptr->y1 = obj_ptr->cy +
sin(obj_ptr->sa/A_RAD) * obj_ptr->cr;
obj_ptr->x2 = obj_ptr->cx +
cos(obj_ptr->ea/A_RAD) * obj_ptr->cr;
obj_ptr->y2 = obj_ptr->cy +
sin(obj_ptr->ea/A_RAD) * obj_ptr->cr;
obj_ptr->prev_obj_ptr =
obj_last_ptr;
// 現在の前へ1つ前のポインタを設定
if (obj_index >= 1)
obj_last_ptr->next_obj_ptr =
obj_ptr; // 1つ前の次へ現在のポインタを設定
obj_ptr->next_obj_ptr = (OBJ
*)NULL;
// 現在の次はNULL
obj_last_ptr =
obj_ptr;
// ラストポインタを設定
obj_index++;
// 連番をインクリメント
}
// ・
// ・
// ARC以外の処理
// ・
// ・
}
このプログラムを前回のテスト図形で実行した結果が以下です。動的メモリにデータを入れたあとその内容を表示したものです。緑でコメントを入れました。
>ARC[0] // 左側のARC
style=0 color=0 width=0
layer=100 cw=1
cx=170.000000 cy=100.000000
cr=130.000000
x1=50.000000 y1=150.000000
x2=50.000000 y2=50.000000 //
計算で出した端点
sa=157.380135 ea=202.619865
>ARC[1] // 右側のARC
style=0 color=0 width=0
layer=100 cw=1
cx=30.000000 cy=100.000000
cr=130.000000
x1=150.000000 y1=50.000000
x2=150.000000 y2=150.000000
// 計算で出した端点
sa=337.380135 ea=22.619865
>LINE[2] // 上側の直線
style=0 color=0 width=0
layer=100 cw=1
cx=0.000000 cy=0.000000
cr=0.000000
x1=150.000000 y1=150.000000
x2=50.000000 y2=150.000000
sa=0.000000 ea=0.000000
>LINE[3] //
下側の直線
style=0 color=0 width=0
layer=100 cw=1
cx=0.000000 cy=0.000000
cr=0.000000
x1=50.000000 y1=50.000000
x2=150.000000 y2=50.000000
sa=0.000000 ea=0.000000
>CIRCLE[4]
// 原点を表すマゼンタの円
style=0 color=13 width=5
layer=100 cw=1
cx=100.000000 cy=0.000000
cr=5.000000
x1=0.000000 y1=0.000000
x2=0.000000 y2=0.000000
sa=0.000000 ea=0.000000
>TEXT[5] //
depth,speedのテキスト
string style=0
color=0 width=0 layer=-1 cw=0
cx=60.487805 cy=158.048780
cr=0.000000
x1=0.000000 y1=0.000000
x2=0.000000 y2=0.000000
sa=0.000000 ea=0.000000
// レイヤ情報
>[TEXT]: layer=-1 cw=0
depth=1.000000 step=1.000000 speed=80 depth=1.0/1.0 speed=80
各オブジェクトとレイヤ情報のテキストが正しく読み込めていることを確認ました。
次回は各オブジェクトの接続を辿ってブロックを抽出するプログラムを作成する予定です。