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:
parent
e21972be9b
commit
92382edbc9
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue
Block a user