From d97a393709706a675e97d6650a2ae578cfc40b7f Mon Sep 17 00:00:00 2001 From: Markus Lampert Date: Sun, 24 Jan 2021 18:35:36 -0800 Subject: [PATCH 1/6] Make PathOp rebust(er) against manual Base assignment --- src/Mod/Path/PathScripts/PathOp.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Mod/Path/PathScripts/PathOp.py b/src/Mod/Path/PathScripts/PathOp.py index 8b2679a295..c0e24b03b4 100644 --- a/src/Mod/Path/PathScripts/PathOp.py +++ b/src/Mod/Path/PathScripts/PathOp.py @@ -422,7 +422,10 @@ class ObjectOp(object): zmax = max(zmax, bb.ZMax) for sub in sublist: try: - fbb = base.Shape.getElement(sub).BoundBox + if sub: + fbb = base.Shape.getElement(sub).BoundBox + else: + fbb = base.Shape.BoundBox zmin = max(zmin, faceZmin(bb, fbb)) zmax = max(zmax, fbb.ZMax) except Part.OCCError as e: From 31c9dbafb2f8c6eb7f208f8dd2309488be7b086b Mon Sep 17 00:00:00 2001 From: Markus Lampert Date: Sun, 24 Jan 2021 18:41:09 -0800 Subject: [PATCH 2/6] Add support for multiple models to vcarve op. --- src/Mod/Path/PathScripts/PathVcarve.py | 31 +++++++++++++------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathVcarve.py b/src/Mod/Path/PathScripts/PathVcarve.py index dd713923d6..f9c08cc729 100644 --- a/src/Mod/Path/PathScripts/PathVcarve.py +++ b/src/Mod/Path/PathScripts/PathVcarve.py @@ -242,7 +242,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): edges.append(_getPartEdge(e, geom)) return edges - def buildPathMedial(self, obj, Faces): + def buildPathMedial(self, obj, faces): '''constructs a medial axis path using openvoronoi''' def insert_many_wires(vd, wires): @@ -271,7 +271,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): VD.clear() voronoiWires = [] - for f in Faces: + for f in faces: vd = Path.Voronoi() insert_many_wires(vd, f.Wires) @@ -321,31 +321,30 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): "Engraver Cutting Edge Angle must be < 180 degrees.") + "\n") return try: + faces = [] if obj.Base: PathLog.track() for base in obj.Base: - faces = [] for sub in base[1]: shape = getattr(base[0].Shape, sub) if isinstance(shape, Part.Face): faces.append(shape) - modelshape = Part.makeCompound(faces) + else: + for model in self.model: + if model.isDerivedFrom('Sketcher::SketchObject') or model.isDerivedFrom('Part::Part2DObject'): + faces.extend(model.Shape.Faces) - elif len(self.model) == 1 and self.model[0].isDerivedFrom('Sketcher::SketchObject') or \ - self.model[0].isDerivedFrom('Part::Part2DObject'): - PathLog.track() - - modelshape = self.model[0].Shape - self.buildPathMedial(obj, modelshape.Faces) + if faces: + self.buildPathMedial(obj, faces) + else: + PathLog.error(translate('PathVcarve', 'The Job Base Object has no engraveable element. Engraving operation will produce no output.')) except Exception as e: - PathLog.error(e) - traceback.print_exc() - PathLog.error(translate('PathVcarve', 'The Job Base Object has \ -no engraveable element. Engraving \ -operation will produce no output.')) - raise e + #PathLog.error(e) + #traceback.print_exc() + PathLog.error(translate('PathVcarve', 'Error processing Base object. Engraving operation will produce no output.')) + #raise e def opUpdateDepths(self, obj, ignoreErrors=False): '''updateDepths(obj) ... engraving is always done at the top most z-value''' From c2fa48ba901dfb8e2616e50ccc808ff892f3ef37 Mon Sep 17 00:00:00 2001 From: Markus Lampert Date: Sun, 24 Jan 2021 20:52:43 -0800 Subject: [PATCH 3/6] Disabled base geometry-list resizing since it makes the list unusable on HDP monitors. --- .../Resources/panels/PageBaseGeometryEdit.ui | 180 +++++++++--------- src/Mod/Path/PathScripts/PathOpGui.py | 23 ++- 2 files changed, 98 insertions(+), 105 deletions(-) diff --git a/src/Mod/Path/Gui/Resources/panels/PageBaseGeometryEdit.ui b/src/Mod/Path/Gui/Resources/panels/PageBaseGeometryEdit.ui index 3ea92feef0..42441cbc2c 100644 --- a/src/Mod/Path/Gui/Resources/panels/PageBaseGeometryEdit.ui +++ b/src/Mod/Path/Gui/Resources/panels/PageBaseGeometryEdit.ui @@ -6,8 +6,8 @@ 0 0 - 400 - 250 + 476 + 342 @@ -23,94 +23,28 @@ :/icons/Path_BaseGeometry.svg:/icons/Path_BaseGeometry.svg - - - - - - - Import - - - - - - - <html><head/><body><p>Remove the selected list items from the list of base geometries. The operation will not be applied to them.</p></body></html> - - - Remove - - - - - - - - 0 - 0 - - - - <html><head/><body><p>List of operations with Base Geometry in current Job.</p></body></html> - - - - - - - true - - - - 0 - 0 - - - - <html><head/><body><p>Select one or more features in the 3d view and press 'Add' to add them as the base items for this operation.</p><p><br/></p><p>Selected features can be deleted entirely.</p></body></html> - - - QAbstractItemView::ExtendedSelection - - - - - - - <html><head/><body><p>Clears list of base geometries.</p></body></html> - - - Clear - - - - - - - <html><head/><body><p>Add selected features to the list of base geometries for this operation.</p></body></html> - - - Add - - - - - - - All objects will be processed using the same operation properties - - - Qt::AlignCenter - - - true - - - - + + + + + <html><head/><body><p>Add selected features to the list of base geometries for this operation.</p></body></html> + + + Add + + - + + + + <html><head/><body><p>Remove the selected list items from the list of base geometries. The operation will not be applied to them.</p></body></html> + + + Remove + + + + Qt::Vertical @@ -123,14 +57,70 @@ + + + + <html><head/><body><p>Clears list of base geometries.</p></body></html> + + + Clear + + + + + + + All objects will be processed using the same operation properties + + + Qt::AlignCenter + + + true + + + + + + + true + + + + 0 + 0 + + + + <html><head/><body><p>Select one or more features in the 3d view and press 'Add' to add them as the base items for this operation.</p><p><br/></p><p>Selected features can be deleted entirely.</p></body></html> + + + QAbstractItemView::ExtendedSelection + + + + + + + Import + + + + + + + + 0 + 0 + + + + <html><head/><body><p>List of operations with Base Geometry in current Job.</p></body></html> + + + - - baseList - addBase - deleteBase - clearBase - diff --git a/src/Mod/Path/PathScripts/PathOpGui.py b/src/Mod/Path/PathScripts/PathOpGui.py index 64d93f2966..87e5f9b1e6 100644 --- a/src/Mod/Path/PathScripts/PathOpGui.py +++ b/src/Mod/Path/PathScripts/PathOpGui.py @@ -42,13 +42,8 @@ __author__ = "sliptonic (Brad Collette)" __url__ = "https://www.freecadweb.org" __doc__ = "Base classes and framework for Path operation's UI" -LOGLEVEL = False - -if LOGLEVEL: - PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) - PathLog.trackModule(PathLog.thisModule()) -else: - PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) +PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) +# PathLog.trackModule(PathLog.thisModule()) def translate(context, text, disambig=None): @@ -566,6 +561,7 @@ class TaskPanelBaseGeometryPage(TaskPanelPage): return False def addBase(self): + PathLog.track() if self.addBaseGeometry(FreeCADGui.Selection.getSelectionEx()): # self.obj.Proxy.execute(self.obj) self.setFields(self.obj) @@ -636,11 +632,18 @@ class TaskPanelBaseGeometryPage(TaskPanelPage): # Set base geometry list window to resize based on contents # Code reference: # https://stackoverflow.com/questions/6337589/qlistwidget-adjust-size-to-content + # ml: disabling this logic because I can't get it to work on HPD monitor. + # On my systems the values returned by the list object are also incorrect on + # creation, leading to a list object of size 15. count() always returns 0 until + # the list is actually displayed. The same is true for sizeHintForRow(0), which + # returns -1 until the widget is rendered. The widget claims to have a size of + # (100, 30), once it becomes visible the size is (535, 192). + # Leaving the framework here in case somebody figures out how to set this up + # properly. qList = self.form.baseList - # qList.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) - col = qList.width() # 300 row = (qList.count() + qList.frameWidth()) * 15 - qList.setFixedSize(col, row) + #qList.setMinimumHeight(row) + PathLog.debug("baseList({}, {}) {} * {}".format(qList.size(), row, qList.count(), qList.sizeHintForRow(0))) class TaskPanelBaseLocationPage(TaskPanelPage): From 38b142be7acbe5b4625ecb3bcdc96a385495d32f Mon Sep 17 00:00:00 2001 From: Markus Lampert Date: Sun, 24 Jan 2021 21:09:35 -0800 Subject: [PATCH 4/6] Properly calling base logic for adding a base object if special handling did not apply. --- src/Mod/Path/PathScripts/PathVcarveGui.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathVcarveGui.py b/src/Mod/Path/PathScripts/PathVcarveGui.py index 5254a78a22..e77dab4b7f 100644 --- a/src/Mod/Path/PathScripts/PathVcarveGui.py +++ b/src/Mod/Path/PathScripts/PathVcarveGui.py @@ -53,6 +53,7 @@ class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): return super(TaskPanelBaseGeometryPage, self) def addBaseGeometry(self, selection): + PathLog.track(selection) added = False shapes = self.obj.BaseShapes for sel in selection: @@ -78,10 +79,12 @@ class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): shapes.append(base) self.obj.BaseShapes = shapes added = True - else: - # user wants us to engrave an edge of face of a base model - base = self.super().addBaseGeometry(selection) - added = added or base + + if not added: + # user wants us to engrave an edge of face of a base model + PathLog.info(" call default") + base = self.super().addBaseGeometry(selection) + added = added or base return added From 13a4f54ecd9bccbec5827e997aeb7a1ffe93fbd5 Mon Sep 17 00:00:00 2001 From: Markus Lampert Date: Sun, 24 Jan 2021 21:10:39 -0800 Subject: [PATCH 5/6] Process BaseShapes in vcarve and only fall back to the model if nothing was found to engrave. --- src/Mod/Path/PathScripts/PathVcarve.py | 27 +++++++++++++------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathVcarve.py b/src/Mod/Path/PathScripts/PathVcarve.py index f9c08cc729..438661677a 100644 --- a/src/Mod/Path/PathScripts/PathVcarve.py +++ b/src/Mod/Path/PathScripts/PathVcarve.py @@ -311,26 +311,25 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): PathLog.track() if not hasattr(obj.ToolController.Tool, "CuttingEdgeAngle"): - FreeCAD.Console.PrintError( - translate("Path_Vcarve", "VCarve requires an engraving \ - cutter with CuttingEdgeAngle") + "\n") + PathLog.error(translate("Path_Vcarve", "VCarve requires an engraving cutter with CuttingEdgeAngle")) if obj.ToolController.Tool.CuttingEdgeAngle >= 180.0: - FreeCAD.Console.PrintError( - translate("Path_Vcarve", - "Engraver Cutting Edge Angle must be < 180 degrees.") + "\n") + PathLog.error(translate("Path_Vcarve", "Engraver Cutting Edge Angle must be < 180 degrees.")) return + try: faces = [] - if obj.Base: - PathLog.track() - for base in obj.Base: - for sub in base[1]: - shape = getattr(base[0].Shape, sub) - if isinstance(shape, Part.Face): - faces.append(shape) - else: + for base in obj.BaseShapes: + faces.extend(base.Shape.Faces) + + for base in obj.Base: + for sub in base[1]: + shape = getattr(base[0].Shape, sub) + if isinstance(shape, Part.Face): + faces.append(shape) + + if not faces: for model in self.model: if model.isDerivedFrom('Sketcher::SketchObject') or model.isDerivedFrom('Part::Part2DObject'): faces.extend(model.Shape.Faces) From ce625703b43f7101a5fb2a7d0e0c26c79f1f8393 Mon Sep 17 00:00:00 2001 From: Markus Lampert Date: Sun, 24 Jan 2021 21:15:31 -0800 Subject: [PATCH 6/6] Removed unused BaseObjects property from vcarve --- src/Mod/Path/PathScripts/PathVcarve.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathVcarve.py b/src/Mod/Path/PathScripts/PathVcarve.py index 438661677a..22c974d108 100644 --- a/src/Mod/Path/PathScripts/PathVcarve.py +++ b/src/Mod/Path/PathScripts/PathVcarve.py @@ -210,11 +210,6 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): QtCore.QT_TRANSLATE_NOOP("PathVcarve", "Additional base objects to be engraved")) obj.setEditorMode('BaseShapes', 2) # hide - if not hasattr(obj, 'BaseObject'): - obj.addProperty("App::PropertyLink", "BaseObject", "Path", - QtCore.QT_TRANSLATE_NOOP("PathVcarve", - "Additional base objects to be engraved")) - obj.setEditorMode('BaseObject', 2) # hide def initOperation(self, obj): '''initOperation(obj) ... create vcarve specific properties.'''