前回はezdxfのインストールと、最短5行での作図・setup機能までを解説しました。
今回は実際に図形を描く方法と、色やレイヤーといった属性の指定、そして寸法線の描画までをまとめて解説します。

本記事のコードは、いずれもdoc = ezdxf.new('R2010', setup=True) → msp = doc.modelspace()の続きとして書けます(第1回で紹介した基本の型です)。
図形を描画する
ezdxfで扱える図形(エンティティ)は多数ありますが、まずは基本の7種類を押さえれば大半の図面は描けます。
Line・Circle・Arc(線・円・弧)
この3つは指定する座標が違うだけで、書き方の考え方は同じです。
# 線:始点・終点
msp.add_line((0, 10), (7, 10),
dxfattribs={'layer': 'mylayer', 'color': 2, 'lineweight': 5, 'linetype': 'PHANTOMX2'})
# 円:中心点・半径
msp.add_circle((10, 15), radius=5,
dxfattribs={'layer': 'mylayer', 'color': 6, 'lineweight': 18, 'linetype': 'DIVIDEX2'})
# 弧:中心点・半径・開始角・終了角
msp.add_arc(center=(20, 10), radius=5, start_angle=50, end_angle=200,
dxfattribs={'layer': 'mylayer', 'color': 20, 'linetype': 'DASHED', 'lineweight': 18})

Point(点)
# 点の種類・大きさはヘッダーで設定(matplotlibでは反映されない)
doc.header['$PDMODE'] = 35 # 点の種類
doc.header['$PDSIZE'] = 10 # 点の大きさ
msp.add_point([10, 10], dxfattribs={'layer': 'mylayer', 'color': 3})

Text(文字)
from ezdxf.enums import TextEntityAlignment
msp.add_text('Hello! ezdxf!',
dxfattribs={'style': 'OpenSansCondensed-Bold', 'height': 15, 'width': 0.5,
'rotation': 45, 'color': 4}
).set_placement((1350, 61), align=TextEntityAlignment.TOP_RIGHT)

座標や配置はdxfattribsではなく.set_placement()で後ろに付け加えます。フォント(style)は第1回のsetup=Trueでプリセットしたものがそのまま使えます。配置(align)の指定方法は後述します。
Polyline(ポリライン)
点が複数ある連続線・多角形を作成します。
points = [(120, 70), (120, 110), (60, 80), (70, 130), (0, 150)]
msp.add_lwpolyline(points, format='xy', close=False, # close=Trueで多角形として閉じる
dxfattribs={'layer': 'mylayer', 'color': 6, 'linetype': 'Continuous', 'const_width': 5})

座標タプルは最大5要素まで渡せて、format引数で意味を切り替えられます。
| 記号 | 意味 |
|---|---|
| x, y | 座標 |
| s, e | その線の始点・終点の線幅 |
| b | 円弧の高さ(矢高、0〜1.0の比率) |
# format="xyseb" を全指定する例
points = [(120, 70, 1, 1, 0.5), (120, 110, 2, 5, 1), (60, 30, 5, 2, .2),
(80, 150, 1, 1, .1), (0, 150, 12, 5, 1)]
msp.add_lwpolyline(points, format='xyseb', close=True,
dxfattribs={'layer': 'mylayer', 'color': 6, 'lineweight': 18, 'linetype': 'Continuous'})
# 'const_width'を指定するとs,eの情報が上書きされるので併用しない


Hatch(ハッチング)
基本形は「輪郭のパスを作る→塗りパターンを指定する」の2手順です。
hatch = msp.add_hatch(color=2)
hatch.paths.add_polyline_path(
[(0, 0), (10, 0), (10, 10), (0, 10)], is_closed=True
)
hatch.set_pattern_fill('ANSI31', scale=0.5, color=2)

すでに描いたポリラインの座標をそのまま輪郭として使うこともできます。1本の図形を「線として描く」か「塗り面として使う」かを、同じ座標データから両方作れるということです。
polyline_points = [(20, 0, 0), (30, 10, 0.75), (30, 10, 0.5), (20, 20, 0)]
msp.add_lwpolyline(polyline_points, format='xyb', close=True)
hatch = msp.add_hatch(color=2)
hatch.paths.add_polyline_path(polyline_points, is_closed=True)

図形の属性(レイヤー・色・線幅・線種)
レイヤーの作成と指定
# レイヤーの作成(docに対して行う)
doc.layers.add(name='mylayer', color=7, linetype='DASHED', lineweight=20)
# 図形へのレイヤー指定(dxfattribsで行う)
msp.add_line(start=[0, 0], end=[1, 1], dxfattribs={'layer': 'mylayer'})
色(ACIカラーインデックス)
msp.add_line(start=[0, 0], end=[1, 1], dxfattribs={'color': 2})
色はACI(AutoCAD Color Index)という0〜255の番号で指定します。何色が何番かは公式ドキュメントの色見本で確認してください。
カラーインデックスを作成するコード(趣味の世界)
import ezdxf
import matplotlib.pyplot as plt
from ezdxf.addons.drawing import RenderContext, Frontend
from ezdxf.addons.drawing.matplotlib import MatplotlibBackend
doc = ezdxf.new("R2000")
msp = doc.modelspace()
# ポリラインで図枠を作成
waku_points = [(0, 0), (420, 0), (420, 297), (0, 297)] # 座標をリストに格納
msp.add_lwpolyline(waku_points, format="xy", close=True,
dxfattribs={
'layer': 'mylayer', # レイヤー
'color': 0, # 色
'linetype': "Continuous", # 線種
'const_width': 2 # ポリラインの線幅
})
# forループで文字列とハッチを連続描画
for i in range(256):
y = -15 * (i % 20)
x = 30 * (i // 20)
msp.add_text(i, dxfattribs={'layer': 'mylayer', 'style': 'OpenSans-Bold', 'height': 3}
).set_placement((6 + x, 291 + y))
hatch = msp.add_hatch(color=i)
hatch.paths.add_polyline_path(
[(15 + x, 295 + y), (28 + x, 295 + y), (28 + x, 290 + y), (15 + x, 290 + y)], is_closed=True
)
doc.saveas('color_sample.dxf')
# matplotlibでプレビュー画像を生成
fig = plt.figure(figsize=(10, 8))
ax = fig.add_axes([0, 0, 1, 1])
ctx = RenderContext(doc)
out = MatplotlibBackend(ax)
Frontend(ctx, out).draw_layout(msp, finalize=True)
fig.savefig('color_sample.png')

つかだ美しい…これが自動作図…
線幅・線種
msp.add_line(start=[0, 0], end=[1, 1], dxfattribs={'lineweight': 20})
msp.add_line(start=[0, 0], end=[1, 1], dxfattribs={'linetype': 'PHANTOMX2'})
setup=Trueでプリセットされる21種類の線種(第1回で紹介)で大抵は足りますが、独自の線種を追加することもできます。
doc.linetypes.add(
name='DOTTED_TEST',
pattern=[0.2, 0.0, -0.2],
description='Dotted_test . . . . . .'
)

patternの数値は「長さ」を表し、符号で意味が変わります。
| 値 | 意味 |
|---|---|
| n > 0 | 長さnの直線 |
| n = 0.0 | 点 |
| n < 0 | 長さnの空白 |
文字の配置と日本語フォント
前回、setup=Trueでプリセットされるフォントは英字のみとお伝えしました。
日本語を表示するには、フォントを別途追加します。
doc.styles.add('MSゴシック', font='msgothic.ttc')
msp.add_text('日本語は美しい', dxfattribs={'style': 'MSゴシック'})

配置(align)は15種類
文字の配置は.set_placement()のalign引数で指定します。基準点との位置関係を表す12種類がベースになります。
from ezdxf.enums import TextEntityAlignment
msp.add_text('TEXT', dxfattribs={'height': 0.15}
).set_placement((1, 1), align=TextEntityAlignment.MIDDLE_CENTER)
| テンキー位置 | align値 |
|---|---|
| 1(左下) | BOTTOM_LEFT |
| 2(中下) | BOTTOM_CENTER |
| 3(右下) | BOTTOM_RIGHT |
| 4(左中) | MIDDLE_LEFT |
| 5(中中) | MIDDLE_CENTER |
| 6(右中) | MIDDLE_RIGHT |
| 7(左上) | TOP_LEFT |
| 8(中上) | TOP_CENTER |
| 9(右上) | TOP_RIGHT |
| ― | LEFT/CENTER/RIGHT(1行のみの簡易指定) |
つかだ1〜9はキーボードのテンキーと同じ並びで覚えると迷いません。
「9はTOP_RIGHT(右上)」のように位置で覚えられます。
配置を書き出すコード
alignments_dic = {1:'BOTTOM_LEFT',2:'BOTTOM_CENTER',3:'BOTTOM_RIGHT',4:'MIDDLE_LEFT',5:'MIDDLE_CENTER',6:'MIDDLE_RIGHT',7:'TOP_LEFT',8:'TOP_CENTER', 9:'TOP_RIGHT',10:'LEFT', 11:'CENTER', 12:'RIGHT'}
for i, alignment in enumerate(alignments_dic.values()):
x = (i % 3)*5
y = (i // 3)*3
msp.add_text(alignment,
dxfattribs={
'style': 'LiberationSerif',
'height': 0.15,
'color': 4}
).set_pos((2+x, 6+y), align=alignment)
msp.add_line(start=[0+x, 6+y], end=[4+x, 6+y])
msp.add_line(start=[2+x, 5+y], end=[2+x, 7+y])

つかだalignmentsの辞書を作ってみました。
左下が「1」でテンキーに合わせています。
alignments_dic = {1:'BOTTOM_LEFT',2:'BOTTOM_CENTER',3:'BOTTOM_RIGHT',4:'MIDDLE_LEFT',5:'MIDDLE_CENTER',6:'MIDDLE_RIGHT',7:'TOP_LEFT',8:'TOP_CENTER', 9:'TOP_RIGHT','LEFT':'LEFT', 'CENTER':'CENTER', 'RIGHT':'RIGHT', 'ALIGNED':'ALIGNED', 'FIT':'FIT', 'MIDDLE':'MIDDLE'}
このほか、ALIGNED(縦横比を保って拡縮)・FIT(高さ固定で拡縮)という2点指定の特殊な配置もありますが、CADによって反映されないことが確認されているため、実務ではdxfattribsのrotation(角度)で調整する方が確実です。
alignments = {13:'ALIGNED', 14:'FIT'}
for i, alignment in enumerate(alignments.values()):
msp.add_text(alignment+str(12345),
dxfattribs={
'style': 'LiberationSerif',
'height': 0.15,
'color': 4}
).set_pos((2+5*i, 6),(4+5*i, 8), align=alignment)
msp.add_line(start=[0+5*i, 6], end=[4+5*i, 6])
msp.add_line(start=[2+5*i, 5], end=[2+5*i, 7])

ハッチングパターンは71種類
set_pattern_fill()の第1引数に名前を渡すだけで、AutoCAD標準のハッチングパターンを再現できます。主なパターン名は次のとおりです。
ハッチングパターンのカタログを作成するコード
patterns = ['ANSI31', 'ANSI32', 'ANSI33', 'ANSI34', 'ANSI35', 'ANSI36', 'ANSI37', 'ANSI38', 'ACAD_ISO02W100',
'ACAD_ISO03W100', 'ACAD_ISO04W100', 'ACAD_ISO05W100', 'ACAD_ISO06W100', 'ACAD_ISO07W100', 'ACAD_ISO08W100',
'ACAD_ISO09W100', 'ACAD_ISO10W100', 'ACAD_ISO11W100', 'ACAD_ISO12W100', 'ACAD_ISO13W100', 'ACAD_ISO14W100',
'ACAD_ISO15W100', 'ANGLE', 'AR-B816', 'AR-B816C', 'AR-B88', 'AR-BRELM', 'AR-BRSTD', 'AR-CONC', 'AR-HBONE',
'AR-PARQ1', 'AR-RROOF', 'AR-RSHKE', 'AR-SAND', 'BOX', 'BRASS', 'BRICK', 'BRSTONE', 'CLAY', 'CORK', 'CROSS',
'DASH', 'DOLMIT', 'DOTS', 'EARTH', 'ESCHER', 'FLEX', 'GOST_GLASS', 'GOST_WOOD', 'GOST_GROUND', 'GRASS',
'GRATE', 'GRAVEL', 'HEX', 'HONEY', 'HOUND', 'INSUL', 'LINE', 'MUDST', 'NET', 'NET3', 'PLAST', 'PTAST1',
'SACNCR', 'SRUARE', 'STARS', 'STEEL', 'SWAMP', 'TRANS', 'TRIANG', 'ZIGZAG']
for i, pattern in enumerate(patterns):
hatch = msp.add_hatch()
x = i % 10 * 15
y = i // 10 * -15
msp.add_text(pattern,
dxfattribs={
'style': 'LiberationSerif',
'height': 1,
'color': 0}
).set_placement((0 + x, 10 + y), align=TextEntityAlignment.BOTTOM_LEFT)
hatch.paths.add_polyline_path(
[(0 + x, y), (10 + x, y), (10 + x, 10 + y), (0 + x, 10 + y)], is_closed=True
)
hatch.set_pattern_fill(pattern, scale=0.5, color=i % 10)

つかだああ美しい…。とても美しいですね(?)
まとめ
今回は、7種類の基本図形の描き方から、レイヤー・色・線種といった属性、日本語フォントの追加方法、そしてハッチングパターンまでを解説しました。
- Line・Circle・Arcはdxfattribsの書き方が共通
- レイヤー作成はキーワード引数、指定はdxfattribsの辞書と書き方が違う
- 日本語フォントは
doc.styles.add()で追加登録する - 文字の配置alignはテンキーの並びで覚えると迷わない

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





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