Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
OpenSCAD use PythonFeatures for hull and minkowski
  • Loading branch information
5263 authored and yorikvanhavre committed Feb 20, 2014
1 parent de038b3 commit 0e6b7a6
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 38 deletions.
24 changes: 24 additions & 0 deletions src/Mod/OpenSCAD/OpenSCADFeatures.py
Expand Up @@ -448,6 +448,30 @@ def createGeometry(self,fp):
if fp.Base and fp.Offset:
fp.Shape=fp.Base.Shape.makeOffsetShape(fp.Offset,1e-6)

class CGALFeature:
def __init__(self,obj,opname=None,children=None,arguments=None):
obj.addProperty("App::PropertyLinkList",'Children','OpenSCAD',"Base Objects")
obj.addProperty("App::PropertyString",'Arguments','OpenSCAD',"Arguments")
obj.addProperty("App::PropertyString",'Operation','OpenSCAD',"Operation")
obj.Proxy = self
if opname:
obj.Operation = opname
if children:
obj.Children = children
if arguments:
obj.Arguments = arguments

def execute(self,fp):
#arguments are ignored
maxmeshpoints = None #TBD: add as property
import Part,OpenSCADUtils
shape = OpenSCADUtils.process_ObjectsViaOpenSCADShape(fp.Document,fp.Children,\
fp.Operation, maxmeshpoints=maxmeshpoints)
if shape:
fp.Shape = shape
else:
raise ValueError

def makeSurfaceVolume(filename):
import FreeCAD,Part
f1=open(filename)
Expand Down
58 changes: 36 additions & 22 deletions src/Mod/OpenSCAD/OpenSCADUtils.py
Expand Up @@ -110,7 +110,7 @@ def check_output2(*args,**kwargs):
raise OpenSCADError('%s\n' % stdoutd.strip())
#raise Exception,'stdout %s\n stderr%s' %(stdoutd,stderrd)
if stdoutd.strip():
FreeCAD.Console.PrintWarning(stdoutd+u'\n')
FreeCAD.Console.PrintMessage(stdoutd+u'\n')
return stdoutd

osfilename = FreeCAD.ParamGet(\
Expand Down Expand Up @@ -280,46 +280,43 @@ def meshoponobjs(opname,inobjs):
else:
return (None,[])

def process2D_ObjectsViaOpenSCAD(ObjList,Operation,doc=None):
def process2D_ObjectsViaOpenSCADShape(ObjList,Operation,doc):
import FreeCAD,importDXF
import os,tempfile
#print "process2D"
doc = doc or FreeCAD.activeDocument()
dir1=tempfile.gettempdir()
filenames = []
#print "Export DXF"
for item in ObjList :
outputfilename=os.path.join(dir1,'%s.dxf' % tempfilenamegen.next())
#print "Call Export : "+outputfilename
importDXF.export([item],outputfilename,True,True)
#print "File Exported"
filenames.append(outputfilename)
dxfimports = ' '.join("import(file = \"%s\");" % \
#filename \
os.path.split(filename)[1] for filename in filenames)
#print "Call OpenSCAD : "+dxfimports
tmpfilename = callopenscadstring('%s(){%s}' % (Operation,dxfimports),'dxf')
#from importCSG import processDXF #import the result
#obj = processDXF(tmpfilename,None)
from OpenSCAD2Dgeom import importDXFface
#print "Import DXF"
# TBD: assure the given doc is active
face = importDXFface(tmpfilename,None,None)
#print "Add Hull"
obj=doc.addObject('Part::Feature',Operation)
obj.Shape=face
# Hide Children
if FreeCAD.GuiUp:
for index in ObjList :
index.ViewObject.hide()
#clean up
filenames.append(tmpfilename) #delete the ouptut file as well
try:
os.unlink(tmpfilename)
except OSError:
pass
return face

def process2D_ObjectsViaOpenSCAD(ObjList,Operation,doc=None):
import FreeCAD
doc = doc or FreeCAD.activeDocument()
face=process2D_ObjectsViaOpenSCADShape(ObjList,Operation,doc)
obj=doc.addObject('Part::Feature',Operation)
obj.Shape=face
# Hide Children
if FreeCAD.GuiUp:
for index in ObjList :
index.ViewObject.hide()
return(obj)

def process3D_ObjectsViaOpenSCAD(doc,ObjList,Operation):
def process3D_ObjectsViaOpenSCADShape(ObjList,Operation,maxmeshpoints=None):
import FreeCAD,Mesh,Part
params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/OpenSCAD")
if False: # disabled due to issue 1292
Expand All @@ -332,25 +329,42 @@ def process3D_ObjectsViaOpenSCAD(doc,ObjList,Operation):
meshes = [Mesh.Mesh(obj.Shape.tessellate(params.GetFloat(\
'meshmaxlength',1.0))) for obj in ObjList]
if max(mesh.CountPoints for mesh in meshes) < \
params.GetInt('tempmeshmaxpoints',5000):
(maxmeshpoints or params.GetInt('tempmeshmaxpoints',5000)):
stlmesh = meshoptempfile(Operation,meshes)
sh=Part.Shape()
sh.makeShapeFromMesh(stlmesh.Topology,0.1)
solid = Part.Solid(sh)
obj=doc.addObject('Part::Feature',Operation) #non parametric objec
solid=solid.removeSplitter()
if solid.Volume < 0:
solid.complement()
return solid

def process3D_ObjectsViaOpenSCAD(doc,ObjList,Operation):
solid = process3D_ObjectsViaOpenSCADShape(ObjList,Operation)
if solid is not None:
obj=doc.addObject('Part::Feature',Operation) #non parametric objec
obj.Shape=solid#.removeSplitter()
if FreeCAD.GuiUp:
for index in ObjList :
index.ViewObject.hide()
return(obj)

def process_ObjectsViaOpenSCADShape(doc,children,name,maxmeshpoints=None):
if all((not obj.Shape.isNull() and obj.Shape.Volume == 0) \
for obj in children):
return process2D_ObjectsViaOpenSCADShape(children,name,doc)
elif all((not obj.Shape.isNull() and obj.Shape.Volume > 0) \
for obj in children):
return process3D_ObjectsViaOpenSCADShape(children,name,maxmeshpoints)
else:
import FreeCAD
FreeCAD.Console.PrintError( unicode(translate('OpenSCAD',\
"Error all shapes must be either 2D or both must be 3D"))+u'\n')

def process_ObjectsViaOpenSCAD(doc,children,name):
if all((not obj.Shape.isNull() and obj.Shape.Volume == 0) \
for obj in children):
return process2D_ObjectsViaOpenSCAD(children,name)
return process2D_ObjectsViaOpenSCAD(children,name,doc)
elif all((not obj.Shape.isNull() and obj.Shape.Volume > 0) \
for obj in children):
return process3D_ObjectsViaOpenSCAD(doc,children,name)
Expand Down
32 changes: 16 additions & 16 deletions src/Mod/OpenSCAD/importCSG.py
Expand Up @@ -46,12 +46,10 @@
import ply.yacc as yacc
import Part

from OpenSCADFeatures import RefineShape
from OpenSCADFeatures import Frustum
from OpenSCADFeatures import *
#from OpenSCAD2Dgeom import *
from OpenSCADUtils import *
isspecialorthogonaldeterminant = isspecialorthogonalpython
from OpenSCADFeatures import Twist

if open.__module__ == '__builtin__':
pythonopen = open # to distinguish python built-in open function from the one declared here
Expand Down Expand Up @@ -357,26 +355,28 @@ def placeholder(name,children,arguments):
#don't hide the children
return newobj

def CGALorPlaceholder(name,children,arguments=[]):
'''Tries to perform a CGAL opertion by calling scad
if it fails it creates a placeholder object to continue parsing
'''
if any(obj.Shape.isNull() for obj in children):
doc.recompute() #we need valid shapes
newobj = process_ObjectsViaOpenSCAD(doc,children,name)
if newobj is not None :
return newobj
else:
return placeholder(name,children,arguments)
def CGALFeatureObj(name,children,arguments=[]):
myobj=doc.addObject("Part::FeaturePython",name)
CGALFeature(myobj,name,children,str(arguments))
if gui:
for subobj in children:
subobj.ViewObject.hide()
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/OpenSCAD").\
GetBool('useViewProviderTree'):
from OpenSCADFeatures import ViewProviderTree
ViewProviderTree(myobj.ViewObject)
else:
myobj.ViewObject.Proxy = 0
return myobj

def p_hull_action(p):
'hull_action : hull LPAREN RPAREN OBRACE block_list EBRACE'
p[0] = [ CGALorPlaceholder(p[1],p[5]) ]
p[0] = [ CGALFeatureObj(p[1],p[5]) ]

def p_minkowski_action(p):
'''
minkowski_action : minkowski LPAREN keywordargument_list RPAREN OBRACE block_list EBRACE'''
p[0] = [ CGALorPlaceholder(p[1],p[6],p[3]) ]
p[0] = [ CGALFeatureObj(p[1],p[6],p[3]) ]

def p_not_supported(p):
'''
Expand Down

0 comments on commit 0e6b7a6

Please sign in to comment.