dxfLibrary.py

Go to the documentation of this file.
00001 #dxfLibrary.py : provides functions for generating DXF files
00002 # --------------------------------------------------------------------------
00003 __version__ = "v1.33 - 2009.06.16"
00004 __author__ = "Stani Michiels(Stani), Remigiusz Fiedler(migius)"
00005 __license__ = "GPL"
00006 __url__ = "http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_dxf"
00007 __bpydoc__ ="""The library to export geometry data to DXF format r12 version.
00008 
00009 Copyright %s
00010 Version %s
00011 License %s
00012 Homepage %s
00013 
00014 See the homepage for documentation.
00015 Dedicated thread on BlenderArtists: http://blenderartists.org/forum/showthread.php?t=136439
00016 
00017 IDEAs:
00018 -
00019 
00020 TODO:
00021 - add support for DXFr14 (needs extended file header)
00022 - add support for SPLINEs (possible first in DXFr14 version)
00023 - add user preset for floating point precision (3-16?)
00024 
00025 History
00026 v1.33 - 2009.06.16 by migius
00027  - modif _point(): converts all coords to floats
00028  - modif LineType class: implement elements
00029  - added VPORT class, incl. defaults
00030  - fix Insert class
00031 v1.32 - 2009.06.06 by migius
00032  - modif Style class: changed defaults to widthFactor=1.0, obliqueAngle=0.0
00033  - modif Text class: alignment parameter reactivated
00034 v1.31 - 2009.06.02 by migius
00035  - modif _Entity class: added paperspace,elevation
00036 v1.30 - 2009.05.28 by migius
00037  - bugfix 3dPOLYLINE/POLYFACE: VERTEX needs x,y,z coordinates, index starts with 1 not 0
00038 v1.29 - 2008.12.28 by Yorik
00039  - modif POLYLINE to support bulge segments
00040 v1.28 - 2008.12.13 by Steeve/BlenderArtists
00041  - bugfix for EXTMIN/EXTMAX to suit Cycas-CAD
00042 v1.27 - 2008.10.07 by migius
00043  - beautifying output code: keys whitespace prefix
00044  - refactoring DXF-strings format: NewLine moved to the end of
00045 v1.26 - 2008.10.05 by migius
00046  - modif POLYLINE to support POLYFACE
00047 v1.25 - 2008.09.28 by migius
00048  - modif FACE class for r12
00049 v1.24 - 2008.09.27 by migius
00050  - modif POLYLINE class for r12
00051  - changing output format from r9 to r12(AC1009)
00052 v1.1 (20/6/2005) by www.stani.be/python/sdxf
00053  - Python library to generate dxf drawings
00054 ______________________________________________________________
00055 """ % (__author__,__version__,__license__,__url__)
00056 
00057 # --------------------------------------------------------------------------
00058 # DXF Library: copyright (C) 2005 by Stani Michiels (AKA Stani)
00059 #                       2008/2009 modif by Remigiusz Fiedler (AKA migius)
00060 # --------------------------------------------------------------------------
00061 # ***** BEGIN GPL LICENSE BLOCK *****
00062 #
00063 # This program is free software; you can redistribute it and/or
00064 # modify it under the terms of the GNU General Public License
00065 # as published by the Free Software Foundation; either version 2
00066 # of the License, or (at your option) any later version.
00067 #
00068 # This program is distributed in the hope that it will be useful,
00069 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00070 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00071 # GNU General Public License for more details.
00072 #
00073 # You should have received a copy of the GNU General Public License
00074 # along with this program; if not, write to the Free Software Foundation,
00075 # Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00076 #
00077 # ***** END GPL LICENCE BLOCK *****
00078 
00079 
00080 #import Blender
00081 #from Blender import Mathutils, Window, Scene, sys, Draw
00082 #import BPyMessages
00083 
00084 try:
00085         import copy
00086         #from struct import pack
00087 except:
00088         copy = None
00089 
00090 ####1) Private (only for developpers)
00091 _HEADER_POINTS=['insbase','extmin','extmax']
00092 
00093 #---helper functions-----------------------------------
00094 def _point(x,index=0):
00095         """Convert tuple to a dxf point"""
00096         #print 'deb: _point=', x #-------------
00097         return '\n'.join([' %s\n%s'%((i+1)*10+index,float(x[i])) for i in range(len(x))])
00098 
00099 def _points(plist):
00100         """Convert a list of tuples to dxf points"""
00101         out = '\n'.join([_point(plist[i],i)for i in range(len(plist))])
00102         return out
00103 
00104 #---base classes----------------------------------------
00105 class _Call:
00106         """Makes a callable class."""
00107         def copy(self):
00108                 """Returns a copy."""
00109                 return copy.deepcopy(self)
00110 
00111         def __call__(self,**attrs):
00112                 """Returns a copy with modified attributes."""
00113                 copied=self.copy()
00114                 for attr in attrs:setattr(copied,attr,attrs[attr])
00115                 return copied
00116 
00117 #-------------------------------------------------------
00118 class _Entity(_Call):
00119         """Base class for _common group codes for entities."""
00120         def __init__(self,paperspace=None,color=None,layer='0',
00121                                  lineType=None,lineTypeScale=None,lineWeight=None,
00122                                  extrusion=None,elevation=None,thickness=None,
00123                                  parent=None):
00124                 """None values will be omitted."""
00125                 self.paperspace   = paperspace
00126                 self.color                = color
00127                 self.layer                = layer
00128                 self.lineType      = lineType
00129                 self.lineTypeScale  = lineTypeScale
00130                 self.lineWeight  = lineWeight
00131                 self.extrusion    = extrusion
00132                 self.elevation    = elevation
00133                 self.thickness    = thickness
00134                 #self.visible     = visible
00135                 self.parent              = parent
00136 
00137         def _common(self):
00138                 """Return common group codes as a string."""
00139                 if self.parent:parent=self.parent
00140                 else:parent=self
00141                 result =''
00142                 if parent.paperspace==1: result+='  67\n1\n'
00143                 if parent.layer!=None: result+='  8\n%s\n'%parent.layer
00144                 if parent.color!=None: result+=' 62\n%s\n'%parent.color
00145                 if parent.lineType!=None: result+='  6\n%s\n'%parent.lineType
00146                 # TODO: if parent.lineWeight!=None: result+='370\n%s\n'%parent.lineWeight
00147                 # TODO: if parent.visible!=None: result+='60\n%s\n'%parent.visible
00148                 if parent.lineTypeScale!=None: result+=' 48\n%s\n'%parent.lineTypeScale
00149                 if parent.elevation!=None: result+=' 38\n%s\n'%parent.elevation
00150                 if parent.thickness!=None: result+=' 39\n%s\n'%parent.thickness
00151                 if parent.extrusion!=None: result+='%s\n'%_point(parent.extrusion,200)
00152                 return result
00153 
00154 #--------------------------
00155 class _Entities:
00156         """Base class to deal with composed objects."""
00157         def __dxf__(self):
00158                 return []
00159 
00160         def __str__(self):
00161                 return ''.join([str(x) for x in self.__dxf__()])
00162 
00163 #--------------------------
00164 class _Collection(_Call):
00165         """Base class to expose entities methods to main object."""
00166         def __init__(self,entities=[]):
00167                 self.entities=copy.copy(entities)
00168                 #link entities methods to drawing
00169                 for attr in dir(self.entities):
00170                         if attr[0]!='_':
00171                                 attrObject=getattr(self.entities,attr)
00172                                 if callable(attrObject):
00173                                         setattr(self,attr,attrObject)
00174 
00175 ####2) Constants
00176 #---color values
00177 BYBLOCK=0
00178 BYLAYER=256
00179 
00180 #---block-type flags (bit coded values, may be combined):
00181 ANONYMOUS =1  # This is an anonymous block generated by hatching, associative dimensioning, other internal operations, or an application
00182 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)
00183 XREF =4  # This block is an external reference (xref)
00184 XREF_OVERLAY =8  # This block is an xref overlay
00185 EXTERNAL =16 # This block is externally dependent
00186 RESOLVED =32 # This is a resolved external reference, or dependent of an external reference (ignored on input)
00187 REFERENCED =64 # This definition is a referenced external reference (ignored on input)
00188 
00189 #---mtext flags
00190 #attachment point
00191 TOP_LEFT = 1
00192 TOP_CENTER = 2
00193 TOP_RIGHT = 3
00194 MIDDLE_LEFT = 4
00195 MIDDLE_CENTER = 5
00196 MIDDLE_RIGHT    = 6
00197 BOTTOM_LEFT = 7
00198 BOTTOM_CENTER = 8
00199 BOTTOM_RIGHT = 9
00200 #drawing direction
00201 LEFT_RIGHT = 1
00202 TOP_BOTTOM = 3
00203 BY_STYLE = 5 #the flow direction is inherited from the associated text style
00204 #line spacing style (optional):
00205 AT_LEAST = 1 #taller characters will override
00206 EXACT = 2 #taller characters will not override
00207 
00208 #---polyline flags
00209 CLOSED =1         # This is a closed polyline (or a polygon mesh closed in the M direction)
00210 CURVE_FIT =2      # Curve-fit vertices have been added
00211 SPLINE_FIT =4     # Spline-fit vertices have been added
00212 POLYLINE_3D =8    # This is a 3D polyline
00213 POLYGON_MESH =16         # This is a 3D polygon mesh
00214 CLOSED_N =32     # The polygon mesh is closed in the N direction
00215 POLYFACE_MESH =64        # The polyline is a polyface mesh
00216 CONTINOUS_LINETYPE_PATTERN =128 # The linetype pattern is generated continuously around the vertices of this polyline
00217 
00218 #---text flags
00219 #horizontal
00220 LEFT = 0
00221 CENTER = 1
00222 RIGHT = 2
00223 ALIGNED = 3 #if vertical alignment = 0
00224 MIDDLE = 4 #if vertical alignment = 0
00225 FIT = 5 #if vertical alignment = 0
00226 #vertical
00227 BASELINE = 0
00228 BOTTOM  = 1
00229 MIDDLE = 2
00230 TOP = 3
00231 
00232 ####3) Classes
00233 #---entitities -----------------------------------------------
00234 #--------------------------
00235 class Arc(_Entity):
00236         """Arc, angles in degrees."""
00237         def __init__(self,center=(0,0,0),radius=1,
00238                                  startAngle=0.0,endAngle=90,**common):
00239                 """Angles in degrees."""
00240                 _Entity.__init__(self,**common)
00241                 self.center=center
00242                 self.radius=radius
00243                 self.startAngle=startAngle
00244                 self.endAngle=endAngle
00245         def __str__(self):
00246                 return '  0\nARC\n%s%s\n 40\n%s\n 50\n%s\n 51\n%s\n'%\
00247                            (self._common(),_point(self.center),
00248                                 self.radius,self.startAngle,self.endAngle)
00249 
00250 #-----------------------------------------------
00251 class Circle(_Entity):
00252         """Circle"""
00253         def __init__(self,center=(0,0,0),radius=1,**common):
00254                 _Entity.__init__(self,**common)
00255                 self.center=center
00256                 self.radius=radius
00257         def __str__(self):
00258                 return '  0\nCIRCLE\n%s%s\n 40\n%s\n'%\
00259                            (self._common(),_point(self.center),self.radius)
00260 
00261 #-----------------------------------------------
00262 class Face(_Entity):
00263         """3dface"""
00264         def __init__(self,points,**common):
00265                 _Entity.__init__(self,**common)
00266                 while len(points)<4: #fix for r12 format
00267                         points.append(points[-1])
00268                 self.points=points
00269                 
00270         def __str__(self):
00271                 out = '  0\n3DFACE\n%s%s\n' %(self._common(),_points(self.points))
00272                 #print 'deb:out=', out #-------------------
00273                 return out
00274 
00275 #-----------------------------------------------
00276 class Insert(_Entity):
00277         """Block instance."""
00278         def __init__(self,name,point=(0,0,0),
00279                                  xscale=None,yscale=None,zscale=None,
00280                                  cols=None,colspacing=None,rows=None,rowspacing=None,
00281                                  rotation=None,
00282                                  **common):
00283                 _Entity.__init__(self,**common)
00284                 self.name=name
00285                 self.point=point
00286                 self.xscale=xscale
00287                 self.yscale=yscale
00288                 self.zscale=zscale
00289                 self.cols=cols
00290                 self.colspacing=colspacing
00291                 self.rows=rows
00292                 self.rowspacing=rowspacing
00293                 self.rotation=rotation
00294 
00295         def __str__(self):
00296                 result='  0\nINSERT\n  2\n%s\n%s%s\n'%\
00297                                 (self.name,self._common(),_point(self.point))
00298                 if self.xscale!=None:result+=' 41\n%s\n'%self.xscale
00299                 if self.yscale!=None:result+=' 42\n%s\n'%self.yscale
00300                 if self.zscale!=None:result+=' 43\n%s\n'%self.zscale
00301                 if self.rotation:result+=' 50\n%s\n'%self.rotation
00302                 if self.cols!=None:result+=' 70\n%s\n'%self.cols
00303                 if self.colspacing!=None:result+=' 44\n%s\n'%self.colspacing
00304                 if self.rows!=None:result+=' 71\n%s\n'%self.rows
00305                 if self.rowspacing!=None:result+=' 45\n%s\n'%self.rowspacing
00306                 return result
00307 
00308 #-----------------------------------------------
00309 class Line(_Entity):
00310         """Line"""
00311         def __init__(self,points,**common):
00312                 _Entity.__init__(self,**common)
00313                 self.points=points
00314         def __str__(self):
00315                 return '  0\nLINE\n%s%s\n' %(
00316                                 self._common(), _points(self.points))
00317 
00318 
00319 #-----------------------------------------------
00320 class PolyLine(_Entity):
00321         def __init__(self,points,org_point=[0,0,0],flag=0,width=None,**common):
00322                 #width = number, or width = list [width_start=None, width_end=None]
00323                 #for 2d-polyline: points = [ [x, y, z, width_start=None, width_end=None, bulge=0 or None], ...]
00324                 #for 3d-polyline: points = [ [x, y, z], ...]
00325                 #for polyface: points = [points_list, faces_list]
00326                 _Entity.__init__(self,**common)
00327                 self.points=points
00328                 self.org_point=org_point
00329                 self.flag=flag
00330                 self.polyface = False
00331                 self.polyline2d = False
00332                 self.faces = [] # dummy value
00333                 self.width= None # dummy value
00334                 if self.flag & POLYFACE_MESH:
00335                         self.polyface=True
00336                         self.points=points[0]
00337                         self.faces=points[1]
00338                         self.p_count=len(self.points)
00339                         self.f_count=len(self.faces)
00340                 elif not self.flag & POLYLINE_3D:
00341                         self.polyline2d = True
00342                         if width:
00343                                 if type(width)!='list':
00344                                         width=[width,width]
00345                                 self.width=width
00346 
00347         def __str__(self):
00348                 result= '  0\nPOLYLINE\n%s 70\n%s\n' %(self._common(),self.flag)
00349                 result+=' 66\n1\n'
00350                 result+='%s\n' %_point(self.org_point)
00351                 if self.polyface:
00352                         result+=' 71\n%s\n' %self.p_count
00353                         result+=' 72\n%s\n' %self.f_count
00354                 elif self.polyline2d:
00355                         if self.width!=None: result+=' 40\n%s\n 41\n%s\n' %(self.width[0],self.width[1])
00356                 for point in self.points:
00357                         result+='  0\nVERTEX\n'
00358                         result+='  8\n%s\n' %self.layer
00359                         if self.polyface:
00360                                 result+='%s\n' %_point(point[0:3])
00361                                 result+=' 70\n192\n'
00362                         elif self.polyline2d:
00363                                 result+='%s\n' %_point(point[0:2])
00364                                 if len(point)>4:
00365                                         width1, width2 = point[3], point[4]
00366                                         if width1!=None: result+=' 40\n%s\n' %width1
00367                                         if width2!=None: result+=' 41\n%s\n' %width2
00368                                 if len(point)==6:
00369                                         bulge = point[5]
00370                                         if bulge: result+=' 42\n%s\n' %bulge
00371                         else:
00372                                 result+='%s\n' %_point(point[0:3])
00373                 for face in self.faces:
00374                         result+='  0\nVERTEX\n'
00375                         result+='  8\n%s\n' %self.layer
00376                         result+='%s\n' %_point(self.org_point)
00377                         result+=' 70\n128\n'
00378                         result+=' 71\n%s\n' %face[0]
00379                         result+=' 72\n%s\n' %face[1]
00380                         result+=' 73\n%s\n' %face[2]
00381                         if len(face)==4: result+=' 74\n%s\n' %face[3]
00382                 result+='  0\nSEQEND\n'
00383                 result+='  8\n%s\n' %self.layer
00384                 return result
00385 
00386 #-----------------------------------------------
00387 class Point(_Entity):
00388         """Point."""
00389         def __init__(self,points=None,**common):
00390                 _Entity.__init__(self,**common)
00391                 self.points=points
00392         def __str__(self): # TODO:
00393                 return '  0\nPOINT\n%s%s\n' %(self._common(),
00394                          _points(self.points)
00395                         )
00396 
00397 #-----------------------------------------------
00398 class Solid(_Entity):
00399         """Colored solid fill."""
00400         def __init__(self,points=None,**common):
00401                 _Entity.__init__(self,**common)
00402                 self.points=points
00403         def __str__(self):
00404                 return '  0\nSOLID\n%s%s\n' %(self._common(),
00405                          _points(self.points[:2]+[self.points[3],self.points[2]])
00406                         )
00407 
00408 
00409 #-----------------------------------------------
00410 class Dimension(_Entity):
00411         """Basic dimension entity"""
00412         def __init__(self,point,start,end,**common):
00413                 _Entity.__init__(self,**common)
00414                 self.points=[point,start,end]
00415         def __str__(self):
00416                 result = '  0\nDIMENSION\n%s' %(self._common())
00417                 result+=' 3\nStandard\n'
00418                 result+=' 70\n1\n'
00419                 result+='%s\n' %_point(self.points[0])
00420                 result+='%s\n' %_point(self.points[1],3)
00421                 result+='%s\n' %_point(self.points[2],4)
00422                 print result
00423                 return result
00424 
00425 #-----------------------------------------------
00426 class Text(_Entity):
00427         """Single text line."""
00428         def __init__(self,text='',point=(0,0,0),alignment=None,
00429                                  flag=None,height=1,justifyhor=None,justifyver=None,
00430                                  rotation=None,obliqueAngle=None,style=None,xscale=None,**common):
00431                 _Entity.__init__(self,**common)
00432                 self.text=text
00433                 self.point=point
00434                 self.alignment=alignment
00435                 self.flag=flag
00436                 self.height=height
00437                 self.justifyhor=justifyhor
00438                 self.justifyver=justifyver
00439                 self.rotation=rotation
00440                 self.obliqueAngle=obliqueAngle
00441                 self.style=style
00442                 self.xscale=xscale
00443         def __str__(self):
00444                 result= '  0\nTEXT\n%s%s\n 40\n%s\n  1\n%s\n'%\
00445                                 (self._common(),_point(self.point),self.height,self.text)
00446                 if self.rotation: result+=' 50\n%s\n'%self.rotation
00447                 if self.xscale: result+=' 41\n%s\n'%self.xscale
00448                 if self.obliqueAngle: result+=' 51\n%s\n'%self.obliqueAngle
00449                 if self.style: result+='  7\n%s\n'%self.style
00450                 if self.flag: result+=' 71\n%s\n'%self.flag
00451                 if self.justifyhor: result+=' 72\n%s\n'%self.justifyhor
00452                 if self.alignment: result+='%s\n'%_point(self.alignment,1)
00453                 if self.justifyver: result+=' 73\n%s\n'%self.justifyver
00454                 return result
00455 
00456 #-----------------------------------------------
00457 class Mtext(Text):
00458         """Surrogate for mtext, generates some Text instances."""
00459         def __init__(self,text='',point=(0,0,0),width=250,spacingFactor=1.5,down=0,spacingWidth=None,**options):
00460                 Text.__init__(self,text=text,point=point,**options)
00461                 if down:spacingFactor*=-1
00462                 self.spacingFactor=spacingFactor
00463                 self.spacingWidth=spacingWidth
00464                 self.width=width
00465                 self.down=down
00466         def __str__(self):
00467                 texts=self.text.replace('\r\n','\n').split('\n')
00468                 if not self.down:texts.reverse()
00469                 result=''
00470                 x=y=0
00471                 if self.spacingWidth:spacingWidth=self.spacingWidth
00472                 else:spacingWidth=self.height*self.spacingFactor
00473                 for text in texts:
00474                         while text:
00475                                 result+='%s\n'%Text(text[:self.width],
00476                                         point=(self.point[0]+x*spacingWidth,
00477                                                    self.point[1]+y*spacingWidth,
00478                                                    self.point[2]),
00479                                         alignment=self.alignment,flag=self.flag,height=self.height,
00480                                         justifyhor=self.justifyhor,justifyver=self.justifyver,
00481                                         rotation=self.rotation,obliqueAngle=self.obliqueAngle,
00482                                         style=self.style,xscale=self.xscale,parent=self
00483                                 )
00484                                 text=text[self.width:]
00485                                 if self.rotation:x+=1
00486                                 else:y+=1
00487                 return result[1:]
00488 
00489 #-----------------------------------------------
00490 ##class _Mtext(_Entity):
00491 ##      """Mtext not functioning for minimal dxf."""
00492 ##      def __init__(self,text='',point=(0,0,0),attachment=1,
00493 ##                               charWidth=None,charHeight=1,direction=1,height=100,rotation=0,
00494 ##                               spacingStyle=None,spacingFactor=None,style=None,width=100,
00495 ##                               xdirection=None,**common):
00496 ##              _Entity.__init__(self,**common)
00497 ##              self.text=text
00498 ##              self.point=point
00499 ##              self.attachment=attachment
00500 ##              self.charWidth=charWidth
00501 ##              self.charHeight=charHeight
00502 ##              self.direction=direction
00503 ##              self.height=height
00504 ##              self.rotation=rotation
00505 ##              self.spacingStyle=spacingStyle
00506 ##              self.spacingFactor=spacingFactor
00507 ##              self.style=style
00508 ##              self.width=width
00509 ##              self.xdirection=xdirection
00510 ##      def __str__(self):
00511 ##              input=self.text
00512 ##              text=''
00513 ##              while len(input)>250:
00514 ##                      text+='3\n%s\n'%input[:250]
00515 ##                      input=input[250:]
00516 ##              text+='1\n%s\n'%input
00517 ##              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'%\
00518 ##                              (self._common(),_point(self.point),self.charHeight,self.width,
00519 ##                               self.attachment,self.direction,text,
00520 ##                               self.height,
00521 ##                               self.rotation)
00522 ##              if self.style:result+='7\n%s\n'%self.style
00523 ##              if self.xdirection:result+='%s\n'%_point(self.xdirection,1)
00524 ##              if self.charWidth:result+='42\n%s\n'%self.charWidth
00525 ##              if self.spacingStyle:result+='73\n%s\n'%self.spacingStyle
00526 ##              if self.spacingFactor:result+='44\n%s\n'%self.spacingFactor
00527 ##              return result
00528 
00529 #---tables ---------------------------------------------------
00530 #-----------------------------------------------
00531 class Block(_Collection):
00532         """Use list methods to add entities, eg append."""
00533         def __init__(self,name,layer='0',flag=0,base=(0,0,0),entities=[]):
00534                 self.entities=copy.copy(entities)
00535                 _Collection.__init__(self,entities)
00536                 self.layer=layer
00537                 self.name=name
00538                 self.flag=0
00539                 self.base=base
00540         def __str__(self): # TODO:
00541                 e=''.join([str(x)for x in self.entities])
00542                 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'%\
00543                            (self.layer,self.name.upper(),self.flag,_point(self.base),self.name.upper(),e)
00544 
00545 #-----------------------------------------------
00546 class Layer(_Call):
00547         """Layer"""
00548         def __init__(self,name='pydxf',color=7,lineType='continuous',flag=64):
00549                 self.name=name
00550                 self.color=color
00551                 self.lineType=lineType
00552                 self.flag=flag
00553         def __str__(self):
00554                 return '  0\nLAYER\n  2\n%s\n 70\n%s\n 62\n%s\n  6\n%s\n'%\
00555                            (self.name.upper(),self.flag,self.color,self.lineType)
00556 
00557 #-----------------------------------------------
00558 class LineType(_Call):
00559         """Custom linetype"""
00560         def __init__(self,name='CONTINUOUS',description='Solid line',elements=[0.0],flag=0):
00561                 self.name=name
00562                 self.description=description
00563                 self.elements=copy.copy(elements)
00564                 self.flag=flag
00565         def __str__(self):
00566                 result = '  0\nLTYPE\n  2\n%s\n 70\n%s\n  3\n%s\n 72\n65\n'%\
00567                         (self.name.upper(),self.flag,self.description)
00568                 if self.elements:
00569                         elements = ' 73\n%s\n' %(len(self.elements)-1)
00570                         elements += ' 40\n%s\n' %(self.elements[0])
00571                         for e in self.elements[1:]:
00572                                 elements += ' 49\n%s\n' %e
00573                         result += elements
00574                 return result
00575                  
00576 
00577 #-----------------------------------------------
00578 class Style(_Call):
00579         """Text style"""
00580         def __init__(self,name='standard',flag=0,height=0,widthFactor=1.0,obliqueAngle=0.0,
00581                                  mirror=0,lastHeight=1,font='arial.ttf',bigFont=''):
00582                 self.name=name
00583                 self.flag=flag
00584                 self.height=height
00585                 self.widthFactor=widthFactor
00586                 self.obliqueAngle=obliqueAngle
00587                 self.mirror=mirror
00588                 self.lastHeight=lastHeight
00589                 self.font=font
00590                 self.bigFont=bigFont
00591         def __str__(self):
00592                 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'%\
00593                            (self.name.upper(),self.flag,self.flag,self.widthFactor,
00594                                 self.obliqueAngle,self.mirror,self.lastHeight,
00595                                 self.font.upper(),self.bigFont.upper())
00596 
00597 #-----------------------------------------------
00598 class VPort(_Call):
00599         def __init__(self,name,flag=0,
00600                                 leftBottom=(0.0,0.0),
00601                                 rightTop=(1.0,1.0),
00602                                 center=(0.5,0.5),
00603                                 snap_base=(0.0,0.0),
00604                                 snap_spacing=(0.1,0.1),
00605                                 grid_spacing=(0.1,0.1),
00606                                 direction=(0.0,0.0,1.0),
00607                                 target=(0.0,0.0,0.0),
00608                                 height=1.0,
00609                                 ratio=1.0,
00610                                 lens=50,
00611                                 frontClipping=0,
00612                                 backClipping=0,
00613                                 snap_rotation=0,
00614                                 twist=0,
00615                                 mode=0,
00616                                 circle_zoom=100,
00617                                 fast_zoom=1,
00618                                 ucsicon=1,
00619                                 snap_on=0,
00620                                 grid_on=0,
00621                                 snap_style=0,
00622                                 snap_isopair=0
00623                                 ):
00624                 self.name=name
00625                 self.flag=flag
00626                 self.leftBottom=leftBottom
00627                 self.rightTop=rightTop
00628                 self.center=center
00629                 self.snap_base=snap_base
00630                 self.snap_spacing=snap_spacing
00631                 self.grid_spacing=grid_spacing
00632                 self.direction=direction
00633                 self.target=target
00634                 self.height=float(height)
00635                 self.ratio=float(ratio)
00636                 self.lens=float(lens)
00637                 self.frontClipping=float(frontClipping)
00638                 self.backClipping=float(backClipping)
00639                 self.snap_rotation=float(snap_rotation)
00640                 self.twist=float(twist)
00641                 self.mode=mode
00642                 self.circle_zoom=circle_zoom
00643                 self.fast_zoom=fast_zoom
00644                 self.ucsicon=ucsicon
00645                 self.snap_on=snap_on
00646                 self.grid_on=grid_on
00647                 self.snap_style=snap_style
00648                 self.snap_isopair=snap_isopair
00649         def __str__(self):
00650                 output = ['  0', 'VPORT',
00651                         '  2', self.name,
00652                         ' 70', self.flag,
00653                         _point(self.leftBottom),
00654                         _point(self.rightTop,1),
00655                         _point(self.center,2), # View center point (in DCS)
00656                         _point(self.snap_base,3),
00657                         _point(self.snap_spacing,4),
00658                         _point(self.grid_spacing,5),
00659                         _point(self.direction,6), #view direction from target (in WCS)
00660                         _point(self.target,7),
00661                         ' 40', self.height,
00662                         ' 41', self.ratio,
00663                         ' 42', self.lens,
00664                         ' 43', self.frontClipping,
00665                         ' 44', self.backClipping,
00666                         ' 50', self.snap_rotation,
00667                         ' 51', self.twist,
00668                         ' 71', self.mode,
00669                         ' 72', self.circle_zoom,
00670                         ' 73', self.fast_zoom,
00671                         ' 74', self.ucsicon,
00672                         ' 75', self.snap_on,
00673                         ' 76', self.grid_on,
00674                         ' 77', self.snap_style,
00675                         ' 78', self.snap_isopair
00676                         ]
00677 
00678                 output_str = ''
00679                 for s in output:
00680                         output_str += '%s\n' %s
00681                 return output_str
00682 
00683 
00684 
00685 #-----------------------------------------------
00686 class View(_Call):
00687         def __init__(self,name,flag=0,
00688                         width=1,
00689                         height=1,
00690                         center=(0.5,0.5),
00691                         direction=(0,0,1),
00692                         target=(0,0,0),
00693                         lens=50,
00694                         frontClipping=0,
00695                         backClipping=0,
00696                         twist=0,mode=0
00697                         ):
00698                 self.name=name
00699                 self.flag=flag
00700                 self.width=float(width)
00701                 self.height=float(height)
00702                 self.center=center
00703                 self.direction=direction
00704                 self.target=target
00705                 self.lens=float(lens)
00706                 self.frontClipping=float(frontClipping)
00707                 self.backClipping=float(backClipping)
00708                 self.twist=float(twist)
00709                 self.mode=mode
00710         def __str__(self):
00711                 output = ['  0', 'VIEW',
00712                         '  2', self.name,
00713                         ' 70', self.flag,
00714                         ' 40', self.height,
00715                         _point(self.center),
00716                         ' 41', self.width,
00717                         _point(self.direction,1),
00718                         _point(self.target,2),
00719                         ' 42', self.lens,
00720                         ' 43', self.frontClipping,
00721                         ' 44', self.backClipping,
00722                         ' 50', self.twist,
00723                         ' 71', self.mode
00724                         ]
00725                 output_str = ''
00726                 for s in output:
00727                         output_str += '%s\n' %s
00728                 return output_str
00729 
00730 #-----------------------------------------------
00731 def ViewByWindow(name,leftBottom=(0,0),rightTop=(1,1),**options):
00732         width=abs(rightTop[0]-leftBottom[0])
00733         height=abs(rightTop[1]-leftBottom[1])
00734         center=((rightTop[0]+leftBottom[0])*0.5,(rightTop[1]+leftBottom[1])*0.5)
00735         return View(name=name,width=width,height=height,center=center,**options)
00736 
00737 #---drawing
00738 #-----------------------------------------------
00739 class Drawing(_Collection):
00740         """Dxf drawing. Use append or any other list methods to add objects."""
00741         def __init__(self,insbase=(0.0,0.0,0.0),extmin=(0.0,0.0,0.0),extmax=(0.0,0.0,0.0),
00742                                  layers=[Layer()],linetypes=[LineType()],styles=[Style()],blocks=[],
00743                                  views=[],vports=[],entities=None,fileName='test.dxf'):
00744                 # TODO: replace list with None,arial
00745                 if not entities:
00746                         entities=[]
00747                 _Collection.__init__(self,entities)
00748                 self.insbase=insbase
00749                 self.extmin=extmin
00750                 self.extmax=extmax
00751                 self.layers=copy.copy(layers)
00752                 self.linetypes=copy.copy(linetypes)
00753                 self.styles=copy.copy(styles)
00754                 self.views=copy.copy(views)
00755                 self.vports=copy.copy(vports)
00756                 self.blocks=copy.copy(blocks)
00757                 self.fileName=fileName
00758                 #private
00759                 #self.acadver='9\n$ACADVER\n1\nAC1006\n'
00760                 self.acadver='  9\n$ACADVER\n  1\nAC1009\n'
00761                 """DXF AutoCAD-Release format codes
00762                 AC1021  2008, 2007 
00763                 AC1018  2006, 2005, 2004 
00764                 AC1015  2002, 2000i, 2000 
00765                 AC1014  R14,14.01 
00766                 AC1012  R13    
00767                 AC1009  R12,11 
00768                 AC1006  R10    
00769                 AC1004  R9    
00770                 AC1002  R2.6  
00771                 AC1.50  R2.05 
00772                 """
00773 
00774         def _name(self,x):
00775                 """Helper function for self._point"""
00776                 return '  9\n$%s\n' %x.upper()
00777 
00778         def _point(self,name,x):
00779                 """Point setting from drawing like extmin,extmax,..."""
00780                 return '%s%s' %(self._name(name),_point(x))
00781 
00782         def _section(self,name,x):
00783                 """Sections like tables,blocks,entities,..."""
00784                 if x: xstr=''.join(x)
00785                 else: xstr=''
00786                 return '  0\nSECTION\n  2\n%s\n%s  0\nENDSEC\n'%(name.upper(),xstr)
00787 
00788         def _table(self,name,x):
00789                 """Tables like ltype,layer,style,..."""
00790                 if x: xstr=''.join(x)
00791                 else: xstr=''
00792                 return '  0\nTABLE\n  2\n%s\n 70\n%s\n%s  0\nENDTAB\n'%(name.upper(),len(x),xstr)
00793 
00794         def __str__(self):
00795                 """Returns drawing as dxf string."""
00796                 header=[self.acadver]+[self._point(attr,getattr(self,attr))+'\n' for attr in _HEADER_POINTS]
00797                 header=self._section('header',header)
00798 
00799                 tables=[self._table('vport',[str(x) for x in self.vports]),
00800                                 self._table('ltype',[str(x) for x in self.linetypes]),
00801                                 self._table('layer',[str(x) for x in self.layers]),
00802                                 self._table('style',[str(x) for x in self.styles]),
00803                                 self._table('view',[str(x) for x in self.views]),
00804                 ]
00805                 tables=self._section('tables',tables)
00806 
00807                 blocks=self._section('blocks',[str(x) for x in self.blocks])
00808 
00809                 entities=self._section('entities',[str(x) for x in self.entities])
00810 
00811                 all=''.join([header,tables,blocks,entities,'  0\nEOF\n'])
00812                 return all
00813 
00814         def saveas(self,fileName):
00815                 self.fileName=fileName
00816                 self.save()
00817 
00818         def save(self):
00819                 test=open(self.fileName,'w')
00820                 test.write(str(self))
00821                 test.close()
00822 
00823 
00824 #---extras
00825 #-----------------------------------------------
00826 class Rectangle(_Entity):
00827         """Rectangle, creates lines."""
00828         def __init__(self,point=(0,0,0),width=1,height=1,solid=None,line=1,**common):
00829                 _Entity.__init__(self,**common)
00830                 self.point=point
00831                 self.width=width
00832                 self.height=height
00833                 self.solid=solid
00834                 self.line=line
00835         def __str__(self):
00836                 result=''
00837                 points=[self.point,(self.point[0]+self.width,self.point[1],self.point[2]),
00838                         (self.point[0]+self.width,self.point[1]+self.height,self.point[2]),
00839                         (self.point[0],self.point[1]+self.height,self.point[2]),self.point]
00840                 if self.solid:
00841                         result+= Solid(points=points[:-1],parent=self.solid)
00842                 if self.line:
00843                         for i in range(4):
00844                                 result+= Line(points=[points[i],points[i+1]],parent=self)
00845                 return result[1:]
00846 
00847 #-----------------------------------------------
00848 class LineList(_Entity):
00849         """Like polyline, but built of individual lines."""
00850         def __init__(self,points=[],org_point=[0,0,0],closed=0,**common):
00851                 _Entity.__init__(self,**common)
00852                 self.closed=closed
00853                 self.points=copy.copy(points)
00854         def __str__(self):
00855                 if self.closed:points=self.points+[self.points[0]]
00856                 else: points=self.points
00857                 result=''
00858                 for i in range(len(points)-1):
00859                         result+= Line(points=[points[i],points[i+1]],parent=self)
00860                 return result[1:]
00861 
00862 #-----------------------------------------------------
00863 def test():
00864         #Blocks
00865         b=Block('test')
00866         b.append(Solid(points=[(0,0,0),(1,0,0),(1,1,0),(0,1,0)],color=1))
00867         b.append(Arc(center=(1,0,0),color=2))
00868 
00869         #Drawing
00870         d=Drawing()
00871         #tables
00872         d.blocks.append(b)  #table blocks
00873         d.styles.append(Style())  #table styles
00874         d.views.append(View('Normal'))  #table view
00875         d.views.append(ViewByWindow('Window',leftBottom=(1,0),rightTop=(2,1)))  #idem
00876 
00877         #entities
00878         d.append(Circle(center=(1,1,0),color=3))
00879         d.append(Face(points=[(0,0,0),(1,0,0),(1,1,0),(0,1,0)],color=4))
00880         d.append(Insert('test',point=(3,3,3),cols=5,colspacing=2))
00881         d.append(Line(points=[(0,0,0),(1,1,1)]))
00882         d.append(Mtext('Click on Ads\nmultiple lines with mtext',point=(1,1,1),color=5,rotation=90))
00883         d.append(Text('Please donate!',point=(3,0,1)))
00884         #d.append(Rectangle(point=(2,2,2),width=4,height=3,color=6,solid=Solid(color=2)))
00885         d.append(Solid(points=[(4,4,0),(5,4,0),(7,8,0),(9,9,0)],color=3))
00886         #d.append(PolyLine(points=[(1,1,1),(2,1,1),(2,2,1),(1,2,1)],flag=1,color=1))
00887 
00888         #d.saveas('c:\\test.dxf')
00889         d.saveas('test.dxf')
00890 
00891 #-----------------------------------------------------
00892 if __name__=='__main__':
00893         if not copy:
00894                 Draw.PupMenu('Error%t|This script requires a full python install')
00895         else: test()
00896         

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