#1~#3で、図形の描画・レイヤーや色などの属性・寸法線の描き方を一通りまとめました。今回はその集大成として、実際の構造物を規格違いでまとめて自動作図してみます。後半では、作った図面を今度はezdxf側で読み込んで、図形データをpandasでExcelに書き出す方法も解説します。

【作図実践】今回作るもの
土木・造園の現場でおなじみのU形トラフ(U字溝)を題材にします。
JIS A 5372で規格化されたサイズごとに寸法が微妙に異なりますが、1つのコードに規格値を辞書で渡すだけで、まとめて作図できるようにします。

前提事項
今回はこれまでの描画メソッドの総復習を兼ねるため、座標の管理方法は必ずしも合理的ではありません。また、正確な形状の再現には三角関数が必要になる箇所がありますが、可読性を優先してその部分は簡略化し、寸法が入っていない辺があります。
つかだあくまで「Pythonで規格違いの構造物を同じコードから量産できる」という考え方のサンプルです。実務で使う際は、必要な精度・法規に応じて座標計算を作り直してください。
規格パラメータを辞書で管理する
U形トラフの各規格値(全幅A・全高H・内幅a・内高h・厚みなど)を辞書にまとめ、リストに格納します。

import ezdxf
from ezdxf.addons.drawing import RenderContext, Frontend
from ezdxf.addons.drawing.matplotlib import MatplotlibBackend
from ezdxf.enums import TextEntityAlignment
import matplotlib.pyplot as plt
doc = ezdxf.new("R2010", setup=True)
msp = doc.modelspace()
# JIS A 5372 に基づくU形トラフの規格値(一部抜粋)
traf_150 = {'name': "150", 'A':210,'H':185,'a':150,'h':150,'b':140,'c':35,'d':30,'e':35,'g':160,'r':30}
traf_240 = {'name': "240", 'A':330,'H':290,'a':240,'h':240,'b':220,'c':50,'d':45,'e':50,'g':240,'r':50}
traf_360A= {'name': "360A",'A':460,'H':365,'a':360,'h':300,'b':310,'c':65,'d':50,'e':65,'g':360,'r':50}
trafs = [traf_150, traf_240, traf_360A]
for layer in ["structure", "dimension", "text", "frame"]:
doc.layers.add(name=layer)
座標を計算して図形を描く
規格値から各頂点の座標を計算し、直線と円弧で断面形状を描きます。x = 500 * iで規格ごとに横にずらして並べているだけで、描画ロジック自体は共通です。
for i, traf in enumerate(trafs):
x = 500 * i
y = 0
A_point = (x, traf['H']+y)
B_point = (traf['d']+x, A_point[1])
C_center = (traf['e']+traf['r']+x, traf['c']+traf['r']+y)
D_point = (traf['A']+x, A_point[1])
E_point = (traf['A']-traf['d']+x, A_point[1])
F_center = (traf['A']-traf['e']-traf['r']+x, C_center[1])
G_point = ((traf['A']-traf['g'])/2+x, y)
H_point = (G_point[0]+traf['g'], y)
I_point = (x, (traf['A']-traf['g'])/2+y)
J_point = (traf['A']+x, I_point[1])
arc_C = msp.add_arc(center=C_center, radius=traf['r'], start_angle=180, end_angle=270, dxfattribs={'layer': 'structure'})
arc_F = msp.add_arc(center=F_center, radius=traf['r'], start_angle=270, end_angle=360, dxfattribs={'layer': 'structure'})
def line_add(p1, p2):
return msp.add_line(p1, p2, dxfattribs={'layer': 'structure'})
line_AB = line_add(A_point, B_point)
line_DE = line_add(E_point, D_point)
line_GH = line_add(G_point, H_point)
line_GI = line_add(I_point, G_point)
line_AI = line_add(I_point, A_point)
line_HJ = line_add(H_point, J_point)
line_DJ = line_add(J_point, D_point)
円弧の始点・終点はarc_C.start_pointのように作成済みの図形から直接座標を取得できます。自分で三角関数を計算し直す必要がないので、地味に便利です。
寸法線とハッチングを追加する
override = {"dimtxsty": "Standard", "dimtxt": 15, "dimclrt": 0, "dimtad": 1, "dimexo": 2, "dimlfac": 1}
def aligned_dim(p1, p2, dis):
msp.add_aligned_dim(p1=p1, p2=p2, distance=dis, dimstyle="EZDXF",
override=override, dxfattribs={'layer': 'dimension'}).render()
aligned_dim(line_AB.dxf.start, line_AB.dxf.end, 30)
aligned_dim(line_DE.dxf.start, line_DE.dxf.end, 30)
aligned_dim(line_AB.dxf.end, line_DE.dxf.start, 30)
aligned_dim(line_AB.dxf.start, line_DE.dxf.end, 60)
ハッチングは第2回で紹介したエッジパス(add_edge_path)で、直線と円弧を交互につないで断面形状を塗りつぶします。
patterns = ['ANSI31', 'ANSI32', 'ANSI33']
hatch = msp.add_hatch()
edge_path = hatch.paths.add_edge_path()
edge_path.add_line(A_point, B_point)
edge_path.add_line(B_point, arc_C.start_point)
edge_path.add_arc(arc_C.dxf.center, arc_C.dxf.radius,
start_angle=arc_C.dxf.start_angle, end_angle=arc_C.dxf.end_angle, ccw=False)
edge_path.add_line(arc_C.end_point, arc_F.start_point)
edge_path.add_arc(arc_F.dxf.center, arc_F.dxf.radius,
start_angle=arc_F.dxf.start_angle, end_angle=arc_F.dxf.end_angle, ccw=False)
edge_path.add_line(E_point, arc_F.end_point)
edge_path.add_line(E_point, D_point)
edge_path.add_line(J_point, D_point)
edge_path.add_line(H_point, J_point)
edge_path.add_line(G_point, H_point)
edge_path.add_line(I_point, G_point)
edge_path.add_line(I_point, A_point)
hatch.set_pattern_fill(patterns[i], scale=0.5, color=i+1)
文字ラベルを配置する
規格名を第2回で解説したset_placement()で配置します。
msp.add_text(
'JIS A 5372 ' + traf['name'],
dxfattribs={'height': 15, 'color': 4, 'layer': 'text'}
).set_placement((traf['A']/2+x, traf['H']+95+y), align=TextEntityAlignment.TOP_CENTER)
実行結果
ここまでのコードを規格3種でforループを回すと、冒頭の画像のように規格ごとに寸法とハッチングが自動でついた断面図ができあがります。パラメータを増やせば、13規格すべてを同じコードで量産できます。
上記コードを統合版し、13種類のトラフを作成するサンプルコード

ここまでの13規格版のコードをまとめて、そのままダウンロードできる形にしました。
【DXF読込】作った図面をezdxfで読み込む
ここまでは「作る」側でしたが、ezdxfは既存のDXFを読み込んで図形情報を取り出すこともできます。ここでは、先ほど作ったDXFを読み込んで、図形の座標や種類をpandasでExcelに書き出す方法をまとめます。
DXFファイルの読み込み
作図とは別に、読み込み専用のライブラリとしてpandasを使います。ExcelやCSVへの書き出しに便利なので、ここで導入します。
doc.saveas('traf_sample.dxf')
fig = plt.figure(figsize=(10, 4.2), dpi=140)
ax = fig.add_axes([0, 0, 1, 1])
ctx = RenderContext(doc)
out = MatplotlibBackend(ax)
Frontend(ctx, out).draw_layout(msp, finalize=True)
fig.savefig('traf_sample.png')

import ezdxf
import pandas as pd
dxf = ezdxf.readfile('traf_sample.dxf') # 読み込むDXFのパス
msp = dxf.modelspace()
図形情報の取得(query)
読み込んだモデルスペースに対して.query()を使うと、指定した種類の図形だけをまとめて取得できます。
図形の種類(LINE・ARC・TEXTなど)はすべて大文字で指定する決まりです。
lines = [entity.dxfattribs() for entity in msp.query('LINE')]
arcs = [entity.dxfattribs() for entity in msp.query('ARC')]
texts = [entity.dxfattribs() for entity in msp.query('TEXT')]
pandasでデータフレーム化
取得した図形属性のリストを、そのままpd.DataFrame()に渡すだけでデータフレームになります。ここでは「Excelに変換するための道具」くらいの理解で問題ありません。
df_line = pd.DataFrame(lines)
df_arc = pd.DataFrame(arcs)
df_text = pd.DataFrame(texts)
print(df_text[['layer', 'text', 'height']])
実際に先ほどのU形トラフ3規格分のDXFを読み込むと、次のように取得できます。
| layer | text | height |
|---|---|---|
| text | JIS A 5372 150 | 15.0 |
| text | JIS A 5372 240 | 15.0 |
| text | JIS A 5372 360A | 15.0 |
Excelに保存する
pd.ExcelWriterを使うと、1つのブックに図形種類ごとのシートをまとめて保存できます。
with pd.ExcelWriter('dxf_excel.xlsx') as writer:
df_line.to_excel(writer, sheet_name='line')
df_text.to_excel(writer, sheet_name='text')
df_arc.to_excel(writer, sheet_name='arc')
LINEエンティティのみ抽出したシート

TEXTエンティティのみ抽出したシート

ARCエンティティのみ抽出したシート

まとめ
今回は、これまでの内容を組み合わせた実践編として、規格違いの構造物をまとめて自動作図する方法と、逆にDXFを読み込んでデータ化する方法をまとめました。
- 規格値を辞書+リストで管理すれば、同じコードで規格違いをまとめて作図できる
- 円弧の始点・終点は作成済み図形から直接取得すると計算が楽
- 標準の“EZDXF”dimstyleは寸法値が100倍表示される。
"dimlfac": 1で解消できる - 図形の読み込みは
modelspace.query('LINE')のように大文字で指定する - 取得した属性リストはpandasでそのままデータフレーム化でき、Excelにも簡単に書き出せる

シリーズ記事一覧
「ezdxfを使ってみよう」シリーズの全記事です。





コメントお待ちしてます!