dxfImportObjects.py

Go to the documentation of this file.
00001 """This module provides wrapper objects for dxf entities.
00002     
00003     The wrappers expect a "dxf object" as input.  The dxf object is
00004     an object with a type and a data attribute.  Type is a lowercase 
00005     string matching the 0 code of a dxf entity.  Data is a list containing
00006     dxf objects or lists of [code, data] pairs.
00007     
00008     This module is not general, and is only for dxf import.
00009 """
00010 
00011 # --------------------------------------------------------------------------
00012 # DXF Import Objects v0.8 by Ed Blake (AKA Kitsu)
00013 # --------------------------------------------------------------------------
00014 # ***** BEGIN GPL LICENSE BLOCK *****
00015 #
00016 # This program is free software; you can redistribute it and/or
00017 # modify it under the terms of the GNU General Public License
00018 # as published by the Free Software Foundation; either version 2
00019 # of the License, or (at your option) any later version.
00020 #
00021 # This program is distributed in the hope that it will be useful,
00022 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00023 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024 # GNU General Public License for more details.
00025 #
00026 # You should have received a copy of the GNU General Public License
00027 # along with this program; if not, write to the Free Software Foundation,
00028 # Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00029 #
00030 # ***** END GPL LICENCE BLOCK *****
00031 # --------------------------------------------------------------------------
00032 from math import *
00033 
00034 
00035 # from Stani's dxf writer v1.1 (c)www.stani.be (GPL)
00036 #---color values
00037 BYBLOCK=0
00038 BYLAYER=256
00039 
00040 #---block-type flags (bit coded values, may be combined): 
00041 ANONYMOUS               =1  # This is an anonymous block generated by hatching, associative dimensioning, other internal operations, or an application
00042 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)
00043 XREF                    =4  # This block is an external reference (xref)
00044 XREF_OVERLAY            =8  # This block is an xref overlay 
00045 EXTERNAL                =16 # This block is externally dependent
00046 RESOLVED                =32 # This is a resolved external reference, or dependent of an external reference (ignored on input)
00047 REFERENCED              =64 # This definition is a referenced external reference (ignored on input)
00048 
00049 #---mtext flags
00050 #attachment point
00051 TOP_LEFT        = 1
00052 TOP_CENTER      = 2
00053 TOP_RIGHT       = 3
00054 MIDDLE_LEFT     = 4
00055 MIDDLE_CENTER   = 5
00056 MIDDLE_RIGHT    = 6
00057 BOTTOM_LEFT     = 7
00058 BOTTOM_CENTER   = 8
00059 BOTTOM_RIGHT    = 9
00060 #drawing direction
00061 LEFT_RIGHT      = 1
00062 TOP_BOTTOM      = 3
00063 BY_STYLE        = 5 #the flow direction is inherited from the associated text style
00064 #line spacing style (optional): 
00065 AT_LEAST        = 1 #taller characters will override
00066 EXACT           = 2 #taller characters will not override
00067 
00068 #---polyline flags
00069 CLOSED                      =1      # This is a closed polyline (or a polygon mesh closed in the M direction)
00070 CURVE_FIT                   =2      # Curve-fit vertices have been added
00071 SPLINE_FIT                  =4      # Spline-fit vertices have been added
00072 POLYLINE_3D                 =8      # This is a 3D polyline
00073 POLYGON_MESH                =16     # This is a 3D polygon mesh
00074 CLOSED_N                    =32     # The polygon mesh is closed in the N direction
00075 POLYFACE_MESH               =64     # The polyline is a polyface mesh
00076 CONTINOUS_LINETYPE_PATTERN  =128    # The linetype pattern is generated continuously around the vertices of this polyline
00077 
00078 #---text flags
00079 #horizontal
00080 LEFT        = 0
00081 CENTER      = 1
00082 RIGHT       = 2
00083 ALIGNED     = 3 #if vertical alignment = 0
00084 MIDDLE      = 4 #if vertical alignment = 0
00085 FIT         = 5 #if vertical alignment = 0
00086 #vertical
00087 BASELINE    = 0
00088 BOTTOM      = 1
00089 MIDDLE      = 2
00090 TOP         = 3
00091 class Object:
00092     """Empty container class for dxf objects"""
00093     
00094     def __init__(self, _type=''):
00095         """_type expects a string value."""
00096         self.type = _type
00097         self.name = ''
00098         self.data = []
00099     
00100     def __str__(self):
00101         if self.name:
00102             return self.name
00103         else:
00104             return self.type
00105     
00106     def __repr__(self):
00107         return str(self.data)
00108     
00109     def get_type(self, kind=''):
00110         """Despite the name, this method actually returns all objects of type 'kind' from self.data."""
00111         if type:
00112             objects = []
00113             for item in self.data:
00114                 if type(item) != list and item.type == kind:
00115                     # we want this type of object
00116                     objects.append(item)
00117                 elif type(item) == list and item[0] == kind:
00118                     # we want this type of data
00119                     objects.append(item[1])
00120             return objects
00121     
00122 
00123 class Layer:
00124     """Class for objects representing dxf layers."""
00125     
00126     def __init__(self, obj):
00127         """Expects an entity object of type line as input."""
00128         self.type = obj.type
00129         self.data = obj.data[:]
00130         
00131         self.name = obj.get_type(2)[0]
00132         self.color = obj.get_type(62)[0]
00133         self.flags = obj.get_type(70)[0]
00134         self.frozen = self.flags&1
00135         
00136     
00137     
00138     def __repr__(self):
00139         return "%s: name - %s, color - %s" %(self.__class__.__name__, self.name, self.color)
00140     
00141 
00142 
00143 class Line:
00144     """Class for objects representing dxf lines."""
00145     
00146     def __init__(self, obj):
00147         """Expects an entity object of type line as input."""
00148         if not obj.type == 'line':
00149             raise TypeError, "Wrong type %s for line object!" %obj.type
00150         self.type = obj.type
00151         self.data = obj.data[:]
00152         
00153         self.space = obj.get_type(67)
00154         if self.space:
00155             self.space = self.space[0]
00156         else:
00157             self.space = 0
00158         
00159         self.color_index = obj.get_type(62)
00160         if self.color_index:
00161             self.color_index = self.color_index[0]
00162         else:
00163             self.color_index = BYLAYER
00164         
00165         discard, self.layer, discard_index = get_layer(obj.data)
00166         del obj.data[discard_index]
00167         
00168         self.points = self.get_points(obj.data)
00169     
00170     
00171     
00172     
00173     def get_points(self, data):
00174         """Gets start and end points for a line type object.
00175         
00176         Lines have a fixed number of points (two) and fixed codes for each value.
00177         """
00178         
00179         # start x, y, z and end x, y, z = 0
00180         sx, sy, sz, ex, ey, ez = 0, 0, 0, 0, 0, 0
00181         for item in data:
00182             if item[0] == 10:   # 10 = x
00183                 sx = item[1]
00184             elif item[0] == 20: # 20 = y
00185                 sy = item[1]
00186             elif item[0] == 30: # 30 = z
00187                 sz = item[1]
00188             elif item[0] == 11: # 11 = x
00189                 ex = item[1]
00190             elif item[0] == 21: # 21 = y
00191                 ey = item[1]
00192             elif item[0] == 31: # 31 = z
00193                 ez = item[1]
00194         return [[sx, sy, sz], [ex, ey, ez]]
00195     
00196     
00197     
00198     def __repr__(self):
00199         return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points)
00200     
00201 
00202 
00203 class LWpolyline:
00204     """Class for objects representing dxf LWpolylines."""
00205     
00206     def __init__(self, obj):
00207         """Expects an entity object of type lwpolyline as input."""
00208         if not obj.type == 'lwpolyline':
00209             raise TypeError, "Wrong type %s for polyline object!" %obj.type
00210         self.type = obj.type
00211         self.data = obj.data[:]
00212         
00213         # required data
00214         self.num_points = obj.get_type(90)[0]
00215         
00216         # optional data (with defaults)
00217         self.space = obj.get_type(67)
00218         if self.space:
00219             self.space = self.space[0]
00220         else:
00221             self.space = 0
00222             
00223         self.color_index = obj.get_type(62)
00224         if self.color_index:
00225             self.color_index = self.color_index[0]
00226         else:
00227             self.color_index = BYLAYER
00228             
00229         self.elevation = obj.get_type(38)
00230         if self.elevation:
00231             self.elevation = self.elevation[0]
00232         else:
00233             self.elevation = 0
00234             
00235         self.flags = obj.get_type(70)
00236         if self.flags:
00237             self.flags = self.flags[0]
00238         else:
00239             self.flags = 0
00240         
00241         self.closed = self.flags&1 # byte coded, 1 = closed, 128 = plinegen
00242         discard, self.layer, discard_index = get_layer(obj.data)
00243         del obj.data[discard_index]
00244         self.points = self.get_points(obj.data)
00245         self.extrusion = self.get_extrusion(obj.data)
00246     
00247     
00248     
00249     
00250     
00251     
00252     def get_points(self, data):
00253         """Gets points for a polyline type object.
00254         
00255         Polylines have no fixed number of verts, and 
00256         each vert can have a number of properties.
00257         Verts should be coded as 
00258         10:xvalue
00259         20:yvalue
00260         40:startwidth or 0
00261         41:endwidth or 0
00262         42:bulge or 0
00263         for each vert
00264         """
00265         num = self.num_points
00266         point = None
00267         points = []
00268         for item in data:
00269             if item[0] == 10:   # 10 = x
00270                 if point:
00271                     points.append(point)
00272                 point = Vertex()
00273                 point.x = item[1]
00274             elif item[0] == 20: # 20 = y
00275                 point.y = item[1]
00276             elif item[0] == 40: # 40 = start width
00277                 point.swidth = item[1]
00278             elif item[0] == 41: # 41 = end width
00279                 point.ewidth = item[1]
00280             elif item[0] == 42: # 42 = bulge
00281                 point.bulge = item[1]
00282         points.append(point)
00283         return points
00284     
00285     
00286     def get_extrusion(self, data):
00287         """Find the axis of extrusion.
00288         
00289         Used to get the objects Object Coordinate System (ocs).
00290         """
00291         vec = [0,0,1]
00292         for item in data:
00293             if item[0] == 210:   # 210 = x
00294                 vec[0] = item[1]
00295             elif item[0] == 220: # 220 = y
00296                 vec[1] = item[1]
00297             elif item[0] == 230: # 230 = z
00298                 vec[2] = item[1]
00299         return vec
00300     
00301     
00302     def __repr__(self):
00303         return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points)
00304     
00305 
00306 
00307 class Polyline:
00308     """Class for objects representing dxf LWpolylines."""
00309     
00310     def __init__(self, obj):
00311         """Expects an entity object of type polyline as input."""
00312         if not obj.type == 'polyline':
00313             raise TypeError, "Wrong type %s for polyline object!" %obj.type
00314         self.type = obj.type
00315         self.data = obj.data[:]
00316         self.points = []
00317         
00318         # optional data (with defaults)
00319         self.space = obj.get_type(67)
00320         if self.space:
00321             self.space = self.space[0]
00322         else:
00323             self.space = 0
00324             
00325         self.color_index = obj.get_type(62)
00326         if self.color_index:
00327             self.color_index = self.color_index[0]
00328         else:
00329             self.color_index = BYLAYER
00330             
00331         self.elevation = obj.get_type(30)
00332         if self.elevation:
00333             self.elevation = self.elevation[0]
00334         else:
00335             self.elevation = 0
00336             
00337         self.flags = obj.get_type(70)
00338         if self.flags:
00339             self.flags = self.flags[0]
00340         else:
00341             self.flags = 0
00342         
00343         self.closed = self.flags&1 # byte coded, 1 = closed, 128 = plinegen
00344             
00345         discard, self.layer, discard_index = get_layer(obj.data)
00346         del obj.data[discard_index]
00347         self.extrusion = self.get_extrusion(obj.data)
00348     
00349     
00350     
00351     
00352     
00353     def get_extrusion(self, data):
00354         """Find the axis of extrusion.
00355         
00356         Used to get the objects Object Coordinate System (ocs).
00357         """
00358         vec = [0,0,1]
00359         for item in data:
00360             if item[0] == 210:   # 210 = x
00361                 vec[0] = item[1]
00362             elif item[0] == 220: # 220 = y
00363                 vec[1] = item[1]
00364             elif item[0] == 230: # 230 = z
00365                 vec[2] = item[1]
00366         return vec
00367     
00368     
00369     def __repr__(self):
00370         return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points)
00371     
00372 
00373 
00374 class Vertex(object):
00375     """Generic vertex object used by polylines (and maybe others)."""
00376     
00377     def __init__(self, obj=None):
00378         """Initializes vertex data.
00379         
00380             The optional obj arg is an entity object of type vertex.
00381         """
00382         self.loc = [0,0,0]
00383         self.bulge = 0
00384         self.swidth = 0
00385         self.ewidth = 0
00386         self.flags = 0
00387         
00388         if obj is not None:
00389             if not obj.type == 'vertex':
00390                 raise TypeError, "Wrong type %s for vertex object!" %obj.type
00391             self.type = obj.type
00392             self.data = obj.data[:]
00393             
00394             self.get_props(obj.data)
00395     
00396     
00397     def get_props(self, data):
00398         """Gets coords for a vertex type object.
00399         
00400         Each vert can have a number of properties.
00401         Verts should be coded as 
00402         10:xvalue
00403         20:yvalue
00404         40:startwidth or 0
00405         41:endwidth or 0
00406         42:bulge or 0
00407         """
00408         for item in data:
00409             if item[0] == 10:   # 10 = x
00410                 self.x = item[1]
00411             elif item[0] == 20: # 20 = y
00412                 self.y = item[1]
00413             elif item[0] == 30: # 30 = z
00414                 self.z = item[1]
00415             elif item[0] == 40: # 40 = start width
00416                 self.swidth = item[1]
00417             elif item[0] == 41: # 41 = end width
00418                 self.ewidth = item[1]
00419             elif item[0] == 42: # 42 = bulge
00420                 self.bulge = item[1]
00421             elif item[0] == 70: # 70 = vert flags
00422                 self.flags = item[1]
00423     
00424     
00425     def __len__(self):
00426         return 3
00427     
00428     
00429     def __getitem__(self, key):
00430         return self.loc[key]
00431     
00432     
00433     def __setitem__(self, key, value):
00434         if key in [0,1,2]:
00435             self.loc[key]
00436     
00437     
00438     def __iter__(self):
00439         return self.loc.__iter__()
00440     
00441     
00442     def __str__(self):
00443         return str(self.loc)
00444     
00445     
00446     def __repr__(self):
00447         return "Vertex %s, swidth=%s, ewidth=%s, bulge=%s" %(self.loc, self.swidth, self.ewidth, self.bulge)
00448     
00449     
00450     def getx(self):
00451         return self.loc[0]
00452     
00453     def setx(self, value):
00454         self.loc[0] = value
00455     
00456     x = property(getx, setx)
00457     
00458     
00459     def gety(self):
00460         return self.loc[1]
00461     
00462     def sety(self, value):
00463         self.loc[1] = value
00464     
00465     y = property(gety, sety)
00466     
00467     
00468     def getz(self):
00469         return self.loc[2]
00470     
00471     def setz(self, value):
00472         self.loc[2] = value
00473     
00474     z = property(getz, setz)
00475     
00476 
00477 
00478 class Text:
00479     """Class for objects representing dxf Text."""
00480     
00481     def __init__(self, obj):
00482         """Expects an entity object of type text as input."""
00483         if not obj.type == 'text':
00484             raise TypeError, "Wrong type %s for text object!" %obj.type
00485         self.type = obj.type
00486         self.data = obj.data[:]
00487         
00488         # required data
00489         self.height = obj.get_type(40)[0]
00490         self.value = obj.get_type(1)[0] # The text string value
00491         
00492         # optional data (with defaults)
00493         self.space = obj.get_type(67)
00494         if self.space:
00495             self.space = self.space[0]
00496         else:
00497             self.space = 0
00498             
00499         self.color_index = obj.get_type(62)
00500         if self.color_index:
00501             self.color_index = self.color_index[0]
00502         else:
00503             self.color_index = BYLAYER
00504             
00505         self.rotation = obj.get_type(50) # radians?
00506         if not self.rotation:
00507             self.rotation = 0
00508         else:
00509             self.rotation = self.rotation[0]
00510         
00511         self.width_factor = obj.get_type(41) # Scaling factor along local x axis
00512         if not self.width_factor:
00513             self.width_factor = 1
00514         else:
00515             self.width_factor = self.width_factor[0]
00516         
00517         self.oblique = obj.get_type(51) # skew in degrees -90 <= oblique <= 90
00518         if not self.oblique:
00519             self.oblique = 0
00520         else:
00521             self.oblique = self.oblique[0]
00522         
00523         self.halignment = obj.get_type(72) # horiz. alignment
00524         if not self.halignment:  # 0=left, 1=center, 2=right, 3=aligned, 4=middle, 5=fit
00525             self.halignment = 0
00526         else:
00527             self.halignment = self.halignment[0]
00528             
00529         self.valignment = obj.get_type(73) # vert. alignment
00530         if not self.valignment:  # 0=baseline, 1=bottom, 2=middle, 3=top
00531             self.valignment = 0
00532         else:
00533             self.valignment = self.valignment[0]
00534             
00535         discard, self.layer, discard_index = get_layer(obj.data)
00536         del obj.data[discard_index]
00537         self.loc = self.get_loc(obj.data, self.halignment, self.valignment)
00538         self.extrusion = self.get_extrusion(obj.data)
00539     
00540     
00541     
00542     
00543     def get_loc(self, data, halign, valign):
00544         """Gets adjusted location for text type objects.
00545         
00546         If group 72 and/or 73 values are nonzero then the first alignment point values
00547         are ignored and AutoCAD calculates new values based on the second alignment
00548         point and the length and height of the text string itself (after applying the
00549         text style). If the 72 and 73 values are zero or missing, then the second
00550         alignment point is meaningless.
00551         
00552         I don't know how to calc text size...
00553         """
00554         # bottom left x, y, z and justification x, y, z = 0
00555         x, y, z, jx, jy, jz = 0, 0, 0, 0, 0, 0
00556         for item in data:
00557             if item[0] == 10:   # 10 = x
00558                 x = item[1]
00559             elif item[0] == 20: # 20 = y
00560                 y = item[1]
00561             elif item[0] == 30: # 30 = z
00562                 z = item[1]
00563             elif item[0] == 11: # 11 = x
00564                 jx = item[1]
00565             elif item[0] == 21: # 21 = y
00566                 jy = item[1]
00567             elif item[0] == 31: # 31 = z
00568                 jz = item[1]
00569                 
00570         if halign or valign:
00571             x, y, z = jx, jy, jz
00572         return [x, y, z]
00573     
00574     def get_extrusion(self, data):
00575         """Find the axis of extrusion.
00576         
00577         Used to get the objects Object Coordinate System (ocs).
00578         """
00579         vec = [0,0,1]
00580         for item in data:
00581             if item[0] == 210:   # 210 = x
00582                 vec[0] = item[1]
00583             elif item[0] == 220: # 220 = y
00584                 vec[1] = item[1]
00585             elif item[0] == 230: # 230 = z
00586                 vec[2] = item[1]
00587         return vec
00588     
00589     
00590     def __repr__(self):
00591         return "%s: layer - %s, value - %s" %(self.__class__.__name__, self.layer, self.value)
00592     
00593 
00594 
00595 class Mtext:
00596     """Class for objects representing dxf Mtext."""
00597     
00598     def __init__(self, obj):
00599         """Expects an entity object of type mtext as input."""
00600         if not obj.type == 'mtext':
00601             raise TypeError, "Wrong type %s for mtext object!" %obj.type
00602         self.type = obj.type
00603         self.data = obj.data[:]
00604         
00605         # required data
00606         self.height = obj.get_type(40)[0]
00607         self.width = obj.get_type(41)[0]
00608         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
00609         self.value = self.get_text(obj.data) # The text string value
00610         
00611         # optional data (with defaults)
00612         self.space = obj.get_type(67)
00613         if self.space:
00614             self.space = self.space[0]
00615         else:
00616             self.space = 0
00617             
00618         self.color_index = obj.get_type(62)
00619         if self.color_index:
00620             self.color_index = self.color_index[0]
00621         else:
00622             self.color_index = BYLAYER
00623             
00624         self.rotation = obj.get_type(50) # radians
00625         if not self.rotation:
00626             self.rotation = 0
00627         else:
00628             self.rotation = self.rotation[0]
00629         
00630         self.width_factor = obj.get_type(42) # Scaling factor along local x axis
00631         if not self.width_factor:
00632             self.width_factor = 1
00633         else:
00634             self.width_factor = self.width_factor[0]
00635         
00636         self.line_space = obj.get_type(44) # percentage of default
00637         if not self.line_space:
00638             self.line_space = 1
00639         else:
00640             self.line_space = self.line_space[0]
00641             
00642         discard, self.layer, discard_index = get_layer(obj.data)
00643         del obj.data[discard_index]
00644         self.loc = self.get_loc(obj.data)
00645         self.extrusion = self.get_extrusion(obj.data)
00646     
00647     
00648     
00649     
00650     
00651     def get_text(self, data):
00652         """Reconstructs mtext data from dxf codes."""
00653         primary = ''
00654         secondary = []
00655         for item in data:
00656             if item[0] == 1: # There should be only one primary...
00657                 primary = item[1]
00658             elif item[0] == 3: # There may be any number of extra strings (in order)
00659                 secondary.append(item[1])
00660         if not primary:
00661             #raise ValueError, "Empty Mtext Object!"
00662             string = "Empty Mtext Object!"
00663         if not secondary:
00664             string = primary.replace(r'\P', '\n')
00665         else:
00666             string = ''.join(secondary)+primary
00667             string = string.replace(r'\P', '\n')
00668         return string    
00669     def get_loc(self, data):
00670         """Gets location for a mtext type objects.
00671         
00672         Mtext objects have only one point indicating location.
00673         """
00674         loc = [0,0,0]
00675         for item in data:
00676             if item[0] == 10:   # 10 = x
00677                 loc[0] = item[1]
00678             elif item[0] == 20: # 20 = y
00679                 loc[1] = item[1]
00680             elif item[0] == 30: # 30 = z
00681                 loc[2] = item[1]
00682         return loc
00683     
00684     
00685     
00686     
00687     def get_extrusion(self, data):
00688         """Find the axis of extrusion.
00689         
00690         Used to get the objects Object Coordinate System (ocs).
00691         """
00692         vec = [0,0,1]
00693         for item in data:
00694             if item[0] == 210:   # 210 = x
00695                 vec[0] = item[1]
00696             elif item[0] == 220: # 220 = y
00697                 vec[1] = item[1]
00698             elif item[0] == 230: # 230 = z
00699                 vec[2] = item[1]
00700         return vec
00701     
00702     
00703     def __repr__(self):
00704         return "%s: layer - %s, value - %s" %(self.__class__.__name__, self.layer, self.value)
00705     
00706 
00707 
00708 class Circle:
00709     """Class for objects representing dxf Circles."""
00710     
00711     def __init__(self, obj):
00712         """Expects an entity object of type circle as input."""
00713         if not obj.type == 'circle':
00714             raise TypeError, "Wrong type %s for circle object!" %obj.type
00715         self.type = obj.type
00716         self.data = obj.data[:]
00717         
00718         # required data
00719         self.radius = obj.get_type(40)[0]
00720         
00721         # optional data (with defaults)
00722         self.space = obj.get_type(67)
00723         if self.space:
00724             self.space = self.space[0]
00725         else:
00726             self.space = 0
00727             
00728         self.color_index = obj.get_type(62)
00729         if self.color_index:
00730             self.color_index = self.color_index[0]
00731         else:
00732             self.color_index = BYLAYER
00733             
00734         discard, self.layer, discard_index = get_layer(obj.data)
00735         del obj.data[discard_index]
00736         self.loc = self.get_loc(obj.data)
00737         self.extrusion = self.get_extrusion(obj.data)
00738     
00739     
00740     
00741     
00742     
00743     def get_loc(self, data):
00744         """Gets the center location for circle type objects.
00745         
00746         Circles have a single coord location.
00747         """
00748         loc = [0, 0, 0]
00749         for item in data:
00750             if item[0] == 10:   # 10 = x
00751                 loc[0] = item[1]
00752             elif item[0] == 20: # 20 = y
00753                 loc[1] = item[1]
00754             elif item[0] == 30: # 30 = z
00755                 loc[2] = item[1]
00756         return loc
00757     
00758     
00759     
00760     def get_extrusion(self, data):
00761         """Find the axis of extrusion.
00762         
00763         Used to get the objects Object Coordinate System (ocs).
00764         """
00765         vec = [0,0,1]
00766         for item in data:
00767             if item[0] == 210:   # 210 = x
00768                 vec[0] = item[1]
00769             elif item[0] == 220: # 220 = y
00770                 vec[1] = item[1]
00771             elif item[0] == 230: # 230 = z
00772                 vec[2] = item[1]
00773         return vec
00774     
00775     
00776     def __repr__(self):
00777         return "%s: layer - %s, radius - %s" %(self.__class__.__name__, self.layer, self.radius)
00778     
00779 
00780 
00781 class Arc:
00782     """Class for objects representing dxf arcs."""
00783     
00784     def __init__(self, obj):
00785         """Expects an entity object of type arc as input."""
00786         if not obj.type == 'arc':
00787             raise TypeError, "Wrong type %s for arc object!" %obj.type
00788         self.type = obj.type
00789         self.data = obj.data[:]
00790         
00791         # required data
00792         self.radius = obj.get_type(40)[0]
00793         self.start_angle = obj.get_type(50)[0]
00794         self.end_angle = obj.get_type(51)[0]
00795         
00796         # optional data (with defaults)
00797         self.space = obj.get_type(67)
00798         if self.space:
00799             self.space = self.space[0]
00800         else:
00801             self.space = 0
00802             
00803         self.color_index = obj.get_type(62)
00804         if self.color_index:
00805             self.color_index = self.color_index[0]
00806         else:
00807             self.color_index = BYLAYER
00808             
00809         discard, self.layer, discard_index = get_layer(obj.data)
00810         del obj.data[discard_index]
00811         self.loc = self.get_loc(obj.data)
00812         self.extrusion = self.get_extrusion(obj.data)
00813     
00814     
00815     
00816     
00817     
00818     def get_loc(self, data):
00819         """Gets the center location for arc type objects.
00820         
00821         Arcs have a single coord location.
00822         """
00823         loc = [0, 0, 0]
00824         for item in data:
00825             if item[0] == 10:   # 10 = x
00826                 loc[0] = item[1]
00827             elif item[0] == 20: # 20 = y
00828                 loc[1] = item[1]
00829             elif item[0] == 30: # 30 = z
00830                 loc[2] = item[1]
00831         return loc
00832     
00833     
00834     
00835     def get_extrusion(self, data):
00836         """Find the axis of extrusion.
00837         
00838         Used to get the objects Object Coordinate System (ocs).
00839         """
00840         vec = [0,0,1]
00841         for item in data:
00842             if item[0] == 210:   # 210 = x
00843                 vec[0] = item[1]
00844             elif item[0] == 220: # 220 = y
00845                 vec[1] = item[1]
00846             elif item[0] == 230: # 230 = z
00847                 vec[2] = item[1]
00848         return vec
00849     
00850     
00851     def __repr__(self):
00852         return "%s: layer - %s, radius - %s" %(self.__class__.__name__, self.layer, self.radius)
00853     
00854 
00855 
00856 class BlockRecord:
00857     """Class for objects representing dxf block_records."""
00858     
00859     def __init__(self, obj):
00860         """Expects an entity object of type block_record as input."""
00861         if not obj.type == 'block_record':
00862             raise TypeError, "Wrong type %s for block_record object!" %obj.type
00863         self.type = obj.type
00864         self.data = obj.data[:]
00865         
00866         # required data
00867         self.name = obj.get_type(2)[0]
00868         
00869         # optional data (with defaults)
00870         self.insertion_units = obj.get_type(70)
00871         if not self.insertion_units:
00872             self.insertion_units = None
00873         else:
00874             self.insertion_units = self.insertion_units[0]
00875             
00876         self.insert_units = obj.get_type(1070)
00877         if not self.insert_units:
00878             self.insert_units = None
00879         else:
00880             self.insert_units = self.insert_units[0]
00881         
00882     
00883     
00884     
00885     
00886     
00887     def __repr__(self):
00888         return "%s: name - %s, insert units - %s" %(self.__class__.__name__, self.name, self.insertion_units)
00889     
00890 
00891 
00892 
00893 class Block:
00894     """Class for objects representing dxf blocks."""
00895     
00896     def __init__(self, obj):
00897         """Expects an entity object of type block as input."""
00898         if not obj.type == 'block':
00899             raise TypeError, "Wrong type %s for block object!" %obj.type
00900         self.type = obj.type
00901         self.data = obj.data[:]
00902         
00903         # required data
00904         self.flags = obj.get_type(70)[0]
00905         self.entities = Object('block_contents')
00906         self.entities.data = objectify([ent for ent in obj.data if type(ent) != list])
00907         
00908         # optional data (with defaults)
00909         self.name = obj.get_type(3)
00910         if self.name:
00911             self.name = self.name[0]
00912         else:
00913             self.name = obj.get_type(2)
00914             if self.name:
00915                 self.name = self.name[0]
00916             else:
00917                 self.name = 'blank'
00918             
00919         self.path = obj.get_type(1)
00920         if self.path:
00921             self.path = self.path[0]
00922         else:
00923             self.path = ''
00924             
00925         self.discription = obj.get_type(4)
00926         if self.discription:
00927             self.discription = self.discription[0]
00928         else:
00929             self.discription = ''
00930             
00931         discard, self.layer, discard_index = get_layer(obj.data)
00932         del obj.data[discard_index]
00933         self.loc = self.get_loc(obj.data)
00934     
00935     
00936     
00937     
00938     
00939     def get_loc(self, data):
00940         """Gets the insert point of the block."""
00941         loc = [0, 0, 0]
00942         for item in data:
00943             if type(item) != list:
00944                 continue
00945             if item[0] == 10:   # 10 = x
00946                 loc[0] = item[1]
00947             elif item[0] == 20: # 20 = y
00948                 loc[1] = item[1]
00949             elif item[0] == 30: # 30 = z
00950                 loc[2] = item[1]
00951         return loc
00952     
00953     
00954     
00955     def __repr__(self):
00956         return "%s: name - %s, description - %s, xref-path - %s" %(self.__class__.__name__, self.name, self.discription, self.path)
00957     
00958 
00959 
00960 
00961 class Insert:
00962     """Class for objects representing dxf inserts."""
00963     
00964     def __init__(self, obj):
00965         """Expects an entity object of type insert as input."""
00966         if not obj.type == 'insert':
00967             raise TypeError, "Wrong type %s for insert object!" %obj.type
00968         self.type = obj.type
00969         self.data = obj.data[:]
00970         
00971         # required data
00972         self.block = obj.get_type(2)[0]
00973         
00974         # optional data (with defaults)
00975         self.rotation = obj.get_type(50)
00976         if self.rotation:
00977             self.rotation = self.rotation[0]
00978         else:
00979             self.rotation = 0
00980         
00981         self.space = obj.get_type(67)
00982         if self.space:
00983             self.space = self.space[0]
00984         else:
00985             self.space = 0
00986             
00987         self.color_index = obj.get_type(62)
00988         if self.color_index:
00989             self.color_index = self.color_index[0]
00990         else:
00991             self.color_index = BYLAYER
00992         
00993         discard, self.layer, discard_index = get_layer(obj.data)
00994         del obj.data[discard_index]
00995         self.loc = self.get_loc(obj.data)
00996         self.scale = self.get_scale(obj.data)
00997         self.rows, self.columns = self.get_array(obj.data)
00998         self.extrusion = self.get_extrusion(obj.data)
00999     
01000     
01001     
01002     
01003     
01004     def get_loc(self, data):
01005         """Gets the center location for circle type objects.
01006         
01007         Circles have a single coord location.
01008         """
01009         loc = [0, 0, 0]
01010         for item in data:
01011             if item[0] == 10:   # 10 = x
01012                 loc[0] = item[1]
01013             elif item[0] == 20: # 20 = y
01014                 loc[1] = item[1]
01015             elif item[0] == 30: # 30 = z
01016                 loc[2] = item[1]
01017         return loc
01018     
01019     
01020     
01021     def get_scale(self, data):
01022         """Gets the x/y/z scale factor for the block.
01023         """
01024         scale = [1, 1, 1]
01025         for item in data:
01026             if item[0] == 41:   # 41 = x scale
01027                 scale[0] = item[1]
01028             elif item[0] == 42: # 42 = y scale
01029                 scale[1] = item[1]
01030             elif item[0] == 43: # 43 = z scale
01031                 scale[2] = item[1]
01032         return scale
01033     
01034     
01035     
01036     def get_array(self, data):
01037         """Returns the pair (row number, row spacing), (column number, column spacing)."""
01038         columns = 1
01039         rows = 1
01040         cspace = 0
01041         rspace = 0
01042         for item in data:
01043             if item[0] == 70:   # 70 = columns
01044                 columns = item[1]
01045             elif item[0] == 71: # 71 = rows
01046                 rows = item[1]
01047             if item[0] == 44:   # 44 = columns
01048                 cspace = item[1]
01049             elif item[0] == 45: # 45 = rows
01050                 rspace = item[1]
01051         return (rows, rspace), (columns, cspace)
01052     
01053     
01054     
01055     def get_extrusion(self, data):
01056         """Find the axis of extrusion.
01057         
01058         Used to get the objects Object Coordinate System (ocs).
01059         """
01060         vec = [0,0,1]
01061         for item in data:
01062             if item[0] == 210:   # 210 = x
01063                 vec[0] = item[1]
01064             elif item[0] == 220: # 220 = y
01065                 vec[1] = item[1]
01066             elif item[0] == 230: # 230 = z
01067                 vec[2] = item[1]
01068         return vec
01069     
01070     
01071     def __repr__(self):
01072         return "%s: layer - %s, block - %s" %(self.__class__.__name__, self.layer, self.block)
01073     
01074 
01075 
01076 
01077 class Ellipse:
01078     """Class for objects representing dxf ellipses."""
01079     
01080     def __init__(self, obj):
01081         """Expects an entity object of type ellipse as input."""
01082         if not obj.type == 'ellipse':
01083             raise TypeError, "Wrong type %s for ellipse object!" %obj.type
01084         self.type = obj.type
01085         self.data = obj.data[:]
01086         
01087         # required data
01088         self.ratio = obj.get_type(40)[0]
01089         self.start_angle = obj.get_type(41)[0]
01090         self.end_angle = obj.get_type(42)[0]
01091         
01092         # optional data (with defaults)
01093         self.space = obj.get_type(67)
01094         if self.space:
01095             self.space = self.space[0]
01096         else:
01097             self.space = 0
01098             
01099         self.color_index = obj.get_type(62)
01100         if self.color_index:
01101             self.color_index = self.color_index[0]
01102         else:
01103             self.color_index = BYLAYER
01104             
01105         discard, self.layer, discard_index = get_layer(obj.data)
01106         del obj.data[discard_index]
01107         self.loc = self.get_loc(obj.data)
01108         self.major = self.get_major(obj.data)
01109         self.extrusion = self.get_extrusion(obj.data)
01110         self.radius = sqrt(self.major[0]**2 + self.major[0]**2 + self.major[0]**2)
01111     
01112     
01113     
01114     
01115     def get_loc(self, data):
01116         """Gets the center location for arc type objects.
01117         
01118         Arcs have a single coord location.
01119         """
01120         loc = [0, 0, 0]
01121         for item in data:
01122             if item[0] == 10:   # 10 = x
01123                 loc[0] = item[1]
01124             elif item[0] == 20: # 20 = y
01125                 loc[1] = item[1]
01126             elif item[0] == 30: # 30 = z
01127                 loc[2] = item[1]
01128         return loc
01129     
01130     
01131     
01132     def get_major(self, data):
01133         """Gets the major axis for ellipse type objects.
01134         
01135         The ellipse major axis defines the rotation of the ellipse and its radius.
01136         """
01137         loc = [0, 0, 0]
01138         for item in data:
01139             if item[0] == 11:   # 11 = x
01140                 loc[0] = item[1]
01141             elif item[0] == 21: # 21 = y
01142                 loc[1] = item[1]
01143             elif item[0] == 31: # 31 = z
01144                 loc[2] = item[1]
01145         return loc
01146     
01147     
01148     
01149     def get_extrusion(self, data):
01150         """Find the axis of extrusion.
01151         
01152         Used to get the objects Object Coordinate System (ocs).
01153         """
01154         vec = [0,0,1]
01155         for item in data:
01156             if item[0] == 210:   # 210 = x
01157                 vec[0] = item[1]
01158             elif item[0] == 220: # 220 = y
01159                 vec[1] = item[1]
01160             elif item[0] == 230: # 230 = z
01161                 vec[2] = item[1]
01162         return vec
01163     
01164     
01165     def __repr__(self):
01166         return "%s: layer - %s, radius - %s" %(self.__class__.__name__, self.layer, self.radius)
01167     
01168 
01169 
01170 class Face:
01171     """Class for objects representing dxf 3d faces."""
01172     
01173     def __init__(self, obj):
01174         """Expects an entity object of type 3dfaceplot as input."""
01175         if not obj.type == '3dface':
01176             raise TypeError, "Wrong type %s for 3dface object!" %obj.type
01177         self.type = obj.type
01178         self.data = obj.data[:]
01179         
01180         # optional data (with defaults)
01181         self.space = obj.get_type(67)
01182         if self.space:
01183             self.space = self.space[0]
01184         else:
01185             self.space = 0
01186         
01187         self.color_index = obj.get_type(62)
01188         if self.color_index:
01189             self.color_index = self.color_index[0]
01190         else:
01191             self.color_index = BYLAYER
01192         
01193         discard, self.layer, discard_index = get_layer(obj.data)
01194         del obj.data[discard_index]
01195         self.points = self.get_points(obj.data)
01196     
01197     
01198     
01199     
01200     def get_points(self, data):
01201         """Gets 3-4 points for a 3d face type object.
01202         
01203         Faces have three or optionally four verts.
01204         """
01205         
01206         a = [0, 0, 0]
01207         b = [0, 0, 0]
01208         c = [0, 0, 0]
01209         d = False
01210         for item in data:
01211             # ----------- a -------------
01212             if item[0] == 10:   # 10 = x
01213                 a[0] = item[1]
01214             elif item[0] == 20: # 20 = y
01215                 a[1] = item[1]
01216             elif item[0] == 30: # 30 = z
01217                 a[2] = item[1]
01218             # ----------- b -------------
01219             elif item[0] == 11: # 11 = x
01220                 b[0] = item[1]
01221             elif item[0] == 21: # 21 = y
01222                 b[1] = item[1]
01223             elif item[0] == 31: # 31 = z
01224                 b[2] = item[1]
01225             # ----------- c -------------
01226             elif item[0] == 12: # 12 = x
01227                 c[0] = item[1]
01228             elif item[0] == 22: # 22 = y
01229                 c[1] = item[1]
01230             elif item[0] == 32: # 32 = z
01231                 c[2] = item[1]
01232             # ----------- d -------------
01233             elif item[0] == 13: # 13 = x
01234                 d = [0, 0, 0]
01235                 d[0] = item[1]
01236             elif item[0] == 23: # 23 = y
01237                 d[1] = item[1]
01238             elif item[0] == 33: # 33 = z
01239                 d[2] = item[1]
01240         out = [a,b,c]
01241         if d:
01242             out.append(d)
01243         return out
01244     
01245     
01246     def __repr__(self):
01247         return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points)
01248     
01249 
01250 def get_name(data):
01251     """Get the name of an object from its object data.
01252     
01253     Returns a pair of (data_item, name) where data_item is the list entry where the name was found
01254     (the data_item can be used to remove the entry from the object data).  Be sure to check 
01255     name not None before using the returned values!
01256     """
01257     value = None
01258     for i, item in enumerate(data):
01259         if item[0] == 2:
01260             value = item[1]
01261             break
01262     return item, value, i
01263 
01264 def get_layer(data):
01265     """Expects object data as input.
01266     
01267     Returns (entry, layer_name, entry_index) where entry is the data item that provided the layer name.
01268     """
01269     value = None
01270     for i, item in enumerate(data):
01271         if item[0] == 8:
01272             value = item[1]
01273             break
01274     return item, value, i
01275 
01276 
01277 # type to object map
01278 type_map = {
01279     'line':Line,
01280     'lwpolyline':LWpolyline,
01281     'text':Text,
01282     'mtext':Mtext,
01283     'circle':Circle,
01284     'arc':Arc,
01285     'layer':Layer,
01286     'block_record':BlockRecord,
01287     'block':Block,
01288     'insert':Insert,
01289     'ellipse':Ellipse,
01290     '3dface':Face
01291 }
01292 
01293 def objectify(data):
01294     """Expects a section type object's data as input.
01295     
01296     Maps object data to the correct object type.
01297     """
01298     objects = [] # colector for finished objects
01299     known_types = type_map.keys() # so we don't have to call foo.keys() every iteration
01300     index = 0
01301     while index < len(data):
01302         item = data[index]
01303         if type(item) != list and item.type in known_types:
01304             # proccess the object and append the resulting object
01305             objects.append(type_map[item.type](item))
01306         elif type(item) != list and item.type == 'table':
01307             item.data = objectify(item.data) # tables have sub-objects
01308             objects.append(item)
01309         elif type(item) != list and item.type == 'polyline':
01310             pline = Polyline(item)
01311             while 1:
01312                 index += 1
01313                 item = data[index]
01314                 if item.type == 'vertex':
01315                     v = Vertex(item)
01316                     pline.points.append(v)
01317                 elif item.type == 'seqend':
01318                     break
01319                 else:
01320                     print "Error: non-vertex found before seqend!"
01321                     index -= 1
01322                     break
01323             objects.append(pline)
01324         else:
01325             # we will just let the data pass un-harrased
01326             objects.append(item)
01327         index += 1
01328     return objects    
01329 if __name__ == "__main__":
01330     print "No example yet!"

Generated on Wed Nov 23 19:00:09 2011 for FreeCAD by  doxygen 1.6.1