0
# Rendering
1
2
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.
3
4
## Capabilities
5
6
### Mesh Construction
7
8
3D mesh building utilities for creating, modifying, and optimizing polygon meshes.
9
10
```python { .api }
11
class MeshBuilder:
12
"""3D mesh construction with vertices, faces, and materials"""
13
14
def __init__(self): ...
15
16
@property
17
def vertices(self) -> List[Vec3]:
18
"""Vertex coordinates"""
19
20
@property
21
def faces(self) -> List[List[int]]:
22
"""Face definitions as vertex indices"""
23
24
def add_vertex(self, vertex: Vec3) -> int:
25
"""Add vertex and return its index"""
26
27
def add_vertices(self, vertices) -> List[int]:
28
"""Add multiple vertices and return their indices"""
29
30
def add_face(self, face) -> 'MeshBuilder':
31
"""Add face defined by vertex indices"""
32
33
def add_mesh(self, vertices = None, faces = None, mesh = None) -> 'MeshBuilder':
34
"""Add another mesh to this mesh"""
35
36
def transform(self, matrix: Matrix44) -> 'MeshBuilder':
37
"""Transform all vertices by matrix"""
38
39
def translate(self, dx: float, dy: float, dz: float) -> 'MeshBuilder':
40
"""Translate all vertices"""
41
42
def scale(self, sx: float, sy: float, sz: float) -> 'MeshBuilder':
43
"""Scale all vertices"""
44
45
def render_mesh(self, layout, dxfattribs: dict = None, matrix: Matrix44 = None):
46
"""Render mesh to layout as DXF entities"""
47
48
def render_polyface(self, layout, dxfattribs: dict = None, matrix: Matrix44 = None):
49
"""Render mesh as POLYFACE entity"""
50
51
class MeshVertexMerger:
52
"""Utility for merging duplicate vertices in meshes"""
53
54
def __init__(self, mesh: MeshBuilder, precision: int = 6): ...
55
56
def merged_mesh(self) -> MeshBuilder:
57
"""Return mesh with merged vertices"""
58
59
class MeshAverageVertexMerger:
60
"""Merge vertices by averaging coordinates"""
61
62
def __init__(self, mesh: MeshBuilder, precision: int = 6): ...
63
64
class MeshTransformer:
65
"""Advanced mesh transformation utilities"""
66
67
def __init__(self, mesh: MeshBuilder): ...
68
69
def subdivide_faces(self, quads: bool = True) -> MeshBuilder:
70
"""Subdivide mesh faces for smoother surfaces"""
71
72
def subdivide_ngons(self, max_vertices: int = 4) -> MeshBuilder:
73
"""Subdivide n-gons into triangles or quads"""
74
```
75
76
Usage examples:
77
```python
78
from ezdxf.render import MeshBuilder
79
from ezdxf.math import Vec3, Matrix44
80
81
# Create a simple pyramid mesh
82
mesh = MeshBuilder()
83
84
# Add vertices
85
v0 = mesh.add_vertex(Vec3(0, 0, 0)) # base vertices
86
v1 = mesh.add_vertex(Vec3(10, 0, 0))
87
v2 = mesh.add_vertex(Vec3(10, 10, 0))
88
v3 = mesh.add_vertex(Vec3(0, 10, 0))
89
v4 = mesh.add_vertex(Vec3(5, 5, 8)) # apex
90
91
# Add faces (triangles using vertex indices)
92
mesh.add_face([v0, v1, v4]) # side faces
93
mesh.add_face([v1, v2, v4])
94
mesh.add_face([v2, v3, v4])
95
mesh.add_face([v3, v0, v4])
96
mesh.add_face([v3, v2, v1, v0]) # base quad
97
98
# Transform mesh
99
matrix = Matrix44.z_rotate(math.radians(45))
100
mesh.transform(matrix)
101
102
# Render to layout
103
msp.render_mesh(mesh, dxfattribs={'color': 1})
104
```
105
106
### Form Generators
107
108
Predefined geometric form generators for common shapes and patterns.
109
110
```python { .api }
111
def circle(radius: float = 1, segments: int = None) -> List[Vec3]:
112
"""
113
Generate circle vertex coordinates.
114
115
Parameters:
116
- radius: circle radius
117
- segments: number of segments (auto-calculated if None)
118
119
Returns:
120
List[Vec3]: Circle vertices
121
"""
122
123
def ellipse(rx: float = 1, ry: float = 1, segments: int = None) -> List[Vec3]:
124
"""Generate ellipse vertex coordinates"""
125
126
def ngon(count: int, radius: float = 1, rotation: float = 0,
127
elevation: float = 0, close: bool = False) -> List[Vec3]:
128
"""
129
Generate regular polygon vertices.
130
131
Parameters:
132
- count: number of sides
133
- radius: circumscribed radius
134
- rotation: rotation angle in radians
135
- elevation: Z coordinate
136
- close: add closing vertex
137
"""
138
139
def star(count: int, r1: float, r2: float, rotation: float = 0,
140
elevation: float = 0, close: bool = False) -> List[Vec3]:
141
"""Generate star shape vertices with alternating radii"""
142
143
def box(width: float = 2, height: float = 1, depth: float = 1,
144
center: bool = True) -> MeshBuilder:
145
"""Generate box/cube mesh"""
146
147
def cylinder(radius: float = 1, height: float = 1, segments: int = 16,
148
caps: bool = True) -> MeshBuilder:
149
"""Generate cylinder mesh"""
150
151
def cone(radius: float = 1, height: float = 1, segments: int = 16,
152
caps: bool = True) -> MeshBuilder:
153
"""Generate cone mesh"""
154
155
def sphere(radius: float = 1, stacks: int = 16, slices: int = 16) -> MeshBuilder:
156
"""Generate sphere mesh"""
157
```
158
159
Usage examples:
160
```python
161
from ezdxf.render import forms
162
from ezdxf.math import Vec3
163
import math
164
165
# Generate basic shapes
166
circle_verts = forms.circle(radius=5, segments=20)
167
pentagon = forms.ngon(count=5, radius=3)
168
star_shape = forms.star(count=8, r1=5, r2=2.5)
169
170
# Create polylines from vertices
171
circle_poly = msp.add_lwpolyline(circle_verts)
172
circle_poly.close()
173
174
# Generate 3D meshes
175
box_mesh = forms.box(width=10, height=6, depth=4)
176
cylinder_mesh = forms.cylinder(radius=3, height=10, segments=12)
177
sphere_mesh = forms.sphere(radius=4, stacks=12, slices=16)
178
179
# Render meshes to layout
180
box_mesh.render_mesh(msp, dxfattribs={'color': 1})
181
cylinder_mesh.render_mesh(msp, dxfattribs={'color': 2})
182
sphere_mesh.render_mesh(msp, dxfattribs={'color': 3})
183
```
184
185
### Curve Rendering
186
187
Curve tessellation and rendering utilities for converting mathematical curves to line segments and DXF entities.
188
189
```python { .api }
190
class Bezier:
191
"""Bézier curve renderer"""
192
193
@staticmethod
194
def from_3_points(start: Vec3, control: Vec3, end: Vec3, segments: int = 20) -> List[Vec3]:
195
"""Create quadratic Bézier curve from 3 points"""
196
197
@staticmethod
198
def from_4_points(start: Vec3, ctrl1: Vec3, ctrl2: Vec3, end: Vec3,
199
segments: int = 20) -> List[Vec3]:
200
"""Create cubic Bézier curve from 4 points"""
201
202
class EulerSpiral:
203
"""Euler spiral (clothoid) curve renderer"""
204
205
@staticmethod
206
def from_params(radius: float, curvature: float, length: float,
207
segments: int = 100) -> List[Vec3]:
208
"""Generate Euler spiral vertices"""
209
210
class Spline:
211
"""Spline curve rendering utilities"""
212
213
@staticmethod
214
def from_fit_points(points, degree: int = 3, segments: int = 100) -> List[Vec3]:
215
"""Render spline from fit points"""
216
217
@staticmethod
218
def from_control_points(points, degree: int = 3, segments: int = 100) -> List[Vec3]:
219
"""Render spline from control points"""
220
221
class R12Spline:
222
"""DXF R12 compatible spline rendering"""
223
224
@staticmethod
225
def from_fit_points(points, segments: int = 100) -> List[Vec3]:
226
"""Render as polyline for R12 compatibility"""
227
```
228
229
Usage examples:
230
```python
231
from ezdxf.render.curves import Bezier, Spline
232
from ezdxf.math import Vec3
233
234
# Bézier curves
235
start, ctrl, end = Vec3(0, 0), Vec3(5, 10), Vec3(10, 0)
236
bezier_points = Bezier.from_3_points(start, ctrl, end, segments=25)
237
bezier_poly = msp.add_lwpolyline(bezier_points)
238
239
# Cubic Bézier
240
ctrl_points = [Vec3(0, 0), Vec3(3, 8), Vec3(7, -3), Vec3(10, 5)]
241
cubic_points = Bezier.from_4_points(*ctrl_points, segments=30)
242
243
# Spline rendering
244
fit_points = [Vec3(i, math.sin(i), 0) for i in range(0, 10)]
245
spline_points = Spline.from_fit_points(fit_points, degree=3, segments=50)
246
spline_poly = msp.add_lwpolyline(spline_points)
247
```
248
249
### Multi-leader Builders
250
251
Advanced multi-leader entity construction with support for text and block content.
252
253
```python { .api }
254
class MultiLeaderBuilder:
255
"""Base multi-leader entity builder"""
256
257
def __init__(self): ...
258
259
def quick_leader(self, text: str, insert, leader_length: float = 4,
260
dogleg_length: float = 2) -> 'MultiLeader': ...
261
262
class MultiLeaderMTextBuilder:
263
"""Text-based multi-leader builder"""
264
265
def __init__(self): ...
266
267
def add_leader_line(self, start: Vec3, end: Vec3): ...
268
def add_mtext_content(self, text: str, insert: Vec3, char_height: float = 2.5): ...
269
270
def build(self, layout, override: dict = None, dxfattribs: dict = None) -> 'MultiLeader': ...
271
272
class MultiLeaderBlockBuilder:
273
"""Block-based multi-leader builder"""
274
275
def __init__(self): ...
276
277
def add_leader_line(self, start: Vec3, end: Vec3): ...
278
def add_block_content(self, name: str, insert: Vec3, scale: float = 1.0): ...
279
280
def build(self, layout, override: dict = None, dxfattribs: dict = None) -> 'MultiLeader': ...
281
282
# Enumerations for multi-leader configuration
283
class LeaderType(Enum):
284
STRAIGHT = 0
285
SPLINE = 1
286
287
class TextAlignment(Enum):
288
LEFT = 0
289
CENTER = 1
290
RIGHT = 2
291
292
class BlockAlignment(Enum):
293
CENTER = 0
294
INSERT_POINT = 1
295
```
296
297
### Dimension Rendering
298
299
Dimension entity rendering utilities for creating measurement annotations.
300
301
```python { .api }
302
class AngularDimension:
303
"""Angular dimension renderer"""
304
305
@staticmethod
306
def from_2_lines(line1_start: Vec3, line1_end: Vec3, line2_start: Vec3,
307
line2_end: Vec3, dimstyle: str = 'EZDXF') -> List[DXFEntity]: ...
308
309
class Angular3PDimension:
310
"""3-point angular dimension renderer"""
311
312
@staticmethod
313
def from_3_points(center: Vec3, p1: Vec3, p2: Vec3,
314
dimstyle: str = 'EZDXF') -> List[DXFEntity]: ...
315
316
class ArcLengthDimension:
317
"""Arc length dimension renderer"""
318
319
@staticmethod
320
def from_arc(center: Vec3, radius: float, start_angle: float, end_angle: float,
321
dimstyle: str = 'EZDXF') -> List[DXFEntity]: ...
322
323
class OrdinateDimension:
324
"""Ordinate dimension renderer"""
325
326
@staticmethod
327
def from_point(origin: Vec3, point: Vec3, axis: str = 'X',
328
dimstyle: str = 'EZDXF') -> List[DXFEntity]: ...
329
```
330
331
### Trace Builders
332
333
Polyline and trace building utilities for creating complex linear features.
334
335
```python { .api }
336
class TraceBuilder:
337
"""Base trace builder for polyline-like entities"""
338
339
def __init__(self, width: float = 1.0): ...
340
341
def add_vertex(self, location: Vec3, bulge: float = 0): ...
342
def close(self): ...
343
344
def render(self, layout, dxfattribs: dict = None) -> List[DXFEntity]: ...
345
346
class LinearTrace:
347
"""Linear trace with constant width"""
348
349
def __init__(self, start: Vec3, end: Vec3, width: float): ...
350
351
class CurvedTrace:
352
"""Curved trace following a path"""
353
354
def __init__(self, path, width: float): ...
355
```
356
357
### Utility Functions
358
359
Miscellaneous rendering utilities and helper functions.
360
361
```python { .api }
362
def virtual_entities(entity) -> List[DXFEntity]:
363
"""
364
Extract virtual entities from complex entities like MLINE or MLEADER.
365
366
Parameters:
367
- entity: complex DXF entity
368
369
Returns:
370
List[DXFEntity]: Basic entities representing the complex entity
371
"""
372
373
def random_2d_path(count: int = 10, max_step: float = 1.0,
374
max_heading: float = math.pi/4) -> List[Vec2]:
375
"""Generate random 2D path for testing"""
376
377
def random_3d_path(count: int = 10, max_step: float = 1.0,
378
max_heading: float = math.pi/4) -> List[Vec3]:
379
"""Generate random 3D path for testing"""
380
```
381
382
## Abstract Base Classes
383
384
```python { .api }
385
class AbstractMTextRenderer:
386
"""Base class for custom MTEXT rendering implementations"""
387
388
def word_wrap(self, text: str, box_width: float) -> List[str]: ...
389
def get_font_measurements(self, char_height: float, font: str): ...
390
def render_text(self, text: str, insert: Vec3, char_height: float): ...
391
```
392
393
## Exception Classes
394
395
```python { .api }
396
class MeshBuilderError(Exception):
397
"""Base exception for mesh construction errors"""
398
399
class NonManifoldMeshError(MeshBuilderError):
400
"""Mesh contains non-manifold geometry"""
401
402
class MultipleMeshesError(MeshBuilderError):
403
"""Operation requires single connected mesh"""
404
405
class NodeMergingError(Exception):
406
"""Error during vertex merging operations"""
407
408
class DegeneratedPathError(Exception):
409
"""Path contains degenerated segments"""
410
```
411
412
Usage examples:
413
```python
414
from ezdxf.render import MeshBuilder, forms
415
from ezdxf.math import Vec3, Matrix44
416
import ezdxf
417
418
doc = ezdxf.new()
419
msp = doc.modelspace()
420
421
# Create complex mesh
422
mesh = MeshBuilder()
423
424
# Add box and cylinder
425
box = forms.box(width=5, height=5, depth=5)
426
cylinder = forms.cylinder(radius=2, height=8, segments=12)
427
cylinder.translate(0, 0, 5) # Move cylinder up
428
429
# Combine meshes
430
mesh.add_mesh(mesh=box)
431
mesh.add_mesh(mesh=cylinder)
432
433
# Optimize mesh
434
from ezdxf.render import MeshVertexMerger
435
merger = MeshVertexMerger(mesh, precision=3)
436
optimized_mesh = merger.merged_mesh()
437
438
# Render to layout
439
optimized_mesh.render_mesh(msp, dxfattribs={
440
'color': 1,
441
'layer': 'MESH'
442
})
443
444
# Save document
445
doc.saveas('rendered_mesh.dxf')
446
```