enhancements in exportDRAWEXE.py

simplify float formatting
support for Part::Thickness in exportDRAWEXE.py
support for Draft::Ellipse in exportDRAWEXE.py
support for Annotations
This commit is contained in:
Sebastian Hoogen 2014-10-19 14:18:52 +02:00 committed by Yorik van Havre
parent 58a84d2748
commit c8934c06a8

View File

@ -32,21 +32,24 @@ if open.__module__ == '__builtin__':
# Part:: Wedge, Helix, Spiral, Elipsoid # Part:: Wedge, Helix, Spiral, Elipsoid
# Draft: Rectangle, BSpline, BezCurve # Draft: Rectangle, BSpline, BezCurve
def f2s(n,angle=False): def f2s(n,angle=False,axis=False):
'''convert to numerical value to string '''convert to numerical value to string
try to remove no significant digits, by guessing a former rounding try to remove no significant digits, by guessing a former rounding
if it fail use 18 decimal place in fixed point notation
''' '''
if abs(n) < 1e-14: return '0' if abs(n) < 1e-14: return '0'
elif len(('%0.13e' % n).split('e')[0].rstrip('0') ) < 6: if angle and len(('%0.6e' % n).split('e')[0].rstrip('0') ) < 3:
return ('%0.10f' % n).rstrip('0').rstrip('.')
elif not angle and len(('%0.15e' % n).split('e')[0].rstrip('0') ) < 15:
return ('%0.15f' % n).rstrip('0').rstrip('.')
elif angle and len(('%0.6e' % n).split('e')[0].rstrip('0') ) < 3:
return ('%0.5f' % n).rstrip('0').rstrip('.') return ('%0.5f' % n).rstrip('0').rstrip('.')
elif axis and len(('%0.13e' % n).split('e')[0].rstrip('0') ) < 6:
return ('%0.10f' % n).rstrip('0').rstrip('.')
else: else:
return ('%0.18f' % n).rstrip('0').rstrip('.') for i in range(20):
#return str(float(n)) s = ('%%1.%df'% i) % n
if float(s) == n:
return s
for i in range(20):
s = ('%%0.%de'% i) % n
if float(s) == n:
return s
def polygonstr(r,pcount): def polygonstr(r,pcount):
import math import math
@ -80,7 +83,8 @@ def placement2draw(placement,name='object'):
dx,dy,dz=placement.Rotation.Axis dx,dy,dz=placement.Rotation.Axis
an=math.degrees(placement.Rotation.Angle) an=math.degrees(placement.Rotation.Angle)
drawcommand += "trotate %s 0 0 0 %s %s %s %s\n" % \ drawcommand += "trotate %s 0 0 0 %s %s %s %s\n" % \
(name,f2s(dx),f2s(dy),f2s(dz),f2s(an,angle=True)) (name,f2s(dx,axis=True),f2s(dy,axis=True),f2s(dz,axis=True),\
f2s(an,angle=True))
if placement.Base.Length > 1e-8: if placement.Base.Length > 1e-8:
x,y,z=placement.Base x,y,z=placement.Base
drawcommand += "ttranslate %s %s %s %s\n" % \ drawcommand += "ttranslate %s %s %s %s\n" % \
@ -137,6 +141,11 @@ def isDraftCircle(ob):
import Draft import Draft
return isinstance(ob.Proxy,Draft._Circle) return isinstance(ob.Proxy,Draft._Circle)
def isDraftEllipse(ob):
if isDraftFeature(ob):
import Draft
return isinstance(ob.Proxy,Draft._Ellipse)
def isDraftPolygon(ob): def isDraftPolygon(ob):
if isDraftFeature(ob): if isDraftFeature(ob):
import Draft import Draft
@ -316,7 +325,8 @@ class Drawexporter(object):
hasplacement = not ob.Placement.isNull() hasplacement = not ob.Placement.isNull()
else: else:
hasplacement = False hasplacement = False
if ob.TypeId in ["Part::Cut","Part::Fuse","Part::Common","Part::Section"]: if ob.TypeId in ["Part::Cut","Part::Fuse","Part::Common",\
"Part::Section"]:
if checksupported: return True # The object is supported if checksupported: return True # The object is supported
d1.update({'part':ob.Base.Name,'tool':ob.Tool.Name,\ d1.update({'part':ob.Base.Name,'tool':ob.Tool.Name,\
'command':'b%s' % ob.TypeId[6:].lower()}) 'command':'b%s' % ob.TypeId[6:].lower()})
@ -472,6 +482,22 @@ class Drawexporter(object):
self.csg.write('blend %s %s %s\n' % (d1['name'],ob.Base.Name,\ self.csg.write('blend %s %s %s\n' % (d1['name'],ob.Base.Name,\
' '.join(('%s %s'%(f2s(e[1]),'%s_%d' % (ob.Base.Name,e[0])) \ ' '.join(('%s %s'%(f2s(e[1]),'%s_%d' % (ob.Base.Name,e[0])) \
for e in ob.Edges)))) for e in ob.Edges))))
elif ob.TypeId == "Part::Thickness" and not ob.SelfIntersection and \
ob.Mode == 'Skin':
if checksupported: return True # The object is supported
jointype = {'Arc':'a','Intersection':'i','Tangent':'t'} #Join
inter = {False: 'p', True: 'c'} #Intersection
baseobj, facelist = ob.Faces
self.process_object(baseobj)
faces = ' '.join([('%s_%s' %(baseobj.Name,f[4:])) \
for f in facelist])
value = f2s(ob.Value)
self.csg.write('explode %s F\n' % baseobj.Name )
self.csg.write('offsetparameter 1e-7 %s %s\n' % \
(inter[ob.Intersection],jointype[ob.Join]))
self.csg.write('offsetload %s %s %s\n'%(baseobj.Name,value,faces))
self.csg.write('offsetperform %s\n' % d1['name'] )
elif ob.TypeId == "Part::Sweep" and True: elif ob.TypeId == "Part::Sweep" and True:
if checksupported: return True # The object is supported if checksupported: return True # The object is supported
self.saveSweep(ob) self.saveSweep(ob)
@ -552,9 +578,11 @@ class Drawexporter(object):
d1['y']=f2s(ob.Y) d1['y']=f2s(ob.Y)
d1['z']=f2s(ob.Z) d1['z']=f2s(ob.Z)
self.csg.write('vertex %(name)s %(x)s %(y)s %(z)s\n' % d1) self.csg.write('vertex %(name)s %(x)s %(y)s %(z)s\n' % d1)
elif isDraftCircle(ob) or ob.TypeId == "Part::Circle" or \
elif isDraftCircle(ob) or ob.TypeId == "Part::Circle": isDraftEllipse(ob):
if checksupported: return True # The object is supported if checksupported: return True # The object is supported
isdraftcircle=isDraftCircle(ob)
isdraftellipse=isDraftCircle(ob)
"circle name x y [z [dx dy dz]] [ux uy [uz]] radius" "circle name x y [z [dx dy dz]] [ux uy [uz]] radius"
curvename = '%s-curve' % d1['name'] curvename = '%s-curve' % d1['name']
if ob.TypeId == "Part::Circle": if ob.TypeId == "Part::Circle":
@ -564,17 +592,26 @@ class Drawexporter(object):
self.csg.write('circle %s 0 0 0 %s\n' % (curvename,radius)) self.csg.write('circle %s 0 0 0 %s\n' % (curvename,radius))
self.csg.write('mkedge %s %s %s %s\n' % \ self.csg.write('mkedge %s %s %s %s\n' % \
(d1['name'],curvename,pfirst,plast)) (d1['name'],curvename,pfirst,plast))
else: else: #draft
radius=f2s(ob.Radius.Value)
pfirst=f2s(ob.FirstAngle.getValueAs('rad').Value)
plast=f2s(ob.LastAngle.getValueAs('rad').Value)
makeface = ob.MakeFace and \ makeface = ob.MakeFace and \
(ob.Shape.isNull() or ob.Shape.ShapeType == 'Face') (ob.Shape.isNull() or ob.Shape.ShapeType == 'Face')
#FreeCAD ignore a failed mkplane but it may #FreeCAD ignores a failed mkplane but it may
#brake the model in DRAWEXE #break the model in DRAWEXE
edgename = '%s-edge' % d1['name'] edgename = '%s-edge' % d1['name']
self.csg.write('circle %s 0 0 0 %s\n' % (curvename,radius))
if isdraftcircle:
pfirst=f2s(ob.FirstAngle.getValueAs('rad').Value)
plast=f2s(ob.LastAngle.getValueAs('rad').Value)
radius=f2s(ob.Radius.Value)
self.csg.write('circle %s 0 0 0 %s\n' % (curvename,radius))
else: #draft ellipse
import math
majr=f2s(float(ob.MajorRadius))
minr=f2s(float(ob.MinorRadius))
pfirst=0
plast=2*math.pi
self.csg.write('ellipse %s 0 0 0 %s %s\n' % \
(curvename,majr,minr))
self.csg.write('mkedge %s %s %s %s\n' % \ self.csg.write('mkedge %s %s %s %s\n' % \
(edgename,curvename,pfirst,plast)) (edgename,curvename,pfirst,plast))
if makeface: if makeface:
@ -583,7 +620,6 @@ class Drawexporter(object):
self.csg.write('mkplane %s %s\n' % (d1['name'],wirename)) self.csg.write('mkplane %s %s\n' % (d1['name'],wirename))
else: else:
self.csg.write('wire %s %s\n' %(d1['name'],edgename)) self.csg.write('wire %s %s\n' %(d1['name'],edgename))
elif ob.TypeId == "Part::Line": elif ob.TypeId == "Part::Line":
if checksupported: return True # The object is supported if checksupported: return True # The object is supported
self.csg.write('polyline %s %s %s %s %s %s %s\n' % \ self.csg.write('polyline %s %s %s %s %s %s %s\n' % \
@ -651,6 +687,9 @@ class Drawexporter(object):
formatobjtype(ob)) formatobjtype(ob))
hasplacement = saveShape(self.csg,self.filename,ob.Shape,ob.Name,\ hasplacement = saveShape(self.csg,self.filename,ob.Shape,ob.Name,\
hasplacement,self.cleanshape) hasplacement,self.cleanshape)
elif ob.isDerivedFrom('App::Annotation') :
return False # ignored here
#anntotations needs to be drawn after erase/donly
else: # not derived from Part::Feature else: # not derived from Part::Feature
if not toplevel: if not toplevel:
raise ValueError('Can not export child object') raise ValueError('Can not export child object')
@ -671,12 +710,27 @@ class Drawexporter(object):
self.csg.write('#Object Label: %s\n' % ob.Label.encode('unicode-escape')) self.csg.write('#Object Label: %s\n' % ob.Label.encode('unicode-escape'))
return ob.Name #The object is present and can be referenced return ob.Name #The object is present and can be referenced
def export_annotations(self,objlst):
for ob in objlst:
if ob.isDerivedFrom('App::Annotation') :
if ob.Name != ob.Label:
self.csg.write('#Annotation Name %s Label %s"\n' % \
(ob.Name,ob.Label.encode('unicode-escape')))
else:
self.csg.write('#Annotation %s\n' % (ob.Name))
v=ob.Position
self.csg.write('dtext %s %s %s "%s"\n' % \
(f2s(v.x),f2s(v.y),f2s(v.z), '\\n'.join(\
ob.LabelText).encode(\
'ascii', errors='xmlcharrefreplace')))
def export_objects(self,objlst,toplevel=True): def export_objects(self,objlst,toplevel=True):
self.write_header() self.write_header()
toplevelobjs = [self.process_object(ob, toplevel=toplevel)\ toplevelobjs = [self.process_object(ob, toplevel=toplevel)\
for ob in objlst] for ob in objlst]
names = [name for name in toplevelobjs if name is not False] names = [name for name in toplevelobjs if name is not False]
self.csg.write('donly %s\n'%(' '.join(names))) self.csg.write('donly %s\n'%(' '.join(names)))
self.export_annotations(objlst)
#for ob in objlst: #for ob in objlst:
# self.process_object(ob,toplevel=toplevel) # self.process_object(ob,toplevel=toplevel)
#self.write_displayonly(objlst) #self.write_displayonly(objlst)