A comprehensive Python package for creating, reading, modifying, and writing DXF (Drawing Exchange Format) documents with support for multiple DXF versions.
—
Advanced geometry processing including mesh construction, curve tessellation, and entity rendering to basic primitives. The rendering system supports both 2D and 3D geometry processing with optimization utilities.
3D mesh building utilities for creating, modifying, and optimizing polygon meshes.
class MeshBuilder:
"""3D mesh construction with vertices, faces, and materials"""
def __init__(self): ...
@property
def vertices(self) -> List[Vec3]:
"""Vertex coordinates"""
@property
def faces(self) -> List[List[int]]:
"""Face definitions as vertex indices"""
def add_vertex(self, vertex: Vec3) -> int:
"""Add vertex and return its index"""
def add_vertices(self, vertices) -> List[int]:
"""Add multiple vertices and return their indices"""
def add_face(self, face) -> 'MeshBuilder':
"""Add face defined by vertex indices"""
def add_mesh(self, vertices = None, faces = None, mesh = None) -> 'MeshBuilder':
"""Add another mesh to this mesh"""
def transform(self, matrix: Matrix44) -> 'MeshBuilder':
"""Transform all vertices by matrix"""
def translate(self, dx: float, dy: float, dz: float) -> 'MeshBuilder':
"""Translate all vertices"""
def scale(self, sx: float, sy: float, sz: float) -> 'MeshBuilder':
"""Scale all vertices"""
def render_mesh(self, layout, dxfattribs: dict = None, matrix: Matrix44 = None):
"""Render mesh to layout as DXF entities"""
def render_polyface(self, layout, dxfattribs: dict = None, matrix: Matrix44 = None):
"""Render mesh as POLYFACE entity"""
class MeshVertexMerger:
"""Utility for merging duplicate vertices in meshes"""
def __init__(self, mesh: MeshBuilder, precision: int = 6): ...
def merged_mesh(self) -> MeshBuilder:
"""Return mesh with merged vertices"""
class MeshAverageVertexMerger:
"""Merge vertices by averaging coordinates"""
def __init__(self, mesh: MeshBuilder, precision: int = 6): ...
class MeshTransformer:
"""Advanced mesh transformation utilities"""
def __init__(self, mesh: MeshBuilder): ...
def subdivide_faces(self, quads: bool = True) -> MeshBuilder:
"""Subdivide mesh faces for smoother surfaces"""
def subdivide_ngons(self, max_vertices: int = 4) -> MeshBuilder:
"""Subdivide n-gons into triangles or quads"""Usage examples:
from ezdxf.render import MeshBuilder
from ezdxf.math import Vec3, Matrix44
# Create a simple pyramid mesh
mesh = MeshBuilder()
# Add vertices
v0 = mesh.add_vertex(Vec3(0, 0, 0)) # base vertices
v1 = mesh.add_vertex(Vec3(10, 0, 0))
v2 = mesh.add_vertex(Vec3(10, 10, 0))
v3 = mesh.add_vertex(Vec3(0, 10, 0))
v4 = mesh.add_vertex(Vec3(5, 5, 8)) # apex
# Add faces (triangles using vertex indices)
mesh.add_face([v0, v1, v4]) # side faces
mesh.add_face([v1, v2, v4])
mesh.add_face([v2, v3, v4])
mesh.add_face([v3, v0, v4])
mesh.add_face([v3, v2, v1, v0]) # base quad
# Transform mesh
matrix = Matrix44.z_rotate(math.radians(45))
mesh.transform(matrix)
# Render to layout
msp.render_mesh(mesh, dxfattribs={'color': 1})Predefined geometric form generators for common shapes and patterns.
def circle(radius: float = 1, segments: int = None) -> List[Vec3]:
"""
Generate circle vertex coordinates.
Parameters:
- radius: circle radius
- segments: number of segments (auto-calculated if None)
Returns:
List[Vec3]: Circle vertices
"""
def ellipse(rx: float = 1, ry: float = 1, segments: int = None) -> List[Vec3]:
"""Generate ellipse vertex coordinates"""
def ngon(count: int, radius: float = 1, rotation: float = 0,
elevation: float = 0, close: bool = False) -> List[Vec3]:
"""
Generate regular polygon vertices.
Parameters:
- count: number of sides
- radius: circumscribed radius
- rotation: rotation angle in radians
- elevation: Z coordinate
- close: add closing vertex
"""
def star(count: int, r1: float, r2: float, rotation: float = 0,
elevation: float = 0, close: bool = False) -> List[Vec3]:
"""Generate star shape vertices with alternating radii"""
def box(width: float = 2, height: float = 1, depth: float = 1,
center: bool = True) -> MeshBuilder:
"""Generate box/cube mesh"""
def cylinder(radius: float = 1, height: float = 1, segments: int = 16,
caps: bool = True) -> MeshBuilder:
"""Generate cylinder mesh"""
def cone(radius: float = 1, height: float = 1, segments: int = 16,
caps: bool = True) -> MeshBuilder:
"""Generate cone mesh"""
def sphere(radius: float = 1, stacks: int = 16, slices: int = 16) -> MeshBuilder:
"""Generate sphere mesh"""Usage examples:
from ezdxf.render import forms
from ezdxf.math import Vec3
import math
# Generate basic shapes
circle_verts = forms.circle(radius=5, segments=20)
pentagon = forms.ngon(count=5, radius=3)
star_shape = forms.star(count=8, r1=5, r2=2.5)
# Create polylines from vertices
circle_poly = msp.add_lwpolyline(circle_verts)
circle_poly.close()
# Generate 3D meshes
box_mesh = forms.box(width=10, height=6, depth=4)
cylinder_mesh = forms.cylinder(radius=3, height=10, segments=12)
sphere_mesh = forms.sphere(radius=4, stacks=12, slices=16)
# Render meshes to layout
box_mesh.render_mesh(msp, dxfattribs={'color': 1})
cylinder_mesh.render_mesh(msp, dxfattribs={'color': 2})
sphere_mesh.render_mesh(msp, dxfattribs={'color': 3})Curve tessellation and rendering utilities for converting mathematical curves to line segments and DXF entities.
class Bezier:
"""Bézier curve renderer"""
@staticmethod
def from_3_points(start: Vec3, control: Vec3, end: Vec3, segments: int = 20) -> List[Vec3]:
"""Create quadratic Bézier curve from 3 points"""
@staticmethod
def from_4_points(start: Vec3, ctrl1: Vec3, ctrl2: Vec3, end: Vec3,
segments: int = 20) -> List[Vec3]:
"""Create cubic Bézier curve from 4 points"""
class EulerSpiral:
"""Euler spiral (clothoid) curve renderer"""
@staticmethod
def from_params(radius: float, curvature: float, length: float,
segments: int = 100) -> List[Vec3]:
"""Generate Euler spiral vertices"""
class Spline:
"""Spline curve rendering utilities"""
@staticmethod
def from_fit_points(points, degree: int = 3, segments: int = 100) -> List[Vec3]:
"""Render spline from fit points"""
@staticmethod
def from_control_points(points, degree: int = 3, segments: int = 100) -> List[Vec3]:
"""Render spline from control points"""
class R12Spline:
"""DXF R12 compatible spline rendering"""
@staticmethod
def from_fit_points(points, segments: int = 100) -> List[Vec3]:
"""Render as polyline for R12 compatibility"""Usage examples:
from ezdxf.render.curves import Bezier, Spline
from ezdxf.math import Vec3
# Bézier curves
start, ctrl, end = Vec3(0, 0), Vec3(5, 10), Vec3(10, 0)
bezier_points = Bezier.from_3_points(start, ctrl, end, segments=25)
bezier_poly = msp.add_lwpolyline(bezier_points)
# Cubic Bézier
ctrl_points = [Vec3(0, 0), Vec3(3, 8), Vec3(7, -3), Vec3(10, 5)]
cubic_points = Bezier.from_4_points(*ctrl_points, segments=30)
# Spline rendering
fit_points = [Vec3(i, math.sin(i), 0) for i in range(0, 10)]
spline_points = Spline.from_fit_points(fit_points, degree=3, segments=50)
spline_poly = msp.add_lwpolyline(spline_points)Advanced multi-leader entity construction with support for text and block content.
class MultiLeaderBuilder:
"""Base multi-leader entity builder"""
def __init__(self): ...
def quick_leader(self, text: str, insert, leader_length: float = 4,
dogleg_length: float = 2) -> 'MultiLeader': ...
class MultiLeaderMTextBuilder:
"""Text-based multi-leader builder"""
def __init__(self): ...
def add_leader_line(self, start: Vec3, end: Vec3): ...
def add_mtext_content(self, text: str, insert: Vec3, char_height: float = 2.5): ...
def build(self, layout, override: dict = None, dxfattribs: dict = None) -> 'MultiLeader': ...
class MultiLeaderBlockBuilder:
"""Block-based multi-leader builder"""
def __init__(self): ...
def add_leader_line(self, start: Vec3, end: Vec3): ...
def add_block_content(self, name: str, insert: Vec3, scale: float = 1.0): ...
def build(self, layout, override: dict = None, dxfattribs: dict = None) -> 'MultiLeader': ...
# Enumerations for multi-leader configuration
class LeaderType(Enum):
STRAIGHT = 0
SPLINE = 1
class TextAlignment(Enum):
LEFT = 0
CENTER = 1
RIGHT = 2
class BlockAlignment(Enum):
CENTER = 0
INSERT_POINT = 1Dimension entity rendering utilities for creating measurement annotations.
class AngularDimension:
"""Angular dimension renderer"""
@staticmethod
def from_2_lines(line1_start: Vec3, line1_end: Vec3, line2_start: Vec3,
line2_end: Vec3, dimstyle: str = 'EZDXF') -> List[DXFEntity]: ...
class Angular3PDimension:
"""3-point angular dimension renderer"""
@staticmethod
def from_3_points(center: Vec3, p1: Vec3, p2: Vec3,
dimstyle: str = 'EZDXF') -> List[DXFEntity]: ...
class ArcLengthDimension:
"""Arc length dimension renderer"""
@staticmethod
def from_arc(center: Vec3, radius: float, start_angle: float, end_angle: float,
dimstyle: str = 'EZDXF') -> List[DXFEntity]: ...
class OrdinateDimension:
"""Ordinate dimension renderer"""
@staticmethod
def from_point(origin: Vec3, point: Vec3, axis: str = 'X',
dimstyle: str = 'EZDXF') -> List[DXFEntity]: ...Polyline and trace building utilities for creating complex linear features.
class TraceBuilder:
"""Base trace builder for polyline-like entities"""
def __init__(self, width: float = 1.0): ...
def add_vertex(self, location: Vec3, bulge: float = 0): ...
def close(self): ...
def render(self, layout, dxfattribs: dict = None) -> List[DXFEntity]: ...
class LinearTrace:
"""Linear trace with constant width"""
def __init__(self, start: Vec3, end: Vec3, width: float): ...
class CurvedTrace:
"""Curved trace following a path"""
def __init__(self, path, width: float): ...Miscellaneous rendering utilities and helper functions.
def virtual_entities(entity) -> List[DXFEntity]:
"""
Extract virtual entities from complex entities like MLINE or MLEADER.
Parameters:
- entity: complex DXF entity
Returns:
List[DXFEntity]: Basic entities representing the complex entity
"""
def random_2d_path(count: int = 10, max_step: float = 1.0,
max_heading: float = math.pi/4) -> List[Vec2]:
"""Generate random 2D path for testing"""
def random_3d_path(count: int = 10, max_step: float = 1.0,
max_heading: float = math.pi/4) -> List[Vec3]:
"""Generate random 3D path for testing"""class AbstractMTextRenderer:
"""Base class for custom MTEXT rendering implementations"""
def word_wrap(self, text: str, box_width: float) -> List[str]: ...
def get_font_measurements(self, char_height: float, font: str): ...
def render_text(self, text: str, insert: Vec3, char_height: float): ...class MeshBuilderError(Exception):
"""Base exception for mesh construction errors"""
class NonManifoldMeshError(MeshBuilderError):
"""Mesh contains non-manifold geometry"""
class MultipleMeshesError(MeshBuilderError):
"""Operation requires single connected mesh"""
class NodeMergingError(Exception):
"""Error during vertex merging operations"""
class DegeneratedPathError(Exception):
"""Path contains degenerated segments"""Usage examples:
from ezdxf.render import MeshBuilder, forms
from ezdxf.math import Vec3, Matrix44
import ezdxf
doc = ezdxf.new()
msp = doc.modelspace()
# Create complex mesh
mesh = MeshBuilder()
# Add box and cylinder
box = forms.box(width=5, height=5, depth=5)
cylinder = forms.cylinder(radius=2, height=8, segments=12)
cylinder.translate(0, 0, 5) # Move cylinder up
# Combine meshes
mesh.add_mesh(mesh=box)
mesh.add_mesh(mesh=cylinder)
# Optimize mesh
from ezdxf.render import MeshVertexMerger
merger = MeshVertexMerger(mesh, precision=3)
optimized_mesh = merger.merged_mesh()
# Render to layout
optimized_mesh.render_mesh(msp, dxfattribs={
'color': 1,
'layer': 'MESH'
})
# Save document
doc.saveas('rendered_mesh.dxf')Install with Tessl CLI
npx tessl i tessl/pypi-ezdxf