ezdxfを使ってみよう #2~図形・属性編~【描画・レイヤー・日本語フォント・ハッチング】

当ページのリンクには広告が含まれています。
  • URLをコピーしました!

※本ページはプロモーション(広告)が含まれています。当サイトは各種アフィリエイトプログラムに参加しており、リンク経由で報酬を得る場合があります。詳しくはプライバシーポリシーをご確認ください。

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

前回(第1回)の内容はこちらです。

本記事のコードは、いずれも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})

dxfattribs(layer・color・lineweight・linetypeなど)は、この3つの図形で共通の書き方です。1つ覚えれば他にも使い回せます。線幅はCADが読み込んだ際に既定の近似値に変換されることが多いです。

Point(点)

# 点の種類・大きさはヘッダーで設定(matplotlibでは反映されない)
doc.header['$PDMODE'] = 35   # 点の種類
doc.header['$PDSIZE'] = 10   # 点の大きさ

msp.add_point([10, 10], dxfattribs={'layer': 'mylayer', 'color': 3})

点の種類・大きさはヘッダー単位の設定で、図面内の全ての点に一括で反映されます。色とレイヤーだけが個別指定できます。CADによっては表示が反映されない場合もあります。

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の情報が上書きされるので併用しない

作成済みのポリラインに、あとから点を追加することもできます。poliline_1.append_points([(8, 7), (120, 30)])のように、変数に格納しておいた図形オブジェクトに対して呼び出します。

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'})

レイヤー作成はcolor=7のようにキーワード引数で指定しますが、図形へのレイヤー指定は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')
つかだ

美しい…これが自動作図…

参考:ezdxf公式ドキュメント(ACIカラーの一覧は “Concepts” 内の色関連ページに掲載されています)

線幅・線種

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ゴシック'})

日本語フォントを使った文字は、matplotlibのプレビューでは正しく表示されないことがあります。最終的な見た目はCADソフト側で確認してください。

配置(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)

バージョン注意:古いezdxf(0.17系など)ではalign='MIDDLE_CENTER'のように文字列で直接指定できましたが、現行バージョン(1.x系)では文字列を渡すとエラーになりますfrom ezdxf.enums import TextEntityAlignmentをインポートし、align=TextEntityAlignment.MIDDLE_CENTERのようにEnumで指定してください。

テンキー位置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])

注意点TOP_LEFTは「基準点の左上に文字が来る」のではなく、「文字の左上が基準点になる」という意味です。CADで作図していれば当たり前の感覚ですが、コードで書くと逆に捉えがちです。

つかだ

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によって反映されないことが確認されているため、実務ではdxfattribsrotation(角度)で調整する方が確実です。

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])

参考:ezdxf公式ドキュメント(Tutorials)

ハッチングパターンは71種類

set_pattern_fill()の第1引数に名前を渡すだけで、AutoCAD標準のハッチングパターンを再現できます。主なパターン名は次のとおりです。

ANSI31〜ANSI38、ACAD_ISO02W100〜ACAD_ISO15W100、ANGLE、AR-B816、AR-B88、AR-BRSTD、AR-CONC、AR-HBONE、AR-SAND、BOX、BRICK、CLAY、CORK、CROSS、DASH、DOTS、EARTH、GRASS、GRATE、GRAVEL、HEX、HONEY、INSUL、LINE、NET、PLAST、STARS、STEEL、SWAMP、TRIANG、ZIGZAG など全71種類

ハッチングパターンのカタログを作成するコード

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)

setupの内容確認(第1回)と同じ考え方で、パターン名をリストに入れてforループで回すと、全種類を一覧表示するDXFがそのまま作れます。

つかだ

ああ美しい…。とても美しいですね(?)

まとめ

今回は、7種類の基本図形の描き方から、レイヤー・色・線種といった属性、日本語フォントの追加方法、そしてハッチングパターンまでを解説しました。

  • Line・Circle・Arcはdxfattribsの書き方が共通
  • レイヤー作成はキーワード引数、指定はdxfattribsの辞書と書き方が違う
  • 日本語フォントはdoc.styles.add()で追加登録する
  • 文字の配置alignはテンキーの並びで覚えると迷わない

次回・第3回では、寸法線(直線・半径・直径・角度・弧の長さ)の描き方だけをじっくり解説します。

シリーズ記事一覧

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

よかったらシェアしてね!
  • URLをコピーしました!

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

コメントする

CAPTCHA


目次