From 811fa90efe4446e9ef8f9ef98d64b1c2bfefc1d3 Mon Sep 17 00:00:00 2001 From: Daniel Wood Date: Tue, 27 Oct 2020 21:28:19 +0000 Subject: [PATCH 1/4] [Path] Enable Face selection for axis selection (JobSetUp) --- src/Mod/Path/PathScripts/PathJobGui.py | 63 +++++++++++++------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathJobGui.py b/src/Mod/Path/PathScripts/PathJobGui.py index 2169b2a962..a534167fce 100644 --- a/src/Mod/Path/PathScripts/PathJobGui.py +++ b/src/Mod/Path/PathScripts/PathJobGui.py @@ -916,18 +916,13 @@ class TaskPanel: self.template.updateUI() def modelSetAxis(self, axis): - def flipSel(sel): - PathLog.debug("flip") - p = sel.Object.Placement - loc = sel.Object.Placement.Base - rot = FreeCAD.Rotation(FreeCAD.Vector(1 - axis.x, 1 - axis.y, 1 - axis.z), 180) - sel.Object.Placement = FreeCAD.Placement(loc, p.Rotation.multiply(rot)) - - def rotateSel(sel, n): - # p = sel.Object.Placement - # loc = sel.Object.Placement.Base + def alignSel(sel, n, flip=False): + PathLog.debug("alignSel") + vector = axis + if flip: + vector = n.negative() r = axis.cross(n) # rotation axis - a = DraftVecUtils.angle(n, axis, r) * 180 / math.pi + a = DraftVecUtils.angle(n, vector, r) * 180 / math.pi PathLog.debug("oh boy: (%.2f, %.2f, %.2f) -> %.2f" % (r.x, r.y, r.z, a)) Draft.rotate(sel.Object, a, axis=r) @@ -939,28 +934,26 @@ class TaskPanel: selFeature = feature sub = sel.Object.Shape.getElement(feature) if 'Face' == sub.ShapeType: - n = sub.Surface.Axis + n = sub.normalAt(0,0).negative() if sub.Orientation == 'Reversed': n = FreeCAD.Vector() - n PathLog.debug("(%.2f, %.2f, %.2f) -> reversed (%s)" % (n.x, n.y, n.z, sub.Orientation)) else: PathLog.debug("(%.2f, %.2f, %.2f) -> forward (%s)" % (n.x, n.y, n.z, sub.Orientation)) - if PathGeom.pointsCoincide(axis, n): - PathLog.debug("face properly oriented (%.2f, %.2f, %.2f)" % (n.x, n.y, n.z)) + if PathGeom.pointsCoincide(axis, n) or PathGeom.pointsCoincide(axis, FreeCAD.Vector() - n): + alignSel(sel, n, True) else: - if PathGeom.pointsCoincide(axis, FreeCAD.Vector() - n): - flipSel(sel) - else: - rotateSel(sel, n) + alignSel(sel, n) + if 'Edge' == sub.ShapeType: n = (sub.Vertexes[1].Point - sub.Vertexes[0].Point).normalize() if PathGeom.pointsCoincide(axis, n) or PathGeom.pointsCoincide(axis, FreeCAD.Vector() - n): # Don't really know the orientation of an edge, so let's just flip the object # and if the user doesn't like it they can flip again - flipSel(sel) + alignSel(sel, n, True) else: - rotateSel(sel, n) + alignSel(sel, n) if selObject and selFeature: FreeCADGui.Selection.clearSelection() FreeCADGui.Selection.addSelection(selObject, selFeature) @@ -1134,6 +1127,17 @@ class TaskPanel: # no valid selection return False + def isValidAxisSelection(self, sel): + if sel.ShapeType in ['Vertex', 'Edge', 'Face']: + if hasattr(sel, 'Curve') and type(sel.Curve) in [Part.Circle]: + return False + if hasattr(sel, 'Surface') and sel.Surface.curvature(0,0,"Max") != 0: + return False + return True + + # no valid selection + return False + def updateSelection(self): # Remove Job object if present in Selection: source of phantom paths if self.obj in FreeCADGui.Selection.getSelection(): @@ -1141,26 +1145,21 @@ class TaskPanel: sel = FreeCADGui.Selection.getSelectionEx() + self.form.setOrigin.setEnabled(False) + self.form.moveToOrigin.setEnabled(False) + self.form.modelSetXAxis.setEnabled(False) + self.form.modelSetYAxis.setEnabled(False) + self.form.modelSetZAxis.setEnabled(False) + if len(sel) == 1 and len(sel[0].SubObjects) == 1: subObj = sel[0].SubObjects[0] if self.isValidDatumSelection(subObj): - self.form.modelSetXAxis.setEnabled(False) - self.form.modelSetYAxis.setEnabled(False) - self.form.modelSetZAxis.setEnabled(False) self.form.setOrigin.setEnabled(True) self.form.moveToOrigin.setEnabled(True) - else: + if self.isValidAxisSelection(subObj): self.form.modelSetXAxis.setEnabled(True) self.form.modelSetYAxis.setEnabled(True) self.form.modelSetZAxis.setEnabled(True) - self.form.setOrigin.setEnabled(False) - self.form.moveToOrigin.setEnabled(False) - else: - self.form.modelSetXAxis.setEnabled(False) - self.form.modelSetYAxis.setEnabled(False) - self.form.modelSetZAxis.setEnabled(False) - self.form.setOrigin.setEnabled(False) - self.form.moveToOrigin.setEnabled(False) if len(sel) == 0 or self.obj.Stock in [s.Object for s in sel]: self.form.centerInStock.setEnabled(False) From 7a55d5120de718dadf2c93ea0c2854ce0c47609d Mon Sep 17 00:00:00 2001 From: Daniel Wood Date: Wed, 28 Oct 2020 06:50:04 +0000 Subject: [PATCH 2/4] PEP8 whitespace fixes --- src/Mod/Path/PathScripts/PathJobGui.py | 41 +++++++++++++------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathJobGui.py b/src/Mod/Path/PathScripts/PathJobGui.py index a534167fce..ae4d1cb212 100644 --- a/src/Mod/Path/PathScripts/PathJobGui.py +++ b/src/Mod/Path/PathScripts/PathJobGui.py @@ -56,6 +56,7 @@ from pivy import coin def translate(context, text, disambig=None): return QtCore.QCoreApplication.translate(context, text, disambig) + LOGLEVEL = False if LOGLEVEL: @@ -303,7 +304,7 @@ class StockEdit(object): widget.hide() if select: self.form.stock.setCurrentIndex(self.Index) - editor = self.editorFrame() # pylint: disable=assignment-from-none + editor = self.editorFrame() # pylint: disable=assignment-from-none showHide(self.form.stockFromExisting, editor) showHide(self.form.stockFromBase, editor) showHide(self.form.stockCreateBox, editor) @@ -365,7 +366,7 @@ class StockFromBaseBoundBoxEdit(StockEdit): stock.ExtZneg = FreeCAD.Units.Quantity(self.form.stockExtZneg.text()) if 'zpos' in fields: stock.ExtZpos = FreeCAD.Units.Quantity(self.form.stockExtZpos.text()) - except Exception: # pylint: disable=broad-except + except Exception: # pylint: disable=broad-except pass def getFields(self, obj, fields=None): @@ -462,7 +463,7 @@ class StockCreateBoxEdit(StockEdit): obj.Stock.Height = FreeCAD.Units.Quantity(self.form.stockBoxHeight.text()) else: PathLog.error(translate('PathJob', 'Stock not a box!')) - except Exception: # pylint: disable=broad-except + except Exception: # pylint: disable=broad-except pass def setFields(self, obj): @@ -498,7 +499,7 @@ class StockCreateCylinderEdit(StockEdit): obj.Stock.Height = FreeCAD.Units.Quantity(self.form.stockCylinderHeight.text()) else: PathLog.error(translate('PathJob', 'Stock not a cylinder!')) - except Exception: # pylint: disable=broad-except + except Exception: # pylint: disable=broad-except pass def setFields(self, obj): @@ -533,7 +534,7 @@ class StockFromExistingEdit(StockEdit): def candidates(self, obj): solids = [o for o in obj.Document.Objects if PathUtil.isSolid(o)] - if hasattr(obj, 'Model'): + if hasattr(obj, 'Model'): job = obj else: job = PathUtils.findParentJob(obj) @@ -672,7 +673,7 @@ class TaskPanel: if self.form.wcslist.item(i).checkState() == QtCore.Qt.CheckState.Checked: flist.append(self.form.wcslist.item(i).text()) self.obj.Fixtures = flist - except Exception: # pylint: disable=broad-except + except Exception: # pylint: disable=broad-except FreeCAD.Console.PrintWarning("The Job was created without fixture support. Please delete and recreate the job\r\n") self.updateTooltips() @@ -878,7 +879,7 @@ class TaskPanel: elif 'Number' == prop: try: tc.ToolNumber = int(item.text()) - except Exception: # pylint: disable=broad-except + except Exception: # pylint: disable=broad-except pass item.setText("%d" % tc.ToolNumber) elif 'Spindle' == prop: @@ -890,7 +891,7 @@ class TaskPanel: speed = -speed tc.SpindleDir = rot tc.SpindleSpeed = speed - except Exception: # pylint: disable=broad-except + except Exception: # pylint: disable=broad-except pass item.setText("%s%g" % ('+' if tc.SpindleDir == 'Forward' else '-', tc.SpindleSpeed)) elif 'HorizFeed' == prop or 'VertFeed' == prop: @@ -902,14 +903,14 @@ class TaskPanel: elif FreeCAD.Units.Unit() == val.Unit: val = FreeCAD.Units.Quantity(item.text() + vUnit) setattr(tc, prop, val) - except Exception: # pylint: disable=broad-except + except Exception: # pylint: disable=broad-except pass item.setText("%g" % getattr(tc, prop).getValueAs(vUnit)) else: try: val = FreeCAD.Units.Quantity(item.text()) setattr(tc, prop, val) - except Exception: # pylint: disable=broad-except + except Exception: # pylint: disable=broad-except pass item.setText("%g" % getattr(tc, prop).Value) @@ -934,7 +935,7 @@ class TaskPanel: selFeature = feature sub = sel.Object.Shape.getElement(feature) if 'Face' == sub.ShapeType: - n = sub.normalAt(0,0).negative() + n = sub.normalAt(0, 0).negative() if sub.Orientation == 'Reversed': n = FreeCAD.Vector() - n PathLog.debug("(%.2f, %.2f, %.2f) -> reversed (%s)" % (n.x, n.y, n.z, sub.Orientation)) @@ -981,9 +982,9 @@ class TaskPanel: # if selection is not model, move the model too # if the selection is not stock and there is a stock, move the stock too for model in self.obj.Model.Group: - if model != selObject: + if model != selObject: Draft.move(model, offset) - if selObject != self.obj.Stock and self.obj.Stock: + if selObject != self.obj.Stock and self.obj.Stock: Draft.move(self.obj.Stock, offset) def modelMove(self, axis): @@ -1033,10 +1034,10 @@ class TaskPanel: p = FreeCAD.Vector() - sub.Curve.Location if 'Face' == sub.ShapeType: p = FreeCAD.Vector() - sub.BoundBox.Center - + if p: Draft.move(sel.Object, p) - + if selObject and selFeature: FreeCADGui.Selection.clearSelection() FreeCADGui.Selection.addSelection(selObject, selFeature) @@ -1130,9 +1131,9 @@ class TaskPanel: def isValidAxisSelection(self, sel): if sel.ShapeType in ['Vertex', 'Edge', 'Face']: if hasattr(sel, 'Curve') and type(sel.Curve) in [Part.Circle]: - return False - if hasattr(sel, 'Surface') and sel.Surface.curvature(0,0,"Max") != 0: - return False + return False + if hasattr(sel, 'Surface') and sel.Surface.curvature(0, 0, "Max") != 0: + return False return True # no valid selection @@ -1200,7 +1201,7 @@ class TaskPanel: # first remove all obsolete base models for model, count in PathUtil.keyValueIter(obsolete): - for i in range(count): # pylint: disable=unused-variable + for i in range(count): # pylint: disable=unused-variable # it seems natural to remove the last of all the base objects for a given model base = [b for b in obj.Model.Group if proxy.baseObject(obj, b) == model][-1] self.vproxy.forgetBaseVisibility(obj, base) @@ -1350,7 +1351,7 @@ def Create(base, template=None): obj.Document.recompute() obj.ViewObject.Proxy.editObject(obj.Stock) return obj - except Exception as exc: # pylint: disable=broad-except + except Exception as exc: # pylint: disable=broad-except PathLog.error(exc) traceback.print_exc() FreeCAD.ActiveDocument.abortTransaction() From 7618dba49d4b364ec53107600c5b8ad6da1679b8 Mon Sep 17 00:00:00 2001 From: Daniel Wood Date: Wed, 28 Oct 2020 17:09:49 +0000 Subject: [PATCH 3/4] silence lgtm warnings --- src/Mod/Path/PathScripts/PathJobGui.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathJobGui.py b/src/Mod/Path/PathScripts/PathJobGui.py index ae4d1cb212..9bd88db76a 100644 --- a/src/Mod/Path/PathScripts/PathJobGui.py +++ b/src/Mod/Path/PathScripts/PathJobGui.py @@ -60,8 +60,8 @@ def translate(context, text, disambig=None): LOGLEVEL = False if LOGLEVEL: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) + PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) # lgtm [py/unreachable-statement] + PathLog.trackModule(PathLog.thisModule()) # lgtm [py/unreachable-statement] else: PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) From e64cb66a322f36adda515d2c9f7e379de6c96223 Mon Sep 17 00:00:00 2001 From: Daniel Wood Date: Wed, 28 Oct 2020 17:10:51 +0000 Subject: [PATCH 4/4] Reorder imports to match PEP8 guidance --- src/Mod/Path/PathScripts/PathJobGui.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathJobGui.py b/src/Mod/Path/PathScripts/PathJobGui.py index 9bd88db76a..bf33a43fb9 100644 --- a/src/Mod/Path/PathScripts/PathJobGui.py +++ b/src/Mod/Path/PathScripts/PathJobGui.py @@ -22,8 +22,18 @@ # * * # *************************************************************************** + +from collections import Counter +from contextlib import contextmanager +import math +import traceback + +from pivy import coin +from PySide import QtCore, QtGui + import FreeCAD import FreeCADGui + import PathScripts.PathJob as PathJob import PathScripts.PathJobCmd as PathJobCmd import PathScripts.PathJobDlg as PathJobDlg @@ -37,8 +47,6 @@ import PathScripts.PathToolControllerGui as PathToolControllerGui import PathScripts.PathToolLibraryEditor as PathToolLibraryEditor import PathScripts.PathUtil as PathUtil import PathScripts.PathUtils as PathUtils -import math -import traceback # lazily loaded modules from lazy_loader.lazy_loader import LazyLoader @@ -46,11 +54,6 @@ Draft = LazyLoader('Draft', globals(), 'Draft') Part = LazyLoader('Part', globals(), 'Part') DraftVecUtils = LazyLoader('DraftVecUtils', globals(), 'DraftVecUtils') -from PySide import QtCore, QtGui -from collections import Counter -from contextlib import contextmanager -from pivy import coin - # Qt translation handling def translate(context, text, disambig=None):