DXFのPOLYLINEとVERTEXを読む|旧形式ポリライン・SEQEND・LWPOLYLINEとの違い

「DXFのPOLYLINEとVERTEXを読む|旧形式ポリライン・SEQEND・LWPOLYLINEとの違い」の内容を表す技術イラスト

DXFでポリラインを扱うとき、LWPOLYLINEだけを読めれば十分とは限りません。

古いDXFや、3Dポリライン、ポリゴンメッシュ、polyface meshを含むデータでは、POLYLINEエンティティが現れます。

このPOLYLINEは、LWPOLYLINEのように1エンティティ内部へ頂点座標をまとめて持つ構造ではありません。

基本的には、

POLYLINE
VERTEX
VERTEX
VERTEX
...
SEQEND

という複数エンティティからなるシーケンスとして保存されます。

AutodeskのDXF仕様でも、POLYLINE本体とVERTEXは別エンティティとして定義され、SEQENDがその頂点列の終端を示します。

DXFパーサーを作るなら、この構造を理解しておくことが重要です。

目次

POLYLINEは頂点そのものを持たない

LWPOLYLINEではコード10・20が繰り返され、同じエンティティ内部に頂点が並びます。

一方、旧形式のPOLYLINEでは、POLYLINE本体は主として、

  • 種類
  • 閉じているか
  • 2Dか3Dか
  • デフォルト幅
  • elevation
  • mesh情報

などを保持します。

実際の頂点座標は、後続するVERTEXエンティティに格納されます。

つまり、

POLYLINE = ヘッダ
VERTEX   = 頂点データ
SEQEND   = 終端

と考えると理解しやすくなります。

POLYLINE本体の重要なグループコード

Autodesk公式仕様で、POLYLINEには次のようなコードがあります。

コード意味
10,20,30ダミー点・elevation
39thickness
40デフォルト開始幅
41デフォルト終了幅
70POLYLINEフラグ
71,72meshの頂点数
73,74smooth surface density
75曲面フィット方式
210,220,230extrusion direction

特に重要なのがコード70です。

これはビットフラグとして使われます。

代表的な値は、

値意味
1閉じたポリライン
2curve-fit vertexあり
4spline-fit vertexあり
83D polyline
163D polygon mesh
32meshをN方向にも閉じる
64polyface mesh
128linetypeを頂点間で連続生成

です。

単純な列挙値ではないため、

is_closed = bool(flags & 1)
is_3d = bool(flags & 8)
is_mesh = bool(flags & 16)
is_polyface = bool(flags & 64)

のように判定します。

コード66はどう扱うか

古いDXFを見るとPOLYLINEに、

66
1

が付いている場合があります。

コード66は、かつて後続エンティティが存在することを示すフラグとして使われていました。

しかしAutodeskの現行DXFリファレンスでは、POLYLINEのコード66はobsolete、存在しても無視してよいとされています。

つまり現代的なパーサーでは、

コード66があるから頂点列を読む

のではなく、

POLYLINEを開始したら、後続VERTEXをSEQENDまで読む

という構造として処理する方が明確です。

VERTEXから座標を読む

POLYLINEに続く各頂点はVERTEXエンティティです。

基本座標は、

10 → X
20 → Y
30 → Z

で表されます。

たとえば、

0
VERTEX
10
100.0
20
50.0
30
0.0

なら、P=(100, 50, 0)P=(100,\ 50,\ 0)

という頂点です。

複数のVERTEXを順番に収集することで、ポリライン形状を再構築できます。

2Dと3Dでは座標系にも注意する

Autodeskの仕様では、VERTEX座標は2Dの場合はOCS、3Dの場合はWCSとして扱われます。

そのため本格的なDXF処理では、

POLYLINE flags
↓
2D / 3D判定
↓
VERTEX取得
↓
必要ならOCS→WCS変換

という段階を設ける方が安全です。

単純なXY図面だけを対象にする初期実装なら、対応範囲を「2D・標準extrusionのみ」と明示して始める方法もあります。

VERTEXにもコード70がある

注意したいのは、POLYLINEだけでなくVERTEXにもコード70が存在することです。

意味は異なります。

VERTEXの主なフラグには、

  • 1:curve-fittingで追加された頂点
  • 8:spline-fittingで作られた頂点
  • 16:spline frame control point
  • 32:3D polyline vertex
  • 64:3D polygon mesh vertex
  • 128:polyface mesh vertex

などがあります。

したがって、

if group_code == 70:

だけで処理を決めることはできません。

必要なのは、

entity type
+
group code

の組み合わせです。

これはDXF全体に共通する重要な設計原則です。

VERTEXにもbulgeがある

2Dポリラインでは、VERTEXのコード42にbulgeを持つことがあります。

Autodesk仕様ではbulgeは、b=tan⁡(θ4)b=\tan\left(\frac{\theta}{4}\right)

で定義されます。

ここでθ\thetaは、その頂点から次の頂点へ向かう円弧の包含角です。

したがって、b=0b=0

なら直線、b=1b=1

なら半円に相当します。

負のbulgeは逆方向の円弧を表します。

これはLWPOLYLINEのbulgeと同じ考え方です。LWPOLYLINEでもコード42が各頂点に対応するbulgeとして定義されています。

つまり内部モデルでは、両形式を同じ構造へ変換できます。

SEQENDで頂点列が終わる

旧POLYLINEでは、VERTEXが何個続くかを単純な頂点数だけで読むのではなく、SEQENDまでを一つのシーケンスとして扱うのが基本です。

Autodesk仕様ではSEQENDは、POLYLINEのVERTEX列や、属性を持つINSERTのATTRIB列などの終端を示します。

したがってパーサーは概念的に、

vertices = []

while True:
    entity = next_entity()

    if entity.type == "VERTEX":
        vertices.append(parse_vertex(entity))

    elif entity.type == "SEQEND":
        break

のような状態遷移を持つことになります。

LWPOLYLINEとの最大の違い

LWPOLYLINEは構造がより単純です。

Autodesk仕様では、

  • コード90:頂点数
  • コード10・20:各頂点座標
  • コード40・41:開始・終了幅
  • コード42:bulge
  • コード70:closedなどのフラグ

が1つのLWPOLYLINEエンティティ内部に格納されます。

つまり、

LWPOLYLINE
 ├─ vertex
 ├─ vertex
 └─ vertex

です。

旧形式は、

POLYLINE
↓
VERTEX
↓
VERTEX
↓
VERTEX
↓
SEQEND

です。

この違いはDXFパーサーの設計に直接影響します。

両方を同じ内部モデルへ変換する

アプリケーション側では、POLYLINEとLWPOLYLINEをいつまでも別形式として扱う必要はありません。

読み込み時だけ形式差を吸収し、

from dataclasses import dataclass


@dataclass
class PolylineVertex:
    x: float
    y: float
    z: float = 0.0
    bulge: float = 0.0
    start_width: float = 0.0
    end_width: float = 0.0


@dataclass
class PolylineData:
    vertices: list[PolylineVertex]
    closed: bool
    is_3d: bool

のような中間モデルへ正規化できます。

すると、

POLYLINE + VERTEX + SEQEND
               ↓
          PolylineData
               ↑
           LWPOLYLINE

という構造にできます。

描画側は元のDXF形式を意識する必要がありません。

parserとgeometryを分ける

実装では、

DXF parser
↓
正規化
↓
geometry model
↓
renderer / validator / converter

に分けると再利用しやすくなります。

POLYLINE固有のSEQEND処理やコード70の判定はparser側で完結させます。

その後の、

  • SVG変換
  • Canvas描画
  • 長さ計算
  • 閉領域判定
  • DXF比較
  • JSON化

では、正規化された頂点列だけを使います。

3D POLYLINEも同じヘッダから始まる

コード70のビット8が立っている場合、POLYLINEは3D polylineです。

VERTEX側でもビット32が3D polyline vertexを示します。

したがって、

is_3d = bool(polyline_flags & 8)

を入口にして、

2D
→ OCSを考慮

3D
→ XYZをWCSとして保持

と処理を分けられます。

2D専用ビューアで3D POLYLINEを受け取った場合は、黙ってZを捨てるより、

unsupported: 3d_polyline

として明示する方がデータ品質を保てます。

POLYLINEはmeshにも使われる

旧POLYLINEが単なる折れ線だけではない点にも注意が必要です。

コード70には、

  • 16:polygon mesh
  • 64:polyface mesh

があります。

polyface meshでは、VERTEXが座標だけでなく面の定義にも使われます。

Autodesk仕様では、polyface meshの面を表すVERTEXでコード71〜74が頂点インデックスとして利用される場合があります。

したがって、

POLYLINEを見たら全部2D折れ線として読む

という実装は安全ではありません。

まずコード70でサブタイプを分類すべきです。

読み込みルールをデータ化する

POLYLINE系を将来の検証資産にするなら、次のようにルール化できます。

{
  "entity": "POLYLINE",
  "rules": {
    "sequence_end": "SEQEND",
    "vertex_entity": "VERTEX",
    "flag_code": 70,
    "closed_bit": 1,
    "3d_polyline_bit": 8,
    "polygon_mesh_bit": 16,
    "polyface_mesh_bit": 64
  }
}

さらにVERTEX側を、

{
  "entity": "VERTEX",
  "coordinate_codes": [10, 20, 30],
  "bulge_code": 42,
  "flag_code": 70
}

として分離できます。

このような構造なら、DXF仕様をPythonコードへ直書きせず、テーブル駆動型のパーサーやvalidatorへ発展させられます。

よくある失敗

旧POLYLINEを扱う際には、いくつか典型的な落とし穴があります。

POLYLINE本体に頂点座標が全部あると思うと、後続VERTEXを読み落とします。

SEQENDを無視すると、次の独立エンティティまでPOLYLINEの一部として誤認する可能性があります。

POLYLINEのコード70とVERTEXのコード70を同じ意味として扱うと、フラグ判定を誤ります。

また、POLYLINEを常に2D折れ線だと仮定すると、3D polyline、polygon mesh、polyface meshを正しく分類できません。

まとめ

旧形式のDXF POLYLINEで最も重要なのは、1エンティティだけを読んでも図形が完成しないという点です。

基本構造は、

POLYLINE
↓
VERTEX
↓
VERTEX
↓
...
↓
SEQEND

です。

POLYLINE本体で種類やフラグを読み、VERTEXから座標・幅・bulgeなどを取得し、SEQENDでシーケンスを終了します。

一方LWPOLYLINEでは、頂点情報が一つのエンティティ内部へまとめられています。

パーサーでは両形式を別々に読みながら、その後、

POLYLINE / LWPOLYLINE → 共通PolylineData

へ正規化する構造にすると、描画、計算、Web表示、JSON化、CAD変換へ再利用しやすくなります。

旧POLYLINEへの対応は単なる古い形式の互換処理ではありません。3Dポリラインやmesh系DXFを扱うための入口でもあり、DXFを汎用的な幾何データとして読むうえで重要な構造です。

参考情報

Autodesk公式DXF ReferenceのPOLYLINE仕様では、コード70の各ビット、mesh情報、elevation、extrusion directionなどが定義されています。

VERTEX仕様では、座標、幅、bulge、頂点フラグ、polyface mesh用インデックスが定義されています。

SEQENDはPOLYLINEのVERTEXシーケンスなどの終端として使用されます。

LWPOLYLINEとのデータ構造比較にはAutodesk公式LWPOLYLINE仕様を参照しました。

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

この記事を書いた人

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

目次