From d07319e4d2d969abf79ea5ee135ae9dacfd6637c Mon Sep 17 00:00:00 2001 From: Markus Lampert Date: Fri, 4 Aug 2017 21:00:26 -0700 Subject: [PATCH] Fixed issues with BaseGeometry UI processing and extended interface to support multiple shapes. --- src/Mod/Path/PathScripts/PathAreaOp.py | 34 +++++----- src/Mod/Path/PathScripts/PathAreaOpGui.py | 75 ++++++++++++++--------- src/Mod/Path/PathScripts/PathContour.py | 9 ++- src/Mod/Path/PathScripts/PathPocket.py | 57 +++++------------ 4 files changed, 85 insertions(+), 90 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathAreaOp.py b/src/Mod/Path/PathScripts/PathAreaOp.py index 5053372c85..640c814338 100644 --- a/src/Mod/Path/PathScripts/PathAreaOp.py +++ b/src/Mod/Path/PathScripts/PathAreaOp.py @@ -111,6 +111,7 @@ class ObjectOp(object): pass def onChanged(self, obj, prop): + #PathLog.track(obj.Label, prop) if prop in ['AreaParams', 'PathParams', 'removalshape']: obj.setEditorMode(prop, 2) self.opOnChanged(obj, prop) @@ -174,8 +175,10 @@ class ObjectOp(object): PathLog.debug("Area with params: {}".format(area.getParams())) - sections = area.makeSections(mode=0, project=True, heights=heights) + sections = area.makeSections(mode=0, project=self.opUseProjection(obj), heights=heights) + PathLog.debug("sections = %s" % sections) shapelist = [sec.getShape() for sec in sections] + PathLog.debug("shapelist = %s" % shapelist) pathParams = self.opPathParams(obj) pathParams['shapes'] = shapelist @@ -192,6 +195,7 @@ class ObjectOp(object): pathParams['start'] = obj.StartPoint obj.PathParams = str({key: value for key, value in pathParams.items() if key != 'shapes'}) + PathLog.debug("Path with params: {}".format(obj.PathParams)) (pp, end_vector) = Path.fromShapes(**pathParams) PathLog.debug('pp: {}, end vector: {}'.format(pp, end_vector)) @@ -244,23 +248,25 @@ class ObjectOp(object): else: self.radius = tool.Diameter/2 - commandlist = [] - commandlist.append(Path.Command("(" + obj.Label + ")")) - - shape = self.opShape(obj, commandlist) - if FeatureStartPoint and obj.UseStartPoint: start = obj.StartPoint else: start = FreeCAD.Vector() - try: - (pp, sim) = self._buildPathArea(obj, shape, start, getsim) - commandlist.extend(pp.Commands) - except Exception as e: - FreeCAD.Console.PrintError(e) - FreeCAD.Console.PrintError("Something unexpected happened. Check project and tool config.") - sim = None + commandlist = [] + commandlist.append(Path.Command("(" + obj.Label + ")")) + + shapes = self.opShapes(obj, commandlist) + + sims = [] + for shape in shapes: + try: + (pp, sim) = self._buildPathArea(obj, shape, start, getsim) + commandlist.extend(pp.Commands) + sims.append(sim) + except Exception as e: + FreeCAD.Console.PrintError(e) + FreeCAD.Console.PrintError("Something unexpected happened. Check project and tool config.") # Let's finish by rapid to clearance...just for safety @@ -269,7 +275,7 @@ class ObjectOp(object): PathLog.track() path = Path.Path(commandlist) obj.Path = path - return sim + return sims def addBase(self, obj, base, sub=""): PathLog.track() diff --git a/src/Mod/Path/PathScripts/PathAreaOpGui.py b/src/Mod/Path/PathScripts/PathAreaOpGui.py index cf9258f4aa..32f0169fea 100644 --- a/src/Mod/Path/PathScripts/PathAreaOpGui.py +++ b/src/Mod/Path/PathScripts/PathAreaOpGui.py @@ -39,6 +39,10 @@ from PySide import QtCore, QtGui # 2 ... multi panel layout TaskPanelLayout = 2 + +PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) +PathLog.trackModule(PathLog.thisModule()) + def translate(context, text, disambig=None): return QtCore.QCoreApplication.translate(context, text, disambig) @@ -49,6 +53,9 @@ class ViewProvider(object): PathLog.track() vobj.Proxy = self + #for sel in FreeCADGui.Selection.getSelectionEx(): + # if sel[0].HasSubObjects: + def attach(self, vobj): PathLog.track() self.Object = vobj.Object @@ -180,9 +187,9 @@ class TaskPanelBaseGeometryPage(TaskPanelPage): #FreeCADGui.updateGui() def supportsEdges(self): - return self.support & PathAreaOp.FeatureBaseEdges + return self.supports & PathAreaOp.FeatureBaseEdges def supportsFaces(self): - return self.support & PathAreaOp.FeatureBaseFaces + return self.supports & PathAreaOp.FeatureBaseFaces def featureName(self): if self.supportsEdges() and self.supportsFaces(): return 'features' @@ -192,38 +199,36 @@ class TaskPanelBaseGeometryPage(TaskPanelPage): return 'edges' return 'nothing' - def addBase(self): - selection = FreeCADGui.Selection.getSelectionEx() - + def addBaseGeometry(self, selection): if len(selection) != 1: - PahtLog.error(translate("PathProject", "Please select %s from a single solid" % self.featureName())) - return + PathLog.error(translate("PathProject", "Please select %s from a single solid" % self.featureName())) + return False sel = selection[0] if not sel.HasSubObjects: - PahtLog.error(translate("PathProject", "Please select %s of a solid" % self.featureName())) - return + PathLog.error(translate("PathProject", "Please select %s of a solid" % self.featureName())) + return False if not self.supportsEdges() and selection[0].SubObjects[0].ShapeType == "Edge": - PahtLog.error(translate("PathProject", "Please select only %s of a solid" % self.featureName())) - return + PathLog.error(translate("PathProject", "Please select only %s of a solid" % self.featureName())) + return False if not self.supportsFaces() and selection[0].SubObjects[0].ShapeType == "Face": - PahtLog.error(translate("PathProject", "Please select only %s of a solid" % self.featureName())) - return - for i in sel.SubElementNames: - self.obj.Proxy.addBase(self.obj, sel.Object, i) + PathLog.error(translate("PathProject", "Please select only %s of a solid" % self.featureName())) + return False - self.obj.Proxy.execute(self.obj) - self.setFields() + for sub in sel.SubElementNames: + self.obj.Proxy.addBase(self.obj, sel.Object, sub) + return True + + def addBase(self): + if self.addBaseGeometry(FreeCADGui.Selection.getSelectionEx()): + #self.obj.Proxy.execute(self.obj) + self.setFields(self.obj) def deleteBase(self): - newlist = [] - for item in self.form.baseList.selectedItems(): - obj = item.data(self.DataObject) - sub = itme.data(self.DataObjectSub) - for base in self.obj.Base: - if base[0].Name != obj.Name and base[1] != sub: - newlist.append(base) + PathLog.track() + selected = self.form.baseList.selectedItems() + for item in selected: self.form.baseList.takeItem(self.form.baseList.row(item)) - self.obj.Base = newlist + self.updateBase() #self.obj.Proxy.execute(self.obj) #FreeCAD.ActiveDocument.recompute() @@ -232,8 +237,10 @@ class TaskPanelBaseGeometryPage(TaskPanelPage): for i in range(self.form.baseList.count()): item = self.form.baseList.item(i) obj = item.data(self.DataObject) - sub = item.data(self.DataObjectSub) - newlist.append((obj, sub)) + sub = str(item.data(self.DataObjectSub)) + base = (obj, sub) + newlist.append(base) + PathLog.debug("Setting new base: %s -> %s" % (self.obj.Base, newlist)) self.obj.Base = newlist #self.obj.Proxy.execute(self.obj) @@ -305,6 +312,7 @@ class TaskPanelDepthsPage(TaskPanelDepthsWoFinishPage): class TaskPanel(object): def __init__(self, obj, deleteOnReject, opPage, selectionFactory): + PathLog.track(obj.Label, deleteOnReject, opPage, selectionFactory) FreeCAD.ActiveDocument.openTransaction(translate("Path_AreaOp", "AreaOp Operation")) self.deleteOnReject = deleteOnReject self.featurePages = [] @@ -363,8 +371,7 @@ class TaskPanel(object): FreeCADGui.ActiveDocument.resetEdit() FreeCAD.ActiveDocument.commitTransaction() FreeCADGui.Selection.removeObserver(self.s) - if self.isDirty(): - FreeCAD.ActiveDocument.recompute() + FreeCAD.ActiveDocument.recompute() def reject(self): FreeCADGui.Control.closeDialog() @@ -380,8 +387,8 @@ class TaskPanel(object): def clicked(self, button): if button == QtGui.QDialogButtonBox.Apply: self.panelGetFields() - FreeCAD.ActiveDocument.recompute() self.setClean() + FreeCAD.ActiveDocument.recompute() def panelGetFields(self): PathLog.track() @@ -403,6 +410,14 @@ class TaskPanel(object): def setupUi(self): PathLog.track() + + if self.deleteOnReject and PathAreaOp.FeatureBaseGeometry & self.obj.Proxy.opFeatures(self.obj): + sel = FreeCADGui.Selection.getSelectionEx() + if len(sel) == 1 and sel[0].Object != self.obj: + for page in self.featurePages: + if hasattr(page, 'addBase'): + page.addBaseGeometry(sel) + self.panelSetFields() for page in self.featurePages: page.pageRegisterSignalHandlers() diff --git a/src/Mod/Path/PathScripts/PathContour.py b/src/Mod/Path/PathScripts/PathContour.py index 45fbf04b33..b7104fd285 100644 --- a/src/Mod/Path/PathScripts/PathContour.py +++ b/src/Mod/Path/PathScripts/PathContour.py @@ -58,6 +58,9 @@ class ObjectContour(PathAreaOp.ObjectOp): def opFeatures(self, obj): return PathAreaOp.FeatureTool | PathAreaOp.FeatureDepths | PathAreaOp.FeatureHeights | PathAreaOp.FeatureStartPoint + def opUseProjection(self, obj): + return True + def initOperation(self, obj): PathLog.track() @@ -97,7 +100,7 @@ class ObjectContour(PathAreaOp.ObjectOp): obj.MiterLimit = 0.1 - def opShape(self, obj, commandlist): + def opShapes(self, obj, commandlist): if obj.UseComp: commandlist.append(Path.Command("(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")")) else: @@ -120,10 +123,10 @@ class ObjectContour(PathAreaOp.ObjectOp): for shape in shapes: f = Part.makeFace([shape], 'Part::FaceMakerSimple') thickness = baseobject.Group[0].Source.Thickness - return f.extrude(FreeCAD.Vector(0, 0, thickness)) + return [f.extrude(FreeCAD.Vector(0, 0, thickness))] if hasattr(baseobject, "Shape") and not isPanel: - return PathUtils.getEnvelope(partshape=baseobject.Shape, subshape=None, depthparams=self.depthparams) + return [PathUtils.getEnvelope(partshape=baseobject.Shape, subshape=None, depthparams=self.depthparams)] def opAreaParams(self, obj): params = {'Fill': 0, 'Coplanar': 2} diff --git a/src/Mod/Path/PathScripts/PathPocket.py b/src/Mod/Path/PathScripts/PathPocket.py index 63057ba240..2de69e9496 100644 --- a/src/Mod/Path/PathScripts/PathPocket.py +++ b/src/Mod/Path/PathScripts/PathPocket.py @@ -33,7 +33,7 @@ from PySide import QtCore """Path Pocket object and FreeCAD command""" -if False: +if True: PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) PathLog.trackModule(PathLog.thisModule()) else: @@ -64,6 +64,9 @@ class ObjectPocket(PathAreaOp.ObjectOp): def opFeatures(self, obj): return PathAreaOp.FeatureTool | PathAreaOp.FeatureDepths | PathAreaOp.FeatureHeights | PathAreaOp.FeatureStartPoint | PathAreaOp.FeatureBaseFaces | PathAreaOp.FeatureFinishDepth + def opUseProjection(self, obj): + return False + def opShapeForDepths(self, obj): job = PathUtils.findParentJob(obj) if job and job.Base: @@ -72,44 +75,6 @@ class ObjectPocket(PathAreaOp.ObjectOp): PathLog.warning("No job object found (%s), or job has no Base." % job) return None - def addpocketbase(self, obj, ss, sub=""): - PathLog.track() - baselist = obj.Base - if baselist is None: - baselist = [] - if len(baselist) == 0: # When adding the first base object, guess at heights - - try: - bb = ss.Shape.BoundBox # parent boundbox - subobj = ss.Shape.getElement(sub) - fbb = subobj.BoundBox # feature boundbox - obj.StartDepth = bb.ZMax - obj.ClearanceHeight = bb.ZMax + 5.0 - obj.SafeHeight = bb.ZMax + 3.0 - - if fbb.ZMax == fbb.ZMin and fbb.ZMax == bb.ZMax: # top face - obj.FinalDepth = bb.ZMin - elif fbb.ZMax > fbb.ZMin and fbb.ZMax == bb.ZMax: # vertical face, full cut - obj.FinalDepth = fbb.ZMin - elif fbb.ZMax > fbb.ZMin and fbb.ZMin > bb.ZMin: # internal vertical wall - obj.FinalDepth = fbb.ZMin - elif fbb.ZMax == fbb.ZMin and fbb.ZMax > bb.ZMin: # face/shelf - obj.FinalDepth = fbb.ZMin - else: # catch all - obj.FinalDepth = bb.ZMin - except: - obj.StartDepth = 5.0 - obj.ClearanceHeight = 10.0 - obj.SafeHeight = 8.0 - - item = (ss, sub) - if item in baselist: - PathLog.warning(translate("Path", "this object already in the list" + "\n")) - else: - baselist.append(item) - obj.Base = baselist - self.execute(obj) - def opAreaParams(self, obj): params = {} params['Fill'] = 0 @@ -136,7 +101,7 @@ class ObjectPocket(PathAreaOp.ObjectOp): params['sort_mode'] = 2 return params - def opShape(self, obj, commandlist): + def opShapes(self, obj, commandlist): PathLog.track() job = PathUtils.findParentJob(obj) @@ -146,6 +111,7 @@ class ObjectPocket(PathAreaOp.ObjectOp): if obj.Base: PathLog.debug("base items exist. Processing...") + removalshapes = [] for b in obj.Base: PathLog.debug("Base item: {}".format(b)) for sub in b[1]: @@ -157,22 +123,26 @@ class ObjectPocket(PathAreaOp.ObjectOp): env = PathUtils.getEnvelope(baseobject.Shape, subshape=shape, depthparams=self.depthparams) obj.removalshape = env.cut(baseobject.Shape) + removalshapes.append(obj.removalshape) else: # process the job base object as a whole PathLog.debug("processing the whole job base object") env = PathUtils.getEnvelope(baseobject.Shape, subshape=None, depthparams=self.depthparams) obj.removalshape = env.cut(baseobject.Shape) - return obj.removalshape + removalshapes = [obj.removalshape] + return removalshapes def opSetDefaultValues(self, obj): obj.StepOver = 100 obj.ZigZagAngle = 45 def opOnChanged(self, obj, prop): + #PathLog.track(obj.Label, prop) if prop == 'Base' and len(obj.Base) == 1: try: + (base, sub) = obj.Base[0] bb = base.Shape.BoundBox # parent boundbox - subobj = base.Shape.getElement(sub) + subobj = base.Shape.getElement(sub[0]) fbb = subobj.BoundBox # feature boundbox obj.StartDepth = bb.ZMax obj.ClearanceHeight = bb.ZMax + 5.0 @@ -188,7 +158,8 @@ class ObjectPocket(PathAreaOp.ObjectOp): obj.FinalDepth = fbb.ZMin else: # catch all obj.FinalDepth = bb.ZMin - except: + except Exception as e: + PathLog.error(translate("PathPocket", "Error in calculating depths: %s" % e)) obj.StartDepth = 5.0 obj.ClearanceHeight = 10.0 obj.SafeHeight = 8.0