DXFのレイヤー・線種・色を読む|共通グループコード8・6・62とBYLAYERの仕組み

DXFからLINEやCIRCLE、LWPOLYLINEなどの形状を読み取れるようになると、次に必要になるのが図形の属性です。

CAD上では同じLINEでも、中心線、外形線、寸法補助線などで意味が異なることがあります。その違いを表す代表的な情報が、レイヤー、線種、色、線幅です。

DXFではこれらの属性の多くが、LINEだけに固有の情報ではなく、さまざまな図形に共通するグループコードとして記録されます。

代表的なものは次のとおりです。

グループコード意味
8レイヤー名
6線種名
62色番号
370線幅

AutodeskのDXF Referenceでは、これらを多くのグラフィカルオブジェクトに共通する属性として定義しています。

ただし、DXF解析では単に「コード62を読めば色が分かる」と考えるだけでは不十分です。

重要なのがBYLAYERです。

目次

グループコード8はレイヤー名

図形が所属するレイヤーはグループコード8で表されます。

たとえば概念的に、

0
LINE
8
CENTER
10
0.0
20
0.0
11
100.0
21
0.0

というエンティティがあれば、このLINEはCENTERというレイヤーに所属しています。

コード8はDXFグループコードの数値リファレンスでもLayer nameとして定義されています。

Pythonで単純に取り出すなら、

layer = entity.get(8)

のような処理になります。

しかし、レイヤー名を取得しただけでは、その図形が最終的にどの色・線種・線幅で表示されるかまでは分かりません。

そこでLAYERテーブルが必要になります。

LAYERテーブルにはレイヤー側の属性がある

DXFではレイヤーそのものの定義がLAYERシンボルテーブルに記録されます。

AutodeskのLAYERリファレンスでは、主に、

コード意味
2レイヤー名
70フラグ
62色番号
6線種名
290印刷フラグ
370線幅

などが定義されています。

つまり、

ENTITIES
    ↓
LINE
    ↓ code 8
CENTER

という参照を、

TABLES
    ↓
LAYER
    ↓
CENTER

へ結び付けることで、そのレイヤーの属性を調べられます。

この構造はプログラム設計上かなり重要です。

図形データとレイヤー定義を別々に読み取り、あとから参照関係を解決する必要があるからです。

線種はグループコード6

図形固有の線種はグループコード6で表されます。

ただし、Autodeskの共通エンティティコードでは、コード6は線種がBYLAYERでない場合に存在する属性として説明されています。既定値はBYLAYERです。

つまり、コード6が存在しないからといって、

「線種情報がない」

とは限りません。

むしろ、

「この図形では個別の線種指定をしておらず、レイヤー側の線種を使う」

という意味になる場合があります。

この違いはDXFパーサーで非常に重要です。

BYLAYERとは

BYLAYERは、図形自身に表示属性を固定せず、所属レイヤーの属性を使用する考え方です。

たとえば、

図形
layer = CENTER
linetype = BYLAYER

で、LAYERテーブル側が、

CENTER
linetype = CENTER

なら、最終的な線種はレイヤー側のCENTERになります。

したがってレンダラーでは、

if entity_linetype == "BYLAYER":
    resolved_linetype = layer.linetype
else:
    resolved_linetype = entity_linetype

というような属性解決処理が必要です。

DXFファイルに書かれている値と、最終的に画面へ表示すべき値は必ずしも同じではありません。

色はグループコード62

AutoCAD Color Index、いわゆるACIによる色指定にはグループコード62が使われます。

共通エンティティコードでは、

  • 0:BYBLOCK
  • 256:BYLAYER

として定義されています。

つまり、

62
256

なら、その図形の色はレイヤーから継承されます。

一方、

62
3

のように具体的なACI値を持っていれば、図形側で色が指定されています。

Autodeskのentmakeの例でも、グループコード62によるACI色指定が示されています。

True Colorにも注意する

DXFの色はACIだけとは限りません。

Autodeskの共通グループコードには、コード420として24-bit color valueも定義されています。

さらにAutodeskは、コード62のACIとコード420のTrue Colorが競合した場合、True Color側が使用されることを説明しています。

したがって本格的なDXFレンダラーでは、

True Color
↓
ACI
↓
BYLAYER

のように、どの指定を優先して最終色を決定するかという処理が必要になります。

単純な初期実装ならACIとBYLAYERだけから始め、その後True Colorへ拡張する方法もあります。

線幅はグループコード370

線幅はグループコード370で扱われます。

Autodeskは共通エンティティコードとLAYERテーブルの両方で370をLineweightとして定義しています。

これも色や線種と同様に、図形側とレイヤー側の属性を考慮して最終表示を決める必要があります。

したがってDXFレンダラーでは、

class ResolvedStyle:
    layer: str
    color: object
    linetype: str
    lineweight: object

のような「解決済みスタイル」を作っておくと扱いやすくなります。

DXFパーサーでは属性を2段階で扱う

DXF解析では、

読み取り

と、

意味の解決

を分けると設計が整理されます。

たとえば最初のパーサーでは、

{
  "type": "LINE",
  "layer": "CENTER",
  "color": 256,
  "linetype": "BYLAYER"
}

というDXFに記録された状態を保持します。

次の処理でLAYERテーブルを参照し、

{
  "type": "LINE",
  "layer": "CENTER",
  "resolved_color": 3,
  "resolved_linetype": "CENTER"
}

のような実際に使用する属性へ変換します。

この2段階構造にすると、

  • DXF原文の解析
  • 属性継承
  • レンダリング
  • 図面検査

を分離できます。

レイヤー定義を辞書化する

Pythonでは、LAYERテーブルをレイヤー名をキーとした辞書へ変換すると扱いやすくなります。

layers = {
    "0": {
        "color": 7,
        "linetype": "CONTINUOUS",
    },
    "CENTER": {
        "color": 3,
        "linetype": "CENTER",
    },
}

図形が、

entity = {
    "layer": "CENTER",
    "color": 256,
    "linetype": "BYLAYER",
}

なら、

layer = layers[entity["layer"]]

color = (
    layer["color"]
    if entity["color"] == 256
    else entity["color"]
)

linetype = (
    layer["linetype"]
    if entity["linetype"] == "BYLAYER"
    else entity["linetype"]
)

のように解決できます。

実際にはBYBLOCK、True Color、線幅などもあるため処理は増えますが、基本構造は同じです。

コードの並び順には依存しない

DXFを自作パーサーで読む場合、グループコードの掲載順をそのまま固定フォーマットだと考えないことも重要です。

Autodeskは、DXFコード表に掲載された順番が変わる可能性があるため、コード順へ依存するプログラムを書かないよう明示しています。

したがって、

8の次は必ず6
6の次は必ず62

のような実装は避けます。

コード番号を判定して、

match code:
    case 8:
        ...
    case 6:
        ...
    case 62:
        ...

のように処理する方が堅牢です。

レイヤーを読めると図面解析の幅が広がる

レイヤー情報は単なる表示属性ではありません。

実際の図面ではレイヤー名によって、

  • 外形線
  • 中心線
  • 寸法
  • 配管
  • 部品
  • 補助線

などを分類している場合があります。

そのため、

DXF
↓
図形抽出
↓
レイヤー分類
↓
属性解決
↓
図面解析

という処理が可能になります。

たとえば特定レイヤーだけを抽出するなら、

center_entities = [
    entity
    for entity in entities
    if entity["layer"] == "CENTER"
]

のように処理できます。

さらにレイヤー命名規則が標準化されている環境なら、レイヤー名そのものを設計データとして利用できる可能性があります。

ただし、レイヤー名の意味は企業・案件・テンプレートによって異なるため、一般規則として決めつけてはいけません。

まとめ

DXFでは図形形状だけでなく、レイヤー・線種・色・線幅といった共通属性もグループコードとして保持されています。

特に重要なのは、

  • コード8:レイヤー
  • コード6:線種
  • コード62:色
  • コード370:線幅

です。

ただし、図形側の値だけを読んでも最終表示を決定できない場合があります。

BYLAYERが指定されている場合には、

ENTITIES
↓
図形のレイヤーを取得
↓
LAYERテーブルを参照
↓
色・線種・線幅を解決
↓
表示・解析

という処理が必要です。

LINEやCIRCLE、LWPOLYLINEなどの形状解析と、レイヤーや色などのスタイル解析を分離しておけば、DXFパーサーを将来レンダラーや図面検査ツールへ発展させやすくなります。

参考情報

Autodesk AutoCAD DXF ReferenceのCommon Group Codes for Entities、LAYER、DXF Group Codes in Numerical Order Referenceを参照。

参考になったらシェアしてください
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

機械設計・油圧・CAD・Python・AIなど、ものづくりに関わる技術を扱っています。工学知識を整理・構造化し、設計や自動化に再利用できる形へ変えていくことを目指しています。

目次