Drawing / Export Addon¶
This add-on provides the functionality to render a DXF document to produce a rasterized or vector-graphic image which can be saved to a file or viewed interactively depending on the backend being used.
The module provides two example scripts in the folder examples/addons/drawing
which can be run to save rendered
images to files or view an interactive visualisation
$ ./draw_cad.py --supported_formats
# will list the file formats supported by the matplotlib backend.
# Many formats are supported including vector graphics formats
# such as pdf and svg
$ ./draw_cad.py <my_file.dxf> --out image.png
# draw a layout other than the model space
$ ./draw_cad.py <my_file.dxf> --layout Layout1 --out image.png
# opens a GUI application to view CAD files
$ ./cad_viewer.py
Example for the usage of the matplotlib
backend:
import sys
import matplotlib.pyplot as plt
from ezdxf import recover
from ezdxf.addons.drawing import RenderContext, Frontend
from ezdxf.addons.drawing.matplotlib import MatplotlibBackend
# Safe loading procedure (requires ezdxf v0.14):
try:
doc, auditor = recover.readfile('your.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)
# The auditor.errors attribute stores severe errors,
# which may raise exceptions when rendering.
if not auditor.has_errors:
fig = plt.figure()
ax = fig.add_axes([0, 0, 1, 1])
ctx = RenderContext(doc)
out = MatplotlibBackend(ax)
Frontend(ctx, out).draw_layout(doc.modelspace(), finalize=True)
fig.savefig('your.png', dpi=300)
Simplified render workflow but with less control:
from ezdxf import recover
from ezdxf.addons.drawing import matplotlib
# Exception handling left out for compactness:
doc, auditor = recover.readfile('your.dxf')
if not auditor.has_errors:
matplotlib.qsave(doc.modelspace(), 'your.png')
- ezdxf.addons.drawing.matplotlib.qsave(layout: Layout, filename: str, *, bg: Color = None, fg: Color = None, dpi: int = 300, size_inches: Tuple[float, float] = None, backend: str = 'agg', config: Configuration = None, filter_func: FilterFunc = None) None ¶
Quick and simplified render export by matplotlib.
- Parameters
layout – modelspace or paperspace layout to export
filename – export filename, file extension determines the format e.g. “image.png” to save in PNG format.
bg – override default background color in hex format #RRGGBB or #RRGGBBAA, e.g. use bg=”#FFFFFF00” to get a transparent background and a black foreground color (ACI=7), because a white background #FFFFFF gets a black foreground color or vice versa bg=”#00000000” for a transparent (black) background and a white foreground color.
fg – override default foreground color in hex format #RRGGBB or #RRGGBBAA, requires also bg argument. There is no explicit foreground color in DXF defined (also not a background color), but the ACI color 7 has already a variable color value, black on a light background and white on a dark background, this argument overrides this (ACI=7) default color value.
dpi – image resolution (dots per inches).
size_inches – paper size in inch as (width, height) tuple, which also defines the size in pixels = (width * dpi) x (height * dpi). If width or height is 0.0 the value is calculated by the aspect ratio of the drawing.
backend – the matplotlib rendering backend to use (agg, cairo, svg etc) (see documentation for matplotlib.use() for a complete list of backends)
config – drawing parameters
filter_func – filter function which takes a DXFGraphic object as input and returns
True
if the entity should be drawn orFalse
if the entity should be ignored
New in version 0.14.
New in version 0.15: added argument params to pass parameters to the matplotlib backend
Changed in version 0.16: removed arguments ltype and lineweight_scaling
New in version 0.17: added argument filter_func to filter DXF entities
Changed in version 0.17: params argument replaced by config argument
Changed in version 0.18: added argument size_inches
MatplotlibBackend¶
PyQtBackend¶
Configuration¶
Additional options for the drawing add-on can be passed by the config
argument of the Frontend
constructor __init__()
. Not every
option will be supported by all backends.
- class ezdxf.addons.drawing.config.Configuration¶
Configuration options for the
drawing
add-on.- pdsize¶
the size to draw POINT entities (in drawing units) set to None to use the $PDSIZE value from the dxf document header
0
5% of draw area height
<0
Specifies a percentage of the viewport size
>0
Specifies an absolute size
None
use the $PDMODE value from the dxf document header
- Type
Optional[int]
- pdmode¶
point styling mode (see POINT documentation)
see
Point
class documentation- Type
Optional[int]
- measurement¶
whether to use metric or imperial units as enum
ezdxf.enums.Measurement
0
use imperial units (in, ft, yd, …)
1
use metric units (ISO meters)
None
use the $MEASUREMENT value from the dxf document header
- Type
Optional[ezdxf.enums.Measurement]
- show_defpoints¶
whether to show or filter out POINT entities on the defpoints layer
- Type
bool
- proxy_graphic_policy¶
the action to take when a proxy graphic is encountered
- line_policy¶
the method to use when drawing styled lines (eg dashed, dotted etc)
- hatch_policy¶
the method to use when drawing HATCH entities
- infinite_line_length¶
the length to use when drawing infinite lines
- Type
float
- lineweight_scaling¶
set to 0.0 for a constant minimal width the current result is correct, in SVG the line width is 0.7 points for 0.25mm as required, but it often looks too thick
- Type
float
- min_lineweight¶
the minimum line width in 1/300 inch, set to None for let the the backend choose.
- Type
Optional[float]
- min_dash_length¶
the minimum length for a dash when drawing a styled line (default value is arbitrary)
- Type
float
- max_flattening_distance¶
Max flattening distance in drawing units see Path.flattening documentation. The backend implementation should calculate an appropriate value, like 1 screen- or paper pixel on the output medium, but converted into drawing units. Sets Path() approximation accuracy
- Type
float
- circle_approximation_count¶
Approximate a full circle by n segments, arcs have proportional less segments. Only used for approximation of arcs in banded polylines.
- Type
int
- defaults()¶
Returns a frozen
Configuration
object with default values.
- with_changes()¶
Returns a new frozen
Configuration
object with modified values.Usage:
my_config = Configuration.defaults() my_config = my_config.with_changes(lineweight_scaling=2)
LinePolicy¶
- class ezdxf.addons.drawing.config.LinePolicy(value)¶
- SOLID¶
draw all lines as solid regardless of the linetype style
- APPROXIMATE¶
use the closest approximation available to the backend for rendering styled lines
- ACCURATE¶
analyse and render styled lines as accurately as possible. This approach is slower and is not well suited to interactive applications.
HatchPolicy¶
- class ezdxf.addons.drawing.config.HatchPolicy(value)¶
The action to take when a HATCH entity is encountered
- IGNORE¶
do not show HATCH entities at all
- SHOW_OUTLINE¶
show only the outline of HATCH entities
- SHOW_SOLID¶
show HATCH entities but draw with solid fill regardless of the pattern
- SHOW_APPROXIMATE_PATTERN¶
show HATCH entities using the closest approximation available to the current backend
ProxyGraphicPolicy¶
- class ezdxf.addons.drawing.config.ProxyGraphicPolicy(value)¶
The action to take when an entity with a proxy graphic is encountered
Note
To get proxy graphics support proxy graphics have to be loaded: Set the global option
ezdxf.options.load_proxy_graphics
toTrue
, which is the default value.This can not prevent drawing proxy graphic inside of blocks, because this is outside of the domain of the drawing add-on!
- IGNORE¶
do not display proxy graphics (skip_entity will be called instead)
- SHOW¶
if the entity cannot be rendered directly (eg if not implemented) but a proxy is present: display the proxy
- PREFER¶
display proxy graphics even for entities where direct rendering is available
Details¶
The rendering is performed in two stages. The front-end traverses the DXF document
structure, converting each encountered entity into primitive drawing commands.
These commands are fed to a back-end which implements the interface:
Backend
.
Currently a PyQtBackend
(QGraphicsScene based) and a
MatplotlibBackend
are implemented.
Although the resulting images will not be pixel-perfect with AutoCAD (which was taken as the ground truth when developing this add-on) great care has been taken to achieve similar behavior in some areas:
The algorithm for determining color should match AutoCAD. However, the color palette is not stored in the dxf file, so the chosen colors may be different to what is expected. The
RenderContext
class supports passing a plot style table (CTB-file) as custom color palette but uses the same palette as AutoCAD by default.Text rendering is quite accurate, text positioning, alignment and word wrapping are very faithful. Differences may occur if a different font from what was used by the CAD application but even in that case, for supported backends, measurements are taken of the font being used to match text as closely as possible.
Visibility determination (based on which layers are visible) should match AutoCAD
See examples/addons/drawing/cad_viewer.py
for an advanced use of the module.
See examples/addons/drawing/draw_cad.py
for a simple use of the module.
See drawing.md
in the ezdxf repository for additional behaviours documented
during the development of this add-on.
Limitations¶
Rich text formatting is ignored (drawn as plain text)
If the backend does not match the font then the exact text placement and wrapping may appear slightly different
MULTILEADER renders only proxy graphic if available
relative size of POINT entities cannot be replicated exactly
only basic support for:
infinite lines (rendered as lines with a finite length)
VIEWPORT and OLE2FRAME entities (rendered as rectangles)
3D entities are projected into the xy-plane and 3D text is not supported
vertical text (will render as horizontal text)
multiple columns of text (placement of additional columns may be incorrect)