Merge remote-tracking branch 'refs/remotes/shoogen-github/dev-openscad'
This commit is contained in:
commit
729188d759
|
@ -32,3 +32,6 @@ openscadfilename = param.GetString('openscadexecutable')
|
|||
openscadbin = openscadfilename and os.path.isfile(openscadfilename)
|
||||
if openscadbin:
|
||||
FreeCAD.addImportType("OpenSCAD Format (*.scad)","importCSG")
|
||||
FreeCAD.addExportType("OpenSCAD CSG Format (*.csg)","exportCSG")
|
||||
FreeCAD.addExportType("OpenSCAD Format (*.scad)","exportCSG")
|
||||
|
||||
|
|
|
@ -107,9 +107,19 @@ static char * openscadlogo_xpm[] = {
|
|||
param = FreeCAD.ParamGet(\
|
||||
"User parameter:BaseApp/Preferences/Mod/OpenSCAD")
|
||||
openscadfilename = param.GetString('openscadexecutable')
|
||||
if not openscadfilename:
|
||||
|
||||
import OpenSCADUtils
|
||||
openscadfilename = OpenSCADUtils.searchforopenscadexe()
|
||||
if openscadfilename: #automatic search was succsessful
|
||||
FreeCAD.addImportType("OpenSCAD Format (*.scad)","importCSG")
|
||||
param.SetString('openscadexecutable',openscadfilename) #save the result
|
||||
if openscadfilename:
|
||||
commands.extend(['OpenSCAD_AddOpenSCADElement'])
|
||||
toolbarcommands.extend(['OpenSCAD_AddOpenSCADElement'])
|
||||
else:
|
||||
FreeCAD.Console.PrintWarning('OpenSCAD executable not found\n')
|
||||
|
||||
self.appendToolbar("OpenSCADTools",toolbarcommands)
|
||||
self.appendMenu('OpenSCAD',commands)
|
||||
self.appendToolbar('OpenSCAD Part tools',parttoolbarcommands)
|
||||
|
@ -124,5 +134,3 @@ static char * openscadlogo_xpm[] = {
|
|||
|
||||
|
||||
Gui.addWorkbench(OpenSCADWorkbench())
|
||||
App.addExportType("OpenSCAD CSG Format (*.csg)","exportCSG")
|
||||
App.addExportType("OpenSCAD Format (*.scad)","exportCSG")
|
||||
|
|
|
@ -215,8 +215,8 @@ class AddSCADTask:
|
|||
asmesh=self.form.checkboxmesh.checkState()
|
||||
import OpenSCADUtils, os
|
||||
extension= 'stl' if asmesh else 'csg'
|
||||
tmpfilename=OpenSCADUtils.callopenscadstring(scadstr,extension)
|
||||
if tmpfilename:
|
||||
try:
|
||||
tmpfilename=OpenSCADUtils.callopenscadstring(scadstr,extension)
|
||||
doc=FreeCAD.activeDocument() or FreeCAD.newDocument()
|
||||
if asmesh:
|
||||
import Mesh
|
||||
|
@ -225,8 +225,8 @@ class AddSCADTask:
|
|||
import importCSG
|
||||
importCSG.insert(tmpfilename,doc.Name)
|
||||
os.unlink(tmpfilename)
|
||||
else:
|
||||
FreeCAD.Console.PrintError(unicode(translate('OpenSCAD','Running OpenSCAD failed'))+u'\n')
|
||||
except OpenSCADUtils.OpenSCADError, e:
|
||||
FreeCAD.Console.PrintError(e.value)
|
||||
|
||||
class AddOpenSCADElement:
|
||||
def IsActive(self):
|
||||
|
|
|
@ -28,22 +28,90 @@ __url__ = ["http://free-cad.sourceforge.net"]
|
|||
This Script includes various pyhton helper functions that are shared across
|
||||
the module
|
||||
'''
|
||||
|
||||
class OpenSCADError(Exception):
|
||||
def __init__(self,value):
|
||||
self.value= value
|
||||
#def __repr__(self):
|
||||
# return self.msg
|
||||
def __str__(self):
|
||||
return repr(self.value)
|
||||
|
||||
def searchforopenscadexe():
|
||||
import os,sys,subprocess
|
||||
if sys.platform == 'win32':
|
||||
testpaths = [os.path.join(os.environ.get('Programfiles(x86)','C:'),\
|
||||
'OpenSCAD\\openscad.exe')]
|
||||
if 'ProgramW6432' in os.environ:
|
||||
testpaths.append(os.path.join(os.environ.get('ProgramW6432','C:')\
|
||||
,'OpenSCAD\\openscad.exe'))
|
||||
for testpath in testpaths:
|
||||
if os.path.isfile(testpath):
|
||||
return testpath
|
||||
else:
|
||||
p1=subprocess.Popen(['which','openscad'],stdout=subprocess.PIPE)
|
||||
if p1.wait() == 0:
|
||||
opath=p1.stdout.read().split('\n')[0]
|
||||
return opath
|
||||
|
||||
def workaroundforissue128needed():
|
||||
'''sets the import path depending on the OpenSCAD Verion
|
||||
for versions <= 2012.06.23 to the current working dir
|
||||
for versions above to the inputfile dir
|
||||
see https://github.com/openscad/openscad/issues/128'''
|
||||
vdate=getopenscadversion().split(' ')[2].split('.')
|
||||
year,mon=int(vdate[0]),int(vdate[1])
|
||||
return (year<2012 or (year==2012 and (mon <6 or (mon == 6 and \
|
||||
(len(vdate)<3 or int(vdate[2]) <=23)))))
|
||||
#ifdate=int(vdate[0])+(int(vdate[1])-1)/12.0
|
||||
#if len(vdate)>2:
|
||||
# fdate+=int((vdate[2])-1)/12.0/31.0
|
||||
#return fdate < 2012.4759
|
||||
|
||||
def getopenscadversion(osfilename=None):
|
||||
import os,subprocess,tempfile,time
|
||||
if not osfilename:
|
||||
import FreeCAD
|
||||
osfilename = FreeCAD.ParamGet(\
|
||||
"User parameter:BaseApp/Preferences/Mod/OpenSCAD").\
|
||||
GetString('openscadexecutable')
|
||||
if osfilename and os.path.isfile(osfilename):
|
||||
p=subprocess.Popen([osfilename,'-v'],\
|
||||
stdout=subprocess.PIPE,universal_newlines=True)
|
||||
p.wait()
|
||||
return p.stdout.read().strip()
|
||||
|
||||
def callopenscad(inputfilename,outputfilename=None,outputext='csg',keepname=False):
|
||||
'''call the open scad binary
|
||||
returns the filename of the result (or None),
|
||||
please delete the file afterwards'''
|
||||
import FreeCAD,os,subprocess,tempfile,time
|
||||
osfilename = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/OpenSCAD").\
|
||||
def check_output2(*args,**kwargs):
|
||||
kwargs.update({'stdout':subprocess.PIPE})
|
||||
p=subprocess.Popen(*args,**kwargs)
|
||||
stdoutd,stderrd = p.communicate()
|
||||
if p.returncode != 0:
|
||||
raise OpenSCADError('%s\n' % stdoutd.strip())
|
||||
#raise Exception,'stdout %s\n stderr%s' %(stdoutd,stderrd)
|
||||
if stdoutd.strip():
|
||||
FreeCAD.Console.PrintWarning(stdoutd+u'\n')
|
||||
return stdoutd
|
||||
|
||||
osfilename = FreeCAD.ParamGet(\
|
||||
"User parameter:BaseApp/Preferences/Mod/OpenSCAD").\
|
||||
GetString('openscadexecutable')
|
||||
if osfilename and os.path.isfile(osfilename):
|
||||
if not outputfilename:
|
||||
dir1=tempfile.gettempdir()
|
||||
if keepname:
|
||||
outputfilename=os.path.join(dir1,'%s.%s' % (os.path.split(inputfilename)[1].rsplit('.',1)[0],outputext))
|
||||
outputfilename=os.path.join(dir1,'%s.%s' % (os.path.split(\
|
||||
inputfilename)[1].rsplit('.',1)[0],outputext))
|
||||
else:
|
||||
outputfilename=os.path.join(dir1,'output-%d.%s' % (int(time.time()*10) % 1000000,outputext))
|
||||
if subprocess.call([osfilename,'-o',outputfilename,inputfilename]) == 0:
|
||||
return outputfilename
|
||||
outputfilename=os.path.join(dir1,'output-%d.%s' % \
|
||||
(int(time.time()*100) % 1000000,outputext))
|
||||
check_output2([osfilename,'-o',outputfilename, inputfilename],\
|
||||
stderr=subprocess.STDOUT)
|
||||
return outputfilename
|
||||
|
||||
def callopenscadstring(scadstr,outputext='csg'):
|
||||
'''create a tempfile and call the open scad binary
|
||||
|
@ -51,11 +119,13 @@ def callopenscadstring(scadstr,outputext='csg'):
|
|||
please delete the file afterwards'''
|
||||
import os,tempfile,time
|
||||
dir1=tempfile.gettempdir()
|
||||
inputfilename=os.path.join(dir1,'input-%d.scad' % (int(time.time()*10) % 1000000))
|
||||
inputfilename=os.path.join(dir1,'input-%d.scad' % \
|
||||
(int(time.time()*10) % 1000000))
|
||||
inputfile = open(inputfilename,'w')
|
||||
inputfile.write(scadstr)
|
||||
inputfile.close()
|
||||
outputfilename = callopenscad(inputfilename,outputext=outputext,keepname=True)
|
||||
outputfilename = callopenscad(inputfilename,outputext=outputext,\
|
||||
keepname=True)
|
||||
os.unlink(inputfilename)
|
||||
return outputfilename
|
||||
|
||||
|
|
|
@ -104,32 +104,32 @@ def process_object(csg,ob):
|
|||
print "axis : "+str(ob.Placement.Rotation.Axis)
|
||||
print "angle : "+str(ob.Placement.Rotation.Angle)
|
||||
|
||||
if ob.Type == "Part::Sphere" :
|
||||
if ob.TypeId == "Part::Sphere" :
|
||||
print "Sphere Radius : "+str(ob.Radius)
|
||||
check_multmatrix(csg,ob,0,0,0)
|
||||
csg.write("sphere($fn = 0, "+fafs+", r = "+str(ob.Radius)+");\n")
|
||||
|
||||
elif ob.Type == "Part::Box" :
|
||||
elif ob.TypeId == "Part::Box" :
|
||||
print "cube : ("+ str(ob.Length)+","+str(ob.Width)+","+str(ob.Height)+")"
|
||||
mm = check_multmatrix(csg,ob,-ob.Length/2,-ob.Width/2,-ob.Height/2)
|
||||
csg.write("cube (size = ["+str(ob.Length)+", "+str(ob.Width)+", "+str(ob.Height)+"], center = "+center(mm)+");\n")
|
||||
if mm == 1 : csg.write("}\n")
|
||||
|
||||
elif ob.Type == "Part::Cylinder" :
|
||||
elif ob.TypeId == "Part::Cylinder" :
|
||||
print "cylinder : Height "+str(ob.Height)+ " Radius "+str(ob.Radius)
|
||||
mm = check_multmatrix(csg,ob,0,0,-ob.Height/2)
|
||||
csg.write("cylinder($fn = 0, "+fafs+", h = "+str(ob.Height)+ ", r1 = "+str(ob.Radius)+\
|
||||
", r2 = " + str(ob.Radius) + ", center = "+center(mm)+");\n")
|
||||
if mm == 1 : csg.write("}\n")
|
||||
|
||||
elif ob.Type == "Part::Cone" :
|
||||
elif ob.TypeId == "Part::Cone" :
|
||||
print "cone : Height "+str(ob.Height)+ " Radius1 "+str(ob.Radius1)+" Radius2 "+str(ob.Radius2)
|
||||
mm = check_multmatrix(csg,ob,0,0,-ob.Height/2)
|
||||
csg.write("cylinder($fn = 0, "+fafs+", h = "+str(ob.Height)+ ", r1 = "+str(ob.Radius1)+\
|
||||
", r2 = "+str(ob.Radius2)+", center = "+center(mm)+");\n")
|
||||
if mm == 1 : csg.write("}\n")
|
||||
|
||||
elif ob.Type == "Part::Torus" :
|
||||
elif ob.TypeId == "Part::Torus" :
|
||||
print "Torus"
|
||||
print ob.Radius1
|
||||
print ob.Radius2
|
||||
|
@ -142,76 +142,82 @@ def process_object(csg,ob):
|
|||
else : # Cannot convert to rotate extrude so best effort is polyhedron
|
||||
csg.write('%s\n' % shape2polyhedron(ob.Shape))
|
||||
|
||||
elif ob.Type == "Part::Extrusion" :
|
||||
elif ob.TypeId == "Part::Extrusion" :
|
||||
print "Extrusion"
|
||||
print ob.Base
|
||||
print ob.Base.Name
|
||||
#if ( ob.Base == "Part::FeaturePython" and ob.Base.Name == "Polygon") :
|
||||
if ob.Base.Name.startswith("Polygon") :
|
||||
f = str(ob.Base.FacesNumber)
|
||||
r = str(ob.Base.Radius)
|
||||
h = str(ob.Dir[2])
|
||||
print "Faces : " + f
|
||||
print "Radius : " + r
|
||||
print "Height : " + h
|
||||
mm = check_multmatrix(csg,ob,0,0,-float(h)/2)
|
||||
csg.write("cylinder($fn = "+f+", "+fafs+", h = "+h+", r1 = "+r+\
|
||||
", r2 = "+r+", center = "+center(mm)+");\n")
|
||||
if mm == 1: csg.write("}\n")
|
||||
if ob.Base.isDerivedFrom('Part::Part2DObjectPython') and \
|
||||
hasattr(ob.Base,'Proxy') and hasattr(ob.Base.Proxy,'TypeId'):
|
||||
ptype=ob.Base.Proxy.TypeId
|
||||
if ptype == "Polygon" :
|
||||
f = str(ob.Base.FacesNumber)
|
||||
r = str(ob.Base.Radius)
|
||||
h = str(ob.Dir[2])
|
||||
print "Faces : " + f
|
||||
print "Radius : " + r
|
||||
print "Height : " + h
|
||||
mm = check_multmatrix(csg,ob,0,0,-float(h)/2)
|
||||
csg.write("cylinder($fn = "+f+", "+fafs+", h = "+h+", r1 = "+r+\
|
||||
", r2 = "+r+", center = "+center(mm)+");\n")
|
||||
if mm == 1: csg.write("}\n")
|
||||
|
||||
elif ob.Base.Name.startswith("circle") :
|
||||
r = str(ob.Base.Radius)
|
||||
h = str(ob.Dir[2])
|
||||
print "Radius : " + r
|
||||
print "Height : " + h
|
||||
mm = check_multmatrix(csg,ob,0,0,-float(h)/2)
|
||||
csg.write("cylinder($fn = 0, "+fafs+", h = "+h+", r1 = "+r+\
|
||||
", r2 = "+r+", center = "+center(mm)+");\n")
|
||||
if mm == 1: csg.write("}\n")
|
||||
|
||||
elif ob.Base.Name.startswith("Wire") :
|
||||
print "Wire extrusion"
|
||||
print ob.Base
|
||||
mm = check_multmatrix(csg,ob,0,0,0)
|
||||
csg.write("linear_extrude(height = "+str(ob.Dir[2])+", center = "+center(mm)+", "+convexity+", twist = 0, slices = 2, $fn = 0, "+fafs+")\n{\n")
|
||||
csg.write(vertexs2polygon(ob.Base.Shape.Vertexes))
|
||||
if mm == 1: csg.write("}\n")
|
||||
elif ptype == "Circle" :
|
||||
r = str(ob.Base.Radius)
|
||||
h = str(ob.Dir[2])
|
||||
print "Radius : " + r
|
||||
print "Height : " + h
|
||||
mm = check_multmatrix(csg,ob,0,0,-float(h)/2)
|
||||
csg.write("cylinder($fn = 0, "+fafs+", h = "+h+", r1 = "+r+\
|
||||
", r2 = "+r+", center = "+center(mm)+");\n")
|
||||
if mm == 1: csg.write("}\n")
|
||||
|
||||
elif ob.Base.Name.startswith("square") :
|
||||
elif ptype == "Wire" :
|
||||
print "Wire extrusion"
|
||||
print ob.Base
|
||||
mm = check_multmatrix(csg,ob,0,0,0)
|
||||
csg.write("linear_extrude(height = "+str(ob.Dir[2])+", center = "+center(mm)+", "+convexity+", twist = 0, slices = 2, $fn = 0, "+fafs+")\n{\n")
|
||||
csg.write(vertexs2polygon(ob.Base.Shape.Vertexes))
|
||||
if mm == 1: csg.write("}\n")
|
||||
|
||||
elif ob.Base.isDerivedFrom('Part::Plane'):
|
||||
mm = check_multmatrix(csg,ob,0,0,0)
|
||||
csg.write("linear_extrude(height = "+str(ob.Dir[2])+", center = true, "+convexity+", twist = 0, slices = 2, $fn = 0, "+fafs+")\n{\n")
|
||||
csg.write("square (size = ["+str(ob.Base.Length)+", "+str(ob.Base.Width)+"],center = "+center(mm)+";\n}\n")
|
||||
if mm == 1: csg.write("}\n")
|
||||
|
||||
elif ob.Type == "Part::Cut" :
|
||||
elif ob.Base.Name.startswith('this_is_a_bad_idea'):
|
||||
pass
|
||||
else:
|
||||
pass #There should be a fallback solution
|
||||
|
||||
elif ob.TypeId == "Part::Cut" :
|
||||
print "Cut"
|
||||
csg.write("difference() {\n")
|
||||
process_object(csg,ob.Base)
|
||||
process_object(csg,ob.Tool)
|
||||
csg.write("}\n")
|
||||
|
||||
elif ob.Type == "Part::Fuse" :
|
||||
elif ob.TypeId == "Part::Fuse" :
|
||||
print "union"
|
||||
csg.write("union() {\n")
|
||||
process_object(csg,ob.Base)
|
||||
process_object(csg,ob.Tool)
|
||||
csg.write("}\n")
|
||||
|
||||
elif ob.Type == "Part::Common" :
|
||||
elif ob.TypeId == "Part::Common" :
|
||||
print "intersection"
|
||||
csg.write("intersection() {\n")
|
||||
process_object(csg,ob.Base)
|
||||
process_object(csg,ob.Tool)
|
||||
csg.write("}\n")
|
||||
|
||||
elif ob.Type == "Part::MultiFuse" :
|
||||
elif ob.TypeId == "Part::MultiFuse" :
|
||||
print "Multi Fuse / union"
|
||||
csg.write("union() {\n")
|
||||
for subobj in ob.Shapes:
|
||||
process_object(csg,subobj)
|
||||
csg.write("}\n")
|
||||
|
||||
elif ob.Type == "Part::Common" :
|
||||
elif ob.TypeId == "Part::Common" :
|
||||
print "Multi Common / intersection"
|
||||
csg.write("intersection() {\n")
|
||||
for subobj in ob.Shapes:
|
||||
|
@ -241,7 +247,7 @@ def export(exportList,filename):
|
|||
for ob in exportList:
|
||||
print ob
|
||||
print "Name : "+ob.Name
|
||||
print "Type : "+ob.Type
|
||||
print "Type : "+ob.TypeId
|
||||
print "Shape : "
|
||||
print ob.Shape
|
||||
process_object(csg,ob)
|
||||
|
|
|
@ -73,10 +73,16 @@ def open(filename):
|
|||
doc = FreeCAD.newDocument(docname)
|
||||
if filename.lower().endswith('.scad'):
|
||||
tmpfile=callopenscad(filename)
|
||||
pathName = '' #https://github.com/openscad/openscad/issues/128
|
||||
#pathName = os.getcwd() #https://github.com/openscad/openscad/issues/128
|
||||
if workaroundforissue128needed():
|
||||
pathName = '' #https://github.com/openscad/openscad/issues/128
|
||||
#pathName = os.getcwd() #https://github.com/openscad/openscad/issues/128
|
||||
else:
|
||||
pathName = os.path.dirname(os.path.normpath(filename))
|
||||
processcsg(tmpfile)
|
||||
os.unlink(tmpfile)
|
||||
try:
|
||||
os.unlink(tmpfile)
|
||||
except OSError:
|
||||
pass
|
||||
else:
|
||||
pathName = os.path.dirname(os.path.normpath(filename))
|
||||
processcsg(filename)
|
||||
|
@ -94,10 +100,16 @@ def insert(filename,docname):
|
|||
importgroup = doc.addObject("App::DocumentObjectGroup",groupname)
|
||||
if filename.lower().endswith('.scad'):
|
||||
tmpfile=callopenscad(filename)
|
||||
pathName = '' #https://github.com/openscad/openscad/issues/128
|
||||
#pathName = os.getcwd() #https://github.com/openscad/openscad/issues/128
|
||||
if workaroundforissue128needed():
|
||||
pathName = '' #https://github.com/openscad/openscad/issues/128
|
||||
#pathName = os.getcwd() #https://github.com/openscad/openscad/issues/128
|
||||
else:
|
||||
pathName = os.path.dirname(os.path.normpath(filename))
|
||||
processcsg(tmpfile)
|
||||
os.unlink(tmpfile)
|
||||
try:
|
||||
os.unlink(tmpfile)
|
||||
except OSError:
|
||||
pass
|
||||
else:
|
||||
pathName = os.path.dirname(os.path.normpath(filename))
|
||||
processcsg(filename)
|
||||
|
@ -477,7 +489,7 @@ def process_rotate_extrude(obj):
|
|||
ViewProviderTree(newobj.ViewObject)
|
||||
else:
|
||||
newobj.ViewObject.Proxy = 0
|
||||
myrev.ViewObject.hide()
|
||||
myrev.ViewObject.hide()
|
||||
return(newobj)
|
||||
|
||||
def p_rotate_extrude_action(p):
|
||||
|
|
|
@ -659,14 +659,18 @@ def readfile(filename):
|
|||
isopenscad = relname.lower().endswith('.scad')
|
||||
if isopenscad:
|
||||
tmpfile=callopenscad(filename)
|
||||
lastimportpath = os.getcwd() #https://github.com/openscad/openscad/issues/128
|
||||
if OpenSCADUtils.workaroundforissue128needed():
|
||||
lastimportpath = os.getcwd() #https://github.com/openscad/openscad/issues/128
|
||||
f = pythonopen(tmpfile)
|
||||
else:
|
||||
f = pythonopen(filename)
|
||||
rootnode=parsenode(f.read())[0]
|
||||
f.close()
|
||||
if isopenscad:
|
||||
os.unlink(tmpfile)
|
||||
if isopenscad and tmpfile:
|
||||
try:
|
||||
os.unlink(tmpfile)
|
||||
except OSError:
|
||||
pass
|
||||
return rootnode.flattengroups()
|
||||
|
||||
def open(filename):
|
||||
|
|
Loading…
Reference in New Issue
Block a user