1
#dxfLibrary.py : provides functions for generating DXF files
2
# --------------------------------------------------------------------------
3
__version__ = "v1.35 - 2010.06.23"
4
__author__ = "Stani Michiels(Stani), Remigiusz Fiedler(migius)"
6
__url__ = "http://wiki.blender.org/index.php/Extensions:2.4/Py/Scripts/Export/DXF"
7
__bpydoc__ ="""The library to export geometry data to DXF format r12 version.
14
See the homepage for documentation.
15
Dedicated thread on BlenderArtists: http://blenderartists.org/forum/showthread.php?t=136439
21
- add support for DXFr14 version (needs extended file header)
22
- add support for DXF-SPLINEs (possible first in DXFr14 version)
23
- add support for DXF-MTEXT
24
- add user preset for floating point precision (3-16?)
27
v1.35 - 2010.06.23 by migius
28
- added (as default) writing to DXF file without RAM-buffering: faster and low-RAM-machines friendly
29
v1.34 - 2010.06.20 by migius
31
- added DXF-flags for POLYLINE and VERTEX class (NURBS-export)
32
v1.33 - 2009.07.03 by migius
33
- fix MTEXT newline bug (not supported by DXF-Exporter yet)
34
- modif _point(): converts all coords to floats
35
- modif LineType class: implement elements
36
- added VPORT class, incl. defaults
38
v1.32 - 2009.06.06 by migius
39
- modif Style class: changed defaults to widthFactor=1.0, obliqueAngle=0.0
40
- modif Text class: alignment parameter reactivated
41
v1.31 - 2009.06.02 by migius
42
- modif _Entity class: added paperspace,elevation
43
v1.30 - 2009.05.28 by migius
44
- bugfix 3dPOLYLINE/POLYFACE: VERTEX needs x,y,z coordinates, index starts with 1 not 0
45
v1.29 - 2008.12.28 by Yorik
46
- modif POLYLINE to support bulge segments
47
v1.28 - 2008.12.13 by Steeve/BlenderArtists
48
- bugfix for EXTMIN/EXTMAX to suit Cycas-CAD
49
v1.27 - 2008.10.07 by migius
50
- beautifying output code: keys whitespace prefix
51
- refactoring DXF-strings format: NewLine moved to the end of
52
v1.26 - 2008.10.05 by migius
53
- modif POLYLINE to support POLYFACE
54
v1.25 - 2008.09.28 by migius
55
- modif FACE class for r12
56
v1.24 - 2008.09.27 by migius
57
- modif POLYLINE class for r12
58
- changing output format from r9 to r12(AC1009)
59
v1.1 (20/6/2005) by www.stani.be/python/sdxf
60
- Python library to generate dxf drawings
61
______________________________________________________________
62
""" % (__author__,__version__,__license__,__url__)
64
# --------------------------------------------------------------------------
65
# DXF Library: copyright (C) 2005 by Stani Michiels (AKA Stani)
66
# 2008/2009 modif by Remigiusz Fiedler (AKA migius)
67
# --------------------------------------------------------------------------
68
# ***** BEGIN GPL LICENSE BLOCK *****
70
# This program is free software; you can redistribute it and/or
71
# modify it under the terms of the GNU General Public License
72
# as published by the Free Software Foundation; either version 2
73
# of the License, or (at your option) any later version.
75
# This program is distributed in the hope that it will be useful,
76
# but WITHOUT ANY WARRANTY; without even the implied warranty of
77
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
78
# GNU General Public License for more details.
80
# You should have received a copy of the GNU General Public License
81
# along with this program; if not, write to the Free Software Foundation,
82
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
84
# ***** END GPL LICENCE BLOCK *****
88
#from Blender import Mathutils, Window, Scene, sys, Draw
93
#from struct import pack
97
####1) Private (only for developpers)
98
_HEADER_POINTS=['insbase','extmin','extmax']
100
#---helper functions-----------------------------------
101
def _point(x,index=0):
102
"""Convert tuple to a dxf point"""
103
return '\n'.join([' %s\n%s'%((i+1)*10+index,float(x[i])) for i in range(len(x))])
106
"""Convert a list of tuples to dxf points"""
107
out = '\n'.join([_point(plist[i],i)for i in range(len(plist))])
110
#---base classes----------------------------------------
112
"""Makes a callable class."""
114
"""Returns a copy."""
115
return copy.deepcopy(self)
117
def __call__(self,**attrs):
118
"""Returns a copy with modified attributes."""
120
for attr in attrs:setattr(copied,attr,attrs[attr])
123
#-------------------------------------------------------
124
class _Entity(_Call):
125
"""Base class for _common group codes for entities."""
126
def __init__(self,paperspace=None,color=None,layer='0',
127
lineType=None,lineTypeScale=None,lineWeight=None,
128
extrusion=None,elevation=None,thickness=None,
130
"""None values will be omitted."""
131
self.paperspace = paperspace
134
self.lineType = lineType
135
self.lineTypeScale = lineTypeScale
136
self.lineWeight = lineWeight
137
self.extrusion = extrusion
138
self.elevation = elevation
139
self.thickness = thickness
140
#self.visible = visible
144
"""Return common group codes as a string."""
145
if self.parent:parent=self.parent
148
if parent.paperspace==1: result+=' 67\n1\n'
149
if parent.layer!=None: result+=' 8\n%s\n'%parent.layer
150
if parent.color!=None: result+=' 62\n%s\n'%parent.color
151
if parent.lineType!=None: result+=' 6\n%s\n'%parent.lineType
152
# TODO: if parent.lineWeight!=None: result+='370\n%s\n'%parent.lineWeight
153
# TODO: if parent.visible!=None: result+='60\n%s\n'%parent.visible
154
if parent.lineTypeScale!=None: result+=' 48\n%s\n'%parent.lineTypeScale
155
if parent.elevation!=None: result+=' 38\n%s\n'%parent.elevation
156
if parent.thickness!=None: result+=' 39\n%s\n'%parent.thickness
157
if parent.extrusion!=None: result+='%s\n'%_point(parent.extrusion,200)
160
#--------------------------
162
"""Base class to deal with composed objects."""
167
return ''.join([str(x) for x in self.__dxf__()])
169
#--------------------------
170
class _Collection(_Call):
171
"""Base class to expose entities methods to main object."""
172
def __init__(self,entities=[]):
173
self.entities=copy.copy(entities)
174
#link entities methods to drawing
175
for attr in dir(self.entities):
177
attrObject=getattr(self.entities,attr)
178
if callable(attrObject):
179
setattr(self,attr,attrObject)
186
#---block-type flags (bit coded values, may be combined):
187
ANONYMOUS =1 # This is an anonymous block generated by hatching, associative dimensioning, other internal operations, or an application
188
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)
189
XREF =4 # This block is an external reference (xref)
190
XREF_OVERLAY =8 # This block is an xref overlay
191
EXTERNAL =16 # This block is externally dependent
192
RESOLVED =32 # This is a resolved external reference, or dependent of an external reference (ignored on input)
193
REFERENCED =64 # This definition is a referenced external reference (ignored on input)
209
BY_STYLE = 5 #the flow direction is inherited from the associated text style
210
#line spacing style (optional):
211
AT_LEAST = 1 #taller characters will override
212
EXACT = 2 #taller characters will not override
215
CLOSED =1 # This is a closed polyline (or a polygon mesh closed in the M direction)
216
CURVE_FIT =2 # Curve-fit vertices have been added
217
SPLINE_FIT =4 # Spline-fit vertices have been added
218
POLYLINE_3D =8 # This is a 3D polyline
219
POLYGON_MESH =16 # This is a 3D polygon mesh
220
CLOSED_N =32 # The polygon mesh is closed in the N direction
221
POLYFACE_MESH =64 # The polyline is a polyface mesh
222
CONTINOUS_LINETYPE_PATTERN =128 # The linetype pattern is generated continuously around the vertices of this polyline
224
#---polyline flag 75, = curve type
235
ALIGNED = 3 #if vertical alignment = 0
236
MIDDLE = 4 #if vertical alignment = 0
237
FIT = 5 #if vertical alignment = 0
245
#---entitities -----------------------------------------------
246
#--------------------------
248
"""Arc, angles in degrees."""
249
def __init__(self,center=(0,0,0),radius=1,
250
startAngle=0.0,endAngle=90,**common):
251
"""Angles in degrees."""
252
_Entity.__init__(self,**common)
255
self.startAngle=startAngle
256
self.endAngle=endAngle
258
return ' 0\nARC\n%s%s\n 40\n%s\n 50\n%s\n 51\n%s\n'%\
259
(self._common(),_point(self.center),
260
self.radius,self.startAngle,self.endAngle)
262
#-----------------------------------------------
263
class Circle(_Entity):
265
def __init__(self,center=(0,0,0),radius=1,**common):
266
_Entity.__init__(self,**common)
270
return ' 0\nCIRCLE\n%s%s\n 40\n%s\n'%\
271
(self._common(),_point(self.center),self.radius)
273
#-----------------------------------------------
276
def __init__(self,points,**common):
277
_Entity.__init__(self,**common)
278
while len(points)<4: #fix for r12 format
279
points.append(points[-1])
283
out = ' 0\n3DFACE\n%s%s\n' %(self._common(),_points(self.points))
286
#-----------------------------------------------
287
class Insert(_Entity):
288
"""Block instance."""
289
def __init__(self,name,point=(0,0,0),
290
xscale=None,yscale=None,zscale=None,
291
cols=None,colspacing=None,rows=None,rowspacing=None,
294
_Entity.__init__(self,**common)
301
self.colspacing=colspacing
303
self.rowspacing=rowspacing
304
self.rotation=rotation
307
result=' 0\nINSERT\n 2\n%s\n%s%s\n'%\
308
(self.name,self._common(),_point(self.point))
309
if self.xscale!=None:result+=' 41\n%s\n'%self.xscale
310
if self.yscale!=None:result+=' 42\n%s\n'%self.yscale
311
if self.zscale!=None:result+=' 43\n%s\n'%self.zscale
312
if self.rotation:result+=' 50\n%s\n'%self.rotation
313
if self.cols!=None:result+=' 70\n%s\n'%self.cols
314
if self.colspacing!=None:result+=' 44\n%s\n'%self.colspacing
315
if self.rows!=None:result+=' 71\n%s\n'%self.rows
316
if self.rowspacing!=None:result+=' 45\n%s\n'%self.rowspacing
319
#-----------------------------------------------
322
def __init__(self,points,**common):
323
_Entity.__init__(self,**common)
326
return ' 0\nLINE\n%s%s\n' %(
327
self._common(), _points(self.points))
330
#-----------------------------------------------
331
class PolyLine(_Entity):
332
def __init__(self,points,org_point=[0,0,0],flag70=0,flag75=0,width=None,**common):
333
#width = number, or width = list [width_start=None, width_end=None]
334
#for 2d-polyline: points = [ [[x, y, z], vflag=None, [width_start=None, width_end=None], bulge=0 or None] ...]
335
#for 3d-polyline: points = [ [[x, y, z], vflag=None], ...]
336
#for polyface: points = [points_list, faces_list]
337
_Entity.__init__(self,**common)
339
self.org_point=org_point
340
self.pflag70 = flag70
341
self.pflag75 = flag75
342
self.polyface = False
343
self.polyline2d = False
344
self.faces = [] # dummy value
345
self.width= None # dummy value
346
if self.pflag70 & POLYFACE_MESH:
348
self.points=points[0]
350
self.p_count=len(self.points)
351
self.f_count=len(self.faces)
352
elif not (self.pflag70 & POLYLINE_3D):
353
self.polyline2d = True
355
if type(width)!='list': width=[width,width]
359
result= ' 0\nPOLYLINE\n%s 70\n%s\n' %(self._common(),self.pflag70)
361
result+='%s\n' %_point(self.org_point)
363
result+=' 71\n%s\n' %self.p_count
364
result+=' 72\n%s\n' %self.f_count
365
elif self.polyline2d:
366
if self.width!=None: result+=' 40\n%s\n 41\n%s\n' %(self.width[0],self.width[1])
368
result+=' 75\n%s\n' %self.pflag75
369
for point in self.points:
370
result+=' 0\nVERTEX\n'
371
result+=' 8\n%s\n' %self.layer
373
result+='%s\n' %_point(point)
375
elif self.polyline2d:
376
result+='%s\n' %_point(point[0])
379
[width1, width2] = point[2]
380
if width1!=None: result+=' 40\n%s\n' %width1
381
if width2!=None: result+=' 41\n%s\n' %width2
384
if bulge: result+=' 42\n%s\n' %bulge
386
result+=' 70\n%s\n' %flag
388
result+='%s\n' %_point(point[0])
391
result+=' 70\n%s\n' %flag
393
for face in self.faces:
394
result+=' 0\nVERTEX\n'
395
result+=' 8\n%s\n' %self.layer
396
result+='%s\n' %_point(self.org_point)
398
result+=' 71\n%s\n' %face[0]
399
result+=' 72\n%s\n' %face[1]
400
result+=' 73\n%s\n' %face[2]
401
if len(face)==4: result+=' 74\n%s\n' %face[3]
402
result+=' 0\nSEQEND\n'
403
result+=' 8\n%s\n' %self.layer
406
#-----------------------------------------------
407
class Point(_Entity):
409
def __init__(self,points=None,**common):
410
_Entity.__init__(self,**common)
412
def __str__(self): # TODO:
413
return ' 0\nPOINT\n%s%s\n' %(self._common(),
417
#-----------------------------------------------
418
class Solid(_Entity):
419
"""Colored solid fill."""
420
def __init__(self,points=None,**common):
421
_Entity.__init__(self,**common)
424
return ' 0\nSOLID\n%s%s\n' %(self._common(),
425
_points(self.points[:2]+[self.points[3],self.points[2]])
429
#-----------------------------------------------
431
"""Single text line."""
432
def __init__(self,text='',point=(0,0,0),alignment=None,
433
flag=None,height=1,justifyhor=None,justifyver=None,
434
rotation=None,obliqueAngle=None,style=None,xscale=None,**common):
435
_Entity.__init__(self,**common)
438
self.alignment=alignment
441
self.justifyhor=justifyhor
442
self.justifyver=justifyver
443
self.rotation=rotation
444
self.obliqueAngle=obliqueAngle
448
result= ' 0\nTEXT\n%s%s\n 40\n%s\n 1\n%s\n'%\
449
(self._common(),_point(self.point),self.height,self.text)
450
if self.rotation: result+=' 50\n%s\n'%self.rotation
451
if self.xscale: result+=' 41\n%s\n'%self.xscale
452
if self.obliqueAngle: result+=' 51\n%s\n'%self.obliqueAngle
453
if self.style: result+=' 7\n%s\n'%self.style
454
if self.flag: result+=' 71\n%s\n'%self.flag
455
if self.justifyhor: result+=' 72\n%s\n'%self.justifyhor
456
if self.alignment: result+='%s\n'%_point(self.alignment,1)
457
if self.justifyver: result+=' 73\n%s\n'%self.justifyver
460
#-----------------------------------------------
462
"""Surrogate for mtext, generates some Text instances."""
463
def __init__(self,text='',point=(0,0,0),width=250,spacingFactor=1.5,down=0,spacingWidth=None,**options):
464
Text.__init__(self,text=text,point=point,**options)
465
if down:spacingFactor*=-1
466
self.spacingFactor=spacingFactor
467
self.spacingWidth=spacingWidth
471
texts=self.text.replace('\r\n','\n').split('\n')
472
if not self.down:texts.reverse()
475
if self.spacingWidth:spacingWidth=self.spacingWidth
476
else:spacingWidth=self.height*self.spacingFactor
479
result+='%s' %Text(text[:self.width],
480
point=(self.point[0]+x*spacingWidth,
481
self.point[1]+y*spacingWidth,
483
alignment=self.alignment,flag=self.flag,height=self.height,
484
justifyhor=self.justifyhor,justifyver=self.justifyver,
485
rotation=self.rotation,obliqueAngle=self.obliqueAngle,
486
style=self.style,xscale=self.xscale,parent=self
488
text=text[self.width:]
489
if self.rotation:x+=1
493
#-----------------------------------------------
494
##class _Mtext(_Entity):
495
"""Mtext not functioning for minimal dxf."""
497
def __init__(self,text='',point=(0,0,0),attachment=1,
498
charWidth=None,charHeight=1,direction=1,height=100,rotation=0,
499
spacingStyle=None,spacingFactor=None,style=None,width=100,
500
xdirection=None,**common):
501
_Entity.__init__(self,**common)
504
self.attachment=attachment
505
self.charWidth=charWidth
506
self.charHeight=charHeight
507
self.direction=direction
509
self.rotation=rotation
510
self.spacingStyle=spacingStyle
511
self.spacingFactor=spacingFactor
514
self.xdirection=xdirection
518
while len(input)>250:
519
text+='3\n%s\n'%input[:250]
521
text+='1\n%s\n'%input
522
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'%\
523
(self._common(),_point(self.point),self.charHeight,self.width,
524
self.attachment,self.direction,text,
527
if self.style:result+='7\n%s\n'%self.style
528
if self.xdirection:result+='%s\n'%_point(self.xdirection,1)
529
if self.charWidth:result+='42\n%s\n'%self.charWidth
530
if self.spacingStyle:result+='73\n%s\n'%self.spacingStyle
531
if self.spacingFactor:result+='44\n%s\n'%self.spacingFactor
536
#---tables ---------------------------------------------------
537
#-----------------------------------------------
538
class Block(_Collection):
539
"""Use list methods to add entities, eg append."""
540
def __init__(self,name,layer='0',flag=0,base=(0,0,0),entities=[]):
541
self.entities=copy.copy(entities)
542
_Collection.__init__(self,entities)
547
def __str__(self): # TODO:
548
e=''.join([str(x)for x in self.entities])
549
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'%\
550
(self.layer,self.name.upper(),self.flag,_point(self.base),self.name.upper(),e)
552
#-----------------------------------------------
555
def __init__(self,name='pydxf',color=7,lineType='continuous',flag=64):
558
self.lineType=lineType
561
return ' 0\nLAYER\n 2\n%s\n 70\n%s\n 62\n%s\n 6\n%s\n'%\
562
(self.name.upper(),self.flag,self.color,self.lineType)
564
#-----------------------------------------------
565
class LineType(_Call):
566
"""Custom linetype"""
567
def __init__(self,name='CONTINUOUS',description='Solid line',elements=[0.0],flag=0):
569
self.description=description
570
self.elements=copy.copy(elements)
573
result = ' 0\nLTYPE\n 2\n%s\n 70\n%s\n 3\n%s\n 72\n65\n'%\
574
(self.name.upper(),self.flag,self.description)
576
elements = ' 73\n%s\n' %(len(self.elements)-1)
577
elements += ' 40\n%s\n' %(self.elements[0])
578
for e in self.elements[1:]:
579
elements += ' 49\n%s\n' %e
584
#-----------------------------------------------
587
def __init__(self,name='standard',flag=0,height=0,widthFactor=1.0,obliqueAngle=0.0,
588
mirror=0,lastHeight=1,font='arial.ttf',bigFont=''):
592
self.widthFactor=widthFactor
593
self.obliqueAngle=obliqueAngle
595
self.lastHeight=lastHeight
599
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'%\
600
(self.name.upper(),self.flag,self.flag,self.widthFactor,
601
self.obliqueAngle,self.mirror,self.lastHeight,
602
self.font.upper(),self.bigFont.upper())
604
#-----------------------------------------------
606
def __init__(self,name,flag=0,
607
leftBottom=(0.0,0.0),
611
snap_spacing=(0.1,0.1),
612
grid_spacing=(0.1,0.1),
613
direction=(0.0,0.0,1.0),
614
target=(0.0,0.0,0.0),
633
self.leftBottom=leftBottom
634
self.rightTop=rightTop
636
self.snap_base=snap_base
637
self.snap_spacing=snap_spacing
638
self.grid_spacing=grid_spacing
639
self.direction=direction
641
self.height=float(height)
642
self.ratio=float(ratio)
643
self.lens=float(lens)
644
self.frontClipping=float(frontClipping)
645
self.backClipping=float(backClipping)
646
self.snap_rotation=float(snap_rotation)
647
self.twist=float(twist)
649
self.circle_zoom=circle_zoom
650
self.fast_zoom=fast_zoom
654
self.snap_style=snap_style
655
self.snap_isopair=snap_isopair
657
output = [' 0', 'VPORT',
660
_point(self.leftBottom),
661
_point(self.rightTop,1),
662
_point(self.center,2), # View center point (in DCS)
663
_point(self.snap_base,3),
664
_point(self.snap_spacing,4),
665
_point(self.grid_spacing,5),
666
_point(self.direction,6), #view direction from target (in WCS)
667
_point(self.target,7),
671
' 43', self.frontClipping,
672
' 44', self.backClipping,
673
' 50', self.snap_rotation,
676
' 72', self.circle_zoom,
677
' 73', self.fast_zoom,
681
' 77', self.snap_style,
682
' 78', self.snap_isopair
687
output_str += '%s\n' %s
692
#-----------------------------------------------
694
def __init__(self,name,flag=0,
698
direction=(0.0,0.0,1.0),
699
target=(0.0,0.0,0.0),
707
self.width=float(width)
708
self.height=float(height)
710
self.direction=direction
712
self.lens=float(lens)
713
self.frontClipping=float(frontClipping)
714
self.backClipping=float(backClipping)
715
self.twist=float(twist)
718
output = [' 0', 'VIEW',
724
_point(self.direction,1),
725
_point(self.target,2),
727
' 43', self.frontClipping,
728
' 44', self.backClipping,
734
output_str += '%s\n' %s
737
#-----------------------------------------------
738
def ViewByWindow(name,leftBottom=(0,0),rightTop=(1,1),**options):
739
width=abs(rightTop[0]-leftBottom[0])
740
height=abs(rightTop[1]-leftBottom[1])
741
center=((rightTop[0]+leftBottom[0])*0.5,(rightTop[1]+leftBottom[1])*0.5)
742
return View(name=name,width=width,height=height,center=center,**options)
745
#-----------------------------------------------
746
class Drawing(_Collection):
747
"""Dxf drawing. Use append or any other list methods to add objects."""
748
def __init__(self,insbase=(0.0,0.0,0.0),extmin=(0.0,0.0,0.0),extmax=(0.0,0.0,0.0),
749
layers=[Layer()],linetypes=[LineType()],styles=[Style()],blocks=[],
750
views=[],vports=[],entities=None,fileName='test.dxf'):
751
# TODO: replace list with None,arial
754
_Collection.__init__(self,entities)
758
self.layers=copy.copy(layers)
759
self.linetypes=copy.copy(linetypes)
760
self.styles=copy.copy(styles)
761
self.views=copy.copy(views)
762
self.vports=copy.copy(vports)
763
self.blocks=copy.copy(blocks)
764
self.fileName=fileName
765
#print 'deb: blocks=',blocks #----------
767
#self.acadver='9\n$ACADVER\n1\nAC1006\n'
768
self.acadver=' 9\n$ACADVER\n 1\nAC1009\n'
769
"""DXF AutoCAD-Release format codes:
771
AC1018 2006, 2005, 2004
772
AC1015 2002, 2000i, 2000
783
"""Helper function for self._point"""
784
return ' 9\n$%s\n' %x.upper()
786
def _point(self,name,x):
787
"""Point setting from drawing like extmin,extmax,..."""
788
return '%s%s' %(self._name(name),_point(x))
790
def _section(self,name,x):
791
"""Sections like tables,blocks,entities,..."""
792
if x: xstr=''.join(x)
794
return ' 0\nSECTION\n 2\n%s\n%s 0\nENDSEC\n'%(name.upper(),xstr)
796
def _table(self,name,x):
797
"""Tables like ltype,layer,style,..."""
798
if x: xstr=''.join(x)
800
return ' 0\nTABLE\n 2\n%s\n 70\n%s\n%s 0\nENDTAB\n'%(name.upper(),len(x),xstr)
803
"""Returns drawing as dxf string."""
804
header=[self.acadver]+[self._point(attr,getattr(self,attr))+'\n' for attr in _HEADER_POINTS]
805
header=self._section('header',header)
807
tables=[self._table('vport',[str(x) for x in self.vports]),
808
self._table('ltype',[str(x) for x in self.linetypes]),
809
self._table('layer',[str(x) for x in self.layers]),
810
self._table('style',[str(x) for x in self.styles]),
811
self._table('view',[str(x) for x in self.views]),
813
tables=self._section('tables',tables)
814
blocks=self._section('blocks',[str(x) for x in self.blocks])
815
entities=self._section('entities',[str(x) for x in self.entities])
816
all=''.join([header,tables,blocks,entities,' 0\nEOF\n'])
819
def _write_section(self,file,name,data):
820
file.write(' 0\nSECTION\n 2\n%s\n'%name.upper())
823
file.write(' 0\nENDSEC\n')
825
def saveas(self,fileName,buffer=0):
826
"""Writes DXF file. Needs target file name. If optional parameter buffer>0, then switch to old behavior: store entire output string in RAM.
828
self.fileName=fileName
829
if buffer: self.save()
833
outfile=open(self.fileName,'w')
834
outfile.write(str(self))
838
outfile=open(self.fileName,'w')
839
header=[self.acadver]+[self._point(attr,getattr(self,attr))+'\n' for attr in _HEADER_POINTS]
840
self._write_section(outfile,'header',header)
841
tables=[self._table('vport',[str(x) for x in self.vports]),
842
self._table('ltype',[str(x) for x in self.linetypes]),
843
self._table('layer',[str(x) for x in self.layers]),
844
self._table('style',[str(x) for x in self.styles]),
845
self._table('view',[str(x) for x in self.views]),
847
self._write_section(outfile,'tables',tables)
848
self._write_section(outfile,'blocks',self.blocks)
849
self._write_section(outfile,'entities',self.entities)
850
outfile.write(' 0\nEOF\n')
855
#-----------------------------------------------
856
class Rectangle(_Entity):
857
"""Rectangle, creates lines."""
858
def __init__(self,point=(0,0,0),width=1,height=1,solid=None,line=1,**common):
859
_Entity.__init__(self,**common)
867
points=[self.point,(self.point[0]+self.width,self.point[1],self.point[2]),
868
(self.point[0]+self.width,self.point[1]+self.height,self.point[2]),
869
(self.point[0],self.point[1]+self.height,self.point[2]),self.point]
871
result+= Solid(points=points[:-1],parent=self.solid)
874
result+= Line(points=[points[i],points[i+1]],parent=self)
877
#-----------------------------------------------
878
class LineList(_Entity):
879
"""Like polyline, but built of individual lines."""
880
def __init__(self,points=[],org_point=[0,0,0],closed=0,**common):
881
_Entity.__init__(self,**common)
883
self.points=copy.copy(points)
886
points=self.points+[self.points[0]]
887
else: points=self.points
889
for i in range(len(points)-1):
890
result+= Line(points=[points[i][0],points[i+1][0]],parent=self)
893
#-----------------------------------------------------
897
b.append(Solid(points=[(0,0,0),(1,0,0),(1,1,0),(0,1,0)],color=1))
898
b.append(Arc(center=(1,0,0),color=2))
903
d.blocks.append(b) #table blocks
904
d.styles.append(Style()) #table styles
905
d.views.append(View('Normal')) #table view
906
d.views.append(ViewByWindow('Window',leftBottom=(1,0),rightTop=(2,1))) #idem
909
d.append(Circle(center=(1,1,0),color=3))
910
d.append(Face(points=[(0,0,0),(1,0,0),(1,1,0),(0,1,0)],color=4))
911
d.append(Insert('test',point=(3,3,3),cols=5,colspacing=2))
912
d.append(Line(points=[(0,0,0),(1,1,1)]))
913
d.append(Mtext('Click on Ads\nmultiple lines with mtext',point=(1,1,1),color=5,rotation=90))
914
d.append(Text('Please donate!',point=(3,0,1)))
915
#d.append(Rectangle(point=(2,2,2),width=4,height=3,color=6,solid=Solid(color=2)))
916
d.append(Solid(points=[(4,4,0),(5,4,0),(7,8,0),(9,9,0)],color=3))
917
#d.append(PolyLine(points=[(1,1,1),(2,1,1),(2,2,1),(1,2,1)],flag=1,color=1))
919
#d.saveas('c:\\test.dxf')
922
#-----------------------------------------------------
923
if __name__=='__main__':
925
Draw.PupMenu('Error%t|This script requires a full python install')