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

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRemigiusz Fiedler <migius@gmx.net>2012-07-11 03:16:32 +0400
committerRemigiusz Fiedler <migius@gmx.net>2012-07-11 03:16:32 +0400
commit1dd571efee1758e622f48a42f46ce8dbc1a507af (patch)
tree061cd8c6d7d0ac5ebce89184d56a05cc650e56e2 /io_export_dxf/model
parent891ce0209b978ba8407bbb739e12db1562ea02b6 (diff)
DXF-exporter script moved from addons_contrib to official addons folder
Diffstat (limited to 'io_export_dxf/model')
-rw-r--r--io_export_dxf/model/__init__.py0
-rw-r--r--io_export_dxf/model/dxfLibrary.py927
-rw-r--r--io_export_dxf/model/migiusModel.py122
-rw-r--r--io_export_dxf/model/model.py38
4 files changed, 1087 insertions, 0 deletions
diff --git a/io_export_dxf/model/__init__.py b/io_export_dxf/model/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/io_export_dxf/model/__init__.py
diff --git a/io_export_dxf/model/dxfLibrary.py b/io_export_dxf/model/dxfLibrary.py
new file mode 100644
index 00000000..c1730d4d
--- /dev/null
+++ b/io_export_dxf/model/dxfLibrary.py
@@ -0,0 +1,927 @@
+#dxfLibrary.py : provides functions for generating DXF files
+# --------------------------------------------------------------------------
+__version__ = "v1.35 - 2010.06.23"
+__author__ = "Stani Michiels(Stani), Remigiusz Fiedler(migius)"
+__license__ = "GPL"
+__url__ = "http://wiki.blender.org/index.php/Extensions:2.4/Py/Scripts/Export/DXF"
+__bpydoc__ ="""The library to export geometry data to DXF format r12 version.
+
+Copyright %s
+Version %s
+License %s
+Homepage %s
+
+See the homepage for documentation.
+Dedicated thread on BlenderArtists: http://blenderartists.org/forum/showthread.php?t=136439
+
+IDEAs:
+-
+
+TODO:
+- add support for DXFr14 version (needs extended file header)
+- add support for DXF-SPLINEs (possible first in DXFr14 version)
+- add support for DXF-MTEXT
+- add user preset for floating point precision (3-16?)
+
+History
+v1.35 - 2010.06.23 by migius
+ - added (as default) writing to DXF file without RAM-buffering: faster and low-RAM-machines friendly
+v1.34 - 2010.06.20 by migius
+ - bugfix POLYFACE
+ - added DXF-flags for POLYLINE and VERTEX class (NURBS-export)
+v1.33 - 2009.07.03 by migius
+ - fix MTEXT newline bug (not supported by DXF-Exporter yet)
+ - modif _point(): converts all coords to floats
+ - modif LineType class: implement elements
+ - added VPORT class, incl. defaults
+ - fix Insert class
+v1.32 - 2009.06.06 by migius
+ - modif Style class: changed defaults to widthFactor=1.0, obliqueAngle=0.0
+ - modif Text class: alignment parameter reactivated
+v1.31 - 2009.06.02 by migius
+ - modif _Entity class: added paperspace,elevation
+v1.30 - 2009.05.28 by migius
+ - bugfix 3dPOLYLINE/POLYFACE: VERTEX needs x,y,z coordinates, index starts with 1 not 0
+v1.29 - 2008.12.28 by Yorik
+ - modif POLYLINE to support bulge segments
+v1.28 - 2008.12.13 by Steeve/BlenderArtists
+ - bugfix for EXTMIN/EXTMAX to suit Cycas-CAD
+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/2009 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"""
+ return '\n'.join([' %s\n%s'%((i+1)*10+index,float(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))])
+ 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,paperspace=None,color=None,layer='0',
+ lineType=None,lineTypeScale=None,lineWeight=None,
+ extrusion=None,elevation=None,thickness=None,
+ parent=None):
+ """None values will be omitted."""
+ self.paperspace = paperspace
+ self.color = color
+ self.layer = layer
+ self.lineType = lineType
+ self.lineTypeScale = lineTypeScale
+ self.lineWeight = lineWeight
+ self.extrusion = extrusion
+ self.elevation = elevation
+ self.thickness = thickness
+ #self.visible = visible
+ 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.paperspace==1: result+=' 67\n1\n'
+ if parent.layer!=None: result+=' 8\n%s\n'%parent.layer
+ if parent.color!=None: result+=' 62\n%s\n'%parent.color
+ if parent.lineType!=None: result+=' 6\n%s\n'%parent.lineType
+ # TODO: if parent.lineWeight!=None: result+='370\n%s\n'%parent.lineWeight
+ # TODO: if parent.visible!=None: result+='60\n%s\n'%parent.visible
+ if parent.lineTypeScale!=None: result+=' 48\n%s\n'%parent.lineTypeScale
+ if parent.elevation!=None: result+=' 38\n%s\n'%parent.elevation
+ if parent.thickness!=None: result+=' 39\n%s\n'%parent.thickness
+ if parent.extrusion!=None: result+='%s\n'%_point(parent.extrusion,200)
+ 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 flag 70
+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
+
+#---polyline flag 75, = curve type
+QUADRIC_NURBS = 5
+CUBIC_NURBS = 6
+BEZIER_CURVE = 8
+
+
+#---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)
+ while 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))
+ 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%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],flag70=0,flag75=0,width=None,**common):
+ #width = number, or width = list [width_start=None, width_end=None]
+ #for 2d-polyline: points = [ [[x, y, z], vflag=None, [width_start=None, width_end=None], bulge=0 or None] ...]
+ #for 3d-polyline: points = [ [[x, y, z], vflag=None], ...]
+ #for polyface: points = [points_list, faces_list]
+ _Entity.__init__(self,**common)
+ self.points=points
+ self.org_point=org_point
+ self.pflag70 = flag70
+ self.pflag75 = flag75
+ self.polyface = False
+ self.polyline2d = False
+ self.faces = [] # dummy value
+ self.width= None # dummy value
+ if self.pflag70 & POLYFACE_MESH:
+ self.polyface=True
+ self.points=points[0]
+ self.faces=points[1]
+ self.p_count=len(self.points)
+ self.f_count=len(self.faces)
+ elif not (self.pflag70 & POLYLINE_3D):
+ self.polyline2d = True
+ if width:
+ if type(width)!='list': width=[width,width]
+ self.width=width
+
+ def __str__(self):
+ result= ' 0\nPOLYLINE\n%s 70\n%s\n' %(self._common(),self.pflag70)
+ result+=' 66\n1\n'
+ result+='%s\n' %_point(self.org_point)
+ if self.polyface:
+ result+=' 71\n%s\n' %self.p_count
+ result+=' 72\n%s\n' %self.f_count
+ elif self.polyline2d:
+ if self.width!=None: result+=' 40\n%s\n 41\n%s\n' %(self.width[0],self.width[1])
+ if self.pflag75:
+ result+=' 75\n%s\n' %self.pflag75
+ for point in self.points:
+ result+=' 0\nVERTEX\n'
+ result+=' 8\n%s\n' %self.layer
+ if self.polyface:
+ result+='%s\n' %_point(point)
+ result+=' 70\n192\n'
+ elif self.polyline2d:
+ result+='%s\n' %_point(point[0])
+ flag = point[1]
+ if len(point)>2:
+ [width1, width2] = point[2]
+ if width1!=None: result+=' 40\n%s\n' %width1
+ if width2!=None: result+=' 41\n%s\n' %width2
+ if len(point)==4:
+ bulge = point[3]
+ if bulge: result+=' 42\n%s\n' %bulge
+ if flag:
+ result+=' 70\n%s\n' %flag
+ else:
+ result+='%s\n' %_point(point[0])
+ flag = point[1]
+ if flag:
+ result+=' 70\n%s\n' %flag
+
+ 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):
+ """Point."""
+ def __init__(self,points=None,**common):
+ _Entity.__init__(self,**common)
+ self.points=points
+ def __str__(self): # TODO:
+ return ' 0\nPOINT\n%s%s\n' %(self._common(),
+ _points(self.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
+ 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' %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): # TODO:
+ 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=[0.0],flag=0):
+ self.name=name
+ self.description=description
+ self.elements=copy.copy(elements)
+ self.flag=flag
+ def __str__(self):
+ result = ' 0\nLTYPE\n 2\n%s\n 70\n%s\n 3\n%s\n 72\n65\n'%\
+ (self.name.upper(),self.flag,self.description)
+ if self.elements:
+ elements = ' 73\n%s\n' %(len(self.elements)-1)
+ elements += ' 40\n%s\n' %(self.elements[0])
+ for e in self.elements[1:]:
+ elements += ' 49\n%s\n' %e
+ result += elements
+ return result
+
+
+#-----------------------------------------------
+class Style(_Call):
+ """Text style"""
+ def __init__(self,name='standard',flag=0,height=0,widthFactor=1.0,obliqueAngle=0.0,
+ 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 VPort(_Call):
+ def __init__(self,name,flag=0,
+ leftBottom=(0.0,0.0),
+ rightTop=(1.0,1.0),
+ center=(0.5,0.5),
+ snap_base=(0.0,0.0),
+ snap_spacing=(0.1,0.1),
+ grid_spacing=(0.1,0.1),
+ direction=(0.0,0.0,1.0),
+ target=(0.0,0.0,0.0),
+ height=1.0,
+ ratio=1.0,
+ lens=50.0,
+ frontClipping=0.0,
+ backClipping=0.0,
+ snap_rotation=0.0,
+ twist=0.0,
+ mode=0,
+ circle_zoom=100,
+ fast_zoom=1,
+ ucsicon=1,
+ snap_on=0,
+ grid_on=0,
+ snap_style=0,
+ snap_isopair=0
+ ):
+ self.name=name
+ self.flag=flag
+ self.leftBottom=leftBottom
+ self.rightTop=rightTop
+ self.center=center
+ self.snap_base=snap_base
+ self.snap_spacing=snap_spacing
+ self.grid_spacing=grid_spacing
+ self.direction=direction
+ self.target=target
+ self.height=float(height)
+ self.ratio=float(ratio)
+ self.lens=float(lens)
+ self.frontClipping=float(frontClipping)
+ self.backClipping=float(backClipping)
+ self.snap_rotation=float(snap_rotation)
+ self.twist=float(twist)
+ self.mode=mode
+ self.circle_zoom=circle_zoom
+ self.fast_zoom=fast_zoom
+ self.ucsicon=ucsicon
+ self.snap_on=snap_on
+ self.grid_on=grid_on
+ self.snap_style=snap_style
+ self.snap_isopair=snap_isopair
+ def __str__(self):
+ output = [' 0', 'VPORT',
+ ' 2', self.name,
+ ' 70', self.flag,
+ _point(self.leftBottom),
+ _point(self.rightTop,1),
+ _point(self.center,2), # View center point (in DCS)
+ _point(self.snap_base,3),
+ _point(self.snap_spacing,4),
+ _point(self.grid_spacing,5),
+ _point(self.direction,6), #view direction from target (in WCS)
+ _point(self.target,7),
+ ' 40', self.height,
+ ' 41', self.ratio,
+ ' 42', self.lens,
+ ' 43', self.frontClipping,
+ ' 44', self.backClipping,
+ ' 50', self.snap_rotation,
+ ' 51', self.twist,
+ ' 71', self.mode,
+ ' 72', self.circle_zoom,
+ ' 73', self.fast_zoom,
+ ' 74', self.ucsicon,
+ ' 75', self.snap_on,
+ ' 76', self.grid_on,
+ ' 77', self.snap_style,
+ ' 78', self.snap_isopair
+ ]
+
+ output_str = ''
+ for s in output:
+ output_str += '%s\n' %s
+ return output_str
+
+
+
+#-----------------------------------------------
+class View(_Call):
+ def __init__(self,name,flag=0,
+ width=1.0,
+ height=1.0,
+ center=(0.5,0.5),
+ direction=(0.0,0.0,1.0),
+ target=(0.0,0.0,0.0),
+ lens=50.0,
+ frontClipping=0.0,
+ backClipping=0.0,
+ twist=0.0,mode=0
+ ):
+ self.name=name
+ self.flag=flag
+ self.width=float(width)
+ self.height=float(height)
+ self.center=center
+ self.direction=direction
+ self.target=target
+ self.lens=float(lens)
+ self.frontClipping=float(frontClipping)
+ self.backClipping=float(backClipping)
+ self.twist=float(twist)
+ self.mode=mode
+ def __str__(self):
+ output = [' 0', 'VIEW',
+ ' 2', self.name,
+ ' 70', self.flag,
+ ' 40', self.height,
+ _point(self.center),
+ ' 41', self.width,
+ _point(self.direction,1),
+ _point(self.target,2),
+ ' 42', self.lens,
+ ' 43', self.frontClipping,
+ ' 44', self.backClipping,
+ ' 50', self.twist,
+ ' 71', self.mode
+ ]
+ output_str = ''
+ for s in output:
+ output_str += '%s\n' %s
+ return output_str
+
+#-----------------------------------------------
+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,0.0),extmax=(0.0,0.0,0.0),
+ layers=[Layer()],linetypes=[LineType()],styles=[Style()],blocks=[],
+ views=[],vports=[],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.vports=copy.copy(vports)
+ self.blocks=copy.copy(blocks)
+ self.fileName=fileName
+ #print 'deb: blocks=',blocks #----------
+ #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('vport',[str(x) for x in self.vports]),
+ 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 _write_section(self,file,name,data):
+ file.write(' 0\nSECTION\n 2\n%s\n'%name.upper())
+ for x in data:
+ file.write(str(x))
+ file.write(' 0\nENDSEC\n')
+
+ def saveas(self,fileName,buffer=0):
+ """Writes DXF file. Needs target file name. If optional parameter buffer>0, then switch to old behavior: store entire output string in RAM.
+ """
+ self.fileName=fileName
+ if buffer: self.save()
+ else: self.export()
+
+ def save(self):
+ outfile=open(self.fileName,'w')
+ outfile.write(str(self))
+ outfile.close()
+
+ def export(self):
+ outfile=open(self.fileName,'w')
+ header=[self.acadver]+[self._point(attr,getattr(self,attr))+'\n' for attr in _HEADER_POINTS]
+ self._write_section(outfile,'header',header)
+ tables=[self._table('vport',[str(x) for x in self.vports]),
+ 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]),
+ ]
+ self._write_section(outfile,'tables',tables)
+ self._write_section(outfile,'blocks',self.blocks)
+ self._write_section(outfile,'entities',self.entities)
+ outfile.write(' 0\nEOF\n')
+ outfile.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][0],points[i+1][0]],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)],flag=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')
+ else: test()
+
diff --git a/io_export_dxf/model/migiusModel.py b/io_export_dxf/model/migiusModel.py
new file mode 100644
index 00000000..a1e8b830
--- /dev/null
+++ b/io_export_dxf/model/migiusModel.py
@@ -0,0 +1,122 @@
+"""
+Created on Sep 2, 2011
+
+@author: vencax
+"""
+
+from .model import DxfDrawing
+
+try:
+ from . import dxfLibrary as DXF
+ #reload(DXF)
+ #reload(dxfLibrary)
+ #from dxfLibrary import *
+except Exception:
+ raise Exception("No dxfLibrary.py module in Blender script folder found!")
+
+#------------------------------------------------------
+#def col2RGB(color):
+# return [int(floor(255*color[0])),
+# int(floor(255*color[1])),
+# int(floor(255*color[2]))]
+#
+#global dxfColors
+#dxfColors=None
+#
+##------------------------------------------------------
+#def col2DXF(rgbcolor):
+# global dxfColors
+# if dxfColors is None:
+# from dxfColorMap import color_map
+# dxfColors = [(tuple(color),idx) for idx, color in color_map.iteritems()]
+# dxfColors.sort()
+# entry = (tuple(rgbcolor), -1)
+# dxfColors.append(entry)
+# dxfColors.sort()
+# i = dxfColors.index(entry)
+# dxfColors.pop(i)
+# return dxfColors[i-1][1]
+
+"""
+v = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,\
+28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,46,47,58,59,60,61,62,63,64,91,92,93,94,96,\
+123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,\
+151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,\
+171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,\
+191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,\
+211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,\
+231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254]
+invalid = ''.join([chr(i) for i in v])
+del v, i
+"""
+#TODO: validDXFr14 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.'
+validDXFr12 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_'
+NAMELENGTH_MAX = 80 #max_obnamelength in DXF, (limited to 256? )
+#------------------------------------------------------
+def cleanName(name, valid):
+ validname = ''
+ for ch in name:
+ if ch not in valid: ch = '_'
+ validname += ch
+ return validname
+
+#------------------------------------------------------
+def validDXFr12name(str_name):
+ dxfname = str(str_name)
+ dxfname = dxfname[:NAMELENGTH_MAX].upper()
+ dxfname = cleanName(dxfname, validDXFr12)
+ return dxfname
+
+class MigiusDXFLibDrawing(DxfDrawing):
+ """ Drawing that can convert itself into MIGIUS DXFLib stuff objects """
+
+ def convert(self, file, **kwargs):
+ drawing = self._write()
+ for type, ents in self._entities.items():
+ self._processEntityArray(drawing, type, ents)
+ for v in self._views:
+ drawing.views.append(DXF.View(**v))
+ for v in self._vports:
+ drawing.vports.append(DXF.VPort(**v))
+# for l in self._layers:
+ drawing.saveas(file)
+
+ def _write(self):
+ # init Drawing ---------------------
+ d=DXF.Drawing()
+ # add Tables -----------------
+ # initialized automatic: d.blocks.append(b) #section BLOCKS
+ # initialized automatic: d.styles.append(DXF.Style()) #table STYLE
+
+ #table LTYPE ---------------
+ #d.linetypes.append(DXF.LineType(name='CONTINUOUS',description='--------',elements=[0.0]))
+ d.linetypes.append(DXF.LineType(name='DOT',description='. . . . . . .',elements=[0.25, 0.0, -0.25]))
+ d.linetypes.append(DXF.LineType(name='DASHED',description='__ __ __ __ __',elements=[0.8, 0.5, -0.3]))
+ d.linetypes.append(DXF.LineType(name='DASHDOT',description='__ . __ . __ .',elements=[1.0, 0.5, -0.25, 0.0, -0.25]))
+ d.linetypes.append(DXF.LineType(name='DIVIDE',description='____ . . ____ . . ',elements=[1.25, 0.5, -0.25, 0.0, -0.25, 0.0, -0.25]))
+ d.linetypes.append(DXF.LineType(name='BORDER',description='__ __ . __ __ . ',elements=[1.75, 0.5, -0.25, 0.5, -0.25, 0.0, -0.25]))
+ d.linetypes.append(DXF.LineType(name='HIDDEN',description='__ __ __ __ __',elements=[0.4, 0.25, -0.25]))
+ d.linetypes.append(DXF.LineType(name='CENTER',description='____ _ ____ _ __',elements=[2.0, 1.25, -0.25, 0.25, -0.25]))
+
+ #d.vports.append(DXF.VPort('*ACTIVE'))
+ d.vports.append(DXF.VPort('*ACTIVE',center=(-5.0,1.0),height=10.0))
+ #d.vports.append(DXF.VPort('*ACTIVE',leftBottom=(-100.0,-60.0),rightTop=(100.0,60.0)))
+ #d.views.append(DXF.View('Normal')) #table view
+ d.views.append(DXF.ViewByWindow('BF_TOPVIEW',leftBottom=(-100,-60),rightTop=(100,60))) #idem
+
+ return d
+
+ def _processEntityArray(self, drawing, type, ents):
+ if type=='Point':
+ for e in ents:
+ drawing.append(DXF.Point(**e))
+ elif type=='Line':
+ for e in ents:
+ drawing.append(DXF.Line(**e))
+ elif type=='PolyLine':
+ for e in ents:
+ drawing.append(DXF.PolyLine(**e))
+ elif type=='Face':
+ for e in ents:
+ drawing.append(DXF.Face(**e))
+
diff --git a/io_export_dxf/model/model.py b/io_export_dxf/model/model.py
new file mode 100644
index 00000000..bff37339
--- /dev/null
+++ b/io_export_dxf/model/model.py
@@ -0,0 +1,38 @@
+
+class DxfDrawing(object):
+ """
+ Represents intermediate model of DXF drawing. It is useful in iterating
+ through exported object and for easy change the DXF handling library.
+ """
+ def __init__(self):
+ self._entities = {}
+ self._layers = {}
+ self._views = []
+ self._vports = []
+ self._blocks = []
+
+ def isEmpty(self):
+ return len(self._entities) == 0
+
+ def addEntity(self, type, **kwargs):
+ if type not in self._entities:
+ self._entities[type] = []
+ self._entities[type].append(kwargs)
+
+ def addLayer(self, name, color):
+ self._layers[name] = color
+
+ def containsLayer(self, name):
+ return name in self._layers
+
+ def addBlock(self, block):
+ self._blocks.append(block)
+
+ def containsBlock(self, blockname):
+ return blockname in self._blocks
+
+ def convert(self, **kwargs):
+ """ Converts this drawing into DXF representation object """
+ raise NotImplementedError()
+
+