Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRemigiusz Fiedler <migius@gmx.net>2008-10-08 00:34:24 +0400
committerRemigiusz Fiedler <migius@gmx.net>2008-10-08 00:34:24 +0400
commit8b2f089c6eb77fd979a3d75461405f2236f1d877 (patch)
tree29a2fb3504234dd8e8f04aeab2afbd1f50557720 /release
parentd8758e32a06f76798285c300d2eb37595e1ba646 (diff)
DXF-Exporter update
v1.27 - 2008.10.07 by migius - exclude Stani's DXF-Library to extern module - add "hidden mode" substitut: back-faces removal - add support for mesh ->POLYFACE - optimized code for "Flat" procedure - modif FACE class for r12 - add mesh-polygon -> Bezier-curve converter (Yorik's code) - add support for curves ->POLYLINEs - add "3d-View to Flat" - geometry projection to XY-plane
Diffstat (limited to 'release')
-rw-r--r--release/scripts/bpymodules/dxfLibrary.py708
-rw-r--r--release/scripts/export_dxf.py1029
2 files changed, 996 insertions, 741 deletions
diff --git a/release/scripts/bpymodules/dxfLibrary.py b/release/scripts/bpymodules/dxfLibrary.py
new file mode 100644
index 00000000000..5c63e7f5bf5
--- /dev/null
+++ b/release/scripts/bpymodules/dxfLibrary.py
@@ -0,0 +1,708 @@
+#dxfLibrary.py : provides functions for generating DXF files
+# --------------------------------------------------------------------------
+__version__ = "v1.27beta - 2008.10.05"
+__author__ = "Stani Michiels(Stani), Remigiusz Fiedler(migius)"
+__license__ = "GPL"
+__url__ = "http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_dxf"
+__bpydoc__ ="""The script exports geometry data to DXF format r12 version.
+
+Copyright %s
+Version %s
+License %s
+Homepage %s
+
+See the homepage for documentation.
+url:
+
+IDEAs:
+-
+
+TODO:
+-
+
+History
+v1.27 - 2008.10.07 by migius
+- beautifying output code: keys whitespace prefix
+- refactoring DXF-strings format: NewLine moved to the end of
+v1.26 - 2008.10.05 by migius
+- modif POLYLINE to support POLYFACE
+v1.25 - 2008.09.28 by migius
+- modif FACE class for r12
+v1.24 - 2008.09.27 by migius
+- modif POLYLINE class for r12
+- changing output format from r9 to r12(AC1009)
+v1.1 (20/6/2005) by www.stani.be/python/sdxf
+- Python library to generate dxf drawings
+______________________________________________________________
+""" % (__author__,__version__,__license__,__url__)
+
+# --------------------------------------------------------------------------
+# DXF Library: copyright (C) 2005 by Stani Michiels (AKA Stani)
+# 2008 modif by Remigiusz Fiedler (AKA migius)
+# --------------------------------------------------------------------------
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+
+
+#import Blender
+#from Blender import Mathutils, Window, Scene, sys, Draw
+#import BPyMessages
+
+try:
+ import copy
+ #from struct import pack
+except:
+ copy = None
+
+####1) Private (only for developpers)
+_HEADER_POINTS=['insbase','extmin','extmax']
+
+#---helper functions-----------------------------------
+def _point(x,index=0):
+ """Convert tuple to a dxf point"""
+ #print 'deb: _point=', x #-------------
+ return '\n'.join([' %s\n%s'%((i+1)*10+index,x[i]) for i in range(len(x))])
+
+def _points(plist):
+ """Convert a list of tuples to dxf points"""
+ out = '\n'.join([_point(plist[i],i)for i in range(len(plist))])
+ #print 'deb: points=\n', out #-------------------
+ return out
+
+#---base classes----------------------------------------
+class _Call:
+ """Makes a callable class."""
+ def copy(self):
+ """Returns a copy."""
+ return copy.deepcopy(self)
+
+ def __call__(self,**attrs):
+ """Returns a copy with modified attributes."""
+ copied=self.copy()
+ for attr in attrs:setattr(copied,attr,attrs[attr])
+ return copied
+
+#-------------------------------------------------------
+class _Entity(_Call):
+ """Base class for _common group codes for entities."""
+ def __init__(self,color=None,extrusion=None,layer='0',
+ lineType=None,lineTypeScale=None,lineWeight=None,
+ thickness=None,parent=None):
+ """None values will be omitted."""
+ self.color = color
+ self.extrusion = extrusion
+ self.layer = layer
+ self.lineType = lineType
+ self.lineTypeScale = lineTypeScale
+ self.lineWeight = lineWeight
+ self.thickness = thickness
+ self.parent = parent
+
+ def _common(self):
+ """Return common group codes as a string."""
+ if self.parent:parent=self.parent
+ else:parent=self
+ result =''
+ if parent.layer!=None: result+=' 8\n%s\n'%parent.layer
+ if parent.color!=None: result+=' 62\n%s\n'%parent.color
+ if parent.extrusion!=None: result+='%s\n'%_point(parent.extrusion,200)
+ if parent.lineType!=None: result+=' 6\n%s\n'%parent.lineType
+ #TODO: if parent.lineWeight!=None: result+='370\n%s\n'%parent.lineWeight
+ if parent.lineTypeScale!=None: result+=' 48\n%s\n'%parent.lineTypeScale
+ if parent.thickness!=None: result+=' 39\n%s\n'%parent.thickness
+ return result
+
+#--------------------------
+class _Entities:
+ """Base class to deal with composed objects."""
+ def __dxf__(self):
+ return []
+
+ def __str__(self):
+ return ''.join([str(x) for x in self.__dxf__()])
+
+#--------------------------
+class _Collection(_Call):
+ """Base class to expose entities methods to main object."""
+ def __init__(self,entities=[]):
+ self.entities=copy.copy(entities)
+ #link entities methods to drawing
+ for attr in dir(self.entities):
+ if attr[0]!='_':
+ attrObject=getattr(self.entities,attr)
+ if callable(attrObject):
+ setattr(self,attr,attrObject)
+
+####2) Constants
+#---color values
+BYBLOCK=0
+BYLAYER=256
+
+#---block-type flags (bit coded values, may be combined):
+ANONYMOUS =1 # This is an anonymous block generated by hatching, associative dimensioning, other internal operations, or an application
+NON_CONSTANT_ATTRIBUTES =2 # This block has non-constant attribute definitions (this bit is not set if the block has any attribute definitions that are constant, or has no attribute definitions at all)
+XREF =4 # This block is an external reference (xref)
+XREF_OVERLAY =8 # This block is an xref overlay
+EXTERNAL =16 # This block is externally dependent
+RESOLVED =32 # This is a resolved external reference, or dependent of an external reference (ignored on input)
+REFERENCED =64 # This definition is a referenced external reference (ignored on input)
+
+#---mtext flags
+#attachment point
+TOP_LEFT = 1
+TOP_CENTER = 2
+TOP_RIGHT = 3
+MIDDLE_LEFT = 4
+MIDDLE_CENTER = 5
+MIDDLE_RIGHT = 6
+BOTTOM_LEFT = 7
+BOTTOM_CENTER = 8
+BOTTOM_RIGHT = 9
+#drawing direction
+LEFT_RIGHT = 1
+TOP_BOTTOM = 3
+BY_STYLE = 5 #the flow direction is inherited from the associated text style
+#line spacing style (optional):
+AT_LEAST = 1 #taller characters will override
+EXACT = 2 #taller characters will not override
+
+#---polyline flags
+CLOSED =1 # This is a closed polyline (or a polygon mesh closed in the M direction)
+CURVE_FIT =2 # Curve-fit vertices have been added
+SPLINE_FIT =4 # Spline-fit vertices have been added
+POLYLINE_3D =8 # This is a 3D polyline
+POLYGON_MESH =16 # This is a 3D polygon mesh
+CLOSED_N =32 # The polygon mesh is closed in the N direction
+POLYFACE_MESH =64 # The polyline is a polyface mesh
+CONTINOUS_LINETYPE_PATTERN =128 # The linetype pattern is generated continuously around the vertices of this polyline
+
+#---text flags
+#horizontal
+LEFT = 0
+CENTER = 1
+RIGHT = 2
+ALIGNED = 3 #if vertical alignment = 0
+MIDDLE = 4 #if vertical alignment = 0
+FIT = 5 #if vertical alignment = 0
+#vertical
+BASELINE = 0
+BOTTOM = 1
+MIDDLE = 2
+TOP = 3
+
+####3) Classes
+#---entitities -----------------------------------------------
+#--------------------------
+class Arc(_Entity):
+ """Arc, angles in degrees."""
+ def __init__(self,center=(0,0,0),radius=1,
+ startAngle=0.0,endAngle=90,**common):
+ """Angles in degrees."""
+ _Entity.__init__(self,**common)
+ self.center=center
+ self.radius=radius
+ self.startAngle=startAngle
+ self.endAngle=endAngle
+ def __str__(self):
+ return ' 0\nARC\n%s%s\n 40\n%s\n 50\n%s\n 51\n%s\n'%\
+ (self._common(),_point(self.center),
+ self.radius,self.startAngle,self.endAngle)
+
+#-----------------------------------------------
+class Circle(_Entity):
+ """Circle"""
+ def __init__(self,center=(0,0,0),radius=1,**common):
+ _Entity.__init__(self,**common)
+ self.center=center
+ self.radius=radius
+ def __str__(self):
+ return ' 0\nCIRCLE\n%s%s\n 40\n%s\n'%\
+ (self._common(),_point(self.center),self.radius)
+
+#-----------------------------------------------
+class Face(_Entity):
+ """3dface"""
+ def __init__(self,points,**common):
+ _Entity.__init__(self,**common)
+ if len(points)<4: #fix for r12 format
+ points.append(points[-1])
+ self.points=points
+
+ def __str__(self):
+ out = ' 0\n3DFACE\n%s%s\n' %(self._common(),_points(self.points))
+ #print 'deb:out=', out #-------------------
+ return out
+
+#-----------------------------------------------
+class Insert(_Entity):
+ """Block instance."""
+ def __init__(self,name,point=(0,0,0),
+ xscale=None,yscale=None,zscale=None,
+ cols=None,colspacing=None,rows=None,rowspacing=None,
+ rotation=None,
+ **common):
+ _Entity.__init__(self,**common)
+ self.name=name
+ self.point=point
+ self.xscale=xscale
+ self.yscale=yscale
+ self.zscale=zscale
+ self.cols=cols
+ self.colspacing=colspacing
+ self.rows=rows
+ self.rowspacing=rowspacing
+ self.rotation=rotation
+
+ def __str__(self):
+ result=' 0\nINSERT\n 2\n%s\n%s\n%s\n'%\
+ (self.name,self._common(),_point(self.point))
+ if self.xscale!=None:result+=' 41\n%s\n'%self.xscale
+ if self.yscale!=None:result+=' 42\n%s\n'%self.yscale
+ if self.zscale!=None:result+=' 43\n%s\n'%self.zscale
+ if self.rotation:result+=' 50\n%s\n'%self.rotation
+ if self.cols!=None:result+=' 70\n%s\n'%self.cols
+ if self.colspacing!=None:result+=' 44\n%s\n'%self.colspacing
+ if self.rows!=None:result+=' 71\n%s\n'%self.rows
+ if self.rowspacing!=None:result+=' 45\n%s\n'%self.rowspacing
+ return result
+
+#-----------------------------------------------
+class Line(_Entity):
+ """Line"""
+ def __init__(self,points,**common):
+ _Entity.__init__(self,**common)
+ self.points=points
+ def __str__(self):
+ return ' 0\nLINE\n%s%s\n' %(
+ self._common(), _points(self.points))
+
+
+#-----------------------------------------------
+class PolyLine(_Entity):
+ def __init__(self,points,org_point=[0,0,0],flag=0,width=None,**common):
+ _Entity.__init__(self,**common)
+ self.points=points
+ self.org_point=org_point
+ self.flag=flag
+ if self.flag==64:
+ self.points=points[0]
+ self.faces=points[1]
+ self.p_count=len(self.points)
+ self.f_count=len(self.faces)
+ self.width=width
+
+ def __str__(self):
+ result= ' 0\nPOLYLINE\n%s 70\n%s\n' %(self._common(),self.flag)
+ #print 'deb: self._common()', self._common() #----------
+ result+=' 66\n1\n'
+ result+='%s\n' %_point(self.org_point)
+ if self.flag==64:
+ result+=' 71\n%s\n' %self.p_count
+ result+=' 72\n%s\n' %self.f_count
+ for point in self.points:
+ result+=' 0\nVERTEX\n'
+ result+=' 8\n%s\n' %self.layer
+ result+='%s\n' %_point(point)
+ if self.flag==64: result+=' 70\n192\n'
+ if self.width: result+=' 40\n%s\n 41\n%s\n' %(self.width,self.width)
+ if self.flag==64:
+ for face in self.faces:
+ result+=' 0\nVERTEX\n'
+ result+=' 8\n%s\n' %self.layer
+ result+='%s\n' %_point(self.org_point)
+ result+=' 70\n128\n'
+ result+=' 71\n%s\n' %face[0]
+ result+=' 72\n%s\n' %face[1]
+ result+=' 73\n%s\n' %face[2]
+ if len(face)==4: result+=' 74\n%s\n' %face[3]
+ result+=' 0\nSEQEND\n'
+ result+=' 8\n%s\n' %self.layer
+ return result
+
+#-----------------------------------------------
+class Point(_Entity):
+ """Colored solid fill."""
+ def __init__(self,points=None,**common):
+ _Entity.__init__(self,**common)
+ self.points=points
+
+#-----------------------------------------------
+class Solid(_Entity):
+ """Colored solid fill."""
+ def __init__(self,points=None,**common):
+ _Entity.__init__(self,**common)
+ self.points=points
+ def __str__(self):
+ return ' 0\nSOLID\n%s%s\n' %(self._common(),
+ _points(self.points[:2]+[self.points[3],self.points[2]])
+ )
+
+
+#-----------------------------------------------
+class Text(_Entity):
+ """Single text line."""
+ def __init__(self,text='',point=(0,0,0),alignment=None,
+ flag=None,height=1,justifyhor=None,justifyver=None,
+ rotation=None,obliqueAngle=None,style=None,xscale=None,**common):
+ _Entity.__init__(self,**common)
+ self.text=text
+ self.point=point
+ self.alignment=alignment
+ self.flag=flag
+ self.height=height
+ self.justifyhor=justifyhor
+ self.justifyver=justifyver
+ self.rotation=rotation
+ self.obliqueAngle=obliqueAngle
+ self.style=style
+ self.xscale=xscale
+ def __str__(self):
+ result= ' 0\nTEXT\n%s%s\n 40\n%s\n 1\n%s\n'%\
+ (self._common(),_point(self.point),self.height,self.text)
+ if self.rotation: result+=' 50\n%s\n'%self.rotation
+ if self.xscale: result+=' 41\n%s\n'%self.xscale
+ if self.obliqueAngle: result+=' 51\n%s\n'%self.obliqueAngle
+ if self.style: result+=' 7\n%s\n'%self.style
+ if self.flag: result+=' 71\n%s\n'%self.flag
+ if self.justifyhor: result+=' 72\n%s\n'%self.justifyhor
+ #TODO: if self.alignment: result+='%s\n'%_point(self.alignment,1)
+ if self.justifyver: result+=' 73\n%s\n'%self.justifyver
+ return result
+
+#-----------------------------------------------
+class Mtext(Text):
+ """Surrogate for mtext, generates some Text instances."""
+ def __init__(self,text='',point=(0,0,0),width=250,spacingFactor=1.5,down=0,spacingWidth=None,**options):
+ Text.__init__(self,text=text,point=point,**options)
+ if down:spacingFactor*=-1
+ self.spacingFactor=spacingFactor
+ self.spacingWidth=spacingWidth
+ self.width=width
+ self.down=down
+ def __str__(self):
+ texts=self.text.replace('\r\n','\n').split('\n')
+ if not self.down:texts.reverse()
+ result=''
+ x=y=0
+ if self.spacingWidth:spacingWidth=self.spacingWidth
+ else:spacingWidth=self.height*self.spacingFactor
+ for text in texts:
+ while text:
+ result+='%s\n'%Text(text[:self.width],
+ point=(self.point[0]+x*spacingWidth,
+ self.point[1]+y*spacingWidth,
+ self.point[2]),
+ alignment=self.alignment,flag=self.flag,height=self.height,
+ justifyhor=self.justifyhor,justifyver=self.justifyver,
+ rotation=self.rotation,obliqueAngle=self.obliqueAngle,
+ style=self.style,xscale=self.xscale,parent=self
+ )
+ text=text[self.width:]
+ if self.rotation:x+=1
+ else:y+=1
+ return result[1:]
+
+#-----------------------------------------------
+##class _Mtext(_Entity):
+## """Mtext not functioning for minimal dxf."""
+## def __init__(self,text='',point=(0,0,0),attachment=1,
+## charWidth=None,charHeight=1,direction=1,height=100,rotation=0,
+## spacingStyle=None,spacingFactor=None,style=None,width=100,
+## xdirection=None,**common):
+## _Entity.__init__(self,**common)
+## self.text=text
+## self.point=point
+## self.attachment=attachment
+## self.charWidth=charWidth
+## self.charHeight=charHeight
+## self.direction=direction
+## self.height=height
+## self.rotation=rotation
+## self.spacingStyle=spacingStyle
+## self.spacingFactor=spacingFactor
+## self.style=style
+## self.width=width
+## self.xdirection=xdirection
+## def __str__(self):
+## input=self.text
+## text=''
+## while len(input)>250:
+## text+='3\n%s\n'%input[:250]
+## input=input[250:]
+## text+='1\n%s\n'%input
+## result= '0\nMTEXT\n%s\n%s\n40\n%s\n41\n%s\n71\n%s\n72\n%s%s\n43\n%s\n50\n%s\n'%\
+## (self._common(),_point(self.point),self.charHeight,self.width,
+## self.attachment,self.direction,text,
+## self.height,
+## self.rotation)
+## if self.style:result+='7\n%s\n'%self.style
+## if self.xdirection:result+='%s\n'%_point(self.xdirection,1)
+## if self.charWidth:result+='42\n%s\n'%self.charWidth
+## if self.spacingStyle:result+='73\n%s\n'%self.spacingStyle
+## if self.spacingFactor:result+='44\n%s\n'%self.spacingFactor
+## return result
+
+#---tables ---------------------------------------------------
+#-----------------------------------------------
+class Block(_Collection):
+ """Use list methods to add entities, eg append."""
+ def __init__(self,name,layer='0',flag=0,base=(0,0,0),entities=[]):
+ self.entities=copy.copy(entities)
+ _Collection.__init__(self,entities)
+ self.layer=layer
+ self.name=name
+ self.flag=0
+ self.base=base
+ def __str__(self):
+ e=''.join([str(x)for x in self.entities])
+ return ' 0\nBLOCK\n 8\n%s\n 2\n%s\n 70\n%s\n%s\n 3\n%s\n%s 0\nENDBLK\n'%\
+ (self.layer,self.name.upper(),self.flag,_point(self.base),self.name.upper(),e)
+
+#-----------------------------------------------
+class Layer(_Call):
+ """Layer"""
+ def __init__(self,name='pydxf',color=7,lineType='continuous',flag=64):
+ self.name=name
+ self.color=color
+ self.lineType=lineType
+ self.flag=flag
+ def __str__(self):
+ return ' 0\nLAYER\n 2\n%s\n 70\n%s\n 62\n%s\n 6\n%s\n'%\
+ (self.name.upper(),self.flag,self.color,self.lineType)
+
+#-----------------------------------------------
+class LineType(_Call):
+ """Custom linetype"""
+ def __init__(self,name='continuous',description='Solid line',elements=[],flag=64):
+ # TODO: Implement lineType elements
+ self.name=name
+ self.description=description
+ self.elements=copy.copy(elements)
+ self.flag=flag
+ def __str__(self):
+ 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'%\
+ (self.name.upper(),self.flag,self.description,len(self.elements))
+
+#-----------------------------------------------
+class Style(_Call):
+ """Text style"""
+ def __init__(self,name='standard',flag=0,height=0,widthFactor=40,obliqueAngle=50,
+ mirror=0,lastHeight=1,font='arial.ttf',bigFont=''):
+ self.name=name
+ self.flag=flag
+ self.height=height
+ self.widthFactor=widthFactor
+ self.obliqueAngle=obliqueAngle
+ self.mirror=mirror
+ self.lastHeight=lastHeight
+ self.font=font
+ self.bigFont=bigFont
+ def __str__(self):
+ return ' 0\nSTYLE\n 2\n%s\n 70\n%s\n 40\n%s\n 41\n%s\n 50\n%s\n 71\n%s\n 42\n%s\n 3\n%s\n 4\n%s\n'%\
+ (self.name.upper(),self.flag,self.flag,self.widthFactor,
+ self.obliqueAngle,self.mirror,self.lastHeight,
+ self.font.upper(),self.bigFont.upper())
+
+#-----------------------------------------------
+class View(_Call):
+ def __init__(self,name,flag=0,width=1,height=1,center=(0.5,0.5),
+ direction=(0,0,1),target=(0,0,0),lens=50,
+ frontClipping=0,backClipping=0,twist=0,mode=0):
+ self.name=name
+ self.flag=flag
+ self.width=width
+ self.height=height
+ self.center=center
+ self.direction=direction
+ self.target=target
+ self.lens=lens
+ self.frontClipping=frontClipping
+ self.backClipping=backClipping
+ self.twist=twist
+ self.mode=mode
+ def __str__(self):
+ 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'%\
+ (self.name,self.flag,self.height,_point(self.center),self.width,
+ _point(self.direction,1),_point(self.target,2),self.lens,
+ self.frontClipping,self.backClipping,self.twist,self.mode)
+
+#-----------------------------------------------
+def ViewByWindow(name,leftBottom=(0,0),rightTop=(1,1),**options):
+ width=abs(rightTop[0]-leftBottom[0])
+ height=abs(rightTop[1]-leftBottom[1])
+ center=((rightTop[0]+leftBottom[0])*0.5,(rightTop[1]+leftBottom[1])*0.5)
+ return View(name=name,width=width,height=height,center=center,**options)
+
+#---drawing
+#-----------------------------------------------
+class Drawing(_Collection):
+ """Dxf drawing. Use append or any other list methods to add objects."""
+ def __init__(self,insbase=(0.0,0.0,0.0),extmin=(0.0,0.0),extmax=(0.0,0.0),
+ layers=[Layer()],linetypes=[LineType()],styles=[Style()],blocks=[],
+ views=[],entities=None,fileName='test.dxf'):
+ # TODO: replace list with None,arial
+ if not entities:entities=[]
+ _Collection.__init__(self,entities)
+ self.insbase=insbase
+ self.extmin=extmin
+ self.extmax=extmax
+ self.layers=copy.copy(layers)
+ self.linetypes=copy.copy(linetypes)
+ self.styles=copy.copy(styles)
+ self.views=copy.copy(views)
+ self.blocks=copy.copy(blocks)
+ self.fileName=fileName
+ #private
+ #self.acadver='9\n$ACADVER\n1\nAC1006\n'
+ self.acadver=' 9\n$ACADVER\n 1\nAC1009\n'
+ """DXF AutoCAD-Release format codes
+ AC1021 2008, 2007
+ AC1018 2006, 2005, 2004
+ AC1015 2002, 2000i, 2000
+ AC1014 R14,14.01
+ AC1012 R13
+ AC1009 R12,11
+ AC1006 R10
+ AC1004 R9
+ AC1002 R2.6
+ AC1.50 R2.05
+ """
+
+ def _name(self,x):
+ """Helper function for self._point"""
+ return ' 9\n$%s\n' %x.upper()
+
+ def _point(self,name,x):
+ """Point setting from drawing like extmin,extmax,..."""
+ return '%s%s' %(self._name(name),_point(x))
+
+ def _section(self,name,x):
+ """Sections like tables,blocks,entities,..."""
+ if x: xstr=''.join(x)
+ else: xstr=''
+ return ' 0\nSECTION\n 2\n%s\n%s 0\nENDSEC\n'%(name.upper(),xstr)
+
+ def _table(self,name,x):
+ """Tables like ltype,layer,style,..."""
+ if x: xstr=''.join(x)
+ else: xstr=''
+ return ' 0\nTABLE\n 2\n%s\n 70\n%s\n%s 0\nENDTAB\n'%(name.upper(),len(x),xstr)
+
+ def __str__(self):
+ """Returns drawing as dxf string."""
+ header=[self.acadver]+[self._point(attr,getattr(self,attr))+'\n' for attr in _HEADER_POINTS]
+ header=self._section('header',header)
+
+ tables=[self._table('ltype',[str(x) for x in self.linetypes]),
+ self._table('layer',[str(x) for x in self.layers]),
+ self._table('style',[str(x) for x in self.styles]),
+ self._table('view',[str(x) for x in self.views]),
+ ]
+ tables=self._section('tables',tables)
+
+ blocks=self._section('blocks',[str(x) for x in self.blocks])
+
+ entities=self._section('entities',[str(x) for x in self.entities])
+
+ all=''.join([header,tables,blocks,entities,' 0\nEOF\n'])
+ return all
+
+ def saveas(self,fileName):
+ self.fileName=fileName
+ self.save()
+
+ def save(self):
+ test=open(self.fileName,'w')
+ test.write(str(self))
+ test.close()
+
+
+#---extras
+#-----------------------------------------------
+class Rectangle(_Entity):
+ """Rectangle, creates lines."""
+ def __init__(self,point=(0,0,0),width=1,height=1,solid=None,line=1,**common):
+ _Entity.__init__(self,**common)
+ self.point=point
+ self.width=width
+ self.height=height
+ self.solid=solid
+ self.line=line
+ def __str__(self):
+ result=''
+ points=[self.point,(self.point[0]+self.width,self.point[1],self.point[2]),
+ (self.point[0]+self.width,self.point[1]+self.height,self.point[2]),
+ (self.point[0],self.point[1]+self.height,self.point[2]),self.point]
+ if self.solid:
+ result+= Solid(points=points[:-1],parent=self.solid)
+ if self.line:
+ for i in range(4):
+ result+= Line(points=[points[i],points[i+1]],parent=self)
+ return result[1:]
+
+#-----------------------------------------------
+class LineList(_Entity):
+ """Like polyline, but built of individual lines."""
+ def __init__(self,points=[],org_point=[0,0,0],closed=0,**common):
+ _Entity.__init__(self,**common)
+ self.closed=closed
+ self.points=copy.copy(points)
+ def __str__(self):
+ if self.closed:points=self.points+[self.points[0]]
+ else: points=self.points
+ result=''
+ for i in range(len(points)-1):
+ result+= Line(points=[points[i],points[i+1]],parent=self)
+ return result[1:]
+
+#-----------------------------------------------------
+def test():
+ #Blocks
+ b=Block('test')
+ b.append(Solid(points=[(0,0,0),(1,0,0),(1,1,0),(0,1,0)],color=1))
+ b.append(Arc(center=(1,0,0),color=2))
+
+ #Drawing
+ d=Drawing()
+ #tables
+ d.blocks.append(b) #table blocks
+ d.styles.append(Style()) #table styles
+ d.views.append(View('Normal')) #table view
+ d.views.append(ViewByWindow('Window',leftBottom=(1,0),rightTop=(2,1))) #idem
+
+ #entities
+ d.append(Circle(center=(1,1,0),color=3))
+ d.append(Face(points=[(0,0,0),(1,0,0),(1,1,0),(0,1,0)],color=4))
+ d.append(Insert('test',point=(3,3,3),cols=5,colspacing=2))
+ d.append(Line(points=[(0,0,0),(1,1,1)]))
+ d.append(Mtext('Click on Ads\nmultiple lines with mtext',point=(1,1,1),color=5,rotation=90))
+ d.append(Text('Please donate!',point=(3,0,1)))
+ d.append(Rectangle(point=(2,2,2),width=4,height=3,color=6,solid=Solid(color=2)))
+ d.append(Solid(points=[(4,4,0),(5,4,0),(7,8,0),(9,9,0)],color=3))
+ d.append(PolyLine(points=[(1,1,1),(2,1,1),(2,2,1),(1,2,1)],closed=1,color=1))
+
+ #d.saveas('c:\\test.dxf')
+ d.saveas('test.dxf')
+
+
+#-----------------------------------------------------
+if __name__=='__main__':
+ if not copy:
+ Draw.PupMenu('Error%t|This script requires a full python install')
+ main()
+ \ No newline at end of file
diff --git a/release/scripts/export_dxf.py b/release/scripts/export_dxf.py
index 66586156359..061e29b81c7 100644
--- a/release/scripts/export_dxf.py
+++ b/release/scripts/export_dxf.py
@@ -7,52 +7,65 @@
Tooltip: 'Export geometry to DXF-r12 (Drawing eXchange Format).'
"""
-__version__ = "v1.25beta - 2008.09.28"
-__author__ = "Stani & migius(Remigiusz Fiedler)"
+__version__ = "v1.27beta - 2008.10.07"
+__author__ = "Remigiusz Fiedler (AKA migius)"
__license__ = "GPL"
__url__ = "http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_dxf"
__bpydoc__ ="""The script exports Blender geometry to DXF format r12 version.
-Copyright %s
Version %s
+Copyright %s
License %s
-Homepage %s
+
+extern dependances: dxfLibrary.py
See the homepage for documentation.
-url:
-""" % (__author__,__version__,__license__,__url__)
+url: %s
-"""
IDEAs:
- - correct normals for POLYLINE-POLYFACE objects via correct point-order
- - HPGL output for 2d and flattened3d content
+ - correct normals for POLYLINE-POLYFACE via proper point-order
+ - HPGL output for 2d and flattened 3d content
TODO:
- - support hierarchies: groups, instances, parented structures
- - support 210-code (3d orientation vector)
- - presets for architectural scales
+- optimize back-faces removal (probably needs matrix transform)
+- optimize POLYFACE routine: remove double-vertices
+- optimize POLYFACE routine: remove unused vertices
+- support hierarchies: groups, instances, parented structures
+- support 210-code (3d orientation vector)
+- presets for architectural scales
+- write drawing extends for automatic view positioning in CAD
History
+v1.27 - 2008.10.07 by migius
+- exclude Stani's DXF-Library to extern module
+v1.26 - 2008.10.05 by migius
+- add "hidden mode" substitut: back-faces removal
+- add support for mesh ->POLYFACE
+- optimized code for "Flat" procedure
v1.25 - 2008.09.28 by migius
- - modif FACE class for r12
- - add mesh-polygon -> Bezier-curve converter (Yorik's code)
- - add support for curves ->POLYLINEs
- - add "3d-View to Flat" - geometry projection to XY-plane
+- modif FACE class for r12
+- add mesh-polygon -> Bezier-curve converter (Yorik's code)
+- add support for curves ->POLYLINEs
+- add "3d-View to Flat" - geometry projection to XY-plane
v1.24 - 2008.09.27 by migius
- - add start UI with preferences
- - modif POLYLINE class for r12
- - changing output format from r9 to r12(AC1009)
+- add start UI with preferences
+- modif POLYLINE class for r12
+- changing output format from r9 to r12(AC1009)
v1.23 - 2008.09.26 by migius
- - add finish message-box
+- add finish message-box
v1.22 - 2008.09.26 by migius
- - add support for curves ->LINEs
- - add support for mesh-edges ->LINEs
+- add support for curves ->LINEs
+- add support for mesh-edges ->LINEs
v1.21 - 2008.06.04 by migius
- - initial adaptation for Blender
-v1.1 (20/6/2005) by www.stani.be/python/sdxf
- - Python library to generate dxf drawings
+- initial adaptation for Blender
+v1.1 (20/6/2005) by Stani Michiels www.stani.be/python/sdxf
+- Python library to generate dxf drawings
______________________________________________________________
-"""
+""" % (__author__,__version__,__license__,__url__)
+
+# --------------------------------------------------------------------------
+# Script copyright (C) 2008 Remigiusz Fiedler (AKA migius)
+# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
@@ -76,602 +89,254 @@ import Blender
from Blender import Mathutils, Window, Scene, sys, Draw
import BPyMessages
-try:
- import copy
- #from struct import pack
-except:
- copy = None
-
-####1) Private (only for developpers)
-_HEADER_POINTS=['insbase','extmin','extmax']
-
-#---helper functions-----------------------------------
-def _point(x,index=0):
- """Convert tuple to a dxf point"""
- #print '_point=', x #-------------
- return '\n'.join(['%s\n%s'%((i+1)*10+index,x[i]) for i in range(len(x))])
-
-def _points(plist):
- """Convert a list of tuples to dxf points"""
- return [_point(plist[i],i)for i in range(len(plist))]
-
-#---base classes----------------------------------------
-class _Call:
- """Makes a callable class."""
- def copy(self):
- """Returns a copy."""
- return copy.deepcopy(self)
-
- def __call__(self,**attrs):
- """Returns a copy with modified attributes."""
- copied=self.copy()
- for attr in attrs:setattr(copied,attr,attrs[attr])
- return copied
-
-#-------------------------------------------------------
-class _Entity(_Call):
- """Base class for _common group codes for entities."""
- def __init__(self,color=None,extrusion=None,layer='0',
- lineType=None,lineTypeScale=None,lineWeight=None,
- thickness=None,parent=None):
- """None values will be omitted."""
- self.color = color
- self.extrusion = extrusion
- self.layer = layer
- self.lineType = lineType
- self.lineTypeScale = lineTypeScale
- self.lineWeight = lineWeight
- self.thickness = thickness
- self.parent = parent
-
- def _common(self):
- """Return common group codes as a string."""
- if self.parent:parent=self.parent
- else:parent=self
- result='8\n%s'%parent.layer
- if parent.color!=None: result+='\n62\n%s'%parent.color
- if parent.extrusion!=None: result+='\n%s'%_point(parent.extrusion,200)
- if parent.lineType!=None: result+='\n6\n%s'%parent.lineType
- if parent.lineWeight!=None: result+='\n370\n%s'%parent.lineWeight
- if parent.lineTypeScale!=None: result+='\n48\n%s'%parent.lineTypeScale
- if parent.thickness!=None: result+='\n39\n%s'%parent.thickness
- return result
-
-#--------------------------
-class _Entities:
- """Base class to deal with composed objects."""
- def __dxf__(self):
- return []
-
- def __str__(self):
- return '\n'.join([str(x) for x in self.__dxf__()])
-
-#--------------------------
-class _Collection(_Call):
- """Base class to expose entities methods to main object."""
- def __init__(self,entities=[]):
- self.entities=copy.copy(entities)
- #link entities methods to drawing
- for attr in dir(self.entities):
- if attr[0]!='_':
- attrObject=getattr(self.entities,attr)
- if callable(attrObject):
- setattr(self,attr,attrObject)
-
-####2) Constants
-#---color values
-BYBLOCK=0
-BYLAYER=256
-
-#---block-type flags (bit coded values, may be combined):
-ANONYMOUS =1 # This is an anonymous block generated by hatching, associative dimensioning, other internal operations, or an application
-NON_CONSTANT_ATTRIBUTES =2 # This block has non-constant attribute definitions (this bit is not set if the block has any attribute definitions that are constant, or has no attribute definitions at all)
-XREF =4 # This block is an external reference (xref)
-XREF_OVERLAY =8 # This block is an xref overlay
-EXTERNAL =16 # This block is externally dependent
-RESOLVED =32 # This is a resolved external reference, or dependent of an external reference (ignored on input)
-REFERENCED =64 # This definition is a referenced external reference (ignored on input)
-
-#---mtext flags
-#attachment point
-TOP_LEFT = 1
-TOP_CENTER = 2
-TOP_RIGHT = 3
-MIDDLE_LEFT = 4
-MIDDLE_CENTER = 5
-MIDDLE_RIGHT = 6
-BOTTOM_LEFT = 7
-BOTTOM_CENTER = 8
-BOTTOM_RIGHT = 9
-#drawing direction
-LEFT_RIGHT = 1
-TOP_BOTTOM = 3
-BY_STYLE = 5 #the flow direction is inherited from the associated text style
-#line spacing style (optional):
-AT_LEAST = 1 #taller characters will override
-EXACT = 2 #taller characters will not override
-
-#---polyline flags
-CLOSED =1 # This is a closed polyline (or a polygon mesh closed in the M direction)
-CURVE_FIT =2 # Curve-fit vertices have been added
-SPLINE_FIT =4 # Spline-fit vertices have been added
-POLYLINE_3D =8 # This is a 3D polyline
-POLYGON_MESH =16 # This is a 3D polygon mesh
-CLOSED_N =32 # The polygon mesh is closed in the N direction
-POLYFACE_MESH =64 # The polyline is a polyface mesh
-CONTINOUS_LINETYPE_PATTERN =128 # The linetype pattern is generated continuously around the vertices of this polyline
-
-#---text flags
-#horizontal
-LEFT = 0
-CENTER = 1
-RIGHT = 2
-ALIGNED = 3 #if vertical alignment = 0
-MIDDLE = 4 #if vertical alignment = 0
-FIT = 5 #if vertical alignment = 0
-#vertical
-BASELINE = 0
-BOTTOM = 1
-MIDDLE = 2
-TOP = 3
-
-####3) Classes
-#---entitities -----------------------------------------------
-#--------------------------
-class Arc(_Entity):
- """Arc, angles in degrees."""
- def __init__(self,center=(0,0,0),radius=1,
- startAngle=0.0,endAngle=90,**common):
- """Angles in degrees."""
- _Entity.__init__(self,**common)
- self.center=center
- self.radius=radius
- self.startAngle=startAngle
- self.endAngle=endAngle
- def __str__(self):
- return '0\nARC\n%s\n%s\n40\n%s\n50\n%s\n51\n%s'%\
- (self._common(),_point(self.center),
- self.radius,self.startAngle,self.endAngle)
-
-#-----------------------------------------------
-class Circle(_Entity):
- """Circle"""
- def __init__(self,center=(0,0,0),radius=1,**common):
- _Entity.__init__(self,**common)
- self.center=center
- self.radius=radius
- def __str__(self):
- return '0\nCIRCLE\n%s\n%s\n40\n%s'%\
- (self._common(),_point(self.center),self.radius)
-
-#-----------------------------------------------
-class Face(_Entity):
- """3dface"""
- def __init__(self,points,**common):
- _Entity.__init__(self,**common)
- if len(points)<4: #fix for r12 format
- points.append(points[-1])
- self.points=points
-
- def __str__(self):
- return '\n'.join(['0\n3DFACE',self._common()]+
- _points(self.points)
- )
-#-----------------------------------------------
-class Insert(_Entity):
- """Block instance."""
- def __init__(self,name,point=(0,0,0),
- xscale=None,yscale=None,zscale=None,
- cols=None,colspacing=None,rows=None,rowspacing=None,
- rotation=None,
- **common):
- _Entity.__init__(self,**common)
- self.name=name
- self.point=point
- self.xscale=xscale
- self.yscale=yscale
- self.zscale=zscale
- self.cols=cols
- self.colspacing=colspacing
- self.rows=rows
- self.rowspacing=rowspacing
- self.rotation=rotation
-
- def __str__(self):
- result='0\nINSERT\n2\n%s\n%s\n%s'%\
- (self.name,self._common(),_point(self.point))
- if self.xscale!=None:result+='\n41\n%s'%self.xscale
- if self.yscale!=None:result+='\n42\n%s'%self.yscale
- if self.zscale!=None:result+='\n43\n%s'%self.zscale
- if self.rotation:result+='\n50\n%s'%self.rotation
- if self.cols!=None:result+='\n70\n%s'%self.cols
- if self.colspacing!=None:result+='\n44\n%s'%self.colspacing
- if self.rows!=None:result+='\n71\n%s'%self.rows
- if self.rowspacing!=None:result+='\n45\n%s'%self.rowspacing
- return result
-
-#-----------------------------------------------
-class Line(_Entity):
- """Line"""
- def __init__(self,points,**common):
- _Entity.__init__(self,**common)
- self.points=points
- def __str__(self):
- return '\n'.join(['0\nLINE',self._common()]+
- _points(self.points))
-
-#-----------------------------------------------
-class PolyLine(_Entity):
- #TODO: Finish polyline (now implemented as a series of lines)
- def __init__(self,points,org_point=[0,0,0],flag=0,width=None,**common):
- _Entity.__init__(self,**common)
- self.points=points
- self.org_point=org_point
- self.flag=flag
- self.width=width
- def __str__(self):
- result= '0\nPOLYLINE\n%s\n70\n%s' %(self._common(),self.flag)
- #print 'self._common()', self._common() #----------
- result+='\n66\n1'
- result+='\n%s' %_point(self.org_point)
- for point in self.points:
- result+='\n0\nVERTEX'
- result+='\n8\n%s' %self.layer
- result+='\n%s' %_point(point)
- if self.width:result+='\n40\n%s\n41\n%s' %(self.width,self.width)
- result+='\n0\nSEQEND'
- result+='\n8\n%s' %self.layer
- return result
-
-#-----------------------------------------------
-class Point(_Entity):
- """Colored solid fill."""
- def __init__(self,points=None,**common):
- _Entity.__init__(self,**common)
- self.points=points
-
-#-----------------------------------------------
-class Solid(_Entity):
- """Colored solid fill."""
- def __init__(self,points=None,**common):
- _Entity.__init__(self,**common)
- self.points=points
- def __str__(self):
- return '\n'.join(['0\nSOLID',self._common()]+
- _points(self.points[:2]+[self.points[3],self.points[2]])
- )
-
-#-----------------------------------------------
-class Text(_Entity):
- """Single text line."""
- def __init__(self,text='',point=(0,0,0),alignment=None,
- flag=None,height=1,justifyhor=None,justifyver=None,
- rotation=None,obliqueAngle=None,style=None,xscale=None,**common):
- _Entity.__init__(self,**common)
- self.text=text
- self.point=point
- self.alignment=alignment
- self.flag=flag
- self.height=height
- self.justifyhor=justifyhor
- self.justifyver=justifyver
- self.rotation=rotation
- self.obliqueAngle=obliqueAngle
- self.style=style
- self.xscale=xscale
- def __str__(self):
- result= '0\nTEXT\n%s\n%s\n40\n%s\n1\n%s'%\
- (self._common(),_point(self.point),self.height,self.text)
- if self.rotation:result+='\n50\n%s'%self.rotation
- if self.xscale:result+='\n41\n%s'%self.xscale
- if self.obliqueAngle:result+='\n51\n%s'%self.obliqueAngle
- if self.style:result+='\n7\n%s'%self.style
- if self.flag:result+='\n71\n%s'%self.flag
- if self.justifyhor:result+='\n72\n%s'%self.justifyhor
- if self.alignment:result+='\n%s'%_point(self.alignment,1)
- if self.justifyver:result+='\n73\n%s'%self.justifyver
- return result
-
-#-----------------------------------------------
-class Mtext(Text):
- """Surrogate for mtext, generates some Text instances."""
- def __init__(self,text='',point=(0,0,0),width=250,spacingFactor=1.5,down=0,spacingWidth=None,**options):
- Text.__init__(self,text=text,point=point,**options)
- if down:spacingFactor*=-1
- self.spacingFactor=spacingFactor
- self.spacingWidth=spacingWidth
- self.width=width
- self.down=down
- def __str__(self):
- texts=self.text.replace('\r\n','\n').split('\n')
- if not self.down:texts.reverse()
- result=''
- x=y=0
- if self.spacingWidth:spacingWidth=self.spacingWidth
- else:spacingWidth=self.height*self.spacingFactor
- for text in texts:
- while text:
- result+='\n%s'%Text(text[:self.width],
- point=(self.point[0]+x*spacingWidth,
- self.point[1]+y*spacingWidth,
- self.point[2]),
- alignment=self.alignment,flag=self.flag,height=self.height,
- justifyhor=self.justifyhor,justifyver=self.justifyver,
- rotation=self.rotation,obliqueAngle=self.obliqueAngle,
- style=self.style,xscale=self.xscale,parent=self
- )
- text=text[self.width:]
- if self.rotation:x+=1
- else:y+=1
- return result[1:]
-
-#-----------------------------------------------
-##class _Mtext(_Entity):
-## """Mtext not functioning for minimal dxf."""
-## def __init__(self,text='',point=(0,0,0),attachment=1,
-## charWidth=None,charHeight=1,direction=1,height=100,rotation=0,
-## spacingStyle=None,spacingFactor=None,style=None,width=100,
-## xdirection=None,**common):
-## _Entity.__init__(self,**common)
-## self.text=text
-## self.point=point
-## self.attachment=attachment
-## self.charWidth=charWidth
-## self.charHeight=charHeight
-## self.direction=direction
-## self.height=height
-## self.rotation=rotation
-## self.spacingStyle=spacingStyle
-## self.spacingFactor=spacingFactor
-## self.style=style
-## self.width=width
-## self.xdirection=xdirection
-## def __str__(self):
-## input=self.text
-## text=''
-## while len(input)>250:
-## text+='\n3\n%s'%input[:250]
-## input=input[250:]
-## text+='\n1\n%s'%input
-## result= '0\nMTEXT\n%s\n%s\n40\n%s\n41\n%s\n71\n%s\n72\n%s%s\n43\n%s\n50\n%s'%\
-## (self._common(),_point(self.point),self.charHeight,self.width,
-## self.attachment,self.direction,text,
-## self.height,
-## self.rotation)
-## if self.style:result+='\n7\n%s'%self.style
-## if self.xdirection:result+='\n%s'%_point(self.xdirection,1)
-## if self.charWidth:result+='\n42\n%s'%self.charWidth
-## if self.spacingStyle:result+='\n73\n%s'%self.spacingStyle
-## if self.spacingFactor:result+='\n44\n%s'%self.spacingFactor
-## return result
-
-#---tables ---------------------------------------------------
-#-----------------------------------------------
-class Block(_Collection):
- """Use list methods to add entities, eg append."""
- def __init__(self,name,layer='0',flag=0,base=(0,0,0),entities=[]):
- self.entities=copy.copy(entities)
- _Collection.__init__(self,entities)
- self.layer=layer
- self.name=name
- self.flag=0
- self.base=base
- def __str__(self):
- e='\n'.join([str(x)for x in self.entities])
- return '0\nBLOCK\n8\n%s\n2\n%s\n70\n%s\n%s\n3\n%s\n%s\n0\nENDBLK'%\
- (self.layer,self.name.upper(),self.flag,_point(self.base),self.name.upper(),e)
-
-#-----------------------------------------------
-class Layer(_Call):
- """Layer"""
- def __init__(self,name='pydxf',color=7,lineType='continuous',flag=64):
- self.name=name
- self.color=color
- self.lineType=lineType
- self.flag=flag
- def __str__(self):
- return '0\nLAYER\n2\n%s\n70\n%s\n62\n%s\n6\n%s'%\
- (self.name.upper(),self.flag,self.color,self.lineType)
-
-#-----------------------------------------------
-class LineType(_Call):
- """Custom linetype"""
- def __init__(self,name='continuous',description='Solid line',elements=[],flag=64):
- # TODO: Implement lineType elements
- self.name=name
- self.description=description
- self.elements=copy.copy(elements)
- self.flag=flag
- def __str__(self):
- return '0\nLTYPE\n2\n%s\n70\n%s\n3\n%s\n72\n65\n73\n%s\n40\n0.0'%\
- (self.name.upper(),self.flag,self.description,len(self.elements))
-
-#-----------------------------------------------
-class Style(_Call):
- """Text style"""
- def __init__(self,name='standard',flag=0,height=0,widthFactor=40,obliqueAngle=50,
- mirror=0,lastHeight=1,font='arial.ttf',bigFont=''):
- self.name=name
- self.flag=flag
- self.height=height
- self.widthFactor=widthFactor
- self.obliqueAngle=obliqueAngle
- self.mirror=mirror
- self.lastHeight=lastHeight
- self.font=font
- self.bigFont=bigFont
- def __str__(self):
- return '0\nSTYLE\n2\n%s\n70\n%s\n40\n%s\n41\n%s\n50\n%s\n71\n%s\n42\n%s\n3\n%s\n4\n%s'%\
- (self.name.upper(),self.flag,self.flag,self.widthFactor,
- self.obliqueAngle,self.mirror,self.lastHeight,
- self.font.upper(),self.bigFont.upper())
-
-#-----------------------------------------------
-class View(_Call):
- def __init__(self,name,flag=0,width=1,height=1,center=(0.5,0.5),
- direction=(0,0,1),target=(0,0,0),lens=50,
- frontClipping=0,backClipping=0,twist=0,mode=0):
- self.name=name
- self.flag=flag
- self.width=width
- self.height=height
- self.center=center
- self.direction=direction
- self.target=target
- self.lens=lens
- self.frontClipping=frontClipping
- self.backClipping=backClipping
- self.twist=twist
- self.mode=mode
- def __str__(self):
- return '0\nVIEW\n2\n%s\n70\n%s\n40\n%s\n%s\n41\n%s\n%s\n%s\n42\n%s\n43\n%s\n44\n%s\n50\n%s\n71\n%s'%\
- (self.name,self.flag,self.height,_point(self.center),self.width,
- _point(self.direction,1),_point(self.target,2),self.lens,
- self.frontClipping,self.backClipping,self.twist,self.mode)
-
-#-----------------------------------------------
-def ViewByWindow(name,leftBottom=(0,0),rightTop=(1,1),**options):
- width=abs(rightTop[0]-leftBottom[0])
- height=abs(rightTop[1]-leftBottom[1])
- center=((rightTop[0]+leftBottom[0])*0.5,(rightTop[1]+leftBottom[1])*0.5)
- return View(name=name,width=width,height=height,center=center,**options)
-
-#---drawing
-#-----------------------------------------------
-class Drawing(_Collection):
- """Dxf drawing. Use append or any other list methods to add objects."""
- def __init__(self,insbase=(0.0,0.0,0.0),extmin=(0.0,0.0),extmax=(0.0,0.0),
- layers=[Layer()],linetypes=[LineType()],styles=[Style()],blocks=[],
- views=[],entities=None,fileName='test.dxf'):
- # TODO: replace list with None,arial
- if not entities:entities=[]
- _Collection.__init__(self,entities)
- self.insbase=insbase
- self.extmin=extmin
- self.extmax=extmax
- self.layers=copy.copy(layers)
- self.linetypes=copy.copy(linetypes)
- self.styles=copy.copy(styles)
- self.views=copy.copy(views)
- self.blocks=copy.copy(blocks)
- self.fileName=fileName
- #private
- #self.acadver='9\n$ACADVER\n1\nAC1006'
- self.acadver='9\n$ACADVER\n1\nAC1009'
- """DXF AutoCAD-Release format code
- AC1021 2008, 2007
- AC1018 2006, 2005, 2004
- AC1015 2002, 2000i, 2000
- AC1014 R14,14.01
- AC1012 R13
- AC1009 R12,11
- AC1006 R10
- AC1004 R9
- AC1002 R2.6
- AC1.50 R2.05
- """
-
- def _name(self,x):
- """Helper function for self._point"""
- return '9\n$%s'%x.upper()
-
- def _point(self,name,x):
- """Point setting from drawing like extmin,extmax,..."""
- return '%s\n%s'%(self._name(name),_point(x))
-
- def _section(self,name,x):
- """Sections like tables,blocks,entities,..."""
- if x:xstr='\n'+'\n'.join(x)
- else:xstr=''
- return '0\nSECTION\n2\n%s%s\n0\nENDSEC'%(name.upper(),xstr)
-
- def _table(self,name,x):
- """Tables like ltype,layer,style,..."""
- if x:xstr='\n'+'\n'.join(x)
- else:xstr=''
- return '0\nTABLE\n2\n%s\n70\n%s%s\n0\nENDTAB'%(name.upper(),len(x),xstr)
-
- def __str__(self):
- """Returns drawing as dxf string."""
- header=[self.acadver]+[self._point(attr,getattr(self,attr)) for attr in _HEADER_POINTS]
- header=self._section('header',header)
-
- tables=[self._table('ltype',[str(x) for x in self.linetypes]),
- self._table('layer',[str(x) for x in self.layers]),
- self._table('style',[str(x) for x in self.styles]),
- self._table('view',[str(x) for x in self.views]),
- ]
- tables=self._section('tables',tables)
-
- blocks=self._section('blocks',[str(x) for x in self.blocks])
-
- entities=self._section('entities',[str(x) for x in self.entities])
-
- all='\n'.join([header,tables,blocks,entities,'0\nEOF\n'])
- return all
-
- def saveas(self,fileName):
- self.fileName=fileName
- self.save()
-
- def save(self):
- test=open(self.fileName,'w')
- test.write(str(self))
- test.close()
-
-
-#---extras
-#-----------------------------------------------
-class Rectangle(_Entity):
- """Rectangle, creates lines."""
- def __init__(self,point=(0,0,0),width=1,height=1,solid=None,line=1,**common):
- _Entity.__init__(self,**common)
- self.point=point
- self.width=width
- self.height=height
- self.solid=solid
- self.line=line
- def __str__(self):
- result=''
- points=[self.point,(self.point[0]+self.width,self.point[1],self.point[2]),
- (self.point[0]+self.width,self.point[1]+self.height,self.point[2]),
- (self.point[0],self.point[1]+self.height,self.point[2]),self.point]
- if self.solid:
- result+='\n%s'%Solid(points=points[:-1],parent=self.solid)
- if self.line:
- for i in range(4):result+='\n%s'%\
- Line(points=[points[i],points[i+1]],parent=self)
- return result[1:]
-
-#-----------------------------------------------
-class LineList(_Entity):
- """Like polyline, but built of individual lines."""
- def __init__(self,points=[],org_point=[0,0,0],closed=0,**common):
- _Entity.__init__(self,**common)
- self.closed=closed
- self.points=copy.copy(points)
- def __str__(self):
- if self.closed:points=self.points+[self.points[0]]
- else: points=self.points
- result=''
- for i in range(len(points)-1):
- result+='\n%s' %Line(points=[points[i],points[i+1]],parent=self)
- return result[1:]
+#import dxfLibrary
+#reload(dxfLibrary)
+from dxfLibrary import *
+
+
+#-----------------------------------------------------
+def hidden_status(faces, mx_n):
+ #print 'HIDDEN_MODE: caution! not full implemented yet'
+ ok_faces = []
+ ok_edges = []
+ #sort out back-faces = with normals pointed away from camera
+ for f in faces:
+ #print 'deb: face=', f #---------
+ # get its normal-vector in localCS
+ vec_normal = f.no.copy()
+ #print 'deb: vec_normal=', vec_normal #------------------
+ #must be transfered to camera/view-CS
+ vec_normal *= mx_n
+ #vec_normal *= mb.rotationPart()
+ #print 'deb:2vec_normal=', vec_normal #------------------
+ #vec_normal *= mw0.rotationPart()
+ #print 'deb:3vec_normal=', vec_normal, '\n' #------------------
+
+ # normal must point the Z direction-hemisphere
+ if vec_normal[2] > 0.0 :
+ ok_faces.append(f.index)
+ for key in f.edge_keys:
+ #this test can be done faster with set()
+ if key not in ok_edges:
+ ok_edges.append(key)
+ #print 'deb: amount of visible faces=', len(ok_faces) #---------
+ #print 'deb: visible faces=', ok_faces #---------
+ #print 'deb: amount of visible edges=', len(ok_edges) #---------
+ #print 'deb: visible edges=', ok_edges #---------
+ return ok_faces, ok_edges
+
#-----------------------------------------------------
def projected_co(vec, mw):
- # convert the world coordinates of v to screen coordinates
+ # convert the world coordinates of vector to screen coordinates
#co = vec.co.copy().resize4D()
co = vec.copy().resize4D()
co[3] = 1.0
sc = co * mw
- #print 'viewprojection=', sc #---------
+ #print 'deb: viewprojection=', sc #---------
return [sc[0],sc[1],0.0]
+#--------not used---------------------------------------------
+def flatten(points, mw):
+ for i,v in enumerate(points):
+ v = projected_co(v, mw)
+ points[i]=v
+ #print 'deb: flatten points=', points #---------
+ return points
+
+#-----------------------------------------------------
+def exportMesh(ob, mx, mx_n):
+ entities = []
+ me = ob.getData(mesh=1)
+ #me.transform(mx)
+ # above is eventualy faster, but bad, cause
+ # directly transforms origin geometry and write back rounding errors
+ me_verts = me.verts[:] #we dont want manipulate origin data
+ #print 'deb: me_verts=', me_verts #---------
+ #me.transform(mx_inv) #counterpart to - back to the origin state
+ for v in me_verts:
+ v.co *= mx
+ faces=[]
+ edges=[]
+ if HIDDEN_MODE:
+ ok_faces, ok_edges = hidden_status(me.faces, mx_n)
+
+ #if (not FLATTEN) and len(me.faces)>0 and ONLYFACES:
+ if ONLYFACES:
+ if POLYFACES: #export 3D as POLYFACEs
+ allpoints = []
+ allfaces = []
+ allpoints = [v.co[:3] for v in me_verts]
+ for f in me.faces:
+ #print 'deb: face=', f #---------
+ if not HIDDEN_MODE or \
+ (HIDDEN_MODE and f.index in ok_faces):
+ if 1:
+ points = f.verts
+ face = [p.index+1 for p in points]
+ #print 'deb: face=', face #---------
+ allfaces.append(face)
+ else: #bad, cause create multiple vertex instances
+ points = f.verts
+ points = [ me_verts[p.index].co[:3] for p in points]
+ #points = [p.co[:3] for p in points]
+ #print 'deb: points=', points #---------
+ index = len(allpoints)+1
+ face = [index+i for i in range(len(points))]
+ allpoints.extend(points)
+ allfaces.append(face)
+ if allpoints and allfaces:
+ #print 'deb: allpoints=', allpoints #---------
+ #print 'deb: allfaces=', allfaces #---------
+ dxfPOLYFACE = PolyLine([allpoints, allfaces], flag=64)
+ entities.append(dxfPOLYFACE)
+ else: #export 3D as 3DFACEs
+ for f in me.faces:
+ #print 'deb: face=', f #---------
+ if not HIDDEN_MODE or \
+ (HIDDEN_MODE and f.index in ok_faces):
+ points = f.verts
+ points = [ me_verts[p.index].co[:3] for p in points]
+ #points = [p.co[:3] for p in points]
+ #print 'deb: points=', points #---------
+ dxfFACE = Face(points)
+ entities.append(dxfFACE)
+
+ else: #export 3D as LINEs
+ if HIDDEN_MODE and len(me.faces)!=0:
+ for e in ok_edges:
+ points = [ me_verts[key].co[:3] for key in e]
+ dxfLINE = Line(points)
+ entities.append(dxfLINE)
+
+ else:
+ for e in me.edges:
+ #print 'deb: edge=', e #---------
+ points=[]
+ #points = [e.v1.co*mx, e.v2.co*mx]
+ points = [ me_verts[key].co[:3] for key in e.key]
+ #print 'deb: points=', points #---------
+ dxfLINE = Line(points)
+ entities.append(dxfLINE)
+ return entities
+
+
+#-----------------------------------------------------
+def exportCurve(ob, mx):
+ entities = []
+ curve = ob.getData()
+ for cur in curve:
+ #print 'deb: START cur=', cur #--------------
+ if 1: #not cur.isNurb():
+ #print 'deb: START points' #--------------
+ points = []
+ org_point = [0.0,0.0,0.0]
+ for point in cur:
+ #print 'deb: point=', point #---------
+ if cur.isNurb():
+ vec = point[0:3]
+ else:
+ point = point.getTriple()
+ #print 'deb: point=', point #---------
+ vec = point[1]
+ #print 'deb: vec=', vec #---------
+ pkt = Mathutils.Vector(vec) * mx
+ #print 'deb: pkt=', pkt #---------
+ #pkt *= SCALE_FACTOR
+ if 0: #FLATTEN:
+ pkt = projected_co(pkt, mw)
+ points.append(pkt)
+ if cur.isCyclic(): closed = 1
+ else: closed = 0
+ if len(points)>1:
+ #print 'deb: points', points #--------------
+ if POLYLINES: dxfPLINE = PolyLine(points,org_point,closed)
+ else: dxfPLINE = LineList(points,org_point,closed)
+ entities.append(dxfPLINE)
+ return entities
+
+#-----------------------------------------------------
+def do_export(sel_group, filepath):
+ Window.WaitCursor(1)
+ t = sys.time()
+
+ #init Drawing ---------------------
+ d=Drawing()
+ #add Tables -----------------
+ #d.blocks.append(b) #table blocks
+ d.styles.append(Style()) #table styles
+ d.views.append(View('Normal')) #table view
+ d.views.append(ViewByWindow('Window',leftBottom=(1,0),rightTop=(2,1))) #idem
+
+ #add Entities --------------------
+ something_ready = False
+ #ViewVector = Mathutils.Vector(Window.GetViewVector())
+ #print 'deb: ViewVector=', ViewVector #------------------
+ mw0 = Window.GetViewMatrix()
+ #mw0 = Window.GetPerspMatrix() #TODO: how get it working?
+ mw = mw0.copy()
+ if FLATTEN:
+ m0 = Mathutils.Matrix()
+ m0[2][2]=0.0
+ mw *= m0 #flatten ViewMatrix
+
+ for ob in sel_group:
+ entities = []
+ mx = ob.matrix.copy()
+ mb = mx.copy()
+ #print 'deb: mb =\n', mb #---------
+ #print 'deb: mw0 =\n', mw0 #---------
+ mx_n = mx.rotationPart() * mw0.rotationPart() #trans-matrix for normal_vectors
+ if SCALE_FACTOR!=1.0: mx *= SCALE_FACTOR
+ if FLATTEN: mx *= mw
+
+ #mx_inv = mx.copy().invert()
+ #print 'deb: mx =\n', mx #---------
+ #print 'deb: mx_inv=\n', mx_inv #---------
+
+ if (ob.type == 'Mesh'):
+ entities = exportMesh(ob, mx, mx_n)
+ elif (ob.type == 'Curve'):
+ entities = exportCurve(ob, mx)
+
+ for e in entities:
+ d.append(e)
+ something_ready = True
+
+ if something_ready:
+ d.saveas(filepath)
+ Window.WaitCursor(0)
+ #Draw.PupMenu('DXF Exporter: job finished')
+ print 'exported to %s' % filepath
+ print 'finished in %.2f seconds' % (sys.time()-t)
+ else:
+ Window.WaitCursor(0)
+ print "Abort: selected objects dont mach choosen export option, nothing exported!"
+ Draw.PupMenu('DXF Exporter: nothing exported!|selected objects dont mach choosen export option!')
+
+#----globals------------------------------------------
+ONLYSELECTED = True
+POLYLINES = True
+ONLYFACES = False
+POLYFACES = 1
+FLATTEN = 0
+HIDDEN_MODE = False #filter out hidden lines
+SCALE_FACTOR = 1.0 #optional, can be done later in CAD too
+
+
+
#-----------------------------------------------------
def dxf_export_ui(filepath):
- print '\n\nDXF-Export %s' %__version__
+ global ONLYSELECTED,\
+ POLYLINES,\
+ ONLYFACES,\
+ POLYFACES,\
+ FLATTEN,\
+ HIDDEN_MODE,\
+ SCALE_FACTOR
+
+ print '\n\nDXF-Export %s -----------------------' %__version__
#filepath = 'blend_test.dxf'
# Dont overwrite
if not BPyMessages.Warning_SaveOver(filepath):
@@ -679,29 +344,28 @@ def dxf_export_ui(filepath):
return
#test():return
- ONLYSELECTED = True
- POLYLINES = True
- ONLYFACES = False
- FLATTEN = 0 #dimmensions:1,2,3. Force Z dimmension value to 0.0, equal ground projection
- SCALE_FACTOR = 1.0 #optional, can be done in CAD too
+
PREF_ONLYSELECTED= Draw.Create(ONLYSELECTED)
PREF_POLYLINES= Draw.Create(POLYLINES)
PREF_ONLYFACES= Draw.Create(ONLYFACES)
+ PREF_POLYFACES= Draw.Create(POLYFACES)
PREF_FLATTEN= Draw.Create(FLATTEN)
+ PREF_HIDDEN_MODE= Draw.Create(HIDDEN_MODE)
PREF_SCALE_FACTOR= Draw.Create(SCALE_FACTOR)
PREF_HELP= Draw.Create(0)
block = [\
("only selected", PREF_ONLYSELECTED, "export only selected geometry"),\
("global Scale:", PREF_SCALE_FACTOR, 0.001, 1000, "set global Scale factor for exporting geometry"),\
- ("only faces", PREF_ONLYFACES, "from mesh-objects export only faces, not edges"),\
- ("write POLYLINEs", PREF_POLYLINES, "export curves to POLYLINEs, otherwise to LINEs"),\
+ ("only faces", PREF_ONLYFACES, "from mesh-objects export only faces, otherwise only edges"),\
+ ("write POLYFACE", PREF_POLYFACES, "export mesh to POLYFACE, otherwise to 3DFACEs"),\
+ ("write POLYLINEs", PREF_POLYLINES, "export curve to POLYLINE, otherwise to LINEs"),\
("3D-View to Flat", PREF_FLATTEN, "flatten geometry according current 3d-View"),\
- (''),\
+ ("Hidden Mode", PREF_HIDDEN_MODE, "filter out hidden lines"),\
+ #(''),\
("online Help", PREF_HELP, "calls DXF-Exporter Manual Page on Wiki.Blender.org"),\
]
- if not Draw.PupBlock("DXF-Exporter %s" %__version__[:10], block):
- return
+ if not Draw.PupBlock("DXF-Exporter %s" %__version__[:10], block): return
if PREF_HELP.val!=0:
try:
@@ -715,139 +379,22 @@ http://wiki.blender.org/index.php?title=Scripts/Manual/Export/autodesk_dxf')
ONLYSELECTED = PREF_ONLYSELECTED.val
POLYLINES = PREF_POLYLINES.val
ONLYFACES = PREF_ONLYFACES.val
+ POLYFACES = PREF_POLYFACES.val
FLATTEN = PREF_FLATTEN.val
+ HIDDEN_MODE = PREF_HIDDEN_MODE.val
SCALE_FACTOR = PREF_SCALE_FACTOR.val
sce = Scene.GetCurrent()
if ONLYSELECTED: sel_group = sce.objects.selected
else: sel_group = sce.objects
- if sel_group:
- Window.WaitCursor(1)
- t = sys.time()
-
- #init Drawing ---------------------
- d=Drawing()
- #add Tables -----------------
- #d.blocks.append(b) #table blocks
- d.styles.append(Style()) #table styles
- d.views.append(View('Normal')) #table view
- d.views.append(ViewByWindow('Window',leftBottom=(1,0),rightTop=(2,1))) #idem
-
- #add Entities --------------------
- something_ready = False
- mw = Window.GetViewMatrix()
- #mw = Window.GetPerspMatrix() #TODO: how get it working?
- for ob in sel_group:
- entities = []
- mx = ob.matrix
- if (ob.type == 'Mesh'):
- me = ob.getData(mesh=1)
- faces=[]
- edges=[]
- if (not FLATTEN) and len(me.faces)>0 and ONLYFACES:
- #export 3D as 3DFACEs
- for f in me.faces:
- #print 'face=', f #---------
- verts = f.verts
- points = [verts[i].co*mx for i in range(len(verts))]
- if SCALE_FACTOR!=1.0:
- points = [p*SCALE_FACTOR for p in points]
- #print 'points=', points #---------
- dxfFACE = Face(points)
- entities.append(dxfFACE)
- else: #export 3D as LINEs
- for e in me.edges:
- #print 'edge=', e #---------
- points=[]
- points = [e.v1.co*mx, e.v2.co*mx]
- if SCALE_FACTOR!=1.0:
- points = [p*SCALE_FACTOR for p in points]
- if FLATTEN:
-# for p in points: p[FLATTEN-1]=0.0
- for i,v in enumerate(points):
- v = projected_co(v, mw)
- points[i]=v
- #print 'flatten points=', points #---------
- dxfLINE = Line(points)
- entities.append(dxfLINE)
- elif (ob.type == 'Curve'):
- curve = ob.getData()
- for cur in curve:
- #print 'deb: START cur=', cur #--------------
- if 1: #not cur.isNurb():
- #print 'deb: START points' #--------------
- points = []
- org_point = [0.0,0.0,0.0]
- for point in cur:
- #print 'point=', point #---------
- if cur.isNurb():
- vec = point[0:3]
- else:
- point = point.getTriple()
- #print 'point=', point #---------
- vec = point[1]
- #print 'vec=', vec #---------
- pkt = Mathutils.Vector(vec) * mx
- #print 'pkt=', pkt #---------
- pkt *= SCALE_FACTOR
- if FLATTEN:
- pkt = projected_co(pkt, mw)
- points.append(pkt)
- if cur.isCyclic(): closed = 1
- else: closed = 0
- if len(points)>1:
- #print 'deb: points', points #--------------
- if POLYLINES: dxfPLINE = PolyLine(points,org_point,closed)
- else: dxfPLINE = LineList(points,org_point,closed)
- entities.append(dxfPLINE)
- for e in entities:
- d.append(e)
- something_ready = True
- if something_ready:
- d.saveas(filepath)
- Window.WaitCursor(0)
- #Draw.PupMenu('DXF Exporter: job finished|search for blend_test.dxf in current project directory')
- print 'exported to %s' % filepath
- print 'finished in %.2f seconds' % (sys.time()-t)
- else:
- print "Abort: no supported object types selected, nothing exported!"
- Draw.PupMenu('DXF Exporter: Abort!|Not-supported object types selected.')
+ if sel_group: do_export(sel_group, filepath)
else:
print "Abort: selection was empty, no object to export!"
- Draw.PupMenu('DXF Exporter: Abort!|empty selection, no object to export!')
+ Draw.PupMenu('DXF Exporter: nothing exported!|empty selection!')
# Timing the script is a good way to be aware on any speed hits when scripting
-#-----------------------------------------------------
-def test():
- #Blocks
- b=Block('test')
- b.append(Solid(points=[(0,0,0),(1,0,0),(1,1,0),(0,1,0)],color=1))
- b.append(Arc(center=(1,0,0),color=2))
-
- #Drawing
- d=Drawing()
- #tables
- d.blocks.append(b) #table blocks
- d.styles.append(Style()) #table styles
- d.views.append(View('Normal')) #table view
- d.views.append(ViewByWindow('Window',leftBottom=(1,0),rightTop=(2,1))) #idem
-
- #entities
- d.append(Circle(center=(1,1,0),color=3))
- d.append(Face(points=[(0,0,0),(1,0,0),(1,1,0),(0,1,0)],color=4))
- d.append(Insert('test',point=(3,3,3),cols=5,colspacing=2))
- d.append(Line(points=[(0,0,0),(1,1,1)]))
- d.append(Mtext('Click on Ads\nmultiple lines with mtext',point=(1,1,1),color=5,rotation=90))
- d.append(Text('Please donate!',point=(3,0,1)))
- d.append(Rectangle(point=(2,2,2),width=4,height=3,color=6,solid=Solid(color=2)))
- d.append(Solid(points=[(4,4,0),(5,4,0),(7,8,0),(9,9,0)],color=3))
- d.append(PolyLine(points=[(1,1,1),(2,1,1),(2,2,1),(1,2,1)],closed=1,color=1))
-
- #d.saveas('c:\\test.dxf')
- d.saveas('test.dxf')
-
#-----------------------------------------------------
if __name__=='__main__':