Provided by: python3-ezdxf_0.14.2-3_all bug

NAME

       ezdxf - ezdxf Documentation [image]

       Welcome! This is the documentation for ezdxf release 0.14.2, last updated Nov 27, 2020.

       • ezdxf is a Python package to create new DXF files and read/modify/write existing DXF files

       • the intended audience are developers

       • requires at least Python 3.6

       • OS independent

       • additional required packages: pyparsing

       • MIT-License

       • read/write/new support for DXF versions: R12, R2000, R2004, R2007, R2010, R2013 and R2018

       • additional read support for DXF versions R13/R14 (upgraded to R2000)

       • additional read support for older DXF versions than R12 (upgraded to R12)

       • read/write support for ASCII DXF and Binary DXF

       • preserves third-party DXF content

INCLUDED EXTENSIONS

drawing  add-on to visualise and convert DXF files to images which can be saved to various formats such
         as png, pdf and svg

       • r12writer add-on to write basic DXF entities direct and fast into a DXF R12 file or stream

       • iterdxf add-on to iterate over entities of the modelspace of really big (> 5GB) DXF files which do  not
         fit into memory

       • importer add-on to import entities, blocks and table entries from another DXF document

       • dxf2code  add-on to generate Python code for DXF structures loaded from DXF documents as starting point
         for parametric DXF entity creation

       • acadctb add-on to read/write plot_style_files

       • pycsg add-on for Constructive Solid Geometry (CSG) modeling technique

WEBSITE

       https://ezdxf.mozman.at/

DOCUMENTATION

       Documentation of development version at https://ezdxf.mozman.at/docs

       Documentation of latest release at http://ezdxf.readthedocs.io/

       Source Code: http://github.com/mozman/ezdxf.git

       Issue Tracker at GitHub: http://github.com/mozman/ezdxf/issues

QUESTIONS AND FEEDBACK AT GOOGLE GROUPS

       Please post questions at the forum or stack overflow to make answers available to other users as well.

INTRODUCTION

   What is ezdxf
       ezdxf  is a Python interface to the DXF (drawing interchange  file)  format  developed  by  Autodesk,  it
       allows developers to read and modify existing DXF drawings or create new DXF drawings.

       The  main  objective  in the development of ezdxf was to hide complex DXF details from the programmer but
       still support most capabilities of the DXF format. Nevertheless, a basic understanding of the DXF  format
       is  required,  also  to  understand which tasks and goals are possible to accomplish by using the the DXF
       format.

       Not all DXF features are supported yet, but additional features will be added in the future gradually.

       ezdxf is also a replacement for my dxfwrite and my dxfgrabber packages but with different APIs, for  more
       information see also: faq001

   What ezdxf can’t doezdxf  is  not  a  DXF  converter:  ezdxf can not convert between different DXF versions, if you are
            looking for an appropriate application, try the free ODAFileConverter from the Open Design Alliance,
            which converts between different DXF version and also between the DXF and the DWG file format.

          • ezdxf is not a CAD file format converter: ezdxf can not convert DXF files to other CAD formats  such
            as DWG

          • ezdxf is not a CAD kernel and does not provide high level functionality for construction work, it is
            just  an interface to the DXF file format. If you are looking for a CAD kernel with Python scripting
            support, look at FreeCAD.

   Supported Python Versions
       ezdxf requires at least Python 3.6 and will be tested with the latest stable CPython 3  version  and  the
       latest stable release of pypy3 during development.

       ezdxf  is  written  in  pure  Python  and  requires only pyparser as additional library beside the Python
       Standard Library.  pytest is required to run the unit- and integration tests. Data to run the stress  and
       audit test can not be provided, because I don’t have the rights for publishing this DXF files.

   Supported Operating Systems
       ezdxf  is  OS  independent  and  runs  on  all  platforms which provide an appropriate Python interpreter
       (>=3.6).

   Supported DXF Versions
                                          ┌─────────┬──────────────────────┐
                                          │ Version │ AutoCAD Release      │
                                          ├─────────┼──────────────────────┤
                                          │ AC1009  │ AutoCAD R12          │
                                          ├─────────┼──────────────────────┤
                                          │ AC1012  │ AutoCAD R13 -> R2000 │
                                          ├─────────┼──────────────────────┤
                                          │ AC1014  │ AutoCAD R14 -> R2000 │
                                          ├─────────┼──────────────────────┤
                                          │ AC1015  │ AutoCAD R2000        │
                                          ├─────────┼──────────────────────┤
                                          │ AC1018  │ AutoCAD R2004        │
                                          ├─────────┼──────────────────────┤
                                          │ AC1021  │ AutoCAD R2007        │
                                          ├─────────┼──────────────────────┤
                                          │ AC1024  │ AutoCAD R2010        │
                                          ├─────────┼──────────────────────┤
                                          │ AC1027  │ AutoCAD R2013        │
                                          ├─────────┼──────────────────────┤
                                          │ AC1032  │ AutoCAD R2018        │
                                          └─────────┴──────────────────────┘

       ezdxf reads also older DXF versions but saves it as DXF R12.

   Embedded DXF Information of 3rd Party Applications
       The DXF format allows third-party applications to embed application-specific information.  ezdxf  manages
       DXF data in a structure-preserving form, but for the price of large memory requirement.  Because of this,
       processing of DXF information of third-party applications is possible and will retained on rewriting.

   License
       ezdxf is licensed under the very liberal MIT-License.

USAGE FOR BEGINNERS

       This  section shows the intended usage of the ezdxf package.  This is just a brief overview for new ezdxf
       users, follow the provided links for more detailed information.

       First import the package:

          import ezdxf

   Loading DXF Files
       ezdxf supports loading ASCII and binary DXF files from a file:

          doc = ezdxf.readfile(filename)

       or from a zip-file:

          doc = ezdxf.readzip(zipfilename[, filename])

       Which loads the DXF file filename from the zip-file zipfilename or the first DXF file in the zip-file  if
       filename is absent.

       It  is  also  possible  to read a DXF file from a stream by the ezdxf.read() function, but this is a more
       advanced feature, because this requires detection of the file encoding in advance.

       This works well with DXF files from trusted sources like AutoCAD or BricsCAD, for loading DXF files  with
       minor or major flaws look at the ezdxf.recover module.

       SEE ALSO:
          Documentation  for ezdxf.readfile(), ezdxf.readzip() and ezdxf.read(), for more information about file
          management go to the dwgmanagement section. For loading DXF files with structural errors look  at  the
          ezdxf.recover module.

   Saving DXF Files
       Save the DXF document with a new name:

          doc.saveas('new_name.dxf')

       or with the same name as loaded:

          doc.save()

       SEE ALSO:
          Documentation   for   ezdxf.document.Drawing.save()   and  ezdxf.document.Drawing.saveas(),  for  more
          information about file management go to the dwgmanagement section.

   Create a New DXF File
       Create new file for the latest supported DXF version:

          doc = ezdxf.new()

       Create a new DXF file for a specific DXF version, e.g for DXF R12:

          doc = ezdxf.new('R12')

       To setup some basic DXF resources use the setup argument:

          doc = ezdxf.new(setup=True)

       SEE ALSO:
          Documentation for ezdxf.new(), for more information about file  management  go  to  the  dwgmanagement
          section.

   Layouts and Blocks
       Layouts  are containers for DXF entities like LINE or CIRCLE. The most important layout is the modelspace
       labeled as “Model” in CAD applications which  represents  the  “world”  work  space.  Paperspace  layouts
       represents plottable sheets which contains often the framing and the tile block of a drawing and VIEWPORT
       entities as scaled and clipped “windows” into the modelspace.

       The  modelspace is always present and can not be deleted. The active paperspace is also always present in
       a new DXF document but can be deleted, in that  case  another  paperspace  layout  gets  the  new  active
       paperspace, but you can not delete the last paperspace layout.

       Getting the modelspace of a DXF document:

          msp = doc.modelspace()

       Getting a paperspace layout by the name as shown in the tab of a CAD application:

          psp = doc.layout('Layout1')

       A block is just another kind of entity space, which can be inserted multiple times into other layouts and
       blocks  by  the INSERT entity also called block references, this is a very powerful and important concept
       of the DXF format.

       Getting a block layout by the block name:

          blk = doc.blocks.get('NAME')

       All these layouts have factory functions to create graphical DXF entities for  their  entity  space,  for
       more information about creating entities see section: Create new DXF Entities

   Create New Blocks
       The block definitions of a DXF document are managed by the BlocksSection object:

          my_block = doc.blocks.new('MyBlock')

       SEE ALSO:
          tut_blocks

   Query DXF Entities
       As  said  in  the Layouts and Blocks section, all graphical DXF entities are stored in layouts, all these
       layouts can be iterated and support the index operator e.g. layout[-1] returns the last entity.

       The main difference between iteration and index access is, that iteration filters destroyed entities, but
       the the index operator returns also destroyed entities until these entities are purged by  layout.purge()
       more about this topic in section: Delete Entities.

       There are two advanced query methods: query() and groupby().

       Get all lines of layer 'MyLayer':

          lines = msp.query('LINE[layer=="MyLayer"]')

       This returns an EntityQuery container, which also provides the same query() and groupby() methods.

       Get all lines categorized by a DXF attribute like color:

          all_lines_by_color = msp.query('LINE').groupby('color')
          lines_with_color_1 = all_lines_by_color.get(1, [])

       The  groupby()  method  returns  a  regular  Python  dict with colors as key and a regular Python list of
       entities as values (not an EntityQuery container).

       SEE ALSO:
          For more information go to the tut_getting_data

   Examine DXF Entities
       Each DXF entity has a dxf namespace attribute, which stores the named DXF attributes, some DXF attributes
       are only indirect available like the vertices in the LWPOLYLINE entity. More information  about  the  DXF
       attributes of each entity can found in the documentation of the ezdxf.entities module.

       Get some basic DXF attributes:

          layer = entity.dxf.layer  # default is '0'
          color = entity.dxf.color  # default is 256 = BYLAYER

       Most DXF attributes have a default value, which will be returned if the DXF attribute is not present, for
       DXF attributes without a default value you can check in the attribute really exist:

          entity.dxf.hasattr('true_color')

       or use the get() method and a default value:

          entity.dxf.get('true_color', 0)

       SEE ALSO:
          Common graphical DXF attributes

   Create New DXF Entities
       The  factory  functions for creating new graphical DXF entities are located in the BaseLayout class. This
       means this factory function are available for all entity containers:

          • ModelspacePaperspaceBlockLayout

       The usage is simple:

          msp = doc.modelspace()
          msp.add_line((0, 0), (1, 0), dxfattribs={'layer': 'MyLayer'})

       A few important or required DXF attributes are explicit method arguments, most  additional  and  optional
       DXF  attributes  are gives as a regular Python dict object.  The supported DXF attributes can be found in
       the documentation of the ezdxf.entities module.

       WARNING:
          Do not instantiate DXF entities by yourself and add them to layouts, always use the  provided  factory
          function to create new graphical entities, this is the intended way to use ezdxf.

   Create Block References
       A  block  reference  is just another DXF entity called INSERT, but the term “Block Reference” is a better
       choice and so the Insert entity is created by the factory function: add_blockref():

          msp.add_blockref('MyBlock')

       SEE ALSO:
          See tut_blocks for more advanced features like using Attrib entities.

   Create New Layers
       A layer is not an entity container, a layer is just another DXF attribute stored in the entity  and  this
       entity  can  inherit some properties from this Layer object.  Layer objects are stored in the layer table
       which is available as attribute doc.layers.

       You can create your own layers:

          my_layer = doc.layer.new('MyLayer')

       The layer object also controls the visibility of entities which references this layer, the  on/off  state
       of the layer is unfortunately stored as positive or negative color value which make the raw DXF attribute
       of layers useless, to change the color of a layer use the property Layer.color

          my_layer.color = 1

       To  change  the state of a layer use the provided methods of the Layer object, like on(), off(), freeze()
       or thaw():

          my_layer.off()

       SEE ALSO:
          layer_concept

   Delete Entities
       The safest way to delete entities is to delete the entity from the layout containing that entity:

          line = msp.add_line((0, 0), (1, 0))
          msp.delete_entity(line)

       This removes the entity immediately from the layout and  destroys  the  entity.   The  property  is_alive
       returns  False for a destroyed entity and all Python attributes are deleted, so line.dxf.color will raise
       an AttributeError exception, because line does not have a dxf attribute anymore.

       The current version of ezdxf also supports also destruction  of  entities  by  calling  method  destroy()
       manually:

          line.destroy()

       Manually  destroyed  entities  are  not  removed  immediately from entities containers like Modelspace or
       EntityQuery, but iterating such a container will filter destroyed entities automatically, so a for  e  in
       msp:  ...  loop  will  never  yield  destroyed entities. The index operator and the len() function do not
       filter deleted entities, to avoid getting deleted entities call  the  purge()  method  of  the  container
       manually  to remove deleted entities.

   Further Information
       • reference documentation

       • Documentation of package internals: Developer Guides.

BASIC CONCEPTS

       The  Basic  Concepts section teach the intended meaning of DXF attributes and structures without teaching
       the application of this information or the specific implementation by ezdxf, if you are looking for  more
       information  about  the  ezdxf internals look at the Reference section or if you want to learn how to use
       ezdxf go to the Tutorials section and for the solution of specific problems go to the Howto section.

   AutoCAD Color Index (ACI)
       The color attribute represents an ACI (AutoCAD Color Index).  AutoCAD  and  many  other  CAD  application
       provides a default color table, but pen table would be the more correct term.  Each ACI entry defines the
       color  value, the line weight and some other attributes to use for the pen.  This pen table can be edited
       by the user or loaded from an CTB or STB file.  ezdxf provides functions  to  create  (new())  or  modify
       (ezdxf.acadctb.load()) plot styles files.

       DXF  R12  and prior are not good in preserving the layout of a drawing, because of the lack of a standard
       color table defined by the DXF reference and missing DXF structures to define these color tables  in  the
       DXF  file. So if a CAD user redefined an ACI and do not provide a CTB or STB file, you have no ability to
       determine which color or lineweight was  used.  This  is  better  in  later  DXF  versions  by  providing
       additional DXF attributes like lineweight and  true_color.

       SEE ALSO:
          plot_style_files

   Layer Concept
       Every  object has a layer as one of its properties. You may be familiar with layers - independent drawing
       spaces that stack on top of each other to create an overall image - from using drawing programs. Most CAD
       programs use layers as the primary organizing principle for all the objects that you draw. You use layers
       to organize objects into logical groups of things that belong together; for  example,  walls,  furniture,
       and text notes usually belong on three separate layers, for a couple of reasons:

       • Layers give you a way to turn groups of objects on and off - both on the screen and on the plot.

       • Layers provide the most efficient way of controlling object color and linetype

       Create  a  layer table entry Layer by Drawing.layers.new(), assign the layer properties such as color and
       linetype. Then assign those layers to other DXF entities by setting the DXF attribute layer to the  layer
       name as string.

       It  is possible to use layers without a layer definition but not recommend, just use a layer name without
       a layer definition, the layer has the default linetype 'Continuous' and the default color is 7.

       The advantage of assigning a linetype and a color to a layer is that entities on this layer  can  inherit
       this  properties  by  using 'BYLAYER' as linetype string and 256 as color, both values are default values
       for new entities.

       SEE ALSO:
          tut_layers

   Linetypes
       The linetype defines the pattern of a line. The linetype of  an  entity  can  be  specified  by  the  DXF
       attribute  linetype,  this can be an explicit named linetype or the entity can inherit its line type from
       the assigned layer by setting linetype to 'BYLAYER', which is also the default value. CONTINUOUS  is  the
       default line type for layers with unspecified line type.

       ezdxf  creates  several  standard  linetypes, if the argument setup is True at calling new(), this simple
       line types are supported by all DXF versions:

          doc = ezdxf.new('R2007', setup=True)
       [image]

       In DXF R13 Autodesk introduced complex linetypes, containing TEXT or SHAPES in  linetypes.  ezdxf  v0.8.4
       and later supports complex linetypes.

       SEE ALSO:
          tut_linetypes

   Linetype Scaling
       Global  linetype  scaling can be changed by setting the header variable doc.header['$LTSCALE'] = 2, which
       stretches the line pattern by factor 2.

       To change the linetype scaling for single entities set scaling factor by DXF attribute ltscale, which  is
       supported since DXF version R2000.

   Coordinate Systems
       AutoLISP Reference to Coordinate Systems provided by Autodesk.

       To brush up you knowledge about vectors, watch the YouTube tutorials of 3Blue1Brown about Linear Algebra.

   WCS
       World  coordinate  system  -  the  reference  coordinate system. All other coordinate systems are defined
       relative to the WCS, which never changes. Values measured relative to the WCS are stable  across  changes
       to other coordinate systems.

   UCS
       User  coordinate system - the working coordinate system defined by the user to make drawing tasks easier.
       All points passed to AutoCAD commands, including those  returned  from  AutoLISP  routines  and  external
       functions,  are  points  in  the  current  UCS. As far as I know, all coordinates stored in DXF files are
       always WCS or OCS never UCS.

       User defined coordinate systems are not just helpful for interactive  CAD,  therefore  ezdxf  provides  a
       converter class UCS to translate coordinates from UCS into WCS and vice versa, but always remember: store
       only WCS or OCS coordinates in DXF files, because there is no method to determine which UCS was active or
       used to create UCS coordinates.

       SEE ALSO:

          • Table entry UCSezdxf.math.UCS - converter between WCS and UCS

   OCS
       Object  coordinate system - coordinates relative to the object itself. These points are usually converted
       into the WCS, current UCS, or current DCS, according to the  intended  use  of  the  object.  Conversely,
       points  must be translated into an OCS before they are written to the database. This is also known as the
       entity coordinate system.

       Because ezdxf is just an interface to DXF, it does not automatically convert OCS into WCS,  this  is  the
       domain  of  the  user/application.  And  further more, the main goal of OCS is to place 2D elements in 3D
       space, this maybe was useful in the early years of CAD, I think  nowadays  this  is  an  not  often  used
       feature, but I am not an AutoCAD user.

       OCS differ from WCS only if extrusion != (0, 0, 1), convert OCS into WCS:

          # circle is an DXF entity with extrusion != (0, 0, 1)
          ocs = circle.ocs()
          wcs_center = ocs.to_wcs(circle.dxf.center)

       SEE ALSO:

          • Object Coordinate System - deeper insights into OCS

          • ezdxf.math.OCS - converter between WCS and OCS

   DCS
       Display  coordinate  system  -  the  coordinate system into which objects are transformed before they are
       displayed. The origin of the DCS is the point stored in the  AutoCAD  system  variable  TARGET,  and  its
       z-axis  is  the  viewing  direction.   In other words, a viewport is always a plan view of its DCS. These
       coordinates can be used to determine where something will be displayed to the AutoCAD user.

   Object Coordinate System (OCS)DXF Reference for OCS provided by Autodesk.

       The points associated with each entity are expressed in terms  of  the  entity’s  own  object  coordinate
       system (OCS).  The OCS was referred to as ECS in previous releases of AutoCAD.

       With  OCS, the only additional information needed to describe the entity’s position in 3D space is the 3D
       vector describing the z-axis of the OCS, and the elevation value.

       For a given z-axis (or extrusion) direction, there are an infinite number of coordinate systems,  defined
       by  translating  the origin in 3D space and by rotating the x- and y-axis around the z-axis. However, for
       the same z-axis direction, there is only one OCS. It has the following properties:

       • Its origin coincides with the WCS origin.

       • The orientation of the x- and y-axis within the xy-plane are calculated in an arbitrary but  consistent
         manner.  AutoCAD performs this calculation using the arbitrary axis algorithm.

       These  entities do not lie in a particular plane. All points are expressed in world coordinates. Of these
       entities, only lines and points can be extruded. Their extrusion direction  can  differ  from  the  world
       z-axis.

       • LinePoint3DFacePolyline (3D)

       • Vertex (3D)

       • PolymeshPolyfaceViewport

       These  entities  are  planar  in  nature.  All  points  are expressed in object coordinates. All of these
       entities can be extruded. Their extrusion direction can differ from the world z-axis.

       • CircleArcSolidTraceTextAttribAttdefShapeInsertPolyline (2D)

       • Vertex (2D)

       • LWPolylineHatchImage

       Some of a Dimension’s points are expressed in WCS and some in OCS.

   Elevation
       Elevation group code 38:

       Exists only in output from versions prior to R11. Otherwise, Z coordinates are supplied as part  of  each
       of the entity’s defining points.

   Arbitrary Axis AlgorithmDXF Reference for Arbitrary Axis Algorithm provided by Autodesk.

       The  arbitrary  axis  algorithm  is  used by AutoCAD internally to implement the arbitrary but consistent
       generation of object coordinate systems for all entities that use object coordinates.

       Given a unit-length vector to be used as the z-axis of a coordinate system, the arbitrary axis  algorithm
       generates  a  corresponding  x-axis  for  the coordinate system. The y-axis follows by application of the
       right-hand rule.

       We are looking for the arbitrary x- and y-axis to go with the normal Az  (the  arbitrary  z-axis).   They
       will be called Ax and Ay (using Vector):

          Az = Vector(entity.dxf.extrusion).normalize()  # normal (extrusion) vector
          # Extrusion vector normalization should not be necessary, but don't rely on any DXF content
          if (abs(Az.x) < 1/64.) and (abs(Az.y) < 1/64.):
               Ax = Vector(0, 1, 0).cross(Az).normalize()  # the cross-product operator
          else:
               Ax = Vector(0, 0, 1).cross(Az).normalize()  # the cross-product operator
          Ay = Az.cross(Ax).normalize()

   WCS to OCS
          def wcs_to_ocs(point):
              px, py, pz = Vector(point)  # point in WCS
              x = px * Ax.x + py * Ax.y + pz * Ax.z
              y = px * Ay.x + py * Ay.y + pz * Ay.z
              z = px * Az.x + py * Az.y + pz * Az.z
              return Vector(x, y, z)

   OCS to WCS
          Wx = wcs_to_ocs((1, 0, 0))
          Wy = wcs_to_ocs((0, 1, 0))
          Wz = wcs_to_ocs((0, 0, 1))

          def ocs_to_wcs(point):
              px, py, pz = Vector(point)  # point in OCS
              x = px * Wx.x + py * Wx.y + pz * Wx.z
              y = px * Wy.x + py * Wy.y + pz * Wy.z
              z = px * Wz.x + py * Wz.y + pz * Wz.z
              return Vector(x, y, z)

TUTORIALS

   Tutorial for getting data from DXF files
       In this tutorial I show you how to get data from an existing DXF drawing.

       Loading the DXF file:

          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)

       This  works well with DXF files from trusted sources like AutoCAD or BricsCAD, for loading DXF files with
       minor or major flaws look at the ezdxf.recover module.

       SEE ALSO:
          dwgmanagement

   Layouts
       I use the term layout as synonym for an arbitrary entity space which can contain DXF entities like  LINE,
       CIRCLE, TEXT and so on. Every DXF entity can only reside in exact one layout.

       There are three different layout types:

       • Modelspace: this is the common construction space

       • Paperspace: used to to create print layouts

       • BlockLayout: reusable elements, every block has its own entity space

       A  DXF  drawing  consist  of  exact  one modelspace and at least of one paperspace.  DXF R12 has only one
       unnamed paperspace the later DXF versions support more than one paperspace  and  each  paperspace  has  a
       name.

   Iterate over DXF entities of a layout
       Iterate  over all DXF entities in modelspace. Although this is a possible way to retrieve DXF entities, I
       would like to point out that entity queries are the better way.

          # iterate over all entities in modelspace
          msp = doc.modelspace()
          for e in msp:
              if e.dxftype() == 'LINE':
                  print_entity(e)

          # entity query for all LINE entities in modelspace
          for e in msp.query('LINE'):
              print_entity(e)

          def print_entity(e):
              print("LINE on layer: %s\n" % e.dxf.layer)
              print("start point: %s\n" % e.dxf.start)
              print("end point: %s\n" % e.dxf.end)

       All layout objects supports the standard Python iterator protocol and the in operator.

   Access DXF attributes of an entity
       Check the type of an DXF entity by e.dxftype(). The DXF type is always uppercase. All DXF  attributes  of
       an entity are grouped in the namespace attribute dxf:

          e.dxf.layer  # layer of the entity as string
          e.dxf.color  # color of the entity as integer

       See Common graphical DXF attributes

       If  a  DXF  attribute is not set (a valid DXF attribute has no value), a DXFValueError will be raised. To
       avoid this use the get_dxf_attrib() method with a default value:

          # If DXF attribute 'paperspace' does not exist, the entity defaults
          # to modelspace:
          p = e.get_dxf_attrib('paperspace', 0)

       An unsupported DXF attribute raises an DXFAttributeError.

   Getting a paperspace layout
          paperspace = doc.layout('layout0')

       Retrieves the paperspace named layout0, the usage of the Layout object is the same as of  the  modelspace
       object.   DXF  R12  provides  only  one  paperspace,  therefore  the  paperspace  name in the method call
       doc.layout('layout0') is ignored or can be left off.  For the later DXF versions you get a  list  of  the
       names of the available layouts by layout_names().

   Retrieve entities by query language
       ezdxf  provides  a  flexible  query language for DXF entities.  All layout types have a query() method to
       start an entity query or use the ezdxf.query.new() function.

       The query string is the combination of two queries, first  the  required  entity  query  and  second  the
       optional attribute query, enclosed in square brackets: 'EntityQuery[AttributeQuery]'

       The  entity query is a whitespace separated list of DXF entity names or the special name *. Where * means
       all DXF entities, all other DXF names have to be uppercase. The * search  can  exclude  entity  types  by
       adding the entity name with a presceding ! (e.g. * !LINE, search all entities except lines).

       The  attribute  query  is  used  to  select DXF entities by its DXF attributes. The attribute query is an
       addition to the entity query and matches only if the entity already match the entity query. The attribute
       query is a boolean expression, supported operators: and, or, !.

       SEE ALSO:
          entity query string

       Get all LINE entities from the modelspace:

          msp = doc.modelspace()
          lines = msp.query('LINE')

       The result container EntityQuery also provides the  query()  method,  get  all  LINE  entities  at  layer
       construction:

          construction_lines = lines.query('*[layer=="construction"]')

       The  *  is  a wildcard for all DXF types, in this case you could also use LINE instead of *, * works here
       because lines just contains entities of DXF type LINE.

       All together as one query:

          lines = msp.query('LINE[layer=="construction"]')

       The ENTITIES section also supports the query() method:

          lines_and_circles = doc.entities.query('LINE CIRCLE[layer=="construction"]')

       Get all modelspace entities at layer construction, but excluding entities with linetype DASHED:

          not_dashed_entities = msp.query('*[layer=="construction" and linetype!="DASHED"]')

   Retrieve entities by groupby() function
       Search and group entities by a user defined criteria. As example let’s group all entities from modelspace
       by layer, the result will be a dict with layer names  as  dict-key  and  a  list  of  all  entities  from
       modelspace matching this layer as dict-value. Usage as dedicated function call:

          from ezdxf.groupby import groupby
          group = groupby(entities=msp, dxfattrib='layer')

       The  entities  argument  can  be  any container or generator which yields DXFEntity or inherited objects.
       Shorter and simpler to use as method of BaseLayout (modelspace, paperspace  layouts,  blocks)  and  query
       results as EntityQuery objects:

          group = msp.groupby(dxfattrib='layer')

          for layer, entities in group.items():
              print(f'Layer "{layer}" contains following entities:')
              for entity in entities:
                  print('    {}'.format(str(entity)))
              print('-'*40)

       The  previous  example  shows how to group entities by a single DXF attribute, but it is also possible to
       group entities by a custom key, to do so create a custom key function, which  accepts  a  DXF  entity  as
       argument  and  returns a hashable value as dict-key or None to exclude the entity.  The following example
       shows how to group entities by layer and color, so each result entry has a tuple (layer,  color)  as  key
       and a list of entities with matching DXF attributes:

          def layer_and_color_key(entity):
              # return None to exclude entities from result container
              if entity.dxf.layer == '0':  # exclude entities from default layer '0'
                  return None
              else:
                  return entity.dxf.layer, entity.dxf.color

          group = msp.groupby(key=layer_and_color_key)
          for key, entities in group.items():
              print(f'Grouping criteria "{key}" matches following entities:')
              for entity in entities:
                  print('    {}'.format(str(entity)))
              print('-'*40)

       To exclude entities from the result container the key function should return None. The groupby() function
       catches DXFAttributeError exceptions while processing entities and excludes this entities from the result
       container.  So there is no need to worry about DXF entities which do not support certain attributes, they
       will be excluded automatically.

       SEE ALSO:
          groupby() documentation

   Tutorial for creating simple DXF drawings
       r12writer - create simple DXF R12 drawings with a restricted  entities  set:  LINE,  CIRCLE,  ARC,  TEXT,
       POINT,  SOLID, 3DFACE and POLYLINE. Advantage of the r12writer is the speed and the low memory footprint,
       all entities are written direct to the file/stream without building a drawing data structure in memory.

       SEE ALSO:
          r12writer

       Create a new DXF drawing with ezdxf.new() to use all available DXF entities:

          import ezdxf

          doc = ezdxf.new('R2010')  # create a new DXF R2010 drawing, official DXF version name: 'AC1024'

          msp = doc.modelspace()  # add new entities to the modelspace
          msp.add_line((0, 0), (10, 0))  # add a LINE entity
          doc.saveas('line.dxf')

       New entities are always added to layouts, a layout can be the modelspace, a paperspace layout or a  block
       layout.

       SEE ALSO:
          Look at factory methods of the BaseLayout class to see all the available DXF entities.

   Tutorial for Layers
       If you are not familiar with the concept of layers, please read this first: layer_concept

   Create a Layer Definition
          import ezdxf

          doc = ezdxf.new(setup=True)  # setup required line types
          msp = doc.modelspace()
          doc.layers.new(name='MyLines', dxfattribs={'linetype': 'DASHED', 'color': 7})

       The  advantage  of assigning a linetype and a color to a layer is that entities on this layer can inherit
       this properties by using 'BYLAYER' as linetype string and 256 as color, both values  are  default  values
       for new entities so you can left off this assignments:

          msp.add_line((0, 0), (10, 0), dxfattribs={'layer': 'MyLines'})

       The new created line will be drawn with color 7 and linetype 'DASHED'.

   Changing Layer State
       Get the layer definition object:

          my_lines = doc.layers.get('MyLines')

       Check the state of the layer:

          my_lines.is_off()  # True if layer is off
          my_lines.is_on()   # True if layer is on
          my_lines.is_locked()  # True if layer is locked
          layer_name = my_lines.dxf.name  # get the layer name

       Change the state of the layer:

          # switch layer off, entities at this layer will not shown in CAD applications/viewers
          my_lines.off()

          # lock layer, entities at this layer are not editable in CAD applications
          my_lines.lock()

       Get/set  default  color  of a layer by property Layer.color, because the DXF attribute Layer.dxf.color is
       misused for switching the layer on and off, layer is off if the color value is negative.

       Changing the default layer values:

          my_lines.dxf.linetype = 'DOTTED'
          my_lines.color = 13  # preserves on/off state of layer

       SEE ALSO:
          For all methods and attributes see class Layer.

   Check Available Layers
       The layers object supports some standard Python protocols:

          # iteration
          for layer in doc.layers:
              if layer.dxf.name != '0':
                  layer.off()  # switch all layers off except layer '0'

          # check for existing layer definition
          if 'MyLines' in doc.layers:
              layer = doc.layers.get('MyLines')

          layer_count = len(doc.layers) # total count of layer definitions

   Deleting a Layer
       Delete a layer definition:

          doc.layers.remove('MyLines')

       This just deletes the layer definition, all DXF entities with the DXF attribute layer  set  to  'MyLines'
       are  still  there, but if they inherit color and/or linetype from the layer definition they will be drawn
       now with linetype 'Continuous' and color 1.

   Tutorial for Blocks
   What are Blocks?
       Blocks are collections of DXF entities which  can  be  placed  multiply  times  as  block  references  in
       different  layouts  and  other  block  definitions.  The block reference (Insert) can be rotated, scaled,
       placed in 3D by OCS and arranged in a grid like manner, each Insert entity can have individual attributes
       (Attrib) attached.

   Create a Block
       Blocks are managed as BlockLayout by a BlocksSection object, every drawing has only  one  blocks  section
       stored in the attribute: Drawing.blocks.

          import ezdxf
          import random  # needed for random placing points

          def get_random_point():
              """Returns random x, y coordinates."""
              x = random.randint(-100, 100)
              y = random.randint(-100, 100)
              return x, y

          # Create a new drawing in the DXF format of AutoCAD 2010
          doc = ezdxf.new('R2010')

          # Create a block with the name 'FLAG'
          flag = doc.blocks.new(name='FLAG')

          # Add DXF entities to the block 'FLAG'.
          # The default base point (= insertion point) of the block is (0, 0).
          flag.add_lwpolyline([(0, 0), (0, 5), (4, 3), (0, 3)])  # the flag symbol as 2D polyline
          flag.add_circle((0, 0), .4, dxfattribs={'color': 2})  # mark the base point with a circle

   Block References (Insert)
       A  block  reference is a DXF Insert entity and can be placed in any layout: Modelspace, any Paperspace or
       BlockLayout (which enables nested block references). Every block reference  can  be  scaled  and  rotated
       individually.

       Lets insert some random flags into the modelspace:

          # Get the modelspace of the drawing.
          msp = doc.modelspace()

          # Get 50 random placing points.
          placing_points = [get_random_point() for _ in range(50)]

          for point in placing_points:
              # Every flag has a different scaling and a rotation of -15 deg.
              random_scale = 0.5 + random.random() * 2.0
              # Add a block reference to the block named 'FLAG' at the coordinates 'point'.
              msp.add_blockref('FLAG', point, dxfattribs={
                  'xscale': random_scale,
                  'yscale': random_scale,
                  'rotation': -15
              })

          # Save the drawing.
          doc.saveas("blockref_tutorial.dxf")

       Query all block references of block FLAG:

          for flag_ref in msp.query('INSERT[name=="FLAG"]'):
              print(str(flag_ref))

   What are Attributes?
       An  attribute  (Attrib)  is  a  text  annotation  attached  to  a block reference with an associated tag.
       Attributes are often used to add information to blocks  which  can  be  evaluated  and  exported  by  CAD
       programs.   An  attribute  can  be  visible or hidden. The simple way to use attributes is just to add an
       attribute to a block reference by Insert.add_attrib(), but the attribute is geometrically not related  to
       the  block reference, so you have to calculate the insertion point, rotation and scaling of the attribute
       by yourself.

   Using Attribute Definitions
       The second way to use attributes in block references is a two step process, first step is  to  create  an
       attribute definition (template) in the block definition, the second step is adding the block reference by
       Layout.add_blockref() and attach and fill attribute automatically by the add_auto_attribs() method to the
       block  reference.   The  advantage of this method is that all attributes are placed relative to the block
       base point with the same rotation and scaling as the block, but has the  disadvantage  that  non  uniform
       scaling  is  not  handled  very  well.  The method Layout.add_auto_blockref() handles non uniform scaling
       better by wrapping the block reference and its attributes  into  an  anonymous  block  and  let  the  CAD
       application  do  the  transformation work which will create correct graphical representations at least by
       AutoCAD and BricsCAD. This method  has  the  disadvantage  of  a  more  complex  evaluation  of  attached
       attributes

       Using attribute definitions (Attdef):

          # Define some attributes for the block 'FLAG', placed relative
          # to the base point, (0, 0) in this case.
          flag.add_attdef('NAME', (0.5, -0.5), dxfattribs={'height': 0.5, 'color': 3})
          flag.add_attdef('XPOS', (0.5, -1.0), dxfattribs={'height': 0.25, 'color': 4})
          flag.add_attdef('YPOS', (0.5, -1.5), dxfattribs={'height': 0.25, 'color': 4})

          # Get another 50 random placing points.
          placing_points = [get_random_point() for _ in range(50)]

          for number, point in enumerate(placing_points):
              # values is a dict with the attribute tag as item-key and
              # the attribute text content as item-value.
              values = {
                  'NAME': "P(%d)" % (number + 1),
                  'XPOS': "x = %.3f" % point[0],
                  'YPOS': "y = %.3f" % point[1]
              }

              # Every flag has a different scaling and a rotation of +15 deg.
              random_scale = 0.5 + random.random() * 2.0
              blockref = msp.add_blockref('FLAG', point, dxfattribs={
                  'rotation': 15
              }).set_scale(random_scale)
              blockref.add_auto_attribs(values)

          # Save the drawing.
          doc.saveas("auto_blockref_tutorial.dxf")

   Get/Set Attributes of Existing Block References
       See the howto: howto_get_attribs

   Evaluate Wrapped Block References
       As mentioned above evaluation of block references wrapped into anonymous blocks is complex:

          # Collect all anonymous block references starting with '*U'
          anonymous_block_refs = modelspace.query('INSERT[name ? "^\*U.+"]')

          # Collect real references to 'FLAG'
          flag_refs = []
          for block_ref in anonymous_block_refs:
              # Get the block layout of the anonymous block
              block = doc.blocks.get(block_ref.dxf.name)
              # Find all block references to 'FLAG' in the anonymous block
              flag_refs.extend(block.query('INSERT[name=="FLAG"]'))

          # Evaluation example: collect all flag names.
          flag_numbers = [flag.get_attrib_text('NAME') for flag in flag_refs if flag.has_attrib('NAME')]

          print(flag_numbers)

   Exploding Block References
       New in version 0.12.

       This  is an advanced and still experimental feature and because ezdxf is still not a CAD application, the
       results may no be perfect. Non uniform scaling lead to incorrect results for text entities (TEXT,  MTEXT,
       ATTRIB) and some other entities like HATCH with arc or ellipse path segments.

       By default the “exploded” entities are added to the same layout as the block reference is located.

          for flag_ref in msp.query('INSERT[name=="FLAG"]'):
              flag_ref.explode()

   Examine Entities of Block References
       New in version 0.12.

       If  you  just  want to examine the entities of a block reference use the virtual_entities() method.  This
       methods yields “virtual” entities with attributes identical to  “exploded”  entities  but  they  are  not
       stored in the entity database, have no handle and are not assigned to any layout.

          for flag_ref in msp.query('INSERT[name=="FLAG"]'):
              for entity in flag_ref.virtual_entities():
                  if entity.dxftype() == 'LWPOLYLINE':
                      print(f'Found {str(entity)}.')

   Tutorial for LWPolyline
       The  LWPolyline  is defined as a single graphic entity, which differs from the old-style Polyline entity,
       which is defined as a group of sub-entities.  LWPolyline display faster (in  AutoCAD)  and  consume  less
       disk   space,   it   is   a   planar   element,   therefore   all   points   in  OCS  as  (x,  y)  tuples
       (LWPolyline.dxf.elevation is the z-axis value).

       Create a simple polyline:

          import ezdxf

          doc = ezdxf.new('R2000')
          msp = doc.modelspace()

          points = [(0, 0), (3, 0), (6, 3), (6, 6)]
          msp.add_lwpolyline(points)

          doc.saveas("lwpolyline1.dxf")

       Append multiple points to a polyline:

          doc = ezdxf.readfile("lwpolyline1.dxf")
          msp = doc.modelspace()

          line = msp.query('LWPOLYLINE')[0]  # take first LWPolyline
          line.append_points([(8, 7), (10, 7)])

          doc.saveas("lwpolyline2.dxf")

       Getting points always returns a 5-tuple (x, y, start_width, ent_width, bulge), start_width, end_width and
       bulge is 0 if not present:

          first_point = line[0]
          x, y, start_width, end_width, bulge = first_point

       Use context manager to edit polyline points, this method was introduced because accessing  single  points
       was  very  slow,  but  since  ezdxf v0.8.9, direct access by index operator [] is very fast and using the
       context manager is not required anymore. Advantage of the context manager is the ability to  use  a  user
       defined point format:

          doc = ezdxf.readfile("lwpolyline2.dxf")
          msp = doc.modelspace()

          line = msp.query('LWPOLYLINE').first # take first LWPolyline, 'first' was introduced with v0.10

          with line.points('xyseb') as points:
              # points is a standard python list
              # existing points are 5-tuples, but new points can be
              # set as (x, y, [start_width, [end_width, [bulge]]]) tuple
              # set start_width, end_width to 0 to be ignored (x, y, 0, 0, bulge).

              del points[-2:]  # delete last 2 points
              points.extend([(4, 7), (0, 7)])  # adding 2 other points
              # the same as one command
              # points[-2:] = [(4, 7), (0, 7)]

          doc.saveas("lwpolyline3.dxf")

       Each line segment can have a different start- and end-width, if omitted start- and end-width is 0:

          doc = ezdxf.new('R2000')
          msp = doc.modelspace()

          # point format = (x, y, [start_width, [end_width, [bulge]]])
          # set start_width, end_width to 0 to be ignored (x, y, 0, 0, bulge).

          points = [(0, 0, .1, .15), (3, 0, .2, .25), (6, 3, .3, .35), (6, 6)]
          msp.add_lwpolyline(points)

          doc.saveas("lwpolyline4.dxf")

       The  first  point  carries  the start- and end-width of the first segment, the second point of the second
       segment and so on, the start- and end-width value of the last point is used for the  closing  segment  if
       polyline  is  closed  else  the  values are ignored. Start- and end-width only works if the DXF attribute
       dxf.const_width is unset, to be sure delete it:

          del line.dxf.const_width # no exception will be raised if const_width is already unset

       LWPolyline can also have curved elements, they are defined by the bulge value:

          doc = ezdxf.new('R2000')
          msp = doc.modelspace()

          # point format = (x, y, [start_width, [end_width, [bulge]]])
          # set start_width, end_width to 0 to be ignored (x, y, 0, 0, bulge).

          points = [(0, 0, 0, .05), (3, 0, .1, .2, -.5), (6, 0, .1, .05), (9, 0)]
          msp.add_lwpolyline(points)

          doc.saveas("lwpolyline5.dxf")
       [image]

       The curved segment is drawn from the point which defines the bulge value  to  the  following  point,  the
       curved  segment is always aa arc, The bulge value defines the ratio of the arc sagitta (segment height h)
       to half line segment length (point distance), a bulge value of 1 defines a  semicircle.  bulge  >  0  the
       curve is on the right side of the vertex connection line, bulge < 0 the curve is on the left side.

       ezdxf v0.8.9 supports a user defined points format, default is xyseb:

          • x = x coordinate

          • y = y coordinate

          • s = start width

          • e = end width

          • b = bulge value

          • v = (x, y) as tuple

          msp.add_lwpolyline([(0, 0, 0), (10, 0, 1), (20, 0, 0)], format='xyb')
          msp.add_lwpolyline([(0, 10, 0), (10, 10, .5), (20, 10, 0)], format='xyb')
       [image]

   Tutorial for Text
       Add a simple one line text entity by factory function add_text().

          import ezdxf

          # TEXT is a basic entity and is supported by every DXF version.
          # Argument setup=True for adding standard linetypes and text styles.
          doc = ezdxf.new('R12', setup=True)
          msp = doc.modelspace()

          # use set_pos() for proper TEXT alignment:
          # The relations between DXF attributes 'halign', 'valign',
          # 'insert' and 'align_point' are tricky.
          msp.add_text("A Simple Text").set_pos((2, 3), align='MIDDLE_RIGHT')

          # Using a text style
          msp.add_text("Text Style Example: Liberation Serif",
                       dxfattribs={
                           'style': 'LiberationSerif',
                           'height': 0.35}
                       ).set_pos((2, 6), align='LEFT')

          doc.saveas("simple_text.dxf")

       Valid text alignments for argument align in Text.set_pos():
                             ┌────────────┬─────────────┬───────────────┬──────────────┐
                             │ Vert/Horiz │ Left        │ Center        │ Right        │
                             ├────────────┼─────────────┼───────────────┼──────────────┤
                             │ Top        │ TOP_LEFTTOP_CENTERTOP_RIGHT    │
                             ├────────────┼─────────────┼───────────────┼──────────────┤
                             │ Middle     │ MIDDLE_LEFTMIDDLE_CENTERMIDDLE_RIGHT │
                             ├────────────┼─────────────┼───────────────┼──────────────┤
                             │ Bottom     │ BOTTOM_LEFTBOTTOM_CENTERBOTTOM_RIGHT │
                             ├────────────┼─────────────┼───────────────┼──────────────┤
                             │ Baseline   │ LEFTCENTERRIGHT        │
                             └────────────┴─────────────┴───────────────┴──────────────┘

       Special alignments are ALIGNED and FIT, they require a second alignment point, the text is justified with
       the vertical alignment Baseline on the virtual line between these two points.
                                ┌───────────┬───────────────────────────────────────┐
                                │ Alignment │ Description                           │
                                ├───────────┼───────────────────────────────────────┤
                                │ ALIGNED   │ Text  is  stretched  or compressed to │
                                │           │ fit exactly between p1 and p2 and the │
                                │           │ text  height  is  also  adjusted   to │
                                │           │ preserve height/width ratio.          │
                                ├───────────┼───────────────────────────────────────┤
                                │ FIT       │ Text  is  stretched  or compressed to │
                                │           │ fit exactly between  p1  and  p2  but │
                                │           │ only  the text width is adjusted, the │
                                │           │ text height is fixed  by  the  height │
                                │           │ attribute.                            │
                                ├───────────┼───────────────────────────────────────┤
                                │ MIDDLE    │ also  a  special  adjustment, but the │
                                │           │ result   is   the   same    as    for │
                                │           │ MIDDLE_CENTER.                        │
                                └───────────┴───────────────────────────────────────┘

   Standard Text Styles
       Setup some standard text styles and linetypes by argument setup=True:

          doc = ezdxf.new('R12', setup=True)

       Replaced all proprietary font declarations in setup_styles() (ARIAL, ARIAL_NARROW, ISOCPEUR and TIMES) by
       open source fonts, this is also the style name (e.g. {'style': 'OpenSans-Italic'}): [image]

   New Text Style
       Creating a new text style is simple:

          doc.styles.new('myStandard', dxfattribs={'font' : 'OpenSans-Regular.ttf'})

       But  getting  the  correct  font  name  is  often not that simple, especially on Windows.  This shows the
       required steps to get the font name for Open Sans:

          • open font folder c:\windows\fonts

          • select and open the font-family Open Sans

          • right-click on Open Sans Standard and select Properties

          • on top of the first tab you see the font name: 'OpenSans-Regular.ttf'

       The style name has to be unique in  the  DXF  document,  else  ezdxf  will  raise  an  DXFTableEntryError
       exception.   To  replace an existing entry, delete the existing entry by doc.styles.remove(name), and add
       the replacement entry.

   3D Text
       It is possible to place the 2D Text entity into 3D space by using the OCS, for further  information  see:
       tut_ocs.

   Tutorial for MText
       The  MText entity is a multi line entity with extended formatting possibilities and requires at least DXF
       version R2000, to use all features (e.g. background fill) DXF R2007 is required.

       Prolog code:

          import ezdxf

          doc = ezdxf.new('R2007', setup=True)
          msp = doc.modelspace()

          lorem_ipsum = """
          Lorem ipsum dolor sit amet, consectetur adipiscing elit,
          sed do eiusmod tempor incididunt ut labore et dolore magna
          aliqua. Ut enim ad minim veniam, quis nostrud exercitation
          ullamco laboris nisi ut aliquip ex ea commodo consequat.
          Duis aute irure dolor in reprehenderit in voluptate velit
          esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
          occaecat cupidatat non proident, sunt in culpa qui officia
          deserunt mollit anim id est laborum.
          """

   Adding a MText entity
       The MText entity can be added to  any  layout  (modelspace,  paperspace  or  block)  by  the  add_mtext()
       function.

          # store MText entity for additional manipulations
          mtext = msp.add_mtext(lorem_ipsum, dxfattribs={'style': 'OpenSans'})

       This  adds  a  MText  entity  with  text style 'OpenSans'.  The MText content can be accessed by the text
       attribute, this attribute can be edited like any Python string:

          mtext.text += 'Append additional text to the MText entity.'
          # even shorter with __iadd__() support:
          mtext += 'Append additional text to the MText entity.'
       [image]

       IMPORTANT:
          Line endings \n will be replaced by the MTEXT line endings \P at DXF export, but not vice versa \P  by
          \n at DXF file loading.

   Text placement
       The  location  of  the MText entity is defined by the MText.dxf.insert and the MText.dxf.attachment_point
       attributes. The attachment_point defines the text alignment relative  to  the  insert  location,  default
       value is 1.

       Attachment point constants defined in ezdxf.lldxf.const:
                                        ┌────────────────────────────┬───────┐
                                        │ MText.dxf.attachment_point │ Value │
                                        ├────────────────────────────┼───────┤
                                        │ MTEXT_TOP_LEFT             │ 1     │
                                        ├────────────────────────────┼───────┤
                                        │ MTEXT_TOP_CENTER           │ 2     │
                                        ├────────────────────────────┼───────┤
                                        │ MTEXT_TOP_RIGHT            │ 3     │
                                        ├────────────────────────────┼───────┤
                                        │ MTEXT_MIDDLE_LEFT          │ 4     │
                                        ├────────────────────────────┼───────┤
                                        │ MTEXT_MIDDLE_CENTER        │ 5     │
                                        ├────────────────────────────┼───────┤
                                        │ MTEXT_MIDDLE_RIGHT         │ 6     │
                                        ├────────────────────────────┼───────┤
                                        │ MTEXT_BOTTOM_LEFT          │ 7     │
                                        ├────────────────────────────┼───────┤
                                        │ MTEXT_BOTTOM_CENTER        │ 8     │
                                        ├────────────────────────────┼───────┤
                                        │ MTEXT_BOTTOM_RIGHT         │ 9     │
                                        └────────────────────────────┴───────┘

       The  MText  entity has a method for setting insert, attachment_point and rotation attributes by one call:
       set_location()

   Character height
       The character height is defined by the DXF attribute MText.dxf.char_height in drawing  units,  which  has
       also consequences for the line spacing of the MText entity:

          mtext.dxf.char_height = 0.5

       The character height can be changed inline, see also MText formatting and mtext_inline_codes.

   Text rotation (direction)
       The MText.dxf.rotation attribute defines the text rotation as angle between the x-axis and the horizontal
       direction of the text in degrees. The MText.dxf.text_direction attribute defines the horizontal direction
       of  MText  as  vector  in  WCS  or OCS, if an OCS is defined.  Both attributes can be present at the same
       entity, in this case the MText.dxf.text_direction attribute has the higher priority.

       The MText entity has two methods to get/set  rotation:  get_rotation()  returns  the  rotation  angle  in
       degrees  independent from definition as angle or direction, and set_rotation() set the rotation attribute
       and removes the text_direction attribute if present.

   Defining a wrapping border
       The wrapping border limits the text width and forces a line break for text beyond this  border.   Without
       attribute  dxf.width  (or  setting  0)  the  lines are wrapped only at the regular line endings \P or \n,
       setting the reference column width forces additional line wrappings at the given width. The  text  height
       can not be limited, the text always occupies as much space as needed.

          mtext.dxf.width = 60
       [image]

   MText formatting
       MText supports inline formatting by special codes: mtext_inline_codes

          mtext.text = "{\\C1red text} - {\\C3green text} - {\\C5blue text}"
       [image]

   Stacked text
       MText also supports stacked text:

          # the space ' ' in front of 'Lower' anr the ';' behind 'Lower' are necessary
          # combined with vertical center alignment
          mtext.text = "\\A1\\SUpper^ Lower; - \\SUpper/ Lower;} - \\SUpper# Lower;"
       [image]

       Available helper function for text formatting:

          • set_color() - append text color change

          • set_font() - append text font change

          • add_stacked_text() - append stacked text

   Background color (filling)
       The MText entity can have a background filling:

          • ACI

          • true color value as (r, g, b) tuple

          • color name as string, use special name 'canvas' to use the canvas background color

       Because of the complex dependencies ezdxf provides a method to set all required DXF attributes at once:

          mtext.set_bg_color(2, scale=1.5)

       The  parameter  scale determines how much border there is around the text, the value is based on the text
       height, and should be in the range of 1 - 5, where 1 fits exact the MText entity.  [image]

   Tutorial for Spline
       Background information about B-spline at Wikipedia.

   Splines from fit points
       Splines can be defined by fit points only, this means the  curve  goes  through  all  given  fit  points.
       AutoCAD  and BricsCAD generates required control points and knot values by itself, if only fit points are
       present.

       Create a simple spline:

          doc = ezdxf.new('R2000')

          fit_points = [(0, 0, 0), (750, 500, 0), (1750, 500, 0), (2250, 1250, 0)]
          msp = doc.modelspace()
          spline = msp.add_spline(fit_points)
       [image]

       Append a fit point to a spline:

          # fit_points, control_points, knots and weights are list-like containers:
          spline.fit_points.append((2250, 2500, 0))
       [image]

       You can set additional control points, but if they do not fit the  auto-generated  AutoCAD  values,  they
       will be ignored and don’t mess around with knot values.

       Solve problems of incorrect values after editing a spline generated by AutoCAD:

          doc = ezdxf.readfile("AutoCAD_generated.dxf")

          msp = doc.modelspace()
          spline = msp.query('SPLINE').first

          # fit_points, control_points, knots and weights are list-like objects:
          spline.fit_points.append((2250, 2500, 0))

       As  far  as  I  have  tested,  this  approach  works without complaints from AutoCAD, but for the case of
       problems remove invalid data:

          # current control points do not match spline defined by fit points
          spline.control_points = []

          # count of knots is not correct:
          # count of knots = count of control points + degree + 1
          spline.knots = []

          # same for weights, count of weights == count of control points
          spline.weights = []

   Splines by control points
       To create splines from fit points is the easiest way to create splines, but this method is also the least
       accurate, because a spline is defined by control points and knot values, which are generated for the case
       of a definition by fit points, and the worst fact is that for every given set  of  fit  points  exist  an
       infinite number of possible splines as solution.

       AutoCAD (and BricsCAD also) uses an proprietary algorithm to generate control points and knot values from
       fit  points,  which  differs  from  the  well  documented  Global  Curve Interpolation. Therefore splines
       generated from fit points by ezdxf do not match splines generated by AutoCAD (BricsCAD).

       To ensure the same spline geometry for all CAD applications, the spline has  to  be  defined  by  control
       points.  The method add_spline_control_frame() adds a spline trough fit points by calculating the control
       points  by  the  Global  Curve  Interpolation  algorithm.  There   is   also   a   low   level   function
       ezdxf.math.global_bspline_interpolation() which calculates the control points from fit points.

          msp.add_spline_control_frame(fit_points, method='uniform', dxfattribs={'color': 1})
          msp.add_spline_control_frame(fit_points, method='chord', dxfattribs={'color': 3})
          msp.add_spline_control_frame(fit_points, method='centripetal', dxfattribs={'color': 5})

       • black curve: AutoCAD/BricsCAD spline generated from fit points

       • red curve: spline curve interpolation, “uniform” method

       • green curve: spline curve interpolation, “chord” method

       • blue curve: spline curve interpolation, “centripetal” method
       [image]

   Open Spline
       Add  and  open  (clamped)  spline defined by control points with the method add_open_spline(). If no knot
       values are given, an open uniform knot vector will be generated. A clamped B-spline starts at  the  first
       control point and ends at the last control point.

          control_points = [(0, 0, 0), (1250, 1560, 0), (3130, 610, 0), (2250, 1250, 0)]
          msp.add_open_spline(control_points)
       [image]

   Closed Spline
       A closed spline is continuous closed curve.

          msp.add_closed_spline(control_points)
       [image]

   Rational Spline
       Rational  B-splines  have a weight for every control point, which can raise or lower the influence of the
       control point, default weight = 1, to lower the influence set a weight < 1 to raise the influence  set  a
       weight > 1.  The count of weights has to be always equal to the count of control points.

       Example to raise the influence of the first control point:

          msp.add_closed_rational_spline(control_points, weights=[3, 1, 1, 1])
       [image]

   Spline properties
       Check  if  spline is a closed curve or close/open spline, for a closed spline the last point is connected
       to the first point:

          if spline.closed:
              # this spline is closed
              pass

          # close spline
          spline.closed = True

          # open spline
          spline.closed = False

       Set start- and end tangent for splines defined by fit points:

          spline.dxf.start_tangent = (0, 1, 0)  # in y-axis
          spline.dxf.end_tangent = (1, 0, 0)  # in x-axis

       Get data count as stored in DXF file:

          count = spline.dxf.n_fit_points
          count = spline.dxf.n_control_points
          count = spline.dxf.n_knots

       Get data count of real existing data:

          count = spline.fit_point_count
          count = spline.control_point_count
          count = spline.knot_count

   Tutorial for Polyface
       coming soon …

   Tutorial for Mesh
       Create a cube mesh by direct access to base data structures:

          import ezdxf

          # 8 corner vertices
          cube_vertices = [
              (0, 0, 0),
              (1, 0, 0),
              (1, 1, 0),
              (0, 1, 0),
              (0, 0, 1),
              (1, 0, 1),
              (1, 1, 1),
              (0, 1, 1),
          ]

          # 6 cube faces
          cube_faces = [
              [0, 1, 2, 3],
              [4, 5, 6, 7],
              [0, 1, 5, 4],
              [1, 2, 6, 5],
              [3, 2, 6, 7],
              [0, 3, 7, 4]
          ]

          doc = ezdxf.new('R2000')  # MESH requires DXF R2000 or later
          msp = doc.modelspace()
          mesh = msp.add_mesh()
          mesh.dxf.subdivision_levels = 0  # do not subdivide cube, 0 is the default value
          with mesh.edit_data() as mesh_data:
              mesh_data.vertices = cube_vertices
              mesh_data.faces = cube_faces

          doc.saveas("cube_mesh_1.dxf")

       Create a cube mesh by method calls:

          import ezdxf

          # 8 corner vertices
          p = [
              (0, 0, 0),
              (1, 0, 0),
              (1, 1, 0),
              (0, 1, 0),
              (0, 0, 1),
              (1, 0, 1),
              (1, 1, 1),
              (0, 1, 1),
          ]

          doc = ezdxf.new('R2000')  # MESH requires DXF R2000 or later
          msp = doc.modelspace()
          mesh = msp.add_mesh()

          with mesh.edit_data() as mesh_data:
              mesh_data.add_face([p[0], p[1], p[2], p[3]])
              mesh_data.add_face([p[4], p[5], p[6], p[7]])
              mesh_data.add_face([p[0], p[1], p[5], p[4]])
              mesh_data.add_face([p[1], p[2], p[6], p[5]])
              mesh_data.add_face([p[3], p[2], p[6], p[7]])
              mesh_data.add_face([p[0], p[3], p[7], p[4]])
              mesh_data.optimize()  # optional, minimizes vertex count

          doc.saveas("cube_mesh_2.dxf")

   Tutorial for Hatch
   Create hatches with one boundary path
       The simplest form of the Hatch entity has one polyline path with only straight lines as boundary path:

          import ezdxf

          doc = ezdxf.new('R2000')  # hatch requires the DXF R2000 (AC1015) format or later
          msp = doc.modelspace()  # adding entities to the model space

          hatch = msp.add_hatch(color=2)  # by default a solid fill hatch with fill color=7 (white/black)

          # every boundary path is always a 2D element
          # vertex format for the polyline path is: (x, y[, bulge])
          # there are no bulge values in this example
          hatch.paths.add_polyline_path([(0, 0), (10, 0), (10, 10), (0, 10)], is_closed=1)

          doc.saveas("solid_hatch_polyline_path.dxf")

       But like all polyline entities the polyline path can also have bulge values:

          import ezdxf

          doc = ezdxf.new('R2000')  # hatch requires the DXF R2000 (AC1015) format or later
          msp = doc.modelspace()  # adding entities to the model space

          hatch = msp.add_hatch(color=2)  # by default a solid fill hatch with fill color=7 (white/black)

          # every boundary path is always a 2D element
          # vertex format for the polyline path is: (x, y[, bulge])
          # bulge value 1 = an arc with diameter=10 (= distance to next vertex * bulge value)
          # bulge value > 0 ... arc is right of line
          # bulge value < 0 ... arc is left of line
          hatch.paths.add_polyline_path([(0, 0, 1), (10, 0), (10, 10, -0.5), (0, 10)], is_closed=1)

          doc.saveas("solid_hatch_polyline_path_with_bulge.dxf")

       The most flexible way to define a boundary path is the edge path. An edge path consist  of  a  number  of
       edges and each edge can be one of the following elements:

          • line EdgePath.add_line()

          • arc EdgePath.add_arc()

          • ellipse EdgePath.add_ellipse()

          • spline EdgePath.add_spline()

       Create a solid hatch with an edge path (ellipse) as boundary path:

          import ezdxf

          doc = ezdxf.new('R2000')  # hatch requires the DXF R2000 (AC1015) format or later
          msp = doc.modelspace()  # adding entities to the model space

          # important: major axis >= minor axis (ratio <= 1.)
          # minor axis length = major axis length * ratio
          msp.add_ellipse((0, 0), major_axis=(0, 10), ratio=0.5)

          # by default a solid fill hatch with fill color=7 (white/black)
          hatch = msp.add_hatch(color=2)

          # every boundary path is always a 2D element
          edge_path = hatch.paths.add_edge_path()
          # each edge path can contain line arc, ellipse and spline elements
          # important: major axis >= minor axis (ratio <= 1.)
          edge_path.add_ellipse((0, 0), major_axis=(0, 10), ratio=0.5)

          doc.saveas("solid_hatch_ellipse.dxf")

   Create hatches with multiple boundary paths (islands)
       The DXF atribute hatch_style defines the island detection style:
                                    ─────────────────────────────────────────────
                                      0   nested - altering filled and unfilled
                                          areas
                                    ─────────────────────────────────────────────
                                      1   outer  -  area  between  external and
                                          outermost path is filled
                                    ─────────────────────────────────────────────
                                      2   ignore - external path is filled
                                    ┌───┬───────────────────────────────────────┐
                                    │   │                                       │
--

REFERENCE

       The DXF Reference is online available at Autodesk.

       Quoted from the original DXF 12 Reference which is not available on the web:
          Since  the  AutoCAD  drawing  database  (.dwg  file)  is  written  in  a  compact  format that changes
          significantly as new features are added to AutoCAD, we do not document its format and do not recommend
          that you attempt to write programs to read it directly. To assist in  interchanging  drawings  between
          AutoCAD  and  other  programs,  a  Drawing  Interchange  file  format  (DXF)  has  been  defined.  All
          implementations of AutoCAD accept this format and are able to convert it to and  from  their  internal
          drawing file representation.

   DXF Document
   Document Management
   Create New Drawings
       ezdxf.new(dxfversion='AC1027', setup=False) -> Drawing
              Create a new Drawing from scratch, dxfversion can be either “AC1009” the official DXF version name
              or “R12” the AutoCAD release name.

              new() can create drawings for following DXF versions:
                                                ┌─────────┬─────────────────┐
                                                │ Version │ AutoCAD Release │
                                                ├─────────┼─────────────────┤
                                                │ AC1009  │ AutoCAD R12     │
                                                ├─────────┼─────────────────┤
                                                │ AC1015  │ AutoCAD R2000   │
                                                ├─────────┼─────────────────┤
                                                │ AC1018  │ AutoCAD R2004   │
                                                ├─────────┼─────────────────┤
                                                │ AC1021  │ AutoCAD R2007   │
                                                ├─────────┼─────────────────┤
                                                │ AC1024  │ AutoCAD R2010   │
                                                ├─────────┼─────────────────┤
                                                │ AC1027  │ AutoCAD R2013   │
                                                ├─────────┼─────────────────┤
                                                │ AC1032  │ AutoCAD R2018   │
                                                └─────────┴─────────────────┘

              Parametersdxfversion – DXF version specifier as string, default is “AC1027” respectively “R2013”

                     • setup –

                       setup default styles, False for no setup, True to setup everything or a list of topics as
                       strings, e.g. [“linetypes”, “styles”] to setup only some topics:
                                       ┌──────────────┬──────────────────────────────────────┐
                                       │ Topic        │ Description                          │
                                       ├──────────────┼──────────────────────────────────────┤
                                       │ linetypes    │ setup line types                     │
                                       ├──────────────┼──────────────────────────────────────┤
                                       │ styles       │ setup text styles                    │
                                       ├──────────────┼──────────────────────────────────────┤
                                       │ dimstyles    │ setup default ezdxf dimension styles │
                                       ├──────────────┼──────────────────────────────────────┤
                                       │ visualstyles │ setup 25 standard visual styles      │
                                       └──────────────┴──────────────────────────────────────┘

   Open Drawings
       Open DXF drawings from file system or text stream, byte stream usage is not supported.

       DXF  files  prior  to R2007 requires file encoding defined by header variable $DWGCODEPAGE, DXF R2007 and
       later requires an UTF-8 encoding.

       ezdxf supports reading of files for following DXF versions:
                            ──────────────────────────────────────────────────────────────
                              Version    Release   Encoding       Remarks
                            ──────────────────────────────────────────────────────────────
                              < AC1009             $DWGCODEPAGE   pre    AutoCAD     R12
                                                                  upgraded to AC1009
                            ──────────────────────────────────────────────────────────────
                              AC1009     R12       $DWGCODEPAGE   AutoCAD R12
                            ──────────────────────────────────────────────────────────────
                              AC1012     R13       $DWGCODEPAGE   AutoCAD  R13  upgraded
                                                                  to AC1015
                            ──────────────────────────────────────────────────────────────
                              AC1014     R14       $DWGCODEPAGE   AutoCAD  R14  upgraded
                                                                  to AC1015
                            ──────────────────────────────────────────────────────────────
                              AC1015     R2000     $DWGCODEPAGE   AutoCAD R2000
                            ──────────────────────────────────────────────────────────────
                              AC1018     R2004     $DWGCODEPAGE   AutoCAD R2004
                            ──────────────────────────────────────────────────────────────
                              AC1021     R2007     UTF-8          AutoCAD R2007
                            ──────────────────────────────────────────────────────────────
                              AC1024     R2010     UTF-8          AutoCAD R2010
                            ──────────────────────────────────────────────────────────────
                              AC1027     R2013     UTF-8          AutoCAD R2013
                            ──────────────────────────────────────────────────────────────
                              AC1032     R2018     UTF-8          AutoCAD R2018
                            ┌──────────┬─────────┬──────────────┬────────────────────────┐
                            │          │         │              │                        │
--

HOWTO

       The  Howto  section  show  how  to accomplish specific tasks with ezdxf in a straight forward way without
       teaching basics or internals, if you are looking for more information about the ezdxf internals  look  at
       the  Reference  section  or  if  you want to learn how to use ezdxf go to the Tutorials section or to the
       Basic Concepts section.

   General Document
       General preconditions:

          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()

       This works well with DXF files from trusted sources like AutoCAD or BricsCAD, for loading DXF files  with
       minor or major flaws look at the ezdxf.recover module.

   Load DXF Files with Structure Errors
       If  you  know  the  files  you  will process have most likely minor or major flaws, use the ezdxf.recover
       module:

          import sys
          from ezdxf import recover

          try:  # low level structure repair:
              doc, auditor = recover.readfile(name)
          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: {name}.')
              sys.exit(2)

          # DXF file can still have unrecoverable errors, but this is maybe
          # just a problem when saving the recovered DXF file.
          if auditor.has_errors:
              print(f'Found unrecoverable errors in DXF file: {name}.')
              auditor.print_error_report()

       For more loading scenarios follow the link: ezdxf.recover

   Set/Get Header Variables
       ezdxf has an interface to get and set HEADER variables:

          doc.header['VarName'] = value
          value = doc.header['VarName']

       SEE ALSO:
          HeaderSection and online documentation from Autodesk for available header variables.

   Set DXF Drawing Units
       Use this HEADER variables to setup the default units for CAD applications opening  the  DXF  file.   This
       settings  are  not relevant for ezdxf API calls, which are unitless for length values and coordinates and
       decimal degrees for angles (in most cases).

       Sets drawing units:

       $MEASUREMENT controls whether the current drawing uses imperial or  metric  hatch  pattern  and  linetype
       files:

          doc.header['$MEASUREMENT'] = 1
                                                   ───────────────
                                                     0   English
                                                   ───────────────
                                                     1   Metric
                                                   ┌───┬─────────┐
                                                   │   │         │
--

FAQ

   What is the Relationship between ezdxf, dxfwrite and dxfgrabber?
       In 2010 I started my first Python package for creating DXF documents called dxfwrite, this package  can’t
       read  DXF  files and writes only the DXF R12 (AC1009) version. While dxfwrite works fine, I wanted a more
       versatile package, that can read and write DXF files and maybe also supports newer DXF formats  than  DXF
       R12.

       This  was the start of the ezdxf package in 2011, but the progress was so slow, that I created a spin off
       in 2012 called dxfgrabber, which implements only the reading part of ezdxf, which I needed  for  my  work
       and  I  wasn’t sure if ezdxf will ever be usable. Luckily in 2014 the first usable version of ezdxf could
       be released. The ezdxf package has all the features of dxfwrite and dxfgrabber and much more, but with  a
       different API. So ezdxf is not a drop-in replacement for dxfgrabber or dxfwrite.

       Since  ezdxf  can  do all the things that dxfwrite and dxfgrabber can do, I focused on the development of
       ezdxf, dxfwrite and dxfgrabber are in maintenance mode only and will  not  get  any  new  features,  just
       bugfixes.

       There  are  no  advantages  of  dxfwrite  over  ezdxf, dxfwrite has the smaller memory footprint, but the
       r12writer add-on does the same job as dxfwrite without any in memory structures by writing  direct  to  a
       stream  or  file and there is also no advantage of dxfgrabber over ezdxf for normal DXF files the smaller
       memory footprint of dxfgrabber is not noticeable and for really big  files  the  iterdxf  add-on  does  a
       better job.

RENDERING

       The ezdxf.render subpackage provides helpful utilities to create complex forms.

          • create complex meshes as Mesh entity.

          • render complex curves like bezier curves, euler spirals or splines as Polyline entity

          • vertex generators for simple and complex forms like circle, ellipse or euler spiral

       Content

   Spline
       Render  a  B-spline as 2D/3D Polyline, can be used with DXF R12. The advantage over R12Spline is the real
       3D support which means the B-spline curve vertices has not to be in a plane and no hassle with UCS for 3D
       placing.

       class ezdxf.render.Spline

              __init__(points: Iterable[Vertex] = None, segments: int = 100)

                     Parameterspoints – spline definition points as Vector or (x, y, z) tuple

                            • segments – count of line segments for approximation, vertex count is segments + 1

              subdivide(segments: int = 4) -> None
                     Calculate overall segment count, where segments is the sub-segment  count,  segments  =  4,
                     means 4 line segments between two definition points e.g. 4 definition points and 4 segments
                     = 12 overall segments, useful for fit point rendering.

                     Parameters
                            segments – sub-segments count between two definition points

              render_as_fit_points(layout: BaseLayout, degree: int = 3, method: str = 'chord', dxfattribs: dict
              = None) -> None
                     Render a B-spline as 2D/3D Polyline, where the definition points are fit points.

                        • 2D spline vertices uses: add_polyline2d()

                        • 3D spline vertices uses: add_polyline3d()

                     ParameterslayoutBaseLayout object

                            • degree – degree of B-spline (order = degree + 1)

                            • method   –  “uniform”,  “distance”/”chord”,  “centripetal”/”sqrt_chord”  or  “arc”
                              calculation method for parameter t

                            • dxfattribs – DXF attributes for Polyline

              render_open_bspline(layout: BaseLayout, degree: int = 3, dxfattribs: dict = None) -> None
                     Render an open uniform BSpline as 3D Polyline. Definition points are control points.

                     ParameterslayoutBaseLayout object

                            • degree – degree of B-spline (order = degree + 1)

                            • dxfattribs – DXF attributes for Polyline

              render_uniform_bspline(layout: BaseLayout, degree: int = 3, dxfattribs: dict = None) -> None
                     Render a uniform BSpline as 3D Polyline. Definition points are control points.

                     ParameterslayoutBaseLayout object

                            • degree – degree of B-spline (order = degree + 1)

                            • dxfattribs – DXF attributes for Polyline

              render_closed_bspline(layout: BaseLayout, degree: int = 3, dxfattribs: dict = None) -> None
                     Render a closed uniform BSpline as 3D Polyline. Definition points are control points.

                     ParameterslayoutBaseLayout object

                            • degree – degree of B-spline (order = degree + 1)

                            • dxfattribs – DXF attributes for Polyline

              render_open_rbspline(layout: BaseLayout, weights: Iterable[float], degree: int = 3, dxfattribs:
              dict = None) -> None
                     Render a rational open uniform BSpline  as  3D  Polyline.  Definition  points  are  control
                     points.

                     ParameterslayoutBaseLayout object

                            • weights  –  list  of  weights, requires a weight value (float) for each definition
                              point.

                            • degree – degree of B-spline (order = degree + 1)

                            • dxfattribs – DXF attributes for Polyline

              render_uniform_rbspline(layout: BaseLayout, weights: Iterable[float], degree: int = 3, dxfattribs:
              dict = None) -> None
                     Render a rational uniform BSpline as 3D Polyline. Definition points are control points.

                     ParameterslayoutBaseLayout object

                            • weights – list of weights, requires a weight value  (float)  for  each  definition
                              point.

                            • degree – degree of B-spline (order = degree + 1)

                            • dxfattribs – DXF attributes for Polyline

              render_closed_rbspline(layout: BaseLayout, weights: Iterable[float], degree: int = 3, dxfattribs:
              dict = None) -> None
                     Render a rational BSpline as 3D Polyline. Definition points are control points.

                     ParameterslayoutBaseLayout object

                            • weights  –  list  of  weights, requires a weight value (float) for each definition
                              point.

                            • degree – degree of B-spline (order = degree + 1)

                            • dxfattribs – DXF attributes for Polyline

   R12Spline
       DXF R12 supports 2D B-splines, but Autodesk do not document the usage in  the  DXF  Reference.  The  base
       entity  for splines in DXF R12 is the POLYLINE entity. The spline itself is always in a plane, but as any
       2D entity, the spline can be transformed into the 3D object by elevation and extrusion (OCS, UCS).

       The result is not better than Spline, it is also just a POLYLINE entity, but as with all tools, you never
       know if someone needs it some day.

       class ezdxf.render.R12Spline

              __init__(control_points: Iterable[Vertex], degree: int = 2, closed: bool = True)

                     Parameterscontrol_points – B-spline control frame  vertices  as  (x,  y)  tuples  or  Vector
                              objects

                            • degree – degree of B-spline, 2 or 3 are valid values

                            • closedTrue for closed curve

              render(layout: BaseLayout, segments: int = 40, ucs: UCS = None, dxfattribs: dict = None) ->
              Polyline
                     Renders  the B-spline into layout as 2D Polyline entity.  Use an UCS to place the 2D spline
                     in 3D space, see approximate() for more information.

                     ParameterslayoutBaseLayout object

                            • segments – count of line segments for approximation, vertex count is segments + 1

                            • ucsUCS definition, control points in ucs coordinates.

                            • dxfattribs – DXF attributes for Polyline

              approximate(segments: int = 40, ucs: UCS = None) -> List[Vertex]
                     Approximate B-spline by a polyline with segments line segments. If ucs  is  not  None,  ucs
                     defines  an  UCS, to transformed the curve into OCS. The control points are placed xy-plane
                     of the UCS, don’t use z-axis coordinates, if so make sure all control points are in a plane
                     parallel to the OCS base plane (UCS xy-plane), else the result is unpredictable and depends
                     on the CAD application used to open the DXF file, it maybe crash.

                     Parameterssegments – count of line segments for approximation, vertex count is segments + 1

                            • ucsUCS definition, control points in ucs coordinates.

                     Returns
                            list of vertices in OCS as Vector objects

   Bezier
       Render a bezier curve as 2D/3D Polyline.

       The Bezier class is implemented with multiple segments, each segment  is  an  optimized  4  point  bezier
       curve,  the  4  control  points of the curve are: the start point (1) and the end point (4), point (2) is
       start point + start vector and  point  (3)  is  end  point  +  end  vector.  Each  segment  has  its  own
       approximation count.

       class ezdxf.render.Bezier

              start(point: Vertex, tangent: Vertex) -> None
                     Set start point and start tangent.

                     Parameterspoint – start point as Vector or (x, y, z) tuple

                            • tangent  –  start tangent as vector, example: (5, 0, 0) means a horizontal tangent
                              with a length of 5 drawing units

              append(point: Vertex, tangent1: Vertex, tangent2: Vertex = None, segments: int = 20)
                     Append a control point with two control tangents.

                     Parameterspoint – control point as Vector or (x, y, z) tuple

                            • tangent1 – first control tangent as vector “left” of control point

                            • tangent2 – second control tangent as vector “right” of control point,  if  omitted
                              tangent2 = -tangent1segments  –  count  of  line  segments  for  polyline approximation, count of line
                              segments from previous control point to appended control point.

              render(layout: BaseLayout, force3d: bool = False, dxfattribs: dict = None) -> None
                     Render bezier curve as 2D/3D Polyline.

                     ParameterslayoutBaseLayout object

                            • force3d – force 3D polyline rendering

                            • dxfattribs – DXF attributes for Polyline

   EulerSpiral
       Render an euler spiral as 3D Polyline or Spline.

       This is a parametric curve, which always starts at the origin (0, 0).

       class ezdxf.render.EulerSpiral

              __init__(curvature: float = 1)

                     Parameters
                            curvature – Radius of curvature

              render_polyline(layout: BaseLayout, length: float = 1, segments: int = 100, matrix: Matrix44 =
              None, dxfattribs: dict = None)
                     Render curve as Polyline.

                     ParameterslayoutBaseLayout object

                            • length – length measured along the spiral curve from its initial position

                            • segments – count of line segments to use, vertex count is segments + 1

                            • matrix – transformation matrix as Matrix44dxfattribs – DXF attributes for Polyline

                     Returns
                            Polyline

              render_spline(layout: BaseLayout, length: float = 1, fit_points: int = 10, degree: int = 3,
              matrix: Matrix44 = None, dxfattribs: dict = None)
                     Render curve as Spline.

                     ParameterslayoutBaseLayout object

                            • length – length measured along the spiral curve from its initial position

                            • fit_points – count of spline fit points to use

                            • degree – degree of B-spline

                            • matrix – transformation matrix as Matrix44dxfattribs – DXF attributes for Spline

                     Returns
                            Spline

   Random Paths
       Random path generators for testing purpose.

       ezdxf.render.random_2d_path(steps=100, max_step_size=1, max_heading=pi / 2, retarget=20) ->
       Iterable[Vec2]
              Returns a random 2D path as iterable of Vec2 objects.

              Parameterssteps – count of vertices to generate

                     • max_step_size – max step size

                     • max_heading – limit heading angle change per step to ± max_heading/2 in radians

                     • retarget – specifies steps before changing global walking target

       ezdxf.render.random_3d_path(steps=100, max_step_size=1, max_heading=pi / 2, max_pitch=pi / 8,
       retarget=20) -> Iterable[Vector]
              Returns a random 3D path as iterable of Vector objects.

              Parameterssteps – count of vertices to generate

                     • max_step_size – max step size

                     • max_heading – limit heading angle change per step to ± max_heading/2, rotation about  the
                       z-axis in radians

                     • max_pitch – limit pitch angle change per step to ± max_pitch/2, rotation about the x-axis
                       in radians

                     • retarget – specifies steps before changing global walking target

   Forms
          This module provides functions to create 2D and 3D forms as vertices or mesh objects.

          2D Forms

          • circle()square()box()ellipse()euler_spiral()ngon()star()gear()

          3D Forms

          • cube()cylinder()cylinder_2p()cone()cone_2p()sphere()

          3D Form Builder

          • extrude()from_profiles_linear()from_profiles_spline()rotation_form()

   2D Forms
          Basic 2D shapes as iterable of Vector.

       ezdxf.render.forms.circle(count: int, radius: float = 1, elevation: float = 0, close: bool = False) ->
       Iterable[Vector]
              Create  polygon  vertices  for a circle with radius and count corners, elevation is the z-axis for
              all vertices.

              Parameterscount – count of polygon vertices

                     • radius – circle radius

                     • elevation – z-axis for all vertices

                     • close – yields first vertex also as last vertex if True.

              Returns
                     vertices in counter clockwise orientation as Vector objects

       ezdxf.render.forms.square(size: float = 1.) -> Tuple[Vector, Vector, Vector, Vector]
              Returns 4 vertices for a square with a side length of size, lower left corner  is  (0,  0),  upper
              right corner is (size, size).

       ezdxf.render.forms.box(sx: float = 1., sy: float = 1.) -> Tuple[Vector, Vector, Vector, Vector]
              Returns  4  vertices  for  a box sx by sy, lower left corner is (0, 0), upper right corner is (sx,
              sy).

       ezdxf.render.forms.ellipse(count: int, rx: float = 1, ry: float = 1, start_param: float = 0, end_param:
       float = 2 * pi, elevation: float = 0) -> Iterable[Vector]
              Create polygon vertices for an ellipse with rx as x-axis radius and  ry  for  y-axis  radius  with
              count  vertices,  elevation  is  the z-axis for all vertices. The ellipse goes from start_param to
              end_param in counter clockwise orientation.

              Parameterscount – count of polygon vertices

                     • rx – ellipse x-axis radius

                     • ry – ellipse y-axis radius

                     • start_param – start of ellipse in range 0 .. 2*piend_param – end of ellipse in range 0 .. 2*pielevation – z-axis for all vertices

              Returns
                     vertices in counter clockwise orientation as Vector objects

       ezdxf.render.forms.euler_spiral(count: int, length: float = 1, curvature: float = 1, elevation: float =
       0) -> Iterable[Vector]
              Create polygon vertices for an euler spiral of a given length and radius of curvature. This  is  a
              parametric curve, which always starts at the origin (0, 0).

              Parameterscount – count of polygon vertices

                     • length – length of curve in drawing units

                     • curvature – radius of curvature

                     • elevation – z-axis for all vertices

              Returns
                     vertices as Vector objects

       ezdxf.render.forms.ngon(count: int, length: float = None, radius: float = None, rotation: float = 0.,
       elevation: float = 0., close: bool = False) -> Iterable[Vector]
              Returns  the  corner  vertices  of  a regular polygon.  The polygon size is determined by the edge
              length or the circum radius argument.  If both are given length has higher priority.

              Parameterscount – count of polygon corners >= 3length – length of polygon side

                     • radius – circum radius

                     • rotation – rotation angle in radians

                     • elevation – z-axis for all vertices

                     • close – yields first vertex also as last vertex if True.

              Returns
                     vertices as Vector objects

       ezdxf.render.forms.star(count: int, r1: float, r2: float, rotation: float = 0., elevation: float = 0.,
       close: bool = False) -> Iterable[Vector]
              Returns corner vertices for star shapes.

              Argument count defines the count of star spikes, r1 defines the radius of the “outer” vertices and
              r2 defines the radius of the “inner” vertices, but this does not mean that r1 has  to  be  greater
              than r2.

              Parameterscount – spike count >= 3r1 – radius 1

                     • r2 – radius 2

                     • rotation – rotation angle in radians

                     • elevation – z-axis for all vertices

                     • close – yields first vertex also as last vertex if True.

              Returns
                     vertices as Vector objects

       ezdxf.render.forms.gear(count: int, top_width: float, bottom_width: float, height: float, outside_radius:
       float, elevation: float = 0, close: bool = False) -> Iterable[Vector]
              Returns gear (cogwheel) corner vertices.

              WARNING:
                 This function does not create correct gears for mechanical engineering!

              Parameterscount – teeth count >= 3top_width – teeth width at outside radius

                     • bottom_width – teeth width at base radius

                     • height – teeth height; base radius = outside radius - height

                     • outside_radius – outside radius

                     • elevation – z-axis for all vertices

                     • close – yields first vertex also as last vertex if True.

              Returns
                     vertices in counter clockwise orientation as Vector objects

   3D Forms
       Create 3D forms as MeshTransformer objects.

       ezdxf.render.forms.cube(center: bool = True) -> MeshTransformer
              Create a cube as MeshTransformer object.

              Parameters
                     center – ‘mass’ center of cube, (0, 0, 0) if True, else first corner at (0, 0, 0)

              Returns: MeshTransformer

       ezdxf.render.forms.cylinder(count: int, radius: float = 1., top_radius: float = None, top_center: Vertex
       = (0, 0, 1), caps=True, ngons=True) -> MeshTransformer
              Create a cylinder as MeshTransformer object, the base center is fixed in the origin (0, 0, 0).

              Parameterscount – profiles edge count

                     • radius – radius for bottom profile

                     • top_radius – radius for top profile, if None top_radius == radius

                     • top_center – location vector for the center of the top profile

                     • caps – close hull with bottom cap and top cap (as N-gons)

                     • ngons – use ngons for caps if True else subdivide caps into triangles

              Returns: MeshTransformer

       ezdxf.render.forms.cylinder_2p(count: int = 16, radius: float = 1, base_center=(0, 0, 0), top_center=(0,
       0, 1)) -> MeshTransformer
              Create a cylinder as MeshTransformer object from two points, base_center is the center of the base
              circle and, top_center the center of the top circle.

              Parameterscount – profiles edge count

                     • radius – radius for bottom profile

                     • base_center – center of base circle

                     • top_center – center of top circle

              Returns: MeshTransformer

              New in version 0.11.

       ezdxf.render.forms.cone(count: int, radius: float, apex: Vertex = (0, 0, 1), caps=True, ngons=True) ->
       MeshTransformer
              Create a cone as MeshTransformer object, the base center is fixed in the origin (0, 0, 0).

              Parameterscount – edge count of basis_vector

                     • radius – radius of basis_vector

                     • apex – tip of the cone

                     • caps – add a bottom face if Truengons – use ngons for caps if True else subdivide caps into triangles

              Returns: MeshTransformer

       ezdxf.render.forms.cone_2p(count: int, radius: float, apex: Vertex = (0, 0, 1)) -> MeshTransformer
              Create  a  cone  as  MeshTransformer object from two points, base_center is the center of the base
              circle and apex as the tip of the cone.

              Parameterscount – edge count of basis_vector

                     • radius – radius of basis_vector

                     • base_center – center point of base circle

                     • apex – tip of the cone

              Returns: MeshTransformer

              New in version 0.11.

       ezdxf.render.forms.sphere(count: int = 16, stacks: int = 8, radius: float = 1, quads=True) ->
       MeshTransformer
              Create a sphere as MeshTransformer object, center is fixed at origin (0, 0, 0).

              Parameterscount – longitudinal slices

                     • stacks – latitude slices

                     • radius – radius of sphere

                     • quads – use quads for body faces if True else triangles

              Returns: MeshTransformer

              New in version 0.11.

   3D Form Builder
       ezdxf.render.forms.extrude(profile: Iterable[Vertex], path: Iterable[Vertex], close=True) ->
       MeshTransformer
              Extrude a profile polygon along a  path  polyline,  vertices  of  profile  should  be  in  counter
              clockwise order.

              Parametersprofile – sweeping profile as list of (x, y, z) tuples in counter clock wise order

                     • path – extrusion path as list of (x, y, z) tuples

                     • close – close profile polygon if True

              Returns: MeshTransformer

       ezdxf.render.forms.from_profiles_linear(profiles: Iterable[Iterable[Vertex]], close=True, caps=False,
       ngons=True) -> MeshTransformer
              Create MESH entity by linear connected profiles.

              Parametersprofiles – list of profiles

                     • close – close profile polygon if Truecaps – close hull with bottom cap and top cap

                     • ngons – use ngons for caps if True else subdivide caps into triangles

              Returns: MeshTransformer

       ezdxf.render.forms.from_profiles_spline(profiles: Iterable[Iterable[Vertex]], subdivide: int = 4,
       close=True, caps=False, ngons=True) -> MeshTransformer
              Create  MESH  entity by spline interpolation between given profiles. Requires at least 4 profiles.
              A subdivide value of 4, means, create 4 face loops between two profiles, without interpolation two
              profiles create one face loop.

              Parametersprofiles – list of profiles

                     • subdivide – count of face loops

                     • close – close profile polygon if Truecaps – close hull with bottom cap and top cap

                     • ngons – use ngons for caps if True else subdivide caps into triangles

              Returns: MeshTransformer

       ezdxf.render.forms.rotation_form(count: int, profile: Iterable[Vertex], angle: float = 2 * pi, axis:
       Vertex = (1, 0, 0)) -> MeshTransformer
              Create MESH entity by rotating a profile around an axis.

              Parameterscount – count of rotated profiles

                     • profile – profile to rotate as list of vertices

                     • angle – rotation angle in radians

                     • axis – rotation axis

              Returns: MeshTransformer

   MeshBuilder
       The MeshBuilder is a helper class  to create Mesh entities.  Stores a list of vertices, a list  of  edges
       where  an edge is a list of indices into the vertices list, and a faces list where each face is a list of
       indices into the vertices list.

       The MeshBuilder.render() method, renders the mesh into a Mesh entity.  The Mesh entity supports ngons  in
       AutoCAD, ngons are polygons with more than 4 vertices.

       The basic MeshBuilder class does not support transformations.

       class ezdxf.render.MeshBuilder

              vertices
                     List of vertices as Vector or (x, y, z) tuple

              edges  List of edges as 2-tuple of vertex indices, where a vertex index is the index of the vertex
                     in the vertices list.

              faces  List  of  faces as list of vertex indices,  where a vertex index is the index of the vertex
                     in the vertices list. A face requires at least three vertices, Mesh supports ngons, so  the
                     count of vertices is not limited.

              copy() Returns a copy of mesh.

              faces_as_vertices() -> Iterable[List[Vector]]
                     Iterate over all mesh faces as list of vertices.

              edges_as_vertices() -> Iterable[Tuple[Vector, Vector]]
                     Iterate over all mesh edges as tuple of two vertices.

              add_vertices(vertices: Iterable[Vertex]) -> Sequence[int]
                     Add  new vertices to the mesh, each vertex is a (x, y, z) tuple or a Vector object, returns
                     the indices of the vertices added to the vertices list.

                     e.g. adding 4 vertices to an  empty  mesh,  returns  the  indices  (0,  1,  2,  3),  adding
                     additional 4 vertices returns the indices (4, 5, 6, 7).

                     Parameters
                            vertices – list of vertices, vertex as (x, y, z) tuple or Vector objects

                     Returns
                            indices of the vertices added to the vertices list

                     Return type
                            tuple

              add_edge(vertices: Iterable[Vertex]) -> None
                     An  edge  consist  of  two  vertices [v1, v2], each vertex is a (x, y, z) tuple or a Vector
                     object. The new vertex indices are stored as edge in the edges list.

                     Parameters
                            vertices – list of 2 vertices : [(x1, y1, z1), (x2, y2, z2)]

              add_face(vertices: Iterable[Vertex]) -> None
                     Add a face as vertices list to the mesh. A face requires at least 3 vertices,  each  vertex
                     is  a  (x,  y,  z) tuple or Vector object. The new vertex indices are stored as face in the
                     faces list.

                     Parameters
                            vertices – list of at least 3 vertices [(x1, y1, z1), (x2, y2, z2),  (x3,  y3,  y3),
                            ...]

              add_mesh(vertices=None, faces=None, edges=None, mesh=None) -> None
                     Add another mesh to this mesh.

                     A  mesh  can  be  a MeshBuilder, MeshVertexMerger or Mesh object or requires the attributes
                     vertices, edges and faces.

                     Parametersvertices – list of vertices, a vertex is a (x, y, z) tuple or Vector object

                            • faces – list of faces, a face is a list of vertex indices

                            • edges – list of edges, an edge is a list of vertex indices

                            • mesh – another mesh entity

              has_none_planar_faces() -> bool
                     Returns True if any face is none planar.

              render(layout: BaseLayout, dxfattribs: dict = None, matrix: Matrix44 = None, ucs: UCS = None)
                     Render mesh as Mesh entity into layout.

                     ParameterslayoutBaseLayout object

                            • dxfattribs – dict of DXF attributes e.g. {'layer': 'mesh', 'color': 7}matrix – transformation matrix of type Matrix44ucs – transform vertices by UCS to WCS

              render_polyface(layout: BaseLayout, dxfattribs: dict = None, matrix: Matrix44 = None, ucs: UCS =
              None)
                     Render mesh as Polyface entity into layout.

                     New in version 0.11.1.

                     ParameterslayoutBaseLayout object

                            • dxfattribs – dict of DXF attributes e.g. {'layer': 'mesh', 'color': 7}matrix – transformation matrix of type Matrix44ucs – transform vertices by UCS to WCS

              render_3dfaces(layout: BaseLayout, dxfattribs: dict = None, matrix: Matrix44 = None, ucs: UCS =
              None)
                     Render mesh as Face3d entities into layout.

                     New in version 0.12.

                     ParameterslayoutBaseLayout object

                            • dxfattribs – dict of DXF attributes e.g. {'layer': 'mesh', 'color': 7}matrix – transformation matrix of type Matrix44ucs – transform vertices by UCS to WCS

              render_normals(layout: BaseLayout, length: float = 1, relative=True, dxfattribs: dict = None)
                     Render face normals as Line entities into layout,  useful  to  check  orientation  of  mesh
                     faces.

                     ParameterslayoutBaseLayout object

                            • length  –  visual  length  of  normal, use length < 0 to point normals in opposite
                              direction

                            • relative – scale length relative to face size if Truedxfattribs – dict of DXF attributes e.g. {'layer': 'normals', 'color': 6}

              classmethod from_mesh(other) -> ezdxf.render.mesh.MeshBuilder
                     Create new mesh from other mesh as class method.

                     Parameters
                            othermesh of type MeshBuilder and inherited or DXF  Mesh  entity  or  any  object
                            providing attributes vertices, edges and faces.

              classmethod from_polyface(other: Union[Polymesh, Polyface]) -> MeshBuilder
                     Create new mesh from a  Polyface or Polymesh object.

                     New in version 0.11.1.

              classmethod from_builder(other: MeshBuilder)
                     Create  new  mesh  from  other  mesh  builder,  faster  than  from_mesh() but supports only
                     MeshBuilder and inherited classes.

   MeshTransformer
       Same functionality as MeshBuilder but supports inplace transformation.

       class ezdxf.render.MeshTransformer
              Subclass of MeshBuilder

              subdivide(level: int = 1, quads=True, edges=False) -> MeshTransformer
                     Returns a new MeshTransformer object with subdivided faces and edges.

                     Parameterslevel – subdivide levels from 1 to max of 5

                            • quads – create quad faces if True else create triangles

                            • edges – also subdivide edges if True

              transform(matrix: Matrix44)
                     Transform mesh inplace by applying the transformation matrix.

                     Parameters
                            matrix – 4x4 transformation matrix as Matrix44 object

              translate(dx: float = 0, dy: float = 0, dz: float = 0)
                     Translate mesh inplace.

                     Parametersdx – translation in x-axis

                            • dy – translation in y-axis

                            • dz – translation in z-axis

              scale(sx: float = 1, sy: float = 1, sz: float = 1)
                     Scale mesh inplace.

                     Parameterssx – scale factor for x-axis

                            • sy – scale factor for y-axis

                            • sz – scale factor for z-axis

              scale_uniform(s: float)
                     Scale mesh uniform inplace.

                     Parameters
                            s – scale factor for x-, y- and z-axis

              rotate_x(angle: float)
                     Rotate mesh around x-axis about angle inplace.

                     Parameters
                            angle – rotation angle in radians

              rotate_y(angle: float)
                     Rotate mesh around y-axis about angle inplace.

                     Parameters
                            angle – rotation angle in radians

              rotate_z(angle: float)
                     Rotate mesh around z-axis about angle inplace.

                     Parameters
                            angle – rotation angle in radians

              rotate_axis(axis: Vertex, angle: float)
                     Rotate mesh around an arbitrary axis located in the origin (0, 0, 0) about angle.

                     Parametersaxis – rotation axis as Vector

                            • angle – rotation angle in radians

   MeshVertexMerger
       Same functionality as MeshBuilder,  but  created  meshes  with  unique  vertices  and  no  doublets,  but
       MeshVertexMerger  needs extra memory for bookkeeping and also does not support transformations.  Location
       of merged vertices is the location of the first vertex with the same key.

       This class is  intended  as  intermediate  object  to  create  a  compact  meshes  and  convert  them  to
       MeshTransformer objects to apply transformations to the mesh:

          mesh = MeshVertexMerger()

          # create your mesh
          mesh.add_face(...)

          # convert mesh to MeshTransformer object
          return MeshTransformer.from_builder(mesh)

       class ezdxf.render.MeshVertexMerger(precision: int = 6)
              Subclass of MeshBuilder

              Mesh with unique vertices and no doublets, but needs extra memory for bookkeeping.

              MeshVertexMerger  creates  a key for every vertex by rounding its components by the Python round()
              function and a given precision value. Each vertex with the same key gets the  same  vertex  index,
              which  is  the  index  of  first  vertex  with this key, so all vertices with the same key will be
              located at the location of this first vertex. If you want an  average  location  of  and  for  all
              vertices with the same key look at the MeshAverageVertexMerger class.

              Parameters
                     precision – floating point precision for vertex rounding

   MeshAverageVertexMerger
       This  is an extended version of MeshVertexMerger.  Location of merged vertices is the average location of
       all vertices with the same key, this needs extra memory and runtime in  comparision  to  MeshVertexMerger
       and this class also does not support transformations.

       class ezdxf.render.MeshAverageVertexMerger(precision: int = 6)
              Subclass of MeshBuilder

              Mesh  with unique vertices and no doublets, but needs extra memory for bookkeeping and runtime for
              calculation of average vertex location.

              MeshAverageVertexMerger creates a key for every vertex by rounding its components  by  the  Python
              round()  function  and a given precision value. Each vertex with the same key gets the same vertex
              index, which is the index of first vertex with this key, the difference  to  the  MeshVertexMerger
              class  is  the  calculation of the average location for all vertices with the same key, this needs
              extra memory to keep track of the count of vertices for each key and extra  runtime  for  updating
              the vertex location each time a vertex with an existing key is added.

              Parameters
                     precision – floating point precision for vertex rounding

   Trace
       This module provides tools to create banded lines like LWPOLYLINE with width information.  Path rendering
       as quadrilaterals: Trace, Solid or Face3d.

       class ezdxf.render.trace.TraceBuilder
              Sequence of 2D banded lines like polylines with start- and end width or curves with start- and end
              width.

              Accepts 3D input, but z-axis is ignored.

              abs_tol
                     Absolute tolerance for floating point comparisons

              append(trace: ezdxf.render.trace.AbstractTrace) -> None
                     Append a new trace.

              close()
                     Close multi traces by merging first and last trace, if linear traces.

              faces() -> Iterable[Tuple[Vec2, Vec2, Vec2, Vec2]
                     Yields all faces as 4-tuples of Vec2 objects.

              virtual_entities(dxftype='TRACE', dxfattribs: Dict = None, doc: Drawing = None) -> Union[Solid,
              Trace, Face3d]
                     Yields faces as SOLID, TRACE or 3DFACE entities with DXF attributes given in dxfattribs.

                     If  a  document  is  given,  the  doc attribute of the new entities will be set and the new
                     entities will be automatically added to the entity database of that document.

                     Parametersdxftype – DXF type as string, “SOLID”, “TRACE” or “3DFACE”

                            • dxfattribs – DXF attributes for SOLID, TRACE or 3DFACE entities

                            • doc – associated document

              classmethod from_polyline(polyline: DXFGraphic, segments: int = 64) -> TraceBuilder
                     Create a complete trace from a LWPOLYLINE or a 2D POLYLINE entity,  the  trace  consist  of
                     multiple sub-traces if bulge values are present.

                     ParameterspolylineLWPolyline or 2D Polylinesegments  –  count  of segments for bulge approximation, given count is for a full
                              circle, partial arcs have proportional less segments, but at least 3

              __len__()

              __getitem__(item)

       class ezdxf.render.trace.LinearTrace
              Linear 2D banded lines like polylines with start- and end width.

              Accepts 3D input, but z-axis is ignored.

              abs_tol
                     Absolute tolerance for floating point comparisons

              is_started
                     True if at least one station exist.

              add_station(point: Vertex, start_width: float, end_width: float = None) -> None
                     Add a trace station (like a vertex) at location point, start_width is the width of the next
                     segment starting at this station, end_width is the end width of the next segment.

                     Adding the last location again, replaces the actual last location e.g. adding lines (a, b),
                     (b, c), creates only 3 stations (a, b, c),  this  is  very  important  to  connect  to/from
                     splines.

                     Parameterspoint – 2D location (vertex), z-axis of 3D vertices is ignored.

                            • start_width – start width of next segment

                            • end_width – end width of next segment

              faces() -> Iterable[Tuple[Vec2, Vec2, Vec2, Vec2]
                     Yields all faces as 4-tuples of Vec2 objects.

                     First and last miter is 90 degrees if the path is not closed, otherwise the intersection of
                     first  and  last segment is taken into account, a closed path has to have explicit the same
                     last and first vertex.

              virtual_entities(dxftype='TRACE', dxfattribs: Dict = None, doc: Drawing = None) -> Union[Solid,
              Trace, Face3d]
                     Yields faces as SOLID, TRACE or 3DFACE entities with DXF attributes given in dxfattribs.

                     If a document is given, the doc attribute of the new entities  will  be  set  and  the  new
                     entities will be automatically added to the entity database of that document.

                     Parametersdxftype – DXF type as string, “SOLID”, “TRACE” or “3DFACE”

                            • dxfattribs – DXF attributes for SOLID, TRACE or 3DFACE entities

                            • doc – associated document

       class ezdxf.render.trace.CurvedTrace
              2D banded curves like arcs or splines with start- and end width.

              Represents  always  only  one  curved  entity and all miter of curve segments are perpendicular to
              curve tangents.

              Accepts 3D input, but z-axis is ignored.

              faces() -> Iterable[Tuple[Vec2, Vec2, Vec2, Vec2]
                     Yields all faces as 4-tuples of Vec2 objects.

              virtual_entities(dxftype='TRACE', dxfattribs: Dict = None, doc: Drawing = None) -> Union[Solid,
              Trace, Face3d]
                     Yields faces as SOLID, TRACE or 3DFACE entities with DXF attributes given in dxfattribs.

                     If a document is given, the doc attribute of the new entities  will  be  set  and  the  new
                     entities will be automatically added to the entity database of that document.

                     Parametersdxftype – DXF type as string, “SOLID”, “TRACE” or “3DFACE”

                            • dxfattribs – DXF attributes for SOLID, TRACE or 3DFACE entities

                            • doc – associated document

              classmethod from_arc(arc: ezdxf.math.arc.ConstructionArc, start_width: float, end_width: float,
              segments: int = 64) -> ezdxf.render.trace.CurvedTrace
                     Create curved trace from an arc.

                     ParametersarcConstructionArc object

                            • start_width – start width

                            • end_width – end width

                            • segments  –  count of segments for full circle (360 degree) approximation, partial
                              arcs have proportional less segments, but at least 3

                     Raises ValueError – if arc.radius <= 0

              classmethod from_spline(spline: ezdxf.math.bspline.BSpline, start_width: float, end_width: float,
              segments: int) -> ezdxf.render.trace.CurvedTrace
                     Create curved trace from a B-spline.

                     ParameterssplineBSpline object

                            • start_width – start width

                            • end_width – end width

                            • segments – count of segments for approximation

   Path
       This module implements a geometrical Path supported by several render backends, with the goal  to  create
       such  paths  from  LWPOLYLINE, POLYLINE and HATCH boundary paths and send them to the render backend, see
       ezdxf.addons.drawing.

       Minimum common interface:

       •

         matplotlib: PathPatch

                • matplotlib.path.Path() codes:

                • MOVETO

                • LINETO

                • CURVE4 - cubic Bèzier-curve

       •

         PyQt: QPainterPath

                • moveTo()

                • lineTo()

                • cubicTo() - cubic Bèzier-curve

       •

         PyCairo: Context

                • move_to()

                • line_to()

                • curve_to() - cubic Bèzier-curve

       •

         SVG: SVG-Path

                • “M” - absolute move to

                • “L” - absolute line to

                • “C” - absolute cubic Bèzier-curve

       ARC and ELLIPSE entities are approximated by multiple cubic Bézier-curves, which  are  close  enough  for
       display  rendering.  Non-rational  SPLINES  of  3rd  degree  can  be  represented exact as multiple cubic
       Bézier-curves, other B-splines will be approximated.

       class ezdxf.render.path.Path

              start  Path start point, resetting the start point of an empty path is possible.

              end    Path end point.

              is_closed
                     Returns True if the start point is close to the end point.

              classmethod from_lwpolyline(lwpolyline: LWPolyline) -> Path
                     Returns a Path from a LWPolyline entity, all vertices transformed to WCS.

              classmethod from_polyline(polyline: Polyline) -> Path
                     Returns a Path from a Polyline entity, all vertices transformed to WCS.

              classmethod from_spline(spline: Spline, level: int = 4) -> Path
                     Returns a Path from a Spline.

              classmethod from_ellipse(ellipse: Ellipse, segments: int = 1) -> Path
                     Returns a Path from a Ellipse.

              classmethod from_arc(arc: Arc, segments: int = 1) -> Path
                     Returns a Path from an Arc.

              classmethod from_circle(circle: Circle, segments: int = 1) -> Path
                     Returns a Path from a Circle.

              classmethod from_hatch_polyline_path(polyline: PolylinePath, ocs: ezdxf.math.ucs.OCS = None,
              elevation: float = 0) -> Path
                     Returns a Path from a Hatch polyline path.

              classmethod from_hatch_edge_path(edges: EdgePath, ocs: ezdxf.math.ucs.OCS = None, elevation: float
              = 0) -> Path
                     Returns a Path from a Hatch edge path.

              control_vertices()
                     Yields all path control vertices in consecutive order.

              has_clockwise_orientation() -> bool
                     Returns True if 2D path has clockwise orientation, ignores z-axis of all control vertices.

              line_to(location: Vector)
                     Add a line from actual path end point to location.

              curve_to(location: Vector, ctrl1: Vector, ctrl2: Vector)
                     Add a cubic Bèzier-curve from actual path end point to location, ctrl1 and  ctrl2  are  the
                     control points for the cubic Bèzier-curve.

              close() -> None
                     Close path by adding a line segment from the end point to the start point.

              clone() -> Path
                     Returns a new copy of Path with shared immutable data.

              reversed() -> Path
                     Returns a new Path with reversed segments and control vertices.

              clockwise() -> Path
                     Returns new Path in clockwise orientation.

              counter_clockwise() -> Path
                     Returns new Path in counter-clockwise orientation.

              add_curves(curves: Iterable[Bezier4P])
                     Add multiple cubic Bèzier-curves to the path.

                     Auto-detect if the path end point is connected to the start- or end point of the curves, if
                     none  of  them  is close to the path end point a line from the path end point to the curves
                     start point will be added.

              add_ellipse(ellipse: ConstructionEllipse, segments=1)
                     Add an elliptical arc as multiple cubic Bèzier-curves, use from_arc() constructor of  class
                     ConstructionEllipse to add circular arcs.

                     Auto-detect  connection  point,  if  none  is  close  a line from the path end point to the
                     ellipse start point will be added (see add_curves()).

                     By default the start of an empty path is set to the start point  of  the  ellipse,  setting
                     argument reset to False prevents this behavior.

                     Parametersellipse – ellipse parameters as ConstructionEllipse object

                            • segments  –  count of Bèzier-curve segments, at least one segment for each quarter
                              (pi/2), 1 for as few as possible.

                            • reset – set start point to start of ellipse if path is empty

              add_spline(spline: BSpline, level=4)
                     Add a B-spline as multiple cubic Bèzier-curves.

                     Non-rational B-splines of 3rd degree gets a perfect conversion to cubic bezier curves  with
                     a  minimal count of curve segments, all other B-spline require much more curve segments for
                     approximation.

                     Auto-detect connection point, if none is close a line from the path end point to the spline
                     start point will be added (see add_curves()).

                     By default the start of an empty path is set to the start  point  of  the  spline,  setting
                     argument reset to False prevents this behavior.

                     Parametersspline – B-spline parameters as BSpline object

                            • level – subdivision level of approximation segments

                            • reset – set start point to start of spline if path is empty

              transform(m: Matrix44) -> Path
                     Returns a new transformed path.

                     Parameters
                            m – transformation matrix of type Matrix44

              approximate(segments: int) -> Iterable[Vector]
                     Approximate  path  by  vertices,  segments  is the count of approximation segments for each
                     cubic bezier curve.

ADD-ONS

   r12writer
       The fast file/stream writer creates simple DXF R12 drawings with just an ENTITIES  section.  The  HEADER,
       TABLES and BLOCKS sections are not present except FIXED-TABLES are written. Only LINE, CIRCLE, ARC, TEXT,
       POINT,  SOLID,  3DFACE  and POLYLINE entities are supported. FIXED-TABLES is a predefined TABLES section,
       which will be written, if the init argument fixed_tables of R12FastStreamWriter is True.

       The R12FastStreamWriter writes the DXF entities as strings direct  to  the  stream  without  creating  an
       in-memory drawing and therefore the processing is very fast.

       Because  of  the  lack  of  a  BLOCKS section, BLOCK/INSERT can not be used. Layers can be used, but this
       layers have a default setting color = 7  (black/white)  and  linetype  =  'Continuous'.  If  writing  the
       FIXED-TABLES,  some  predefined  text  styles  and  line  types  are available, else text style is always
       'STANDARD' and line type is always 'ByLayer'.

       If using FIXED-TABLES, following predefined line types are available:

       • CONTINUOUS

       • CENTER ____ _ ____ _ ____ _ ____ _ ____ _ ____

       • CENTERX2 ________  __  ________  __  ________

       • CENTER2 ____ _ ____ _ ____ _ ____ _ ____

       • DASHED __ __ __ __ __ __ __ __ __ __ __ __ __ _

       • DASHEDX2 ____  ____  ____  ____  ____  ____

       • DASHED2 _ _ _ _ _ _ _ _ _ _ _ _ _ _

       • PHANTOM ______  __  __  ______  __  __  ______

       • PHANTOMX2 ____________    ____    ____    ____________

       • PHANTOM2 ___ _ _ ___ _ _ ___ _ _ ___ _ _ ___

       • DASHDOT __ . __ . __ . __ . __ . __ . __ . __

       • DASHDOTX2 ____  .  ____  .  ____  .  ____

       • DASHDOT2 _ . _ . _ . _ . _ . _ . _ . _

       • DOT .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .

       • DOTX2 .    .    .    .    .    .    .    .

       • DOT2 . . . . . . . . . . . . . . . . . . .

       • DIVIDE __ . . __ . . __ . . __ . . __ . . __

       • DIVIDEX2 ____  . .  ____  . .  ____  . .  ____

       • DIVIDE2 _ . _ . _ . _ . _ . _ . _ . _

       If using FIXED-TABLES, following predefined text styles are available:

       • OpenSans

       • OpenSansCondensed-Light

       New in version 0.12: Write Binary DXF files.

   Tutorial
       A simple example with different DXF entities:

          from random import random
          from ezdxf.addons import r12writer

          with r12writer("quick_and_dirty_dxf_r12.dxf") as dxf:
              dxf.add_line((0, 0), (17, 23))
              dxf.add_circle((0, 0), radius=2)
              dxf.add_arc((0, 0), radius=3, start=0, end=175)
              dxf.add_solid([(0, 0), (1, 0), (0, 1), (1, 1)])
              dxf.add_point((1.5, 1.5))

              # 2d polyline, new in v0.12
              dxf.add_polyline_2d([(5, 5), (7, 3), (7, 6)])

              # 2d polyline with bulge value, new in v0.12
              dxf.add_polyline_2d([(5, 5), (7, 3, 0.5), (7, 6)], format='xyb')

              # 3d polyline only, changed in v0.12
              dxf.add_polyline([(4, 3, 2), (8, 5, 0), (2, 4, 9)])

              dxf.add_text("test the text entity", align="MIDDLE_CENTER")

       A simple example of writing really many entities in a short time:

          from random import random
          from ezdxf.addons import r12writer

          MAX_X_COORD = 1000.0
          MAX_Y_COORD = 1000.0
          CIRCLE_COUNT = 1000000

          with r12writer("many_circles.dxf") as dxf:
              for i in range(CIRCLE_COUNT):
                  dxf.add_circle((MAX_X_COORD*random(), MAX_Y_COORD*random()), radius=2)

       Show all available line types:

          import ezdxf

          LINETYPES = [
              'CONTINUOUS', 'CENTER', 'CENTERX2', 'CENTER2',
              'DASHED', 'DASHEDX2', 'DASHED2', 'PHANTOM', 'PHANTOMX2',
              'PHANTOM2', 'DASHDOT', 'DASHDOTX2', 'DASHDOT2', 'DOT',
              'DOTX2', 'DOT2', 'DIVIDE', 'DIVIDEX2', 'DIVIDE2',
          ]

          with r12writer('r12_linetypes.dxf', fixed_tables=True) as dxf:
              for n, ltype in enumerate(LINETYPES):
                  dxf.add_line((0, n), (10, n), linetype=ltype)
                  dxf.add_text(ltype, (0, n+0.1), height=0.25, style='OpenSansCondensed-Light')

   Reference
       ezdxf.addons.r12writer.r12writer(stream: Union[TextIO, BinaryIO, str], fixed_tables=False, fmt='asc') ->
       R12FastStreamWriter
              Context manager for writing DXF entities to a stream/file. stream can be any file like object with
              a write() method or just a string for writing DXF entities to the file system.  If fixed_tables is
              True, a standard TABLES section is written in front of the ENTITIES section  and  some  predefined
              text styles and line types can be used.

              New in version 0.12: Set argument fmt to 'asc' to write ASCII DXF file (default) or 'bin' to write
              Binary DXF files.  ASCII DXF require a TextIO stream and Binary DXF require a BinaryIO stream.

       class ezdxf.addons.r12writer.R12FastStreamWriter(stream: [<class 'typing.TextIO'>, <class
       'ezdxf.addons.r12writer.BinaryDXFWriter'>], fixed_tables=False)
              Fast stream writer to create simple DXF R12 drawings.

              Parametersstream – a file like object with a write() method.

                     • fixed_tables  – if fixed_tables is True, a standard TABLES section is written in front of
                       the ENTITIES section and some predefined text styles and line types can be used.

              close() -> None
                     Writes the DXF tail. Call is not necessary when using the context manager r12writer().

              add_line(start: Sequence[float], end: Sequence[float], layer: str = '0', color: int = None,
              linetype: str = None) -> None
                     Add a LINE entity from start to end.

                     Parametersstart – start vertex as (x, y[, z]) tuple

                            • end – end vertex as  as (x, y[, z]) tuple

                            • layer – layer name as string, without a layer definition the assigned  color  =  7
                              (black/white) and line type is 'Continuous'.

                            • color  – color as ACI in the range from 0 to 256, 0 is ByBlock and 256 is ByLayer,
                              default is ByLayer which is  always  color  =  7  (black/white)  without  a  layer
                              definition.

                            • linetype  –  line type as string, if FIXED-TABLES are written some predefined line
                              types  are  available,  else  line  type  is  always  ByLayer,  which  is   always
                              'Continuous' without a LAYERS table.

              add_circle(center: Sequence[float], radius: float, layer: str = '0', color: int = None, linetype:
              str = None) -> None
                     Add a CIRCLE entity.

                     Parameterscenter – circle center point as (x, y) tuple

                            • radius – circle radius as float

                            • layer – layer name as string see add_line()color – color as ACI see add_line()linetype – line type as string see add_line()

              add_arc(center: Sequence[float], radius: float, start: float = 0, end: float = 360, layer: str =
              '0', color: int = None, linetype: str = None) -> None
                     Add an ARC entity. The arc goes counter clockwise from start angle to end angle.

                     Parameterscenter – arc center point as (x, y) tuple

                            • radius – arc radius as float

                            • start – arc start angle in degrees as float

                            • end – arc end angle in degrees as float

                            • layer – layer name as string see add_line()color – color as ACI see add_line()linetype – line type as string see add_line()

              add_point(location: Sequence[float], layer: str = '0', color: int = None, linetype: str = None) ->
              None
                     Add a POINT entity.

                     Parameterslocation – point location as (x, y [,z]) tuple

                            • layer – layer name as string see add_line()color – color as ACI see add_line()linetype – line type as string see add_line()

              add_3dface(vertices: Iterable[Sequence[float]], invisible: int = 0, layer: str = '0', color: int =
              None, linetype: str = None) -> None
                     Add a 3DFACE entity. 3DFACE is a spatial area with 3 or 4 vertices, all vertices have to be
                     in the same plane.

                     Parametersvertices – iterable of 3 or 4 (x, y, z) vertices.

                            • invisible –

                              bit coded flag to define the invisible edges,

                              1. edge = 1

                              2. edge = 2

                              3. edge = 4

                              4. edge = 8

                              Add  edge  values  to set multiple edges invisible, 1. edge + 3. edge = 1 + 4 = 5,
                              all edges = 15

                            • layer – layer name as string see add_line()color – color as ACI see add_line()linetype – line type as string see add_line()

              add_solid(vertices: Iterable[Sequence[float]], layer: str = '0', color: int = None, linetype: str
              = None) -> None
                     Add a SOLID entity. SOLID is a solid filled area with 3 or  4  edges  and  SOLID  is  a  2D
                     entity.

                     Parametersvertices – iterable of 3 or 4 (x, y[, z]) tuples, z-axis will be ignored.

                            • layer – layer name as string see add_line()color – color as ACI see add_line()linetype – line type as string see add_line()

              add_polyline_2d(points: Iterable[Sequence], format: str = 'xy', closed: bool = False, start_width:
              float = 0, end_width: float = 0, layer: str = '0', color: int = None, linetype: str = None) ->
              None
                     Add a 2D POLYLINE entity with start width, end width and bulge value support.

                     Format codes:
                                              ┌───┬──────────────────────────────────┐
                                              │ x │ x-coordinate                     │
                                              ├───┼──────────────────────────────────┤
                                              │ y │ y-coordinate                     │
                                              ├───┼──────────────────────────────────┤
                                              │ s │ start width                      │
                                              ├───┼──────────────────────────────────┤
                                              │ e │ end width                        │
                                              ├───┼──────────────────────────────────┤
                                              │ b │ bulge value                      │
                                              ├───┼──────────────────────────────────┤
                                              │ v │ (x, y) tuple (z-axis is ignored) │
                                              └───┴──────────────────────────────────┘

                     Parameterspoints  –  iterable  of  (x,  y, [start_width, [end_width, [bulge]]]) tuple, value
                              order according to the format string, unset values default to 0format – format: format string, default is 'xy'closedTrue creates a closed polyline

                            • start_width – default start width, default is 0end_width – default end width, default is 0layer – layer name as string see add_line()color – color as ACI see add_line()linetype – line type as string see add_line()

              add_polyline(vertices: Iterable[Sequence[float]], closed: bool = False, layer: str = '0', color:
              int = None, linetype: str = None) -> None
                     Add a 3D POLYLINE entity.

                     Parametersvertices – iterable of (x, y[, z]) tuples, z-axis is 0 by default

                            • closedTrue creates a closed polyline

                            • layer – layer name as string see add_line()color – color as ACI see add_line()linetype – line type as string see add_line()

                     Changed in version 0.12: Write only 3D POLYLINE entity, added closed argument.

              add_polyface(vertices: Iterable[Sequence[float]], faces: Iterable[Sequence[int]], layer: str =
              '0', color: int = None, linetype: str = None) -> None
                     Add a POLYFACE entity. The POLYFACE entity supports only faces of maximum 4 vertices,  more
                     indices will be ignored. A simple square would be:

                        v0 = (0, 0, 0)
                        v1 = (1, 0, 0)
                        v2 = (1, 1, 0)
                        v3 = (0, 1, 0)
                        dxf.add_polyface(vertices=[v0, v1, v2, v3], faces=[(0, 1, 2, 3)])

                     All  3D  form  functions of the ezdxf.render.forms module return MeshBuilder objects, which
                     provide the required vertex and face lists.

                     See sphere example: https://github.com/mozman/ezdxf/blob/master/examples/r12writer.py

                     Parametersvertices – iterable of (x, y, z) tuples

                            • faces – iterable of 3 or 4 vertex indices, indices have to be 0-based

                            • layer – layer name as string see add_line()color – color as ACI see add_line()linetype – line type as string see add_line()

              add_polymesh(vertices: Iterable[Sequence[float]], size: Tuple[int, int], closed=(False, False),
              layer: str = '0', color: int = None, linetype: str = None) -> None
                     Add a POLYMESH entity. A POLYMESH is a mesh of m rows and n columns, each mesh  vertex  has
                     its  own  x-,  y-  and  z coordinates. The mesh can be closed in m- and/or n-direction. The
                     vertices have to be in column order:  (m0, n0), (m0, n1), (m0, n2),  (m1,  n0),  (m1,  n1),
                     (m1, n2), …

                     See example: https://github.com/mozman/ezdxf/blob/master/examples/r12writer.py

                     Parametersvertices – iterable of (x, y, z) tuples, in column order

                            • size – mesh dimension as (m, n)-tuple, requirement: len(vertices) == m*nclosed – (m_closed, n_closed) tuple, for closed mesh in m and/or n direction

                            • layer – layer name as string see add_line()color – color as ACI see add_line()linetype – line type as string see add_line()

              add_text(text: str, insert: Sequence[float] = (0, 0), height: float = 1.0, width: float = 1.0,
              align: str = 'LEFT', rotation: float = 0.0, oblique: float = 0.0, style: str = 'STANDARD', layer:
              str = '0', color: int = None) -> None
                     Add a one line TEXT entity.

                     Parameterstext – the text as string

                            • insert – insert location as (x, y) tuple

                            • height – text height in drawing units

                            • width – text width as factor

                            • align – text alignment, see table below

                            • rotation – text rotation in degrees as float

                            • oblique – oblique in degrees as float, vertical = 0 (default)

                            • style  –  text  style  name as string, if FIXED-TABLES are written some predefined
                              text styles are available, else text style is always 'STANDARD'.

                            • layer – layer name as string see add_line()color – color as ACI see add_line()
                                    ┌────────────┬─────────────┬───────────────┬──────────────┐
                                    │ Vert/Horiz │ Left        │ Center        │ Right        │
                                    ├────────────┼─────────────┼───────────────┼──────────────┤
                                    │ Top        │ TOP_LEFTTOP_CENTERTOP_RIGHT    │
                                    ├────────────┼─────────────┼───────────────┼──────────────┤
                                    │ Middle     │ MIDDLE_LEFTMIDDLE_CENTERMIDDLE_RIGHT │
                                    ├────────────┼─────────────┼───────────────┼──────────────┤
                                    │ Bottom     │ BOTTOM_LEFTBOTTOM_CENTERBOTTOM_RIGHT │
                                    ├────────────┼─────────────┼───────────────┼──────────────┤
                                    │ Baseline   │ LEFTCENTERRIGHT        │
                                    └────────────┴─────────────┴───────────────┴──────────────┘

                     The special alignments ALIGNED and FIT are not available.

   iterdxf
       This add-on allows iterating over entities of the modelspace of really big (> 5GB) DXF files which do not
       fit into memory by only loading one entity at the time. Only ASCII DXF files are supported.

       The entities are regular DXFGraphic objects with access to all supported DXF  attributes,  this  entities
       can  be  written  to  new DXF files created by the IterDXF.export() method.  The new add_foreign_entity()
       method allows also to add this entities to new regular ezdxf drawings (except for the INSERT entity), but
       resources like linetype and style are removed, only  layer  will  be  preserved  but  only  with  default
       attributes like color 7 and linetype CONTINUOUS.

       The  following example shows how to split a big DXF files into several separated DXF files which contains
       only LINE, TEXT or POLYLINE entities.

          from ezdxf.addons import iterdxf

          doc = iterdxf.opendxf('big.dxf')
          line_exporter = doc.export('line.dxf')
          text_exporter = doc.export('text.dxf')
          polyline_exporter = doc.export('polyline.dxf')
          try:
              for entity in doc.modelspace():
                  if entity.dxftype() == 'LINE':
                      line_exporter.write(entity)
                  elif entity.dxftype() == 'TEXT':
                      text_exporter.write(entity)
                  elif entity.dxftype() == 'POLYLINE':
                      polyline_exporter.write(entity)
          finally:
              line_exporter.close()
              text_exporter.close()
              polyline_exporter.close()
              doc.close()

       Supported DXF types:

       3DFACE, ARC, ATTDEF, ATTRIB, CIRCLE, DIMENSION, ELLIPSE,  HATCH,  HELIX,  IMAGE,  INSERT,  LEADER,  LINE,
       LWPOLYLINE, MESH, MLEADER, MLINE, MTEXT, POINT, POLYLINE, RAY, SHAPE, SOLID, SPLINE, TEXT, TRACE, VERTEX,
       WIPEOUT, XLINE

       Transfer  simple  entities  to  another  DXF document, this works for some supported entities, except for
       entities with strong dependencies to the original document like INSERT look at  add_foreign_entity()  for
       all supported types:

          newdoc = ezdxf.new()
          msp = newdoc.modelspace()
          # line is an entity from a big source file
          msp.add_foreign_entity(line)
          # and so on ...
          msp.add_foreign_entity(lwpolyline)
          msp.add_foreign_entity(mesh)
          msp.add_foreign_entity(polyface)

       Transfer  MESH  and  POLYFACE  (dxftype  for  POLYFACE and POLYMESH is POLYLINE!) entities into a new DXF
       document by the MeshTransformer class:

          from ezdxf.render import MeshTransformer

          # mesh is MESH from a big source file
          t = MeshTransformer.from_mesh(mesh)
          # create a new MESH entity from MeshTransformer
          t.render(msp)

          # polyface is POLYFACE from a big source file
          t = MeshTransformer.from_polyface(polyface)
          # create a new POLYMESH entity from MeshTransformer
          t.render_polyface(msp)

       Another way to import entities from a big source file into new DXF documents is to  split  the  big  file
       into smaller parts and use the Importer add-on for a more safe entity import.

       ezdxf.addons.iterdxf.opendxf(filename: str, errors: str = 'surrogateescape') -> IterDXF
              Open  DXF  file  for  iterating,  be sure to open valid DXF files, no DXF structure checks will be
              applied.

              Use this function to split up big DXF files as shown in the example above.

              Parametersfilename – DXF filename of a seekable DXF file.

                     • errors –

                       specify decoding error handler

                       • ”surrogateescape” to preserve possible binary data (default)

                       • ”ignore” to use the replacement char U+FFFD “�” for invalid data

                       • ”strict” to raise an UnicodeDecodeError exception for invalid data

              RaisesDXFStructureError – invalid or incomplete DXF file

                     • UnicodeDecodeError – if errors is “strict” and a decoding error occurs

       ezdxf.addons.iterdxf.modelspace(filename: str, types: Iterable[str] = None, errors: str =
       'surrogateescape') -> Iterable[DXFGraphic]
              Iterate over all modelspace entities as DXFGraphic objects of a seekable file.

              Use this function to iterate “quick” over modelspace entities of a DXF file, filtering  DXF  types
              may speed up things if many entity types will be skipped.

              Parametersfilename – filename of a seekable DXF file

                     • types  –  DXF  types  like  ['LINE', '3DFACE'] which should be returned, None returns all
                       supported types.

                     • errors –

                       specify decoding error handler

                       • ”surrogateescape” to preserve possible binary data (default)

                       • ”ignore” to use the replacement char U+FFFD “�” for invalid data

                       • ”strict” to raise an UnicodeDecodeError exception for invalid data

              RaisesDXFStructureError – invalid or incomplete DXF file

                     • UnicodeDecodeError – if errors is “strict” and a decoding error occurs

       ezdxf.addons.iterdxf.single_pass_modelspace(stream: BinaryIO, types: Iterable[str] = None, errors: str =
       'surrogateescape') -> Iterable[DXFGraphic]
              Iterate over all modelspace entities as DXFGraphic objects in one single pass.

              Use this function to ‘quick’ iterate over modelspace entities of a not seekable binary DXF stream,
              filtering DXF types may speed up things if many entity types will be skipped.

              Parametersstream – (not seekable) binary DXF stream

                     • types – DXF types like ['LINE', '3DFACE'] which should  be  returned,  None  returns  all
                       supported types.

                     • errors –

                       specify decoding error handler

                       • ”surrogateescape” to preserve possible binary data (default)

                       • ”ignore” to use the replacement char U+FFFD “�” for invalid data

                       • ”strict” to raise an UnicodeDecodeError exception for invalid data

              RaisesDXFStructureError – Invalid or incomplete DXF file

                     • UnicodeDecodeError – if errors is “strict” and a decoding error occurs

       class ezdxf.addons.iterdxf.IterDXF

              export(name: str) -> IterDXFWriter
                     Returns  a companion object to export parts from the source DXF file into another DXF file,
                     the new file will have the same HEADER, CLASSES, TABLES, BLOCKS and OBJECTS sections, which
                     guarantees all necessary dependencies are present in the new file.

                     Parameters
                            name – filename, no special requirements

              modelspace(types: Iterable[str] = None) -> Iterable[DXFGraphic]
                     Returns an iterator for all supported DXF entities in the modelspace.  These  entities  are
                     regular DXFGraphic objects but without a valid document assigned. It is not possible to add
                     these entities to other ezdxf documents.

                     It  is only possible to recreate the objects by factory functions base on attributes of the
                     source entity.  For MESH, POLYMESH and POLYFACE it is possible to use  the  MeshTransformer
                     class to render (recreate) this objects as new entities in another document.

                     Parameters
                            types – DXF types like ['LINE', '3DFACE'] which should be returned, None returns all
                            supported types.

              close()
                     Safe closing source DXF file.

       class ezdxf.addons.iterdxf.IterDXFWriter

              write(entity: DXFGraphic)
                     Write a DXF entity from the source DXF file to the export file.

                     Don’t  write  entities  from different documents than the source DXF file, dependencies and
                     resources will not match, maybe it will work once, but not in a reliable way for  different
                     DXF documents.

              close()
                     Safe  closing  of exported DXF file. Copying of OBJECTS section happens only at closing the
                     file, without closing the new DXF file is invalid.

   Importer
       This add-on is meant to import graphical entities from another  DXF  drawing  and  their  required  table
       entries like LAYER, LTYPE or STYLE.

       Because of complex extensibility of the DXF format and the lack of sufficient documentation, I decided to
       remove  most  of  the  possible  source  drawing  dependencies from imported entities, therefore imported
       entities may not look the same as the original entities in the source drawing, but at least the  geometry
       should be the same and the DXF file does not break.

       Removed data which could contain source drawing dependencies: Extension Dictionaries, AppData and XDATA.

       WARNING:
          DON’T EXPECT PERFECT RESULTS!

       The Importer supports following data import:

          • entities  which  are  really  safe  to import: LINE, POINT, CIRCLE, ARC, TEXT, SOLID, TRACE, 3DFACE,
            SHAPE, POLYLINE, ATTRIB, ATTDEF, INSERT, ELLIPSE, MTEXT, LWPOLYLINE,  SPLINE,  HATCH,  MESH,  XLINE,
            RAY, DIMENSION, LEADER, VIEWPORT

          • table and table entry import is restricted to LAYER, LTYPE, STYLE, DIMSTYLE

          • import of BLOCK definitions is supported

          • import of paper space layouts is supported

       Import of DXF objects from the OBJECTS section is not supported.

       DIMSTYLE override for entities DIMENSION and LEADER is not supported.

       Example:

          import ezdxf
          from ezdxf.addons import Importer

          sdoc = ezdxf.readfile('original.dxf')
          tdoc = ezdxf.new()

          importer = Importer(sdoc, tdoc)

          # import all entities from source modelspace into modelspace of the target drawing
          importer.import_modelspace()

          # import all paperspace layouts from source drawing
          importer.import_paperspace_layouts()

          # import all CIRCLE and LINE entities from source modelspace into an arbitrary target layout.
          # create target layout
          tblock = tdoc.blocks.new('SOURCE_ENTS')
          # query source entities
          ents = sdoc.modelspace().query('CIRCLE LINE')
          # import source entities into target block
          importer.import_entities(ents, tblock)

          # This is ALWAYS the last & required step, without finalizing the target drawing is maybe invalid!
          # This step imports all additional required table entries and block definitions.
          importer.finalize()

          tdoc.saveas('imported.dxf')

       class ezdxf.addons.importer.Importer(source: Drawing, target: Drawing)
              The Importer class is central element for importing data from other DXF drawings.

              Parameterssource – source Drawingtarget – target Drawing

              Variablessource – source drawing

                     • target – target drawing

                     • used_layer  –  Set  of  used layer names as string, AutoCAD accepts layer names without a
                       LAYER table entry.

                     • used_linetypes – Set of used linetype names as string, these linetypes  require  a  TABLE
                       entry or AutoCAD will crash.

                     • used_styles  –  Set  of used text style names, these text styles require a TABLE entry or
                       AutoCAD will crash.

                     • used_dimstyles – Set of used dimension style names,  these  dimension  styles  require  a
                       TABLE entry or AutoCAD will crash.

              finalize() -> None
                     Finalize  import  by  importing  required  table  entries  and  block  definition,  without
                     finalization the target drawing is maybe invalid fore AutoCAD. Call finalize() as last step
                     of the import process.

              import_block(block_name: str, rename=True) -> str
                     Import one block definition. If block already exist the block will be renamed  if  argument
                     rename  is  True,  else the existing target block will be used instead of the source block.
                     Required  name  resolving  for  imported  block  references  (INSERT),  will  be  done   in
                     Importer.finalize().

                     To  replace  an  existing  block  in  the  target drawing, just delete it before importing:
                     target.blocks.delete_block(block_name, safe=False)

                     Parametersblock_name – name of block to import

                            • rename – rename block if exists in target drawing

                     Returns: block name (renamed)

                     Raises ValueError – source block not found

              import_blocks(block_names: Iterable[str], rename=False) -> None
                     Import all block definitions. If block already exist the block will be renamed if  argument
                     rename  is  True,  else the existing target block will be used instead of the source block.
                     Required  name  resolving  for  imported  block  references  (INSERT),  will  be  done   in
                     Importer.finalize().

                     Parametersblock_names – names of blocks to import

                            • rename – rename block if exists in target drawing

                     Raises ValueError – source block not found

              import_entities(entities: Iterable[DXFEntity], target_layout: BaseLayout = None) -> None
                     Import  all  entities  into  target_layout  or  the  modelspace  of  the target drawing, if
                     target_layout is None.

                     Parametersentities – Iterable of DXF entities

                            • target_layout – any layout (modelspace,  paperspace  or  block)  from  the  target
                              drawing

                     Raises DXFStructureErrortarget_layout is not a layout of target drawing

              import_entity(entity: DXFEntity, target_layout: BaseLayout = None) -> None
                     Imports  a single DXF entity into target_layout or the modelspace of the target drawing, if
                     target_layout is None.

                     Parametersentity – DXF entity to import

                            • target_layout – any layout (modelspace,  paperspace  or  block)  from  the  target
                              drawing

                     Raises DXFStructureErrortarget_layout is not a layout of target drawing

              import_modelspace(target_layout: BaseLayout = None) -> None
                     Import  all  entities  from  source  modelspace into target_layout or the modelspace of the
                     target drawing, if target_layout is None.

                     Parameters
                            target_layout – any layout (modelspace, paperspace or block) from the target drawing

                     Raises DXFStructureErrortarget_layout is not a layout of target drawing

              import_paperspace_layout(name: str) -> Layout
                     Import paperspace layout name into target drawing. Recreates the source  paperspace  layout
                     in the target drawing, renames the target paperspace if already a paperspace with same name
                     exist and imports all entities from source paperspace into target paperspace.

                     Parameters
                            name – source paper space name as string

                     Returns: new created target paperspace Layout

                     RaisesKeyError – source paperspace does not exist

                            • DXFTypeError – invalid modelspace import

              import_paperspace_layouts() -> None
                     Import all paperspace layouts and their content into target drawing. Target layouts will be
                     renamed  if already a layout with same name exist. Layouts will be imported in original tab
                     order.

              import_table(name: str, entries: Union[str, Iterable[str]] = '*', replace=False) -> None
                     Import specific table entries from source drawing into target drawing.

                     Parametersname – valid table names are layers, linetypes and stylesentries – Iterable of table names as strings, or a single table name or * for  all
                              table entries

                            • replace – True to replace already existing table entry else ignore existing entry

                     Raises TypeError – unsupported table type

              import_tables(table_names: Union[str, Iterable[str]] = '*', replace=False) -> None
                     Import DXF tables from source drawing into target drawing.

                     Parameterstable_names  –  iterable  of  tables  names  as strings, or a single table name as
                              string or * for all supported tables

                            • replace – True to replace already existing  table  entries  else  ignore  existing
                              entries

                     Raises TypeError – unsupported table type

              recreate_source_layout(name: str) -> Layout
                     Recreate source paperspace layout name in the target drawing. The layout will be renamed if
                     name  already  exist  in  the  target  drawing.  Returns  target modelspace for layout name
                     “Model”.

                     Parameters
                            name – layout name as string

                     Raises KeyError – if source layout name not exist

   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')

   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 PyQt5 (QGraphicsScene based) and Matplotlib backend 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
       • Line types and hatch patterns/gradients are ignored

       • 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

       • No support for MULTILEADER

       • The style which POINT entities are drawn in are not stored in the dxf file and so cannot be  replicated
         exactly

       • only basic support for:

         • infinite lines (rendered as lines with a finite length)

         • hatches with holes (holes are rendered filled)

         • viewports (rendered as rectangles)

         • 3D  (some  entities  may  not display correctly in 3D (see possible improvements below)) however many
           things should already work in 3D.

         • vertical text (will render as horizontal text)

         • multiple columns of text (placement of additional columns may be incorrect)

   Future Possible Improvements
       • pass the font to backend if available

       • deal with nested polygons/hatches by triangulating them: Triangulation

       • both the matplotlib and pyqt backends  have  built-in  support  for  rendering  hatched  patterns  (see
         MatplotlibHatch  and  QtBrushHatch)  so  the interface could pass that information through or query the
         backend to determine whether it automatically supports complex drawing commands such  as  hatching,  or
         whether the frontend should break the shape into simpler commands (i.e. calculate and draw each line of
         a hatch)

       • text  formatting  commands  could  be interpreted and broken into text chunks which can be drawn with a
         single font weight or modification such as italics

   dxf2code
       Translate DXF entities and structures into Python source code.

       Short example:

          import ezdxf
          from ezdxf.addons.dxf2code import entities_to_code, block_to_code

          doc = ezdxf.readfile('original.dxf')
          msp = doc.modelspace()
          source = entities_to_code(msp)

          # create source code for a block definition
          block_source = block_to_code(doc.blocks['MyBlock'])

          # merge source code objects
          source.merge(block_source)

          with open('source.py', mode='wt') as f:
              f.write(source.import_str())
              f.write('\n\n')
              f.write(source.code_str())
              f.write('\n')

       ezdxf.addons.dxf2code.entities_to_code(entities: Iterable[DXFEntity], layout: str = 'layout', ignore:
       Iterable[str] = None) -> Code
              Translates DXF entities into Python source code to recreate this entities by ezdxf.

              Parametersentities – iterable of DXFEntity

                     • layout – variable name of the layout (model space or block) as string

                     • ignore – iterable of entities types to ignore as strings like ['IMAGE', 'DIMENSION']

              Returns
                     Code

       ezdxf.addons.dxf2code.block_to_code(block: BlockLayout, drawing: str = 'doc', ignore: Iterable[str] =
       None) -> Code
              Translates a BLOCK into Python source code to recreate the BLOCK by ezdxf.

              Parametersblock – block definition layout

                     • drawing – variable name of the drawing as string

                     • ignore – iterable of entities types to ignore as strings like [‘IMAGE’, ‘DIMENSION’]

              Returns
                     Code

       ezdxf.addons.dxf2code.table_entries_to_code(entities: Iterable[DXFEntity], drawing='doc') -> Code

       class ezdxf.addons.dxf2code.Code
              Source code container.

              code   Source code line storage, store lines without line ending \\n

              imports
                     source code line storage for global imports, store lines without line ending \\n

              layers Layers used by the generated source code, AutoCAD accepts layer names without a LAYER table
                     entry.

              linetypes
                     Linetypes used by the generated source code, these  linetypes  require  a  TABLE  entry  or
                     AutoCAD will crash.

              styles Text  styles  used by the generated source code, these text styles require a TABLE entry or
                     AutoCAD will crash.

              dimstyles
                     Dimension styles  used by the generated source code, these dimension styles require a TABLE
                     entry or AutoCAD will crash.

              blocks Blocks used by the generated source code, these blocks require a BLOCK  definition  in  the
                     BLOCKS section or AutoCAD will crash.

              code_str(indent: int = 0) -> str
                     Returns the source code as a single string.

                     Parameters
                            indent – source code indentation count by spaces

              import_str(indent: int = 0) -> str
                     Returns required imports as a single string.

                     Parameters
                            indent – source code indentation count by spaces

              merge(code: ezdxf.addons.dxf2code.Code, indent: int = 0) -> None
                     Add another Code object.

              add_import(statement: str) -> None
                     Add import statement, identical import statements are merged together.

              add_line(code: str, indent: int = 0) -> None
                     Add a single source code line without line ending \n.

              add_lines(code: Iterable[str], indent: int = 0) -> None
                     Add multiple source code lines without line ending \n.

   Plot Style Files (CTB/STB)
       CTB and STB files store plot styles used by AutoCAD and BricsCAD for printing and plotting.

       If  the  plot style table is attached to a Paperspace or the Modelspace, a change of a plot style affects
       any object that uses that plot style. CTB files contain color dependent  plot  style  tables,  STB  files
       contain named plot style tables.

       SEE ALSO:Using plot style tables in AutoCADAutoCAD Plot Style Table EditorBricsCAD Plot Style Table Editor

          • AUTODESK KNOWLEDGE NETWORK: How to install CTB files in AutoCAD

       ezdxf.addons.acadctb.load(filename: str) -> Union[ColorDependentPlotStyles, NamedPlotStyles]
              Load the CTB or STB file filename from file system.

       ezdxf.addons.acadctb.new_ctb() -> ColorDependentPlotStyles
              Create a new CTB file.

              Changed in version 0.10: renamed from new()

       ezdxf.addons.acadctb.new_stb() -> NamedPlotStyles
              Create a new STB file.

              New in version 0.10.

   ColorDependentPlotStyles
       Color dependent plot style table (CTB file), table entries are PlotStyle objects.

       class ezdxf.addons.acadctb.ColorDependentPlotStyles

              description
                     Custom description of plot style file.

              scale_factor
                     Specifies the factor by which to scale non-ISO linetypes and fill patterns.

              apply_factor
                     Specifies whether or not you want to apply the scale_factor.

              custom_lineweight_display_units
                     Set  1  for  showing  lineweight  in inch in AutoCAD CTB editor window, but lineweights are
                     always defined in millimeters.

              lineweights
                     Lineweights table as array.array

              __getitem__(aci: int) -> PlotStyle
                     Returns PlotStyle for ACI aci.

              __iter__() -> Iterable[PlotStyle]
                     Iterable of all plot styles.

              new_style(aci: int, data: dict = None) -> PlotStyle
                     Set aci to new attributes defined by data dict.

                     Parametersaci – ACI

                            • datadict of  PlotStyle  attributes:  description,  color,  physical_pen_number,
                              virtual_pen_number,   screen,   linepattern_size,   linetype,   adaptive_linetype,
                              lineweight, end_style, join_style, fill_style

              get_lineweight(aci: int)
                     Returns the assigned lineweight for PlotStyle aci in millimeter.

              get_lineweight_index(lineweight: float) -> int
                     Get index of lineweight in the lineweight table or append lineweight to lineweight table.

              get_table_lineweight(index: int) -> float
                     Returns lineweight in millimeters of lineweight table entry index.

                     Parameters
                            index – lineweight table index = PlotStyle.lineweight

                     Returns
                            lineweight in mm or 0.0 for use entity lineweight

              set_table_lineweight(index: int, lineweight: float) -> int
                     Argument index is the lineweight table index, not the ACI.

                     Parametersindex – lineweight table index = PlotStyle.lineweightlineweight – in millimeters

              save(filename: str) -> None
                     Save CTB file as filename to the file system.

              write(stream: BinaryIO) -> None
                     Compress and write CTB file to binary stream.

   NamedPlotStyles
       Named plot style table (STB file), table entries are PlotStyle objects.

       class ezdxf.addons.acadctb.NamedPlotStyles

              description
                     Custom description of plot style file.

              scale_factor
                     Specifies the factor by which to scale non-ISO linetypes and fill patterns.

              apply_factor
                     Specifies whether or not you want to apply the scale_factor.

              custom_lineweight_display_units
                     Set 1 for showing lineweight in inch in AutoCAD CTB  editor  window,  but  lineweights  are
                     always defined in millimeters.

              lineweights
                     Lineweights table as array.array

              __getitem__(name: str) -> PlotStyle
                     Returns PlotStyle by name.

              __delitem__(name: str)
                     Delete plot style name. Plot style 'Normal' is not deletable.

              __iter__() -> Iterable[str]
                     Iterable of all plot style names.

              new_style(name: str, localized_name: str = None, data: dict = None) -> PlotStyle
                     Create  new  class:PlotStyle name by attribute dict data, replaces existing class:PlotStyle
                     objects.

                     Parametersname – plot style name

                            • localized_name – name shown in plot style editor, uses name if Nonedatadict of  PlotStyle  attributes:  description,  color,  physical_pen_number,
                              virtual_pen_number,   screen,   linepattern_size,   linetype,   adaptive_linetype,
                              lineweight, end_style, join_style, fill_style

              get_lineweight(name: str)
                     Returns the assigned lineweight for PlotStyle name in millimeter.

              get_lineweight_index(lineweight: float) -> int
                     Get index of lineweight in the lineweight table or append lineweight to lineweight table.

              get_table_lineweight(index: int) -> float
                     Returns lineweight in millimeters of lineweight table entry index.

                     Parameters
                            index – lineweight table index = PlotStyle.lineweight

                     Returns
                            lineweight in mm or 0.0 for use entity lineweight

              set_table_lineweight(index: int, lineweight: float) -> int
                     Argument index is the lineweight table index, not the ACI.

                     Parametersindex – lineweight table index = PlotStyle.lineweightlineweight – in millimeters

              save(filename: str) -> None
                     Save STB file as filename to the file system.

              write(stream: BinaryIO) -> None
                     Compress and write STB file to binary stream.

   PlotStyle
       class ezdxf.addons.acadctb.PlotStyle

              index  Table index (0-based). (int)

              aci    ACI in range from 1 to 255. Has no meaning for named plot styles. (int)

              description
                     Custom description of plot style. (str)

              physical_pen_number
                     Specifies physical plotter pen, valid range from 1 to 32 or AUTOMATIC. (int)

              virtual_pen_number
                     Only used by non-pen plotters and only if they are configured for virtual pens. valid range
                     from 1 to 255 or AUTOMATIC. (int)

              screen Specifies the color intensity of the plot on the paper, valid range is from 0 to 100. (int)

                     If you select 100 the drawing will plotted with its full  color  intensity.  In  order  for
                     screening to work, the dithering option must be active.

              linetype
                     Overrides the entity linetype, default value is OBJECT_LINETYPE. (bool)

              adaptive_linetype
                     True  if  a  complete  linetype  pattern is more important than a correct linetype scaling,
                     default is True. (bool)

              linepattern_size
                     Line pattern size, default = 0.5. (float)

              lineweight
                     Overrides the entity lineWEIGHT, default value is OBJECT_LINEWEIGHT. This is an index  into
                     the UserStyles.lineweights table. (int)

              end_style
                     Line end cap style, see table below, default is END_STYLE_OBJECT (int)

              join_style
                     Line join style, see table below, default is JOIN_STYLE_OBJECT (int)

              fill_style
                     Line fill style, see table below, default is FILL_STYLE_OBJECT (int)

              dithering
                     Depending  on  the capabilities of your plotter, dithering approximates the colors with dot
                     patterns.  When this option is False, the colors are mapped to the nearest color, resulting
                     in a smaller range of colors when plotting.

                     Dithering is available only whether you select the object’s color or assign  a  plot  style
                     color.

              grayscale
                     Plot colors in grayscale. (bool)

   Default Line Weights
                                                    ┌────┬──────┐
                                                    │ #  │ [mm] │
                                                    ├────┼──────┤
                                                    │ 0  │ 0.00 │
                                                    ├────┼──────┤
                                                    │ 1  │ 0.05 │
                                                    ├────┼──────┤
                                                    │ 2  │ 0.09 │
                                                    ├────┼──────┤
                                                    │ 3  │ 0.10 │
                                                    ├────┼──────┤
                                                    │ 4  │ 0.13 │
                                                    ├────┼──────┤
                                                    │ 5  │ 0.15 │
                                                    ├────┼──────┤
                                                    │ 6  │ 0.18 │
                                                    ├────┼──────┤
                                                    │ 7  │ 0.20 │
                                                    ├────┼──────┤
                                                    │ 8  │ 0.25 │
                                                    ├────┼──────┤
                                                    │ 9  │ 0.30 │
                                                    ├────┼──────┤
                                                    │ 10 │ 0.35 │
                                                    ├────┼──────┤
                                                    │ 11 │ 0.40 │
                                                    ├────┼──────┤
                                                    │ 12 │ 0.45 │
                                                    ├────┼──────┤
                                                    │ 13 │ 0.50 │
                                                    ├────┼──────┤
                                                    │ 14 │ 0.53 │
                                                    ├────┼──────┤
                                                    │ 15 │ 0.60 │
                                                    ├────┼──────┤
                                                    │ 16 │ 0.65 │
                                                    ├────┼──────┤
                                                    │ 17 │ 0.70 │
                                                    ├────┼──────┤
                                                    │ 18 │ 0.80 │
                                                    ├────┼──────┤
                                                    │ 19 │ 0.90 │
                                                    ├────┼──────┤
                                                    │ 20 │ 1.00 │
                                                    ├────┼──────┤
                                                    │ 21 │ 1.06 │
                                                    ├────┼──────┤
                                                    │ 22 │ 1.20 │
                                                    ├────┼──────┤
                                                    │ 23 │ 1.40 │
                                                    ├────┼──────┤
                                                    │ 24 │ 1.58 │
                                                    ├────┼──────┤
                                                    │ 25 │ 2.00 │
                                                    ├────┼──────┤
                                                    │ 26 │ 2.11 │
                                                    └────┴──────┘

   Predefined Values
       ezdxf.addons.acadctb.AUTOMATIC

       ezdxf.addons.acadctb.OBJECT_LINEWEIGHT

       ezdxf.addons.acadctb.OBJECT_LINETYPE

       ezdxf.addons.acadctb.OBJECT_COLOR

       ezdxf.addons.acadctb.OBJECT_COLOR2

   Line End Style
       [image]
                                              ┌───────────────────┬───┐
                                              │ END_STYLE_BUTT    │ 0 │
                                              ├───────────────────┼───┤
                                              │ END_STYLE_SQUARE  │ 1 │
                                              ├───────────────────┼───┤
                                              │ END_STYLE_ROUND   │ 2 │
                                              ├───────────────────┼───┤
                                              │ END_STYLE_DIAMOND │ 3 │
                                              ├───────────────────┼───┤
                                              │ END_STYLE_OBJECT  │ 4 │
                                              └───────────────────┴───┘

   Line Join Style
       [image]
                                              ┌────────────────────┬───┐
                                              │ JOIN_STYLE_MITER   │ 0 │
                                              ├────────────────────┼───┤
                                              │ JOIN_STYLE_BEVEL   │ 1 │
                                              ├────────────────────┼───┤
                                              │ JOIN_STYLE_ROUND   │ 2 │
                                              ├────────────────────┼───┤
                                              │ JOIN_STYLE_DIAMOND │ 3 │
                                              ├────────────────────┼───┤
                                              │ JOIN_STYLE_OBJECT  │ 5 │
                                              └────────────────────┴───┘

   Fill Style
       [image]
                                         ┌────────────────────────────┬────┐
                                         │ FILL_STYLE_SOLID           │ 64 │
                                         ├────────────────────────────┼────┤
                                         │ FILL_STYLE_CHECKERBOARD    │ 65 │
                                         ├────────────────────────────┼────┤
                                         │ FILL_STYLE_CROSSHATCH      │ 66 │
                                         ├────────────────────────────┼────┤
                                         │ FILL_STYLE_DIAMONDS        │ 67 │
                                         ├────────────────────────────┼────┤
                                         │ FILL_STYLE_HORIZONTAL_BARS │ 68 │
                                         ├────────────────────────────┼────┤
                                         │ FILL_STYLE_SLANT_LEFT      │ 69 │
                                         ├────────────────────────────┼────┤
                                         │ FILL_STYLE_SLANT_RIGHT     │ 70 │
                                         ├────────────────────────────┼────┤
                                         │ FILL_STYLE_SQUARE_DOTS     │ 71 │
                                         ├────────────────────────────┼────┤
                                         │ FILL_STYLE_VERICAL_BARS    │ 72 │
                                         ├────────────────────────────┼────┤
                                         │ FILL_STYLE_OBJECT          │ 73 │
                                         └────────────────────────────┴────┘

   Linetypes
       [image] [image]
                                    ┌───────────────────────────────────┬───────┐
                                    │ Linetype name                     │ Value │
                                    ├───────────────────────────────────┼───────┤
                                    │ Solid                             │ 0     │
                                    ├───────────────────────────────────┼───────┤
                                    │ Dashed                            │ 1     │
                                    ├───────────────────────────────────┼───────┤
                                    │ Dotted                            │ 2     │
                                    ├───────────────────────────────────┼───────┤
                                    │ Dash Dot                          │ 3     │
                                    ├───────────────────────────────────┼───────┤
                                    │ Short Dash                        │ 4     │
                                    ├───────────────────────────────────┼───────┤
                                    │ Medium Dash                       │ 5     │
                                    ├───────────────────────────────────┼───────┤
                                    │ Long Dash                         │ 6     │
                                    ├───────────────────────────────────┼───────┤
                                    │ Short Dash x2                     │ 7     │
                                    ├───────────────────────────────────┼───────┤
                                    │ Medium Dash x2                    │ 8     │
                                    ├───────────────────────────────────┼───────┤
                                    │ Long Dash x2                      │ 9     │
                                    ├───────────────────────────────────┼───────┤
                                    │ Medium Lang Dash                  │ 10    │
                                    ├───────────────────────────────────┼───────┤
                                    │ Medium Dash Short Dash Short Dash │ 11    │
                                    ├───────────────────────────────────┼───────┤
                                    │ Long Dash Short Dash              │ 12    │
                                    ├───────────────────────────────────┼───────┤
                                    │ Long Dash Dot Dot                 │ 13    │
                                    ├───────────────────────────────────┼───────┤
                                    │ Long Dash Dot                     │ 14    │
                                    ├───────────────────────────────────┼───────┤
                                    │ Medium Dash Dot Short Dash Dot    │ 15    │
                                    ├───────────────────────────────────┼───────┤
                                    │ Sparse Dot                        │ 16    │
                                    ├───────────────────────────────────┼───────┤
                                    │ ISO Dash                          │ 17    │
                                    ├───────────────────────────────────┼───────┤
                                    │ ISO Dash Space                    │ 18    │
                                    ├───────────────────────────────────┼───────┤
                                    │ ISO Long Dash Dot                 │ 19    │
                                    ├───────────────────────────────────┼───────┤
                                    │ ISO Long Dash Double Dot          │ 20    │
                                    ├───────────────────────────────────┼───────┤
                                    │ ISO Long Dash Triple Dot          │ 21    │
                                    ├───────────────────────────────────┼───────┤
                                    │ ISO Dot                           │ 22    │
                                    ├───────────────────────────────────┼───────┤
                                    │ ISO Long Dash Short Dash          │ 23    │
                                    ├───────────────────────────────────┼───────┤
                                    │ ISO Long Dash Double Short Dash   │ 24    │
                                    ├───────────────────────────────────┼───────┤
                                    │ ISO Dash Dot                      │ 25    │
                                    ├───────────────────────────────────┼───────┤
                                    │ ISO Double Dash Dot               │ 26    │
                                    ├───────────────────────────────────┼───────┤
                                    │ ISO Dash Double Dot               │ 27    │
                                    ├───────────────────────────────────┼───────┤
                                    │ ISO Double Dash Double Dot        │ 28    │
                                    ├───────────────────────────────────┼───────┤
                                    │ ISO Dash Triple Dot               │ 29    │
                                    ├───────────────────────────────────┼───────┤
                                    │ ISO Double Dash Triple Dot        │ 30    │
                                    ├───────────────────────────────────┼───────┤
                                    │ Use entity linetype               │ 31    │
                                    └───────────────────────────────────┴───────┘

   PyCSG
       Constructive  Solid  Geometry  (CSG)  is a modeling technique that uses Boolean operations like union and
       intersection to combine 3D solids. This  library  implements  CSG  operations  on  meshes  elegantly  and
       concisely  using  BSP  trees,  and  is  meant  to serve as an easily understandable implementation of the
       algorithm. All edge cases involving overlapping coplanar polygons in both solids are correctly handled.

       New in version 0.11.

       Example for usage:

          import ezdxf
          from ezdxf.render.forms import cube, cylinder_2p
          from ezdxf.addons.pycsg import CSG

          # create new DXF document
          doc = ezdxf.new()
          msp = doc.modelspace()

          # create same geometric primitives as MeshTransformer() objects
          cube1 = cube()
          cylinder1 = cylinder_2p(count=32, base_center=(0, -1, 0), top_center=(0, 1, 0), radius=.25)

          # build solid union
          union = CSG(cube1) + CSG(cylinder1)
          # convert to mesh and render mesh to modelspace
          union.mesh().render(msp, dxfattribs={'color': 1})

          # build solid difference
          difference = CSG(cube1) - CSG(cylinder1)
          # convert to mesh, translate mesh and render mesh to modelspace
          difference.mesh().translate(1.5).render(msp, dxfattribs={'color': 3})

          # build solid intersection
          intersection = CSG(cube1) * CSG(cylinder1)
          # convert to mesh, translate mesh and render mesh to modelspace
          intersection.mesh().translate(2.75).render(msp, dxfattribs={'color': 5})

          doc.saveas('csg.dxf')
       [image: Cube vs Cylinder] [image]

       This CSG kernel supports only meshes as MeshBuilder objects, which can be created from and  converted  to
       DXF Mesh entities.

       This CSG kernel is not compatible with ACIS objects like Solid3d, Body, Surface or Region.

       NOTE:
          This  is  a pure Python implementation, don’t expect great performance and the implementation is based
          on an unbalanced BSP tree, so in the case of RecursionError, increase the recursion limit:

              import sys

              actual_limit = sys.getrecursionlimit()
              # default is 1000, increasing too much may cause a seg fault
              sys.setrecursionlimit(10000)

              ...  # do the CSG stuff

              sys.setrecursionlimit(actual_limit)

       CSG works also with spheres, but  with  really  bad  runtime  behavior  and  most  likely  RecursionError
       exceptions, and use quadrilaterals as body faces to reduce face count by setting argument quads to True.

          import ezdxf

          from ezdxf.render.forms import sphere, cube
          from ezdxf.addons.pycsg import CSG

          doc = ezdxf.new()
          doc.set_modelspace_vport(6, center=(5, 0))
          msp = doc.modelspace()

          cube1 = cube().translate(-.5, -.5, -.5)
          sphere1 = sphere(count=32, stacks=16, radius=.5, quads=True)

          union = (CSG(cube1) + CSG(sphere1)).mesh()
          union.render(msp, dxfattribs={'color': 1})

          subtract = (CSG(cube1) - CSG(sphere1)).mesh().translate(2.5)
          subtract.render(msp, dxfattribs={'color': 3})

          intersection = (CSG(cube1) * CSG(sphere1)).mesh().translate(4)
          intersection.render(msp, dxfattribs={'color': 5})
       [image: Cube vs Sphere] [image]

       Hard Core CSG - Menger Sponge Level 3 vs Sphere

       Required  runtime  on  an old Xeon E5-1620 Workstation @ 3.60GHz, with default recursion limit of 1000 on
       Windows 10:

          • CPython 3.8.1 64bit: ~60 seconds,

          • pypy3 [PyPy 7.2.0] 32bit: ~6 seconds, and using __slots__ reduced runtime below  5  seconds,  yes  -
            pypy is worth a look for long running scripts!

          from ezdxf.render.forms import sphere
          from ezdxf.addons import MengerSponge
          from ezdxf.addons.pycsg import CSG

          doc = ezdxf.new()
          doc.layers.new('sponge', dxfattribs={'color': 5})
          doc.layers.new('sphere', dxfattribs={'color': 6})

          doc.set_modelspace_vport(6, center=(5, 0))
          msp = doc.modelspace()

          sponge1 = MengerSponge(level=3).mesh()
          sphere1 = sphere(count=32, stacks=16, radius=.5, quads=True).translate(.25, .25, 1)

          subtract = (CSG(sponge1, meshid=1) - CSG(sphere1, meshid=2))
          # get mesh result by id
          subtract.mesh(1).render(msp, dxfattribs={'layer': 'sponge'})
          subtract.mesh(2).render(msp, dxfattribs={'layer': 'sphere'})
       [image: Menger Sponge vs Sphere] [image]

   CSG Class
       class ezdxf.addons.pycsg.CSG(mesh: MeshBuilder, meshid: int = 0)
              Constructive  Solid Geometry (CSG) is a modeling technique that uses Boolean operations like union
              and intersection to combine 3D solids. This class implements CSG operations on meshes.

              New 3D solids are created from MeshBuilder objects and results can be exported as  MeshTransformer
              objects to ezdxf by method mesh().

              Parametersmeshezdxf.render.MeshBuilder or inherited object

                     • meshid – individual mesh ID to separate result meshes, 0 is default

              mesh(meshid: int = 0) -> MeshTransformer
                     Returns a ezdxf.render.MeshTransformer object.

                     Parameters
                            meshid – individual mesh ID, 0 is default

              union(other: CSG) -> CSG
                     Return  a  new  CSG  solid  representing  space in either this solid or in the solid other.
                     Neither this solid nor the solid other are modified:

                        A.union(B)

                        +-------+            +-------+
                        |       |            |       |
                        |   A   |            |       |
                        |    +--+----+   =   |       +----+
                        +----+--+    |       +----+       |
                             |   B   |            |       |
                             |       |            |       |
                             +-------+            +-------+

              __add__(other: CSG) -> CSG

                        union = A + B

              subtract(other: CSG) -> CSG
                     Return a new CSG solid representing space in this solid but not in the solid other. Neither
                     this solid nor the solid other are modified:

                        A.subtract(B)

                        +-------+            +-------+
                        |       |            |       |
                        |   A   |            |       |
                        |    +--+----+   =   |    +--+
                        +----+--+    |       +----+
                             |   B   |
                             |       |
                             +-------+

              __sub__(other: CSG) -> CSG

                        difference = A - B

              intersect(other: CSG) -> CSG
                     Return a new CSG solid representing space both this solid and in the solid  other.  Neither
                     this solid nor the solid other are modified:

                        A.intersect(B)

                        +-------+
                        |       |
                        |   A   |
                        |    +--+----+   =   +--+
                        +----+--+    |       +--+
                             |   B   |
                             |       |
                             +-------+

              __mul__(other: CSG) -> CSG

                        intersection = A * B

              inverse() -> CSG
                     Return a new CSG solid with solid and empty space switched. This solid is not modified.

   License
       • Original implementation csg.js, Copyright (c) 2011 Evan Wallace (http://madebyevan.com/), under the MIT
         license.

       • Python port pycsg, Copyright (c) 2012 Tim Knip (http://www.floorplanner.com), under the MIT license.

       • Additions by Alex Pletzer (Pennsylvania State University)

       • Integration as ezdxf add-on, Copyright (c) 2020, Manfred Moitzi, MIT License.

   Showcase Forms
   MengerSponge
       Build a 3D Menger sponge.

       class ezdxf.addons.MengerSponge(location: Vertex = (0.0, 0.0, 0.0), length: float = 1.0, level: int = 1,
       kind: int = 0)

              Parameterslocation – location of lower left corner as (x, y, z) tuple

                     • length – side length

                     • level – subdivide level

                     • kind – type of menger sponge
                                               ┌───┬────────────────────────┐
                                               │ 0 │ Original Menger Sponge │
                                               ├───┼────────────────────────┤
                                               │ 1 │ Variant XOX            │
                                               ├───┼────────────────────────┤
                                               │ 2 │ Variant OXO            │
                                               ├───┼────────────────────────┤
                                               │ 3 │ Jerusalem Cube         │
                                               └───┴────────────────────────┘

              render(layout: GenericLayoutType, merge: bool = False, dxfattribs: dict = None, matrix: Matrix44 =
              None, ucs: UCS = None) -> None
                     Renders  the  menger  sponge  into layout, set merge to True for rendering the whole menger
                     sponge into one MESH entity, set merge to False for rendering the individual cubes  of  the
                     menger sponge as MESH entities.

                     Parameterslayout – DXF target layout

                            • mergeTrue for one MESH entity, False for individual MESH entities per cube

                            • dxfattribs – DXF attributes for the MESH entities

                            • matrix – apply transformation matrix at rendering

                            • ucs – apply UCS transformation at rendering

              cubes() -> Iterable[ezdxf.render.mesh.MeshTransformer]
                     Yields all cubes of the menger sponge as individual MeshTransformer objects.

              mesh() -> ezdxf.render.mesh.MeshTransformer
                     Returns geometry as one MeshTransformer object.

       Menger Sponge kind=0: [image]

       Menger Sponge kind=1: [image]

       Menger Sponge kind=2: [image]

       Jerusalem Cube kind=3: [image]

   SierpinskyPyramid
       Build a 3D Sierpinsky Pyramid.

       class ezdxf.addons.SierpinskyPyramid(location: Vertex = (0.0, 0.0, 0.0), length: float = 1.0, level: int
       = 1, sides: int = 4)

              Parameterslocation – location of base center as (x, y, z) tuple

                     • length – side length

                     • level – subdivide level

                     • sides – sides of base geometry

              render(layout: GenericLayoutType, merge: bool = False, dxfattribs: dict = None, matrix: Matrix44 =
              None, ucs: UCS = None) -> None
                     Renders  the  sierpinsky  pyramid  into  layout,  set merge to True for rendering the whole
                     sierpinsky pyramid into one MESH entity, set merge to False for individual pyramids as MESH
                     entities.

                     Parameterslayout – DXF target layout

                            • mergeTrue for one MESH entity, False for individual MESH entities per pyramid

                            • dxfattribs – DXF attributes for the MESH entities

                            • matrix – apply transformation matrix at rendering

                            • ucs – apply UCS at rendering

              pyramids() -> Iterable[ezdxf.render.mesh.MeshTransformer]
                     Yields all pyramids of the sierpinsky pyramid as individual MeshTransformer objects.

              mesh() -> ezdxf.render.mesh.MeshTransformer
                     Returns geometry as one MeshTransformer object.

       Sierpinsky Pyramid with triangle base: [image]

       Sierpinsky Pyramid with square base: [image]

   ODA File Converter Support
       Use an installed ODA File Converter for converting between different versions of .dwg, .dxb and .dxf.

       WARNING:
          Execution of an external application is a  big  security  issue!  Especially  when  the  path  to  the
          executable can be altered.

          To avoid this problem delete the ezdxf.addons.odafc.py module.

       The  ODA  File  Converter  has  to be installed by the user, the application is available for Windows XP,
       Windows 7 or later, Mac OS X, and Linux in 32/64-bit RPM and DEB format.

       At least at Windows the GUI of the ODA File Converter pops up on every call.

       ODA File Converter version strings, you can use any of this strings  to  specify  a  version,  'R..'  and
       'AC....' strings will be automatically mapped to 'ACAD....' strings:
                                        ──────────────────────────────────────
                                          ODAFC      ezdxf           Version
                                        ──────────────────────────────────────
                                          ACAD9      not supported   AC1004
                                        ──────────────────────────────────────
                                          ACAD10     not supported   AC1006
                                        ──────────────────────────────────────
                                          ACAD12     R12             AC1009
                                        ──────────────────────────────────────
                                          ACAD13     R13             AC1012
                                        ──────────────────────────────────────
                                          ACAD14     R14             AC1014
                                        ──────────────────────────────────────
                                          ACAD2000   R2000           AC1015
                                        ──────────────────────────────────────
                                          ACAD2004   R2004           AC1018
                                        ──────────────────────────────────────
                                          ACAD2007   R2007           AC1021
                                        ──────────────────────────────────────
                                          ACAD2010   R2010           AC1024
                                        ──────────────────────────────────────
                                          ACAD2013   R2013           AC1027
                                        ──────────────────────────────────────
                                          ACAD2018   R2018           AC1032
                                        ┌──────────┬───────────────┬─────────┐
                                        │          │               │         │
       Usage:                           │          │               │         │
                                        │          │               │         │
          from ezdxf.addons import odafc│          │               │         │
                                        │          │               │         │
          # Load a DWG file             │          │               │         │
          doc = odafc.readfile('my.dwg')│          │               │         │
                                        │          │               │         │
--
DXF INTERNALS                           │          │               │         │
--

DEVELOPER GUIDES

       Information about ezdxf internals.

   Design
       The pkg-design section shows the structure of the ezdxf package  for  developers  with  more  experience,
       which  want  to have more insight into the package an maybe want to develop add-ons or want contribute to
       the ezdxf package.  !!! UNDER CONSTRUCTION !!!

   Package Design for Developers
       A DXF document is divided into several sections, this sections are managed by  the  Drawing  object.  For
       each section exist a corresponding attribute in the Drawing object:
                                           ┌──────────┬──────────────────┐
                                           │ Section  │ Attribute        │
                                           ├──────────┼──────────────────┤
                                           │ HEADER   │ Drawing.header   │
                                           ├──────────┼──────────────────┤
                                           │ CLASSES  │ Drawing.classes  │
                                           ├──────────┼──────────────────┤
                                           │ TABLES   │ Drawing.tables   │
                                           ├──────────┼──────────────────┤
                                           │ BLOCKS   │ Drawing.blocks   │
                                           ├──────────┼──────────────────┤
                                           │ ENTITIES │ Drawing.entities │
                                           ├──────────┼──────────────────┤
                                           │ OBJECTS  │ Drawing.objects  │
                                           └──────────┴──────────────────┘

       Resource  entities  (LAYER, STYLE, LTYPE, …) are stored in tables in the TABLES section. A table owns the
       table entries, the owner handle of table entry is the handle of the table. Each table has a  shortcut  in
       the Drawing object:
                                       ┌──────────────┬───────────────────────┐
                                       │ Table        │ Attribute             │
                                       ├──────────────┼───────────────────────┤
                                       │ APPID        │ Drawing.appids        │
                                       ├──────────────┼───────────────────────┤
                                       │ BLOCK_RECORD │ Drawing.block_records │
                                       ├──────────────┼───────────────────────┤
                                       │ DIMSTYLE     │ Drawing.dimstyles     │
                                       ├──────────────┼───────────────────────┤
                                       │ LAYER        │ Drawing.layers        │
                                       ├──────────────┼───────────────────────┤
                                       │ LTYPE        │ Drawing.linetypes     │
                                       ├──────────────┼───────────────────────┤
                                       │ STYLE        │ Drawing.styles        │
                                       ├──────────────┼───────────────────────┤
                                       │ UCS          │ Drawing.ucs           │
                                       ├──────────────┼───────────────────────┤
                                       │ VIEW         │ Drawing.views         │
                                       ├──────────────┼───────────────────────┤
                                       │ VPORT        │ Drawing.viewports     │
                                       └──────────────┴───────────────────────┘

       Graphical  entities  are  stored  in  layouts:  Modelspace, Paperspace layouts and BlockLayout.  The core
       management object of this layouts is the BLOCK_RECORD entity (BlockRecord), the BLOCK_RECORD is the  real
       owner  of  the  entities,  the  owner  handle  of  the entities is the handle of the BLOCK_RECORD and the
       BLOCK_RECORD also owns and manages the entity space of the layout which  contains  all  entities  of  the
       layout.

       For more information about layouts see also: Layout Management Structures

       For more information about blocks see also: Block Management Structures

       Non-graphical  entities (objects) are stored in the OBJECTS section.  Every object has a parent object in
       the OBJECTS section, most likely a DICTIONARY object, and is stored in the entity space  of  the  OBJECTS
       section.

       For more information about the OBJECTS section see also: objects_section_internals

       All  table  entries,  DXF  entities  and  DXF  objects  are stored in the entities database accessible as
       Drawing.entitydb. The entity database is a simple key, value storage, key is the entity handle, value  is
       the DXF object.

       For more information about the DXF data model see also: Data Model

   Terminology
   States
       DXF entities and objects can have different states:

       UNBOUND
              Entity is not stored in the Drawing entity database and DXF attribute handle is None and attribute
              doc can be None

       BOUND  Entity  is stored in the Drawing entity database, attribute doc has a reference to Drawing and DXF
              attribute handle is not None

       UNLINKED
              Entity is not linked to a layout/owner, DXF attribute owner is None

       LINKED Entity is linked to a layout/owner, DXF attribute owner is not None

       Virtual Entity
              State: UNBOUND & UNLINKED

       Unlinked Entity
              State: BOUND & UNLINKED

       Bound Entity
              State: BOUND & LINKED

   Actions
       NEW    Create a new DXF document

       LOAD   Load a DXF document from an external source

       CREATE Create DXF structures from NEW or LOAD data

       DESTROY
              Delete DXF structures

       BIND   Bind an entity to a Drawing, set entity state to BOUND & UNLINKED and  check  or  create  required
              resources

       UNBIND unbind …

       LINK   Link  an  entity  to  an  owner/layout.   This makes an entity to a real DXF entity, which will be
              exported at the saving process. Any DXF entity can only  be  linked  to  one  parent  entity  like
              DICTIONARY or BLOCK_RECORD.

       UNLINK unlink …

   Loading a DXF Document
       Loading  a  DXF  document from an external source, creates a new Drawing object. This loading process has
       two stages:

   First Loading Stage
       • LOAD content from external source as SectionDict: loader.load_dxf_structure()

       • LOAD tag structures as DXFEntity objects: loader.load_dxf_entities()

       • BIND entities: loader.load_and_bind_dxf_content(); Special handling of the BIND  process,  because  the
         Drawing is not full initialized, a complete validation is not possible at this stage.

   Second Loading Stage
       Parse SectionDict:

       • CREATE sections: HEADER, CLASSES, TABLES, BLOCKS and OBJECTS

       • CREATE layouts: Blocks, Layouts

       • LINK entities to a owner/layout

       The  ENTITIES section is a relict from older DXF versions and has to be exported including the modelspace
       and active paperspace entities, but all entities reside  in  a  BLOCK  definition,  even  modelspace  and
       paperspace layouts are only BLOCK definitions and ezdxf has no explicit ENTITIES section.

       Source  Code:  as  developer  start  your  journey  at ezdxf.document.Drawing.read(), which has no public
       documentation, because package-user should use ezdxf.read() and ezdxf.readfile().

   New DXF Document
   Creating New DXF Entities
       The default constructor of each entity type creates a new virtual entity:

       • DXF attribute owner is None

       • DXF attribute handle is None

       • Attribute doc is None

       The DXFEntity.new() constructor creates entities with given owner, handle and doc attributes, if  doc  is
       not  None  and  entity  is  not already bound to a document, the new() constructor automatically bind the
       entity to the given document doc.

       There exist only two scenarios:

       1. UNBOUND: doc is None and handle is None

       2. BOUND: doc is not None and handle is not None

   Factory functionsnew(), create a new virtual DXF object/entity

       • load(), load (create) virtual DXF object/entity from DXF tags

       • bind(), bind an entity to a document, create required resources  if  necessary  (e.g.  ImageDefReactor,
         SEQEND) and raise exceptions for non-existing resources.

         • Bind  entity  loaded  from an external source to a document, all referenced resources must exist, but
           try to repair as many flaws as possible because errors were created by another  application  and  are
           not the responsibility of the package-user.

         • Bind  an  entity from another DXF document, all invalid resources will be removed silently or created
           (e.g. SEQEND). This is a simple import from another document without  resource  import,  for  a  more
           advanced import including resources exist the importer add-on.

         • Bootstrap  problem  for  binding  loaded  table entries and objects in the OBJECTS section! Can’t use
           Auditor to repair this objects, because the DXF document is not fully initialized.

       • is_bound() returns True if entity is bound to document docunbind() function to remove an entity from a document and set state to a virtual entity,  which  should
         also UNLINK the entity from layout, because an layout can not store a virtual entity.

       • cls(), returns the class

       • register_entity(), registration decorator

       • replace_entity(), registration decorator

   Class Interfaces
   DXF Entities
       • NEW constructor to create an entity from scratch

       • LOAD constructor to create an entity loaded from an external source

       • DESTROY  interface  to  kill  an  entity, set entity state to dead, which means entity.is_alive returns
         False. All entity iterators like EntitySpace, EntityQuery,  and  EntityDB  must  filter  (ignore)  dead
         entities.  Calling DXFEntity.destroy() is a regular way to delete entities.

       • LINK  an entity to a layout by BlockRecord.link(), which set the owner handle to BLOCK_RECORD handle (=
         layout key) and add the entity to the entity space of the BLOCK_RECORD  and  set/clear  the  paperspace
         flag.

   DXF Objects
       • NEW, LOAD, DESTROY see DXF entities

       • LINK:  Linking  an  DXF  object means adding the entity to a parent object in the OBJECTS section, most
         likely a DICTIONARY object, and adding the object to the entity  space  of  the  OBJECTS  section,  the
         root-dict  is  the  only entity in the OBJECTS section which has an invalid owner handle “0”. Any other
         object with an invalid or destroyed owner is an  orphaned  entity.   The  audit  process  destroys  and
         removes orphaned objects.

       • Extension  dictionaries  (ACAD_XDICTIONARY)  are DICTIONARY objects located in the OBJECTS sections and
         can reference/own other entities of the OBJECTS section.

       • The root-dictionary is the only entity in the OBJECTS section which has an invalid  owner  handle  “0”.
         Any other object with an invalid or destroyed owner is an orphaned entity.

   Layouts
       • LINK interface to link an entity to a layout

       • UNLINK interface to remove an entity from a layout

   Database
       • BIND interface to add an entity to the database of a document

       • delete_entity() interface, same as UNBIND and DESTROY an entity

   Internal Data Structures
   Entity Database
       The  EntityDB is a simple key/value database to store DXFEntity objects by it’s handle, every Drawing has
       its own EntityDB, stored in the Drawing attribute entitydb.

       Every DXF entity/object, except tables and sections, are represented as  DXFEntity  or  inherited  types,
       this entities are stored in the EntityDB, database-key is the dxf.handle as plain hex string.

       All iterators like keys(), values(), items() and __iter__() do not yield destroyed entities.

       WARNING:
          The get() method and the index operator [], return destroyed entities and entities from the trashcan.

       class ezdxf.entitydb.EntityDB

              __getitem__(handle: str) -> DXFEntity
                     Get entity by handle, does not filter destroyed entities nor entities in the trashcan.

              __setitem__(handle: str, entity: DXFEntity) -> None
                     Set entity for handle.

              __delitem__(handle: str) -> None
                     Delete entity by handle. Removes entity only from database, does not destroy the entity.

              __contains__(item: Union[str, DXFEntity]) -> bool
                     True if database contains handle.

              __len__() -> int
                     Count of database items.

              __iter__() -> Iterable[str]
                     Iterable of all handles, does filter destroyed entities but not entities in the trashcan.

              get(handle: str) -> Optional[DXFEntity]
                     Returns entity for handle or None if no entry exist, does not filter destroyed entities.

              next_handle() -> str
                     Returns next unique handle.

              keys() -> Iterable[str]
                     Iterable of all handles, does filter destroyed entities.

              values() -> Iterable[DXFEntity]
                     Iterable of all entities, does filter destroyed entities.

              items() -> Iterable[Tuple[str, DXFEntity]]
                     Iterable of all (handle, entities) pairs, does filter destroyed entities.

              add(entity: DXFEntity) -> None
                     Add  entity  to  database, assigns a new handle to the entity if entity.dxf.handle is None.
                     Adding the same entity multiple times is possible and creates only a single database entry.

              new_trashcan() -> ezdxf.entitydb.EntityDB.Trashcan
                     Returns a new trashcan, empty trashcan manually by: : func:Trashcan.clear().

              trashcan() -> ezdxf.entitydb.EntityDB.Trashcan
                     Returns a new trashcan in context manager mode,  trashcan  will  be  emptied  when  leaving
                     context.

              purge() -> None
                     Remove all destroyed entities from database, but does not empty the trashcan.

   Entity Space
       class ezdxf.entitydb.EntitySpace(entities=None)
              An  EntitySpace  is  a  collection of DXFEntity objects, that stores only  references to DXFEntity
              objects.

              The Modelspace, any Paperspace layout and BlockLayout objects have  an  EntitySpace  container  to
              store their entities.

              __iter__() -> Iterable[DXFEntity]
                     Iterable of all entities, filters destroyed entities.

              __getitem__(index) -> DXFEntity
                     Get entity at index item

                     EntitySpace  has  a  standard  Python list like interface, therefore index can be any valid
                     list indexing or slicing term, like a single index layout[-1] to get the last entity, or an
                     index slice layout[:10] to get the first 10 or less entities as List[DXFEntity].  Does  not
                     filter destroyed entities.

              __len__() -> int
                     Count of entities inluding destroyed entities.

              has_handle(handle: str) -> bool
                     True if handle is present, does filter destroyed entities.

              purge()
                     Remove all destroyed entities from entity space.

              add(entity: DXFEntity) -> None
                     Add entity.

              extend(entities: Iterable[DXFEntity]) -> None
                     Add multiple entities.

              remove(entity: DXFEntity) -> None
                     Remove entity.

              clear() -> None
                     Remove all entities.

   DXF Types
       Required DXF tag interface:

          • property code: group code as int

          • property value: tag value of unspecific type

          • dxfstr(): returns the DXF string

          • clone(): returns a deep copy of tag

   DXFTag Factory Functions
       ezdxf.lldxf.types.dxftag(code: int, value: TagValue) -> ezdxf.lldxf.types.DXFTag
              DXF tag factory function.

              Parameterscode – group code

                     • value – tag value

              Returns: DXFTag or inherited

       ezdxf.lldxf.types.tuples_to_tags(iterable: Iterable[Tuple[int, TagValue]]) ->
       Iterable[ezdxf.lldxf.types.DXFTag]
              Returns an iterable if :class: DXFTag or inherited, accepts an iterable of (code, value) tuples as
              input.

   DXFTag
       class ezdxf.lldxf.types.DXFTag(code: int, value: TagValue)
              Immutable DXFTag class - immutable by design, not by implementation.

              Parameterscode – group code as int

                     • value – tag value, type depends on group code

              Variablescode – group code as int (do not change)

                     • value – tag value (read-only property)

              __eq__(other) -> bool
                     True if other and self has same content for code and value.

              __getitem__(index: int)
                     Returns code for index 0 and value for index 1, emulates a tuple.

              __hash__()
                     Hash support, DXFTag can be used in sets and as dict key.

              __iter__() -> Iterable
                     Returns (code, value) tuples.

              __repr__() -> str
                     Returns representation string 'DXFTag(code, value)'.

              __str__() -> str
                     Returns content string '(code, value)'.

              clone() -> ezdxf.lldxf.types.DXFTag
                     Returns  a  clone  of  itself,  this  method  is  necessary  for  the more complex (and not
                     immutable) DXF tag types.

              dxfstr() -> str
                     Returns the DXF string e.g. '  0\nLINE\n'

   DXFBinaryTag
       class ezdxf.lldxf.types.DXFBinaryTag(DXFTag)
              Immutable BinaryTags class - immutable by design, not by implementation.

              dxfstr() -> str
                     Returns the DXF string for all vertex components.

              tostring() -> str
                     Returns binary value as single hex-string.

   DXFVertex
       class ezdxf.lldxf.types.DXFVertex(DXFTag)
              Represents a 2D or 3D vertex, stores only the group code of the x-component of the vertex, because
              the y-group-code is x-group-code + 10 and z-group-code id x-group-code+20, this  is  a  rule  that
              ALWAYS applies.  This tag is immutable by design, not by implementation.

              Parameterscode – group code of x-component

                     • value – sequence of x, y and optional z values

              dxfstr() -> str
                     Returns the DXF string for all vertex components.

              dxftags() -> Iterable[Tuple]
                     Returns all vertex components as single DXFTag objects.

   NONE_TAG
       ezdxf.lldxf.types.NONE_TAG
              Special tag representing a none existing tag.

   Tags
       A  list  of DXFTag, inherits from Python standard list. Unlike the statement in the DXF Reference “Do not
       write programs that rely on the order given here”, tag order is sometimes essential and some group  codes
       may appear multiples times in one entity. At the worst case (Material: normal map shares group codes with
       diffuse map) using same group codes with different meanings.

       class ezdxf.lldxf.tags.Tags
              Subclass of list.

              Collection of DXFTag as flat list. Low level tag container, only required for advanced stuff.

              classmethod from_text(text: str) -> Tags
                     Constructor from DXF string.

              dxftype() -> str
                     Returns DXF type of entity, e.g. 'LINE'.

              get_handle() -> str
                     Get DXF handle. Raises DXFValueError if handle not exist.

                     Returns
                            handle as plain hex string like 'FF00'

                     Raises DXFValueError – no handle found

              replace_handle(new_handle: str) -> None
                     Replace existing handle.

                     Parameters
                            new_handle – new handle as plain hex string e.g. 'FF00'

              has_tag(code: int) -> bool
                     Returns True if a DXFTag with given group code is present.

                     Parameters
                            code – group code as int

              has_embedded_objects() -> bool

              get_first_tag(code: int, default=DXFValueError) -> DXFTag
                     Returns  first  DXFTag  with given group code or default, if default != DXFValueError, else
                     raises DXFValueError.

                     Parameterscode – group code as int

                            • default – return value for default case or raises DXFValueError

              get_first_value(code: int, default=DXFValueError) -> Any
                     Returns value of first DXFTag with given group code or default if default != DXFValueError,
                     else raises DXFValueError.

                     Parameterscode – group code as int

                            • default – return value for default case or raises DXFValueError

              find_all(code: int) -> List[DXFTag]
                     Returns a list of DXFTag with given group code.

                     Parameters
                            code – group code as int

              filter(codes: Iterable[int]) -> Iterable[DXFTag]
                     Iterate and filter tags by group codes.

                     Parameters
                            codes – group codes to filter

              collect_consecutive_tags(codes: Iterable[int], start: int = 0, end: int = None) -> Tags
                     Collect all consecutive tags with group code in codes, start and end  delimits  the  search
                     range. A tag code not in codes ends the process.

                     Parameterscodes – iterable of group codes

                            • start – start index as int

                            • end – end index as int, None for end index = len(self)

                     Returns
                            collected tags as Tags

              tag_index(code: int, start: int = 0, end: int = None) -> int
                     Return index of first DXFTag with given group code.

                     Parameterscode – group code as int

                            • start – start index as int

                            • end – end index as int, None for end index = len(self)

              update(tag: DXFTag)
                     Update  first  existing  tag  with  same group code as tag, raises DXFValueError if tag not
                     exist.

              set_first(tag: DXFTag)
                     Update first existing tag with group code tag.code or append tag.

              remove_tags(codes: Iterable[int]) -> None
                     Remove all tags inplace with group codes specified in codes.

                     Parameters
                            codes – iterable of group codes as int

              remove_tags_except(codes: Iterable[int]) -> None
                     Remove all tags inplace except those with group codes specified in codes.

                     Parameters
                            codes – iterable of group codes

              pop_tags(codes: Iterable[int]) -> Iterable[DXFTag]
                     Pop tags with group codes specified in codes.

                     Parameters
                            codes – iterable of group codes

              classmethod strip(tags: Tags, codes: Iterable[int]) -> Tags
                     Constructor from tags, strips all tags with group codes in codes from tags.

                     Parameterstags – iterable of DXFTagcodes – iterable of group codes as int

       ezdxf.lldxf.tags.group_tags(tags: Iterable[DXFTag], splitcode: int = 0) -> Iterable[Tags]
              Group of tags starts with a SplitTag and ends before the next SplitTag.  A SplitTag is a tag  with
              code == splitcode, like (0, ‘SECTION’) for splitcode == 0.

              Parameterstags – iterable of DXFTagint (splitcode) – group code of split tag

       class ezdxf.lldxf.extendedtags.ExtendedTags(tags: Iterable[DXFTag] = None, legacy=False)
              Represents the extended DXF tag structure introduced with DXF R13.

              Args:  tags: iterable of DXFTag legacy: flag for DXF R12 tags

              appdata
                     Application defined data as list of Tags

              subclasses
                     Subclasses as list of Tags

              xdata  XDATA as list of Tags

              embedded_objects
                     embedded objects as list of Tags

              noclass
                     Short cut to access first subclass.

              get_handle() -> str
                     Returns handle as hex string.

              dxftype() -> str
                     Returns DXF type as string like “LINE”.

              replace_handle(handle: str) -> None
                     Replace the existing entity handle by a new value.

              legacy_repair()
                     Legacy (DXF R12) tags handling and repair.

              clone() -> ExtendedTags
                     Shallow copy.

              flatten_subclasses()
                     Flatten subclasses in legacy mode (DXF R12).

                     There  exists  DXF  R12  with subclass markers, technical incorrect but works if the reader
                     ignore subclass marker tags, unfortunately ezdxf tries to use  this  subclass  markers  and
                     therefore R12 parsing by ezdxf does not work without removing these subclass markers.

                     This   method   removes   all   subclass   markers   and   flattens   all  subclasses  into
                     ExtendedTags.noclass.

              get_subclass(name: str, pos: int = 0) -> Tags
                     Get subclass name.

                     Parametersname – subclass name as string like “AcDbEntity”

                            • pos – start searching at subclass pos.

              has_xdata(appid: str) -> bool
                     True if has XDATA for appid.

              get_xdata(appid: str) -> Tags
                     Returns XDATA for appid as Tags.

              set_xdata(appid: str, tags: IterableTags) -> None
                     Set tags as XDATA for appid.

              new_xdata(appid: str, tags: IterableTags = None) -> Tags
                     Append a new XDATA block.

                     Assumes that no XDATA block with the same appid already exist:

                        try:
                            xdata = tags.get_xdata('EZDXF')
                        except ValueError:
                            xdata = tags.new_xdata('EZDXF')

              has_app_data(appid: str) -> bool
                     True if has application defined data for appid.

              get_app_data(appid: str) -> Tags
                     Returns application defined data for appid as Tags including marker tags.

              get_app_data_content(appid: str) -> Tags
                     Returns application defined data for appid as Tags without first and last marker tag.

              set_app_data_content(appid: str, tags: IterableTags) -> None
                     Set application defined data for appid for already exiting data.

              new_app_data(appid: str, tags: IterableTags = None, subclass_name: str = None) -> Tags
                     Append a new application defined data to subclass subclass_name.

                     Assumes that no app data block with the same appid already exist:

                        try:
                            app_data = tags.get_app_data('{ACAD_REACTORS', tags)
                        except ValueError:
                            app_data = tags.new_app_data('{ACAD_REACTORS', tags)

              classmethod from_text(text: str, legacy: bool = False) -> ExtendedTags
                     Create ExtendedTags from DXF text.

   Packed DXF Tags
       Store DXF tags in compact data structures as list or array.array to reduce memory usage.

       class ezdxf.lldxf.packedtags.TagList(data: Iterable = None)
              Store data in a standard Python list.

              Args:  data: iterable of DXF tag values.

              values Data storage as list.

              clone() -> TagList
                     Returns a deep copy.

              classmethod from_tags(tags: Tags, code: int) -> TagList
                     Setup list from iterable tags.

                     Parameterstags – tag collection as Tagscode – group code to collect

              clear() -> None
                     Delete all data values.

       class ezdxf.lldxf.packedtags.TagArray(data: Iterable = None)
              TagArray is a subclass of TagList, which store data in an array.array.  Array type is  defined  by
              class variable DTYPE.

              Args:  data: iterable of DXF tag values.

              DTYPE  array.array type as string

              values Data storage as array.array

              set_values(values: Iterable) -> None
                     Replace data by values.

       class ezdxf.lldxf.packedtags.VertexArray(data: Iterable = None)
              Store vertices in an array.array('d').  Vertex size is defined by class variable VERTEX_SIZE.

              Args:  data: iterable of vertex values as linear list e.g. [x1, y1, x2, y2, x3, y3, ...].

              VERTEX_SIZE
                     Size of vertex (2 or 3 axis).

              __len__() -> int
                     Count of vertices.

              __getitem__(index: int)
                     Get vertex at index, extended slicing supported.

              __setitem__(index: int, point: Sequence[float]) -> None
                     Set vertex point at index, extended slicing not supported.

              __delitem__(index: int) -> None
                     Delete vertex at index, extended slicing supported.

              __iter__() -> Iterable[Sequence[float]]
                     Returns iterable of vertices.

              __str__() -> str
                     String representation.

              insert(pos: int, point: Sequence[float])
                     Insert point in front of vertex at index pos.

                     Parameterspos – insert position

                            • point – point as tuple

              append(point: Sequence[float]) -> None
                     Append point.

              extend(points: Iterable[Sequence[float]]) -> None
                     Extend array by points.

              set(points: Iterable[Sequence[float]]) -> None
                     Replace all vertices by points.

              clear() -> None
                     Delete all vertices.

              clone() -> VertexArray
                     Returns a deep copy.

              classmethod from_tags(tags: Iterable[DXFTag], code: int = 10) -> VertexArray
                     Setup point array from iterable tags.

                     Parameterstags – iterable of DXFVertexcode – group code to collect

              export_dxf(tagwriter: ezdxf.lldxf.tagwriter.TagWriter, code=10)

   Documentation Guide
   Formatting Guide
       This  section is only for me, because of the long pauses between develop iterations, I often forget to be
       consistent in documentation formatting.

       Documentation is written with Sphinx and reSturcturedText.

       Started integration of documentation into source code and  using  autodoc  features  of  Sphinx  wherever
       useful.

       Sphinx theme provided by Read the Docs :

          pip install sphinx-rtd-theme

   guide  Example module
       guide.example_func(a: int, b: str, test: str = None, flag: bool = True) -> None
              Parameters a and b are positional arguments, argument test defaults to None and flag to True.  Set
              a  to  70  and  b  to  “x”  as  an  example.  Inline code examples example_func(70, 'x') or simple
              example_func(70, "x")

                 • arguments: a, b, test and flags

                 • literal number values: 1, 2 … 999

                 • literal string values: “a String”

                 • literal tags: (5, “F000”)

                 • inline code: call a example_func(x)

                 • Python keywords: None, True, False, tuple, list, dict, str, int, float

                 • Exception classes: DXFAttributeError

       class guide.ExampleCls(**kwargs)
              The ExampleCls constructor accepts a number of optional keyword arguments.  Each keyword  argument
              corresponds to an instance attribute, so for example

                 e = ExampleCls(flag=True)

              flag   This is the attribute flag.

                     New in version 0.9: New feature flag

                     Changed in version 0.10: The new meaning of flag is …

                     Deprecated since version 0.11: flag is obsolete

              set_axis(axis)
                     axis as (x, y, z) tuple

                     Args:  axis: (x, y, z) tuple

              example_method(flag: bool = False) -> None
                     Method example_method() of class ExampleCls

   Text Formatting
       DXF version
              DXF R12 (AC1009), DXF R2004 (AC1018)

       DXF Types
              DXF  types  are  always  written  in  uppercase letters but without further formatting: DXF, LINE,
              CIRCLE

       (internal API)
              Marks methods as internal API, gets no public documentation.

       (internal class)
              Marks classes only for internal usage, gets not public documentation.

       Spatial Dimensions
              2D and 3D with an uppercase letter D

       Axis   x-axis, y-axis and z-axis

       Planes xy-plane, xz-plane, yz-plane

       Layouts
              modelspace, paperspace [layout], block [layout]

       Extended Entity Data
              AppData, XDATA, embedded object, APPID

GLOSSARY

       ACI    ACI

       ACIS   The 3D ACIS Modeler (ACIS) is a geometric modeling kernel developed by Spatial Corp.  ®  (formerly
              Spatial Technology), part of Dassault Systems.

       bulge  The bulge value is used to create arc shaped line segments in Polyline and LWPolyline entities.

       CAD    Computer-Assisted Drafting or Computer-Aided Design

       CTB    Color dependent plot style table (ColorDependentPlotStyles)

       DWG    Proprietary  file  format  of  AutoCAD ®. Documentation for this format is available from the Open
              Design Alliance (ODA) at their  Downloads  section.  This  documentation  is  created  by  reverse
              engineering therefore not perfect nor complete.

       DXF    Drawing  eXchange  Format  is  a  file format used by AutoCAD ® to interchange data with other CAD
              applications. DXF is a trademark of Autodesk ®.

       STB    Named plot style table (NamedPlotStyles)

       true color
              RGB color representation, a combination red, green and blue values to define a color.

INDICES AND TABLES

       • genindex

       • search

AUTHOR

       Manfred Moitzi

COPYRIGHT

       2011-2020, Manfred Moitzi

0.14.2                                            Nov 27, 2020                                          EZDXF(1)