0
# Layouts
1
2
Layout management system for organizing drawing content in Model Space (3D geometry) and Paper Space (plotting layouts). Layouts provide the structure for placing entities and managing drawing hierarchy.
3
4
## Capabilities
5
6
### Layout Management
7
8
Core layout functionality for managing drawing organization and entity placement.
9
10
```python { .api }
11
class Layout:
12
"""Base layout class with entity management"""
13
14
@property
15
def name(self) -> str:
16
"""Layout name"""
17
18
@property
19
def dxf_layout(self):
20
"""Associated DXF layout table entry"""
21
22
def __len__(self) -> int:
23
"""Number of entities in layout"""
24
25
def __iter__(self):
26
"""Iterate over entities in layout"""
27
28
def query(self, query: str = '*'):
29
"""
30
Query entities by criteria.
31
32
Parameters:
33
- query: entity selection query string ('*', 'LINE', 'CIRCLE[layer=="0"]', etc.)
34
35
Returns:
36
EntityQuery: Collection of matching entities
37
"""
38
39
def groupby(self, dxfattrib: str = '', key = None):
40
"""Group entities by DXF attribute or custom key function"""
41
42
def delete_entity(self, entity): ...
43
def delete_all_entities(self): ...
44
def unlink_entity(self, entity): ...
45
46
class Modelspace(Layout):
47
"""Model space layout for 3D geometry and main drawing content"""
48
49
def add_foreign_entity(self, entity, copy: bool = True):
50
"""Add entity from another document"""
51
52
class Paperspace(Layout):
53
"""Paper space layout for plotting and annotation"""
54
55
@property
56
def page_setup(self):
57
"""Page setup configuration"""
58
59
class BlockLayout(Layout):
60
"""Block definition layout containing block entities"""
61
62
@property
63
def block(self):
64
"""Associated block definition entity"""
65
66
@property
67
def endblk(self):
68
"""Block end marker entity"""
69
70
@property
71
def attdefs(self):
72
"""Attribute definitions in block"""
73
```
74
75
Usage examples:
76
```python
77
import ezdxf
78
79
doc = ezdxf.new()
80
81
# Access model space
82
msp = doc.modelspace()
83
print(f"Entities in model space: {len(msp)}")
84
85
# Create paper space layout
86
psp = doc.new_layout('Plot Layout')
87
88
# Query entities
89
lines = msp.query('LINE') # All lines
90
red_circles = msp.query('CIRCLE[color==1]') # Red circles
91
layer0_entities = msp.query('*[layer=="0"]') # All entities on layer 0
92
93
# Group entities
94
by_layer = msp.groupby('layer')
95
for layer_name, entities in by_layer.items():
96
print(f"Layer {layer_name}: {len(entities)} entities")
97
```
98
99
### Entity Creation
100
101
Factory methods for creating and adding entities to layouts.
102
103
```python { .api }
104
# Basic geometry
105
def add_point(self, location, dxfattribs: dict = None) -> Point: ...
106
def add_line(self, start, end, dxfattribs: dict = None) -> Line: ...
107
def add_circle(self, center, radius: float, dxfattribs: dict = None) -> Circle: ...
108
def add_arc(self, center, radius: float, start_angle: float, end_angle: float,
109
dxfattribs: dict = None) -> Arc: ...
110
def add_ellipse(self, center, major_axis, ratio: float = 1,
111
start_param: float = 0, end_param: float = 2*pi,
112
dxfattribs: dict = None) -> Ellipse: ...
113
114
# Text entities
115
def add_text(self, text: str, dxfattribs: dict = None) -> Text: ...
116
def add_mtext(self, text: str, dxfattribs: dict = None) -> MText: ...
117
118
# Polylines
119
def add_lwpolyline(self, points, format: str = 'xy', dxfattribs: dict = None) -> LWPolyline: ...
120
def add_polyline2d(self, points, dxfattribs: dict = None) -> Polyline: ...
121
def add_polyline3d(self, points, dxfattribs: dict = None) -> Polyline: ...
122
123
# Curves
124
def add_spline(self, control_points, degree: int = 3, dxfattribs: dict = None) -> Spline: ...
125
def add_spline_with_a_fit_points(self, fit_points, degree: int = 3,
126
dxfattribs: dict = None) -> Spline: ...
127
128
# Complex entities
129
def add_hatch(self, color: int = 256, dxfattribs: dict = None) -> Hatch: ...
130
def add_mpolygon(self, dxfattribs: dict = None) -> MPolygon: ...
131
def add_mesh(self, dxfattribs: dict = None) -> Mesh: ...
132
133
# Block insertions
134
def add_insert(self, name: str, insert = (0, 0), dxfattribs: dict = None) -> Insert: ...
135
def add_auto_blockref(self, name: str, insert = (0, 0), values: dict = None,
136
dxfattribs: dict = None) -> Insert: ...
137
138
# Images and underlays
139
def add_image(self, image_def, insert = (0, 0), size_in_units = (1, 1),
140
rotation: float = 0, dxfattribs: dict = None) -> Image: ...
141
def add_underlay(self, underlay_def, insert = (0, 0), scale = (1, 1, 1),
142
rotation: float = 0, dxfattribs: dict = None) -> Underlay: ...
143
144
# Dimensions
145
def add_linear_dim(self, base, p1, p2, dimstyle: str = 'EZDXF',
146
override: dict = None, dxfattribs: dict = None): ...
147
def add_aligned_dim(self, p1, p2, distance: float, dimstyle: str = 'EZDXF',
148
override: dict = None, dxfattribs: dict = None): ...
149
def add_angular_dim_2l(self, base, line1, line2, dimstyle: str = 'EZDXF',
150
override: dict = None, dxfattribs: dict = None): ...
151
def add_diameter_dim(self, center, radius: float, angle: float = 0,
152
dimstyle: str = 'EZDXF', override: dict = None,
153
dxfattribs: dict = None): ...
154
```
155
156
Usage examples:
157
```python
158
from ezdxf.math import Vec3
159
import math
160
161
# Basic entities
162
line = msp.add_line((0, 0), (10, 10))
163
circle = msp.add_circle((5, 5), 3)
164
arc = msp.add_arc((0, 0), 5, 0, 90)
165
166
# Text with attributes
167
text = msp.add_text("Hello World", dxfattribs={
168
'height': 2.5,
169
'color': 1, # Red
170
'layer': 'TEXT'
171
})
172
173
# Polyline with multiple points
174
points = [(0, 0), (10, 0), (10, 10), (0, 10)]
175
lwpoly = msp.add_lwpolyline(points, dxfattribs={'layer': 'POLYLINES'})
176
lwpoly.close() # Close the polyline
177
178
# Spline curve
179
control_points = [Vec3(0, 0), Vec3(2, 4), Vec3(4, 0), Vec3(6, -2)]
180
spline = msp.add_spline(control_points, degree=3)
181
182
# Block insertion with scaling and rotation
183
insert = msp.add_insert('MY_BLOCK', insert=(20, 20), dxfattribs={
184
'xscale': 2.0,
185
'yscale': 2.0,
186
'rotation': 45
187
})
188
```
189
190
### Layout Collections
191
192
Management of multiple layouts in a document.
193
194
```python { .api }
195
class Layouts:
196
"""Collection of all layouts in a document"""
197
198
def __len__(self) -> int:
199
"""Number of layouts"""
200
201
def __iter__(self):
202
"""Iterate over all layouts"""
203
204
def __contains__(self, name: str) -> bool:
205
"""Check if layout exists"""
206
207
def __getitem__(self, name: str) -> Layout:
208
"""Get layout by name"""
209
210
def names(self) -> List[str]:
211
"""List of all layout names"""
212
213
def names_in_taborder(self) -> List[str]:
214
"""Layout names in tab display order"""
215
216
def get(self, name: str) -> Layout:
217
"""Get layout by name, returns None if not found"""
218
219
def new(self, name: str, dxfattribs: dict = None) -> Paperspace:
220
"""Create new paper space layout"""
221
222
def rename(self, old_name: str, new_name: str): ...
223
def delete(self, name: str): ...
224
def set_active_layout(self, name: str): ...
225
226
@property
227
def active_layout(self) -> Layout:
228
"""Currently active layout"""
229
230
@property
231
def modelspace(self) -> Modelspace:
232
"""Model space layout"""
233
```
234
235
Usage examples:
236
```python
237
# Access layouts collection
238
layouts = doc.layouts
239
240
# List all layouts
241
print(f"Available layouts: {layouts.names()}")
242
243
# Create new layout
244
plot_layout = layouts.new('Plot Sheet 1', dxfattribs={
245
'taborder': 1
246
})
247
248
# Switch active layout
249
layouts.set_active_layout('Plot Sheet 1')
250
current = layouts.active_layout
251
252
# Rename layout
253
layouts.rename('Plot Sheet 1', 'Main Plot')
254
255
# Check if layout exists
256
if 'Detail View' in layouts:
257
detail = layouts['Detail View']
258
```
259
260
### Block Definitions
261
262
Creating and managing reusable block definitions.
263
264
```python { .api }
265
class BlocksSection:
266
"""Collection of block definitions"""
267
268
def __len__(self) -> int: ...
269
def __iter__(self): ...
270
def __contains__(self, name: str) -> bool: ...
271
def __getitem__(self, name: str) -> BlockLayout: ...
272
273
def new(self, name: str, base_point = (0, 0), dxfattribs: dict = None) -> BlockLayout:
274
"""Create new block definition"""
275
276
def get(self, name: str) -> BlockLayout:
277
"""Get block by name, returns None if not found"""
278
279
def rename_block(self, old_name: str, new_name: str): ...
280
def delete_block(self, name: str, safe: bool = True): ...
281
def delete_all_blocks(self): ...
282
283
@property
284
def names(self) -> List[str]:
285
"""List of all block names"""
286
```
287
288
Usage examples:
289
```python
290
# Access blocks collection
291
blocks = doc.blocks
292
293
# Create new block definition
294
symbol_block = blocks.new('SYMBOL_1', base_point=(0, 0))
295
296
# Add entities to block
297
symbol_block.add_circle((0, 0), 1)
298
symbol_block.add_line((-1, 0), (1, 0))
299
symbol_block.add_line((0, -1), (0, 1))
300
301
# Use block in layout
302
msp.add_insert('SYMBOL_1', insert=(10, 10))
303
304
# List all blocks
305
print(f"Available blocks: {blocks.names}")
306
307
# Check block usage before deletion
308
if 'OLD_SYMBOL' in blocks:
309
try:
310
blocks.delete_block('OLD_SYMBOL', safe=True)
311
except ezdxf.DXFBlockInUseError:
312
print("Block is still referenced")
313
```
314
315
### Entity Queries
316
317
Advanced entity selection and filtering capabilities.
318
319
```python { .api }
320
class EntityQuery:
321
"""Result of layout.query() operations"""
322
323
def __len__(self) -> int: ...
324
def __iter__(self): ...
325
def __getitem__(self, index): ...
326
327
def extend(self, entities): ...
328
def filter(self, predicate) -> 'EntityQuery': ...
329
def query(self, query: str) -> 'EntityQuery': ...
330
331
@property
332
def first(self):
333
"""First entity or None"""
334
335
@property
336
def last(self):
337
"""Last entity or None"""
338
```
339
340
Query syntax examples:
341
```python
342
# Basic entity type queries
343
lines = msp.query('LINE')
344
circles = msp.query('CIRCLE')
345
all_entities = msp.query('*')
346
347
# Attribute-based queries
348
red_entities = msp.query('*[color==1]')
349
layer0_lines = msp.query('LINE[layer=="0"]')
350
thick_lines = msp.query('LINE[lineweight>50]')
351
352
# Complex queries with multiple conditions
353
complex_query = msp.query('CIRCLE[color==1][layer=="SYMBOLS"][radius>=5.0]')
354
355
# Combine queries
356
lines_and_arcs = msp.query('LINE ARC')
357
geometric_entities = msp.query('LINE CIRCLE ARC ELLIPSE')
358
359
# Use query results
360
for entity in msp.query('TEXT'):
361
if entity.dxf.height < 2.0:
362
entity.dxf.height = 2.0
363
364
# Filter query results further
365
large_circles = msp.query('CIRCLE').filter(lambda e: e.dxf.radius > 10)
366
```
367
368
## Layout Hierarchy
369
370
Layout organization and relationships:
371
372
```python { .api }
373
class Drawing:
374
"""Main document class"""
375
376
def modelspace(self) -> Modelspace:
377
"""Get model space layout"""
378
379
def layout(self, name: str = None) -> Layout:
380
"""Get layout by name (active layout if name is None)"""
381
382
def new_layout(self, name: str, dxfattribs: dict = None) -> Paperspace:
383
"""Create new paper space layout"""
384
385
@property
386
def layouts(self) -> Layouts:
387
"""Layouts collection"""
388
389
@property
390
def blocks(self) -> BlocksSection:
391
"""Block definitions collection"""
392
```
393
394
Usage examples:
395
```python
396
import ezdxf
397
398
# Document with layouts
399
doc = ezdxf.new('R2018', setup=True)
400
401
# Model space for 3D geometry
402
msp = doc.modelspace()
403
msp.add_line((0, 0, 0), (100, 100, 50))
404
405
# Paper space for plotting
406
psp1 = doc.new_layout('Sheet 1')
407
psp1.add_text('Title: My Drawing', dxfattribs={'height': 5})
408
409
# Block for reusable content
410
title_block = doc.blocks.new('TITLE_BLOCK')
411
title_block.add_rectangle((0, 0), 100, 20)
412
title_block.add_text('Company Name', dxfattribs={'height': 3})
413
414
# Use block in paper space
415
psp1.add_insert('TITLE_BLOCK', insert=(0, 0))
416
417
# Save document
418
doc.saveas('drawing_with_layouts.dxf')
419
```