adding files from merge.
This commit is contained in:
1326
release/scripts/bpymodules/dxfImportObjects.py
Normal file
1326
release/scripts/bpymodules/dxfImportObjects.py
Normal file
@@ -0,0 +1,1326 @@
|
||||
"""This module provides wrapper objects for dxf entities.
|
||||
|
||||
The wrappers expect a "dxf object" as input. The dxf object is
|
||||
an object with a type and a data attribute. Type is a lowercase
|
||||
string matching the 0 code of a dxf entity. Data is a list containing
|
||||
dxf objects or lists of [code, data] pairs.
|
||||
|
||||
This module is not general, and is only for dxf import.
|
||||
"""
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# DXF Import Objects v0.8 by Ed Blake (AKA Kitsu)
|
||||
# --------------------------------------------------------------------------
|
||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# ***** END GPL LICENCE BLOCK *****
|
||||
# --------------------------------------------------------------------------
|
||||
from math import *
|
||||
|
||||
|
||||
# from Stani's dxf writer v1.1 (c)www.stani.be (GPL)
|
||||
#---color values
|
||||
BYBLOCK=0
|
||||
BYLAYER=256
|
||||
|
||||
#---block-type flags (bit coded values, may be combined):
|
||||
ANONYMOUS =1 # This is an anonymous block generated by hatching, associative dimensioning, other internal operations, or an application
|
||||
NON_CONSTANT_ATTRIBUTES =2 # This block has non-constant attribute definitions (this bit is not set if the block has any attribute definitions that are constant, or has no attribute definitions at all)
|
||||
XREF =4 # This block is an external reference (xref)
|
||||
XREF_OVERLAY =8 # This block is an xref overlay
|
||||
EXTERNAL =16 # This block is externally dependent
|
||||
RESOLVED =32 # This is a resolved external reference, or dependent of an external reference (ignored on input)
|
||||
REFERENCED =64 # This definition is a referenced external reference (ignored on input)
|
||||
|
||||
#---mtext flags
|
||||
#attachment point
|
||||
TOP_LEFT = 1
|
||||
TOP_CENTER = 2
|
||||
TOP_RIGHT = 3
|
||||
MIDDLE_LEFT = 4
|
||||
MIDDLE_CENTER = 5
|
||||
MIDDLE_RIGHT = 6
|
||||
BOTTOM_LEFT = 7
|
||||
BOTTOM_CENTER = 8
|
||||
BOTTOM_RIGHT = 9
|
||||
#drawing direction
|
||||
LEFT_RIGHT = 1
|
||||
TOP_BOTTOM = 3
|
||||
BY_STYLE = 5 #the flow direction is inherited from the associated text style
|
||||
#line spacing style (optional):
|
||||
AT_LEAST = 1 #taller characters will override
|
||||
EXACT = 2 #taller characters will not override
|
||||
|
||||
#---polyline flags
|
||||
CLOSED =1 # This is a closed polyline (or a polygon mesh closed in the M direction)
|
||||
CURVE_FIT =2 # Curve-fit vertices have been added
|
||||
SPLINE_FIT =4 # Spline-fit vertices have been added
|
||||
POLYLINE_3D =8 # This is a 3D polyline
|
||||
POLYGON_MESH =16 # This is a 3D polygon mesh
|
||||
CLOSED_N =32 # The polygon mesh is closed in the N direction
|
||||
POLYFACE_MESH =64 # The polyline is a polyface mesh
|
||||
CONTINOUS_LINETYPE_PATTERN =128 # The linetype pattern is generated continuously around the vertices of this polyline
|
||||
|
||||
#---text flags
|
||||
#horizontal
|
||||
LEFT = 0
|
||||
CENTER = 1
|
||||
RIGHT = 2
|
||||
ALIGNED = 3 #if vertical alignment = 0
|
||||
MIDDLE = 4 #if vertical alignment = 0
|
||||
FIT = 5 #if vertical alignment = 0
|
||||
#vertical
|
||||
BASELINE = 0
|
||||
BOTTOM = 1
|
||||
MIDDLE = 2
|
||||
TOP = 3
|
||||
class Object:
|
||||
"""Empty container class for dxf objects"""
|
||||
|
||||
def __init__(self, _type=''):
|
||||
"""_type expects a string value."""
|
||||
self.type = _type
|
||||
self.name = ''
|
||||
self.data = []
|
||||
|
||||
def __str__(self):
|
||||
if self.name:
|
||||
return self.name
|
||||
else:
|
||||
return self.type
|
||||
|
||||
def __repr__(self):
|
||||
return str(self.data)
|
||||
|
||||
def get_type(self, kind=''):
|
||||
"""Despite the name, this method actually returns all objects of type 'kind' from self.data."""
|
||||
if type:
|
||||
objects = []
|
||||
for item in self.data:
|
||||
if type(item) != list and item.type == kind:
|
||||
# we want this type of object
|
||||
objects.append(item)
|
||||
elif type(item) == list and item[0] == kind:
|
||||
# we want this type of data
|
||||
objects.append(item[1])
|
||||
return objects
|
||||
|
||||
|
||||
class Layer:
|
||||
"""Class for objects representing dxf layers."""
|
||||
|
||||
def __init__(self, obj):
|
||||
"""Expects an entity object of type line as input."""
|
||||
self.type = obj.type
|
||||
self.data = obj.data[:]
|
||||
|
||||
self.name = obj.get_type(2)[0]
|
||||
self.color = obj.get_type(62)[0]
|
||||
self.flags = obj.get_type(70)[0]
|
||||
self.frozen = self.flags&1
|
||||
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return "%s: name - %s, color - %s" %(self.__class__.__name__, self.name, self.color)
|
||||
|
||||
|
||||
|
||||
class Line:
|
||||
"""Class for objects representing dxf lines."""
|
||||
|
||||
def __init__(self, obj):
|
||||
"""Expects an entity object of type line as input."""
|
||||
if not obj.type == 'line':
|
||||
raise TypeError, "Wrong type %s for line object!" %obj.type
|
||||
self.type = obj.type
|
||||
self.data = obj.data[:]
|
||||
|
||||
self.space = obj.get_type(67)
|
||||
if self.space:
|
||||
self.space = self.space[0]
|
||||
else:
|
||||
self.space = 0
|
||||
|
||||
self.color_index = obj.get_type(62)
|
||||
if self.color_index:
|
||||
self.color_index = self.color_index[0]
|
||||
else:
|
||||
self.color_index = BYLAYER
|
||||
|
||||
discard, self.layer, discard_index = get_layer(obj.data)
|
||||
del obj.data[discard_index]
|
||||
|
||||
self.points = self.get_points(obj.data)
|
||||
|
||||
|
||||
|
||||
|
||||
def get_points(self, data):
|
||||
"""Gets start and end points for a line type object.
|
||||
|
||||
Lines have a fixed number of points (two) and fixed codes for each value.
|
||||
"""
|
||||
|
||||
# start x, y, z and end x, y, z = 0
|
||||
sx, sy, sz, ex, ey, ez = 0, 0, 0, 0, 0, 0
|
||||
for item in data:
|
||||
if item[0] == 10: # 10 = x
|
||||
sx = item[1]
|
||||
elif item[0] == 20: # 20 = y
|
||||
sy = item[1]
|
||||
elif item[0] == 30: # 30 = z
|
||||
sz = item[1]
|
||||
elif item[0] == 11: # 11 = x
|
||||
ex = item[1]
|
||||
elif item[0] == 21: # 21 = y
|
||||
ey = item[1]
|
||||
elif item[0] == 31: # 31 = z
|
||||
ez = item[1]
|
||||
return [[sx, sy, sz], [ex, ey, ez]]
|
||||
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points)
|
||||
|
||||
|
||||
|
||||
class LWpolyline:
|
||||
"""Class for objects representing dxf LWpolylines."""
|
||||
|
||||
def __init__(self, obj):
|
||||
"""Expects an entity object of type lwpolyline as input."""
|
||||
if not obj.type == 'lwpolyline':
|
||||
raise TypeError, "Wrong type %s for polyline object!" %obj.type
|
||||
self.type = obj.type
|
||||
self.data = obj.data[:]
|
||||
|
||||
# required data
|
||||
self.num_points = obj.get_type(90)[0]
|
||||
|
||||
# optional data (with defaults)
|
||||
self.space = obj.get_type(67)
|
||||
if self.space:
|
||||
self.space = self.space[0]
|
||||
else:
|
||||
self.space = 0
|
||||
|
||||
self.color_index = obj.get_type(62)
|
||||
if self.color_index:
|
||||
self.color_index = self.color_index[0]
|
||||
else:
|
||||
self.color_index = BYLAYER
|
||||
|
||||
self.elevation = obj.get_type(38)
|
||||
if self.elevation:
|
||||
self.elevation = self.elevation[0]
|
||||
else:
|
||||
self.elevation = 0
|
||||
|
||||
self.flags = obj.get_type(70)
|
||||
if self.flags:
|
||||
self.flags = self.flags[0]
|
||||
else:
|
||||
self.flags = 0
|
||||
|
||||
self.closed = self.flags&1 # byte coded, 1 = closed, 128 = plinegen
|
||||
discard, self.layer, discard_index = get_layer(obj.data)
|
||||
del obj.data[discard_index]
|
||||
self.points = self.get_points(obj.data)
|
||||
self.extrusion = self.get_extrusion(obj.data)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def get_points(self, data):
|
||||
"""Gets points for a polyline type object.
|
||||
|
||||
Polylines have no fixed number of verts, and
|
||||
each vert can have a number of properties.
|
||||
Verts should be coded as
|
||||
10:xvalue
|
||||
20:yvalue
|
||||
40:startwidth or 0
|
||||
41:endwidth or 0
|
||||
42:bulge or 0
|
||||
for each vert
|
||||
"""
|
||||
num = self.num_points
|
||||
point = None
|
||||
points = []
|
||||
for item in data:
|
||||
if item[0] == 10: # 10 = x
|
||||
if point:
|
||||
points.append(point)
|
||||
point = Vertex()
|
||||
point.x = item[1]
|
||||
elif item[0] == 20: # 20 = y
|
||||
point.y = item[1]
|
||||
elif item[0] == 40: # 40 = start width
|
||||
point.swidth = item[1]
|
||||
elif item[0] == 41: # 41 = end width
|
||||
point.ewidth = item[1]
|
||||
elif item[0] == 42: # 42 = bulge
|
||||
point.bulge = item[1]
|
||||
points.append(point)
|
||||
return points
|
||||
|
||||
|
||||
def get_extrusion(self, data):
|
||||
"""Find the axis of extrusion.
|
||||
|
||||
Used to get the objects Object Coordinate System (ocs).
|
||||
"""
|
||||
vec = [0,0,1]
|
||||
for item in data:
|
||||
if item[0] == 210: # 210 = x
|
||||
vec[0] = item[1]
|
||||
elif item[0] == 220: # 220 = y
|
||||
vec[1] = item[1]
|
||||
elif item[0] == 230: # 230 = z
|
||||
vec[2] = item[1]
|
||||
return vec
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points)
|
||||
|
||||
|
||||
|
||||
class Polyline:
|
||||
"""Class for objects representing dxf LWpolylines."""
|
||||
|
||||
def __init__(self, obj):
|
||||
"""Expects an entity object of type polyline as input."""
|
||||
if not obj.type == 'polyline':
|
||||
raise TypeError, "Wrong type %s for polyline object!" %obj.type
|
||||
self.type = obj.type
|
||||
self.data = obj.data[:]
|
||||
self.points = []
|
||||
|
||||
# optional data (with defaults)
|
||||
self.space = obj.get_type(67)
|
||||
if self.space:
|
||||
self.space = self.space[0]
|
||||
else:
|
||||
self.space = 0
|
||||
|
||||
self.color_index = obj.get_type(62)
|
||||
if self.color_index:
|
||||
self.color_index = self.color_index[0]
|
||||
else:
|
||||
self.color_index = BYLAYER
|
||||
|
||||
self.elevation = obj.get_type(30)
|
||||
if self.elevation:
|
||||
self.elevation = self.elevation[0]
|
||||
else:
|
||||
self.elevation = 0
|
||||
|
||||
self.flags = obj.get_type(70)
|
||||
if self.flags:
|
||||
self.flags = self.flags[0]
|
||||
else:
|
||||
self.flags = 0
|
||||
|
||||
self.closed = self.flags&1 # byte coded, 1 = closed, 128 = plinegen
|
||||
|
||||
discard, self.layer, discard_index = get_layer(obj.data)
|
||||
del obj.data[discard_index]
|
||||
self.extrusion = self.get_extrusion(obj.data)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def get_extrusion(self, data):
|
||||
"""Find the axis of extrusion.
|
||||
|
||||
Used to get the objects Object Coordinate System (ocs).
|
||||
"""
|
||||
vec = [0,0,1]
|
||||
for item in data:
|
||||
if item[0] == 210: # 210 = x
|
||||
vec[0] = item[1]
|
||||
elif item[0] == 220: # 220 = y
|
||||
vec[1] = item[1]
|
||||
elif item[0] == 230: # 230 = z
|
||||
vec[2] = item[1]
|
||||
return vec
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points)
|
||||
|
||||
|
||||
|
||||
class Vertex(object):
|
||||
"""Generic vertex object used by polylines (and maybe others)."""
|
||||
|
||||
def __init__(self, obj=None):
|
||||
"""Initializes vertex data.
|
||||
|
||||
The optional obj arg is an entity object of type vertex.
|
||||
"""
|
||||
self.loc = [0,0,0]
|
||||
self.bulge = 0
|
||||
self.swidth = 0
|
||||
self.ewidth = 0
|
||||
self.flags = 0
|
||||
|
||||
if obj is not None:
|
||||
if not obj.type == 'vertex':
|
||||
raise TypeError, "Wrong type %s for vertex object!" %obj.type
|
||||
self.type = obj.type
|
||||
self.data = obj.data[:]
|
||||
|
||||
self.get_props(obj.data)
|
||||
|
||||
|
||||
def get_props(self, data):
|
||||
"""Gets coords for a vertex type object.
|
||||
|
||||
Each vert can have a number of properties.
|
||||
Verts should be coded as
|
||||
10:xvalue
|
||||
20:yvalue
|
||||
40:startwidth or 0
|
||||
41:endwidth or 0
|
||||
42:bulge or 0
|
||||
"""
|
||||
for item in data:
|
||||
if item[0] == 10: # 10 = x
|
||||
self.x = item[1]
|
||||
elif item[0] == 20: # 20 = y
|
||||
self.y = item[1]
|
||||
elif item[0] == 30: # 30 = z
|
||||
self.z = item[1]
|
||||
elif item[0] == 40: # 40 = start width
|
||||
self.swidth = item[1]
|
||||
elif item[0] == 41: # 41 = end width
|
||||
self.ewidth = item[1]
|
||||
elif item[0] == 42: # 42 = bulge
|
||||
self.bulge = item[1]
|
||||
elif item[0] == 70: # 70 = vert flags
|
||||
self.flags = item[1]
|
||||
|
||||
|
||||
def __len__(self):
|
||||
return 3
|
||||
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self.loc[key]
|
||||
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
if key in [0,1,2]:
|
||||
self.loc[key]
|
||||
|
||||
|
||||
def __iter__(self):
|
||||
return self.loc.__iter__()
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return str(self.loc)
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return "Vertex %s, swidth=%s, ewidth=%s, bulge=%s" %(self.loc, self.swidth, self.ewidth, self.bulge)
|
||||
|
||||
|
||||
def getx(self):
|
||||
return self.loc[0]
|
||||
|
||||
def setx(self, value):
|
||||
self.loc[0] = value
|
||||
|
||||
x = property(getx, setx)
|
||||
|
||||
|
||||
def gety(self):
|
||||
return self.loc[1]
|
||||
|
||||
def sety(self, value):
|
||||
self.loc[1] = value
|
||||
|
||||
y = property(gety, sety)
|
||||
|
||||
|
||||
def getz(self):
|
||||
return self.loc[2]
|
||||
|
||||
def setz(self, value):
|
||||
self.loc[2] = value
|
||||
|
||||
z = property(getz, setz)
|
||||
|
||||
|
||||
|
||||
class Text:
|
||||
"""Class for objects representing dxf Text."""
|
||||
|
||||
def __init__(self, obj):
|
||||
"""Expects an entity object of type text as input."""
|
||||
if not obj.type == 'text':
|
||||
raise TypeError, "Wrong type %s for text object!" %obj.type
|
||||
self.type = obj.type
|
||||
self.data = obj.data[:]
|
||||
|
||||
# required data
|
||||
self.height = obj.get_type(40)[0]
|
||||
self.value = obj.get_type(1)[0] # The text string value
|
||||
|
||||
# optional data (with defaults)
|
||||
self.space = obj.get_type(67)
|
||||
if self.space:
|
||||
self.space = self.space[0]
|
||||
else:
|
||||
self.space = 0
|
||||
|
||||
self.color_index = obj.get_type(62)
|
||||
if self.color_index:
|
||||
self.color_index = self.color_index[0]
|
||||
else:
|
||||
self.color_index = BYLAYER
|
||||
|
||||
self.rotation = obj.get_type(50) # radians?
|
||||
if not self.rotation:
|
||||
self.rotation = 0
|
||||
else:
|
||||
self.rotation = self.rotation[0]
|
||||
|
||||
self.width_factor = obj.get_type(41) # Scaling factor along local x axis
|
||||
if not self.width_factor:
|
||||
self.width_factor = 1
|
||||
else:
|
||||
self.width_factor = self.width_factor[0]
|
||||
|
||||
self.oblique = obj.get_type(51) # skew in degrees -90 <= oblique <= 90
|
||||
if not self.oblique:
|
||||
self.oblique = 0
|
||||
else:
|
||||
self.oblique = self.oblique[0]
|
||||
|
||||
self.halignment = obj.get_type(72) # horiz. alignment
|
||||
if not self.halignment: # 0=left, 1=center, 2=right, 3=aligned, 4=middle, 5=fit
|
||||
self.halignment = 0
|
||||
else:
|
||||
self.halignment = self.halignment[0]
|
||||
|
||||
self.valignment = obj.get_type(73) # vert. alignment
|
||||
if not self.valignment: # 0=baseline, 1=bottom, 2=middle, 3=top
|
||||
self.valignment = 0
|
||||
else:
|
||||
self.valignment = self.valignment[0]
|
||||
|
||||
discard, self.layer, discard_index = get_layer(obj.data)
|
||||
del obj.data[discard_index]
|
||||
self.loc = self.get_loc(obj.data, self.halignment, self.valignment)
|
||||
self.extrusion = self.get_extrusion(obj.data)
|
||||
|
||||
|
||||
|
||||
|
||||
def get_loc(self, data, halign, valign):
|
||||
"""Gets adjusted location for text type objects.
|
||||
|
||||
If group 72 and/or 73 values are nonzero then the first alignment point values
|
||||
are ignored and AutoCAD calculates new values based on the second alignment
|
||||
point and the length and height of the text string itself (after applying the
|
||||
text style). If the 72 and 73 values are zero or missing, then the second
|
||||
alignment point is meaningless.
|
||||
|
||||
I don't know how to calc text size...
|
||||
"""
|
||||
# bottom left x, y, z and justification x, y, z = 0
|
||||
x, y, z, jx, jy, jz = 0, 0, 0, 0, 0, 0
|
||||
for item in data:
|
||||
if item[0] == 10: # 10 = x
|
||||
x = item[1]
|
||||
elif item[0] == 20: # 20 = y
|
||||
y = item[1]
|
||||
elif item[0] == 30: # 30 = z
|
||||
z = item[1]
|
||||
elif item[0] == 11: # 11 = x
|
||||
jx = item[1]
|
||||
elif item[0] == 21: # 21 = y
|
||||
jy = item[1]
|
||||
elif item[0] == 31: # 31 = z
|
||||
jz = item[1]
|
||||
|
||||
if halign or valign:
|
||||
x, y, z = jx, jy, jz
|
||||
return [x, y, z]
|
||||
|
||||
def get_extrusion(self, data):
|
||||
"""Find the axis of extrusion.
|
||||
|
||||
Used to get the objects Object Coordinate System (ocs).
|
||||
"""
|
||||
vec = [0,0,1]
|
||||
for item in data:
|
||||
if item[0] == 210: # 210 = x
|
||||
vec[0] = item[1]
|
||||
elif item[0] == 220: # 220 = y
|
||||
vec[1] = item[1]
|
||||
elif item[0] == 230: # 230 = z
|
||||
vec[2] = item[1]
|
||||
return vec
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return "%s: layer - %s, value - %s" %(self.__class__.__name__, self.layer, self.value)
|
||||
|
||||
|
||||
|
||||
class Mtext:
|
||||
"""Class for objects representing dxf Mtext."""
|
||||
|
||||
def __init__(self, obj):
|
||||
"""Expects an entity object of type mtext as input."""
|
||||
if not obj.type == 'mtext':
|
||||
raise TypeError, "Wrong type %s for mtext object!" %obj.type
|
||||
self.type = obj.type
|
||||
self.data = obj.data[:]
|
||||
|
||||
# required data
|
||||
self.height = obj.get_type(40)[0]
|
||||
self.width = obj.get_type(41)[0]
|
||||
self.alignment = obj.get_type(71)[0] # alignment 1=TL, 2=TC, 3=TR, 4=ML, 5=MC, 6=MR, 7=BL, 8=BC, 9=BR
|
||||
self.value = self.get_text(obj.data) # The text string value
|
||||
|
||||
# optional data (with defaults)
|
||||
self.space = obj.get_type(67)
|
||||
if self.space:
|
||||
self.space = self.space[0]
|
||||
else:
|
||||
self.space = 0
|
||||
|
||||
self.color_index = obj.get_type(62)
|
||||
if self.color_index:
|
||||
self.color_index = self.color_index[0]
|
||||
else:
|
||||
self.color_index = BYLAYER
|
||||
|
||||
self.rotation = obj.get_type(50) # radians
|
||||
if not self.rotation:
|
||||
self.rotation = 0
|
||||
else:
|
||||
self.rotation = self.rotation[0]
|
||||
|
||||
self.width_factor = obj.get_type(42) # Scaling factor along local x axis
|
||||
if not self.width_factor:
|
||||
self.width_factor = 1
|
||||
else:
|
||||
self.width_factor = self.width_factor[0]
|
||||
|
||||
self.line_space = obj.get_type(44) # percentage of default
|
||||
if not self.line_space:
|
||||
self.line_space = 1
|
||||
else:
|
||||
self.line_space = self.line_space[0]
|
||||
|
||||
discard, self.layer, discard_index = get_layer(obj.data)
|
||||
del obj.data[discard_index]
|
||||
self.loc = self.get_loc(obj.data)
|
||||
self.extrusion = self.get_extrusion(obj.data)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def get_text(self, data):
|
||||
"""Reconstructs mtext data from dxf codes."""
|
||||
primary = ''
|
||||
secondary = []
|
||||
for item in data:
|
||||
if item[0] == 1: # There should be only one primary...
|
||||
primary = item[1]
|
||||
elif item[0] == 3: # There may be any number of extra strings (in order)
|
||||
secondary.append(item[1])
|
||||
if not primary:
|
||||
#raise ValueError, "Empty Mtext Object!"
|
||||
string = "Empty Mtext Object!"
|
||||
if not secondary:
|
||||
string = primary.replace(r'\P', '\n')
|
||||
else:
|
||||
string = ''.join(secondary)+primary
|
||||
string = string.replace(r'\P', '\n')
|
||||
return string
|
||||
def get_loc(self, data):
|
||||
"""Gets location for a mtext type objects.
|
||||
|
||||
Mtext objects have only one point indicating location.
|
||||
"""
|
||||
loc = [0,0,0]
|
||||
for item in data:
|
||||
if item[0] == 10: # 10 = x
|
||||
loc[0] = item[1]
|
||||
elif item[0] == 20: # 20 = y
|
||||
loc[1] = item[1]
|
||||
elif item[0] == 30: # 30 = z
|
||||
loc[2] = item[1]
|
||||
return loc
|
||||
|
||||
|
||||
|
||||
|
||||
def get_extrusion(self, data):
|
||||
"""Find the axis of extrusion.
|
||||
|
||||
Used to get the objects Object Coordinate System (ocs).
|
||||
"""
|
||||
vec = [0,0,1]
|
||||
for item in data:
|
||||
if item[0] == 210: # 210 = x
|
||||
vec[0] = item[1]
|
||||
elif item[0] == 220: # 220 = y
|
||||
vec[1] = item[1]
|
||||
elif item[0] == 230: # 230 = z
|
||||
vec[2] = item[1]
|
||||
return vec
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return "%s: layer - %s, value - %s" %(self.__class__.__name__, self.layer, self.value)
|
||||
|
||||
|
||||
|
||||
class Circle:
|
||||
"""Class for objects representing dxf Circles."""
|
||||
|
||||
def __init__(self, obj):
|
||||
"""Expects an entity object of type circle as input."""
|
||||
if not obj.type == 'circle':
|
||||
raise TypeError, "Wrong type %s for circle object!" %obj.type
|
||||
self.type = obj.type
|
||||
self.data = obj.data[:]
|
||||
|
||||
# required data
|
||||
self.radius = obj.get_type(40)[0]
|
||||
|
||||
# optional data (with defaults)
|
||||
self.space = obj.get_type(67)
|
||||
if self.space:
|
||||
self.space = self.space[0]
|
||||
else:
|
||||
self.space = 0
|
||||
|
||||
self.color_index = obj.get_type(62)
|
||||
if self.color_index:
|
||||
self.color_index = self.color_index[0]
|
||||
else:
|
||||
self.color_index = BYLAYER
|
||||
|
||||
discard, self.layer, discard_index = get_layer(obj.data)
|
||||
del obj.data[discard_index]
|
||||
self.loc = self.get_loc(obj.data)
|
||||
self.extrusion = self.get_extrusion(obj.data)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def get_loc(self, data):
|
||||
"""Gets the center location for circle type objects.
|
||||
|
||||
Circles have a single coord location.
|
||||
"""
|
||||
loc = [0, 0, 0]
|
||||
for item in data:
|
||||
if item[0] == 10: # 10 = x
|
||||
loc[0] = item[1]
|
||||
elif item[0] == 20: # 20 = y
|
||||
loc[1] = item[1]
|
||||
elif item[0] == 30: # 30 = z
|
||||
loc[2] = item[1]
|
||||
return loc
|
||||
|
||||
|
||||
|
||||
def get_extrusion(self, data):
|
||||
"""Find the axis of extrusion.
|
||||
|
||||
Used to get the objects Object Coordinate System (ocs).
|
||||
"""
|
||||
vec = [0,0,1]
|
||||
for item in data:
|
||||
if item[0] == 210: # 210 = x
|
||||
vec[0] = item[1]
|
||||
elif item[0] == 220: # 220 = y
|
||||
vec[1] = item[1]
|
||||
elif item[0] == 230: # 230 = z
|
||||
vec[2] = item[1]
|
||||
return vec
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return "%s: layer - %s, radius - %s" %(self.__class__.__name__, self.layer, self.radius)
|
||||
|
||||
|
||||
|
||||
class Arc:
|
||||
"""Class for objects representing dxf arcs."""
|
||||
|
||||
def __init__(self, obj):
|
||||
"""Expects an entity object of type arc as input."""
|
||||
if not obj.type == 'arc':
|
||||
raise TypeError, "Wrong type %s for arc object!" %obj.type
|
||||
self.type = obj.type
|
||||
self.data = obj.data[:]
|
||||
|
||||
# required data
|
||||
self.radius = obj.get_type(40)[0]
|
||||
self.start_angle = obj.get_type(50)[0]
|
||||
self.end_angle = obj.get_type(51)[0]
|
||||
|
||||
# optional data (with defaults)
|
||||
self.space = obj.get_type(67)
|
||||
if self.space:
|
||||
self.space = self.space[0]
|
||||
else:
|
||||
self.space = 0
|
||||
|
||||
self.color_index = obj.get_type(62)
|
||||
if self.color_index:
|
||||
self.color_index = self.color_index[0]
|
||||
else:
|
||||
self.color_index = BYLAYER
|
||||
|
||||
discard, self.layer, discard_index = get_layer(obj.data)
|
||||
del obj.data[discard_index]
|
||||
self.loc = self.get_loc(obj.data)
|
||||
self.extrusion = self.get_extrusion(obj.data)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def get_loc(self, data):
|
||||
"""Gets the center location for arc type objects.
|
||||
|
||||
Arcs have a single coord location.
|
||||
"""
|
||||
loc = [0, 0, 0]
|
||||
for item in data:
|
||||
if item[0] == 10: # 10 = x
|
||||
loc[0] = item[1]
|
||||
elif item[0] == 20: # 20 = y
|
||||
loc[1] = item[1]
|
||||
elif item[0] == 30: # 30 = z
|
||||
loc[2] = item[1]
|
||||
return loc
|
||||
|
||||
|
||||
|
||||
def get_extrusion(self, data):
|
||||
"""Find the axis of extrusion.
|
||||
|
||||
Used to get the objects Object Coordinate System (ocs).
|
||||
"""
|
||||
vec = [0,0,1]
|
||||
for item in data:
|
||||
if item[0] == 210: # 210 = x
|
||||
vec[0] = item[1]
|
||||
elif item[0] == 220: # 220 = y
|
||||
vec[1] = item[1]
|
||||
elif item[0] == 230: # 230 = z
|
||||
vec[2] = item[1]
|
||||
return vec
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return "%s: layer - %s, radius - %s" %(self.__class__.__name__, self.layer, self.radius)
|
||||
|
||||
|
||||
|
||||
class BlockRecord:
|
||||
"""Class for objects representing dxf block_records."""
|
||||
|
||||
def __init__(self, obj):
|
||||
"""Expects an entity object of type block_record as input."""
|
||||
if not obj.type == 'block_record':
|
||||
raise TypeError, "Wrong type %s for block_record object!" %obj.type
|
||||
self.type = obj.type
|
||||
self.data = obj.data[:]
|
||||
|
||||
# required data
|
||||
self.name = obj.get_type(2)[0]
|
||||
|
||||
# optional data (with defaults)
|
||||
self.insertion_units = obj.get_type(70)
|
||||
if not self.insertion_units:
|
||||
self.insertion_units = None
|
||||
else:
|
||||
self.insertion_units = self.insertion_units[0]
|
||||
|
||||
self.insert_units = obj.get_type(1070)
|
||||
if not self.insert_units:
|
||||
self.insert_units = None
|
||||
else:
|
||||
self.insert_units = self.insert_units[0]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return "%s: name - %s, insert units - %s" %(self.__class__.__name__, self.name, self.insertion_units)
|
||||
|
||||
|
||||
|
||||
|
||||
class Block:
|
||||
"""Class for objects representing dxf blocks."""
|
||||
|
||||
def __init__(self, obj):
|
||||
"""Expects an entity object of type block as input."""
|
||||
if not obj.type == 'block':
|
||||
raise TypeError, "Wrong type %s for block object!" %obj.type
|
||||
self.type = obj.type
|
||||
self.data = obj.data[:]
|
||||
|
||||
# required data
|
||||
self.flags = obj.get_type(70)[0]
|
||||
self.entities = Object('block_contents')
|
||||
self.entities.data = objectify([ent for ent in obj.data if type(ent) != list])
|
||||
|
||||
# optional data (with defaults)
|
||||
self.name = obj.get_type(3)
|
||||
if self.name:
|
||||
self.name = self.name[0]
|
||||
else:
|
||||
self.name = ''
|
||||
|
||||
self.path = obj.get_type(1)
|
||||
if self.path:
|
||||
self.path = self.path[0]
|
||||
else:
|
||||
self.path = ''
|
||||
|
||||
self.discription = obj.get_type(4)
|
||||
if self.discription:
|
||||
self.discription = self.discription[0]
|
||||
else:
|
||||
self.discription = ''
|
||||
|
||||
discard, self.layer, discard_index = get_layer(obj.data)
|
||||
del obj.data[discard_index]
|
||||
self.loc = self.get_loc(obj.data)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def get_loc(self, data):
|
||||
"""Gets the insert point of the block."""
|
||||
loc = [0, 0, 0]
|
||||
for item in data:
|
||||
if type(item) != list:
|
||||
continue
|
||||
if item[0] == 10: # 10 = x
|
||||
loc[0] = item[1]
|
||||
elif item[0] == 20: # 20 = y
|
||||
loc[1] = item[1]
|
||||
elif item[0] == 30: # 30 = z
|
||||
loc[2] = item[1]
|
||||
return loc
|
||||
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return "%s: name - %s, description - %s, xref-path - %s" %(self.__class__.__name__, self.name, self.discription, self.path)
|
||||
|
||||
|
||||
|
||||
|
||||
class Insert:
|
||||
"""Class for objects representing dxf inserts."""
|
||||
|
||||
def __init__(self, obj):
|
||||
"""Expects an entity object of type insert as input."""
|
||||
if not obj.type == 'insert':
|
||||
raise TypeError, "Wrong type %s for insert object!" %obj.type
|
||||
self.type = obj.type
|
||||
self.data = obj.data[:]
|
||||
|
||||
# required data
|
||||
self.block = obj.get_type(2)[0]
|
||||
|
||||
# optional data (with defaults)
|
||||
self.rotation = obj.get_type(50)
|
||||
if self.rotation:
|
||||
self.rotation = self.rotation[0]
|
||||
else:
|
||||
self.rotation = 0
|
||||
|
||||
self.space = obj.get_type(67)
|
||||
if self.space:
|
||||
self.space = self.space[0]
|
||||
else:
|
||||
self.space = 0
|
||||
|
||||
self.color_index = obj.get_type(62)
|
||||
if self.color_index:
|
||||
self.color_index = self.color_index[0]
|
||||
else:
|
||||
self.color_index = BYLAYER
|
||||
|
||||
discard, self.layer, discard_index = get_layer(obj.data)
|
||||
del obj.data[discard_index]
|
||||
self.loc = self.get_loc(obj.data)
|
||||
self.scale = self.get_scale(obj.data)
|
||||
self.rows, self.columns = self.get_array(obj.data)
|
||||
self.extrusion = self.get_extrusion(obj.data)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def get_loc(self, data):
|
||||
"""Gets the center location for circle type objects.
|
||||
|
||||
Circles have a single coord location.
|
||||
"""
|
||||
loc = [0, 0, 0]
|
||||
for item in data:
|
||||
if item[0] == 10: # 10 = x
|
||||
loc[0] = item[1]
|
||||
elif item[0] == 20: # 20 = y
|
||||
loc[1] = item[1]
|
||||
elif item[0] == 30: # 30 = z
|
||||
loc[2] = item[1]
|
||||
return loc
|
||||
|
||||
|
||||
|
||||
def get_scale(self, data):
|
||||
"""Gets the x/y/z scale factor for the block.
|
||||
"""
|
||||
scale = [1, 1, 1]
|
||||
for item in data:
|
||||
if item[0] == 41: # 41 = x scale
|
||||
scale[0] = item[1]
|
||||
elif item[0] == 42: # 42 = y scale
|
||||
scale[1] = item[1]
|
||||
elif item[0] == 43: # 43 = z scale
|
||||
scale[2] = item[1]
|
||||
return scale
|
||||
|
||||
|
||||
|
||||
def get_array(self, data):
|
||||
"""Returns the pair (row number, row spacing), (column number, column spacing)."""
|
||||
columns = 1
|
||||
rows = 1
|
||||
cspace = 0
|
||||
rspace = 0
|
||||
for item in data:
|
||||
if item[0] == 70: # 70 = columns
|
||||
columns = item[1]
|
||||
elif item[0] == 71: # 71 = rows
|
||||
rows = item[1]
|
||||
if item[0] == 44: # 44 = columns
|
||||
cspace = item[1]
|
||||
elif item[0] == 45: # 45 = rows
|
||||
rspace = item[1]
|
||||
return (rows, rspace), (columns, cspace)
|
||||
|
||||
|
||||
|
||||
def get_extrusion(self, data):
|
||||
"""Find the axis of extrusion.
|
||||
|
||||
Used to get the objects Object Coordinate System (ocs).
|
||||
"""
|
||||
vec = [0,0,1]
|
||||
for item in data:
|
||||
if item[0] == 210: # 210 = x
|
||||
vec[0] = item[1]
|
||||
elif item[0] == 220: # 220 = y
|
||||
vec[1] = item[1]
|
||||
elif item[0] == 230: # 230 = z
|
||||
vec[2] = item[1]
|
||||
return vec
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return "%s: layer - %s, block - %s" %(self.__class__.__name__, self.layer, self.block)
|
||||
|
||||
|
||||
|
||||
|
||||
class Ellipse:
|
||||
"""Class for objects representing dxf ellipses."""
|
||||
|
||||
def __init__(self, obj):
|
||||
"""Expects an entity object of type ellipse as input."""
|
||||
if not obj.type == 'ellipse':
|
||||
raise TypeError, "Wrong type %s for ellipse object!" %obj.type
|
||||
self.type = obj.type
|
||||
self.data = obj.data[:]
|
||||
|
||||
# required data
|
||||
self.ratio = obj.get_type(40)[0]
|
||||
self.start_angle = obj.get_type(41)[0]
|
||||
self.end_angle = obj.get_type(42)[0]
|
||||
|
||||
# optional data (with defaults)
|
||||
self.space = obj.get_type(67)
|
||||
if self.space:
|
||||
self.space = self.space[0]
|
||||
else:
|
||||
self.space = 0
|
||||
|
||||
self.color_index = obj.get_type(62)
|
||||
if self.color_index:
|
||||
self.color_index = self.color_index[0]
|
||||
else:
|
||||
self.color_index = BYLAYER
|
||||
|
||||
discard, self.layer, discard_index = get_layer(obj.data)
|
||||
del obj.data[discard_index]
|
||||
self.loc = self.get_loc(obj.data)
|
||||
self.major = self.get_major(obj.data)
|
||||
self.extrusion = self.get_extrusion(obj.data)
|
||||
self.radius = sqrt(self.major[0]**2 + self.major[0]**2 + self.major[0]**2)
|
||||
|
||||
|
||||
|
||||
|
||||
def get_loc(self, data):
|
||||
"""Gets the center location for arc type objects.
|
||||
|
||||
Arcs have a single coord location.
|
||||
"""
|
||||
loc = [0, 0, 0]
|
||||
for item in data:
|
||||
if item[0] == 10: # 10 = x
|
||||
loc[0] = item[1]
|
||||
elif item[0] == 20: # 20 = y
|
||||
loc[1] = item[1]
|
||||
elif item[0] == 30: # 30 = z
|
||||
loc[2] = item[1]
|
||||
return loc
|
||||
|
||||
|
||||
|
||||
def get_major(self, data):
|
||||
"""Gets the major axis for ellipse type objects.
|
||||
|
||||
The ellipse major axis defines the rotation of the ellipse and its radius.
|
||||
"""
|
||||
loc = [0, 0, 0]
|
||||
for item in data:
|
||||
if item[0] == 11: # 11 = x
|
||||
loc[0] = item[1]
|
||||
elif item[0] == 21: # 21 = y
|
||||
loc[1] = item[1]
|
||||
elif item[0] == 31: # 31 = z
|
||||
loc[2] = item[1]
|
||||
return loc
|
||||
|
||||
|
||||
|
||||
def get_extrusion(self, data):
|
||||
"""Find the axis of extrusion.
|
||||
|
||||
Used to get the objects Object Coordinate System (ocs).
|
||||
"""
|
||||
vec = [0,0,1]
|
||||
for item in data:
|
||||
if item[0] == 210: # 210 = x
|
||||
vec[0] = item[1]
|
||||
elif item[0] == 220: # 220 = y
|
||||
vec[1] = item[1]
|
||||
elif item[0] == 230: # 230 = z
|
||||
vec[2] = item[1]
|
||||
return vec
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return "%s: layer - %s, radius - %s" %(self.__class__.__name__, self.layer, self.radius)
|
||||
|
||||
|
||||
|
||||
class Face:
|
||||
"""Class for objects representing dxf 3d faces."""
|
||||
|
||||
def __init__(self, obj):
|
||||
"""Expects an entity object of type 3dfaceplot as input."""
|
||||
if not obj.type == '3dface':
|
||||
raise TypeError, "Wrong type %s for 3dface object!" %obj.type
|
||||
self.type = obj.type
|
||||
self.data = obj.data[:]
|
||||
|
||||
# optional data (with defaults)
|
||||
self.space = obj.get_type(67)
|
||||
if self.space:
|
||||
self.space = self.space[0]
|
||||
else:
|
||||
self.space = 0
|
||||
|
||||
self.color_index = obj.get_type(62)
|
||||
if self.color_index:
|
||||
self.color_index = self.color_index[0]
|
||||
else:
|
||||
self.color_index = BYLAYER
|
||||
|
||||
discard, self.layer, discard_index = get_layer(obj.data)
|
||||
del obj.data[discard_index]
|
||||
self.points = self.get_points(obj.data)
|
||||
|
||||
|
||||
|
||||
|
||||
def get_points(self, data):
|
||||
"""Gets 3-4 points for a 3d face type object.
|
||||
|
||||
Faces have three or optionally four verts.
|
||||
"""
|
||||
|
||||
a = [0, 0, 0]
|
||||
b = [0, 0, 0]
|
||||
c = [0, 0, 0]
|
||||
d = False
|
||||
for item in data:
|
||||
# ----------- a -------------
|
||||
if item[0] == 10: # 10 = x
|
||||
a[0] = item[1]
|
||||
elif item[0] == 20: # 20 = y
|
||||
a[1] = item[1]
|
||||
elif item[0] == 30: # 30 = z
|
||||
a[2] = item[1]
|
||||
# ----------- b -------------
|
||||
elif item[0] == 11: # 11 = x
|
||||
b[0] = item[1]
|
||||
elif item[0] == 21: # 21 = y
|
||||
b[1] = item[1]
|
||||
elif item[0] == 31: # 31 = z
|
||||
b[2] = item[1]
|
||||
# ----------- c -------------
|
||||
elif item[0] == 12: # 12 = x
|
||||
c[0] = item[1]
|
||||
elif item[0] == 22: # 22 = y
|
||||
c[1] = item[1]
|
||||
elif item[0] == 32: # 32 = z
|
||||
c[2] = item[1]
|
||||
# ----------- d -------------
|
||||
elif item[0] == 13: # 13 = x
|
||||
d = [0, 0, 0]
|
||||
d[0] = item[1]
|
||||
elif item[0] == 23: # 23 = y
|
||||
d[1] = item[1]
|
||||
elif item[0] == 33: # 33 = z
|
||||
d[2] = item[1]
|
||||
out = [a,b,c]
|
||||
if d:
|
||||
out.append(d)
|
||||
return out
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points)
|
||||
|
||||
|
||||
def get_name(data):
|
||||
"""Get the name of an object from its object data.
|
||||
|
||||
Returns a pair of (data_item, name) where data_item is the list entry where the name was found
|
||||
(the data_item can be used to remove the entry from the object data). Be sure to check
|
||||
name not None before using the returned values!
|
||||
"""
|
||||
value = None
|
||||
for i, item in enumerate(data):
|
||||
if item[0] == 2:
|
||||
value = item[1]
|
||||
break
|
||||
return item, value, i
|
||||
|
||||
def get_layer(data):
|
||||
"""Expects object data as input.
|
||||
|
||||
Returns (entry, layer_name, entry_index) where entry is the data item that provided the layer name.
|
||||
"""
|
||||
value = None
|
||||
for i, item in enumerate(data):
|
||||
if item[0] == 8:
|
||||
value = item[1]
|
||||
break
|
||||
return item, value, i
|
||||
|
||||
|
||||
# type to object map
|
||||
type_map = {
|
||||
'line':Line,
|
||||
'lwpolyline':LWpolyline,
|
||||
'text':Text,
|
||||
'mtext':Mtext,
|
||||
'circle':Circle,
|
||||
'arc':Arc,
|
||||
'layer':Layer,
|
||||
'block_record':BlockRecord,
|
||||
'block':Block,
|
||||
'insert':Insert,
|
||||
'ellipse':Ellipse,
|
||||
'3dface':Face
|
||||
}
|
||||
|
||||
def objectify(data):
|
||||
"""Expects a section type object's data as input.
|
||||
|
||||
Maps object data to the correct object type.
|
||||
"""
|
||||
objects = [] # colector for finished objects
|
||||
known_types = type_map.keys() # so we don't have to call foo.keys() every iteration
|
||||
index = 0
|
||||
while index < len(data):
|
||||
item = data[index]
|
||||
if type(item) != list and item.type in known_types:
|
||||
# proccess the object and append the resulting object
|
||||
objects.append(type_map[item.type](item))
|
||||
elif type(item) != list and item.type == 'table':
|
||||
item.data = objectify(item.data) # tables have sub-objects
|
||||
objects.append(item)
|
||||
elif type(item) != list and item.type == 'polyline':
|
||||
pline = Polyline(item)
|
||||
while 1:
|
||||
index += 1
|
||||
item = data[index]
|
||||
if item.type == 'vertex':
|
||||
v = Vertex(item)
|
||||
pline.points.append(v)
|
||||
elif item.type == 'seqend':
|
||||
break
|
||||
else:
|
||||
print "Error: non-vertex found before seqend!"
|
||||
index -= 1
|
||||
break
|
||||
objects.append(pline)
|
||||
else:
|
||||
# we will just let the data pass un-harrased
|
||||
objects.append(item)
|
||||
index += 1
|
||||
return objects
|
||||
if __name__ == "__main__":
|
||||
print "No example yet!"
|
||||
Reference in New Issue
Block a user