A comprehensive Python package for creating, reading, modifying, and writing DXF (Drawing Exchange Format) documents with support for multiple DXF versions.
—
Extended functionality including import/export utilities, geometry generators, table creation, dimension tools, and specialized format support. The addons package provides high-level tools and specialized functionality built on top of the core ezdxf library.
Utilities for transferring entities and definitions between DXF documents and specialized export formats.
class Importer:
"""Import entities and definitions between DXF documents"""
def __init__(self, source_doc, target_doc): ...
def import_entities(self, entities):
"""
Import entities from source to target document.
Parameters:
- entities: sequence of entities to import
Returns:
List: Imported entities in target document
"""
def import_blocks(self, block_names):
"""Import block definitions"""
def import_layers(self, layer_names):
"""Import layer definitions"""
def import_linetypes(self, linetype_names):
"""Import linetype definitions"""
def import_text_styles(self, style_names):
"""Import text style definitions"""
def import_dim_styles(self, dimstyle_names):
"""Import dimension style definitions"""
class MTextExplode:
"""Explode MTEXT entities to simple text and geometric entities"""
def __init__(self): ...
def explode(self, mtext, target_layout):
"""
Explode MTEXT to basic entities.
Parameters:
- mtext: MTEXT entity to explode
- target_layout: layout to receive exploded entities
Returns:
List: Basic entities representing the MTEXT
"""Usage examples:
from ezdxf.addons import Importer, MTextExplode
import ezdxf
# Import entities between documents
source_doc = ezdxf.readfile('source.dxf')
target_doc = ezdxf.new()
importer = Importer(source_doc, target_doc)
# Import specific entities
source_entities = source_doc.modelspace().query('CIRCLE')
imported_circles = importer.import_entities(source_entities)
# Import supporting definitions
importer.import_layers(['GEOMETRY', 'DIMENSIONS'])
importer.import_linetypes(['DASHED', 'CENTER'])
# Explode MTEXT for R12 compatibility
mtext_exploder = MTextExplode()
for mtext in target_doc.modelspace().query('MTEXT'):
exploded = mtext_exploder.explode(mtext, target_doc.modelspace())
target_doc.modelspace().delete_entity(mtext) # Remove originalFast DXF R12 file writer optimized for large datasets and simple geometry.
class R12Writer:
"""High-performance DXF R12 file writer"""
def __init__(self, filename: str, *, fixed_tables: bool = False): ...
def add_line(self, start, end, *, layer: str = '0', color: int = None): ...
def add_circle(self, center, radius: float, *, layer: str = '0', color: int = None): ...
def add_arc(self, center, radius: float, start_angle: float, end_angle: float,
*, layer: str = '0', color: int = None): ...
def add_point(self, location, *, layer: str = '0', color: int = None): ...
def add_text(self, text: str, insert, *, height: float = 1.0, layer: str = '0',
color: int = None, rotation: float = 0, style: str = 'STANDARD'): ...
def add_polyline(self, points, *, layer: str = '0', color: int = None,
closed: bool = False): ...
def add_3dface(self, face, *, layer: str = '0', color: int = None): ...
def close(self): ...
def __enter__(self): ...
def __exit__(self, exc_type, exc_val, exc_tb): ...Usage examples:
from ezdxf.addons.r12writer import R12Writer
import random
# High-performance writing of large datasets
with R12Writer('large_dataset.dxf') as r12:
# Generate thousands of entities quickly
for i in range(10000):
x, y = random.uniform(0, 1000), random.uniform(0, 1000)
radius = random.uniform(1, 10)
r12.add_circle((x, y), radius, layer='CIRCLES', color=1)
if i % 100 == 0: # Add some text markers
r12.add_text(f'#{i}', (x, y + radius + 2), height=2, layer='LABELS')Specialized generators for complex geometric shapes and fractal patterns.
class MengerSponge:
"""Generate Menger sponge fractal meshes"""
def __init__(self, level: int = 3, size: float = 1.0): ...
@property
def level(self) -> int:
"""Fractal recursion level"""
@property
def size(self) -> float:
"""Overall size of the sponge"""
def mesh(self) -> MeshBuilder:
"""Generate mesh representation"""
def render(self, layout, *, dxfattribs: dict = None):
"""Render sponge to layout as mesh entities"""
class SierpinskyPyramid:
"""Generate Sierpinsky pyramid fractal meshes"""
def __init__(self, level: int = 4, size: float = 1.0): ...
def mesh(self) -> MeshBuilder:
"""Generate mesh representation"""
def render(self, layout, *, dxfattribs: dict = None):
"""Render pyramid to layout"""Usage examples:
from ezdxf.addons import MengerSponge, SierpinskyPyramid
# Generate Menger sponge
sponge = MengerSponge(level=3, size=50)
sponge.render(msp, dxfattribs={'color': 1, 'layer': 'FRACTALS'})
# Generate Sierpinsky pyramid
pyramid = SierpinskyPyramid(level=4, size=30)
pyramid_mesh = pyramid.mesh()
pyramid_mesh.translate(100, 0, 0) # Position away from sponge
pyramid_mesh.render_mesh(msp, dxfattribs={'color': 2, 'layer': 'FRACTALS'})Advanced table creation and formatting utilities with cell-based editing.
class TablePainter:
"""Create and format table entities with cells and borders"""
def __init__(self, insert = (0, 0), nrows: int = 1, ncols: int = 1,
cell_width: float = 10, cell_height: float = 5): ...
@property
def nrows(self) -> int:
"""Number of rows"""
@property
def ncols(self) -> int:
"""Number of columns"""
def cell(self, row: int, col: int) -> 'CustomCell':
"""Get cell at specified position"""
def frame(self, *, style: str = 'default', color: int = None) -> 'TablePainter':
"""Set table frame style"""
def grid(self, *, style: str = 'default', color: int = None) -> 'TablePainter':
"""Set grid line style"""
def render(self, layout, *, dxfattribs: dict = None):
"""Render table to layout"""
class CustomCell:
"""Individual table cell with content and formatting"""
def __init__(self): ...
def add_text(self, text: str, *, height: float = 2.5, color: int = None,
halign: str = 'CENTER', valign: str = 'MIDDLE') -> 'CustomCell': ...
def add_line(self, start, end, *, color: int = None) -> 'CustomCell': ...
def add_circle(self, center, radius: float, *, color: int = None) -> 'CustomCell': ...
def background_color(self, color: int) -> 'CustomCell': ...
def border(self, *, style: str = 'default', color: int = None) -> 'CustomCell': ...Usage examples:
from ezdxf.addons import TablePainter
# Create table with data
table = TablePainter(insert=(0, 0), nrows=4, ncols=3,
cell_width=20, cell_height=8)
# Header row
table.cell(0, 0).add_text('Item', height=3, color=1).background_color(250)
table.cell(0, 1).add_text('Quantity', height=3, color=1).background_color(250)
table.cell(0, 2).add_text('Price', height=3, color=1).background_color(250)
# Data rows
items = [
('Widget A', '10', '$5.00'),
('Widget B', '25', '$3.50'),
('Widget C', '5', '$12.00')
]
for i, (item, qty, price) in enumerate(items, 1):
table.cell(i, 0).add_text(item, halign='LEFT')
table.cell(i, 1).add_text(qty, halign='CENTER')
table.cell(i, 2).add_text(price, halign='RIGHT')
# Style table
table.frame(style='thick', color=1)
table.grid(style='thin', color=8)
# Render to layout
table.render(msp, dxfattribs={'layer': 'TABLES'})High-level dimension creation utilities with automatic formatting and positioning.
class LinearDimension:
"""Create linear dimensions with automatic positioning"""
@staticmethod
def quick_dimension(p1, p2, distance: float, *, dimstyle: str = 'EZDXF',
override: dict = None, dxfattribs: dict = None):
"""Create linear dimension between two points"""
class AngularDimension:
"""Create angular dimensions"""
@staticmethod
def quick_dimension(center, p1, p2, *, dimstyle: str = 'EZDXF',
override: dict = None, dxfattribs: dict = None):
"""Create angular dimension from center and two points"""
class RadialDimension:
"""Create radial dimensions for circles and arcs"""
@staticmethod
def quick_dimension(center, radius: float, angle: float = 0,
*, dimstyle: str = 'EZDXF', override: dict = None,
dxfattribs: dict = None):
"""Create radial dimension"""
class ArcDimension:
"""Create arc length dimensions"""
@staticmethod
def quick_dimension(center, radius: float, start_angle: float, end_angle: float,
*, dimstyle: str = 'EZDXF', override: dict = None,
dxfattribs: dict = None):
"""Create arc length dimension"""
# Dimension style management
def dimstyles(doc):
"""Access dimension style management utilities"""Advanced text handling and compatibility utilities for MTEXT processing.
class MTextSurrogate:
"""MTEXT compatibility layer for older DXF versions"""
def __init__(self, mtext): ...
def explode_to_text(self, layout, *, line_spacing: float = 1.67,
dxfattribs: dict = None):
"""Explode MTEXT to multiple TEXT entities"""
def plain_text(self) -> str:
"""Extract plain text content without formatting"""
def word_wrap(self, box_width: float) -> List[str]:
"""Word wrap text to specified width"""Specialized subpackages for complex functionality and format support.
# Drawing and rendering backends
from ezdxf.addons.drawing import Frontend, Backend
from ezdxf.addons.drawing.matplotlib import MatplotlibBackend
from ezdxf.addons.drawing.pyqt import PyQtBackend
# DXF structure browser
from ezdxf.addons.browser import Browser
# HPGL2 plotter format support
from ezdxf.addons.hpgl2 import api as hpgl2
# Limited DWG file support
from ezdxf.addons.dwg import readfile as read_dwgUsage examples:
# Drawing backend example
from ezdxf.addons.drawing import Frontend
from ezdxf.addons.drawing.matplotlib import MatplotlibBackend
import matplotlib.pyplot as plt
# Render DXF to matplotlib
doc = ezdxf.readfile('drawing.dxf')
msp = doc.modelspace()
fig = plt.figure()
ax = fig.add_axes([0, 0, 1, 1])
ctx = MatplotlibBackend(ax)
Frontend(ctx, doc).draw_layout(msp, finalize=True)
plt.show()
# DXF structure browser
from ezdxf.addons.browser import Browser
# Inspect DXF file structure
browser = Browser(doc)
browser.print_structure() # Print document structure to console
# HPGL2 export example
from ezdxf.addons.hpgl2 import api as hpgl2
# Export DXF to HPGL2 format
hpgl2.export_dxf('drawing.dxf', 'output.plt',
paper_size='A3',
pen_table={'1': 'red', '2': 'blue'})Additional utility classes and functions for specialized operations.
class GeneticAlgorithm:
"""Genetic algorithm implementation for optimization problems"""
def __init__(self, population_size: int = 100, mutation_rate: float = 0.01): ...
def evolve(self, fitness_function, generations: int = 100): ...
class BinPacking:
"""2D bin packing algorithms for layout optimization"""
@staticmethod
def pack_rectangles(rectangles, bin_width: float, bin_height: float): ...
def openscad_integration():
"""OpenSCAD file format integration utilities"""
def pycsg_integration():
"""PyCSG (Constructive Solid Geometry) integration"""import ezdxf
from ezdxf.addons import Importer, TablePainter, MengerSponge
from ezdxf.addons import LinearDimension, MTextExplode
from ezdxf.addons.r12writer import R12Writer
# Create main document
doc = ezdxf.new('R2018', setup=True)
msp = doc.modelspace()
# Import from another document
if True: # Conditional import
try:
source_doc = ezdxf.readfile('source_drawing.dxf')
importer = Importer(source_doc, doc)
# Import specific layers and styles
importer.import_layers(['IMPORTED_GEOMETRY'])
importer.import_text_styles(['TITLE_STYLE'])
# Import selected entities
imported_entities = importer.import_entities(
source_doc.modelspace().query('CIRCLE[radius>5.0]')
)
print(f"Imported {len(imported_entities)} large circles")
except ezdxf.DXFError:
print("Source document not found, skipping import")
# Create specification table
spec_table = TablePainter(insert=(50, 50), nrows=6, ncols=3,
cell_width=25, cell_height=10)
# Fill table with specifications
headers = ['Component', 'Specification', 'Notes']
for i, header in enumerate(headers):
spec_table.cell(0, i).add_text(header, height=4, color=1).background_color(251)
spec_data = [
('Material', 'Steel AISI 1018', 'Cold rolled'),
('Thickness', '3.0 mm', '±0.1 tolerance'),
('Surface', 'Zinc plated', 'Clear passivate'),
('Weight', '2.5 kg', 'Approximate'),
('Qty Required', '100 pcs', 'Initial order')
]
for i, (comp, spec, note) in enumerate(spec_data, 1):
spec_table.cell(i, 0).add_text(comp, halign='LEFT')
spec_table.cell(i, 1).add_text(spec, halign='CENTER')
spec_table.cell(i, 2).add_text(note, halign='LEFT', color=8)
spec_table.frame(style='thick', color=1)
spec_table.grid(style='default', color=8)
spec_table.render(msp, dxfattribs={'layer': 'SPECIFICATIONS'})
# Add decorative fractal element
fractal = MengerSponge(level=2, size=20)
fractal_mesh = fractal.mesh()
fractal_mesh.translate(150, 25, 0)
fractal_mesh.render_mesh(msp, dxfattribs={'color': 3, 'layer': 'DECORATION'})
# Create simplified R12 export for compatibility
r12_filename = 'simplified_export.dxf'
with R12Writer(r12_filename) as r12:
# Export basic geometry only
for entity in msp.query('LINE CIRCLE ARC'):
if entity.dxftype() == 'LINE':
r12.add_line(entity.dxf.start, entity.dxf.end,
layer=entity.dxf.layer, color=entity.dxf.color)
elif entity.dxftype() == 'CIRCLE':
r12.add_circle(entity.dxf.center, entity.dxf.radius,
layer=entity.dxf.layer, color=entity.dxf.color)
elif entity.dxftype() == 'ARC':
r12.add_arc(entity.dxf.center, entity.dxf.radius,
entity.dxf.start_angle, entity.dxf.end_angle,
layer=entity.dxf.layer, color=entity.dxf.color)
# Process any MTEXT for R12 compatibility
mtext_exploder = MTextExplode()
for mtext in msp.query('MTEXT'):
exploded_entities = mtext_exploder.explode(mtext, msp)
msp.delete_entity(mtext)
print(f"Exploded MTEXT to {len(exploded_entities)} entities")
# Save main document
doc.saveas('addon_features_demo.dxf')
print(f"Created main document and R12 export: {r12_filename}")Install with Tessl CLI
npx tessl i tessl/pypi-ezdxf