diff --git a/src/Mod/Path/PathScripts/PathJobGui.py b/src/Mod/Path/PathScripts/PathJobGui.py index 2169b2a962..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,21 +54,17 @@ 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): return QtCore.QCoreApplication.translate(context, text, disambig) + 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()) @@ -303,7 +307,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 +369,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 +466,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 +502,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 +537,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 +676,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 +882,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 +894,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,32 +906,27 @@ 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) 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 +938,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) @@ -988,9 +985,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): @@ -1040,10 +1037,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) @@ -1134,6 +1131,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 +1149,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) @@ -1201,7 +1204,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) @@ -1351,7 +1354,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()