File: content.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 (348 lines) | stat: -rw-r--r-- 11,262 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
342
343
344
345
346
347
348
DXF Content
===========

General preconditions:

.. code-block:: python

    import sys
    import ezdxf

    try:
        doc = ezdxf.readfile("your_dxf_file.dxf")
    except IOError:
        print(f'Not a DXF file or a generic I/O error.')
        sys.exit(1)
    except ezdxf.DXFStructureError:
        print(f'Invalid or corrupted DXF file.')
        sys.exit(2)
    msp = doc.modelspace()


.. _howto_get_color:

Get/Set Entity Color
--------------------

The entity color is stored as :term:`ACI` (AutoCAD Color Index):

.. code-block:: python

    aci = entity.dxf.color

Default value is 256 which means BYLAYER:

.. code-block:: python

    layer = doc.layers.get(entity.dxf.layer)
    aci = layer.get_color()

The special :meth:`~ezdxf.entities.Layer.get_color` method is required, because
the color attribute :attr:`Layer.dxf.color` is misused as layer on/off flag, a
negative color value means the layer is off.

ACI value 0 means BYBLOCK, which means the color from the block reference
(INSERT entity).

Set color as ACI value as int in range [0, 256]:

.. code-block:: python

    entity.dxf.color = 1


The ACI value 7 has a special meaning, it is white on dark backgrounds and white
on light backgrounds.

.. _howto_get_entity_rgb_color:

Get/Set Entity RGB Color
------------------------

RGB true color values are supported since DXF R13 (AC1012), the 24-bit RGB value
is stored as integer in the DXF attribute :attr:`~ezdxf.entities.DXFGraphic.dxf.true_color`:

.. code-block:: python

    # 24 bit binary value: 0bRRRRRRRRGGGGGGGGBBBBBBBB or hex value: 0xRRGGBB
    # set true color value to red
    entity.dxf.true_color = 0xFF0000

Use the helper functions from the :mod:`ezdxf.colors` module for
RGB integer value handling:

.. code-block:: python

    from ezdxf import colors

    entity.dxf.true_color = colors.rgb2int((0xFF, 0, 0))
    r, g, b = colors.int2rgb(entity.dxf.true_color)

The RGB values of the AutoCAD default colors are not officially documented,
but an accurate translation table is included in `ezdxf`:

.. code-block:: python

    # Warning: ACI value 256 (BYLAYER) raises an IndexError!
    rgb24 = colors.DXF_DEFAULT_COLORS[aci]
    print(f"RGB Hex Value: #{rgb24:06X}")
    r, g, b = colors.int2rgb(rgb24)
    print(f"RGB Channel Values: R={r:02X} G={g:02X} b={b:02X}")

If :attr:`color` and :attr:`true_color` values are set, BricsCAD and AutoCAD use
the :attr:`true_color` value as display color for the entity.

Get/Set True Color as RGB-Tuple
-------------------------------

Get/Set the true color value as (r, g, b)-tuple by the
:attr:`~ezdxf.entities.DXFGraphic.rgb` property of the
:class:`~ezdxf.entities.DXFGraphic` entity:

.. code-block:: python

    # set true color value to red
    entity.rgb = (0xFF, 0, 0)

    # get true color values
    r, g, b = entity.rgb

.. _howto_get_attribs:

Get/Set Block Reference Attributes
----------------------------------

Block references (:class:`~ezdxf.entities.Insert`) can have attached attributes (:class:`~ezdxf.entities.Attrib`),
these are simple text annotations with an associated tag appended to the block reference.

Iterate over all appended attributes:

.. code-block:: python

    # get all INSERT entities with entity.dxf.name == "Part12"
    blockrefs = msp.query('INSERT[name=="Part12"]')
    if len(blockrefs):
        entity = blockrefs[0]  # process first entity found
        for attrib in entity.attribs:
            if attrib.dxf.tag == "diameter":  # identify attribute by tag
                attrib.dxf.text = "17mm"  # change attribute content

Get attribute by tag:

.. code-block:: python

    diameter = entity.get_attrib('diameter')
    if diameter is not None:
        diameter.dxf.text = "17mm"


Adding XDATA to Entities
------------------------

Adding XDATA as list of tuples (group code, value) by :meth:`~ezdxf.entities.DXFEntity.set_xdata`, overwrites
data if already present:

.. code-block:: python

    doc.appids.new('YOUR_APPID')  # IMPORTANT: create an APP ID entry

    circle = msp.add_circle((10, 10), 100)
    circle.set_xdata(
        'YOUR_APPID',
        [
            (1000, 'your_web_link.org'),
            (1002, '{'),
            (1000, 'some text'),
            (1002, '{'),
            (1071, 1),
            (1002, '}'),
            (1002, '}')
        ])

For group code meaning see DXF reference section `DXF Group Codes in Numerical Order Reference`_, valid group codes are
in the range 1000 - 1071.

Method :meth:`~ezdxf.entities.DXFEntity.get_xdata` returns the extended data for an entity as
:class:`~ezdxf.lldxf.tags.Tags` object.

.. seealso::

    Tutorial: :ref:`tut_custom_data`

Get Overridden DIMSTYLE Values from DIMENSION
---------------------------------------------

In general the :class:`~ezdxf.entities.Dimension` styling and config attributes are stored in the
:class:`~ezdxf.entities.Dimstyle` entity, but every attribute can be overridden for each DIMENSION
entity individually, get overwritten values by the :class:`~ezdxf.entities.DimstyleOverride` object
as shown in the following example:

.. code-block:: python

    for dimension in msp.query('DIMENSION'):
        dimstyle_override = dimension.override()  # requires v0.12
        dimtol = dimstyle_override['dimtol']
        if dimtol:
            print(f'{str(dimension)} has tolerance values:')
            dimtp = dimstyle_override['dimtp']
            dimtm = dimstyle_override['dimtm']
            print(f'Upper tolerance: {dimtp}')
            print(f'Lower tolerance: {dimtm}')

The :class:`~ezdxf.entities.DimstyleOverride` object returns the value of the underlying DIMSTYLE objects if the
value in DIMENSION was not overwritten, or ``None`` if the value was neither defined in DIMSTYLE nor in DIMENSION.

Override DIMSTYLE Values for DIMENSION
--------------------------------------

Same as above, the :class:`~ezdxf.entities.DimstyleOverride` object supports also overriding DIMSTYLE values.
But just overriding this values have no effect on the graphical representation of the DIMENSION entity, because
CAD applications just show the associated anonymous block which contains the graphical representation on the
DIMENSION entity as simple DXF entities. Call the :class:`~ezdxf.entities.DimstyleOverride.render` method of the
:class:`~ezdxf.entities.DimstyleOverride` object to recreate this graphical representation by `ezdxf`, but `ezdxf`
**does not** support all DIMENSION types and DIMVARS yet, and results **will differ** from AutoCAD
or BricsCAD renderings.

.. code-block:: python

    dimstyle_override = dimension.override()
    dimstyle_override.set_tolerance(0.1)

    # delete associated geometry block
    del doc.blocks[dimension.dxf.geometry]

    # recreate geometry block
    dimstyle_override.render()

How to Change the HATCH Pattern Origin Point
--------------------------------------------

This code sets the origin of the first pattern line to the given `origin` and
the origins of all remaining pattern lines relative to the first pattern line
origin.

.. code-block:: python

    from ezdxf.entities import Hatch, Pattern
    from ezdxf.math import Vec2

    def shift_pattern_origin(hatch: Hatch, offset: Vec2):
        if isinstance(hatch.pattern, Pattern):
            for pattern_line in hatch.pattern.lines:
                pattern_line.base_point += offset

    def reset_pattern_origin_of_first_pattern_line(hatch: Hatch, origin: Vec2):
        if isinstance(hatch.pattern, Pattern) and len(hatch.pattern.lines):
            first_pattern_line = hatch.pattern.lines[0]
            offset = origin - first_pattern_line.base_point
            shift_pattern_origin(hatch, offset)

.. seealso::

    - Discussion `#769 <https://github.com/mozman/ezdxf/discussions/769>`_

How to Get the Length of a Spline or Polyline
---------------------------------------------

There exist no analytical function to calculate the length of a `B-spline`_, you
have to approximate the curve and calculate the length of the polyline.
The construction tool :class:`ezdxf.math.ConstructionPolyline` is may be useful
for that.

.. code-block:: python

    import ezdxf
    from ezdxf.math import ConstructionPolyline

    doc = ezdxf.new()
    msp = doc.modelspace()
    fit_points = [(0, 0, 0), (750, 500, 0), (1750, 500, 0), (2250, 1250, 0)]

    spline = msp.add_spline(fit_points)
    # Adjust the max. sagitta distance to your needs or run the calculation in a loop
    # reducing the distance until the difference to the previous run is smaller
    # than your expected precision:
    polyline = ConstructionPolyline(spline.flattening(distance=0.1))
    print(f"approximated length = {polyline.length:.2f}")

How to Resolve DXF Properties
-----------------------------

Graphical properties of DXF entities (color, lineweight, ...) are sometimes
hard to resolve because of the complex possibilities to inherit properties from
layers or blocks, or overriding them by :term:`ctb` files.

The :mod:`~ezdxf.addons.drawing` add-on provides the
:class:`~ezdxf.addons.drawing.properties.RenderContext` class that can be used
to resolve properties of entities in the context of their use:

.. code-block:: python

    import ezdxf
    from ezdxf.addons.drawing.properties import RenderContext

    doc = ezdxf.new()
    doc.layers.add("LINE", color=ezdxf.colors.RED)
    msp = doc.modelspace()
    line = msp.add_line((0, 0), (1, 0), dxfattribs={"layer": "LINE"})

    ctx = RenderContext(doc)
    ctx.set_current_layout(msp)
    print(f"resolved RGB value: {ctx.resolve_color(line)}")

Output::

    resolved RGB value: #ff0000

This works in most simple cases, resolving properties of objects in viewports or
nested blocks requires additional information that is beyond the scope of a
simple guide.

How to Find XREF Definitions
----------------------------

XREFs are normal block definitions and can be found in the BLOCKS section:

.. code-block:: Python

    for block_layout in doc.blocks:
        block = block_layout.block  # the BLOCK entity
        if block.is_xref:
            handle_xref(block_layout)
        elif block.is_xref_overlay:
            handle_xref_overlay(block_layout)

.. seealso::

    - documentation of the :mod:`ezdxf.xref` module
    - :class:`ezdxf.layouts.BlockLayout`

How to Find XREF References
---------------------------

An XREF reference is a block reference (INSERT entity) to the block definition of
the XREF:

.. code-block:: Python

    for insert in msp.query("INSERT"):
        if insert.is_xref:
            handle_xref_reference(insert)
            # ... or get the XREF definition
            block_layout = insert.block()
            if block_layout is not None:
                block = block_layout.block
                if block.is_xref:
                    handle_xref(block_layout)
                elif block.is_xref_overlay:
                    handle_xref_overlay(block_layout)

Like any normal block, an XREF can be inserted multiple times.

.. seealso::

    - documentation of the :mod:`ezdxf.xref` module
    - :class:`ezdxf.layouts.BlockLayout`

.. _DXF Group Codes in Numerical Order Reference: http://help.autodesk.com/view/OARX/2018/ENU/?guid=GUID-3F0380A5-1C15-464D-BC66-2C5F094BCFB9
.. _B-spline: https://en.wikipedia.org/wiki/B-spline