~ubuntu-branches/ubuntu/maverick/blender/maverick

« back to all changes in this revision

Viewing changes to release/scripts/bpymodules/dxfLibrary.py

  • Committer: Bazaar Package Importer
  • Author(s): Khashayar Naderehvandi, Khashayar Naderehvandi, Alessio Treglia
  • Date: 2009-01-22 16:53:59 UTC
  • mfrom: (14.1.1 experimental)
  • Revision ID: james.westby@ubuntu.com-20090122165359-v0996tn7fbit64ni
Tags: 2.48a+dfsg-1ubuntu1
[ Khashayar Naderehvandi ]
* Merge from debian experimental (LP: #320045), Ubuntu remaining changes:
  - Add patch correcting header file locations.
  - Add libvorbis-dev and libgsm1-dev to Build-Depends.
  - Use avcodec_decode_audio2() in source/blender/src/hddaudio.c

[ Alessio Treglia ]
* Add missing previous changelog entries.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#dxfLibrary.py : provides functions for generating DXF files
 
2
# --------------------------------------------------------------------------
 
3
__version__ = "v1.27beta - 2008.10.05"
 
4
__author__  = "Stani Michiels(Stani), Remigiusz Fiedler(migius)"
 
5
__license__ = "GPL"
 
6
__url__  = "http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_dxf"
 
7
__bpydoc__ ="""The script exports geometry data to DXF format r12 version.
 
8
 
 
9
Copyright %s
 
10
Version %s
 
11
License %s
 
12
Homepage %s
 
13
 
 
14
See the homepage for documentation.
 
15
url:
 
16
 
 
17
IDEAs:
 
18
-
 
19
                
 
20
TODO:
 
21
-
 
22
 
 
23
History
 
24
v1.27 - 2008.10.07 by migius
 
25
- beautifying output code: keys whitespace prefix
 
26
- refactoring DXF-strings format: NewLine moved to the end of
 
27
v1.26 - 2008.10.05 by migius
 
28
- modif POLYLINE to support POLYFACE
 
29
v1.25 - 2008.09.28 by migius
 
30
- modif FACE class for r12
 
31
v1.24 - 2008.09.27 by migius
 
32
- modif POLYLINE class for r12
 
33
- changing output format from r9 to r12(AC1009)
 
34
v1.1 (20/6/2005) by www.stani.be/python/sdxf
 
35
- Python library to generate dxf drawings
 
36
______________________________________________________________
 
37
""" % (__author__,__version__,__license__,__url__)
 
38
 
 
39
# --------------------------------------------------------------------------
 
40
# DXF Library: copyright (C) 2005 by Stani Michiels (AKA Stani)
 
41
#                            2008 modif by Remigiusz Fiedler (AKA migius)
 
42
# --------------------------------------------------------------------------
 
43
# ***** BEGIN GPL LICENSE BLOCK *****
 
44
#
 
45
# This program is free software; you can redistribute it and/or
 
46
# modify it under the terms of the GNU General Public License
 
47
# as published by the Free Software Foundation; either version 2
 
48
# of the License, or (at your option) any later version.
 
49
#
 
50
# This program is distributed in the hope that it will be useful,
 
51
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
52
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
53
# GNU General Public License for more details.
 
54
#
 
55
# You should have received a copy of the GNU General Public License
 
56
# along with this program; if not, write to the Free Software Foundation,
 
57
# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
58
#
 
59
# ***** END GPL LICENCE BLOCK *****
 
60
 
 
61
 
 
62
#import Blender
 
63
#from Blender import Mathutils, Window, Scene, sys, Draw
 
64
#import BPyMessages
 
65
 
 
66
try:
 
67
        import copy
 
68
        #from struct import pack
 
69
except:
 
70
        copy = None
 
71
 
 
72
####1) Private (only for developpers)
 
73
_HEADER_POINTS=['insbase','extmin','extmax']
 
74
 
 
75
#---helper functions-----------------------------------
 
76
def _point(x,index=0):
 
77
        """Convert tuple to a dxf point"""
 
78
        #print 'deb: _point=', x #-------------
 
79
        return '\n'.join([' %s\n%s'%((i+1)*10+index,x[i]) for i in range(len(x))])
 
80
 
 
81
def _points(plist):
 
82
        """Convert a list of tuples to dxf points"""
 
83
        out = '\n'.join([_point(plist[i],i)for i in range(len(plist))])
 
84
        #print 'deb: points=\n', out #-------------------
 
85
        return out
 
86
 
 
87
#---base classes----------------------------------------
 
88
class _Call:
 
89
        """Makes a callable class."""
 
90
        def copy(self):
 
91
                """Returns a copy."""
 
92
                return copy.deepcopy(self)
 
93
 
 
94
        def __call__(self,**attrs):
 
95
                """Returns a copy with modified attributes."""
 
96
                copied=self.copy()
 
97
                for attr in attrs:setattr(copied,attr,attrs[attr])
 
98
                return copied
 
99
 
 
100
#-------------------------------------------------------
 
101
class _Entity(_Call):
 
102
        """Base class for _common group codes for entities."""
 
103
        def __init__(self,color=None,extrusion=None,layer='0',
 
104
                                 lineType=None,lineTypeScale=None,lineWeight=None,
 
105
                                 thickness=None,parent=None):
 
106
                """None values will be omitted."""
 
107
                self.color                = color
 
108
                self.extrusion    = extrusion
 
109
                self.layer                = layer
 
110
                self.lineType      = lineType
 
111
                self.lineTypeScale  = lineTypeScale
 
112
                self.lineWeight  = lineWeight
 
113
                self.thickness    = thickness
 
114
                self.parent              = parent
 
115
 
 
116
        def _common(self):
 
117
                """Return common group codes as a string."""
 
118
                if self.parent:parent=self.parent
 
119
                else:parent=self
 
120
                result =''
 
121
                if parent.layer!=None: result+='  8\n%s\n'%parent.layer
 
122
                if parent.color!=None: result+=' 62\n%s\n'%parent.color
 
123
                if parent.extrusion!=None: result+='%s\n'%_point(parent.extrusion,200)
 
124
                if parent.lineType!=None: result+='  6\n%s\n'%parent.lineType
 
125
                #TODO: if parent.lineWeight!=None: result+='370\n%s\n'%parent.lineWeight
 
126
                if parent.lineTypeScale!=None: result+=' 48\n%s\n'%parent.lineTypeScale
 
127
                if parent.thickness!=None: result+=' 39\n%s\n'%parent.thickness
 
128
                return result
 
129
 
 
130
#--------------------------
 
131
class _Entities:
 
132
        """Base class to deal with composed objects."""
 
133
        def __dxf__(self):
 
134
                return []
 
135
 
 
136
        def __str__(self):
 
137
                return ''.join([str(x) for x in self.__dxf__()])
 
138
 
 
139
#--------------------------
 
140
class _Collection(_Call):
 
141
        """Base class to expose entities methods to main object."""
 
142
        def __init__(self,entities=[]):
 
143
                self.entities=copy.copy(entities)
 
144
                #link entities methods to drawing
 
145
                for attr in dir(self.entities):
 
146
                        if attr[0]!='_':
 
147
                                attrObject=getattr(self.entities,attr)
 
148
                                if callable(attrObject):
 
149
                                        setattr(self,attr,attrObject)
 
150
 
 
151
####2) Constants
 
152
#---color values
 
153
BYBLOCK=0
 
154
BYLAYER=256
 
155
 
 
156
#---block-type flags (bit coded values, may be combined):
 
157
ANONYMOUS                          =1  # This is an anonymous block generated by hatching, associative dimensioning, other internal operations, or an application
 
158
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)
 
159
XREF                                    =4  # This block is an external reference (xref)
 
160
XREF_OVERLAY                    =8  # This block is an xref overlay
 
161
EXTERNAL                                =16 # This block is externally dependent
 
162
RESOLVED                                =32 # This is a resolved external reference, or dependent of an external reference (ignored on input)
 
163
REFERENCED                        =64 # This definition is a referenced external reference (ignored on input)
 
164
 
 
165
#---mtext flags
 
166
#attachment point
 
167
TOP_LEFT                = 1
 
168
TOP_CENTER        = 2
 
169
TOP_RIGHT          = 3
 
170
MIDDLE_LEFT      = 4
 
171
MIDDLE_CENTER   = 5
 
172
MIDDLE_RIGHT    = 6
 
173
BOTTOM_LEFT      = 7
 
174
BOTTOM_CENTER   = 8
 
175
BOTTOM_RIGHT    = 9
 
176
#drawing direction
 
177
LEFT_RIGHT        = 1
 
178
TOP_BOTTOM        = 3
 
179
BY_STYLE                = 5 #the flow direction is inherited from the associated text style
 
180
#line spacing style (optional):
 
181
AT_LEAST                = 1 #taller characters will override
 
182
EXACT              = 2 #taller characters will not override
 
183
 
 
184
#---polyline flags
 
185
CLOSED                                    =1      # This is a closed polyline (or a polygon mesh closed in the M direction)
 
186
CURVE_FIT                                  =2     # Curve-fit vertices have been added
 
187
SPLINE_FIT                                =4      # Spline-fit vertices have been added
 
188
POLYLINE_3D                              =8       # This is a 3D polyline
 
189
POLYGON_MESH                            =16      # This is a 3D polygon mesh
 
190
CLOSED_N                                        =32      # The polygon mesh is closed in the N direction
 
191
POLYFACE_MESH                      =64   # The polyline is a polyface mesh
 
192
CONTINOUS_LINETYPE_PATTERN  =128        # The linetype pattern is generated continuously around the vertices of this polyline
 
193
 
 
194
#---text flags
 
195
#horizontal
 
196
LEFT            = 0
 
197
CENTER    = 1
 
198
RIGHT      = 2
 
199
ALIGNED  = 3 #if vertical alignment = 0
 
200
MIDDLE    = 4 #if vertical alignment = 0
 
201
FIT              = 5 #if vertical alignment = 0
 
202
#vertical
 
203
BASELINE        = 0
 
204
BOTTOM    = 1
 
205
MIDDLE    = 2
 
206
TOP              = 3
 
207
 
 
208
####3) Classes
 
209
#---entitities -----------------------------------------------
 
210
#--------------------------
 
211
class Arc(_Entity):
 
212
        """Arc, angles in degrees."""
 
213
        def __init__(self,center=(0,0,0),radius=1,
 
214
                                 startAngle=0.0,endAngle=90,**common):
 
215
                """Angles in degrees."""
 
216
                _Entity.__init__(self,**common)
 
217
                self.center=center
 
218
                self.radius=radius
 
219
                self.startAngle=startAngle
 
220
                self.endAngle=endAngle
 
221
        def __str__(self):
 
222
                return '  0\nARC\n%s%s\n 40\n%s\n 50\n%s\n 51\n%s\n'%\
 
223
                           (self._common(),_point(self.center),
 
224
                                self.radius,self.startAngle,self.endAngle)
 
225
 
 
226
#-----------------------------------------------
 
227
class Circle(_Entity):
 
228
        """Circle"""
 
229
        def __init__(self,center=(0,0,0),radius=1,**common):
 
230
                _Entity.__init__(self,**common)
 
231
                self.center=center
 
232
                self.radius=radius
 
233
        def __str__(self):
 
234
                return '  0\nCIRCLE\n%s%s\n 40\n%s\n'%\
 
235
                           (self._common(),_point(self.center),self.radius)
 
236
 
 
237
#-----------------------------------------------
 
238
class Face(_Entity):
 
239
        """3dface"""
 
240
        def __init__(self,points,**common):
 
241
                _Entity.__init__(self,**common)
 
242
                if len(points)<4: #fix for r12 format
 
243
                        points.append(points[-1])
 
244
                self.points=points
 
245
                
 
246
        def __str__(self):
 
247
                out = '  0\n3DFACE\n%s%s\n' %(self._common(),_points(self.points))
 
248
                #print 'deb:out=', out #-------------------
 
249
                return out
 
250
 
 
251
#-----------------------------------------------
 
252
class Insert(_Entity):
 
253
        """Block instance."""
 
254
        def __init__(self,name,point=(0,0,0),
 
255
                                 xscale=None,yscale=None,zscale=None,
 
256
                                 cols=None,colspacing=None,rows=None,rowspacing=None,
 
257
                                 rotation=None,
 
258
                                 **common):
 
259
                _Entity.__init__(self,**common)
 
260
                self.name=name
 
261
                self.point=point
 
262
                self.xscale=xscale
 
263
                self.yscale=yscale
 
264
                self.zscale=zscale
 
265
                self.cols=cols
 
266
                self.colspacing=colspacing
 
267
                self.rows=rows
 
268
                self.rowspacing=rowspacing
 
269
                self.rotation=rotation
 
270
 
 
271
        def __str__(self):
 
272
                result='  0\nINSERT\n  2\n%s\n%s\n%s\n'%\
 
273
                                (self.name,self._common(),_point(self.point))
 
274
                if self.xscale!=None:result+=' 41\n%s\n'%self.xscale
 
275
                if self.yscale!=None:result+=' 42\n%s\n'%self.yscale
 
276
                if self.zscale!=None:result+=' 43\n%s\n'%self.zscale
 
277
                if self.rotation:result+=' 50\n%s\n'%self.rotation
 
278
                if self.cols!=None:result+=' 70\n%s\n'%self.cols
 
279
                if self.colspacing!=None:result+=' 44\n%s\n'%self.colspacing
 
280
                if self.rows!=None:result+=' 71\n%s\n'%self.rows
 
281
                if self.rowspacing!=None:result+=' 45\n%s\n'%self.rowspacing
 
282
                return result
 
283
 
 
284
#-----------------------------------------------
 
285
class Line(_Entity):
 
286
        """Line"""
 
287
        def __init__(self,points,**common):
 
288
                _Entity.__init__(self,**common)
 
289
                self.points=points
 
290
        def __str__(self):
 
291
                return '  0\nLINE\n%s%s\n' %(
 
292
                                self._common(), _points(self.points))
 
293
 
 
294
 
 
295
#-----------------------------------------------
 
296
class PolyLine(_Entity):
 
297
        def __init__(self,points,org_point=[0,0,0],flag=0,width=None,**common):
 
298
                _Entity.__init__(self,**common)
 
299
                self.points=points
 
300
                self.org_point=org_point
 
301
                self.flag=flag
 
302
                if self.flag==64:
 
303
                        self.points=points[0]
 
304
                        self.faces=points[1]
 
305
                        self.p_count=len(self.points)
 
306
                        self.f_count=len(self.faces)
 
307
                self.width=width
 
308
 
 
309
        def __str__(self):
 
310
                result= '  0\nPOLYLINE\n%s 70\n%s\n' %(self._common(),self.flag)
 
311
                #print 'deb: self._common()', self._common() #----------
 
312
                result+=' 66\n1\n'
 
313
                result+='%s\n' %_point(self.org_point)
 
314
                if self.flag==64:
 
315
                        result+=' 71\n%s\n' %self.p_count
 
316
                        result+=' 72\n%s\n' %self.f_count
 
317
                for point in self.points:
 
318
                        result+='  0\nVERTEX\n'
 
319
                        result+='  8\n%s\n' %self.layer
 
320
                        result+='%s\n' %_point(point)
 
321
                        if self.flag==64: result+=' 70\n192\n'
 
322
                        if self.width: result+=' 40\n%s\n 41\n%s\n' %(self.width,self.width)
 
323
                if self.flag==64:
 
324
                        for face in self.faces:
 
325
                                result+='  0\nVERTEX\n'
 
326
                                result+='  8\n%s\n' %self.layer
 
327
                                result+='%s\n' %_point(self.org_point)
 
328
                                result+=' 70\n128\n'
 
329
                                result+=' 71\n%s\n' %face[0]
 
330
                                result+=' 72\n%s\n' %face[1]
 
331
                                result+=' 73\n%s\n' %face[2]
 
332
                                if len(face)==4: result+=' 74\n%s\n' %face[3]
 
333
                result+='  0\nSEQEND\n'
 
334
                result+='  8\n%s\n' %self.layer
 
335
                return result
 
336
 
 
337
#-----------------------------------------------
 
338
class Point(_Entity):
 
339
        """Colored solid fill."""
 
340
        def __init__(self,points=None,**common):
 
341
                _Entity.__init__(self,**common)
 
342
                self.points=points
 
343
 
 
344
#-----------------------------------------------
 
345
class Solid(_Entity):
 
346
        """Colored solid fill."""
 
347
        def __init__(self,points=None,**common):
 
348
                _Entity.__init__(self,**common)
 
349
                self.points=points
 
350
        def __str__(self):
 
351
                return '  0\nSOLID\n%s%s\n' %(self._common(),
 
352
                         _points(self.points[:2]+[self.points[3],self.points[2]])
 
353
                        )
 
354
 
 
355
 
 
356
#-----------------------------------------------
 
357
class Text(_Entity):
 
358
        """Single text line."""
 
359
        def __init__(self,text='',point=(0,0,0),alignment=None,
 
360
                                 flag=None,height=1,justifyhor=None,justifyver=None,
 
361
                                 rotation=None,obliqueAngle=None,style=None,xscale=None,**common):
 
362
                _Entity.__init__(self,**common)
 
363
                self.text=text
 
364
                self.point=point
 
365
                self.alignment=alignment
 
366
                self.flag=flag
 
367
                self.height=height
 
368
                self.justifyhor=justifyhor
 
369
                self.justifyver=justifyver
 
370
                self.rotation=rotation
 
371
                self.obliqueAngle=obliqueAngle
 
372
                self.style=style
 
373
                self.xscale=xscale
 
374
        def __str__(self):
 
375
                result= '  0\nTEXT\n%s%s\n 40\n%s\n  1\n%s\n'%\
 
376
                                (self._common(),_point(self.point),self.height,self.text)
 
377
                if self.rotation: result+=' 50\n%s\n'%self.rotation
 
378
                if self.xscale: result+=' 41\n%s\n'%self.xscale
 
379
                if self.obliqueAngle: result+=' 51\n%s\n'%self.obliqueAngle
 
380
                if self.style: result+='  7\n%s\n'%self.style
 
381
                if self.flag: result+=' 71\n%s\n'%self.flag
 
382
                if self.justifyhor: result+=' 72\n%s\n'%self.justifyhor
 
383
                #TODO: if self.alignment: result+='%s\n'%_point(self.alignment,1)
 
384
                if self.justifyver: result+=' 73\n%s\n'%self.justifyver
 
385
                return result
 
386
 
 
387
#-----------------------------------------------
 
388
class Mtext(Text):
 
389
        """Surrogate for mtext, generates some Text instances."""
 
390
        def __init__(self,text='',point=(0,0,0),width=250,spacingFactor=1.5,down=0,spacingWidth=None,**options):
 
391
                Text.__init__(self,text=text,point=point,**options)
 
392
                if down:spacingFactor*=-1
 
393
                self.spacingFactor=spacingFactor
 
394
                self.spacingWidth=spacingWidth
 
395
                self.width=width
 
396
                self.down=down
 
397
        def __str__(self):
 
398
                texts=self.text.replace('\r\n','\n').split('\n')
 
399
                if not self.down:texts.reverse()
 
400
                result=''
 
401
                x=y=0
 
402
                if self.spacingWidth:spacingWidth=self.spacingWidth
 
403
                else:spacingWidth=self.height*self.spacingFactor
 
404
                for text in texts:
 
405
                        while text:
 
406
                                result+='%s\n'%Text(text[:self.width],
 
407
                                        point=(self.point[0]+x*spacingWidth,
 
408
                                                   self.point[1]+y*spacingWidth,
 
409
                                                   self.point[2]),
 
410
                                        alignment=self.alignment,flag=self.flag,height=self.height,
 
411
                                        justifyhor=self.justifyhor,justifyver=self.justifyver,
 
412
                                        rotation=self.rotation,obliqueAngle=self.obliqueAngle,
 
413
                                        style=self.style,xscale=self.xscale,parent=self
 
414
                                )
 
415
                                text=text[self.width:]
 
416
                                if self.rotation:x+=1
 
417
                                else:y+=1
 
418
                return result[1:]
 
419
 
 
420
#-----------------------------------------------
 
421
##class _Mtext(_Entity):
 
422
##      """Mtext not functioning for minimal dxf."""
 
423
##      def __init__(self,text='',point=(0,0,0),attachment=1,
 
424
##                               charWidth=None,charHeight=1,direction=1,height=100,rotation=0,
 
425
##                               spacingStyle=None,spacingFactor=None,style=None,width=100,
 
426
##                               xdirection=None,**common):
 
427
##              _Entity.__init__(self,**common)
 
428
##              self.text=text
 
429
##              self.point=point
 
430
##              self.attachment=attachment
 
431
##              self.charWidth=charWidth
 
432
##              self.charHeight=charHeight
 
433
##              self.direction=direction
 
434
##              self.height=height
 
435
##              self.rotation=rotation
 
436
##              self.spacingStyle=spacingStyle
 
437
##              self.spacingFactor=spacingFactor
 
438
##              self.style=style
 
439
##              self.width=width
 
440
##              self.xdirection=xdirection
 
441
##      def __str__(self):
 
442
##              input=self.text
 
443
##              text=''
 
444
##              while len(input)>250:
 
445
##                      text+='3\n%s\n'%input[:250]
 
446
##                      input=input[250:]
 
447
##              text+='1\n%s\n'%input
 
448
##              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'%\
 
449
##                              (self._common(),_point(self.point),self.charHeight,self.width,
 
450
##                               self.attachment,self.direction,text,
 
451
##                               self.height,
 
452
##                               self.rotation)
 
453
##              if self.style:result+='7\n%s\n'%self.style
 
454
##              if self.xdirection:result+='%s\n'%_point(self.xdirection,1)
 
455
##              if self.charWidth:result+='42\n%s\n'%self.charWidth
 
456
##              if self.spacingStyle:result+='73\n%s\n'%self.spacingStyle
 
457
##              if self.spacingFactor:result+='44\n%s\n'%self.spacingFactor
 
458
##              return result
 
459
 
 
460
#---tables ---------------------------------------------------
 
461
#-----------------------------------------------
 
462
class Block(_Collection):
 
463
        """Use list methods to add entities, eg append."""
 
464
        def __init__(self,name,layer='0',flag=0,base=(0,0,0),entities=[]):
 
465
                self.entities=copy.copy(entities)
 
466
                _Collection.__init__(self,entities)
 
467
                self.layer=layer
 
468
                self.name=name
 
469
                self.flag=0
 
470
                self.base=base
 
471
        def __str__(self):
 
472
                e=''.join([str(x)for x in self.entities])
 
473
                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'%\
 
474
                           (self.layer,self.name.upper(),self.flag,_point(self.base),self.name.upper(),e)
 
475
 
 
476
#-----------------------------------------------
 
477
class Layer(_Call):
 
478
        """Layer"""
 
479
        def __init__(self,name='pydxf',color=7,lineType='continuous',flag=64):
 
480
                self.name=name
 
481
                self.color=color
 
482
                self.lineType=lineType
 
483
                self.flag=flag
 
484
        def __str__(self):
 
485
                return '  0\nLAYER\n  2\n%s\n 70\n%s\n 62\n%s\n  6\n%s\n'%\
 
486
                           (self.name.upper(),self.flag,self.color,self.lineType)
 
487
 
 
488
#-----------------------------------------------
 
489
class LineType(_Call):
 
490
        """Custom linetype"""
 
491
        def __init__(self,name='continuous',description='Solid line',elements=[],flag=64):
 
492
                # TODO: Implement lineType elements
 
493
                self.name=name
 
494
                self.description=description
 
495
                self.elements=copy.copy(elements)
 
496
                self.flag=flag
 
497
        def __str__(self):
 
498
                return '  0\nLTYPE\n  2\n%s\n 70\n%s\n  3\n%s\n 72\n65\n 73\n%s\n 40\n0.0\n'%\
 
499
                        (self.name.upper(),self.flag,self.description,len(self.elements))
 
500
 
 
501
#-----------------------------------------------
 
502
class Style(_Call):
 
503
        """Text style"""
 
504
        def __init__(self,name='standard',flag=0,height=0,widthFactor=40,obliqueAngle=50,
 
505
                                 mirror=0,lastHeight=1,font='arial.ttf',bigFont=''):
 
506
                self.name=name
 
507
                self.flag=flag
 
508
                self.height=height
 
509
                self.widthFactor=widthFactor
 
510
                self.obliqueAngle=obliqueAngle
 
511
                self.mirror=mirror
 
512
                self.lastHeight=lastHeight
 
513
                self.font=font
 
514
                self.bigFont=bigFont
 
515
        def __str__(self):
 
516
                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'%\
 
517
                           (self.name.upper(),self.flag,self.flag,self.widthFactor,
 
518
                                self.obliqueAngle,self.mirror,self.lastHeight,
 
519
                                self.font.upper(),self.bigFont.upper())
 
520
 
 
521
#-----------------------------------------------
 
522
class View(_Call):
 
523
        def __init__(self,name,flag=0,width=1,height=1,center=(0.5,0.5),
 
524
                                 direction=(0,0,1),target=(0,0,0),lens=50,
 
525
                                 frontClipping=0,backClipping=0,twist=0,mode=0):
 
526
                self.name=name
 
527
                self.flag=flag
 
528
                self.width=width
 
529
                self.height=height
 
530
                self.center=center
 
531
                self.direction=direction
 
532
                self.target=target
 
533
                self.lens=lens
 
534
                self.frontClipping=frontClipping
 
535
                self.backClipping=backClipping
 
536
                self.twist=twist
 
537
                self.mode=mode
 
538
        def __str__(self):
 
539
                return '  0\nVIEW\n  2\n%s\n 70\n%s\n 40\n%s\n%s\n 41\n%s\n%s\n%s\n 42\n%s\n 43\n%s\n 44\n%s\n 50\n%s\n 71\n%s\n'%\
 
540
                           (self.name,self.flag,self.height,_point(self.center),self.width,
 
541
                                _point(self.direction,1),_point(self.target,2),self.lens,
 
542
                                self.frontClipping,self.backClipping,self.twist,self.mode)
 
543
 
 
544
#-----------------------------------------------
 
545
def ViewByWindow(name,leftBottom=(0,0),rightTop=(1,1),**options):
 
546
        width=abs(rightTop[0]-leftBottom[0])
 
547
        height=abs(rightTop[1]-leftBottom[1])
 
548
        center=((rightTop[0]+leftBottom[0])*0.5,(rightTop[1]+leftBottom[1])*0.5)
 
549
        return View(name=name,width=width,height=height,center=center,**options)
 
550
 
 
551
#---drawing
 
552
#-----------------------------------------------
 
553
class Drawing(_Collection):
 
554
        """Dxf drawing. Use append or any other list methods to add objects."""
 
555
        def __init__(self,insbase=(0.0,0.0,0.0),extmin=(0.0,0.0),extmax=(0.0,0.0),
 
556
                                 layers=[Layer()],linetypes=[LineType()],styles=[Style()],blocks=[],
 
557
                                 views=[],entities=None,fileName='test.dxf'):
 
558
                # TODO: replace list with None,arial
 
559
                if not entities:entities=[]
 
560
                _Collection.__init__(self,entities)
 
561
                self.insbase=insbase
 
562
                self.extmin=extmin
 
563
                self.extmax=extmax
 
564
                self.layers=copy.copy(layers)
 
565
                self.linetypes=copy.copy(linetypes)
 
566
                self.styles=copy.copy(styles)
 
567
                self.views=copy.copy(views)
 
568
                self.blocks=copy.copy(blocks)
 
569
                self.fileName=fileName
 
570
                #private
 
571
                #self.acadver='9\n$ACADVER\n1\nAC1006\n'
 
572
                self.acadver='  9\n$ACADVER\n  1\nAC1009\n'
 
573
                """DXF AutoCAD-Release format codes
 
574
                AC1021  2008, 2007 
 
575
                AC1018  2006, 2005, 2004 
 
576
                AC1015  2002, 2000i, 2000 
 
577
                AC1014  R14,14.01 
 
578
                AC1012  R13    
 
579
                AC1009  R12,11 
 
580
                AC1006  R10    
 
581
                AC1004  R9    
 
582
                AC1002  R2.6  
 
583
                AC1.50  R2.05 
 
584
                """
 
585
 
 
586
        def _name(self,x):
 
587
                """Helper function for self._point"""
 
588
                return '  9\n$%s\n' %x.upper()
 
589
 
 
590
        def _point(self,name,x):
 
591
                """Point setting from drawing like extmin,extmax,..."""
 
592
                return '%s%s' %(self._name(name),_point(x))
 
593
 
 
594
        def _section(self,name,x):
 
595
                """Sections like tables,blocks,entities,..."""
 
596
                if x: xstr=''.join(x)
 
597
                else: xstr=''
 
598
                return '  0\nSECTION\n  2\n%s\n%s  0\nENDSEC\n'%(name.upper(),xstr)
 
599
 
 
600
        def _table(self,name,x):
 
601
                """Tables like ltype,layer,style,..."""
 
602
                if x: xstr=''.join(x)
 
603
                else: xstr=''
 
604
                return '  0\nTABLE\n  2\n%s\n 70\n%s\n%s  0\nENDTAB\n'%(name.upper(),len(x),xstr)
 
605
 
 
606
        def __str__(self):
 
607
                """Returns drawing as dxf string."""
 
608
                header=[self.acadver]+[self._point(attr,getattr(self,attr))+'\n' for attr in _HEADER_POINTS]
 
609
                header=self._section('header',header)
 
610
 
 
611
                tables=[self._table('ltype',[str(x) for x in self.linetypes]),
 
612
                                self._table('layer',[str(x) for x in self.layers]),
 
613
                                self._table('style',[str(x) for x in self.styles]),
 
614
                                self._table('view',[str(x) for x in self.views]),
 
615
                ]
 
616
                tables=self._section('tables',tables)
 
617
 
 
618
                blocks=self._section('blocks',[str(x) for x in self.blocks])
 
619
 
 
620
                entities=self._section('entities',[str(x) for x in self.entities])
 
621
 
 
622
                all=''.join([header,tables,blocks,entities,'  0\nEOF\n'])
 
623
                return all
 
624
 
 
625
        def saveas(self,fileName):
 
626
                self.fileName=fileName
 
627
                self.save()
 
628
 
 
629
        def save(self):
 
630
                test=open(self.fileName,'w')
 
631
                test.write(str(self))
 
632
                test.close()
 
633
 
 
634
 
 
635
#---extras
 
636
#-----------------------------------------------
 
637
class Rectangle(_Entity):
 
638
        """Rectangle, creates lines."""
 
639
        def __init__(self,point=(0,0,0),width=1,height=1,solid=None,line=1,**common):
 
640
                _Entity.__init__(self,**common)
 
641
                self.point=point
 
642
                self.width=width
 
643
                self.height=height
 
644
                self.solid=solid
 
645
                self.line=line
 
646
        def __str__(self):
 
647
                result=''
 
648
                points=[self.point,(self.point[0]+self.width,self.point[1],self.point[2]),
 
649
                        (self.point[0]+self.width,self.point[1]+self.height,self.point[2]),
 
650
                        (self.point[0],self.point[1]+self.height,self.point[2]),self.point]
 
651
                if self.solid:
 
652
                        result+= Solid(points=points[:-1],parent=self.solid)
 
653
                if self.line:
 
654
                        for i in range(4):
 
655
                                result+= Line(points=[points[i],points[i+1]],parent=self)
 
656
                return result[1:]
 
657
 
 
658
#-----------------------------------------------
 
659
class LineList(_Entity):
 
660
        """Like polyline, but built of individual lines."""
 
661
        def __init__(self,points=[],org_point=[0,0,0],closed=0,**common):
 
662
                _Entity.__init__(self,**common)
 
663
                self.closed=closed
 
664
                self.points=copy.copy(points)
 
665
        def __str__(self):
 
666
                if self.closed:points=self.points+[self.points[0]]
 
667
                else: points=self.points
 
668
                result=''
 
669
                for i in range(len(points)-1):
 
670
                        result+= Line(points=[points[i],points[i+1]],parent=self)
 
671
                return result[1:]
 
672
 
 
673
#-----------------------------------------------------
 
674
def test():
 
675
        #Blocks
 
676
        b=Block('test')
 
677
        b.append(Solid(points=[(0,0,0),(1,0,0),(1,1,0),(0,1,0)],color=1))
 
678
        b.append(Arc(center=(1,0,0),color=2))
 
679
 
 
680
        #Drawing
 
681
        d=Drawing()
 
682
        #tables
 
683
        d.blocks.append(b)                                        #table blocks
 
684
        d.styles.append(Style())                                #table styles
 
685
        d.views.append(View('Normal'))            #table view
 
686
        d.views.append(ViewByWindow('Window',leftBottom=(1,0),rightTop=(2,1)))  #idem
 
687
 
 
688
        #entities
 
689
        d.append(Circle(center=(1,1,0),color=3))
 
690
        d.append(Face(points=[(0,0,0),(1,0,0),(1,1,0),(0,1,0)],color=4))
 
691
        d.append(Insert('test',point=(3,3,3),cols=5,colspacing=2))
 
692
        d.append(Line(points=[(0,0,0),(1,1,1)]))
 
693
        d.append(Mtext('Click on Ads\nmultiple lines with mtext',point=(1,1,1),color=5,rotation=90))
 
694
        d.append(Text('Please donate!',point=(3,0,1)))
 
695
        d.append(Rectangle(point=(2,2,2),width=4,height=3,color=6,solid=Solid(color=2)))
 
696
        d.append(Solid(points=[(4,4,0),(5,4,0),(7,8,0),(9,9,0)],color=3))
 
697
        d.append(PolyLine(points=[(1,1,1),(2,1,1),(2,2,1),(1,2,1)],closed=1,color=1))
 
698
 
 
699
        #d.saveas('c:\\test.dxf')
 
700
        d.saveas('test.dxf')
 
701
 
 
702
 
 
703
#-----------------------------------------------------
 
704
if __name__=='__main__':
 
705
        if not copy:
 
706
                Draw.PupMenu('Error%t|This script requires a full python install')
 
707
        main()
 
708
        
 
 
b'\\ No newline at end of file'