The new browse command opens a DXF structure browser to investigate the
internals of a DXF file without interpreting the content. The functionality of
the DXF browser is similar to the DXF Pretty Printer, but without the
disadvantage of creating giant HTML files. The intended usage is debugging
invalid DXF files, which can not be loaded by ezdxf.readfile() or the
ezdxf.recover.readfile() functions.
C:\> ezdxf browse gear.dxf

The new command strip removes all comment tags (999) and the THUMBNAILIMAGE
section.
The new command config manages config files.
For more information read the launcher documentation.
Config files store global ezdxf options in INI-files.
The default config files are loaded from the user home directory as
"~/.config/ezdxf/ezdxf.ini", and the current working directory as "./ezdxf.ini".
A custom config file can be specified by the environment variable EZDXF_CONFIG_FILE.
Ezdxf follows the XDG Base Directory specification if the environment variable
XDG_CONFIG_HOME is set.
For more information read the documentation about global options.
ezdxf Meta Data in DXF filesFor debugging the ezdxf version and date/time of creation or modification of
a DXF file is stored as meta data in DXF file itself. Ezdxf uses standard DXF
features to store its meta data. This meta data is preserved by Autodesk products,
BricsCAD and of course ezdxf. Other 3rd party DXF libraries may remove this
meta data.
The MetaData object is open to store additional user data as strings:
import ezdxf
doc = ezdxf.new()
metadata = doc.ezdxf_metadata()
metadata["MyAdditionalUserData"] = "XYZ"
Keys used by ezdxf:
CREATED_BY_EZDXFWRITTEN_BY_EZDXFFor more information read the documentation about document settings.
New helper classes to store custom data in DXF files in a simple way.
For more information read the new tutorial about storing custom data in DXF files.
The MPOLYGON entity is supported by all internal modules and functions and the
following add-ons:
drawingdxf2codegeoupright ModuleThe upright() and upright_all() functions convert an inverted OCS defined
by an extrusion vector (0, 0, -1) into a WCS aligned OCS defined by an extrusion
vector (0, 0, 1).
This simplifies 2D entity processing for ezdxf users and creates DXF output for 3rd party DXF libraries which ignore the existence of the OCS.
Supported DXF entities:
CIRCLEARCELLIPSE (WCS entity, flips only the extrusion vector)SOLIDTRACELWPOLYLINEPOLYLINE (only 2D entities)HATCHMPOLYGONINSERT (block references)The WCS representation of OCS entities with flipped extrusion vector is not 100%
identical to the source entity, curve orientation and vertex order may change,
see additional explanation in the docs. A mirrored text represented by an
extrusion vector (0, 0, -1) cannot represented by an extrusion vector (0, 0, 1),
therefore this CANNOT work for text entities or entities including text: TEXT,
ATTRIB, ATTDEF, MTEXT, DIMENSION, LEADER, MLEADER
The functions can be applied to any DXF entity without expecting errors or exceptions if the DXF entity is not supported or the extrusion vector differs from (0, 0, -1). This also means you can apply the functions multiple times to the same entities without any problems. A common case would be to upright all entities of the model space:
import ezdxf
from ezdxf.upright import upright_all
doc = ezdxf.readfile("your.dxf")
msp = doc.modelspace()
upright_all(msp)
# doing it again is no problem but also has no further effects
upright_all(msp)
For more information read the upright documentation.
MTextExplode Add-onThis tool is meant to explode MTEXT entities into single line TEXT entities
by replicating the MTEXT layout as close as possible. This tool requires the
optional Matplotlib package to create usable results, nonetheless it also
works without Matplotlib, but then uses a mono-spaced replacement font for
text size measuring which leads to very inaccurate results.
Example to explode all MTEXT entities in the DXF file "mtext.dxf":
import ezdxf
from ezdxf.addons import MTextExplode
doc = ezdxf.readfile("mtext.dxf")
msp = doc.modelspace()
# msp is the target layout for "exploded" parts of the MTEXT entity
with MTextExplode(msp) as xpl:
for mtext in msp.query("MTEXT"):
xpl.explode(mtext)
doc.saveas("xpl_mtext.dxf")
For more information read the MTextExplode documentation.
drawing Add-onThe previous way to configure the drawing add-on by passing an untyped dict
to the backend, has been replaced by a Configuration
dataclass, which is passed as the config argument of the Frontend class
initializer.
Excerpt from example file draw_cad.py
# required imports
from ezdxf.addons.drawing.config import Configuration, LinePolicy
# -x-x-x- snip
# create configuration
config = Configuration.defaults()
config = config.with_changes(
line_policy=LinePolicy.ACCURATE
if args.ltype == "ezdxf"
else config.line_policy
)
# -x-x-x- snip
# pass configuration to Frontend() class
Frontend(ctx, out, config=config).draw_layout(layout, finalize=True)
# -x-x-x- snip
drawing Add-onColumns and inline formatting codes are now supported. Because this feature depends on the exact same font rendering as done by CAD applications, which cannot be replicated, results are close to CAD applications but are not perfect.

ezdxf.path.Path ClassThe class ezdxf.path.Path supports now multiple paths in one instance. This
required the new command move_to(location), which starts a new sub-path
at the given location. The new property Path.has_sub_paths is True if
more than one path is present in an instance. The method Path.sub_paths()
yield all sub paths as single path instances, the utility function
ezdxf.path.single_paths() does the same for an iterable of of single- or
multi-path objects.
The function ezdxf.path.to_multi_path() builds a new multi-path object from
an iterable of single- or multi-path objects.
The converter function ezdxf.path.make_path() supports now the HATCH and the
MPOLYGON entity directly and returns a multi-path instance with a sub-path
for each HATCH boundary path. The converter function ezdxf.path.from_hatch()
still exist and returns all boundary paths of HATCH entities as single-path
objects like in the previous versions of ezdxf:
from ezdxf.path import make_path, from_hatch
# ...
paths = list(make_path(hatch).sub_paths())
# is the same as
paths = list(from_hatch(hatch))
dxf2code Add-onThe method black_code_str() returns the same code string as the
code_str() method, but reformatted by the Black
formatting tool, if Black is installed.
import ezdxf
from ezdxf.addons.dxf2code import entities_to_code
doc = ezdxf.readfile('original.dxf')
msp = doc.modelspace()
source = entities_to_code(msp)
with open('source.py', mode='wt') as f:
f.write(source.import_str())
f.write('\n\n')
f.write(source.black_code_str())
f.write('\n')
With the addition of support for type annotations, typed factory methods were required to create resource table entries:
Drawing.layers.add() factory method to create new layersDrawing.styles.add() factory method to create new text stylesDrawing.linetypes.add() factory method to create new line typesThe new recommended way to create layers, text styles or linetypes is:
import ezdxf
doc = ezdxf.new(setup=True)
doc.layers.add("MyLayer", color=2, linetype="DASHED")
doc.styles.add("Arial", font="arial.ttf")
doc.linetypes.add("DASHEDX3", [0.9, 0.8, -0.1], description="Dashed (3x) ___ ___ ___ ___ ___")
There are also new typed factory methods for all remaining resource tables, but they are not that important to library users:
Drawing.dimstyles.add()Drawing.appids.add()Drawing.ucs.add()Drawing.views.add()Drawing.viewports.add()Drawing.block_records.add()The MTextEditor is a helper class to build MTEXT content strings with
support for inline codes to change color, font or paragraph properties.
from ezdxf.tools.text import MTextEditor
e = MTextEditor("This example ").color("red").append("switches color to red.")
mtext = msp.add_mtext(str(e))
For more information see the docs
or the MTEXT tutorial.
New factory methods to create MTEXT entities with columns. The current
implementation works best for DXF R2018, because the content is stored as a
continuous text in a single MTEXT entity.
For DXF versions prior to R2018 the content should be distributed across multiple
MTEXT entities (one entity per column), which is not done by ezdxf, but
the result is correct for advanced DXF viewers and CAD application, which
do the MTEXT content distribution completely by itself.
BaseLayout.add_mtext_static_columns()BaseLayout.add_mtext_dynamic_manual_height_columns()BaseLayout.add_mtext_dynamic_auto_height_columns()It is recommended to use DXF R2018 for MTEXT with columns!
ezdxf.entity.MText column support, parsing tools, composing toolsACAD_PROXY_ENTITY entityATTRIB and ATTDEF entities in DXF R2018.Auditor removes invalid DXF entities from layouts, blocks and the
OBJECTS sectionAuditor removes invalid standalone ATTRIB entities from layouts and
blocks.XDATA section of a
DXF entity Environment variable options, these are config file only options now:
EZDXF_AUTO_LOAD_FONTSEZDXF_FONT_CACHE_DIRECTORYEZDXF_PRESERVE_PROXY_GRAPHICSEZDXF_LOG_UNPROCESSED_TAGSEZDXF_FILTER_INVALID_XDATA_GROUP_CODESRemoved the Vector alias for the ezdxf.math.Vec3 class.
Removed the BaseLayout.add_attrib() factory method to add (invalid) standalone
ATTRIB entities
Removed the deprecated class methods from_...(entity) from the
ezdxf.path.Path class, use ezdxf.path.make_path(entity) instead.
Also removed the deprecated ezdxf.path.Path methods add_...(entity),
use path.add_...(path, entity) function instead.
manylinux2010_x86_64 for Python < 3.10 and manylinux2014_x86_64
for Python >= 3.10 musllinux_2010_x86_64 for Python < 3.10 and musllinux_2014_x86_64
for Python >= 3.10manylinux_2014_aarch64 for ARM64 based Linuxmusllinux_2014_aarch64 for ARM64 based Linuxmacosx_11_0_arm64 for Apple siliconmacosx_10_9_universal2 for Apple silicon & x86MESH entitiestransparency argument to LayerTable.add()BYLAYER and BYBLOCK for the drawing add-onTextstyle.make_font() returns the ezdxf font abstractiondxfattribs argument to method Drawing.set_modelspace_vport()ezdxf.math.split_bezier() function to split Bezier curves of any degreeezdxf.math.intersection_line_line_3d()ezdxf.math.intersect_poylines_2d()ezdxf.math.intersect_poylines_3d()ezdxf.math.quadratic_bezier_from_3p()ezdxf.math.cubic_bezier_from_3p()BoundingBox.contains(), check if a bounding box contains completely
another bounding box TextEntityAlignment enum replaces the string based alignment definitionText.get_placement(), replaces get_pos() Text.set_placement(), replaces set_pos() Text.get_align_enum(), replaces get_align()Text.set_align_enum(), replaces set_align()Text.get_pos() will be removed in v1.0.0Text.set_pos() will be removed in v1.0.0Text.get_align() will be removed in v1.0.0Text.set_align() will be removed in v1.0.0MTextEntityAlignment to ezdxf.enumsMTextParagraphAlignment to ezdxf.enumsMTextFlowDirection to ezdxf.enumsMTextLineAlignment to ezdxf.enumsMTextStroke to ezdxf.enumsMTextLineSpacing to ezdxf.enumsMTextBackgroundColor to ezdxf.enumsDimstyle.set_tolerance(): argument align as enum MTextLineAlignmentDimstyleOverride.set_tolerance(): argument align as enum MTextLineAlignmentMeshData.add_edge() is changed to MeshData.add_edge_crease(),
this fixes my misunderstanding of edge and crease data in the MESH entity. Path() and ConstructionEllipse() drawing add-on shows block references in ACAD_TABLE at the
correct locationPolyface.virtual_entities() yields correct triangle facesMESH entity PyQt5 is still supported as fallbackDXFEntitysource_of_copy - the immediate source of an entity copyorigin_of_copy - the first non virtual source entity of an entity copyis_copy - is True if the entity is a copyPOINT, LWPOLYLINE, POLYLINE, LEADER, MLINE, ACAD_PROXY_ENTITY DXFEntityhas_source_block_reference - is True if the virtual entity was created
by a block referencesource_block_reference - the immediate source block reference (INSERT),
which created the virtual entity, otherwise Noneezdxf.tools.text_size module to measure TEXT and MTEXT entity dimensions--ltype arguments of the draw command to approximate and accurate
to be in sync with the drawing add-on configuration.--ltype arguments of the view command to approximate and accurate
to be in sync with the drawing add-on configuration.--scale argument of the view commandPolylinePath.PATH_TYPE, use PolylinePath.type insteadEdgePath.PATH_TYPE, use EdgePath.type insteadXData.safe_init() DIMSTYLE attribute dimtxsty browse command MTEXT entities with column count different than the count of
linked MTEXT entities BaseLayout.add_mtext_static_columns()BaseLayout.add_mtext_dynamic_manual_height_columns()MTextExplode() to explode MTEXT entities
into single line TEXT entities and additional LINE entities to emulate
strokes, requires the Matplotlib packagemove_to() command and multi-path support for the ezdxf.path.Path class make_path() support for the HATCH entity, returns a multi-path object make_primitive() support for the HATCH entity text2path.make_path_from_str() returns a multi-path object text2path.make_path_from_enity() returns a multi-path object MPOLYGON load/write/create supportezdxf.path.to_mpolygons() function: Path() to MPOLYGON converterezdxf.path.render_mpolygons() function: render MPOLYGON entities form pathsezdxf browse FILE ..., PyQt DXF structure browserdxf2code add-on: function black() and method Code.black_code_str()
returns the code string formatted by Blackezdxf.upright module to flip inverted extrusion vectors, for more
information read the docs ACAD_PROXY_ENTITYBaseLayout.add_mtext_static_columns()BaseLayout.add_mtext_dynamic_manual_height_columns()MTEXT entities for the drawing
add-onXDATA transformation supportdrawing add-on: replaced the backend params argument (untyped dict)
by the new typed Configuration object passed to the frontend class as
argument configfrom_...(entity) from Path class,
use path.make_path(entity) insteadPath methods add_...(entity),
use path.add_...(path, entity) function insteadexec_path as win_exec_path DICTIONARY entries DICTIONARY was not added to the OBJECTS section by calling factory.bind()XRecord.copy() copies content tagsRelease notes for v0.16: https://ezdxf.mozman.at/release-v0-16.html