きゃんブロ

きゃんなブログ

自作npm、square-dxf-checker完成までの道のり#2 DXFの構造

こんにちは。
aya-kyanです。

 

「自作npm、square-dxf-checker完成までの道のり」というタイトルでDXFの図形を判断し、面積を計算するというnpmを作成した過程について書いています。
今回は、2番目の記事です。

 

この記事では、DXFファイルからどのように座標情報や辺の情報を取得したのかについて書きます。
前回の記事は下記よりどうぞ。

aya-kyan.hatenablog.com

 

 

DXFの構造について

まずは、下記のようにわかりやすく書いてくれているものがあるので、この二つの記事から読むことをお勧めします。

qiita.com

qiita.com

 

これから説明することを理解するには、下記を押さえればOKです。

  • DXFは2行でひとつ
  • グループコードというものがある

こちらをもとに話を進めていきます。
以後、DXFの中身を記載する際は全て2行を1行にまとめたものを記載します。
先にお勧めした記事をめんどくさくて読んでおらず、「2行を1行...?」とwakaran状態になっている方は、元々のdxfファイルの中身だけ押さえておいてください。
こんな感じになっています。

0
SECTION
  2
HEADER
  9
$ACADVER
  1
AC1027
  9
$ACADMAINTVER
 70
   125
  9
$DWGCODEPAGE
  3
ANSI_932
  9
$LASTSAVEDBY
  1
thangas
  9
$REQUIREDVERSIONS
160
                 0
  9
$INSBASE
 10
.
.
.
#続く

今回、開発をするにあたり長方形のDXFファイルを用意しました。
開くと、下記のようになっています。

image.png

始点と終点を見つける

AutoCADの公式を見たところ、DXFでは

  • 10, 20, 30でx, y, z軸の始点
  • 11, 21, 31でx, y, z軸の終点

と定義づけをしているそうです。

 

これに従い、DXFファイルの中身を見て寸法らしきものを探してみました。
すると、10~30と、11~31がまとまって表示されている部分がありました。

 100 AcDbEntity
  8 表示
100 AcDbLine
 10 293.924544
 20 199.219757
 30 5.0
 11 293.924544
 21 99.219757
 31 5.0
  0 LINE
  5 B3
330 70

10, 20, 30でx, y, z軸の始点なので、始点は x 293.924544, y 199.219757, z 5.0
11, 21, 31でx, y, z軸の終点なので、終点は x 293.924544, y 99.219757, z 5.0

これで始点と終点を見つけることができました。

 

辺の長さを出し、辺が垂直方向か水平方向か判断する

上記で見つけた、始点から終点までの差分を計算してみると、
x = 293.924544 - 293.924544 = 0
y = 199.219757 - 99.219757 = 100
z = 5.0 - 5.0 = 0
となります。始点から終点にかけて、y軸方向に100の長さが表現されているとわかりますね。

ここで、最初にあげたDXFの図形を思い出してみます。

image.png

縦方向の100の長さの辺があります。

このことから、始点から終点のx座標の差分が0、かつ始点から終点のy座標には差分があるという場合はこの辺は垂直方向であると言えます。

横方向も同じようにして求めることができます。

  • 始点から終点のy座標の差分が0
  • 始点から終点のx座標の差分がある

という場合は、辺は水平方向であると言えます。

正面図の線分なのか側面図の線分なのか見分ける

正面図と、側面図の線分情報を見比べてみます。

正面図の線分情報

 0 LINE
  5 159
330 70
100 AcDbEntity
  8 表示
100 AcDbLine
 10 293.924544
 20 99.219757
 30 5.0
 11 93.924544
 21 99.219757
 31 5.0

側面図の線分情報

  0 LINE
  5 15A
330 70
100 AcDbEntity
  8 表示
100 AcDbLine
 10 324.126701
 20 199.219757
 30 100.0
 11 324.126701
 21 99.219757
 31 100.0
210 -1.0
220 0.0000000000002967
230 0.0000000000002967

二つを見比べると、側面図の方にだけ、210~230のグループコードがあることがわかります。
なぜ後者のグループコードが側面図の線分情報だとわかったかというと、AutoCADの公式によれば、210~230は押し出し方向のグループコードのようでした。
このことから、線分情報の中に210~230のグループコードが見つかった場合は側面図の線分であると特定することができます。

寸法線を見分ける

今度は、モデルの線分情報と、寸法線の線分情報だと思われるものを見比べてみます。

モデルの線分情報

100 AcDbEntity
  8 表示
100 AcDbLine
 10 293.924544
 20 199.219757
 30 5.0
 11 293.924544
 21 99.219757
 31 5.0
  0 LINE
  5 157
330 70

寸法線と思われる線分情報

100 AcDbEntity
  8 Dimensions
440 16777216
370 -2
100 AcDbLine
 10 327.626701
 20 209.719757
 30 0.0
 11 330.626701
 21 209.719757
 31 0.0
  0 SOLID
  5 19D
330 F9

違いを見つけられましたか?
答えは、寸法線の線分情報には「Dimensions」が含まれていることです。
上記の2列ずつにまとめたコード例で言うと、2行目です。

上記のような感じで、あっという間に下記情報の特定が出来ました。

  • 始点と終点
  • 辺の長さと向き
  • 側面図と正面図の線分
  • 寸法線

これらを利用し、寸法線は除外し、図形を構成している線分データのみから情報を取り出すようにコードを書きます。
コードは、githubをご確認ください。

ターミナル上に出力したものが下記です。(現時点で説明しているもののみを掲載)

【Side View】
Vertical line in side view:
 [
  {
    StartPoint: [ '324.126701', '199.219757' ],
    EndPoint: [ '324.126701', '99.219757' ]
  },
  {
    StartPoint: [ '334.126701', '199.219757' ],
    EndPoint: [ '334.126701', '99.219757' ]
  }
]
Length of first line: 100
Length of second line: 100
These lines are same length.

Horizontal line in side view:
 [
  {
    StartPoint: [ '324.126701', '99.219757' ],
    EndPoint: [ '334.126701', '99.219757' ]
  },
  {
    StartPoint: [ '324.126701', '199.219757' ],
    EndPoint: [ '334.126701', '199.219757' ]
  }
]
Length of first line: 10
Length of second line: 10
These lines are same length.

Thickness: 10 

【Front View】
Vertical line in front view:
 [
  {
    StartPoint: [ '293.924544', '199.219757' ],
    EndPoint: [ '293.924544', '99.219757' ]
  },
  {
    StartPoint: [ '93.924544', '99.219757' ],
    EndPoint: [ '93.924544', '199.219757' ]
  }
]
Length of first line: 100
Length of second line: 100
These lines are same length.

Horizontal line in front view:
 [
  {
    StartPoint: [ '93.924544', '199.219757' ],
    EndPoint: [ '293.924544', '199.219757' ]
  },
  {
    StartPoint: [ '293.924544', '99.219757' ],
    EndPoint: [ '93.924544', '99.219757' ]
  }
]
Length of first line: 200
Length of second line: 200
These lines are same length.

参考