2008-10-07 20:34:24 +00:00
#dxfLibrary.py : provides functions for generating DXF files
# --------------------------------------------------------------------------
2009-06-16 10:43:43 +00:00
__version__ = " v1.33 - 2009.06.16 "
2008-12-14 21:26:24 +00:00
__author__ = " Stani Michiels(Stani), Remigiusz Fiedler(migius) "
2008-10-07 20:34:24 +00:00
__license__ = " GPL "
2008-12-14 21:26:24 +00:00
__url__ = " http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_dxf "
__bpydoc__ = """ The library to export geometry data to DXF format r12 version.
2008-10-07 20:34:24 +00:00
Copyright % s
Version % s
License % s
Homepage % s
See the homepage for documentation .
2008-12-14 21:26:24 +00:00
Dedicated thread on BlenderArtists : http : / / blenderartists . org / forum / showthread . php ? t = 136439
2008-10-07 20:34:24 +00:00
IDEAs :
-
2008-12-14 21:26:24 +00:00
2008-10-07 20:34:24 +00:00
TODO :
2009-06-04 19:49:19 +00:00
- add support for DXFr14 ( needs extended file header )
- add support for SPLINEs ( possible first in DXFr14 version )
2009-06-16 10:43:43 +00:00
- add user preset for floating point precision ( 3 - 16 ? )
2008-10-07 20:34:24 +00:00
History
2009-06-16 10:43:43 +00:00
v1 .33 - 2009.06 .16 by migius
- modif _point ( ) : converts all coords to floats
- modif LineType class : implement elements
- added VPORT class , incl . defaults
- fix Insert class
2009-06-06 10:33:10 +00:00
v1 .32 - 2009.06 .06 by migius
2009-06-06 13:24:06 +00:00
- modif Style class : changed defaults to widthFactor = 1.0 , obliqueAngle = 0.0
2009-06-06 10:33:10 +00:00
- modif Text class : alignment parameter reactivated
2009-06-04 19:49:19 +00:00
v1 .31 - 2009.06 .02 by migius
- modif _Entity class : added paperspace , elevation
2009-05-29 06:50:31 +00:00
v1 .30 - 2009.05 .28 by migius
2009-06-04 19:49:19 +00:00
- bugfix 3 dPOLYLINE / POLYFACE : VERTEX needs x , y , z coordinates , index starts with 1 not 0
2009-04-14 23:57:14 +00:00
v1 .29 - 2008.12 .28 by Yorik
2009-06-04 19:49:19 +00:00
- modif POLYLINE to support bulge segments
2008-12-14 21:26:24 +00:00
v1 .28 - 2008.12 .13 by Steeve / BlenderArtists
2009-06-04 19:49:19 +00:00
- bugfix for EXTMIN / EXTMAX to suit Cycas - CAD
2008-10-07 20:34:24 +00:00
v1 .27 - 2008.10 .07 by migius
2009-06-04 19:49:19 +00:00
- beautifying output code : keys whitespace prefix
- refactoring DXF - strings format : NewLine moved to the end of
2008-10-07 20:34:24 +00:00
v1 .26 - 2008.10 .05 by migius
2009-06-04 19:49:19 +00:00
- modif POLYLINE to support POLYFACE
2008-10-07 20:34:24 +00:00
v1 .25 - 2008.09 .28 by migius
2009-06-04 19:49:19 +00:00
- modif FACE class for r12
2008-10-07 20:34:24 +00:00
v1 .24 - 2008.09 .27 by migius
2009-06-04 19:49:19 +00:00
- modif POLYLINE class for r12
- changing output format from r9 to r12 ( AC1009 )
2008-10-07 20:34:24 +00:00
v1 .1 ( 20 / 6 / 2005 ) by www . stani . be / python / sdxf
2009-06-04 19:49:19 +00:00
- Python library to generate dxf drawings
2008-10-07 20:34:24 +00:00
______________________________________________________________
""" % (__author__,__version__,__license__,__url__)
# --------------------------------------------------------------------------
# DXF Library: copyright (C) 2005 by Stani Michiels (AKA Stani)
2009-05-29 06:50:31 +00:00
# 2008/2009 modif by Remigiusz Fiedler (AKA migius)
2008-10-07 20:34:24 +00:00
# --------------------------------------------------------------------------
# ***** 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 #-------------
2009-06-16 10:43:43 +00:00
return ' \n ' . join ( [ ' %s \n %s ' % ( ( i + 1 ) * 10 + index , float ( x [ i ] ) ) for i in range ( len ( x ) ) ] )
2008-10-07 20:34:24 +00:00
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. """
2009-06-04 19:49:19 +00:00
def __init__ ( self , paperspace = None , color = None , layer = ' 0 ' ,
2008-10-07 20:34:24 +00:00
lineType = None , lineTypeScale = None , lineWeight = None ,
2009-06-04 19:49:19 +00:00
extrusion = None , elevation = None , thickness = None ,
parent = None ) :
2008-10-07 20:34:24 +00:00
""" None values will be omitted. """
2009-06-04 19:49:19 +00:00
self . paperspace = paperspace
2008-10-07 20:34:24 +00:00
self . color = color
self . layer = layer
self . lineType = lineType
self . lineTypeScale = lineTypeScale
self . lineWeight = lineWeight
2009-06-04 19:49:19 +00:00
self . extrusion = extrusion
self . elevation = elevation
2008-10-07 20:34:24 +00:00
self . thickness = thickness
2009-06-04 19:49:19 +00:00
#self.visible = visible
2008-10-07 20:34:24 +00:00
self . parent = parent
def _common ( self ) :
""" Return common group codes as a string. """
if self . parent : parent = self . parent
else : parent = self
result = ' '
2009-06-04 19:49:19 +00:00
if parent . paperspace == 1 : result + = ' 67 \n 1 \n '
2008-10-07 20:34:24 +00:00
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
2009-06-16 10:43:43 +00:00
# TODO: if parent.lineWeight!=None: result+='370\n%s\n'%parent.lineWeight
# TODO: if parent.visible!=None: result+='60\n%s\n'%parent.visible
2008-10-07 20:34:24 +00:00
if parent . lineTypeScale != None : result + = ' 48 \n %s \n ' % parent . lineTypeScale
2009-06-04 19:49:19 +00:00
if parent . elevation != None : result + = ' 38 \n %s \n ' % parent . elevation
2008-10-07 20:34:24 +00:00
if parent . thickness != None : result + = ' 39 \n %s \n ' % parent . thickness
2009-06-04 19:49:19 +00:00
if parent . extrusion != None : result + = ' %s \n ' % _point ( parent . extrusion , 200 )
2008-10-07 20:34:24 +00:00
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):
2008-12-14 21:26:24 +00:00
ANONYMOUS = 1 # This is an anonymous block generated by hatching, associative dimensioning, other internal operations, or an application
2008-10-07 20:34:24 +00:00
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)
2008-12-14 21:26:24 +00:00
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)
2008-10-07 20:34:24 +00:00
#---mtext flags
#attachment point
2008-12-14 21:26:24 +00:00
TOP_LEFT = 1
TOP_CENTER = 2
TOP_RIGHT = 3
MIDDLE_LEFT = 4
MIDDLE_CENTER = 5
2008-10-07 20:34:24 +00:00
MIDDLE_RIGHT = 6
2008-12-14 21:26:24 +00:00
BOTTOM_LEFT = 7
BOTTOM_CENTER = 8
BOTTOM_RIGHT = 9
2008-10-07 20:34:24 +00:00
#drawing direction
2008-12-14 21:26:24 +00:00
LEFT_RIGHT = 1
TOP_BOTTOM = 3
BY_STYLE = 5 #the flow direction is inherited from the associated text style
2008-10-07 20:34:24 +00:00
#line spacing style (optional):
2008-12-14 21:26:24 +00:00
AT_LEAST = 1 #taller characters will override
EXACT = 2 #taller characters will not override
2008-10-07 20:34:24 +00:00
#---polyline flags
2008-12-14 21:26:24 +00:00
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
2008-10-07 20:34:24 +00:00
#---text flags
#horizontal
2008-12-14 21:26:24 +00:00
LEFT = 0
CENTER = 1
RIGHT = 2
ALIGNED = 3 #if vertical alignment = 0
MIDDLE = 4 #if vertical alignment = 0
FIT = 5 #if vertical alignment = 0
2008-10-07 20:34:24 +00:00
#vertical
2008-12-14 21:26:24 +00:00
BASELINE = 0
BOTTOM = 1
MIDDLE = 2
TOP = 3
2008-10-07 20:34:24 +00:00
####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 \n ARC \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 \n CIRCLE \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 )
2008-12-14 21:26:24 +00:00
while len ( points ) < 4 : #fix for r12 format
2008-10-07 20:34:24 +00:00
points . append ( points [ - 1 ] )
self . points = points
def __str__ ( self ) :
out = ' 0 \n 3DFACE \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 ) :
2009-06-16 10:43:43 +00:00
result = ' 0 \n INSERT \n 2 \n %s \n %s %s \n ' % \
2008-10-07 20:34:24 +00:00
( 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 \n LINE \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 ) :
2009-04-14 23:57:14 +00:00
#width = number, or width = list [width_start=None, width_end=None]
#for 2d-polyline: points = [ [x, y, z, width_start=None, width_end=None, bulge=0 or None], ...]
#for 3d-polyline: points = [ [x, y, z], ...]
#for polyface: points = [points_list, faces_list]
2008-10-07 20:34:24 +00:00
_Entity . __init__ ( self , * * common )
self . points = points
self . org_point = org_point
self . flag = flag
2009-05-06 02:19:16 +00:00
self . polyface = False
self . polyline2d = False
self . faces = [ ] # dummy value
self . width = None # dummy value
2009-04-14 23:57:14 +00:00
if self . flag & POLYFACE_MESH :
self . polyface = True
2008-10-07 20:34:24 +00:00
self . points = points [ 0 ]
self . faces = points [ 1 ]
self . p_count = len ( self . points )
self . f_count = len ( self . faces )
2009-04-14 23:57:14 +00:00
elif not self . flag & POLYLINE_3D :
self . polyline2d = True
if width :
if type ( width ) != ' list ' :
width = [ width , width ]
self . width = width
2008-10-07 20:34:24 +00:00
def __str__ ( self ) :
result = ' 0 \n POLYLINE \n %s 70 \n %s \n ' % ( self . _common ( ) , self . flag )
result + = ' 66 \n 1 \n '
result + = ' %s \n ' % _point ( self . org_point )
2009-04-14 23:57:14 +00:00
if self . polyface :
2008-10-07 20:34:24 +00:00
result + = ' 71 \n %s \n ' % self . p_count
result + = ' 72 \n %s \n ' % self . f_count
2009-04-14 23:57:14 +00:00
elif self . polyline2d :
2009-05-06 02:19:16 +00:00
if self . width != None : result + = ' 40 \n %s \n 41 \n %s \n ' % ( self . width [ 0 ] , self . width [ 1 ] )
2008-10-07 20:34:24 +00:00
for point in self . points :
result + = ' 0 \n VERTEX \n '
result + = ' 8 \n %s \n ' % self . layer
2009-04-14 23:57:14 +00:00
if self . polyface :
2009-05-29 06:50:31 +00:00
result + = ' %s \n ' % _point ( point [ 0 : 3 ] )
2009-04-14 23:57:14 +00:00
result + = ' 70 \n 192 \n '
elif self . polyline2d :
2009-05-29 06:50:31 +00:00
result + = ' %s \n ' % _point ( point [ 0 : 2 ] )
2009-04-14 23:57:14 +00:00
if len ( point ) > 4 :
width1 , width2 = point [ 3 ] , point [ 4 ]
if width1 != None : result + = ' 40 \n %s \n ' % width1
if width2 != None : result + = ' 41 \n %s \n ' % width2
if len ( point ) == 6 :
bulge = point [ 5 ]
if bulge : result + = ' 42 \n %s \n ' % bulge
2009-05-29 06:50:31 +00:00
else :
result + = ' %s \n ' % _point ( point [ 0 : 3 ] )
2009-04-14 23:57:14 +00:00
for face in self . faces :
result + = ' 0 \n VERTEX \n '
result + = ' 8 \n %s \n ' % self . layer
result + = ' %s \n ' % _point ( self . org_point )
result + = ' 70 \n 128 \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 ]
2008-10-07 20:34:24 +00:00
result + = ' 0 \n SEQEND \n '
result + = ' 8 \n %s \n ' % self . layer
return result
#-----------------------------------------------
class Point ( _Entity ) :
2008-12-14 21:26:24 +00:00
""" Point. """
2008-10-07 20:34:24 +00:00
def __init__ ( self , points = None , * * common ) :
_Entity . __init__ ( self , * * common )
self . points = points
2009-06-16 10:43:43 +00:00
def __str__ ( self ) : # TODO:
2008-12-14 21:26:24 +00:00
return ' 0 \n POINT \n %s %s \n ' % ( self . _common ( ) ,
_points ( self . points )
)
2008-10-07 20:34:24 +00:00
#-----------------------------------------------
class Solid ( _Entity ) :
""" Colored solid fill. """
def __init__ ( self , points = None , * * common ) :
_Entity . __init__ ( self , * * common )
self . points = points
def __str__ ( self ) :
return ' 0 \n SOLID \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 \n TEXT \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
2009-06-06 10:33:10 +00:00
if self . alignment : result + = ' %s \n ' % _point ( self . alignment , 1 )
2008-10-07 20:34:24 +00:00
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
2009-06-16 10:43:43 +00:00
def __str__ ( self ) : # TODO:
2008-10-07 20:34:24 +00:00
e = ' ' . join ( [ str ( x ) for x in self . entities ] )
return ' 0 \n BLOCK \n 8 \n %s \n 2 \n %s \n 70 \n %s \n %s \n 3 \n %s \n %s 0 \n ENDBLK \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 \n LAYER \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 """
2009-06-16 10:43:43 +00:00
def __init__ ( self , name = ' CONTINUOUS ' , description = ' Solid line ' , elements = [ 0.0 ] , flag = 0 ) :
2008-10-07 20:34:24 +00:00
self . name = name
self . description = description
self . elements = copy . copy ( elements )
self . flag = flag
def __str__ ( self ) :
2009-06-16 10:43:43 +00:00
result = ' 0 \n LTYPE \n 2 \n %s \n 70 \n %s \n 3 \n %s \n 72 \n 65 \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
2008-10-07 20:34:24 +00:00
#-----------------------------------------------
class Style ( _Call ) :
""" Text style """
2009-06-06 13:24:06 +00:00
def __init__ ( self , name = ' standard ' , flag = 0 , height = 0 , widthFactor = 1.0 , obliqueAngle = 0.0 ,
2008-10-07 20:34:24 +00:00
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 \n STYLE \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 ( ) )
2009-06-16 10:43:43 +00:00
#-----------------------------------------------
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 ,
frontClipping = 0 ,
backClipping = 0 ,
snap_rotation = 0 ,
twist = 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
2008-10-07 20:34:24 +00:00
#-----------------------------------------------
class View ( _Call ) :
2009-06-16 10:43:43 +00:00
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
) :
2008-10-07 20:34:24 +00:00
self . name = name
self . flag = flag
2009-06-16 10:43:43 +00:00
self . width = float ( width )
self . height = float ( height )
2008-10-07 20:34:24 +00:00
self . center = center
self . direction = direction
self . target = target
2009-06-16 10:43:43 +00:00
self . lens = float ( lens )
self . frontClipping = float ( frontClipping )
self . backClipping = float ( backClipping )
self . twist = float ( twist )
2008-10-07 20:34:24 +00:00
self . mode = mode
def __str__ ( self ) :
2009-06-16 10:43:43 +00:00
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
2008-10-07 20:34:24 +00:00
#-----------------------------------------------
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. """
2008-12-14 21:26:24 +00:00
def __init__ ( self , insbase = ( 0.0 , 0.0 , 0.0 ) , extmin = ( 0.0 , 0.0 , 0.0 ) , extmax = ( 0.0 , 0.0 , 0.0 ) ,
2008-10-07 20:34:24 +00:00
layers = [ Layer ( ) ] , linetypes = [ LineType ( ) ] , styles = [ Style ( ) ] , blocks = [ ] ,
2009-06-16 10:43:43 +00:00
views = [ ] , vports = [ ] , entities = None , fileName = ' test.dxf ' ) :
2008-10-07 20:34:24 +00:00
# TODO: replace list with None,arial
2008-12-14 21:26:24 +00:00
if not entities :
entities = [ ]
2008-10-07 20:34:24 +00:00
_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 )
2009-06-16 10:43:43 +00:00
self . vports = copy . copy ( vports )
2008-10-07 20:34:24 +00:00
self . blocks = copy . copy ( blocks )
self . fileName = fileName
#private
#self.acadver='9\n$ACADVER\n1\nAC1006\n'
self . acadver = ' 9 \n $ACADVER \n 1 \n AC1009 \n '
""" DXF AutoCAD-Release format codes
AC1021 2008 , 2007
AC1018 2006 , 2005 , 2004
AC1015 2002 , 2000 i , 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 \n SECTION \n 2 \n %s \n %s 0 \n ENDSEC \n ' % ( name . upper ( ) , xstr )
def _table ( self , name , x ) :
""" Tables like ltype,layer,style,... """
if x : xstr = ' ' . join ( x )
else : xstr = ' '
return ' 0 \n TABLE \n 2 \n %s \n 70 \n %s \n %s 0 \n ENDTAB \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 )
2009-06-16 10:43:43 +00:00
tables = [ self . _table ( ' vport ' , [ str ( x ) for x in self . vports ] ) ,
self . _table ( ' ltype ' , [ str ( x ) for x in self . linetypes ] ) ,
2008-10-07 20:34:24 +00:00
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 \n EOF \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
2008-12-14 21:26:24 +00:00
d . blocks . append ( b ) #table blocks
d . styles . append ( Style ( ) ) #table styles
d . views . append ( View ( ' Normal ' ) ) #table view
2008-10-07 20:34:24 +00:00
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 \n multiple lines with mtext ' , point = ( 1 , 1 , 1 ) , color = 5 , rotation = 90 ) )
d . append ( Text ( ' Please donate! ' , point = ( 3 , 0 , 1 ) ) )
2009-06-16 10:43:43 +00:00
#d.append(Rectangle(point=(2,2,2),width=4,height=3,color=6,solid=Solid(color=2)))
2008-10-07 20:34:24 +00:00
d . append ( Solid ( points = [ ( 4 , 4 , 0 ) , ( 5 , 4 , 0 ) , ( 7 , 8 , 0 ) , ( 9 , 9 , 0 ) ] , color = 3 ) )
2009-06-16 10:43:43 +00:00
#d.append(PolyLine(points=[(1,1,1),(2,1,1),(2,2,1),(1,2,1)],flag=1,color=1))
2008-10-07 20:34:24 +00:00
#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 ' )
2009-06-16 10:43:43 +00:00
else : test ( )
2008-10-07 20:34:24 +00:00