File: xref_module.rst

package info (click to toggle)
ezdxf 1.4.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 104,528 kB
  • sloc: python: 182,341; makefile: 116; lisp: 20; ansic: 4
file content (341 lines) | stat: -rw-r--r-- 11,148 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
.. _tut_xref_module:

Tutorial for External References
================================

.. contents::
    :local:

Introduction
------------

This tutorial uses the :mod:`ezdxf.xref` module to work with external references (XREF).

Attached XREFs are links to the modelspace of a specified drawing file. Changes made
to the referenced drawing are automatically reflected in the current drawing when it's
opened or if the XREF is reloaded.

.. important::

    **AutoCAD can only display DWG files as attached XREFs.**
    Any DXF file attached as an XREF to a DXF document must be converted to DWG in order
    to be viewed in AutoCAD.
    Fortunately, other CAD applications are more cooperative, BricsCAD has no problem
    displaying DXF files as XREFs.

    The :mod:`~ezdxf.addons.drawing` add-on included in `ezdxf` **does not display external
    references at all!**

There are some example files included in the `examples/xref <https://github.com/mozman/ezdxf/tree/master/examples/xref>`_
folder of the repository:

    - attach_dxf_dwg_xref.py
    - detach_block_as_xref.py
    - embed_dxf_dwg_xref.py
    - load_table_resources.py


Supported Entities
------------------

All operations which move entities between layouts and XREFs copy these entities,
therefore only entities which are copyable can be transferred.
The following entities are not copyable:

- All entities which are not documented by the DXF reference.
- ACAD_TABLE
- ACAD_PROXY_ENTITY
- OLE2FRAME
- ACIS based entities: BODY, 3DSOLID, REGION, ...
- Custom entities from applications on top of AutoCAD like Map 3D, Civil 3D or
  Architecture. The vertical integration stack is not documented by the DXF reference.

Unsupported entities are ignored and do not raise exceptions.

Environment Setup
-----------------

Required imports to follow this tutorial:

.. literalinclude:: src/xref/attach_dxf_dwg_xref.py
    :lines: 3-9

Function to create a simple DXF file as XREF, the insertion point of the XREF is set to
(5, 5):

.. literalinclude:: src/xref/attach_dxf_dwg_xref.py
    :lines: 14-26

Create the DXF file::

    make_dxf_xref_document("xref.dxf")

The XREF looks like this:

.. image:: gfx/xref_doc.png
    :align: center

Attach a DXF File
-----------------

Create a host document to which the XREF will be attached::

    host_doc = ezdxf.new(DXFVERSION, units=units.M)

Attach the XREF by the :func:`ezdxf.xref.attach` function and save the host DXF file::

    xref.attach(host_doc, block_name="dxf_xref", insert=(0, 0), filename="attached_xref.dxf")
    host_doc.set_modelspace_vport(height=10, center=(0, 0))
    host_doc.saveas("attach_host_dxf.dxf")


The :func:`attach` function is meant to simply attach an XREF once without any
overhead, therefore the :func:`attach` function creates the required block definition
automatically and raises an :class:`XrefDefinitionError` exception if the block definition
already exist. To attach additional XREF references use the method
:meth:`~ezdxf.layouts.BaseLayout.add_blockref`::

    msp.add_blockref("dxf_xref", insert=another_location)


The attached DXF file in BricsCAD:

.. image:: gfx/xref_attached_dxf.png
    :align: center

.. important::

    AutoCAD can not display DXF files as attached XREFs.

Attach a DWG File
-----------------

Export the DXF file as DWG by the :mod:`~ezdxf.addons.odafc` add-on::

    # It's not required to save the DXF file!
    doc = make_dxf_xref_document("attached_xref.dxf")
    try:
        odafc.export_dwg(doc, "attached_xref.dwg", replace=True)
    except odafc.ODAFCError as e:
        print(str(e))

Attach the DWG file by the :func:`ezdxf.xref.attach` function and save the host DXF file::

    host_doc = ezdxf.new(DXFVERSION, units=units.M)
    xref.attach(host_doc, block_name="dwg_xref", filename="attached_xref.dwg", insert=(0, 0))
    host_doc.set_modelspace_vport(height=10, center=(0, 0))
    host_doc.saveas("attached_dwg.dxf")


Attached DWG file in Autodesk DWG TrueView 2023:

.. image:: gfx/xref_attached_dwg.png
    :align: center

Detach an XREF
--------------

The :func:`~ezdxf.xref.detach` function writes the content of a block definition into
the modelspace of a new DXF document and convert the block to an external reference (XREF).
The new DXF document has to be written/exported by the caller.
The function does not create any block references. These references should already exist
and do not need to be changed since references to blocks and XREFs are the same.

.. literalinclude:: src/xref/detach_dxf_dwg_xref.py
    :lines: 23-29

.. important::

    Save the host document after detaching the block!
    Detaching a block definition modifies the host document.

The :func:`detach` function returns a :class:`Drawing` instance, so it's possible
to convert the DXF document to DWG by the :mod:`~ezdxf.addons.odafc` add-on if necessary
(e.g. for Autodesk products). It's important that the argument :attr:`xref_filename`
match the filename of the exported DWG file:

.. literalinclude:: src/xref/detach_dxf_dwg_xref.py
    :lines: 33-42

It's recommended to clean up the entity database of the host document afterwards::

    host_doc.entitydb.purge()

For understanding, this is the :func:`make_block` function:

.. literalinclude:: src/xref/detach_dxf_dwg_xref.py
    :lines: 10-19

Embed an XREF
-------------

The :func:`embed` function loads the content of the XREF into the block definition,
this is the reverse operation of detaching an XREF.

For loading the content of DWG files is a loading function required, which loads the
DWG file as :class:`Drawing` document. The :mod:`~ezdxf.addons.odafc` add-on module
provides such a function: :func:`~ezdxf.addons.odafc.readfile`.

This example embeds the XREF "attached_xref.dwg" of the first example as content of the
block definition "GEAR", the "attach_host_dwg.dxf" file is the host DXF document:

.. code-block:: Python

    import ezdxf
    from ezdxf.addons import odafc

    doc = ezdxf.readfile("attach_host_dwg.dxf")
    gear_xref = doc.blocks.get("GEAR")

    try:
        xref.embed(gear_xref, load_fn=odafc.readfile)
    except FileNotFoundError as e:
        print(str(e))

The default loading function for DXF files is the :func:`ezdxf.readfile` function and
doesn't have to be specified. For the loading function from the :mod:`~ezdxf.recover`
module use a lambda function:

.. code-block:: Python

    import ezdxf
    from ezdxf import recover

    doc = ezdxf.readfile("attach_host_dxf.dxf")
    gear_xref = doc.blocks.get("GEAR")

    try:
        xref.embed(gear_xref, load_fn=lambda f: recover.readfile(f)[0])
    except FileNotFoundError as e:
        print(str(e))


Load Modelspace
---------------

The :func:`ezdxf.xref.load_modelspace` function loads the content of the modelspace
of the source document into a layout of the target document, the modelspace of the
target document is the default target layout.

.. hint::

    Use this function to combine multiple existing DXF files.
    If the goal is just to add new entities to an existing document, rather load the
    source document as a template by :func:`ezdxf.readfile`, add your content and save
    the document as a new DXF file with the :meth:`saveas` method.

Merge multiple DXF files:

.. literalinclude:: src/xref/merge_dxf_files.py
    :lines: 3-26

.. image:: gfx/xref_merged.png
    :align: center

Load Paperspace
---------------

The function :func:`ezdxf.xref.load_paperspace` loads a paperspace layout as a new
paperspace layout into the target document. To be clear this function loads **only**
the content of the paperspace layout, the content of the modelspace isn't loaded,
therefore the loaded VIEWPORT entities show the content of the target modelspace.


Write Block
-----------

The function :func:`ezdxf.xref.write_block` writes the given entities into the
modelspace of a new DXF document, this document can be, but doesn't have to be used as
an external referenced block.

Conflict Policies
-----------------

Resources are definitions of layers, linetypes, text-, dimension-, mline- and mleader
styles, materials and blocks.

A resource conflict occurs when the source and target documents contain elements such as
layers, linetypes, text styles and so on that share the same name.

Many of the functions shown above support an argument to define the
:class:`ezdxf.xref.ConflictPolicy`, that gives you the choice how to handle resource
name conflicts.

ConflictPolicy.KEEP
~~~~~~~~~~~~~~~~~~~

Keeps the existing resource name of the target document and ignore the resource from the
source document. The loaded entities from the source document use the resources defined
in the target document and may alter their visual appearance, when the resources are
different.

ConflictPolicy.XREF_PREFIX
~~~~~~~~~~~~~~~~~~~~~~~~~~

This policy handles the resource import like CAD applications by **always** renaming the
loaded resources to `<xref>$0$<name>`, where `xref` is the name of source document,
the `$0$` part is a number to create a unique resource name and `<name>` is the name of
the resource itself.

.. important::

    This policy ALWAYS renames the resource, even if the loaded resource doesn't have a
    conflict in the target document.

ConflictPolicy.NUM_PREFIX
~~~~~~~~~~~~~~~~~~~~~~~~~~

This policy renames the loaded resources to `$0$<name>` only if the resource `<name>`
already exists. The `$0$` prefix is a number to create a unique resource name and
`<name>` is the name of the resource itself.

.. important::

    This policy renames the resource ONLY when the loaded resource has a conflict in
    the target document.

Load Table Resources
--------------------

Resources are definitions of layers, linetypes, text-, dimension-, mline- and mleader
styles, materials and blocks.

The :class:`Loader` class is the low level tool to build a loading operation from simple
loading commands. Study the `source code`_ of the :mod:`xref` module, most of loading
commands used above are build upon the :class:`Loader` class.
This example shows how to import layer, linetype, text- and dimension style definitions:

.. code-block:: Python

    import ezdxf
    from ezdxf import xref

    sdoc = ezdxf.new(setup=True)
    tdoc = ezdxf.new()

    # The default conflict policy is ConflictPolicy.KEEP
    loader = xref.Loader(sdoc, tdoc)

    # Load all layers:
    loader.load_layers([layer.dxf.name for layer in sdoc.layers])

    # Load specific linetypes:
    loader.load_linetypes(["CENTER", "DASHED", "DASHDOT"])

    # Load specific text style:
    loader.load_text_styles(["OpenSans", "LiberationMono"])

    # Load all DIMENSION styles, this command loads also the dependent text styles:
    loader.load_dim_styles([dimstyle.dxf.name for dimstyle in sdoc.dimstyles])

    # execute all loading commands:
    loader.execute()
    tdoc.saveas("target.dxf")

.. note::

    Loading a layer does not load the entities which do reference this layer, a layer
    is not an entity container, it's just an DXF attribute, see also Basic Concepts:
    :ref:`layer_concept`.

.. _source code: https://github.com/mozman/ezdxf/blob/master/src/ezdxf/xref.py