DXFのTEXTとMTEXTを読む|文字列・配置・高さ・回転・位置合わせの基本

「DXFのTEXTとMTEXTを読む|文字列・配置・高さ・回転・位置合わせの基本」の内容を表す技術イラスト

DXFからLINE、CIRCLE、LWPOLYLINEなどを読み取れるようになると、次に扱いたくなるのが文字情報です。

機械図面には、部品名、注記、材料、加工指示、座標値、識別番号など、多くの情報が文字として記録されています。

DXFでは代表的な文字エンティティとして、

  • TEXT
  • MTEXT

があります。

TEXTは基本的に単一行文字、MTEXTは矩形領域を持つ複数行文字として考えると理解しやすいでしょう。

ただし、文字列だけを取得すれば十分というわけではありません。

DXFから元の図面に近い状態を再現したり、文字位置を使って図面解析したりするなら、

  • 文字列
  • 挿入点
  • 文字高さ
  • 回転
  • 文字スタイル
  • 水平・垂直位置合わせ
  • MTEXTの矩形幅
  • 文字の向き

まで扱う必要があります。

この記事では、TEXTとMTEXTの構造を、将来PythonパーサーやDXFビューアへ利用できる形で整理します。

目次

TEXTは単一行文字を表す

TEXTエンティティの主要なグループコードには、次のものがあります。

コード意味
1文字列
10 / 20 / 30第1位置合わせ点
40文字高さ
50文字回転
7文字スタイル名
41X方向の幅係数
51斜体角度
71文字生成フラグ
72水平方向の位置合わせ
73垂直方向の位置合わせ
11 / 21 / 31第2位置合わせ点

AutodeskのDXF Referenceでも、この構造がTEXTエンティティの属性として定義されています。

最初に解析するなら、まず、

1
10 / 20
40
50
7
72 / 73
11 / 21

を理解するとよいでしょう。

文字列本体はグループコード1

TEXTの実際の文字列はコード1に格納されます。

概念的には、

0
TEXT
1
SHAFT
10
100.0
20
50.0
40
5.0

のようなデータがあった場合、

SHAFT

が文字列です。

Python側では、正規化後に、

text = {
    "type": "TEXT",
    "content": "SHAFT",
}

のように保持できます。

文字情報を将来RAGや図面検索へ利用したい場合、DXFの生コードだけでなく、まずcontentとして明示的に取り出しておくと扱いやすくなります。

コード10・20は文字の位置に関係する

TEXTではコード10、20、30が第1位置合わせ点を表します。

通常の2D DXFなら、

10
100.0
20
50.0

を、(x,y)=(100,50)(x,y)=(100,50)

として読み取れます。

ただしTEXTでは、位置合わせ設定によってコード10側だけを見てはいけない場合があります。

Autodeskによると、コード72または73が非ゼロ、つまり左基準・ベースライン以外の位置合わせを行っている場合、第2位置合わせ点であるコード11/21/31が意味を持ちます。

この点はTEXTパーサーで重要です。

TEXTの位置合わせは72と73で決まる

コード72は水平位置合わせです。

代表値は、

72水平方向
0Left
1Center
2Right
3Aligned
4Middle
5Fit

です。

コード73は垂直位置合わせです。

73垂直方向
0Baseline
1Bottom
2Middle
3Top

です。

たとえば、

72 = 1
73 = 2

なら、水平Center・垂直Middleという組み合わせになります。

ここで注意したいのが位置座標です。

Autodeskは、72または73が非ゼロなら、第1位置合わせ点は表示位置の決定にそのまま使われず、第2位置合わせ点と文字サイズ・スタイルから位置が計算されると説明しています。

したがって、

position = (group_10, group_20)

だけでTEXTの表示位置を決める実装は不十分です。

TEXTの第2位置合わせ点

コード11、21、31は第2位置合わせ点です。

ただし常に有効なわけではありません。

位置合わせが通常の、

72 = 0
73 = 0

なら、第2位置合わせ点は意味を持ちません。

反対に、CenterやRight、Top、Middleなどを使用すると重要になります。

そのため、正規化データでは、

text = {
    "type": "TEXT",
    "first_alignment_point": (100.0, 50.0),
    "second_alignment_point": (120.0, 50.0),
    "horizontal_alignment": 1,
    "vertical_alignment": 0,
}

のように両方を保持しておく方が安全です。

パーサー段階で「不要そうだから削除する」のではなく、まず原情報を保持し、レンダリング段階で意味を解決する構成が適しています。

文字高さはコード40

TEXTの文字高さはコード40です。

たとえば、

40
5.0

なら、DXF上の文字高さは5.0です。

ただし、その5.0が実世界で5 mmを意味するかどうかは、図面単位やDXF全体の条件によります。

DXF解析では、

{
    "height": 5.0
}

と値を取得する処理と、

この図面の1単位は何mmか

を判断する処理は分離した方がよいでしょう。

文字だけ特別に単位換算するのではなく、図形座標と同じ座標系・単位系の中で扱います。

TEXTの回転

TEXTではコード50が文字の回転に使用されます。

DXFの一般グループコードリファレンスでは、50〜58は角度値を扱い、DXFファイルへの出力時は度で表現されるとされています。

そのため、Python内部でラジアンを使うなら、

from math import radians

rotation_rad = radians(rotation_deg)

のように変換できます。

内部データ構造では単位を曖昧にせず、

{
  "rotation": {
    "value": 30.0,
    "unit": "deg"
  }
}

のように保持する方法もあります。

角度を単なる30.0として保存すると、後から度かラジアンか分からなくなるためです。

文字スタイルはコード7

TEXTのコード7は文字スタイル名です。

省略された場合の既定はSTANDARDです。

つまりTEXT自身が、

7
STANDARD

のように文字スタイルを参照します。

ここでもレイヤー属性と同じように、

TEXT
↓
text style name
↓
STYLEテーブル
↓
実際の文字スタイル定義

という参照関係があります。

文字を完全にレンダリングするなら、TEXTエンティティだけではなくSTYLEテーブルも参照する必要があります。

しかし図面検索や注記抽出が目的なら、まず文字列・位置・高さ・回転を取得するだけでも多くの用途に利用できます。

MTEXTは複数行文字を扱う

MTEXTはTEXTより多くのレイアウト情報を持ちます。

主要コードには、

コード意味
10 / 20 / 30挿入点
40初期文字高さ
41参照矩形幅
71アタッチメント位置
72描画方向
1文字列
3追加文字列
7文字スタイル
11 / 21 / 31X軸方向ベクトル
50回転
73行間スタイル
44行間係数

などがあります。

TEXTと比べて特徴的なのは、参照矩形の幅とアタッチメントポイントを持つことです。

MTEXTの挿入点

MTEXTではコード10/20/30が挿入点です。

10
100.0
20
50.0

なら、その位置がMTEXT配置の基準になります。

ただし、どの部分がその座標へ接続されるかはコード71によって変わります。

コード71はアタッチメント位置

MTEXTのコード71は、矩形に対してどの位置を基準点にするかを指定します。

Autodeskでは1〜9が、

Top left       Top center       Top right
Middle left    Middle center    Middle right
Bottom left    Bottom center    Bottom right

の9位置に対応します。

したがって、MTEXTを表示するときは、

挿入点
+
アタッチメント
+
矩形幅
+
文字高さ

を組み合わせて考えます。

この構造は、TEXTの72/73による位置合わせと似ていますが、同じデータ形式ではありません。

TEXTとMTEXTを無理に同じDXFグループコード構造として処理するより、最後に共通の内部モデルへ変換する方が整理しやすくなります。

MTEXTの幅はコード41

MTEXTには参照矩形幅があります。

コード41がその幅です。

つまりMTEXTは単なる、

座標 + 文字列

ではなく、

挿入点
+
幅
+
文字高さ
+
配置位置
+
文字列

を持つレイアウト要素として考える必要があります。

Web上でDXFビューアを作る場合も、MTEXTの幅を無視すると改行位置や配置が大きく変わる可能性があります。

MTEXTの長い文字列はコード3に分割される

MTEXT解析で特に重要なのが文字列の分割です。

Autodeskによると、文字列が250文字未満ならコード1だけに格納されます。

250文字を超える場合は、コード3に250文字単位のチャンクが格納され、最後の部分がコード1に格納されます。

したがって、

content = entity.get(1)

だけでは長いMTEXTを途中までしか取得できない可能性があります。

概念的には、

3 → 250文字
3 → 250文字
3 → 250文字
1 → 最後の残り

という構造になります。

したがって、出現順を保って連結する必要があります。

def collect_mtext_content(groups):
    parts = []

    for code, value in groups:
        if code in (3, 1):
            parts.append(value)

    return "".join(parts)

ここでも、DXFを単純な、

dict[int, value]

へ変換すると問題が起こります。

コード3が複数回出現するため、後の値で上書きされるからです。

LWPOLYLINEの頂点と同じく、DXFには同一コードが繰り返されるエンティティがあることを前提にしたパーサーが必要です。

TEXTとMTEXTを共通モデルへ変換する

DXF解析後の処理で毎回グループコードを扱うと、ロジックが複雑になります。

そこで、

DXF
↓
TEXT / MTEXT parser
↓
正規化
↓
共通Textモデル

という構造にすると再利用しやすくなります。

たとえば、

from dataclasses import dataclass
from typing import Literal


@dataclass
class TextEntity:
    entity_type: Literal["TEXT", "MTEXT"]
    content: str
    x: float
    y: float
    height: float
    rotation_deg: float | None
    style: str

という基本モデルを作れます。

TEXT固有属性は、

horizontal_alignment
vertical_alignment
second_alignment_point

として追加します。

MTEXT固有属性は、

reference_width
attachment_point
drawing_direction

として別フィールドへ持たせます。

こうすると、元データの違いを残しながら、

全文検索
座標検索
文字高さによる分類
レイヤー別抽出
レンダリング

などの共通処理が可能になります。

位置情報を使うと図面解析へ発展できる

文字を位置付きデータとして取得すると、単なる全文検索以上のことができます。

たとえば、

文字列
+
座標
+
レイヤー
+
近傍図形

を関連付けることで、

  • 部品番号と図形の対応推定
  • 注記の抽出
  • 図面タイトル欄の解析
  • 特定領域の文字検索
  • CAD図面のインデックス作成

などへ発展できます。

たとえばJSONへ、

{
  "type": "TEXT",
  "content": "SHAFT",
  "position": {
    "x": 100.0,
    "y": 50.0
  },
  "height": 5.0,
  "layer": "TEXT",
  "style": "STANDARD"
}

として保存すれば、文字列だけでなく空間情報も検索できます。

DXF原文と正規化データは分ける

解析システムを長期的に使うなら、

raw DXF groups

と、

normalized engineering data

を分離しておくと安全です。

たとえば、

{
    "raw": [
        (0, "TEXT"),
        (1, "SHAFT"),
        (10, 100.0),
        (20, 50.0),
        (40, 5.0),
    ],
    "normalized": {
        "type": "TEXT",
        "content": "SHAFT",
        "position": [100.0, 50.0],
        "height": 5.0,
    },
}

という構造です。

正規化ロジックに問題が見つかっても、元のDXF値へ戻って再検証できます。

これはCADデータを知識資産として扱う場合に有効です。

最初から完全な文字レンダラーを目指さない

TEXTとMTEXTを正確にAutoCADと同じ外観で再現するには、文字スタイル、フォント、幅係数、斜体、制御コード、OCS、MTEXT書式など、さらに多くの処理が必要になります。

したがって実装を段階化するとよいでしょう。

Phase 1
文字列を取得

Phase 2
座標・高さ・回転を取得

Phase 3
位置合わせを解決

Phase 4
MTEXT幅・配置を処理

Phase 5
文字スタイル・フォントを解決

Phase 6
高精度レンダリング

図面検索が目的ならPhase 2程度でも十分役立つ場合があります。

一方、CADビューアを作るなら後段まで必要になります。

目的に応じて必要な精度を決めることが重要です。

まとめ

DXFのTEXTでは、まず、

  • コード1:文字列
  • コード10/20/30:第1位置合わせ点
  • コード40:文字高さ
  • コード50:回転
  • コード7:文字スタイル
  • コード72/73:水平・垂直位置合わせ
  • コード11/21/31:第2位置合わせ点

を押さえるとよいでしょう。

MTEXTでは、

  • コード1・3:文字列
  • コード10/20/30:挿入点
  • コード40:文字高さ
  • コード41:参照矩形幅
  • コード71:アタッチメント位置
  • コード7:文字スタイル

が基本になります。

特に重要なのは、DXFの文字を単なる文字列としてではなく、

文字
+
座標
+
高さ
+
向き
+
配置
+
スタイル

を持つ空間データとして扱うことです。

この形へ正規化できれば、DXFビューアだけでなく、図面検索、注記抽出、CADデータベース化、図面チェック、自動分類などへ再利用できます。

参考情報

  • Autodesk AutoCAD DXF Reference — TEXT
  • Autodesk AutoCAD DXF Reference — MTEXT
  • Autodesk AutoCAD DXF Reference — Group Codes in Numerical Order
参考になったらシェアしてください
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

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

目次