bugfixes and feature enhancements in exportDRAWEXE

bugfix to Loft in exportDRAWEXE
added Extrusion
ability to clean shapes from teselation before export
support for Fillet in exportDRAWEXE
name shapes with restore command
remove trailing dot from decimals
include version information in output
allow to test if a suboject is supported
explode sections of loft and sweep and edges for fillet
This commit is contained in:
Sebastian Hoogen 2014-07-25 18:21:03 +02:00
parent e21972be9b
commit 92382edbc9

View File

@ -31,7 +31,7 @@ if open.__module__ == '__builtin__':
def f2s(n):
'''convert to numerical value to string'''
#return str(float(n))
return ('%0.18f' % n).rstrip('0')
return ('%0.18f' % n).rstrip('0').rstrip('.')
def placement2draw(placement,name='object'):
"""converts a FreeCAD Placement to trotate and ttranslate commands"""
@ -48,14 +48,18 @@ def placement2draw(placement,name='object'):
(name,f2s(x),f2s(y),f2s(z))
return drawcommand
def saveShape(csg,filename,shape,name,hasplacement = True):
def saveShape(csg,filename,shape,name,hasplacement = True,cleanshape=False):
import os
spath,sname = os.path.split(filename)
sname=sname.replace('.','-')
uname='%s-%s' %(sname,name)
breppath=os.path.join(spath,'%s.brep'%uname)
csg.write("restore %s.brep\n"%uname)
csg.write("renamevar %s %s\n"%(uname,name))
csg.write("restore %s.brep %s\n" % (uname,name))
if cleanshape:
try:
shape = shape.cleaned()
except:
shape = shape.copy()
if hasplacement is None: # saved with placement
hasplacement = False # saved with placement
shape.exportBrep(breppath)
@ -64,6 +68,11 @@ def saveShape(csg,filename,shape,name,hasplacement = True):
else: #remove placement
sh=shape.copy()
sh.Placement=FreeCAD.Placement()
# it not yet tested if changing the placement recreated the
# tesselation. but for now we simply do the cleaing once agian
# to stay on the safe side
if cleanshape:
shape = shape.cleaned()
sh.exportBrep(breppath)
return hasplacement
@ -71,18 +80,31 @@ def saveSweep(csg,ob,filename):
import Part
spine,subshapelst=ob.Spine
#process_object(csg,spine,filename)
try:
explodeshape = process_object(spine)
if explodeshape:
try:
#raise NotImplementedError # hit the fallback
# currently all subshapes are edges
process_object(spine,csg,filename)
csg.write('explode %s E\n' % spine.Name )
edgelst = ' '.join(('%s_%s' % (spine.Name,ss[4:]) for ss \
in subshapelst))
spinename = '%s-0-spine' % ob.Name
csg.write('wire %s %s\n' %(spinename,edgelst))
except:
explodeshape = False # fallback
raise
if not explodeshape: # extract only the used subshape
path=Part.Wire([spine.Shape.getElement(subshapename) for \
subshapename in spine,subshapelst])
except: # BRep_API: command not done
subshapename in subshapelst])
if spine.Shape.ShapeType == 'Edge':
path = spine.Shape
elif spine.Shape.ShapeType == 'Wire':
path = Part.Wire(spine.Shape)
else:
raise ValueError('Unsuitabel Shape Type')
spinename = '%s-0-spine' % ob.Name
hasplacement = saveShape(csg,filename, path,spinename,None) # placement with shape
spinename = '%s-0-spine' % ob.Name
saveShape(csg,filename, path,spinename,None) # placement with shape
#safePlacement(ob.Placement,ob.Name)
csg.write('mksweep %s\n' % spinename)
#setsweep
@ -110,16 +132,36 @@ def saveSweep(csg,ob,filename):
#d1['basename']=subobj.Name
sectionname = '%s-0-section-%02d-%s' % (ob.Name,i,subobj.Name)
addoptions=[]
sh = subobj.Shape
if sh.ShapeType == 'Vertex':
pass
elif sh.ShapeType == 'Wire' or sh.ShapeType == 'Edge':
sh = Part.Wire(sh)
elif sh.ShapeType == 'Face':
sh = sh.OuterWire
else:
raise ValueError('Unrecognized Shape Type')
hasplacement = saveShape(csg,filename,sh,sectionname,None) # placement with shape
explodeshape = process_object(subobj)
if explodeshape:
sh = subobj.Shape
if sh.ShapeType == 'Wire' or sh.ShapeType == 'Edge' or \
sh.ShapeType == 'Face' and len(sh.Wires) == 1:
process_object(subobj,csg,filename)
if sh.ShapeType == 'Wire':
#csg.write('tcopy %s %s\n' %(subobj.Name,sectionname))
sectionname = subobj.Name
if sh.ShapeType == 'Edge':
csg.write('explode %s E\n' % subobj.Name )
csg.write('wire %s %s_1\n' %(sectionname,subobj.Name))
if sh.ShapeType == 'Face':
#we should use outer wire when it becomes avaiable
csg.write('explode %s W\n' % subobj.Name )
#csg.write('tcopy %s_1 %s\n' %(subobj.Name,sectionname))
sectionname ='%s_1' % subobj.Name
else:
explodeshape = False
if not explodeshape: # extract only the used subshape
sh = subobj.Shape
if sh.ShapeType == 'Vertex':
pass
elif sh.ShapeType == 'Wire' or sh.ShapeType == 'Edge':
sh = Part.Wire(sh)
elif sh.ShapeType == 'Face':
sh = sh.OuterWire
else:
raise ValueError('Unrecognized Shape Type')
saveShape(csg,filename,sh,sectionname,None) # placement with shape
csg.write('addsweep %s %s\n' % (sectionname," ".join(addoptions)))
csg.write('buildsweep %s %s\n' % (ob.Name," ".join(buildoptions)))
@ -182,39 +224,53 @@ def isDeform(ob):
def process_object(csg,ob,filename):
def process_object(ob,csg=None,filename='unnamed'):
d1 = {'name':ob.Name}
hasplacement = not ob.Placement.isNull()
if ob.TypeId in ["Part::Cut","Part::Fuse","Part::Common","Part::Section"]:
if csg is None:
return True # The object is supported
d1.update({'part':ob.Base.Name,'tool':ob.Tool.Name,\
'command':'b%s' % ob.TypeId[6:].lower()})
process_object(csg,ob.Base,filename)
process_object(csg,ob.Tool,filename)
process_object(ob.Base,csg,filename)
process_object(ob.Tool,csg,filename)
csg.write("%(command)s %(name)s %(part)s %(tool)s\n"%d1)
elif ob.TypeId == "Part::Sphere" :
if csg is None:
return True # The object is supported
d1.update({'radius':f2s(ob.Radius),'angle1':f2s(ob.Angle1),\
'angle2':f2s(ob.Angle2),'angle3':f2s(ob.Angle3)})
csg.write('psphere %(name)s %(radius)s %(angle1)s %(angle2)s '\
'%(angle3)s\n'%d1)
elif ob.TypeId == "Part::Box" :
if csg is None:
return True # The object is supported
d1.update({'dx':f2s(ob.Length),'dy':f2s(ob.Width),'dz':f2s(ob.Height)})
csg.write('box %(name)s %(dx)s %(dy)s %(dz)s\n'%d1)
elif ob.TypeId == "Part::Cylinder" :
if csg is None:
return True # The object is supported
d1.update({'radius':f2s(ob.Radius),'height':f2s(ob.Height),\
'angle':f2s(ob.Angle)})
csg.write('pcylinder %(name)s %(radius)s %(height)s %(angle)s\n'%d1)
elif ob.TypeId == "Part::Cone" :
if csg is None:
return True # The object is supported
d1.update({'radius1':f2s(ob.Radius1),'radius2':f2s(ob.Radius2),\
'height':f2s(ob.Height)})
csg.write('pcone %(name)s %(radius1)s %(radius2)s %(height)s\n'%d1)
elif ob.TypeId == "Part::Torus" :
if csg is None:
return True # The object is supported
d1.update({'radius1':f2s(ob.Radius1),'radius2':f2s(ob.Radius2),\
'angle1': f2s(ob.Angle1),'angle2':f2s(ob.Angle2),\
'angle3': f2s(ob.Angle3)})
csg.write('ptorus %(name)s %(radius1)s %(radius2)s %(angle1)s '\
'%(angle2)s %(angle3)s\n' % d1)
elif ob.TypeId == "Part::Mirroring" :
process_object(csg,ob.Source,filename)
if csg is None:
return True # The object is supported
process_object(ob.Source,csg,filename)
csg.write('tcopy %s %s\n'%(ob.Source.Name,d1['name']))
b=ob.Base
d1['x']=f2s(ob.Base.x)
@ -229,27 +285,35 @@ def process_object(csg,ob,filename):
if len(ob.Links) == 0:
pass
elif len(ob.Links) == 1:
process_object(csg,ob.Links[0],filename)
if csg is None:
return process_object(ob.Links[0],None,filename)
process_object(ob.Links[0],csg,filename)
csg.write('tcopy %s %s\n'%(ob.Links[0].Name,d1['name']))
else:
if csg is None:
return True # The object is supported
basenames=[]
for i,subobj in enumerate(ob.Links):
process_object(csg,subobj,filename)
process_object(subobj,csg,filename)
basenames.append(subobj.Name)
csg.write('compound %s %s\n' % (' '.join(basenames),ob.Name))
elif ob.TypeId in ["Part::MultiCommon", "Part::MultiFuse"]:
if len(ob.Shapes) == 0:
pass
elif len(ob.Shapes) == 1:
process_object(csg,ob.Shapes[0],filename)
if csg is None:
return process_object(ob.Shapes[0],None,filename)
process_object(ob.Shapes[0],csg,filename)
csg.write('tcopy %s %s\n'%(ob.Shapes[0].Name,d1['name']))
else:
if csg is None:
return True # The object is supported
topname = ob.Name
command = 'b%s' % ob.TypeId[11:].lower()
lst1=ob.Shapes[:]
current=lst1.pop(0)
curname=current.Name
process_object(csg,current,filename)
process_object(current,csg,filename)
i=1
while lst1:
if len(lst1) >= 2:
@ -257,11 +321,13 @@ def process_object(csg,ob,filename):
else:
nxtname=topname
nxt=lst1.pop(0)
process_object(csg,nxt,filename)
process_object(nxt,csg,filename)
csg.write("%s %s %s %s\n"%(command,nxtname,curname,nxt.Name))
curname=nxtname
i+=1
elif ob.TypeId == "Part::Prism" :
if csg is None:
return True # The object is supported
import math
polyname = '%s-polyline' % d1['name']
wirename = '%s-polywire' % d1['name']
@ -282,38 +348,90 @@ def process_object(csg,ob,filename):
csg.write('mkplane %s %s\n' % (facename,polyname))
csg.write('prism %s %s 0 0 %s\n' % (d1['name'],facename,\
f2s(ob.Height.Value)))
elif ob.TypeId == "Part::Extrusion" and ob.TaperAngle.Value == 0:
if csg is None:
return True # The object is supported
process_object(ob.Base,csg,filename)
#Warning does not fully ressemle the functionallity of
#Part::Extrusion
#csg.write('tcopy %s %s\n'%(ob.Base.Name,d1['name']))
facename=ob.Base.Name
csg.write('prism %s %s %s %s %s\n' % (d1['name'],facename,\
f2s(ob.Dir.x),f2s(ob.Dir.y),f2s(ob.Dir.z)))
elif ob.TypeId == "Part::Fillet" and True: #disabled
if csg is None:
return True # The object is supported
process_object(ob.Base,csg,filename)
csg.write('explode %s E\n' % ob.Base.Name )
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])) \
for e in ob.Edges))))
elif ob.TypeId == "Part::Sweep" and True:
if csg is None:
return True # The object is supported
saveSweep(csg,ob,filename)
elif ob.TypeId == "Part::Loft":
if csg is None:
return True # The object is supported
sectionnames=[]
for i,subobj in enumerate(ob.Sections):
sh = subobj.Shape
if not sh.isNull():
if sh.ShapeType == 'Compound':
sh = sh.Shape.childShapes()[0]
if sh.ShapeType == 'Face':
sh = sh.OuterWire
elif sh.ShapeType == 'Edge':
import Part
sh = Part.Wire([sh])
elif sh.ShapeType == 'Wire':
import Part
sh = Part.Wire(sh)
elif sh.ShapeType == 'Vertex':
pass
else:
raise ValueError('Unsuitabel Shape Type')
sectionname = '%s-%02d-section' % (ob.Name,i)
hasplacement = saveShape(csg,filename, sh,sectionname,None)
# placement with shape
explodeshape = process_object(suboobj)
if explodeshape and False: #diabled TBD
try:
raise NotImplementedError
sectionname = '%s-%02d-section' % (ob.Name,i)
sh = subobj.Shape
if sh.isNull():
raise ValueError # hit the fallback
tempname=spine.Name
if sh.ShapeType == 'Compound':
sh = sh.childShapes()[0]
csg.write('explode %s\n' % tempname )
tempname = '%s_1' % tempname
if sh.ShapeType == 'Face':
#sh = sh.OuterWire #not available
if len(sh.Wires) == 1:
sh=sh.Wires[0]
csg.write('explode %s\n W' % tempname )
tempname = '%s_1' % tempname
else:
raise NotImplementedError
elif sh.ShapeType == 'Edge':
csg.write('wire %s %s\n' %(sectionname,tempname))
tempname = sectionname
sectionname = tempname
except NotImplementedError:
explodeshape = False # fallback
if not explodeshape: # extract only the used subshape
sh = subobj.Shape
if not sh.isNull():
if sh.ShapeType == 'Compound':
sh = sh.childShapes()[0]
if sh.ShapeType == 'Face':
sh = sh.OuterWire
elif sh.ShapeType == 'Edge':
import Part
sh = Part.Wire([sh])
elif sh.ShapeType == 'Wire':
import Part
sh = Part.Wire(sh)
elif sh.ShapeType == 'Vertex':
pass
else:
raise ValueError('Unsuitabel Shape Type')
sectionname = '%s-%02d-section' % (ob.Name,i)
saveShape(csg,filename, sh,sectionname,None)
# placement with shape
sectionnames.append(sectionname)
if ob.Closed:
sectionnames.append(sectionnames[0])
csg.write('thrusections %s %d %d %s\n' % (ob.Name,int(ob.Solid),\
int(ob.Ruled), ' '.join(sectionnames)))
elif isDeform(ob): #non-uniform scaling
if csg is None:
return True # The object is supported
m=ob.Matrix
process_object(csg,ob.Base,filename)
process_object(ob.Base,csg,filename)
#csg.write('tcopy %s %s\n'%(ob.Base.Name,d1['name']))
d1['basename']=ob.Base.Name
d1['cx']=f2s(m.A11)
@ -324,6 +442,8 @@ def process_object(csg,ob,filename):
csg.write("ttranslate %s %s %s %s\n" % \
(ob.Name,f2s(m.A14),f2s(m.A24),f2s(m.A34)))
elif isDraftCircle(ob):
if csg is None:
return True # The object is supported
"circle name x y [z [dx dy dz]] [ux uy [uz]] radius"
d1['radius']=ob.Radius.Value
pfirst=f2s(ob.FirstAngle.getValueAs('rad').Value)
@ -341,6 +461,8 @@ def process_object(csg,ob,filename):
else:
csg.write("renamevar %s %s\n"%(wirename,d1['name'])) #the wire is the final object
elif isDraftWire(ob):
if csg is None:
return True # The object is supported
points=ob.Points
if ob.Closed:
points.append(points[0])
@ -357,6 +479,8 @@ def process_object(csg,ob,filename):
wirename = d1['name']
csg.write('wire %s %s\n' %(wirename,polyname))
elif isDraftClone(ob):
if csg is None:
return True # The object is supported
x,y,z=ob.Scale.x
if x == y == z: #uniform scaling
d1['scale']=f2s(x)
@ -366,7 +490,7 @@ def process_object(csg,ob,filename):
d1['cz']=f2s(z)
if len(ob.Objects) == 1:
d1['basename']=ob.Objects[0].Name
process_object(csg,ob.Objects[0],filename)
process_object(ob.Objects[0],csg,filename)
if x == y == z: #uniform scaling
csg.write('tcopy %(basename)s %(name)s\n' % d1)
csg.write('pscale %(name)s 0 0 0 %(scale)s\n' % d1)
@ -376,7 +500,7 @@ def process_object(csg,ob,filename):
else: #compound
newnames=[]
for i,subobj in enumerate(ob.Objects):
process_object(csg,subobj,filename)
process_object(subobj,csg,filename)
d1['basename']=subobj.Name
newname='%s-%2d' % (ob.Name,i)
d1['newname']=newname
@ -394,7 +518,9 @@ def process_object(csg,ob,filename):
# pass
elif ob.isDerivedFrom('Part::Feature') :
if ob.Shape.isNull(): #would crash in exportBrep otherwise
raise ValueError
raise ValueError('Shape of %s is Null' % ob.Name)
if csg is None:
return False # The object is not supported
hasplacement = saveShape(csg,filename,ob.Shape,ob.Name,hasplacement)
if hasplacement:
csg.write(placement2draw(ob.Placement,ob.Name))
@ -403,9 +529,10 @@ def export(exportList,filename):
"called when freecad exports a file"
# process Objects
csg = pythonopen(filename,'w')
csg.write('#generated by FreeCAD\n')
import FreeCAD
csg.write('#generated by FreeCAD %s\n' % '.'.join(FreeCAD.Version()[0:3]))
csg.write('pload ALL\n')
for ob in exportList:
process_object(csg,ob,filename)
process_object(ob,csg,filename)
csg.write('donly %s\n'%' '.join([obj.Name for obj in exportList]))
csg.close()