Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Treyer <treyer@arch.ethz.ch>2016-08-16 19:24:32 +0300
committerLukas Treyer <treyer@arch.ethz.ch>2016-08-16 19:24:32 +0300
commit37939a32083be2ca80b296bd8b030bffaf65928d (patch)
tree404adb02f8c644b9ac11d3eb65da1005a5334dd1 /io_import_dxf
parentb79cc04f772aefab48e0a9769b1d0dae73198ec8 (diff)
updating to newest version of dxfgrabber; needed for further updates regarding inf.0 problem.
Diffstat (limited to 'io_import_dxf')
-rw-r--r--io_import_dxf/__init__.py27
-rw-r--r--[-rwxr-xr-x]io_import_dxf/dxfgrabber/__init__.py2
-rw-r--r--[-rwxr-xr-x]io_import_dxf/dxfgrabber/acdsdata.py4
-rw-r--r--[-rwxr-xr-x]io_import_dxf/dxfgrabber/blockssection.py6
-rw-r--r--[-rwxr-xr-x]io_import_dxf/dxfgrabber/codepage.py0
-rw-r--r--[-rwxr-xr-x]io_import_dxf/dxfgrabber/color.py0
-rw-r--r--[-rwxr-xr-x]io_import_dxf/dxfgrabber/const.py0
-rwxr-xr-xio_import_dxf/dxfgrabber/cydxfentity.py7
-rwxr-xr-xio_import_dxf/dxfgrabber/cytags.py7
-rw-r--r--[-rwxr-xr-x]io_import_dxf/dxfgrabber/decode.py0
-rw-r--r--[-rwxr-xr-x]io_import_dxf/dxfgrabber/defaultchunk.py5
-rw-r--r--[-rwxr-xr-x]io_import_dxf/dxfgrabber/drawing.py4
-rwxr-xr-xio_import_dxf/dxfgrabber/dxf12.py202
-rwxr-xr-xio_import_dxf/dxfgrabber/dxf13.py546
-rwxr-xr-xio_import_dxf/dxfgrabber/dxfattr.py47
-rwxr-xr-xio_import_dxf/dxfgrabber/dxfentity.py84
-rwxr-xr-xio_import_dxf/dxfgrabber/entities.py930
-rw-r--r--[-rwxr-xr-x]io_import_dxf/dxfgrabber/entitysection.py16
-rwxr-xr-xio_import_dxf/dxfgrabber/headersection.py7
-rw-r--r--[-rwxr-xr-x]io_import_dxf/dxfgrabber/juliandate.py0
-rw-r--r--[-rwxr-xr-x]io_import_dxf/dxfgrabber/layers.py90
-rw-r--r--[-rwxr-xr-x]io_import_dxf/dxfgrabber/linetypes.py72
-rwxr-xr-xio_import_dxf/dxfgrabber/pytags.py385
-rwxr-xr-xio_import_dxf/dxfgrabber/sections.py7
-rw-r--r--[-rwxr-xr-x]io_import_dxf/dxfgrabber/styles.py91
-rw-r--r--[-rwxr-xr-x]io_import_dxf/dxfgrabber/tablessection.py18
-rw-r--r--[-rwxr-xr-x]io_import_dxf/dxfgrabber/tags.py422
-rw-r--r--io_import_dxf/dxfimport/convert.py2
-rw-r--r--io_import_dxf/dxfimport/do.py18
-rw-r--r--io_import_dxf/dxfimport/fake_entities.py6
-rw-r--r--io_import_dxf/dxfimport/is_.py5
31 files changed, 537 insertions, 2473 deletions
diff --git a/io_import_dxf/__init__.py b/io_import_dxf/__init__.py
index 5d588f76..d768d624 100644
--- a/io_import_dxf/__init__.py
+++ b/io_import_dxf/__init__.py
@@ -22,7 +22,6 @@ import bpy
import os
from bpy.props import StringProperty, BoolProperty, EnumProperty, IntProperty, FloatProperty
from .dxfimport.do import Do, Indicator
-from .dxfgrabber.headersection import MinVersionError
from .transverse_mercator import TransverseMercator
@@ -114,20 +113,18 @@ def read(report, filename, obj_merge=BY_LAYER, import_text=True, import_light=Tr
thicknessWidth=True, but_group_by_att=True, dxf_unit_scale=1.0):
# import dxf and export nurbs types to sat/sab files
# because that's how autocad stores nurbs types in a dxf...
- try:
- do = Do(filename, obj_merge, import_text, import_light, export_acis, merge_lines, do_bbox, block_rep, recenter,
- projDXF, projSCN, thicknessWidth, but_group_by_att, dxf_unit_scale)
- errors = do.entities(os.path.basename(filename).replace(".dxf", ""), new_scene)
-
- # display errors
- for error in errors:
- report({'ERROR', 'INFO'}, error)
-
- # inform the user about the sat/sab files
- if len(do.acis_files) > 0:
- report({'INFO'}, "Exported %d NURBS objects to sat/sab files next to your DXF file" % len(do.acis_files))
- except MinVersionError as minv:
- report({'ERROR', 'INFO'}, str(minv))
+ do = Do(filename, obj_merge, import_text, import_light, export_acis, merge_lines, do_bbox, block_rep, recenter,
+ projDXF, projSCN, thicknessWidth, but_group_by_att, dxf_unit_scale)
+
+ errors = do.entities(os.path.basename(filename).replace(".dxf", ""), new_scene)
+
+ # display errors
+ for error in errors:
+ report({'ERROR', 'INFO'}, error)
+
+ # inform the user about the sat/sab files
+ if len(do.acis_files) > 0:
+ report({'INFO'}, "Exported %d NURBS objects to sat/sab files next to your DXF file" % len(do.acis_files))
def display_groups_in_outliner():
diff --git a/io_import_dxf/dxfgrabber/__init__.py b/io_import_dxf/dxfgrabber/__init__.py
index 9d3da9d0..2581a404 100755..100644
--- a/io_import_dxf/dxfgrabber/__init__.py
+++ b/io_import_dxf/dxfgrabber/__init__.py
@@ -3,7 +3,7 @@
# Created: 21.07.2012
# License: MIT License
-version = (0, 7, 4)
+version = (0, 8, 1)
VERSION = "%d.%d.%d" % version
__author__ = "mozman <mozman@gmx.at>"
diff --git a/io_import_dxf/dxfgrabber/acdsdata.py b/io_import_dxf/dxfgrabber/acdsdata.py
index 60538d5f..b864fff0 100755..100644
--- a/io_import_dxf/dxfgrabber/acdsdata.py
+++ b/io_import_dxf/dxfgrabber/acdsdata.py
@@ -21,10 +21,10 @@ class AcDsDataSection(object):
@classmethod
def from_tags(cls, tags, drawing):
data_section = cls()
- data_section._build(tags, drawing.dxfversion)
+ data_section._build(tags)
return data_section
- def _build(self, tags, dxfversion):
+ def _build(self, tags):
if len(tags) == 3: # empty entities section
return
diff --git a/io_import_dxf/dxfgrabber/blockssection.py b/io_import_dxf/dxfgrabber/blockssection.py
index d8f6b057..a64a364e 100755..100644
--- a/io_import_dxf/dxfgrabber/blockssection.py
+++ b/io_import_dxf/dxfgrabber/blockssection.py
@@ -21,17 +21,17 @@ class BlocksSection(object):
def from_tags(tags, drawing):
blocks_section = BlocksSection()
if drawing.grab_blocks:
- blocks_section._build(tags, drawing.dxfversion)
+ blocks_section._build(tags)
return blocks_section
- def _build(self, tags, dxfversion):
+ def _build(self, tags):
if len(tags) == 3: # empty block section
return
groups = list()
for group in TagGroups(islice(tags, 2, len(tags)-1)):
groups.append(group)
if group[0].value == 'ENDBLK':
- entities = build_entities(groups, dxfversion)
+ entities = build_entities(groups)
block = entities[0]
block.set_entities(entities[1:-1])
self._add(block)
diff --git a/io_import_dxf/dxfgrabber/codepage.py b/io_import_dxf/dxfgrabber/codepage.py
index 47e8e3ea..47e8e3ea 100755..100644
--- a/io_import_dxf/dxfgrabber/codepage.py
+++ b/io_import_dxf/dxfgrabber/codepage.py
diff --git a/io_import_dxf/dxfgrabber/color.py b/io_import_dxf/dxfgrabber/color.py
index ae999804..ae999804 100755..100644
--- a/io_import_dxf/dxfgrabber/color.py
+++ b/io_import_dxf/dxfgrabber/color.py
diff --git a/io_import_dxf/dxfgrabber/const.py b/io_import_dxf/dxfgrabber/const.py
index cf8c6613..cf8c6613 100755..100644
--- a/io_import_dxf/dxfgrabber/const.py
+++ b/io_import_dxf/dxfgrabber/const.py
diff --git a/io_import_dxf/dxfgrabber/cydxfentity.py b/io_import_dxf/dxfgrabber/cydxfentity.py
deleted file mode 100755
index be39b48d..00000000
--- a/io_import_dxf/dxfgrabber/cydxfentity.py
+++ /dev/null
@@ -1,7 +0,0 @@
-def __bootstrap__():
- global __bootstrap__, __loader__, __file__
- import sys, pkg_resources, imp
- __file__ = pkg_resources.resource_filename(__name__,'cydxfentity.so')
- __loader__ = None; del __bootstrap__, __loader__
- imp.load_dynamic(__name__,__file__)
-__bootstrap__()
diff --git a/io_import_dxf/dxfgrabber/cytags.py b/io_import_dxf/dxfgrabber/cytags.py
deleted file mode 100755
index 071cea03..00000000
--- a/io_import_dxf/dxfgrabber/cytags.py
+++ /dev/null
@@ -1,7 +0,0 @@
-def __bootstrap__():
- global __bootstrap__, __loader__, __file__
- import sys, pkg_resources, imp
- __file__ = pkg_resources.resource_filename(__name__,'cytags.so')
- __loader__ = None; del __bootstrap__, __loader__
- imp.load_dynamic(__name__,__file__)
-__bootstrap__()
diff --git a/io_import_dxf/dxfgrabber/decode.py b/io_import_dxf/dxfgrabber/decode.py
index 3187cc8f..3187cc8f 100755..100644
--- a/io_import_dxf/dxfgrabber/decode.py
+++ b/io_import_dxf/dxfgrabber/decode.py
diff --git a/io_import_dxf/dxfgrabber/defaultchunk.py b/io_import_dxf/dxfgrabber/defaultchunk.py
index 5a280bd1..1df9969a 100755..100644
--- a/io_import_dxf/dxfgrabber/defaultchunk.py
+++ b/io_import_dxf/dxfgrabber/defaultchunk.py
@@ -9,14 +9,13 @@ from .tags import Tags, DXFTag
class DefaultChunk(object):
- def __init__(self, tags, drawing):
+ def __init__(self, tags):
assert isinstance(tags, Tags)
self.tags = tags
- self._drawing = drawing
@staticmethod
def from_tags(tags, drawing):
- return DefaultChunk(tags, drawing)
+ return DefaultChunk(tags)
@property
def name(self):
diff --git a/io_import_dxf/dxfgrabber/drawing.py b/io_import_dxf/dxfgrabber/drawing.py
index 1b275e86..f9a01faf 100755..100644
--- a/io_import_dxf/dxfgrabber/drawing.py
+++ b/io_import_dxf/dxfgrabber/drawing.py
@@ -5,7 +5,7 @@
__author__ = "mozman <mozman@gmx.at>"
-from .tags import TagIterator
+from .tags import stream_tagger
from .sections import Sections
DEFAULT_OPTIONS = {
@@ -23,7 +23,7 @@ class Drawing(object):
self.assure_3d_coords = options.get('assure_3d_coords', False)
self.resolve_text_styles = options.get('resolve_text_styles', True)
- tagreader = TagIterator(stream, self.assure_3d_coords)
+ tagreader = stream_tagger(stream, self.assure_3d_coords)
self.dxfversion = 'AC1009'
self.encoding = 'cp1252'
self.filename = None
diff --git a/io_import_dxf/dxfgrabber/dxf12.py b/io_import_dxf/dxfgrabber/dxf12.py
deleted file mode 100755
index 7663ae44..00000000
--- a/io_import_dxf/dxfgrabber/dxf12.py
+++ /dev/null
@@ -1,202 +0,0 @@
-# Purpose: DXF12 tag wrapper
-# Created: 21.07.2012, taken from my ezdxf project
-# Copyright (C) 2012, Manfred Moitzi
-# License: MIT License
-from __future__ import unicode_literals
-__author__ = "mozman <mozman@gmx.at>"
-
-
-from .dxfattr import DXFAttr, DXFAttributes, DefSubclass
-from .dxfentity import DXFEntity
-from . import const
-from .const import XTYPE_3D, XTYPE_2D_3D
-
-def make_attribs(additional=None):
- dxfattribs = {
- 'handle': DXFAttr(5),
- 'layer': DXFAttr(8), # layername as string, default is '0'
- 'linetype': DXFAttr(6), # linetype as string, special names BYLAYER/BYBLOCK, default is BYLAYER
- 'thickness': DXFAttr(39),
- 'color': DXFAttr(62), # dxf color index, 0 .. BYBLOCK, 256 .. BYLAYER, default is 256
- 'paperspace': DXFAttr(67), # 0 .. modelspace, 1 .. paperspace, default is 0
- 'extrusion': DXFAttr(210, XTYPE_3D),
- }
- if additional:
- dxfattribs.update(additional)
- return DXFAttributes(DefSubclass(None, dxfattribs))
-
-
-class Line(DXFEntity):
- DXFATTRIBS = make_attribs({
- 'start': DXFAttr(10, XTYPE_2D_3D),
- 'end': DXFAttr(11, XTYPE_2D_3D),
- })
-
-
-class Point(DXFEntity):
- DXFATTRIBS = make_attribs({
- 'point': DXFAttr(10, XTYPE_2D_3D),
- })
-
-
-class Circle(DXFEntity):
- DXFATTRIBS = make_attribs({
- 'center': DXFAttr(10, XTYPE_2D_3D),
- 'radius': DXFAttr(40),
- })
-
-
-class Arc(DXFEntity):
- DXFATTRIBS = make_attribs({
- 'center': DXFAttr(10, XTYPE_2D_3D),
- 'radius': DXFAttr(40),
- 'startangle': DXFAttr(50),
- 'endangle': DXFAttr(51),
- })
-
-
-class Trace(DXFEntity):
- DXFATTRIBS = make_attribs({
- 'vtx0': DXFAttr(10, XTYPE_2D_3D),
- 'vtx1': DXFAttr(11, XTYPE_2D_3D),
- 'vtx2': DXFAttr(12, XTYPE_2D_3D),
- 'vtx3': DXFAttr(13, XTYPE_2D_3D),
- })
-
-
-Solid = Trace
-
-
-class Face(DXFEntity):
- DXFATTRIBS = make_attribs({
- 'vtx0': DXFAttr(10, XTYPE_2D_3D),
- 'vtx1': DXFAttr(11, XTYPE_2D_3D),
- 'vtx2': DXFAttr(12, XTYPE_2D_3D),
- 'vtx3': DXFAttr(13, XTYPE_2D_3D),
- 'invisible_edge': DXFAttr(70),
- })
-
-
-class Text(DXFEntity):
- DXFATTRIBS = make_attribs({
- 'insert': DXFAttr(10, XTYPE_2D_3D),
- 'height': DXFAttr(40),
- 'text': DXFAttr(1),
- 'rotation': DXFAttr(50), # in degrees (circle = 360deg)
- 'oblique': DXFAttr(51), # in degrees, vertical = 0deg
- 'style': DXFAttr(7), # text style
- 'width': DXFAttr(41), # width FACTOR!
- 'textgenerationflag': DXFAttr(71), # 2 = backward (mirr-x), 4 = upside down (mirr-y)
- 'halign': DXFAttr(72), # horizontal justification
- 'valign': DXFAttr(73), # vertical justification
- 'alignpoint': DXFAttr(11, XTYPE_2D_3D),
- })
-
-
-class Insert(DXFEntity):
- DXFATTRIBS = make_attribs({
- 'attribsfollow': DXFAttr(66),
- 'name': DXFAttr(2),
- 'insert': DXFAttr(10, XTYPE_2D_3D),
- 'xscale': DXFAttr(41),
- 'yscale': DXFAttr(42),
- 'zscale': DXFAttr(43),
- 'rotation': DXFAttr(50),
- 'colcount': DXFAttr(70),
- 'rowcount': DXFAttr(71),
- 'colspacing': DXFAttr(44),
- 'rowspacing': DXFAttr(45),
- })
-
-
-class SeqEnd(DXFEntity):
- DXFATTRIBS = DXFAttributes(DefSubclass(None, {'handle': DXFAttr(5), 'paperspace': DXFAttr(67), }))
-
-
-class Attrib(DXFEntity): # also ATTDEF
- DXFATTRIBS = make_attribs({
- 'insert': DXFAttr(10, XTYPE_2D_3D),
- 'height': DXFAttr(40),
- 'text': DXFAttr(1),
- 'prompt': DXFAttr(3), # just in ATTDEF not ATTRIB
- 'tag': DXFAttr(2),
- 'flags': DXFAttr(70),
- 'fieldlength': DXFAttr(73),
- 'rotation': DXFAttr(50),
- 'oblique': DXFAttr(51),
- 'width': DXFAttr(41), # width factor
- 'style': DXFAttr(7),
- 'textgenerationflag': DXFAttr(71), # 2 = backward (mirr-x), 4 = upside down (mirr-y)
- 'halign': DXFAttr(72), # horizontal justification
- 'valign': DXFAttr(74), # vertical justification
- 'alignpoint': DXFAttr(11, XTYPE_2D_3D),
- })
-
-
-class Polyline(DXFEntity):
- DXFATTRIBS = make_attribs({
- 'elevation': DXFAttr(10, XTYPE_2D_3D),
- 'flags': DXFAttr(70),
- 'defaultstartwidth': DXFAttr(40),
- 'defaultendwidth': DXFAttr(41),
- 'mcount': DXFAttr(71),
- 'ncount': DXFAttr(72),
- 'msmoothdensity': DXFAttr(73),
- 'nsmoothdensity': DXFAttr(74),
- 'smoothtype': DXFAttr(75),
- })
-
- def get_vertex_flags(self):
- return const.VERTEX_FLAGS[self.get_mode()]
-
- @property
- def flags(self):
- return self.get_dxf_attrib('flags', 0)
-
- def get_mode(self):
- flags = self.flags
- if flags & const.POLYLINE_SPLINE_FIT_VERTICES_ADDED:
- return 'spline2d'
- elif flags & const.POLYLINE_3D_POLYLINE:
- return 'polyline3d'
- elif flags & const.POLYLINE_3D_POLYMESH:
- return 'polymesh'
- elif flags & const.POLYLINE_POLYFACE:
- return 'polyface'
- else:
- return 'polyline2d'
-
- def is_mclosed(self):
- return bool(self.flags & const.POLYLINE_MESH_CLOSED_M_DIRECTION)
-
- def is_nclosed(self):
- return bool(self.flags & const.POLYLINE_MESH_CLOSED_N_DIRECTION)
-
-
-class Vertex(DXFEntity):
- DXFATTRIBS = make_attribs({
- 'location': DXFAttr(10, XTYPE_2D_3D),
- 'startwidth': DXFAttr(40),
- 'endwidth': DXFAttr(41),
- 'bulge': DXFAttr(42),
- 'flags': DXFAttr(70),
- 'tangent': DXFAttr(50),
- 'vtx0': DXFAttr(71),
- 'vtx1': DXFAttr(72),
- 'vtx2': DXFAttr(73),
- 'vtx3': DXFAttr(74),
- })
-
-
-class Block(DXFEntity):
- DXFATTRIBS = make_attribs({
- 'name': DXFAttr(2),
- 'name2': DXFAttr(3),
- 'flags': DXFAttr(70),
- 'basepoint': DXFAttr(10, XTYPE_2D_3D),
- 'xrefpath': DXFAttr(1),
- })
-
-
-class EndBlk(SeqEnd):
- DXFATTRIBS = DXFAttributes(DefSubclass(None, {'handle': DXFAttr(5)}))
diff --git a/io_import_dxf/dxfgrabber/dxf13.py b/io_import_dxf/dxfgrabber/dxf13.py
deleted file mode 100755
index d88ada42..00000000
--- a/io_import_dxf/dxfgrabber/dxf13.py
+++ /dev/null
@@ -1,546 +0,0 @@
-# Purpose: DXF13 tag wrapper
-# Created: 21.07.2012, taken from my ezdxf project
-# Copyright (C) 2012, Manfred Moitzi
-# License: MIT License
-from __future__ import unicode_literals
-__author__ = "mozman <mozman@gmx.at>"
-
-
-from . import dxf12
-from .dxfentity import DXFEntity
-from .dxfattr import DXFAttr, DXFAttributes, DefSubclass
-from . import const
-from .const import XTYPE_2D, XTYPE_3D, XTYPE_2D_3D
-from .tags import Tags
-from .decode import decode
-
-none_subclass = DefSubclass(None, {
- 'handle': DXFAttr(5),
- 'block_record': DXFAttr(330), # Soft-pointer ID/handle to owner BLOCK_RECORD object
-})
-
-entity_subclass = DefSubclass('AcDbEntity', {
- 'paperspace': DXFAttr(67), # 0 .. modelspace, 1 .. paperspace, default is 0
- 'layer': DXFAttr(8), # layername as string, default is '0'
- 'linetype': DXFAttr(6), # linetype as string, special names BYLAYER/BYBLOCK, default is BYLAYER
- 'ltscale': DXFAttr(48), # linetype scale, default is 1.0
- 'invisible': DXFAttr(60), # invisible .. 1, visible .. 0, default is 0
- 'color': DXFAttr(62), # dxf color index, 0 .. BYBLOCK, 256 .. BYLAYER, default is 256
- 'true_color': DXFAttr(420), # true color as 0x00RRGGBB 24-bit value (since AC1018)
- 'transparency': DXFAttr(440), # transparency value 0x020000TT (since AC1018) 0 = fully transparent / 255 = opaque
- 'shadow_mode': DXFAttr(284), # shadow_mode (since AC1021)
- # 0 = Casts and receives shadows
- # 1 = Casts shadows
- # 2 = Receives shadows
- # 3 = Ignores shadows
-})
-
-line_subclass = DefSubclass('AcDbLine', {
- 'start': DXFAttr(10, XTYPE_2D_3D),
- 'end': DXFAttr(11, XTYPE_2D_3D),
- 'thickness': DXFAttr(39),
- 'extrusion': DXFAttr(210, XTYPE_3D),
-})
-
-
-class Line(dxf12.Line):
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, line_subclass)
-
-point_subclass = DefSubclass('AcDbPoint', {
- 'point': DXFAttr(10, XTYPE_2D_3D),
- 'thickness': DXFAttr(39),
- 'extrusion': DXFAttr(210, XTYPE_3D),
-})
-
-
-class Point(dxf12.Point):
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, point_subclass)
-
-
-circle_subclass = DefSubclass('AcDbCircle', {
- 'center': DXFAttr(10, XTYPE_2D_3D),
- 'radius': DXFAttr(40),
- 'thickness': DXFAttr(39),
- 'extrusion': DXFAttr(210, XTYPE_3D),
-})
-
-
-class Circle(dxf12.Circle):
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, circle_subclass)
-
-arc_subclass = DefSubclass('AcDbArc', {
- 'startangle': DXFAttr(50),
- 'endangle': DXFAttr(51),
-})
-
-
-class Arc(dxf12.Arc):
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, circle_subclass, arc_subclass)
-
-
-trace_subclass = DefSubclass('AcDbTrace', {
- 'vtx0': DXFAttr(10, XTYPE_2D_3D),
- 'vtx1': DXFAttr(11, XTYPE_2D_3D),
- 'vtx2': DXFAttr(12, XTYPE_2D_3D),
- 'vtx3': DXFAttr(13, XTYPE_2D_3D),
- 'thickness': DXFAttr(39),
- 'extrusion': DXFAttr(210, XTYPE_3D),
-})
-
-
-class Trace(dxf12.Trace):
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, trace_subclass)
-
-
-Solid = Trace
-
-
-face_subclass = DefSubclass('AcDbFace', {
- 'vtx0': DXFAttr(10, XTYPE_2D_3D),
- 'vtx1': DXFAttr(11, XTYPE_2D_3D),
- 'vtx2': DXFAttr(12, XTYPE_2D_3D),
- 'vtx3': DXFAttr(13, XTYPE_2D_3D),
- 'invisible_edge': DXFAttr(70),
-})
-
-
-class Face(dxf12.Face):
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, face_subclass)
-
-
-text_subclass = (
- DefSubclass('AcDbText', {
- 'insert': DXFAttr(10, XTYPE_2D_3D),
- 'height': DXFAttr(40),
- 'text': DXFAttr(1),
- 'rotation': DXFAttr(50), # in degrees (circle = 360deg)
- 'oblique': DXFAttr(51), # in degrees, vertical = 0deg
- 'style': DXFAttr(7), # text style
- 'width': DXFAttr(41), # width FACTOR!
- 'textgenerationflag': DXFAttr(71), # 2 = backward (mirr-x), 4 = upside down (mirr-y)
- 'halign': DXFAttr(72), # horizontal justification
- 'alignpoint': DXFAttr(11, XTYPE_2D_3D),
- 'thickness': DXFAttr(39),
- 'extrusion': DXFAttr(210, XTYPE_3D),
- }),
- DefSubclass('AcDbText', {'valign': DXFAttr(73)}))
-
-
-class Text(dxf12.Text):
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, *text_subclass)
-
-polyline_subclass = DefSubclass('AcDb2dPolyline', {
- 'elevation': DXFAttr(10, XTYPE_3D),
- 'flags': DXFAttr(70),
- 'defaultstartwidth': DXFAttr(40),
- 'defaultendwidth': DXFAttr(41),
- 'mcount': DXFAttr(71),
- 'ncount': DXFAttr(72),
- 'msmoothdensity': DXFAttr(73),
- 'nsmoothdensity': DXFAttr(74),
- 'smoothtype': DXFAttr(75),
- 'thickness': DXFAttr(39),
- 'extrusion': DXFAttr(210, XTYPE_3D),
-})
-
-
-class Polyline(dxf12.Polyline):
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, polyline_subclass)
-
-
-vertex_subclass = (
- DefSubclass('AcDbVertex', {}), # subclasses[2]
- DefSubclass('AcDb2dVertex', { # subclasses[3]
- 'location': DXFAttr(10, XTYPE_2D_3D),
- 'startwidth': DXFAttr(40),
- 'endwidth': DXFAttr(41),
- 'bulge': DXFAttr(42),
- 'flags': DXFAttr(70),
- 'tangent': DXFAttr(50),
- 'vtx0': DXFAttr(71),
- 'vtx1': DXFAttr(72),
- 'vtx2': DXFAttr(73),
- 'vtx3': DXFAttr(74),
- })
-)
-
-EMPTY_SUBCLASS = Tags()
-
-
-class Vertex(dxf12.Vertex):
- VTX3D = const.VTX_3D_POLYFACE_MESH_VERTEX | const.VTX_3D_POLYGON_MESH_VERTEX | const.VTX_3D_POLYLINE_VERTEX
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, *vertex_subclass)
-
- def post_read_correction(self):
- if self.tags.subclasses[2][0].value != 'AcDbVertex':
- self.tags.subclasses.insert(2, EMPTY_SUBCLASS) # create empty AcDbVertex subclass
-
-
-class SeqEnd(dxf12.SeqEnd):
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass)
-
-lwpolyline_subclass = DefSubclass('AcDbPolyline', {
- 'elevation': DXFAttr(38),
- 'thickness': DXFAttr(39),
- 'flags': DXFAttr(70),
- 'const_width': DXFAttr(43),
- 'count': DXFAttr(90),
- 'extrusion': DXFAttr(210, XTYPE_3D),
-})
-
-
-LWPOINTCODES = (10, 20, 40, 41, 42)
-
-
-class LWPolyline(DXFEntity):
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, lwpolyline_subclass)
-
- def __iter__(self):
- subclass = self.tags.subclasses[2] # subclass AcDbPolyline
-
- def get_vertex():
- point.append(attribs.get(40, 0))
- point.append(attribs.get(41, 0))
- point.append(attribs.get(42, 0))
- return tuple(point)
-
- point = None
- attribs = {}
- for tag in subclass:
- if tag.code in LWPOINTCODES:
- if tag.code == 10:
- if point is not None:
- yield get_vertex()
- point = list(tag.value)
- attribs = {}
- else:
- attribs[tag.code] = tag.value
- if point is not None:
- yield get_vertex() # last point
-
- def data(self):
- full_points = list(self)
- points = []
- width = []
- bulge = []
- for point in full_points:
- x = 2 if len(point) == 5 else 3
- points.append(point[:x])
- width.append((point[-3], point[-2]))
- bulge.append(point[-1])
- return points, width, bulge
-
- @property
- def flags(self):
- return self.get_dxf_attrib('flags', 0)
-
- def is_closed(self):
- return bool(self.flags & const.LWPOLYLINE_CLOSED)
-
-
-insert_subclass = DefSubclass('AcDbBlockReference', {
- 'attribsfollow': DXFAttr(66),
- 'name': DXFAttr(2),
- 'insert': DXFAttr(10, XTYPE_2D_3D),
- 'xscale': DXFAttr(41),
- 'yscale': DXFAttr(42),
- 'zscale': DXFAttr(43),
- 'rotation': DXFAttr(50),
- 'colcount': DXFAttr(70),
- 'rowcount': DXFAttr(71),
- 'colspacing': DXFAttr(44),
- 'rowspacing': DXFAttr(45),
- 'extrusion': DXFAttr(210, XTYPE_3D),
-})
-
-
-class Insert(dxf12.Insert):
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, insert_subclass)
-
-
-attrib_subclass = (
- DefSubclass('AcDbText', {
- 'insert': DXFAttr(10, XTYPE_2D_3D),
- 'thickness': DXFAttr(39),
- 'height': DXFAttr(40),
- 'text': DXFAttr(1),
- 'style': DXFAttr(7), # DXF-specs: 'AcDbAttribute'; AutoCAD: 'AcDbText'
- }),
- DefSubclass('AcDbAttribute', {
- 'tag': DXFAttr(2),
- 'flags': DXFAttr(70),
- 'fieldlength': DXFAttr(73),
- 'rotation': DXFAttr(50),
- 'width': DXFAttr(41),
- 'oblique': DXFAttr(51),
- 'textgenerationflag': DXFAttr(71),
- 'halign': DXFAttr(72),
- 'valign': DXFAttr(74),
- 'alignpoint': DXFAttr(11, XTYPE_2D_3D),
- 'extrusion': DXFAttr(210, XTYPE_3D),
- })
-)
-
-
-class Attrib(dxf12.Attrib):
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, *attrib_subclass)
-
-
-attdef_subclass = (
- DefSubclass('AcDbText', {
- 'insert': DXFAttr(10, XTYPE_2D_3D),
- 'thickness': DXFAttr(39),
- 'height': DXFAttr(40),
- 'text': DXFAttr(1),
- 'rotation': DXFAttr(50),
- 'width': DXFAttr(41),
- 'oblique': DXFAttr(51),
- 'style': DXFAttr(7),
- 'textgenerationflag': DXFAttr(71),
- 'halign': DXFAttr(72),
- 'alignpoint': DXFAttr(11),
- 'extrusion': DXFAttr(210),
- }),
- DefSubclass('AcDbAttributeDefinition', {
- 'prompt': DXFAttr(3),
- 'tag': DXFAttr(2),
- 'flags': DXFAttr(70),
- 'fieldlength': DXFAttr(73),
- 'valign': DXFAttr(74),
- }))
-
-
-class Attdef(dxf12.Attrib):
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, *attdef_subclass)
-
-
-ellipse_subclass = DefSubclass('AcDbEllipse', {
- 'center': DXFAttr(10, XTYPE_2D_3D),
- 'majoraxis': DXFAttr(11, XTYPE_2D_3D), # relative to the center
- 'extrusion': DXFAttr(210, XTYPE_3D),
- 'ratio': DXFAttr(40),
- 'startparam': DXFAttr(41), # this value is 0.0 for a full ellipse
- 'endparam': DXFAttr(42), # this value is 2*pi for a full ellipse
-})
-
-
-class Ellipse(DXFEntity):
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, ellipse_subclass)
-
-
-ray_subclass = DefSubclass('AcDbRay', {
- 'start': DXFAttr(10, XTYPE_3D),
- 'unitvector': DXFAttr(11, XTYPE_3D),
-})
-
-
-class Ray(DXFEntity):
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, ray_subclass)
-
-
-xline_subclass = DefSubclass('AcDbXline', {
- 'start': DXFAttr(10, XTYPE_3D),
- 'unitvector': DXFAttr(11, XTYPE_3D),
-})
-
-
-class XLine(DXFEntity):
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, xline_subclass)
-
-
-spline_subclass = DefSubclass('AcDbSpline', {
- 'normalvector': DXFAttr(210, XTYPE_3D), # omitted if spline is not planar
- 'flags': DXFAttr(70),
- 'degree': DXFAttr(71),
- 'nknots': DXFAttr(72),
- 'ncontrolpoints': DXFAttr(73),
- 'nfitcounts': DXFAttr(74),
- 'knot_tolerance': DXFAttr(42), # default 0.0000001
- 'controlpoint_tolerance': DXFAttr(43), # default 0.0000001
- 'fit_tolerance': DXFAttr(44), # default 0.0000000001
- 'starttangent': DXFAttr(12, XTYPE_3D), # optional
- 'endtangent': DXFAttr(13, XTYPE_3D), # optional
-})
-
-
-class Spline(DXFEntity):
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, spline_subclass)
-
- def knots(self):
- # groupcode 40, multiple values: nknots
- subclass = self.tags.subclasses[2] # subclass AcDbSpline
- return (tag.value for tag in subclass if tag.code == 40)
-
- def weights(self):
- # groupcode 41, multiple values
- subclass = self.tags.subclasses[2] # subclass AcDbSpline
- return (tag.value for tag in subclass if tag.code == 41)
-
- def controlpoints(self):
- # groupcode 10,20,30, multiple values: ncontrolpoints
- return self._get_points(10)
-
- def fitpoints(self):
- # groupcode 11,21,31, multiple values: nfitpoints
- return self._get_points(11)
-
- def _get_points(self, code):
- return (tag.value for tag in self.tags.subclasses[2] if tag.code == code)
-
-
-helix_subclass = DefSubclass('AcDbHelix', {
- 'helix_major_version': DXFAttr(90),
- 'helix_maintainance_version': DXFAttr(91),
- 'axis_base_point': DXFAttr(10, XTYPE_3D),
- 'start_point': DXFAttr(11, XTYPE_3D),
- 'axis_vector': DXFAttr(12, XTYPE_3D),
- 'radius': DXFAttr(40),
- 'turns': DXFAttr(41),
- 'turn_height': DXFAttr(42),
- 'handedness': DXFAttr(290), # 0 = left, 1 = right
- 'constrain': DXFAttr(280), # 0 = Constrain turn height; 1 = Constrain turns; 2 = Constrain height
-})
-
-
-class Helix(Spline):
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, spline_subclass, helix_subclass)
-
-mtext_subclass = DefSubclass('AcDbMText', {
- 'insert': DXFAttr(10, XTYPE_3D),
- 'height': DXFAttr(40),
- 'reference_rectangle_width': DXFAttr(41),
- 'horizontal_width': DXFAttr(42),
- 'vertical_height': DXFAttr(43),
- 'attachmentpoint': DXFAttr(71),
- 'text': DXFAttr(1), # also group code 3, if more than 255 chars
- 'style': DXFAttr(7), # text style
- 'extrusion': DXFAttr(210, XTYPE_3D),
- 'xdirection': DXFAttr(11, XTYPE_3D),
- 'rotation': DXFAttr(50), # xdirection beats rotation
- 'linespacing': DXFAttr(44), # valid from 0.25 to 4.00
-})
-
-
-class MText(DXFEntity):
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, mtext_subclass)
-
- def rawtext(self):
- subclass = self.tags.subclasses[2]
- lines = [tag.value for tag in subclass.find_all(3)]
- lines.append(self.get_dxf_attrib('text'))
- return ''.join(lines)
-
-block_subclass = (
- DefSubclass('AcDbEntity', {'layer': DXFAttr(8)}),
- DefSubclass('AcDbBlockBegin', {
- 'name': DXFAttr(2),
- 'name2': DXFAttr(3),
- 'description': DXFAttr(4),
- 'flags': DXFAttr(70),
- 'basepoint': DXFAttr(10, XTYPE_2D_3D),
- 'xrefpath': DXFAttr(1),
- })
-)
-
-
-class Block(dxf12.Block):
- DXFATTRIBS = DXFAttributes(none_subclass, *block_subclass)
-
-endblock_subclass = (
- DefSubclass('AcDbEntity', {'layer': DXFAttr(8)}),
- DefSubclass('AcDbBlockEnd', {}),
-)
-
-
-class EndBlk(dxf12.EndBlk):
- DXFATTRIBS = DXFAttributes(none_subclass, *endblock_subclass)
-
-sun_subclass = DefSubclass('AcDbSun', {
- 'version': DXFAttr(90),
- 'status': DXFAttr(290),
- 'sun_color': DXFAttr(63), # ??? DXF Color Index = (1 .. 255), 256 by layer
- 'intensity': DXFAttr(40),
- 'shadows': DXFAttr(291),
- 'date': DXFAttr(91), # Julian day
- 'time': DXFAttr(92), # Time (in seconds past midnight)
- 'daylight_savings_time': DXFAttr(292),
- 'shadow_type': DXFAttr(70), # 0 = Ray traced shadows; 1 = Shadow maps
- 'shadow_map_size': DXFAttr(71), # 0 = Ray traced shadows; 1 = Shadow maps
- 'shadow_softness': DXFAttr(280),
-})
-
-
-# SUN resides in the objects section and has no AcDbEntity subclass
-class Sun(DXFEntity):
- DXFATTRIBS = DXFAttributes(none_subclass, sun_subclass)
-
-mesh_subclass = DefSubclass('AcDbSubDMesh', {
- 'version': DXFAttr(71),
- 'blend_crease': DXFAttr(72), # 0 = off, 1 = on
- 'subdivision_levels': DXFAttr(91), # int >= 1
-})
-
-
-class Mesh(DXFEntity):
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, mesh_subclass)
-
-light_subclass = DefSubclass('AcDbLight', {
- 'version': DXFAttr(90),
- 'name': DXFAttr(1),
- 'light_type': DXFAttr(70), # distant = 1; point = 2; spot = 3
- 'status': DXFAttr(290),
- 'light_color': DXFAttr(63), # DXF Color Index = (1 .. 255), 256 by layer
- 'true_color': DXFAttr(421), # 24-bit color 0x00RRGGBB
- 'plot_glyph': DXFAttr(291),
- 'intensity': DXFAttr(40),
- 'position': DXFAttr(10, XTYPE_3D),
- 'target': DXFAttr(11, XTYPE_3D),
- 'attenuation_type': DXFAttr(72), # 0 = None; 1 = Inverse Linear; 2 = Inverse Square
- 'use_attenuation_limits': DXFAttr(292), # bool
- 'attenuation_start_limit': DXFAttr(41),
- 'attenuation_end_limit': DXFAttr(42),
- 'hotspot_angle': DXFAttr(50),
- 'fall_off_angle': DXFAttr(51),
- 'cast_shadows': DXFAttr(293),
- 'shadow_type': DXFAttr(73), # 0 = Ray traced shadows; 1 = Shadow maps
- 'shadow_map_size': DXFAttr(91),
- 'shadow_softness': DXFAttr(280),
-})
-
-
-class Light(DXFEntity):
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, light_subclass)
-
-
-modeler_geometry_subclass = DefSubclass('AcDbModelerGeometry', {
- 'version': DXFAttr(70),
-})
-
-
-class Body(DXFEntity):
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, modeler_geometry_subclass)
-
- def get_acis_data(self):
- # for AC1027 and later - ACIS data is stored in the ACDSDATA section in Standard ACIS Binary format
- geometry = self.tags.subclasses[2] # AcDbModelerGeometry
- return decode([tag.value for tag in geometry if tag.code in (1, 3)])
-
-solid3d_subclass = DefSubclass('AcDb3dSolid', {
- 'handle_to_history_object': DXFAttr(350),
-})
-
-# Region == Body
-
-
-class Solid3d(Body):
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, modeler_geometry_subclass, solid3d_subclass)
-
-
-surface_subclass = DefSubclass('AcDbSurface', {
- 'u_isolines': DXFAttr(71),
- 'v_isolines': DXFAttr(72),
-})
-
-
-class Surface(Body):
- DXFATTRIBS = DXFAttributes(none_subclass, entity_subclass, modeler_geometry_subclass, surface_subclass)
diff --git a/io_import_dxf/dxfgrabber/dxfattr.py b/io_import_dxf/dxfgrabber/dxfattr.py
deleted file mode 100755
index a98f038d..00000000
--- a/io_import_dxf/dxfgrabber/dxfattr.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# Purpose: define dxf attributes
-# Created: 21.07.2012, taken from my ezdxf project
-# Copyright (C) 2012, Manfred Moitzi
-# License: MIT License
-from __future__ import unicode_literals
-__author__ = "mozman <mozman@gmx.at>"
-
-from collections import namedtuple
-from .const import XTYPE_NONE
-
-
-def DXFAttr(code, xtype=XTYPE_NONE):
- # assert type(xtype) is int
- return _DXFAttr(code, xtype)
-
-_DXFAttr = namedtuple('DXFAttr', 'code xtype')
-DXFAttr3 = namedtuple('DXFAttr3', 'code xtype subclass')
-DefSubclass = namedtuple('DefSubclass', 'name attribs')
-
-
-class DXFAttributes(object):
- def __init__(self, *subclassdefs):
- self._subclasses = []
- self._attribs = {}
- for subclass in subclassdefs:
- self.add_subclass(subclass)
-
- def add_subclass(self, subclass):
- subclass_index = len(self._subclasses)
- self._subclasses.append(subclass)
- self._add_subclass_attribs(subclass, subclass_index)
-
- def _add_subclass_attribs(self, subclass, subclass_index):
- for name, dxfattrib in subclass.attribs.items():
- self._attribs[name] = DXFAttr3(dxfattrib.code, dxfattrib.xtype, subclass_index)
-
- def __getitem__(self, name):
- return self._attribs[name]
-
- def __contains__(self, name):
- return name in self._attribs
-
- def keys(self):
- return iter(self._attribs.keys())
-
- def subclasses(self):
- return iter(self._subclasses)
diff --git a/io_import_dxf/dxfgrabber/dxfentity.py b/io_import_dxf/dxfgrabber/dxfentity.py
deleted file mode 100755
index 26cfc436..00000000
--- a/io_import_dxf/dxfgrabber/dxfentity.py
+++ /dev/null
@@ -1,84 +0,0 @@
-# Purpose: generic tag wrapper
-# Created: 21.07.2012, taken from my ezdxf project
-# Copyright (C) 2012, Manfred Moitzi
-# License: MIT License
-from __future__ import unicode_literals
-__author__ = "mozman <mozman@gmx.at>"
-
-import os
-
-from .const import ENV_CYTHON, XTYPE_NONE, XTYPE_2D, XTYPE_3D, XTYPE_2D_3D
-
-cyDXFEntity = None
-OPTIMIZE = True
-if ENV_CYTHON in os.environ:
- if os.environ[ENV_CYTHON].upper() in ('1', 'ON', 'TRUE'):
- OPTIMIZE = True
- else:
- OPTIMIZE = False
-try:
- if OPTIMIZE:
- from.cydxfentity import cyDXFEntity
-except ImportError:
- pass
-
-
-class pyDXFEntity(object):
- DXFATTRIBS = {}
-
- def __init__(self, tags):
- self.tags = tags
-
- def dxftype(self):
- return self.tags.noclass[0].value
-
- def get_dxf_attrib(self, key, default=ValueError):
- # core function - every optimization is useful
- try:
- dxfattr = self.DXFATTRIBS[key]
- except KeyError:
- # attribute is not defined - returning the default value is useful
- # to query newer DXF attributes on older DXF files.
- # !! Problem: misspelled attributes with default values do not
- # raise an Exception !!
- if default is ValueError:
- raise ValueError("DXFAttrib '%s' is not defined." % key)
- else:
- return default
- try:
- return self._get_dxf_attrib(dxfattr)
- except ValueError: # attribute is defined but no value is present
- if default is ValueError:
- raise ValueError("DXFAttrib '%s': value is not present." % key)
- else:
- return default
-
- def _get_dxf_attrib(self, dxfattr):
- # no subclass is subclass index 0
- subclass_tags = self.tags.subclasses[dxfattr.subclass]
- xtype = dxfattr.xtype
- if xtype != XTYPE_NONE and xtype != XTYPE_2D_3D:
- return self._get_extented_type(subclass_tags, dxfattr.code, xtype)
- else:
- return subclass_tags.get_value(dxfattr.code)
-
- def paperspace(self):
- return self.get_dxf_attrib('paperspace', default=0) == 1
-
- def post_read_correction(self):
- pass
-
- @staticmethod
- def _get_extented_type(tags, code, xtype):
- value = tags.get_value(code)
- if len(value) == 2:
- if xtype == XTYPE_3D:
- return value[0], value[1], 0.
- elif xtype == XTYPE_2D:
- return value[0], value[1]
- return value
-
-if cyDXFEntity is not None:
- DXFEntity = cyDXFEntity
-else:
- DXFEntity = pyDXFEntity \ No newline at end of file
diff --git a/io_import_dxf/dxfgrabber/entities.py b/io_import_dxf/dxfgrabber/entities.py
deleted file mode 100755
index 937b05bd..00000000
--- a/io_import_dxf/dxfgrabber/entities.py
+++ /dev/null
@@ -1,930 +0,0 @@
-# encoding: utf-8
-# Purpose: entity classes
-# Created: 21.07.2012, parts taken from my ezdxf project
-# Copyright (C) 2012, Manfred Moitzi
-# License: MIT License
-from __future__ import unicode_literals
-__author__ = "mozman <mozman@gmx.at>"
-
-from . import dxf12, dxf13
-from . import const
-from .juliandate import calendar_date
-from datetime import datetime
-from .color import TrueColor
-import math
-
-from .styles import default_text_style
-
-SPECIAL_CHARS = {
- 'd': '°'
-}
-
-
-class SeqEnd(object):
- def __init__(self, wrapper):
- self.dxftype = wrapper.dxftype()
-
-
-class Entity(SeqEnd):
- def __init__(self, wrapper):
- super(Entity, self).__init__(wrapper)
- self.paperspace = bool(wrapper.paperspace())
-
-
-class Shape(Entity):
- def __init__(self, wrapper):
- super(Shape, self).__init__(wrapper)
- get_dxf = wrapper.get_dxf_attrib
- self.layer = get_dxf('layer', '0')
- self.linetype = get_dxf('linetype', None) # None=BYLAYER
- self.thickness = get_dxf('thickness', 0.0)
- self.extrusion = get_dxf('extrusion', (0., 0., 1.))
- self.ltscale = get_dxf('ltscale', 1.0)
- self.invisible = get_dxf('invisible', 0) # 0=visible
- self.color = get_dxf('color', const.BYLAYER) # 256=BYLAYER, 0=BYBLOCK
- self.true_color = get_dxf('true_color', None) # 0x00RRGGBB
- if self.true_color is not None:
- self.true_color = TrueColor(self.true_color)
- self.transparency = get_dxf('transparency', None) # 0x020000TT
- if self.transparency is not None:
- # 0.0 = opaque & 1.0 if fully transparent
- self.transparency = 1. - float(self.transparency & 0xFF) / 255.
- self.shadow_mode = get_dxf('shadow_mode', None)
- # 0 = Casts and receives shadows
- # 1 = Casts shadows
- # 2 = Receives shadows
- # 3 = Ignores shadows
-
- # if adding additional DXF attributes, do it also for PolyShape
-
-
-class PolyShape(object):
- """ Base class for Polyface and Polymesh, both are special cases of POLYLINE.
- """
- def __init__(self, polyline, dxftype):
- self.dxftype = dxftype
- self.paperspace = polyline.paperspace
- self.layer = polyline.layer
- self.linetype = polyline.linetype
- self.ltscale = polyline.ltscale
- self.invisible = polyline.invisible
- self.color = polyline.color
- self.true_color = polyline.true_color
- self.transparency = polyline.transparency
- self.shadow_mode = polyline.shadow_mode
-
-
-class Line(Shape):
- def __init__(self, wrapper):
- super(Line, self).__init__(wrapper)
- self.start = wrapper.get_dxf_attrib('start')
- self.end = wrapper.get_dxf_attrib('end')
-
-
-class Point(Shape):
- def __init__(self, wrapper):
- super(Point, self).__init__(wrapper)
- self.point = wrapper.get_dxf_attrib('point')
-
-
-class Circle(Shape):
- def __init__(self, wrapper):
- super(Circle, self).__init__(wrapper)
- self.center = wrapper.get_dxf_attrib('center')
- self.radius = wrapper.get_dxf_attrib('radius')
-
-
-class Arc(Shape):
- def __init__(self, wrapper):
- super(Arc, self).__init__(wrapper)
- get_dxf = wrapper.get_dxf_attrib
- self.center = get_dxf('center')
- self.radius = get_dxf('radius')
- self.startangle = get_dxf('startangle')
- self.endangle = get_dxf('endangle')
-
-
-class Trace(Shape):
- def __init__(self, wrapper):
- super(Trace, self).__init__(wrapper)
- get_dxf = wrapper.get_dxf_attrib
- self.points = [
- get_dxf(vname) for vname in const.VERTEXNAMES
- ]
-
-Solid = Trace
-
-
-class Face(Trace):
- def __init__(self, wrapper):
- super(Face, self).__init__(wrapper)
- self.invisible_edge = wrapper.get_dxf_attrib('invisible_edge', 0)
-
- def is_edge_invisible(self, edge):
- # edges 0 .. 3
- return bool(self.invisible_edge & (1 << edge))
-
-
-class Text(Shape):
- def __init__(self, wrapper):
- super(Text, self).__init__(wrapper)
- get_dxf = wrapper.get_dxf_attrib
- self.insert = get_dxf('insert')
- self.text = get_dxf('text')
- self.height = get_dxf('height', 0)
- self.width = get_dxf('width', 0)
- self.oblique = get_dxf('oblique', None)
- self.rotation = get_dxf('rotation', 0.)
- self.style = get_dxf('style', "")
- self.halign = get_dxf('halign', 0)
- self.valign = get_dxf('valign', 0)
- self.alignpoint = get_dxf('alignpoint', None)
- if get_dxf('textgenerationflag', None) is not None:
- self.is_backwards = bool(get_dxf('textgenerationflag', 0) & 2)
- self.is_upside_down = bool(get_dxf('textgenerationflag', 0) & 4)
- else:
- self.is_backwards = None
- self.is_upside_down = None
- self.font = ""
- self.bigfont = ""
-
- def resolve_text_style(self, text_styles):
- style = text_styles.get(self.style, None)
- if style is None:
- style = default_text_style
- if self.height == 0:
- self.height = style.height
- if self.width == 0:
- self.width = style.width
- if self.oblique is None:
- self.oblique = style.oblique
- if self.is_backwards is None:
- self.is_backwards = style.is_backwards
- if self.is_upside_down is None:
- self.is_upside_down = style.is_upside_down
- if self.font is None:
- self.font = style.font
- if self.bigfont is None:
- self.bigfont = style.bigfont
-
- def plain_text(self):
- chars = []
- raw_chars = list(reversed(self.text)) # text splitted into chars, in reversed order for efficient pop()
- while len(raw_chars):
- char = raw_chars.pop()
- if char == '%': # formatting codes and special characters
- if len(raw_chars) and raw_chars[-1] == '%':
- raw_chars.pop() # '%'
- if len(raw_chars):
- special_char = raw_chars.pop() # command char
- chars.append(SPECIAL_CHARS.get(special_char, ""))
- else: # char is just a single '%'
- chars.append(char)
- else: # char is what it is, a character
- chars.append(char)
- return "".join(chars)
-
-
-class Insert(Shape):
- def __init__(self, wrapper):
- super(Insert, self).__init__(wrapper)
- get_dxf = wrapper.get_dxf_attrib
- self.name = get_dxf('name')
- self.insert = get_dxf('insert')
- self.rotation = get_dxf('rotation', 0.)
- self.scale = get_dxf('xscale', 1.), get_dxf('yscale', 1.), get_dxf('zscale', 1.)
- self.row_count = get_dxf('rowcount', 1)
- self.row_spacing = get_dxf('rowspacing', 0.)
- self.col_count = get_dxf('colcount', 1)
- self.col_spacing = get_dxf('colspacing', 0.)
- self.attribsfollow = bool(get_dxf('attribsfollow', 0))
- self.attribs = []
-
- def find_attrib(self, attrib_tag):
- for attrib in self.attribs:
- if attrib.tag == attrib_tag:
- return attrib
- return None
-
- def append_data(self, attribs):
- self.attribs = attribs
-
-
-class Attrib(Text): # also ATTDEF
- def __init__(self, wrapper):
- super(Attrib, self).__init__(wrapper)
- self.tag = wrapper.get_dxf_attrib('tag')
-
-_LINE_TYPES = frozenset(('spline2d', 'polyline2d', 'polyline3d'))
-
-
-class Polyline(Shape):
- def __init__(self, wrapper):
- super(Polyline, self).__init__(wrapper)
- self.vertices = [] # set in append data
- self.points = [] # set in append data
- self.controlpoints = [] # set in append data
- self.width = [] # set in append data
- self.bulge = [] # set in append data
- self.tangents = [] # set in append data
- self.flags = wrapper.flags
- self.mode = wrapper.get_mode()
- get_dxf = wrapper.get_dxf_attrib
- self.mcount = get_dxf('mcount', 0)
- self.ncount = get_dxf('ncount', 0)
- self.default_start_width = get_dxf('defaultstartwidth', 0.)
- self.default_end_width = get_dxf('defaultendwidth', 0.)
- self.is_mclosed = wrapper.is_mclosed()
- self.is_nclosed = wrapper.is_nclosed()
- self.elevation = get_dxf('elevation', (0., 0., 0.))
- self.m_smooth_density = get_dxf('msmoothdensity', 0.)
- self.n_smooth_density = get_dxf('nsmoothdensity', 0.)
- self.smooth_type = get_dxf('smoothtype', 0)
- self.spline_type = None
- if self.mode == 'spline2d':
- if self.smooth_type == const.POLYMESH_CUBIC_BSPLINE:
- self.spline_type = 'cubic_bspline'
- elif self.smooth_type == const.POLYMESH_QUADRIC_BSPLINE:
- self.spline_type = 'quadratic_bspline'
- elif self.smooth_type == const.POLYMESH_BEZIER_SURFACE:
- self.spline_type = 'bezier_curve' # is this a valid spline type for DXF12?
-
- def __len__(self):
- return len(self.vertices)
-
- def __getitem__(self, item):
- return self.vertices[item]
-
- def __iter__(self):
- return iter(self.vertices)
-
- @property
- def is_closed(self):
- return self.is_mclosed
-
- @is_closed.setter
- def is_closed(self, status):
- self.is_mclosed = status
-
- def append_data(self, vertices):
- def default_width(start_width, end_width):
- if start_width == 0.:
- start_width = self.default_start_width
- if end_width == 0.:
- end_width = self.default_end_width
- return start_width, end_width
-
- self.vertices = vertices
- if self.mode in _LINE_TYPES:
- for vertex in self.vertices:
- if vertex.flags & const.VTX_SPLINE_FRAME_CONTROL_POINT:
- self.controlpoints.append(vertex.location)
- else:
- self.points.append(vertex.location)
- self.width.append(default_width(vertex.start_width, vertex.end_width))
- self.bulge.append(vertex.bulge)
- self.tangents.append(vertex.tangent if vertex.flags & const.VTX_CURVE_FIT_TANGENT else None)
-
- def cast(self):
- if self.mode == 'polyface':
- return Polyface(self)
- elif self.mode == 'polymesh':
- return Polymesh(self)
- else:
- return self
-
-
-class SubFace(object):
- def __init__(self, face_record, vertices):
- self._vertices = vertices
- self.face_record = face_record
-
- def __len__(self):
- return len(self.face_record.vtx)
-
- def __getitem__(self, item):
- return self._vertices[self._vertex_index(item)]
-
- def __iter__(self):
- return (self._vertices[index].location for index in self.indices())
-
- def _vertex_index(self, pos):
- return abs(self.face_record.vtx[pos]) - 1
-
- def indices(self):
- return tuple(abs(i)-1 for i in self.face_record.vtx if i != 0)
-
- def is_edge_visible(self, pos):
- return self.face_record.vtx[pos] > 0
-
-
-class Polyface(PolyShape):
- def __init__(self, polyline):
- VERTEX_FLAGS = const.VTX_3D_POLYFACE_MESH_VERTEX + const.VTX_3D_POLYGON_MESH_VERTEX
-
- def is_vertex(flags):
- return flags & VERTEX_FLAGS == VERTEX_FLAGS
-
- super(Polyface, self).__init__(polyline, 'POLYFACE')
- vertices = []
- face_records = []
- for vertex in polyline.vertices:
- (vertices if is_vertex(vertex.flags) else face_records).append(vertex)
-
- self.vertices = vertices
- self._face_records = face_records
-
- def __getitem__(self, item):
- return SubFace(self._face_records[item], self.vertices)
-
- def __len__(self):
- return len(self._face_records)
-
- def __iter__(self):
- return (SubFace(f, self.vertices) for f in self._face_records)
-
-
-class Polymesh(PolyShape):
- def __init__(self, polyline):
- super(Polymesh, self).__init__(polyline, 'POLYMESH')
- self.mcount = polyline.mcount
- self.ncount = polyline.ncount
- self.is_mclosed = polyline.is_mclosed
- self.is_nclosed = polyline.is_nclosed
- self._vertices = polyline.vertices
- self.m_smooth_density = polyline.m_smooth_density
- self.n_smooth_density = polyline.n_smooth_density
- self.smooth_type = polyline.smooth_type
-
- def __iter__(self):
- return iter(self._vertices)
-
- def get_location(self, pos):
- return self.get_vertex(pos).location
-
- def get_vertex(self, pos):
- mcount = self.mcount
- ncount = self.ncount
- m, n = pos
- if 0 <= m < mcount and 0 <= n < ncount:
- pos = m * ncount + n
- return self._vertices[pos]
- else:
- raise IndexError(repr(pos))
-
-
-class Vertex(Shape):
- def __init__(self, wrapper):
- super(Vertex, self).__init__(wrapper)
- get_dxf = wrapper.get_dxf_attrib
- self.location = get_dxf('location')
- self.flags = get_dxf('flags', 0)
- self.start_width = get_dxf('startwidth', 0)
- self.end_width = get_dxf('endwidth', 0)
- self.bulge = get_dxf('bulge', 0)
- self.tangent = get_dxf('tangent', None)
- self.vtx = self._get_vtx(wrapper)
-
- def _get_vtx(self, wrapper):
- vtx = []
- get_dxf = wrapper.get_dxf_attrib
- for vname in const.VERTEXNAMES:
- try:
- vtx.append(get_dxf(vname))
- except ValueError:
- pass
- return tuple(vtx)
-
-
-class LWPolyline(Shape):
- def __init__(self, wrapper):
- super(LWPolyline, self).__init__(wrapper)
- self.points, self.width, self.bulge = wrapper.data()
- self.const_width = wrapper.get_dxf_attrib('const_width', 0)
- self.is_closed = wrapper.is_closed()
- self.elevation = wrapper.get_dxf_attrib('elevation', (0., 0., 0.))
-
- def __len__(self):
- return len(self.points)
-
- def __getitem__(self, item):
- return self.points[item]
-
- def __iter__(self):
- return iter(self.points)
-
-
-class Ellipse(Shape):
- def __init__(self, wrapper):
- super(Ellipse, self).__init__(wrapper)
- get_dxf = wrapper.get_dxf_attrib
- self.center = get_dxf('center')
- self.majoraxis = get_dxf('majoraxis')
- self.ratio = get_dxf('ratio', 1.0) # circle
- self.startparam = get_dxf('startparam', 0.)
- self.endparam = get_dxf('endparam', 6.283185307179586) # 2*pi
-
-
-class Ray(Shape):
- def __init__(self, wrapper):
- super(Ray, self).__init__(wrapper)
- self.start = wrapper.get_dxf_attrib('start')
- self.unitvector = wrapper.get_dxf_attrib('unitvector')
-
-XLine = Ray
-
-
-class Spline(Shape):
- def __init__(self, wrapper):
- super(Spline, self).__init__(wrapper)
- get_dxf = wrapper.get_dxf_attrib
- self.normalvector = get_dxf('normalvector', None)
- self.flags = get_dxf('flags', 0)
- self.degree = get_dxf('degree', 3)
- self.starttangent = get_dxf('starttangent', None)
- self.endtangent = get_dxf('endtangent', None)
- self.knots = tuple(wrapper.knots())
- self.weights = tuple(wrapper.weights())
- self.tol_knot = get_dxf('knot_tolernace', .0000001)
- self.tol_controlpoint = get_dxf('controlpoint_tolerance', .0000001)
- self.tol_fitpoint = get_dxf('fitpoint_tolerance', .0000000001)
- self.controlpoints = tuple(wrapper.controlpoints())
- self.fitpoints = tuple(wrapper.fitpoints())
- if len(self.weights) == 0:
- self.weights = tuple([1.0] * len(self.controlpoints))
-
- @property
- def is_closed(self):
- return bool(self.flags & const.SPLINE_CLOSED)
-
- @property
- def is_periodic(self):
- return bool(self.flags & const.SPLINE_PERIODIC)
-
- @property
- def is_rational(self):
- return bool(self.flags & const.SPLINE_RATIONAL)
-
- @property
- def is_planar(self):
- return bool(self.flags & const.SPLINE_PLANAR)
-
- @property
- def is_linear(self):
- return bool(self.flags & const.SPLINE_LINEAR)
-
-
-class Helix(Spline):
- def __init__(self, wrapper):
- super(Helix, self).__init__(wrapper)
- get_dxf = wrapper.get_dxf_attrib
- self.helix_version = (get_dxf('helix_major_version', 1),
- get_dxf('helix_maintainance_version', 1))
- self.axis_base_point = get_dxf('axis_base_point', None)
- self.start_point = get_dxf('start_point', None)
- self.axis_vector = get_dxf('axis_vector', None)
- self.radius = get_dxf('radius', 0)
- self.turns = get_dxf('turns', 0)
- self.turn_height = get_dxf('turn_height', 0)
- self.handedness = get_dxf('handedness', 0) # 0 = left, 1 = right
- self.constrain = get_dxf('constrain', 0)
- # 0 = Constrain turn height;
- # 1 = Constrain turns;
- # 2 = Constrain height
-
-
-def deg2vec(deg):
- rad = float(deg) * math.pi / 180.0
- return math.cos(rad), math.sin(rad), 0.
-
-
-def normalized(vector):
- x, y, z = vector
- m = (x**2 + y**2 + z**2)**0.5
- return x/m, y/m, z/m
-
-##################################################
-# MTEXT inline codes
-# \L Start underline
-# \l Stop underline
-# \O Start overstrike
-# \o Stop overstrike
-# \K Start strike-through
-# \k Stop strike-through
-# \P New paragraph (new line)
-# \pxi Control codes for bullets, numbered paragraphs and columns
-# \X Paragraph wrap on the dimension line (only in dimensions)
-# \Q Slanting (obliquing) text by angle - e.g. \Q30;
-# \H Text height - e.g. \H3x;
-# \W Text width - e.g. \W0.8x;
-# \F Font selection
-#
-# e.g. \Fgdt;o - GDT-tolerance
-# e.g. \Fkroeger|b0|i0|c238|p10 - font Kroeger, non-bold, non-italic, codepage 238, pitch 10
-#
-# \S Stacking, fractions
-#
-# e.g. \SA^B:
-# A
-# B
-# e.g. \SX/Y:
-# X
-# -
-# Y
-# e.g. \S1#4:
-# 1/4
-#
-# \A Alignment
-#
-# \A0; = bottom
-# \A1; = center
-# \A2; = top
-#
-# \C Color change
-#
-# \C1; = red
-# \C2; = yellow
-# \C3; = green
-# \C4; = cyan
-# \C5; = blue
-# \C6; = magenta
-# \C7; = white
-#
-# \T Tracking, char.spacing - e.g. \T2;
-# \~ Non-wrapping space, hard space
-# {} Braces - define the text area influenced by the code
-# \ Escape character - e.g. \\ = "\", \{ = "{"
-#
-# Codes and braces can be nested up to 8 levels deep
-
-ESCAPED_CHARS = "\\{}"
-GROUP_CHARS = "{}"
-ONE_CHAR_COMMANDS = "PLlOoKkX"
-
-
-class MText(Shape):
- def __init__(self, wrapper):
-
- super(MText, self).__init__(wrapper)
- self.insert = wrapper.get_dxf_attrib('insert')
- self.rawtext = wrapper.rawtext()
- get_dxf = wrapper.get_dxf_attrib
- self.height = get_dxf('height', 0)
- self.rect_width = get_dxf('reference_rectangle_width', None)
- self.horizontal_width = get_dxf('horizontal_width', None)
- self.vertical_height = get_dxf('vertical_height', None)
- self.linespacing = get_dxf('linespacing', 1.0)
- self.attachmentpoint = get_dxf('attachmentpoint', 1)
- self.style = get_dxf('style', 'STANDARD')
- self.extrusion = get_dxf('extrusion', (0., 0., 1.))
- try:
- xdir = wrapper.get_dxf_attrib('xdirection')
- except ValueError:
- xdir = deg2vec(get_dxf('rotation', 0.0))
- self.xdirection = normalized(xdir)
- self.font = None
- self.bigfont = None
-
- def lines(self):
- return self.rawtext.split('\P')
-
- def plain_text(self, split=False):
- chars = []
- raw_chars = list(reversed(self.rawtext)) # text splitted into chars, in reversed order for efficient pop()
- while len(raw_chars):
- char = raw_chars.pop()
- if char == '\\': # is a formatting command
- try:
- char = raw_chars.pop()
- except IndexError:
- break # premature end of text - just ignore
-
- if char in ESCAPED_CHARS: # \ { }
- chars.append(char)
- elif char in ONE_CHAR_COMMANDS:
- if char == 'P': # new line
- chars.append('\n')
- # discard other commands
- else: # more character commands are terminated by ';'
- stacking = char == 'S' # stacking command surrounds user data
- try:
- while char != ';': # end of format marker
- char = raw_chars.pop()
- if stacking and char != ';':
- chars.append(char) # append user data of stacking command
- except IndexError:
- break # premature end of text - just ignore
- elif char in GROUP_CHARS: # { }
- pass # discard group markers
- elif char == '%': # special characters
- if len(raw_chars) and raw_chars[-1] == '%':
- raw_chars.pop() # discard next '%'
- if len(raw_chars):
- special_char = raw_chars.pop()
- # replace or discard formatting code
- chars.append(SPECIAL_CHARS.get(special_char, ""))
- else: # char is just a single '%'
- chars.append(char)
- else: # char is what it is, a character
- chars.append(char)
-
- plain_text = "".join(chars)
- return plain_text.split('\n') if split else plain_text
-
- def resolve_text_style(self, text_styles):
- style = text_styles.get(self.style, None)
- if style is None:
- style = default_text_style
- if self.height == 0:
- self.height = style.height
- if self.font is None:
- self.font = style.font
- if self.bigfont is None:
- self.bigfont = style.font
-
-
-class Block(Shape):
- def __init__(self, wrapper):
- super(Block, self).__init__(wrapper)
- self.basepoint = wrapper.get_dxf_attrib('basepoint')
- self.name = wrapper.get_dxf_attrib('name')
- self.flags = wrapper.get_dxf_attrib('flags', 0)
- self.xrefpath = wrapper.get_dxf_attrib('xrefpath', "")
- self._entities = list()
-
- @property
- def is_xref(self):
- return bool(self.flags & const.BLK_XREF)
-
- @property
- def is_xref_overlay(self):
- return bool(self.flags & const.BLK_XREF_OVERLAY)
-
- @property
- def is_anonymous(self):
- return bool(self.flags & const.BLK_ANONYMOUS)
-
- def set_entities(self, entities):
- self._entities = entities
-
- def __iter__(self):
- return iter(self._entities)
-
- def __getitem__(self, item):
- return self._entities[item]
-
- def __len__(self):
- return len(self._entities)
-
-
-class BlockEnd(SeqEnd):
- pass
-
-
-def unpack_seconds(seconds):
- seconds = int(seconds / 1000) # remove 1/1000 part
- hours = int(seconds / 3600)
- seconds = int(seconds % 3600)
- minutes = int(seconds / 60)
- seconds = int(seconds % 60)
- return hours, minutes, seconds
-
-
-class Sun(Entity):
- def __init__(self, wrapper):
- super(Sun, self).__init__(wrapper)
- get_dxf = wrapper.get_dxf_attrib
- self.version = get_dxf('version', 1)
- self.status = bool(get_dxf('status', 0)) # on/off ?
- self.sun_color = get_dxf('sun_color', None) # None is unset
- self.intensity = get_dxf('intensity', 0)
- self.shadows = bool(get_dxf('shadows', 0))
- julian_date = get_dxf('date', 0.)
- if julian_date > 0.:
- date = calendar_date(julian_date)
- else:
- date = datetime.now()
- hours, minutes, seconds = unpack_seconds(get_dxf('time', 0))
- self.date = datetime(date.year, date.month, date.day, hours, minutes, seconds)
- self.daylight_savings_time = bool(get_dxf('daylight_savings_time', 0))
- self.shadow_type = get_dxf('shadows_type', 0)
- self.shadow_map_size = get_dxf('shadow_map_size', 0)
- self.shadow_softness = get_dxf('shadow_softness', 0)
-
-
-class Mesh(Shape):
- def __init__(self, wrapper):
- super(Mesh, self).__init__(wrapper)
- get_dxf = wrapper.get_dxf_attrib
- self.version = get_dxf('version', 2)
- self.blend_crease = bool(get_dxf('blend_crease', 0))
- self.subdivision_levels = get_dxf('subdivision_levels', 1)
- # rest are mostly positional tags
- self.vertices = []
- self.faces = []
- self.edges = []
- self.edge_crease_list = []
-
- subdmesh_tags = wrapper.tags.get_subclass('AcDbSubDMesh')
- # for all blocks I ignore the count values, perhaps they are wrong,
- # but I use the count tags as indicator for the begin of the list
- try:
- pos = subdmesh_tags.tag_index(92)
- except ValueError: # no vertices???
- return
- else:
- self.vertices = Mesh.get_vertices(subdmesh_tags, pos+1)
- try:
- pos = subdmesh_tags.tag_index(93)
- except ValueError: # no faces???
- pass
- else:
- self.faces = Mesh.get_faces(subdmesh_tags, pos+1)
- try:
- pos = subdmesh_tags.tag_index(94)
- except ValueError: # no edges
- pass
- else:
- self.edges = Mesh.get_edges(subdmesh_tags, pos+1)
- try:
- pos = subdmesh_tags.tag_index(95)
- except ValueError: # no edges crease values
- pass
- else:
- self.edge_crease_list = Mesh.get_edge_crease_list(subdmesh_tags, pos+1)
-
- def get_face(self, index):
- return tuple(self.vertices[vertex_index] for vertex_index in self.faces[index])
-
- def get_edge(self, index):
- return tuple(self.vertices[vertex_index] for vertex_index in self.edges[index])
-
- @staticmethod
- def get_vertices(tags, pos):
- vertices = []
- itags = iter(tags[pos:])
- while True:
- try:
- tag = next(itags)
- except StopIteration: # premature end of tags, return what you got
- break
- if tag.code == 10:
- vertices.append(tag.value)
- else:
- break
- return vertices
-
- @staticmethod
- def get_faces(tags, pos):
- faces = []
- face = []
- itags = iter(tags[pos:])
- try:
- while True:
- tag = next(itags)
- # loop until first tag.code != 90
- if tag.code != 90:
- break
- count = tag.value # count of vertex indices
- while count > 0:
- tag = next(itags)
- face.append(tag.value)
- count -= 1
- faces.append(tuple(face))
- del face[:]
- except StopIteration: # premature end of tags, return what you got
- pass
- return faces
-
- @staticmethod
- def get_edges(tags, pos):
- edges = []
- start_index = None
- for index in Mesh.get_raw_list(tags, pos, code=90):
- if start_index is None:
- start_index = index
- else:
- edges.append((start_index, index))
- start_index = None
- return edges
-
- @staticmethod
- def get_edge_crease_list(tags, pos):
- return Mesh.get_raw_list(tags, pos, code=140)
-
- @staticmethod
- def get_raw_list(tags, pos, code):
- raw_list = []
- itags = iter(tags[pos:])
- while True:
- try:
- tag = next(itags)
- except StopIteration:
- break
- if tag.code == code:
- raw_list.append(tag.value)
- else:
- break
- return raw_list
-
-
-class Light(Shape):
- def __init__(self, wrapper):
- super(Light, self).__init__(wrapper)
- get_dxf = wrapper.get_dxf_attrib
- self.version = get_dxf('version', 1)
- self.name = get_dxf('name', "")
- self.light_type = get_dxf('light_type', 1) # distant = 1; point = 2; spot = 3
- self.status = bool(get_dxf('status', 0)) # on/off ?
- self.light_color = get_dxf('light_color', None) # 0 is unset
- self.true_color = get_dxf('true_color', None) # None is unset
- self.plot_glyph = bool(get_dxf('plot_glyph', 0))
- self.intensity = get_dxf('intensity', 0)
- self.position = get_dxf('position', (0, 0, 1))
- self.target = get_dxf('target', (0, 0, 0))
- self.attenuation_type = get_dxf('attenuation_type', 0) # 0 = None; 1 = Inverse Linear; 2 = Inverse Square
- self.use_attenuation_limits = bool(get_dxf('use_attenuation_limits', 0))
- self.attenuation_start_limit = get_dxf('attenuation_start_limit', 0)
- self.attenuation_end_limit = get_dxf('attenuation_end_limit', 0)
- self.hotspot_angle = get_dxf('hotspot_angle', 0)
- self.fall_off_angle = get_dxf('fall_off_angle', 0)
- self.cast_shadows = bool(get_dxf('cast_shadows', 0))
- self.shadow_type = get_dxf('shadow_type', 0) # 0 = Ray traced shadows; 1 = Shadow maps
- self.shadow_map_size = get_dxf('shadow_map_size', 0)
- self.shadow_softness = get_dxf('shadow_softness', 0)
-
-
-class Body(Shape):
- def __init__(self, wrapper):
- super(Body, self).__init__(wrapper)
- # need handle to get SAB data in DXF version AC1027 and later
- self.handle = wrapper.get_dxf_attrib('handle', None)
- self.version = wrapper.get_dxf_attrib('version', 1)
- self.acis = wrapper.get_acis_data()
-
- def set_sab_data(self, sab_data):
- self.acis = sab_data
-
- @property
- def is_sat(self):
- return isinstance(self.acis, list) # but could be an empty list
-
- @property
- def is_sab(self):
- return not self.is_sat # has binary encoded ACIS data
-
-Solid3d = Body
-# perhaps reading creation history is needed
-
-
-class Surface(Body):
- def __init__(self, wrapper):
- super(Surface, self).__init__(wrapper)
- self.u_isolines = wrapper.get_dxf_attrib('u_isolines', 0)
- self.v_isolines = wrapper.get_dxf_attrib('v_isolines', 0)
-
-
-EntityTable = {
- 'LINE': (Line, dxf12.Line, dxf13.Line),
- 'POINT': (Point, dxf12.Point, dxf13.Point),
- 'CIRCLE': (Circle, dxf12.Circle, dxf13.Circle),
- 'ARC': (Arc, dxf12.Arc, dxf13.Arc),
- 'TRACE': (Trace, dxf12.Trace, dxf13.Trace),
- 'SOLID': (Solid, dxf12.Solid, dxf13.Solid),
- '3DFACE': (Face, dxf12.Face, dxf13.Face),
- 'TEXT': (Text, dxf12.Text, dxf13.Text),
- 'INSERT': (Insert, dxf12.Insert, dxf13.Insert),
- 'SEQEND': (SeqEnd, dxf12.SeqEnd, dxf13.SeqEnd),
- 'ATTRIB': (Attrib, dxf12.Attrib, dxf13.Attrib),
- 'ATTDEF': (Attrib, dxf12.Attrib, dxf13.Attdef),
- 'POLYLINE': (Polyline, dxf12.Polyline, dxf13.Polyline),
- 'VERTEX': (Vertex, dxf12.Vertex, dxf13.Vertex),
- 'BLOCK': (Block, dxf12.Block, dxf13.Block),
- 'ENDBLK': (BlockEnd, dxf12.EndBlk, dxf13.EndBlk),
- 'LWPOLYLINE': (LWPolyline, None, dxf13.LWPolyline),
- 'ELLIPSE': (Ellipse, None, dxf13.Ellipse),
- 'RAY': (Ray, None, dxf13.Ray),
- 'XLINE': (XLine, None, dxf13.XLine),
- 'SPLINE': (Spline, None, dxf13.Spline),
- 'HELIX': (Helix, None, dxf13.Helix),
- 'MTEXT': (MText, None, dxf13.MText),
- 'SUN': (Sun, None, dxf13.Sun),
- 'MESH': (Mesh, None, dxf13.Mesh),
- 'LIGHT': (Light, None, dxf13.Light),
- 'BODY': (Body, None, dxf13.Body),
- 'REGION': (Body, None, dxf13.Body),
- '3DSOLID': (Solid3d, None, dxf13.Solid3d),
- 'SURFACE': (Surface, None, dxf13.Surface),
- 'PLANESURFACE': (Surface, None, dxf13.Surface),
-}
-
-
-def entity_factory(tags, dxfversion):
- dxftype = tags.get_type()
- cls, dxf12wrapper, dxf13wrapper = EntityTable[dxftype]
- wrapper = dxf12wrapper(tags) if dxfversion == "AC1009" else dxf13wrapper(tags)
- wrapper.post_read_correction()
- shape = cls(wrapper)
- return shape
-
-
diff --git a/io_import_dxf/dxfgrabber/entitysection.py b/io_import_dxf/dxfgrabber/entitysection.py
index e87bbb46..cd717c56 100755..100644
--- a/io_import_dxf/dxfgrabber/entitysection.py
+++ b/io_import_dxf/dxfgrabber/entitysection.py
@@ -8,8 +8,8 @@ __author__ = "mozman <mozman@gmx.at>"
from itertools import islice
from .tags import TagGroups, DXFStructureError
-from .tags import ClassifiedTags
-from .entities import entity_factory
+from .tags import Tags
+from .dxfentities import entity_factory
class EntitySection(object):
@@ -21,7 +21,7 @@ class EntitySection(object):
@classmethod
def from_tags(cls, tags, drawing):
entity_section = cls()
- entity_section._build(tags, drawing.dxfversion)
+ entity_section._build(tags)
return entity_section
def get_entities(self):
@@ -40,21 +40,21 @@ class EntitySection(object):
# end of public interface
- def _build(self, tags, dxfversion):
+ def _build(self, tags):
if len(tags) == 3: # empty entities section
return
groups = TagGroups(islice(tags, 2, len(tags)-1))
- self._entities = build_entities(groups, dxfversion)
+ self._entities = build_entities(groups)
class ObjectsSection(EntitySection):
name = 'objects'
-def build_entities(tag_groups, dxfversion):
+def build_entities(tag_groups):
def build_entity(group):
try:
- entity = entity_factory(ClassifiedTags(group), dxfversion)
+ entity = entity_factory(Tags(group))
except KeyError:
entity = None # ignore unsupported entities
return entity
@@ -71,7 +71,7 @@ def build_entities(tag_groups, dxfversion):
collector = None
else:
collector.append(entity)
- elif entity.dxftype == 'POLYLINE':
+ elif entity.dxftype in ('POLYLINE', 'POLYFACE', 'POLYMESH'):
collector = _Collector(entity)
elif entity.dxftype == 'INSERT' and entity.attribsfollow:
collector = _Collector(entity)
diff --git a/io_import_dxf/dxfgrabber/headersection.py b/io_import_dxf/dxfgrabber/headersection.py
index 8c709a5e..5c6d1622 100755
--- a/io_import_dxf/dxfgrabber/headersection.py
+++ b/io_import_dxf/dxfgrabber/headersection.py
@@ -7,6 +7,7 @@ __author__ = "mozman <mozman@gmx.at>"
from .tags import TagGroups, DXFTag
+
class HeaderSection(dict):
name = "header"
@@ -31,9 +32,3 @@ class HeaderSection(dict):
groups = TagGroups(tags[2:-1], split_code=9)
for group in groups:
self[group[0].value] = group[1].value
-
-
-class MinVersionError(Exception):
-
- def __init__(self, version):
- Exception.__init__(self, "Minimum Version DXF12 (AC1009) not met. Version found: %s." % version)
diff --git a/io_import_dxf/dxfgrabber/juliandate.py b/io_import_dxf/dxfgrabber/juliandate.py
index 68c5c8e1..68c5c8e1 100755..100644
--- a/io_import_dxf/dxfgrabber/juliandate.py
+++ b/io_import_dxf/dxfgrabber/juliandate.py
diff --git a/io_import_dxf/dxfgrabber/layers.py b/io_import_dxf/dxfgrabber/layers.py
index de6ae39f..02ef66e8 100755..100644
--- a/io_import_dxf/dxfgrabber/layers.py
+++ b/io_import_dxf/dxfgrabber/layers.py
@@ -6,20 +6,34 @@
__author__ = "mozman <mozman@gmx.at>"
from .tags import TagGroups
-from .tags import ClassifiedTags
-from .dxfentity import DXFEntity
+from .tags import Tags
-from .dxfattr import DXFAttr, DXFAttributes, DefSubclass
+LOCK = 0b00000100
+FROZEN = 0b00000001
class Layer(object):
- def __init__(self, wrapper):
- self.name = wrapper.get_dxf_attrib('name')
- self.color = wrapper.get_color()
- self.linetype = wrapper.get_dxf_attrib('linetype')
- self.locked = wrapper.is_locked()
- self.frozen = wrapper.is_frozen()
- self.on = wrapper.is_on()
+ def __init__(self, tags):
+ self.name = ""
+ self.color = 7
+ self.linetype = ""
+ self.locked = False
+ self.frozen = False
+ self.on = True
+ for code, value in tags.plain_tags():
+ if code == 2:
+ self.name = value
+ elif code == 70:
+ self.frozen = bool(value & FROZEN)
+ self.locked = bool(value & LOCK)
+ elif code == 62:
+ if value < 0:
+ self.on = False
+ self.color = abs(value)
+ else:
+ self.color = value
+ elif code == 6:
+ self.linetype = value
class Table(object):
@@ -55,66 +69,22 @@ class Table(object):
# end public interface
- def _classified_tags(self, tags):
+ def entry_tags(self, tags):
groups = TagGroups(tags)
assert groups.get_name(0) == 'TABLE'
assert groups.get_name(-1) == 'ENDTAB'
for entrytags in groups[1:-1]:
- yield ClassifiedTags(entrytags)
+ yield Tags(entrytags)
class LayerTable(Table):
name = 'layers'
@staticmethod
- def from_tags(tags, drawing):
- dxfversion = drawing.dxfversion
+ def from_tags(tags):
layers = LayerTable()
- for entrytags in layers._classified_tags(tags):
- dxflayer = layers.wrap(entrytags, dxfversion)
- layers._table_entries[dxflayer.get_dxf_attrib('name')] = Layer(dxflayer)
+ for entrytags in layers.entry_tags(tags):
+ layer = Layer(entrytags)
+ layers._table_entries[layer.name] = layer
return layers
- @staticmethod
- def wrap(tags, dxfversion):
- return DXF12Layer(tags) if dxfversion == "AC1009" else DXF13Layer(tags)
-
-
-class DXF12Layer(DXFEntity):
- DXFATTRIBS = DXFAttributes(DefSubclass(None, {
- 'handle': DXFAttr(5),
- 'name': DXFAttr(2),
- 'flags': DXFAttr(70),
- 'color': DXFAttr(62), # dxf color index, if < 0 layer is off
- 'linetype': DXFAttr(6),
- }))
- LOCK = 0b00000100
- FROZEN = 0b00000001
-
- def is_frozen(self):
- return self.get_dxf_attrib('flags') & DXF12Layer.FROZEN > 0
-
- def is_locked(self):
- return self.get_dxf_attrib('flags') & DXF12Layer.LOCK > 0
-
- def is_off(self):
- return self.get_dxf_attrib('color') < 0
-
- def is_on(self):
- return not self.is_off()
-
- def get_color(self):
- return abs(self.get_dxf_attrib('color'))
-
-none_subclass = DefSubclass(None, {'handle': DXFAttr(5)})
-symbol_subclass = DefSubclass('AcDbSymbolTableRecord', {})
-layer_subclass = DefSubclass('AcDbLayerTableRecord', {
- 'name': DXFAttr(2), # layer name
- 'flags': DXFAttr(70),
- 'color': DXFAttr(62), # dxf color index
- 'linetype': DXFAttr(6), # linetype name
-})
-
-
-class DXF13Layer(DXF12Layer):
- DXFATTRIBS = DXFAttributes(none_subclass, symbol_subclass, layer_subclass)
diff --git a/io_import_dxf/dxfgrabber/linetypes.py b/io_import_dxf/dxfgrabber/linetypes.py
index 3e2c877e..8e4441bb 100755..100644
--- a/io_import_dxf/dxfgrabber/linetypes.py
+++ b/io_import_dxf/dxfgrabber/linetypes.py
@@ -5,70 +5,34 @@
__author__ = "mozman <mozman@gmx.at>"
-from .dxfentity import DXFEntity
from .layers import Table
-from .dxfattr import DXFAttr, DXFAttributes, DefSubclass
class Linetype(object):
- def __init__(self, wrapper):
- self.name = wrapper.get_dxf_attrib('name')
- self.description = wrapper.get_dxf_attrib('description')
- self.length = wrapper.get_dxf_attrib('length') # overall length of the pattern
- self.pattern = wrapper.get_pattern() # list of floats: value>0: line, value<0: gap, value=0: dot
+ def __init__(self, tags):
+ self.name = ""
+ self.description = ""
+ self.length = 0 # overall length of the pattern
+ self.pattern = [] # list of floats: value>0: line, value<0: gap, value=0: dot
+ for code, value in tags.plain_tags():
+ if code == 2:
+ self.name = value
+ elif code == 3:
+ self.description = value
+ elif code == 40:
+ self.length = value
+ elif code == 49:
+ self.pattern.append(value)
class LinetypeTable(Table):
name = 'linetypes'
@staticmethod
- def from_tags(tags, drawing):
- dxfversion = drawing.dxfversion
+ def from_tags(tags):
styles = LinetypeTable()
- for entrytags in styles._classified_tags(tags):
- dxfstyle = styles.wrap(entrytags, dxfversion)
- styles._table_entries[dxfstyle.get_dxf_attrib('name')] = Linetype(dxfstyle)
+ for entry_tags in styles.entry_tags(tags):
+ style = Linetype(entry_tags)
+ styles._table_entries[style.name] = style
return styles
-
- @staticmethod
- def wrap(tags, dxfversion):
- return DXF12Linetype(tags) if dxfversion == "AC1009" else DXF13Linetype(tags)
-
-
-class DXF12Linetype(DXFEntity):
- DXFATTRIBS = DXFAttributes(DefSubclass(None, {
- 'handle': DXFAttr(5),
- 'name': DXFAttr(2),
- 'description': DXFAttr(3),
- 'length': DXFAttr(40),
- 'items': DXFAttr(73),
- }))
-
- def get_pattern(self):
- items = self.get_dxf_attrib('items')
- if items == 0:
- return []
- else:
- tags = self.tags.noclass
- return [pattern_tag.value for pattern_tag in tags.find_all(49)]
-
-none_subclass = DefSubclass(None, {'handle': DXFAttr(5)})
-symbol_subclass = DefSubclass('AcDbSymbolTableRecord', {})
-linetype_subclass = DefSubclass('AcDbLinetypeTableRecord', {
- 'name': DXFAttr(2),
- 'description': DXFAttr(3),
- 'length': DXFAttr(40),
- 'items': DXFAttr(73),
-})
-
-
-class DXF13Linetype(DXF12Linetype):
- DXFATTRIBS = DXFAttributes(none_subclass, symbol_subclass, linetype_subclass)
- def get_pattern(self):
- items = self.get_dxf_attrib('items')
- if items == 0:
- return []
- else:
- tags = self.tags.get_subclass('AcDbLinetypeTableRecord')
- return [pattern_tag.value for pattern_tag in tags.find_all(49)]
diff --git a/io_import_dxf/dxfgrabber/pytags.py b/io_import_dxf/dxfgrabber/pytags.py
deleted file mode 100755
index d8d0479b..00000000
--- a/io_import_dxf/dxfgrabber/pytags.py
+++ /dev/null
@@ -1,385 +0,0 @@
-# Purpose: tag reader
-# Created: 21.07.2012, taken from my ezdxf project
-# Copyright (C) 2012, Manfred Moitzi
-# License: MIT License
-from __future__ import unicode_literals
-__author__ = "mozman <mozman@gmx.at>"
-
-from io import StringIO
-from collections import namedtuple
-from itertools import chain, islice
-from . import tostr
-
-
-DXFTag = namedtuple('DXFTag', 'code value')
-NONE_TAG = DXFTag(999999, 'NONE')
-APP_DATA_MARKER = 102
-SUBCLASS_MARKER = 100
-XDATA_MARKER = 1001
-
-
-class DXFStructureError(Exception):
- pass
-
-
-def point_tuple(value):
- return tuple(float(f) for f in value)
-
-
-POINT_CODES = frozenset(chain(range(10, 20), (210, ), range(110, 113), range(1010, 1020)))
-
-
-def is_point_tag(tag):
- return tag[0] in POINT_CODES
-
-
-class TagIterator(object):
- def __init__(self, textfile, assure_3d_coords=False):
- self.textfile = textfile
- self.readline = textfile.readline
- self.undo = False
- self.last_tag = NONE_TAG
- self.undo_coord = None
- self.eof = False
- self.assure_3d_coords = assure_3d_coords
-
- def __iter__(self):
- return self
-
- def __next__(self):
- def undo_tag():
- self.undo = False
- tag = self.last_tag
- return tag
-
- def read_next_tag():
- try:
- code = int(self.readline())
- value = self.readline().rstrip('\n')
- except UnicodeDecodeError:
- raise # because UnicodeDecodeError() is a subclass of ValueError()
- except (EOFError, ValueError):
- raise StopIteration()
- return code, value
-
- def read_point(code_x, value_x):
- try:
- code_y, value_y = read_next_tag() # 2. coordinate is always necessary
- except StopIteration:
- code_y = 0 # -> DXF structure error in following if-statement
-
- if code_y != code_x + 10:
- raise DXFStructureError("invalid 2D/3D point found")
-
- value_y = float(value_y)
- try:
- code_z, value_z = read_next_tag()
- except StopIteration: # 2D point at end of file
- self.eof = True # store reaching end of file
- if self.assure_3d_coords:
- value = (value_x, value_y, 0.)
- else:
- value = (value_x, value_y)
- else:
- if code_z != code_x + 20: # not a Z coordinate -> 2D point
- self.undo_coord = (code_z, value_z)
- if self.assure_3d_coords:
- value = (value_x, value_y, 0.)
- else:
- value = (value_x, value_y)
- else: # is a 3D point
- value = (value_x, value_y, float(value_z))
- return value
-
- def next_tag():
- code = 999
- while code == 999: # skip comments
- if self.undo_coord is not None:
- code, value = self.undo_coord
- self.undo_coord = None
- else:
- code, value = read_next_tag()
-
- if code in POINT_CODES: # 2D or 3D point
- value = read_point(code, float(value)) # returns a tuple of floats, no casting needed
- else:
- value = cast_tag_value(code, value)
- self.last_tag = DXFTag(code, value)
- return self.last_tag
-
- if self.eof: # stored end of file
- raise StopIteration()
-
- if self.undo:
- return undo_tag()
- else:
- return next_tag()
- # for Python 2.7
- next = __next__
-
- def undo_tag(self):
- if not self.undo:
- self.undo = True
- else:
- raise ValueError('No tag to undo')
-
-
-class StringIterator(TagIterator):
- def __init__(self, dxfcontent):
- super(StringIterator, self).__init__(StringIO(dxfcontent))
-
-
-class TagCaster:
- def __init__(self):
- self._cast = self._build()
-
- def _build(self):
- table = {}
- for caster, codes in TYPES:
- for code in codes:
- table[code] = caster
- return table
-
- def cast(self, tag):
- code, value = tag
- typecaster = self._cast.get(code, tostr)
- try:
- value = typecaster(value)
- except ValueError:
- if typecaster is int: # convert float to int
- value = int(float(value))
- else:
- raise
- return DXFTag(code, value)
-
- def cast_value(self, code, value):
- typecaster = self._cast.get(code, tostr)
- try:
- return typecaster(value)
- except ValueError:
- if typecaster is int: # convert float to int
- return int(float(value))
- else:
- raise
-
-TYPES = [
- (tostr, range(0, 10)),
- (point_tuple, range(10, 20)),
- (float, range(20, 60)),
- (int, range(60, 100)),
- (tostr, range(100, 106)),
- (point_tuple, range(110, 113)),
- (float, range(113, 150)),
- (int, range(170, 180)),
- (point_tuple, [210]),
- (float, range(211, 240)),
- (int, range(270, 290)),
- (int, range(290, 300)), # bool 1=True 0=False
- (tostr, range(300, 370)),
- (int, range(370, 390)),
- (tostr, range(390, 400)),
- (int, range(400, 410)),
- (tostr, range(410, 420)),
- (int, range(420, 430)),
- (tostr, range(430, 440)),
- (int, range(440, 460)),
- (float, range(460, 470)),
- (tostr, range(470, 480)),
- (tostr, range(480, 482)),
- (tostr, range(999, 1010)),
- (point_tuple, range(1010, 1020)),
- (float, range(1020, 1060)),
- (int, range(1060, 1072)),
-]
-
-_TagCaster = TagCaster()
-cast_tag = _TagCaster.cast
-cast_tag_value = _TagCaster.cast_value
-
-
-class Tags(list):
- """ DXFTag() chunk as flat list. """
- def find_all(self, code):
- """ Returns a list of DXFTag(code, ...). """
- return [tag for tag in self if tag.code == code]
-
- def tag_index(self, code, start=0, end=None):
- """ Return first index of DXFTag(code, ...). """
- if end is None:
- end = len(self)
- for index, tag in enumerate(islice(self, start, end)):
- if tag.code == code:
- return start+index
- raise ValueError(code)
-
- def get_value(self, code):
- for tag in self:
- if tag.code == code:
- return tag.value
- raise ValueError(code)
-
- @staticmethod
- def from_text(text):
- return Tags(StringIterator(text))
-
- def get_type(self):
- return self.__getitem__(0).value
-
-
-class TagGroups(list):
- """
- Group of tags starting with a SplitTag and ending before the next SplitTag.
-
- A SplitTag is a tag with code == splitcode, like (0, 'SECTION') for splitcode=0.
-
- """
- def __init__(self, tags, split_code=0):
- super(TagGroups, self).__init__()
- self._buildgroups(tags, split_code)
-
- def _buildgroups(self, tags, split_code):
- def push_group():
- if len(group) > 0:
- self.append(group)
-
- def start_tag(itags):
- tag = next(itags)
- while tag.code != split_code:
- tag = next(itags)
- return tag
-
- itags = iter(tags)
- group = Tags([start_tag(itags)])
-
- for tag in itags:
- if tag.code == split_code:
- push_group()
- group = Tags([tag])
- else:
- group.append(tag)
- push_group()
-
- def get_name(self, index):
- return self[index][0].value
-
- @staticmethod
- def from_text(text, split_code=0):
- return TagGroups(Tags.from_text(text), split_code)
-
-
-class ClassifiedTags:
- """ Manage Subclasses, AppData and Extended Data """
-
- def __init__(self, iterable=None):
- self.appdata = list() # code == 102, keys are "{<arbitrary name>", values are Tags()
- self.subclasses = list() # code == 100, keys are "subclassname", values are Tags()
- self.xdata = list() # code >= 1000, keys are "APPNAME", values are Tags()
- if iterable is not None:
- self._setup(iterable)
-
- @property
- def noclass(self):
- return self.subclasses[0]
-
- def _setup(self, iterable):
- tagstream = iter(iterable)
-
- def collect_subclass(start_tag):
- """ a subclass can contain appdata, but not xdata, ends with
- SUBCLASSMARKER or XDATACODE.
- """
- data = Tags() if start_tag is None else Tags([start_tag])
- try:
- while True:
- tag = next(tagstream)
- if tag.code == APP_DATA_MARKER and tag.value[0] == '{':
- app_data_pos = len(self.appdata)
- data.append(DXFTag(tag.code, app_data_pos))
- collect_appdata(tag)
- elif tag.code in (SUBCLASS_MARKER, XDATA_MARKER):
- self.subclasses.append(data)
- return tag
- else:
- data.append(tag)
- except StopIteration:
- pass
- self.subclasses.append(data)
- return NONE_TAG
-
- def collect_appdata(starttag):
- """ appdata, can not contain xdata or subclasses """
- data = Tags([starttag])
- while True:
- try:
- tag = next(tagstream)
- except StopIteration:
- raise DXFStructureError("Missing closing DXFTag(102, '}') for appdata structure.")
- data.append(tag)
- if tag.code == APP_DATA_MARKER:
- break
- self.appdata.append(data)
-
- def collect_xdata(starttag):
- """ xdata are always at the end of the entity and can not contain
- appdata or subclasses
- """
- data = Tags([starttag])
- try:
- while True:
- tag = next(tagstream)
- if tag.code == XDATA_MARKER:
- self.xdata.append(data)
- return tag
- else:
- data.append(tag)
- except StopIteration:
- pass
- self.xdata.append(data)
- return NONE_TAG
-
- tag = collect_subclass(None) # preceding tags without a subclass
- while tag.code == SUBCLASS_MARKER:
- tag = collect_subclass(tag)
- while tag.code == XDATA_MARKER:
- tag = collect_xdata(tag)
-
- if tag is not NONE_TAG:
- raise DXFStructureError("Unexpected tag '%r' at end of entity." % tag)
-
- def __iter__(self):
- for subclass in self.subclasses:
- for tag in subclass:
- if tag.code == APP_DATA_MARKER and isinstance(tag.value, int):
- for subtag in self.appdata[tag.value]:
- yield subtag
- else:
- yield tag
-
- for xdata in self.xdata:
- for tag in xdata:
- yield tag
-
- def get_subclass(self, name):
- for subclass in self.subclasses:
- if len(subclass) and subclass[0].value == name:
- return subclass
- raise KeyError("Subclass '%s' does not exist." % name)
-
- def get_xdata(self, appid):
- for xdata in self.xdata:
- if xdata[0].value == appid:
- return xdata
- raise ValueError("No extended data for APPID '%s'" % appid)
-
- def get_appdata(self, name):
- for appdata in self.appdata:
- if appdata[0].value == name:
- return appdata
- raise ValueError("Application defined group '%s' does not exist." % name)
-
- def get_type(self):
- return self.noclass[0].value
-
- @staticmethod
- def from_text(text):
- return ClassifiedTags(StringIterator(text))
diff --git a/io_import_dxf/dxfgrabber/sections.py b/io_import_dxf/dxfgrabber/sections.py
index c1b03714..286ebf09 100755
--- a/io_import_dxf/dxfgrabber/sections.py
+++ b/io_import_dxf/dxfgrabber/sections.py
@@ -8,7 +8,6 @@ __author__ = "mozman <mozman@gmx.at>"
from .codepage import toencoding
from .defaultchunk import DefaultChunk, iterchunks
from .headersection import HeaderSection
-from .headersection import MinVersionError
from .tablessection import TablesSection
from .entitysection import EntitySection, ObjectsSection
from .blockssection import BlocksSection
@@ -30,11 +29,6 @@ class Sections(object):
section = cls()
self._sections[section.name] = section
- def check_min_version(self, version_string):
- v = int(version_string.replace("AC", ""))
- if v < 1009:
- raise MinVersionError(version_string)
-
def _setup_sections(self, tagreader, drawing):
def name(section):
return section[1].value
@@ -44,7 +38,6 @@ class Sections(object):
if bootstrap:
new_section = HeaderSection.from_tags(section)
drawing.dxfversion = new_section.get('$ACADVER', 'AC1009')
- self.check_min_version(drawing.dxfversion)
codepage = new_section.get('$DWGCODEPAGE', 'ANSI_1252')
drawing.encoding = toencoding(codepage)
bootstrap = False
diff --git a/io_import_dxf/dxfgrabber/styles.py b/io_import_dxf/dxfgrabber/styles.py
index 8553bc4f..3d5dc5e0 100755..100644
--- a/io_import_dxf/dxfgrabber/styles.py
+++ b/io_import_dxf/dxfgrabber/styles.py
@@ -5,75 +5,52 @@
from __future__ import unicode_literals
__author__ = "mozman <mozman@gmx.at>"
-from .dxfentity import DXFEntity
from .layers import Table
-from .dxfattr import DXFAttr, DXFAttributes, DefSubclass
-from .tags import ClassifiedTags
+from .tags import Tags
class Style(object):
- def __init__(self, wrapper):
- self.name = wrapper.get_dxf_attrib('name')
- self.height = wrapper.get_dxf_attrib('height')
- self.width = wrapper.get_dxf_attrib('width')
- self.oblique = wrapper.get_dxf_attrib('oblique')
- # backward & mirror_y was first and stays for compatibility
- self.backward = bool(wrapper.get_dxf_attrib('generation_flags') & 2)
- self.mirror_y = bool(wrapper.get_dxf_attrib('generation_flags') & 4)
- self.is_backwards = self.backward
- self.is_upside_down = self.mirror_y
- self.font = wrapper.get_dxf_attrib('font')
- self.bigfont = wrapper.get_dxf_attrib('bigfont', "")
+ def __init__(self, tags):
+ self.name = ""
+ self.height = 1.0
+ self.width = 1.0
+ self.oblique = 0.
+ self.is_backwards = False
+ self.is_upside_down = False
+ self.font = ""
+ self.big_font = ""
+ for code, value in tags.plain_tags():
+ if code == 2:
+ self.name = value
+ elif code == 70:
+ self.flags = value
+ elif code == 40:
+ self.height = value
+ elif code == 41:
+ self.width = value
+ elif code == 50:
+ self.oblique = value
+ elif code == 71:
+ self.is_backwards = bool(value & 2)
+ self.is_upside_down = bool(value & 4)
+ self.oblique = value
+ elif code == 3:
+ self.font = value
+ elif code == 4:
+ self.big_font = value
class StyleTable(Table):
name = 'styles'
@staticmethod
- def from_tags(tags, drawing):
- dxfversion = drawing.dxfversion
+ def from_tags(tags):
styles = StyleTable()
- for entrytags in styles._classified_tags(tags):
- dxfstyle = styles.wrap(entrytags, dxfversion)
- styles._table_entries[dxfstyle.get_dxf_attrib('name')] = Style(dxfstyle)
+ for entry_tags in styles.entry_tags(tags):
+ style = Style(entry_tags)
+ styles._table_entries[style.name] = style
return styles
- @staticmethod
- def wrap(tags, dxfversion):
- return DXF12Style(tags) if dxfversion == "AC1009" else DXF13Style(tags)
-
-
-class DXF12Style(DXFEntity):
- DXFATTRIBS = DXFAttributes(DefSubclass(None, {
- 'handle': DXFAttr(5),
- 'name': DXFAttr(2),
- 'flags': DXFAttr(70),
- 'height': DXFAttr(40), # fixed height, 0 if not fixed
- 'width': DXFAttr(41), # width factor
- 'oblique': DXFAttr(50), # oblique angle in degree, 0 = vertical
- 'generation_flags': DXFAttr(71), # 2 = backward, 4 = mirrored in Y
- 'last_height': DXFAttr(42), # last height used
- 'font': DXFAttr(3), # primary font file name
- 'bigfont': DXFAttr(4), # big font name, blank if none
- }))
-
-none_subclass = DefSubclass(None, {'handle': DXFAttr(5)})
-symbol_subclass = DefSubclass('AcDbSymbolTableRecord', {})
-style_subclass = DefSubclass('AcDbTextStyleTableRecord', {
- 'name': DXFAttr(2),
- 'flags': DXFAttr(70),
- 'height': DXFAttr(40), # fixed height, 0 if not fixed
- 'width': DXFAttr(41), # width factor
- 'oblique': DXFAttr(50), # oblique angle in degree, 0 = vertical
- 'generation_flags': DXFAttr(71), # 2 = backward, 4 = mirrored in Y
- 'last_height': DXFAttr(42), # last height used
- 'font': DXFAttr(3), # primary font file name
- 'bigfont': DXFAttr(4), # big font name, blank if none
-})
-
-
-class DXF13Style(DXF12Style):
- DXFATTRIBS = DXFAttributes(none_subclass, symbol_subclass, style_subclass)
DEFAULT_STYLE = """ 0
STYLE
@@ -97,4 +74,4 @@ Arial
"""
-default_text_style = Style(DXF12Style(ClassifiedTags.from_text(DEFAULT_STYLE))) \ No newline at end of file
+default_text_style = Style(Tags.from_text(DEFAULT_STYLE))
diff --git a/io_import_dxf/dxfgrabber/tablessection.py b/io_import_dxf/dxfgrabber/tablessection.py
index 3737138a..345487fa 100755..100644
--- a/io_import_dxf/dxfgrabber/tablessection.py
+++ b/io_import_dxf/dxfgrabber/tablessection.py
@@ -29,12 +29,6 @@ def tablename(dxfname):
return TABLENAMES.get(name, name+'s')
-class GenericTable(DefaultChunk):
- @property
- def name(self):
- return tablename(self.tags[1].value)
-
-
class DefaultDrawing(object):
dxfversion = 'AC1009'
encoding = 'cp1252'
@@ -43,9 +37,8 @@ class DefaultDrawing(object):
class TablesSection(object):
name = 'tables'
- def __init__(self, drawing=DefaultDrawing()):
+ def __init__(self):
self._tables = dict()
- self._drawing = drawing
self._create_default_tables()
def _create_default_tables(self):
@@ -55,7 +48,7 @@ class TablesSection(object):
@staticmethod
def from_tags(tags, drawing):
- tables_section = TablesSection(drawing)
+ tables_section = TablesSection()
tables_section._setup_tables(tags)
return tables_section
@@ -71,8 +64,9 @@ class TablesSection(object):
itertags = skiptags(iter(tags), 2) # (0, 'SECTION'), (2, 'TABLES')
for table in iterchunks(itertags, stoptag='ENDSEC', endofchunk='ENDTAB'):
table_class = table_factory(name(table))
- new_table = table_class.from_tags(table, self._drawing)
- self._tables[new_table.name] = new_table
+ if table_class is not None:
+ new_table = table_class.from_tags(table)
+ self._tables[new_table.name] = new_table
def __getattr__(self, key):
try:
@@ -89,4 +83,4 @@ TABLESMAP = {
def table_factory(name):
- return TABLESMAP.get(name, GenericTable)
+ return TABLESMAP.get(name, None)
diff --git a/io_import_dxf/dxfgrabber/tags.py b/io_import_dxf/dxfgrabber/tags.py
index fed6aa88..b406bd02 100755..100644
--- a/io_import_dxf/dxfgrabber/tags.py
+++ b/io_import_dxf/dxfgrabber/tags.py
@@ -5,32 +5,410 @@
from __future__ import unicode_literals
__author__ = "mozman <mozman@gmx.at>"
-import os
-from .const import ENV_CYTHON
-
-OPTIMIZE = True
-if ENV_CYTHON in os.environ:
- if os.environ[ENV_CYTHON].upper() in ('1', 'ON', 'TRUE'):
- OPTIMIZE = True
- else:
- OPTIMIZE = False
-try:
- if not OPTIMIZE:
- raise ImportError
- CYTHON_EXT = True
- from.cytags import TagIterator, Tags, TagGroups, DXFTag, NONE_TAG
- from.cytags import DXFStructureError, StringIterator, ClassifiedTags
-except ImportError:
- CYTHON_EXT = False
- from.pytags import TagIterator, Tags, TagGroups, DXFTag, NONE_TAG
- from.pytags import DXFStructureError, StringIterator, ClassifiedTags
-
-
import sys
from .codepage import toencoding
from .const import acadrelease
from array import array
+from io import StringIO
+from collections import namedtuple
+from itertools import chain, islice
+from . import tostr
+
+
+DXFTag = namedtuple('DXFTag', 'code value')
+NONE_TAG = DXFTag(999999, 'NONE')
+APP_DATA_MARKER = 102
+SUBCLASS_MARKER = 100
+XDATA_MARKER = 1001
+
+
+class DXFStructureError(Exception):
+ pass
+
+
+def point_tuple(value):
+ return tuple(float(f) for f in value)
+
+
+POINT_CODES = frozenset(chain(range(10, 20), (210, ), range(110, 113), range(1010, 1020)))
+
+
+def is_point_tag(tag):
+ return tag[0] in POINT_CODES
+
+
+class TagCaster:
+ def __init__(self):
+ self._cast = self._build()
+
+ def _build(self):
+ table = {}
+ for caster, codes in TYPES:
+ for code in codes:
+ table[code] = caster
+ return table
+
+ def cast(self, tag):
+ code, value = tag
+ typecaster = self._cast.get(code, tostr)
+ try:
+ value = typecaster(value)
+ except ValueError:
+ if typecaster is int: # convert float to int
+ value = int(float(value))
+ else:
+ raise
+ return DXFTag(code, value)
+
+ def cast_value(self, code, value):
+ typecaster = self._cast.get(code, tostr)
+ try:
+ return typecaster(value)
+ except ValueError:
+ if typecaster is int: # convert float to int
+ return int(float(value))
+ else:
+ raise
+
+TYPES = [
+ (tostr, range(0, 10)),
+ (point_tuple, range(10, 20)),
+ (float, range(20, 60)),
+ (int, range(60, 100)),
+ (tostr, range(100, 106)),
+ (point_tuple, range(110, 113)),
+ (float, range(113, 150)),
+ (int, range(170, 180)),
+ (point_tuple, [210]),
+ (float, range(211, 240)),
+ (int, range(270, 290)),
+ (int, range(290, 300)), # bool 1=True 0=False
+ (tostr, range(300, 370)),
+ (int, range(370, 390)),
+ (tostr, range(390, 400)),
+ (int, range(400, 410)),
+ (tostr, range(410, 420)),
+ (int, range(420, 430)),
+ (tostr, range(430, 440)),
+ (int, range(440, 460)),
+ (float, range(460, 470)),
+ (tostr, range(470, 480)),
+ (tostr, range(480, 482)),
+ (tostr, range(999, 1010)),
+ (point_tuple, range(1010, 1020)),
+ (float, range(1020, 1060)),
+ (int, range(1060, 1072)),
+]
+
+_TagCaster = TagCaster()
+cast_tag = _TagCaster.cast
+cast_tag_value = _TagCaster.cast_value
+
+
+def stream_tagger(stream, assure_3d_coords=False):
+ """ Generates DXFTag() from a stream (untrusted external source). Does not skip comment tags 999.
+ """
+ class Counter:
+ def __init__(self):
+ self.counter = 0
+
+ undo_tag = None
+ line = Counter() # writeable line counter for next_tag(), Python 2.7 does not support the nonlocal statement
+
+ def next_tag():
+ code = stream.readline()
+ value = stream.readline()
+ line.counter += 2
+ if code and value: # StringIO(): empty strings indicates EOF
+ return DXFTag(int(code[:-1]), value[:-1]) # without '\n'
+ else: # StringIO(): missing '\n' indicates EOF
+ raise EOFError()
+
+ while True:
+ try:
+ if undo_tag is not None:
+ x = undo_tag
+ undo_tag = None
+ else:
+ x = next_tag()
+ code = x.code
+ if code == 999: # skip comments
+ continue
+ if code in POINT_CODES:
+ y = next_tag() # y coordinate is mandatory
+ if y.code != code + 10:
+ raise DXFStructureError("Missing required y coordinate near line: {}.".format(line.counter))
+ z = next_tag() # z coordinate just for 3d points
+ try:
+ if z.code == code + 20:
+ point = (float(x.value), float(y.value), float(z.value))
+ else:
+ if assure_3d_coords:
+ point = (float(x.value), float(y.value), 0.)
+ else:
+ point = (float(x.value), float(y.value))
+ undo_tag = z
+ except ValueError:
+ raise DXFStructureError('Invalid floating point values near line: {}.'.format(line.counter))
+ yield DXFTag(code, point)
+ else: # just a single tag
+ try:
+ yield cast_tag(x)
+ except ValueError:
+ raise DXFStructureError('Invalid tag (code={code}, value="{value}") near line: {line}.'.format(
+ line=line.counter,
+ code=x.code,
+ value=x.value,
+ ))
+ except EOFError:
+ return
+
+
+def string_tagger(s):
+ return stream_tagger(StringIO(s))
+
+
+class Tags(list):
+ """ DXFTag() chunk as flat list. """
+ def find_all(self, code):
+ """ Returns a list of DXFTag(code, ...). """
+ return [tag for tag in self if tag.code == code]
+
+ def tag_index(self, code, start=0, end=None):
+ """Return first index of DXFTag(code, value).
+ """
+ if end is None:
+ end = len(self)
+ index = start
+ while index < end:
+ if self[index].code == code:
+ return index
+ index += 1
+ raise ValueError(code)
+
+ def get_value(self, code):
+ for tag in self:
+ if tag.code == code:
+ return tag.value
+ raise ValueError(code)
+
+ @staticmethod
+ def from_text(text):
+ return Tags(string_tagger(text))
+
+ def get_type(self):
+ return self.__getitem__(0).value
+
+ def plain_tags(self): # yield no app data and no xdata
+ is_app_data = False
+ for tag in self:
+ if tag.code >= 1000: # skip xdata
+ continue
+ if tag.code == APP_DATA_MARKER:
+ if is_app_data: # tag.value == '}'
+ is_app_data = False # end of app data
+ else: # value == '{APPID'
+ is_app_data = True # start of app data
+ continue
+ if not is_app_data:
+ yield tag
+
+ def xdata(self):
+ index = 0
+ end = len(self)
+ while index < end:
+ if self[index].code > 999: # all xdata tag codes are >= 1000
+ return self[index:] # xdata is always at the end of the DXF entity
+ index += 1
+ return []
+
+ def app_data(self):
+ app_data = {}
+ app_tags = None
+ for tag in self:
+ if tag.code == APP_DATA_MARKER:
+ if tag.value == '}': # end of app data
+ app_tags.append(tag)
+ app_data[app_tags[0].value] = app_tags
+ app_tags = None
+ else:
+ app_tags = [tag]
+ else:
+ if app_tags is not None: # collection app data
+ app_tags.append(tag)
+ return app_data
+
+ def subclasses(self):
+ classes = {}
+ name = 'noname'
+ tags = []
+ for tag in self.plain_tags():
+ if tag.code == SUBCLASS_MARKER:
+ classes[name] = tags
+ tags = []
+ name = tag.value
+ else:
+ tags.append(tag)
+ classes[name] = tags
+ return classes
+
+ def get_subclass(self, name):
+ classes = self.subclasses()
+ return classes.get(name, 'noname')
+
+
+class TagGroups(list):
+ """
+ Group of tags starting with a SplitTag and ending before the next SplitTag.
+
+ A SplitTag is a tag with code == splitcode, like (0, 'SECTION') for splitcode=0.
+
+ """
+ def __init__(self, tags, split_code=0):
+ super(TagGroups, self).__init__()
+ self._build_groups(tags, split_code)
+
+ def _build_groups(self, tags, splitcode):
+ def append(tag): # first do nothing, skip tags in front of the first split tag
+ pass
+ group = None
+ for tag in tags: # has to work with iterators/generators
+ if tag.code == splitcode:
+ if group is not None:
+ self.append(group)
+ group = Tags([tag])
+ append = group.append # redefine append: add tags to this group
+ else:
+ append(tag)
+ if group is not None:
+ self.append(group)
+
+ def get_name(self, index):
+ return self[index][0].value
+
+ @staticmethod
+ def from_text(text, split_code=0):
+ return TagGroups(Tags.from_text(text), split_code)
+
+
+class ClassifiedTags:
+ """ Manage Subclasses, AppData and Extended Data """
+
+ def __init__(self, iterable=None):
+ self.appdata = list() # code == 102, keys are "{<arbitrary name>", values are Tags()
+ self.subclasses = list() # code == 100, keys are "subclassname", values are Tags()
+ self.xdata = list() # code >= 1000, keys are "APPNAME", values are Tags()
+ if iterable is not None:
+ self._setup(iterable)
+
+ @property
+ def noclass(self):
+ return self.subclasses[0]
+
+ def _setup(self, iterable):
+ tagstream = iter(iterable)
+
+ def collect_subclass(start_tag):
+ """ a subclass can contain appdata, but not xdata, ends with
+ SUBCLASSMARKER or XDATACODE.
+ """
+ data = Tags() if start_tag is None else Tags([start_tag])
+ try:
+ while True:
+ tag = next(tagstream)
+ if tag.code == APP_DATA_MARKER and tag.value[0] == '{':
+ app_data_pos = len(self.appdata)
+ data.append(DXFTag(tag.code, app_data_pos))
+ collect_appdata(tag)
+ elif tag.code in (SUBCLASS_MARKER, XDATA_MARKER):
+ self.subclasses.append(data)
+ return tag
+ else:
+ data.append(tag)
+ except StopIteration:
+ pass
+ self.subclasses.append(data)
+ return NONE_TAG
+
+ def collect_appdata(starttag):
+ """ appdata, can not contain xdata or subclasses """
+ data = Tags([starttag])
+ while True:
+ try:
+ tag = next(tagstream)
+ except StopIteration:
+ raise DXFStructureError("Missing closing DXFTag(102, '}') for appdata structure.")
+ data.append(tag)
+ if tag.code == APP_DATA_MARKER:
+ break
+ self.appdata.append(data)
+
+ def collect_xdata(starttag):
+ """ xdata are always at the end of the entity and can not contain
+ appdata or subclasses
+ """
+ data = Tags([starttag])
+ try:
+ while True:
+ tag = next(tagstream)
+ if tag.code == XDATA_MARKER:
+ self.xdata.append(data)
+ return tag
+ else:
+ data.append(tag)
+ except StopIteration:
+ pass
+ self.xdata.append(data)
+ return NONE_TAG
+
+ tag = collect_subclass(None) # preceding tags without a subclass
+ while tag.code == SUBCLASS_MARKER:
+ tag = collect_subclass(tag)
+ while tag.code == XDATA_MARKER:
+ tag = collect_xdata(tag)
+
+ if tag is not NONE_TAG:
+ raise DXFStructureError("Unexpected tag '%r' at end of entity." % tag)
+
+ def __iter__(self):
+ for subclass in self.subclasses:
+ for tag in subclass:
+ if tag.code == APP_DATA_MARKER and isinstance(tag.value, int):
+ for subtag in self.appdata[tag.value]:
+ yield subtag
+ else:
+ yield tag
+
+ for xdata in self.xdata:
+ for tag in xdata:
+ yield tag
+
+ def get_subclass(self, name):
+ for subclass in self.subclasses:
+ if len(subclass) and subclass[0].value == name:
+ return subclass
+ raise KeyError("Subclass '%s' does not exist." % name)
+
+ def get_xdata(self, appid):
+ for xdata in self.xdata:
+ if xdata[0].value == appid:
+ return xdata
+ raise ValueError("No extended data for APPID '%s'" % appid)
+
+ def get_appdata(self, name):
+ for appdata in self.appdata:
+ if appdata[0].value == name:
+ return appdata
+ raise ValueError("Application defined group '%s' does not exist." % name)
+
+ def get_type(self):
+ return self.noclass[0].value
+
+ @staticmethod
+ def from_text(text):
+ return ClassifiedTags(string_tagger(text))
+
class DXFInfo(object):
def __init__(self):
@@ -53,7 +431,7 @@ class DXFInfo(object):
def dxfinfo(stream):
info = DXFInfo()
tag = DXFTag(999999, '')
- tagreader = TagIterator(stream)
+ tagreader = stream_tagger(stream)
while tag != DXFTag(0, 'ENDSEC'):
tag = next(tagreader)
if tag.code != 9:
diff --git a/io_import_dxf/dxfimport/convert.py b/io_import_dxf/dxfimport/convert.py
index 8260b519..c21d274c 100644
--- a/io_import_dxf/dxfimport/convert.py
+++ b/io_import_dxf/dxfimport/convert.py
@@ -78,7 +78,7 @@ def bspline_to_cubic(do, en, curve, errors=None):
return new_spline
knots = list(en.knots)
- spline = [ShortVec(cp) for cp in en.controlpoints]
+ spline = [ShortVec(cp) for cp in en.control_points]
degree = len(knots) - len(spline) - 1
if degree <= 3:
clean_knots()
diff --git a/io_import_dxf/dxfimport/do.py b/io_import_dxf/dxfimport/do.py
index e6eb45ea..4b73eaac 100644
--- a/io_import_dxf/dxfimport/do.py
+++ b/io_import_dxf/dxfimport/do.py
@@ -281,10 +281,10 @@ class Do:
def arc(self, en, curve=None, aunits=None, angdir=None, angbase=None):
"""
- en: dxf entity (en.startangle, en.endangle, en.center, en.radius)
+ en: dxf entity (en.start_angle, en.end_angle, en.center, en.radius)
curve: optional; Blender curve data of type "CURVE" (object.data) to which the arc should be added to
return control points of a cubic spline (do be used in a spline with bulges / series of arcs)
- note: en.startangle + en.endangle: angles measured from the angle base (angbase) in the direction of
+ note: en.start_angle + en.end_angle: angles measured from the angle base (angbase) in the direction of
angdir (1 = clockwise, 0 = counterclockwise)
"""
treshold = 0.005
@@ -298,11 +298,11 @@ class Do:
kappa = 0.5522848
if aunits == 0:
- s = radians(en.startangle+angbase)
- e = radians(en.endangle+angbase)
+ s = radians(en.start_angle+angbase)
+ e = radians(en.end_angle+angbase)
else:
- s = en.startangle+angbase
- e = en.endangle+angbase
+ s = en.start_angle+angbase
+ e = en.end_angle+angbase
if s > e:
e += 2 * pi
@@ -420,7 +420,7 @@ class Do:
ratio: ratio between major and minor axis lengths (always < 1)
curve: Blender curve data of type "CURVE" (object.data) to which the ellipse should be added to
"""
- major = Vector(en.majoraxis)
+ major = Vector(en.major_axis)
en.__dict__["radius"] = major.length
c = self.circle(en, curve, major.normalized())
b = c.bezier_points
@@ -755,7 +755,7 @@ class Do:
ratio = 50 / en.rect_width
d.size = en.height * ratio * 1.4 # XXX HACK
scale = (1 / ratio, 1 / ratio, 1 / ratio)
- d.space_line = en.linespacing
+ d.space_line = en.line_spacing
else:
width = en.rect_width
scale = (1, 1, 1)
@@ -1494,6 +1494,8 @@ class Do:
if self.but_group_by_att and self.combination != BY_CLOSED_NO_BULGE_POLY and self.combination != BY_BLOCK:
for atts, by_att in groupsort.by_attributes(grouped_entities):
thickness, subd, width, extrusion = atts
+ if extrusion is None: # unset extrusion defaults to (0, 0, 1)
+ extrusion = (0, 0, 1)
att = ""
if thickness != 0:
att += "thickness" + str(thickness) + ", "
diff --git a/io_import_dxf/dxfimport/fake_entities.py b/io_import_dxf/dxfimport/fake_entities.py
index a3df42f0..35338a7d 100644
--- a/io_import_dxf/dxfimport/fake_entities.py
+++ b/io_import_dxf/dxfimport/fake_entities.py
@@ -25,15 +25,15 @@ class ArcEntity:
an arc. ArcEntity is just used to call do.arc() without having a real Arc-Entity from dxfgrabber.
"""
def __init__(self, start, end, center, radius, angdir):
- self.startangle = start
- self.endangle = end
+ self.start_angle = start
+ self.end_angle = end
self.center = center
self.radius = radius
self.angdir = angdir
def __str__(self):
return "startangle: %s, endangle: %s, center: %s, radius: %s, angdir: %s" % \
- (str(self.startangle), str(self.endangle), str(self.center), str(self.radius), str(self.angdir))
+ (str(self.start_angle), str(self.end_angle), str(self.center), str(self.radius), str(self.angdir))
class LineEntity:
diff --git a/io_import_dxf/dxfimport/is_.py b/io_import_dxf/dxfimport/is_.py
index 20d6fe43..6a8977a5 100644
--- a/io_import_dxf/dxfimport/is_.py
+++ b/io_import_dxf/dxfimport/is_.py
@@ -106,7 +106,10 @@ def varying_width(entity):
if hasattr(entity, "width"):
ew = entity.width
if hasattr(ew, "__iter__"):
- return ew.count(ew[0]) != len(ew) or ew[0][0] != ew[0][1]
+ if len(ew) == 0:
+ return False
+ else:
+ return ew.count(ew[0]) != len(ew) or ew[0][0] != ew[0][1]
return False