diff --git a/src/Mod/Draft/draftlibs/__init__.py b/src/Mod/Draft/draftlibs/__init__.py deleted file mode 100644 index 0f0a32df1..000000000 --- a/src/Mod/Draft/draftlibs/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# this is the init file of the draftlibs library diff --git a/src/Mod/Draft/draftlibs/dxfColorMap.py b/src/Mod/Draft/draftlibs/dxfColorMap.py deleted file mode 100644 index 66c0bd4e9..000000000 --- a/src/Mod/Draft/draftlibs/dxfColorMap.py +++ /dev/null @@ -1,282 +0,0 @@ -# dictionary mapping AutoCAD color indexes with Blender colors - -# -------------------------------------------------------------------------- -# color_map.py Final 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 ***** -# -------------------------------------------------------------------------- - -color_map = { - 0:[0.0, 0.0, 0.0], - 1:[0.99609375, 0.0, 0.0], - 2:[0.99609375, 0.99609375, 0.0], - 3:[0.0, 0.99609375, 0.0], - 4:[0.0, 0.99609375, 0.99609375], - 5:[0.0, 0.0, 0.99609375], - 6:[0.99609375, 0.0, 0.99609375], - 7:[0.99609375, 0.99609375, 0.99609375], - 8:[0.25390625, 0.25390625, 0.25390625], - 9:[0.5, 0.5, 0.5], - 10:[0.99609375, 0.0, 0.0], - 11:[0.99609375, 0.6640625, 0.6640625], - 12:[0.73828125, 0.0, 0.0], - 13:[0.73828125, 0.4921875, 0.4921875], - 14:[0.50390625, 0.0, 0.0], - 15:[0.50390625, 0.3359375, 0.3359375], - 16:[0.40625, 0.0, 0.0], - 17:[0.40625, 0.26953125, 0.26953125], - 18:[0.30859375, 0.0, 0.0], - 19:[0.30859375, 0.20703125, 0.20703125], - 20:[0.99609375, 0.24609375, 0.0], - 21:[0.99609375, 0.74609375, 0.6640625], - 22:[0.73828125, 0.1796875, 0.0], - 23:[0.73828125, 0.55078125, 0.4921875], - 24:[0.50390625, 0.12109375, 0.0], - 25:[0.50390625, 0.375, 0.3359375], - 26:[0.40625, 0.09765625, 0.0], - 27:[0.40625, 0.3046875, 0.26953125], - 28:[0.30859375, 0.07421875, 0.0], - 29:[0.30859375, 0.23046875, 0.20703125], - 30:[0.99609375, 0.49609375, 0.0], - 31:[0.99609375, 0.828125, 0.6640625], - 32:[0.73828125, 0.3671875, 0.0], - 33:[0.73828125, 0.61328125, 0.4921875], - 34:[0.50390625, 0.25, 0.0], - 35:[0.50390625, 0.41796875, 0.3359375], - 36:[0.40625, 0.203125, 0.0], - 37:[0.40625, 0.3359375, 0.26953125], - 38:[0.30859375, 0.15234375, 0.0], - 39:[0.30859375, 0.2578125, 0.20703125], - 40:[0.99609375, 0.74609375, 0.0], - 41:[0.99609375, 0.9140625, 0.6640625], - 42:[0.73828125, 0.55078125, 0.0], - 43:[0.73828125, 0.67578125, 0.4921875], - 44:[0.50390625, 0.375, 0.0], - 45:[0.50390625, 0.4609375, 0.3359375], - 46:[0.40625, 0.3046875, 0.0], - 47:[0.40625, 0.37109375, 0.26953125], - 48:[0.30859375, 0.23046875, 0.0], - 49:[0.30859375, 0.28515625, 0.20703125], - 50:[0.99609375, 0.99609375, 0.0], - 51:[0.99609375, 0.99609375, 0.6640625], - 52:[0.73828125, 0.73828125, 0.0], - 53:[0.73828125, 0.73828125, 0.4921875], - 54:[0.50390625, 0.50390625, 0.0], - 55:[0.50390625, 0.50390625, 0.3359375], - 56:[0.40625, 0.40625, 0.0], - 57:[0.40625, 0.40625, 0.26953125], - 58:[0.30859375, 0.30859375, 0.0], - 59:[0.30859375, 0.30859375, 0.20703125], - 60:[0.74609375, 0.99609375, 0.0], - 61:[0.9140625, 0.99609375, 0.6640625], - 62:[0.55078125, 0.73828125, 0.0], - 63:[0.67578125, 0.73828125, 0.4921875], - 64:[0.375, 0.50390625, 0.0], - 65:[0.4609375, 0.50390625, 0.3359375], - 66:[0.3046875, 0.40625, 0.0], - 67:[0.37109375, 0.40625, 0.26953125], - 68:[0.23046875, 0.30859375, 0.0], - 69:[0.28515625, 0.30859375, 0.20703125], - 70:[0.49609375, 0.99609375, 0.0], - 71:[0.828125, 0.99609375, 0.6640625], - 72:[0.3671875, 0.73828125, 0.0], - 73:[0.61328125, 0.73828125, 0.4921875], - 74:[0.25, 0.50390625, 0.0], - 75:[0.41796875, 0.50390625, 0.3359375], - 76:[0.203125, 0.40625, 0.0], - 77:[0.3359375, 0.40625, 0.26953125], - 78:[0.15234375, 0.30859375, 0.0], - 79:[0.2578125, 0.30859375, 0.20703125], - 80:[0.24609375, 0.99609375, 0.0], - 81:[0.74609375, 0.99609375, 0.6640625], - 82:[0.1796875, 0.73828125, 0.0], - 83:[0.55078125, 0.73828125, 0.4921875], - 84:[0.12109375, 0.50390625, 0.0], - 85:[0.375, 0.50390625, 0.3359375], - 86:[0.09765625, 0.40625, 0.0], - 87:[0.3046875, 0.40625, 0.26953125], - 88:[0.07421875, 0.30859375, 0.0], - 89:[0.23046875, 0.30859375, 0.20703125], - 90:[0.0, 0.99609375, 0.0], - 91:[0.6640625, 0.99609375, 0.6640625], - 92:[0.0, 0.73828125, 0.0], - 93:[0.4921875, 0.73828125, 0.4921875], - 94:[0.0, 0.50390625, 0.0], - 95:[0.3359375, 0.50390625, 0.3359375], - 96:[0.0, 0.40625, 0.0], - 97:[0.26953125, 0.40625, 0.26953125], - 98:[0.0, 0.30859375, 0.0], - 99:[0.20703125, 0.30859375, 0.20703125], - 100:[0.0, 0.99609375, 0.24609375], - 101:[0.6640625, 0.99609375, 0.74609375], - 102:[0.0, 0.73828125, 0.1796875], - 103:[0.4921875, 0.73828125, 0.55078125], - 104:[0.0, 0.50390625, 0.12109375], - 105:[0.3359375, 0.50390625, 0.375], - 106:[0.0, 0.40625, 0.09765625], - 107:[0.26953125, 0.40625, 0.3046875], - 108:[0.0, 0.30859375, 0.07421875], - 109:[0.20703125, 0.30859375, 0.23046875], - 110:[0.0, 0.99609375, 0.49609375], - 111:[0.6640625, 0.99609375, 0.828125], - 112:[0.0, 0.73828125, 0.3671875], - 113:[0.4921875, 0.73828125, 0.61328125], - 114:[0.0, 0.50390625, 0.25], - 115:[0.3359375, 0.50390625, 0.41796875], - 116:[0.0, 0.40625, 0.203125], - 117:[0.26953125, 0.40625, 0.3359375], - 118:[0.0, 0.30859375, 0.15234375], - 119:[0.20703125, 0.30859375, 0.2578125], - 120:[0.0, 0.99609375, 0.74609375], - 121:[0.6640625, 0.99609375, 0.9140625], - 122:[0.0, 0.73828125, 0.55078125], - 123:[0.4921875, 0.73828125, 0.67578125], - 124:[0.0, 0.50390625, 0.375], - 125:[0.3359375, 0.50390625, 0.4609375], - 126:[0.0, 0.40625, 0.3046875], - 127:[0.26953125, 0.40625, 0.37109375], - 128:[0.0, 0.30859375, 0.23046875], - 129:[0.20703125, 0.30859375, 0.28515625], - 130:[0.0, 0.99609375, 0.99609375], - 131:[0.6640625, 0.99609375, 0.99609375], - 132:[0.0, 0.73828125, 0.73828125], - 133:[0.4921875, 0.73828125, 0.73828125], - 134:[0.0, 0.50390625, 0.50390625], - 135:[0.3359375, 0.50390625, 0.50390625], - 136:[0.0, 0.40625, 0.40625], - 137:[0.26953125, 0.40625, 0.40625], - 138:[0.0, 0.30859375, 0.30859375], - 139:[0.20703125, 0.30859375, 0.30859375], - 140:[0.0, 0.74609375, 0.99609375], - 141:[0.6640625, 0.9140625, 0.99609375], - 142:[0.0, 0.55078125, 0.73828125], - 143:[0.4921875, 0.67578125, 0.73828125], - 144:[0.0, 0.375, 0.50390625], - 145:[0.3359375, 0.4609375, 0.50390625], - 146:[0.0, 0.3046875, 0.40625], - 147:[0.26953125, 0.37109375, 0.40625], - 148:[0.0, 0.23046875, 0.30859375], - 149:[0.20703125, 0.28515625, 0.30859375], - 150:[0.0, 0.49609375, 0.99609375], - 151:[0.6640625, 0.828125, 0.99609375], - 152:[0.0, 0.3671875, 0.73828125], - 153:[0.4921875, 0.61328125, 0.73828125], - 154:[0.0, 0.25, 0.50390625], - 155:[0.3359375, 0.41796875, 0.50390625], - 156:[0.0, 0.203125, 0.40625], - 157:[0.26953125, 0.3359375, 0.40625], - 158:[0.0, 0.15234375, 0.30859375], - 159:[0.20703125, 0.2578125, 0.30859375], - 160:[0.0, 0.24609375, 0.99609375], - 161:[0.6640625, 0.74609375, 0.99609375], - 162:[0.0, 0.1796875, 0.73828125], - 163:[0.4921875, 0.55078125, 0.73828125], - 164:[0.0, 0.12109375, 0.50390625], - 165:[0.3359375, 0.375, 0.50390625], - 166:[0.0, 0.09765625, 0.40625], - 167:[0.26953125, 0.3046875, 0.40625], - 168:[0.0, 0.07421875, 0.30859375], - 169:[0.20703125, 0.23046875, 0.30859375], - 170:[0.0, 0.0, 0.99609375], - 171:[0.6640625, 0.6640625, 0.99609375], - 172:[0.0, 0.0, 0.73828125], - 173:[0.4921875, 0.4921875, 0.73828125], - 174:[0.0, 0.0, 0.50390625], - 175:[0.3359375, 0.3359375, 0.50390625], - 176:[0.0, 0.0, 0.40625], - 177:[0.26953125, 0.26953125, 0.40625], - 178:[0.0, 0.0, 0.30859375], - 179:[0.20703125, 0.20703125, 0.30859375], - 180:[0.24609375, 0.0, 0.99609375], - 181:[0.74609375, 0.6640625, 0.99609375], - 182:[0.1796875, 0.0, 0.73828125], - 183:[0.55078125, 0.4921875, 0.73828125], - 184:[0.12109375, 0.0, 0.50390625], - 185:[0.375, 0.3359375, 0.50390625], - 186:[0.09765625, 0.0, 0.40625], - 187:[0.3046875, 0.26953125, 0.40625], - 188:[0.07421875, 0.0, 0.30859375], - 189:[0.23046875, 0.20703125, 0.30859375], - 190:[0.49609375, 0.0, 0.99609375], - 191:[0.828125, 0.6640625, 0.99609375], - 192:[0.3671875, 0.0, 0.73828125], - 193:[0.61328125, 0.4921875, 0.73828125], - 194:[0.25, 0.0, 0.50390625], - 195:[0.41796875, 0.3359375, 0.50390625], - 196:[0.203125, 0.0, 0.40625], - 197:[0.3359375, 0.26953125, 0.40625], - 198:[0.15234375, 0.0, 0.30859375], - 199:[0.2578125, 0.20703125, 0.30859375], - 200:[0.74609375, 0.0, 0.99609375], - 201:[0.9140625, 0.6640625, 0.99609375], - 202:[0.55078125, 0.0, 0.73828125], - 203:[0.67578125, 0.4921875, 0.73828125], - 204:[0.375, 0.0, 0.50390625], - 205:[0.4609375, 0.3359375, 0.50390625], - 206:[0.3046875, 0.0, 0.40625], - 207:[0.37109375, 0.26953125, 0.40625], - 208:[0.23046875, 0.0, 0.30859375], - 209:[0.28515625, 0.20703125, 0.30859375], - 210:[0.99609375, 0.0, 0.99609375], - 211:[0.99609375, 0.6640625, 0.99609375], - 212:[0.73828125, 0.0, 0.73828125], - 213:[0.73828125, 0.4921875, 0.73828125], - 214:[0.50390625, 0.0, 0.50390625], - 215:[0.50390625, 0.3359375, 0.50390625], - 216:[0.40625, 0.0, 0.40625], - 217:[0.40625, 0.26953125, 0.40625], - 218:[0.30859375, 0.0, 0.30859375], - 219:[0.30859375, 0.20703125, 0.30859375], - 220:[0.99609375, 0.0, 0.74609375], - 221:[0.99609375, 0.6640625, 0.9140625], - 222:[0.73828125, 0.0, 0.55078125], - 223:[0.73828125, 0.4921875, 0.67578125], - 224:[0.50390625, 0.0, 0.375], - 225:[0.50390625, 0.3359375, 0.4609375], - 226:[0.40625, 0.0, 0.3046875], - 227:[0.40625, 0.26953125, 0.37109375], - 228:[0.30859375, 0.0, 0.23046875], - 229:[0.30859375, 0.20703125, 0.28515625], - 230:[0.99609375, 0.0, 0.49609375], - 231:[0.99609375, 0.6640625, 0.828125], - 232:[0.73828125, 0.0, 0.3671875], - 233:[0.73828125, 0.4921875, 0.61328125], - 234:[0.50390625, 0.0, 0.25], - 235:[0.50390625, 0.3359375, 0.41796875], - 236:[0.40625, 0.0, 0.203125], - 237:[0.40625, 0.26953125, 0.3359375], - 238:[0.30859375, 0.0, 0.15234375], - 239:[0.30859375, 0.20703125, 0.2578125], - 240:[0.99609375, 0.0, 0.24609375], - 241:[0.99609375, 0.6640625, 0.74609375], - 242:[0.73828125, 0.0, 0.1796875], - 243:[0.73828125, 0.4921875, 0.55078125], - 244:[0.50390625, 0.0, 0.12109375], - 245:[0.50390625, 0.3359375, 0.375], - 246:[0.40625, 0.0, 0.09765625], - 247:[0.40625, 0.26953125, 0.3046875], - 248:[0.30859375, 0.0, 0.07421875], - 249:[0.30859375, 0.20703125, 0.23046875], - 250:[0.19921875, 0.19921875, 0.19921875], - 251:[0.3125, 0.3125, 0.3125], - 252:[0.41015625, 0.41015625, 0.41015625], - 253:[0.5078125, 0.5078125, 0.5078125], - 254:[0.7421875, 0.7421875, 0.7421875], - 255:[0.99609375, 0.99609375, 0.99609375], -} diff --git a/src/Mod/Draft/draftlibs/dxfImportObjects.py b/src/Mod/Draft/draftlibs/dxfImportObjects.py deleted file mode 100644 index 27406b819..000000000 --- a/src/Mod/Draft/draftlibs/dxfImportObjects.py +++ /dev/null @@ -1,1330 +0,0 @@ -"""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 = obj.get_type(2) - if self.name: - self.name = self.name[0] - else: - self.name = 'blank' - - 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!" diff --git a/src/Mod/Draft/draftlibs/dxfLibrary.py b/src/Mod/Draft/draftlibs/dxfLibrary.py deleted file mode 100644 index 05a6e4f03..000000000 --- a/src/Mod/Draft/draftlibs/dxfLibrary.py +++ /dev/null @@ -1,896 +0,0 @@ -#dxfLibrary.py : provides functions for generating DXF files -# -------------------------------------------------------------------------- -__version__ = "v1.33 - 2009.06.16" -__author__ = "Stani Michiels(Stani), Remigiusz Fiedler(migius)" -__license__ = "GPL" -__url__ = "http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_dxf" -__bpydoc__ ="""The library to export geometry data to DXF format r12 version. - -Copyright %s -Version %s -License %s -Homepage %s - -See the homepage for documentation. -Dedicated thread on BlenderArtists: http://blenderartists.org/forum/showthread.php?t=136439 - -IDEAs: -- - -TODO: -- add support for DXFr14 (needs extended file header) -- add support for SPLINEs (possible first in DXFr14 version) -- add user preset for floating point precision (3-16?) - -History -v1.33 - 2009.06.16 by migius - - modif _point(): converts all coords to floats - - modif LineType class: implement elements - - added VPORT class, incl. defaults - - fix Insert class -v1.32 - 2009.06.06 by migius - - modif Style class: changed defaults to widthFactor=1.0, obliqueAngle=0.0 - - modif Text class: alignment parameter reactivated -v1.31 - 2009.06.02 by migius - - modif _Entity class: added paperspace,elevation -v1.30 - 2009.05.28 by migius - - bugfix 3dPOLYLINE/POLYFACE: VERTEX needs x,y,z coordinates, index starts with 1 not 0 -v1.29 - 2008.12.28 by Yorik - - modif POLYLINE to support bulge segments -v1.28 - 2008.12.13 by Steeve/BlenderArtists - - bugfix for EXTMIN/EXTMAX to suit Cycas-CAD -v1.27 - 2008.10.07 by migius - - beautifying output code: keys whitespace prefix - - refactoring DXF-strings format: NewLine moved to the end of -v1.26 - 2008.10.05 by migius - - modif POLYLINE to support POLYFACE -v1.25 - 2008.09.28 by migius - - modif FACE class for r12 -v1.24 - 2008.09.27 by migius - - modif POLYLINE class for r12 - - changing output format from r9 to r12(AC1009) -v1.1 (20/6/2005) by www.stani.be/python/sdxf - - Python library to generate dxf drawings -______________________________________________________________ -""" % (__author__,__version__,__license__,__url__) - -# -------------------------------------------------------------------------- -# DXF Library: copyright (C) 2005 by Stani Michiels (AKA Stani) -# 2008/2009 modif by Remigiusz Fiedler (AKA migius) -# -------------------------------------------------------------------------- -# ***** 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 ***** - - -#import Blender -#from Blender import Mathutils, Window, Scene, sys, Draw -#import BPyMessages - -try: - import copy - #from struct import pack -except: - copy = None - -####1) Private (only for developpers) -_HEADER_POINTS=['insbase','extmin','extmax'] - -#---helper functions----------------------------------- -def _point(x,index=0): - """Convert tuple to a dxf point""" - #print 'deb: _point=', x #------------- - return '\n'.join([' %s\n%s'%((i+1)*10+index,float(x[i])) for i in range(len(x))]) - -def _points(plist): - """Convert a list of tuples to dxf points""" - out = '\n'.join([_point(plist[i],i)for i in range(len(plist))]) - return out - -#---base classes---------------------------------------- -class _Call: - """Makes a callable class.""" - def copy(self): - """Returns a copy.""" - return copy.deepcopy(self) - - def __call__(self,**attrs): - """Returns a copy with modified attributes.""" - copied=self.copy() - for attr in attrs:setattr(copied,attr,attrs[attr]) - return copied - -#------------------------------------------------------- -class _Entity(_Call): - """Base class for _common group codes for entities.""" - def __init__(self,paperspace=None,color=None,layer='0', - lineType=None,lineTypeScale=None,lineWeight=None, - extrusion=None,elevation=None,thickness=None, - parent=None): - """None values will be omitted.""" - self.paperspace = paperspace - self.color = color - self.layer = layer - self.lineType = lineType - self.lineTypeScale = lineTypeScale - self.lineWeight = lineWeight - self.extrusion = extrusion - self.elevation = elevation - self.thickness = thickness - #self.visible = visible - self.parent = parent - - def _common(self): - """Return common group codes as a string.""" - if self.parent:parent=self.parent - else:parent=self - result ='' - if parent.paperspace==1: result+=' 67\n1\n' - if parent.layer!=None: result+=' 8\n%s\n'%parent.layer - if parent.color!=None: result+=' 62\n%s\n'%parent.color - if parent.lineType!=None: result+=' 6\n%s\n'%parent.lineType - # TODO: if parent.lineWeight!=None: result+='370\n%s\n'%parent.lineWeight - # TODO: if parent.visible!=None: result+='60\n%s\n'%parent.visible - if parent.lineTypeScale!=None: result+=' 48\n%s\n'%parent.lineTypeScale - if parent.elevation!=None: result+=' 38\n%s\n'%parent.elevation - if parent.thickness!=None: result+=' 39\n%s\n'%parent.thickness - if parent.extrusion!=None: result+='%s\n'%_point(parent.extrusion,200) - return result - -#-------------------------- -class _Entities: - """Base class to deal with composed objects.""" - def __dxf__(self): - return [] - - def __str__(self): - return ''.join([str(x) for x in self.__dxf__()]) - -#-------------------------- -class _Collection(_Call): - """Base class to expose entities methods to main object.""" - def __init__(self,entities=[]): - self.entities=copy.copy(entities) - #link entities methods to drawing - for attr in dir(self.entities): - if attr[0]!='_': - attrObject=getattr(self.entities,attr) - if callable(attrObject): - setattr(self,attr,attrObject) - -####2) Constants -#---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 - -####3) Classes -#---entitities ----------------------------------------------- -#-------------------------- -class Arc(_Entity): - """Arc, angles in degrees.""" - def __init__(self,center=(0,0,0),radius=1, - startAngle=0.0,endAngle=90,**common): - """Angles in degrees.""" - _Entity.__init__(self,**common) - self.center=center - self.radius=radius - self.startAngle=startAngle - self.endAngle=endAngle - def __str__(self): - return ' 0\nARC\n%s%s\n 40\n%s\n 50\n%s\n 51\n%s\n'%\ - (self._common(),_point(self.center), - self.radius,self.startAngle,self.endAngle) - -#----------------------------------------------- -class Circle(_Entity): - """Circle""" - def __init__(self,center=(0,0,0),radius=1,**common): - _Entity.__init__(self,**common) - self.center=center - self.radius=radius - def __str__(self): - return ' 0\nCIRCLE\n%s%s\n 40\n%s\n'%\ - (self._common(),_point(self.center),self.radius) - -#----------------------------------------------- -class Face(_Entity): - """3dface""" - def __init__(self,points,**common): - _Entity.__init__(self,**common) - while len(points)<4: #fix for r12 format - points.append(points[-1]) - self.points=points - - def __str__(self): - out = ' 0\n3DFACE\n%s%s\n' %(self._common(),_points(self.points)) - #print 'deb:out=', out #------------------- - return out - -#----------------------------------------------- -class Insert(_Entity): - """Block instance.""" - def __init__(self,name,point=(0,0,0), - xscale=None,yscale=None,zscale=None, - cols=None,colspacing=None,rows=None,rowspacing=None, - rotation=None, - **common): - _Entity.__init__(self,**common) - self.name=name - self.point=point - self.xscale=xscale - self.yscale=yscale - self.zscale=zscale - self.cols=cols - self.colspacing=colspacing - self.rows=rows - self.rowspacing=rowspacing - self.rotation=rotation - - def __str__(self): - result=' 0\nINSERT\n 2\n%s\n%s%s\n'%\ - (self.name,self._common(),_point(self.point)) - if self.xscale!=None:result+=' 41\n%s\n'%self.xscale - if self.yscale!=None:result+=' 42\n%s\n'%self.yscale - if self.zscale!=None:result+=' 43\n%s\n'%self.zscale - if self.rotation:result+=' 50\n%s\n'%self.rotation - if self.cols!=None:result+=' 70\n%s\n'%self.cols - if self.colspacing!=None:result+=' 44\n%s\n'%self.colspacing - if self.rows!=None:result+=' 71\n%s\n'%self.rows - if self.rowspacing!=None:result+=' 45\n%s\n'%self.rowspacing - return result - -#----------------------------------------------- -class Line(_Entity): - """Line""" - def __init__(self,points,**common): - _Entity.__init__(self,**common) - self.points=points - def __str__(self): - return ' 0\nLINE\n%s%s\n' %( - self._common(), _points(self.points)) - - -#----------------------------------------------- -class PolyLine(_Entity): - def __init__(self,points,org_point=[0,0,0],flag=0,width=None,**common): - #width = number, or width = list [width_start=None, width_end=None] - #for 2d-polyline: points = [ [x, y, z, width_start=None, width_end=None, bulge=0 or None], ...] - #for 3d-polyline: points = [ [x, y, z], ...] - #for polyface: points = [points_list, faces_list] - _Entity.__init__(self,**common) - self.points=points - self.org_point=org_point - self.flag=flag - self.polyface = False - self.polyline2d = False - self.faces = [] # dummy value - self.width= None # dummy value - if self.flag & POLYFACE_MESH: - self.polyface=True - self.points=points[0] - self.faces=points[1] - self.p_count=len(self.points) - self.f_count=len(self.faces) - elif not self.flag & POLYLINE_3D: - self.polyline2d = True - if width: - if type(width)!='list': - width=[width,width] - self.width=width - - def __str__(self): - result= ' 0\nPOLYLINE\n%s 70\n%s\n' %(self._common(),self.flag) - result+=' 66\n1\n' - result+='%s\n' %_point(self.org_point) - if self.polyface: - result+=' 71\n%s\n' %self.p_count - result+=' 72\n%s\n' %self.f_count - elif self.polyline2d: - if self.width!=None: result+=' 40\n%s\n 41\n%s\n' %(self.width[0],self.width[1]) - for point in self.points: - result+=' 0\nVERTEX\n' - result+=' 8\n%s\n' %self.layer - if self.polyface: - result+='%s\n' %_point(point[0:3]) - result+=' 70\n192\n' - elif self.polyline2d: - result+='%s\n' %_point(point[0:2]) - if len(point)>4: - width1, width2 = point[3], point[4] - if width1!=None: result+=' 40\n%s\n' %width1 - if width2!=None: result+=' 41\n%s\n' %width2 - if len(point)==6: - bulge = point[5] - if bulge: result+=' 42\n%s\n' %bulge - else: - result+='%s\n' %_point(point[0:3]) - for face in self.faces: - result+=' 0\nVERTEX\n' - result+=' 8\n%s\n' %self.layer - result+='%s\n' %_point(self.org_point) - result+=' 70\n128\n' - result+=' 71\n%s\n' %face[0] - result+=' 72\n%s\n' %face[1] - result+=' 73\n%s\n' %face[2] - if len(face)==4: result+=' 74\n%s\n' %face[3] - result+=' 0\nSEQEND\n' - result+=' 8\n%s\n' %self.layer - return result - -#----------------------------------------------- -class Point(_Entity): - """Point.""" - def __init__(self,points=None,**common): - _Entity.__init__(self,**common) - self.points=points - def __str__(self): # TODO: - return ' 0\nPOINT\n%s%s\n' %(self._common(), - _points(self.points) - ) - -#----------------------------------------------- -class Solid(_Entity): - """Colored solid fill.""" - def __init__(self,points=None,**common): - _Entity.__init__(self,**common) - self.points=points - def __str__(self): - return ' 0\nSOLID\n%s%s\n' %(self._common(), - _points(self.points[:2]+[self.points[3],self.points[2]]) - ) - - -#----------------------------------------------- -class Dimension(_Entity): - """Basic dimension entity""" - def __init__(self,point,start,end,**common): - _Entity.__init__(self,**common) - self.points=[point,start,end] - def __str__(self): - result = ' 0\nDIMENSION\n%s' %(self._common()) - result+=' 3\nStandard\n' - result+=' 70\n1\n' - result+='%s\n' %_point(self.points[0]) - result+='%s\n' %_point(self.points[1],3) - result+='%s\n' %_point(self.points[2],4) - print result - return result - -#----------------------------------------------- -class Text(_Entity): - """Single text line.""" - def __init__(self,text='',point=(0,0,0),alignment=None, - flag=None,height=1,justifyhor=None,justifyver=None, - rotation=None,obliqueAngle=None,style=None,xscale=None,**common): - _Entity.__init__(self,**common) - self.text=text - self.point=point - self.alignment=alignment - self.flag=flag - self.height=height - self.justifyhor=justifyhor - self.justifyver=justifyver - self.rotation=rotation - self.obliqueAngle=obliqueAngle - self.style=style - self.xscale=xscale - def __str__(self): - result= ' 0\nTEXT\n%s%s\n 40\n%s\n 1\n%s\n'%\ - (self._common(),_point(self.point),self.height,self.text) - if self.rotation: result+=' 50\n%s\n'%self.rotation - if self.xscale: result+=' 41\n%s\n'%self.xscale - if self.obliqueAngle: result+=' 51\n%s\n'%self.obliqueAngle - if self.style: result+=' 7\n%s\n'%self.style - if self.flag: result+=' 71\n%s\n'%self.flag - if self.justifyhor: result+=' 72\n%s\n'%self.justifyhor - if self.alignment: result+='%s\n'%_point(self.alignment,1) - if self.justifyver: result+=' 73\n%s\n'%self.justifyver - return result - -#----------------------------------------------- -class Mtext(Text): - """Surrogate for mtext, generates some Text instances.""" - def __init__(self,text='',point=(0,0,0),width=250,spacingFactor=1.5,down=0,spacingWidth=None,**options): - Text.__init__(self,text=text,point=point,**options) - if down:spacingFactor*=-1 - self.spacingFactor=spacingFactor - self.spacingWidth=spacingWidth - self.width=width - self.down=down - def __str__(self): - texts=self.text.replace('\r\n','\n').split('\n') - if not self.down:texts.reverse() - result='' - x=y=0 - if self.spacingWidth:spacingWidth=self.spacingWidth - else:spacingWidth=self.height*self.spacingFactor - for text in texts: - while text: - result+='%s\n'%Text(text[:self.width], - point=(self.point[0]+x*spacingWidth, - self.point[1]+y*spacingWidth, - self.point[2]), - alignment=self.alignment,flag=self.flag,height=self.height, - justifyhor=self.justifyhor,justifyver=self.justifyver, - rotation=self.rotation,obliqueAngle=self.obliqueAngle, - style=self.style,xscale=self.xscale,parent=self - ) - text=text[self.width:] - if self.rotation:x+=1 - else:y+=1 - return result[1:] - -#----------------------------------------------- -##class _Mtext(_Entity): -## """Mtext not functioning for minimal dxf.""" -## def __init__(self,text='',point=(0,0,0),attachment=1, -## charWidth=None,charHeight=1,direction=1,height=100,rotation=0, -## spacingStyle=None,spacingFactor=None,style=None,width=100, -## xdirection=None,**common): -## _Entity.__init__(self,**common) -## self.text=text -## self.point=point -## self.attachment=attachment -## self.charWidth=charWidth -## self.charHeight=charHeight -## self.direction=direction -## self.height=height -## self.rotation=rotation -## self.spacingStyle=spacingStyle -## self.spacingFactor=spacingFactor -## self.style=style -## self.width=width -## self.xdirection=xdirection -## def __str__(self): -## input=self.text -## text='' -## while len(input)>250: -## text+='3\n%s\n'%input[:250] -## input=input[250:] -## text+='1\n%s\n'%input -## result= '0\nMTEXT\n%s\n%s\n40\n%s\n41\n%s\n71\n%s\n72\n%s%s\n43\n%s\n50\n%s\n'%\ -## (self._common(),_point(self.point),self.charHeight,self.width, -## self.attachment,self.direction,text, -## self.height, -## self.rotation) -## if self.style:result+='7\n%s\n'%self.style -## if self.xdirection:result+='%s\n'%_point(self.xdirection,1) -## if self.charWidth:result+='42\n%s\n'%self.charWidth -## if self.spacingStyle:result+='73\n%s\n'%self.spacingStyle -## if self.spacingFactor:result+='44\n%s\n'%self.spacingFactor -## return result - -#---tables --------------------------------------------------- -#----------------------------------------------- -class Block(_Collection): - """Use list methods to add entities, eg append.""" - def __init__(self,name,layer='0',flag=0,base=(0,0,0),entities=[]): - self.entities=copy.copy(entities) - _Collection.__init__(self,entities) - self.layer=layer - self.name=name - self.flag=0 - self.base=base - def __str__(self): # TODO: - e=''.join([str(x)for x in self.entities]) - return ' 0\nBLOCK\n 8\n%s\n 2\n%s\n 70\n%s\n%s\n 3\n%s\n%s 0\nENDBLK\n'%\ - (self.layer,self.name.upper(),self.flag,_point(self.base),self.name.upper(),e) - -#----------------------------------------------- -class Layer(_Call): - """Layer""" - def __init__(self,name='pydxf',color=7,lineType='continuous',flag=64): - self.name=name - self.color=color - self.lineType=lineType - self.flag=flag - def __str__(self): - return ' 0\nLAYER\n 2\n%s\n 70\n%s\n 62\n%s\n 6\n%s\n'%\ - (self.name.upper(),self.flag,self.color,self.lineType) - -#----------------------------------------------- -class LineType(_Call): - """Custom linetype""" - def __init__(self,name='CONTINUOUS',description='Solid line',elements=[0.0],flag=0): - self.name=name - self.description=description - self.elements=copy.copy(elements) - self.flag=flag - def __str__(self): - result = ' 0\nLTYPE\n 2\n%s\n 70\n%s\n 3\n%s\n 72\n65\n'%\ - (self.name.upper(),self.flag,self.description) - if self.elements: - elements = ' 73\n%s\n' %(len(self.elements)-1) - elements += ' 40\n%s\n' %(self.elements[0]) - for e in self.elements[1:]: - elements += ' 49\n%s\n' %e - result += elements - return result - - -#----------------------------------------------- -class Style(_Call): - """Text style""" - def __init__(self,name='standard',flag=0,height=0,widthFactor=1.0,obliqueAngle=0.0, - mirror=0,lastHeight=1,font='arial.ttf',bigFont=''): - self.name=name - self.flag=flag - self.height=height - self.widthFactor=widthFactor - self.obliqueAngle=obliqueAngle - self.mirror=mirror - self.lastHeight=lastHeight - self.font=font - self.bigFont=bigFont - def __str__(self): - return ' 0\nSTYLE\n 2\n%s\n 70\n%s\n 40\n%s\n 41\n%s\n 50\n%s\n 71\n%s\n 42\n%s\n 3\n%s\n 4\n%s\n'%\ - (self.name.upper(),self.flag,self.flag,self.widthFactor, - self.obliqueAngle,self.mirror,self.lastHeight, - self.font.upper(),self.bigFont.upper()) - -#----------------------------------------------- -class VPort(_Call): - def __init__(self,name,flag=0, - leftBottom=(0.0,0.0), - rightTop=(1.0,1.0), - center=(0.5,0.5), - snap_base=(0.0,0.0), - snap_spacing=(0.1,0.1), - grid_spacing=(0.1,0.1), - direction=(0.0,0.0,1.0), - target=(0.0,0.0,0.0), - height=1.0, - ratio=1.0, - lens=50, - frontClipping=0, - backClipping=0, - snap_rotation=0, - twist=0, - mode=0, - circle_zoom=100, - fast_zoom=1, - ucsicon=1, - snap_on=0, - grid_on=0, - snap_style=0, - snap_isopair=0 - ): - self.name=name - self.flag=flag - self.leftBottom=leftBottom - self.rightTop=rightTop - self.center=center - self.snap_base=snap_base - self.snap_spacing=snap_spacing - self.grid_spacing=grid_spacing - self.direction=direction - self.target=target - self.height=float(height) - self.ratio=float(ratio) - self.lens=float(lens) - self.frontClipping=float(frontClipping) - self.backClipping=float(backClipping) - self.snap_rotation=float(snap_rotation) - self.twist=float(twist) - self.mode=mode - self.circle_zoom=circle_zoom - self.fast_zoom=fast_zoom - self.ucsicon=ucsicon - self.snap_on=snap_on - self.grid_on=grid_on - self.snap_style=snap_style - self.snap_isopair=snap_isopair - def __str__(self): - output = [' 0', 'VPORT', - ' 2', self.name, - ' 70', self.flag, - _point(self.leftBottom), - _point(self.rightTop,1), - _point(self.center,2), # View center point (in DCS) - _point(self.snap_base,3), - _point(self.snap_spacing,4), - _point(self.grid_spacing,5), - _point(self.direction,6), #view direction from target (in WCS) - _point(self.target,7), - ' 40', self.height, - ' 41', self.ratio, - ' 42', self.lens, - ' 43', self.frontClipping, - ' 44', self.backClipping, - ' 50', self.snap_rotation, - ' 51', self.twist, - ' 71', self.mode, - ' 72', self.circle_zoom, - ' 73', self.fast_zoom, - ' 74', self.ucsicon, - ' 75', self.snap_on, - ' 76', self.grid_on, - ' 77', self.snap_style, - ' 78', self.snap_isopair - ] - - output_str = '' - for s in output: - output_str += '%s\n' %s - return output_str - - - -#----------------------------------------------- -class View(_Call): - def __init__(self,name,flag=0, - width=1, - height=1, - center=(0.5,0.5), - direction=(0,0,1), - target=(0,0,0), - lens=50, - frontClipping=0, - backClipping=0, - twist=0,mode=0 - ): - self.name=name - self.flag=flag - self.width=float(width) - self.height=float(height) - self.center=center - self.direction=direction - self.target=target - self.lens=float(lens) - self.frontClipping=float(frontClipping) - self.backClipping=float(backClipping) - self.twist=float(twist) - self.mode=mode - def __str__(self): - output = [' 0', 'VIEW', - ' 2', self.name, - ' 70', self.flag, - ' 40', self.height, - _point(self.center), - ' 41', self.width, - _point(self.direction,1), - _point(self.target,2), - ' 42', self.lens, - ' 43', self.frontClipping, - ' 44', self.backClipping, - ' 50', self.twist, - ' 71', self.mode - ] - output_str = '' - for s in output: - output_str += '%s\n' %s - return output_str - -#----------------------------------------------- -def ViewByWindow(name,leftBottom=(0,0),rightTop=(1,1),**options): - width=abs(rightTop[0]-leftBottom[0]) - height=abs(rightTop[1]-leftBottom[1]) - center=((rightTop[0]+leftBottom[0])*0.5,(rightTop[1]+leftBottom[1])*0.5) - return View(name=name,width=width,height=height,center=center,**options) - -#---drawing -#----------------------------------------------- -class Drawing(_Collection): - """Dxf drawing. Use append or any other list methods to add objects.""" - def __init__(self,insbase=(0.0,0.0,0.0),extmin=(0.0,0.0,0.0),extmax=(0.0,0.0,0.0), - layers=[Layer()],linetypes=[LineType()],styles=[Style()],blocks=[], - views=[],vports=[],entities=None,fileName='test.dxf'): - # TODO: replace list with None,arial - if not entities: - entities=[] - _Collection.__init__(self,entities) - self.insbase=insbase - self.extmin=extmin - self.extmax=extmax - self.layers=copy.copy(layers) - self.linetypes=copy.copy(linetypes) - self.styles=copy.copy(styles) - self.views=copy.copy(views) - self.vports=copy.copy(vports) - self.blocks=copy.copy(blocks) - self.fileName=fileName - #private - #self.acadver='9\n$ACADVER\n1\nAC1006\n' - self.acadver=' 9\n$ACADVER\n 1\nAC1009\n' - """DXF AutoCAD-Release format codes - AC1021 2008, 2007 - AC1018 2006, 2005, 2004 - AC1015 2002, 2000i, 2000 - AC1014 R14,14.01 - AC1012 R13 - AC1009 R12,11 - AC1006 R10 - AC1004 R9 - AC1002 R2.6 - AC1.50 R2.05 - """ - - def _name(self,x): - """Helper function for self._point""" - return ' 9\n$%s\n' %x.upper() - - def _point(self,name,x): - """Point setting from drawing like extmin,extmax,...""" - return '%s%s' %(self._name(name),_point(x)) - - def _section(self,name,x): - """Sections like tables,blocks,entities,...""" - if x: xstr=''.join(x) - else: xstr='' - return ' 0\nSECTION\n 2\n%s\n%s 0\nENDSEC\n'%(name.upper(),xstr) - - def _table(self,name,x): - """Tables like ltype,layer,style,...""" - if x: xstr=''.join(x) - else: xstr='' - return ' 0\nTABLE\n 2\n%s\n 70\n%s\n%s 0\nENDTAB\n'%(name.upper(),len(x),xstr) - - def __str__(self): - """Returns drawing as dxf string.""" - header=[self.acadver]+[self._point(attr,getattr(self,attr))+'\n' for attr in _HEADER_POINTS] - header=self._section('header',header) - - tables=[self._table('vport',[str(x) for x in self.vports]), - self._table('ltype',[str(x) for x in self.linetypes]), - self._table('layer',[str(x) for x in self.layers]), - self._table('style',[str(x) for x in self.styles]), - self._table('view',[str(x) for x in self.views]), - ] - tables=self._section('tables',tables) - - blocks=self._section('blocks',[str(x) for x in self.blocks]) - - entities=self._section('entities',[str(x) for x in self.entities]) - - all=''.join([header,tables,blocks,entities,' 0\nEOF\n']) - return all - - def saveas(self,fileName): - self.fileName=fileName - self.save() - - def save(self): - test=open(self.fileName,'w') - test.write(str(self)) - test.close() - - -#---extras -#----------------------------------------------- -class Rectangle(_Entity): - """Rectangle, creates lines.""" - def __init__(self,point=(0,0,0),width=1,height=1,solid=None,line=1,**common): - _Entity.__init__(self,**common) - self.point=point - self.width=width - self.height=height - self.solid=solid - self.line=line - def __str__(self): - result='' - points=[self.point,(self.point[0]+self.width,self.point[1],self.point[2]), - (self.point[0]+self.width,self.point[1]+self.height,self.point[2]), - (self.point[0],self.point[1]+self.height,self.point[2]),self.point] - if self.solid: - result+= Solid(points=points[:-1],parent=self.solid) - if self.line: - for i in range(4): - result+= Line(points=[points[i],points[i+1]],parent=self) - return result[1:] - -#----------------------------------------------- -class LineList(_Entity): - """Like polyline, but built of individual lines.""" - def __init__(self,points=[],org_point=[0,0,0],closed=0,**common): - _Entity.__init__(self,**common) - self.closed=closed - self.points=copy.copy(points) - def __str__(self): - if self.closed:points=self.points+[self.points[0]] - else: points=self.points - result='' - for i in range(len(points)-1): - result+= Line(points=[points[i],points[i+1]],parent=self) - return result[1:] - -#----------------------------------------------------- -def test(): - #Blocks - b=Block('test') - b.append(Solid(points=[(0,0,0),(1,0,0),(1,1,0),(0,1,0)],color=1)) - b.append(Arc(center=(1,0,0),color=2)) - - #Drawing - d=Drawing() - #tables - d.blocks.append(b) #table blocks - d.styles.append(Style()) #table styles - d.views.append(View('Normal')) #table view - d.views.append(ViewByWindow('Window',leftBottom=(1,0),rightTop=(2,1))) #idem - - #entities - d.append(Circle(center=(1,1,0),color=3)) - d.append(Face(points=[(0,0,0),(1,0,0),(1,1,0),(0,1,0)],color=4)) - d.append(Insert('test',point=(3,3,3),cols=5,colspacing=2)) - d.append(Line(points=[(0,0,0),(1,1,1)])) - d.append(Mtext('Click on Ads\nmultiple lines with mtext',point=(1,1,1),color=5,rotation=90)) - d.append(Text('Please donate!',point=(3,0,1))) - #d.append(Rectangle(point=(2,2,2),width=4,height=3,color=6,solid=Solid(color=2))) - d.append(Solid(points=[(4,4,0),(5,4,0),(7,8,0),(9,9,0)],color=3)) - #d.append(PolyLine(points=[(1,1,1),(2,1,1),(2,2,1),(1,2,1)],flag=1,color=1)) - - #d.saveas('c:\\test.dxf') - d.saveas('test.dxf') - -#----------------------------------------------------- -if __name__=='__main__': - if not copy: - Draw.PupMenu('Error%t|This script requires a full python install') - else: test() - diff --git a/src/Mod/Draft/draftlibs/dxfReader.py b/src/Mod/Draft/draftlibs/dxfReader.py deleted file mode 100644 index e03777515..000000000 --- a/src/Mod/Draft/draftlibs/dxfReader.py +++ /dev/null @@ -1,384 +0,0 @@ -"""This module provides a function for reading dxf files and parsing them into a useful tree of objects and data. - - The convert function is called by the readDXF fuction to convert dxf strings into the correct data based - on their type code. readDXF expects a (full path) file name as input. -""" - -# -------------------------------------------------------------------------- -# DXF Reader v0.9 by Ed Blake (AKA Kitsu) -# 2008.05.08 modif.def convert() by Remigiusz Fiedler (AKA migius) -# -------------------------------------------------------------------------- -# ***** 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 dxfImportObjects import * - -class Object: - """Empty container class for dxf objects""" - - def __init__(self, _type='', block=False): - """_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 InitializationError(Exception): pass - -class StateMachine: - """(finite) State Machine from the great David Mertz's great Charming Python article.""" - - def __init__(self): - self.handlers = [] - self.startState = None - self.endStates = [] - - def add_state(self, handler, end_state=0): - """All states and handlers are functions which return - a state and a cargo.""" - self.handlers.append(handler) - if end_state: - self.endStates.append(handler) - def set_start(self, handler): - """Sets the starting handler function.""" - self.startState = handler - - - def run(self, cargo=None): - if not self.startState: - raise InitializationError,\ - "must call .set_start() before .run()" - if not self.endStates: - raise InitializationError, \ - "at least one state must be an end_state" - handler = self.startState - while 1: - (newState, cargo) = handler(cargo) - #print cargo - if newState in self.endStates: - return newState(cargo) - #break - elif newState not in self.handlers: - raise RuntimeError, "Invalid target %s" % newState - else: - handler = newState - -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 item in data: - if item[0] == 2: - value = item[1] - break - return item, value - -def get_layer(data): - """Expects object data as input. - - Returns (entry, layer_name) where entry is the data item that provided the layer name. - """ - value = None - for item in data: - if item[0] == 8: - value = item[1] - break - return item, value - - -def convert(code, value): - """Convert a string to the correct Python type based on its dxf code. - code types: - ints = 60-79, 170-179, 270-289, 370-389, 400-409, 1060-1070 - longs = 90-99, 420-429, 440-459, 1071 - floats = 10-39, 40-59, 110-139, 140-149, 210-239, 460-469, 1010-1059 - hex = 105, 310-379, 390-399 - strings = 0-9, 100, 102, 300-309, 410-419, 430-439, 470-479, 999, 1000-1009 - """ - if 59 < code < 80 or 169 < code < 180 or 269 < code < 290 or 369 < code < 390 or 399 < code < 410 or 1059 < code < 1071: - value = int(float(value)) - elif 89 < code < 100 or 419 < code < 430 or 439 < code < 460 or code == 1071: - value = long(float(value)) - elif 9 < code < 60 or 109 < code < 150 or 209 < code < 240 or 459 < code < 470 or 1009 < code < 1060: - value = float(value) - elif code == 105 or 309 < code < 380 or 389 < code < 400: - try: - value = int(value, 16) # should be left as string? - except: - pass - else: # it's already a string so do nothing - pass - return value - - -def findObject(infile, kind=''): - """Finds the next occurance of an object.""" - obj = False - while 1: - line = infile.readline() - if not line: # readline returns '' at eof - return False - if not obj: # We're still looking for our object code - if line.lower().strip() == '0': - obj = True # found it - else: # we are in an object definition - if kind: # if we're looking for a particular kind - if line.lower().strip() == kind: - obj = Object(line.lower().strip()) - break - else: # otherwise take anything non-numeric - if line.lower().strip() not in string.digits: - obj = Object(line.lower().strip()) - break - obj = False # whether we found one or not it's time to start over - return obj - -def handleObject(infile): - """Add data to an object until end of object is found.""" - line = infile.readline() - if line.lower().strip() == 'section': - return 'section' # this would be a problem - elif line.lower().strip() == 'endsec': - return 'endsec' # this means we are done with a section - else: # add data to the object until we find a new object - obj = Object(line.lower().strip()) - obj.name = obj.type - done = False - data = [] - while not done: - line = infile.readline() - if not data: - if line.lower().strip() == '0': - #we've found an object, time to return - return obj - else: - # first part is always an int - data.append(int(line.lower().strip())) - else: - data.append(convert(data[0], line.strip())) - obj.data.append(data) - data = [] - -def handleTable(table, infile): - """Special handler for dealing with nested table objects.""" - item, name = get_name(table.data) - if name: # We should always find a name - table.data.remove(item) - table.name = name.lower() - # This next bit is from handleObject - # handleObject should be generalized to work with any section like object - while 1: - obj = handleObject(infile) - if obj.type == 'table': - print "Warning: previous table not closed!" - return table - elif obj.type == 'endtab': - return table # this means we are done with the table - else: # add objects to the table until one of the above is found - table.data.append(obj) - - - - -def handleBlock(block, infile): - """Special handler for dealing with nested table objects.""" - item, name = get_name(block.data) - if name: # We should always find a name - # block.data.remove(item) - block.name = name - # This next bit is from handleObject - # handleObject should be generalized to work with any section like object - while 1: - obj = handleObject(infile) - if obj.type == 'block': - print "Warning: previous block not closed!" - return block - elif obj.type == 'endblk': - return block # this means we are done with the table - else: # add objects to the table until one of the above is found - block.data.append(obj) - - - - -"""These are the states/functions used in the State Machine. -states: - start - find first section - start_section - add data, find first object - object - add obj-data, watch for next obj (called directly by start_section) - end_section - look for next section or eof - end - return results -""" - -def start(cargo): - """Expects the infile as cargo, initializes the cargo.""" - #print "Entering start state!" - infile = cargo - drawing = Object('drawing') - section = findObject(infile, 'section') - if section: - return start_section, (infile, drawing, section) - else: - return error, (infile, "Failed to find any sections!") - -def start_section(cargo): - """Expects [infile, drawing, section] as cargo, builds a nested section object.""" - #print "Entering start_section state!" - infile = cargo[0] - drawing = cargo[1] - section = cargo[2] - # read each line, if it is an object declaration go to object mode - # otherwise create a [index, data] pair and add it to the sections data. - done = False - data = [] - while not done: - line = infile.readline() - - if not data: # if we haven't found a dxf code yet - if line.lower().strip() == '0': - # we've found an object - while 1: # no way out unless we find an end section or a new section - obj = handleObject(infile) - if obj == 'section': # shouldn't happen - print "Warning: failed to close previous section!" - return end_section, (infile, drawing) - elif obj == 'endsec': # This section is over, look for the next - drawing.data.append(section) - return end_section, (infile, drawing) - elif obj.type == 'table': # tables are collections of data - obj = handleTable(obj, infile) # we need to find all there contents - section.data.append(obj) # before moving on - elif obj.type == 'block': # the same is true of blocks - obj = handleBlock(obj, infile) # we need to find all there contents - section.data.append(obj) # before moving on - else: # found another sub-object - section.data.append(obj) - else: - data.append(int(line.lower().strip())) - else: # we have our code, now we just need to convert the data and add it to our list. - data.append(convert(data[0], line.strip())) - section.data.append(data) - data = [] -def end_section(cargo): - """Expects (infile, drawing) as cargo, searches for next section.""" - #print "Entering end_section state!" - infile = cargo[0] - drawing = cargo[1] - section = findObject(infile, 'section') - if section: - return start_section, (infile, drawing, section) - else: - return end, (infile, drawing) - -def end(cargo): - """Expects (infile, drawing) as cargo, called when eof has been reached.""" - #print "Entering end state!" - infile = cargo[0] - drawing = cargo[1] - #infile.close() - return drawing - -def error(cargo): - """Expects a (infile, string) as cargo, called when there is an error during processing.""" - #print "Entering error state!" - infile = cargo[0] - err = cargo[1] - infile.close() - print "There has been an error:" - print err - return False - -def readDXF(filename): - """Given a file name try to read it as a dxf file. - - Output is an object with the following structure - drawing - header - header data - classes - class data - tables - table data - blocks - block data - entities - entity data - objects - object data - where foo data is a list of sub-objects. True object data - is of the form [code, data]. -""" - infile = open(filename) - - sm = StateMachine() - sm.add_state(error, True) - sm.add_state(end, True) - sm.add_state(start_section) - sm.add_state(end_section) - sm.add_state(start) - sm.set_start(start) - try: - drawing = sm.run(infile) - if drawing: - drawing.name = filename - for obj in drawing.data: - item, name = get_name(obj.data) - if name: - obj.data.remove(item) - obj.name = name.lower() - setattr(drawing, name.lower(), obj) - # Call the objectify function to cast - # raw objects into the right types of object - obj.data = objectify(obj.data) - #print obj.name - finally: - infile.close() - return drawing -if __name__ == "__main__": - filename = r".\examples\block-test.dxf" - drawing = readDXF(filename) - for item in drawing.entities.data: - print item diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py index 85d89ec4c..e56f87fd4 100644 --- a/src/Mod/Draft/importDXF.py +++ b/src/Mod/Draft/importDXF.py @@ -39,9 +39,7 @@ lines, polylines, lwpolylines, circles, arcs, texts, colors,layers (from groups) ''' -import FreeCAD, os, Part, math, re, string, Mesh, Draft, DraftVecUtils, DraftGeomUtils -from draftlibs import dxfColorMap, dxfLibrary -from draftlibs.dxfReader import readDXF +import sys, FreeCAD, os, Part, math, re, string, Mesh, Draft, DraftVecUtils, DraftGeomUtils from Draft import _Dimension, _ViewProviderDimension from FreeCAD import Vector @@ -51,9 +49,23 @@ else: gui = True try: draftui = FreeCADGui.draftToolBar except: draftui = None +files = ['dxfColorMap.py','dxfImportObjects.py','dxfLibrary.py','dxfReader.py'] +baseurl = 'https://raw.github.com/yorikvanhavre/Draft-dxf-importer/master/' +for f in files: + p = os.path.join(FreeCAD.ConfigGet("UserAppData"),f) + if not os.path.exists(p): + import ArchCommands + p = None + p = ArchCommands.download(baseurl+f) + if not p: + FreeCAD.Console.PrintWarning("Download of dxf libraries failed. Please download them manually from https://github.com/yorikvanhavre/Draft-dxf-importer") + sys.exit() +sys.path.append(FreeCAD.ConfigGet("UserAppData")) +import dxfColorMap, dxfLibrary, dxfReader + if open.__module__ == '__builtin__': pythonopen = open # to distinguish python built-in open function from the one declared here - + def prec(): "returns the current Draft precision level" return Draft.getParam("precision") @@ -771,7 +783,7 @@ def processdxf(document,filename): "this does the translation of the dxf contents into FreeCAD Part objects" global drawing # for debugging - so drawing is still accessible to python after the script FreeCAD.Console.PrintMessage("opening "+filename+"...\n") - drawing = readDXF(filename) + drawing = dxfReader.readDXF(filename) global layers layers = [] global doc