From 3e83b1d8e54aad3476f4b4f843d8cd05a888758c Mon Sep 17 00:00:00 2001
From: Russell Johnson <47639332+Russ4262@users.noreply.github.com>
Date: Tue, 2 Jun 2020 21:21:16 -0500
Subject: [PATCH 1/9] Path: Add missing cut patterns and organize the
enumeration lists
---
.../Resources/panels/PageOpWaterlineEdit.ui | 30 ++++++++++++-------
src/Mod/Path/PathScripts/PathSurface.py | 2 +-
src/Mod/Path/PathScripts/PathWaterline.py | 4 +--
3 files changed, 23 insertions(+), 13 deletions(-)
diff --git a/src/Mod/Path/Gui/Resources/panels/PageOpWaterlineEdit.ui b/src/Mod/Path/Gui/Resources/panels/PageOpWaterlineEdit.ui
index a9cdcac0ea..38462d7ed5 100644
--- a/src/Mod/Path/Gui/Resources/panels/PageOpWaterlineEdit.ui
+++ b/src/Mod/Path/Gui/Resources/panels/PageOpWaterlineEdit.ui
@@ -165,16 +165,6 @@
None
- -
-
- Line
-
-
- -
-
- ZigZag
-
-
-
Circular
@@ -185,6 +175,26 @@
CircularZigZag
+ -
+
+ Line
+
+
+ -
+
+ Offset
+
+
+ -
+
+ Spiral
+
+
+ -
+
+ ZigZag
+
+
-
diff --git a/src/Mod/Path/PathScripts/PathSurface.py b/src/Mod/Path/PathScripts/PathSurface.py
index 433e26bb2e..824f8b0254 100644
--- a/src/Mod/Path/PathScripts/PathSurface.py
+++ b/src/Mod/Path/PathScripts/PathSurface.py
@@ -206,7 +206,7 @@ class ObjectSurface(PathOp.ObjectOp):
'BoundBox': ['BaseBoundBox', 'Stock'],
'PatternCenterAt': ['CenterOfMass', 'CenterOfBoundBox', 'XminYmin', 'Custom'],
'CutMode': ['Conventional', 'Climb'],
- 'CutPattern': ['Line', 'Circular', 'CircularZigZag', 'Offset', 'Spiral', 'ZigZag'], # Additional goals ['Offset', 'ZigZagOffset', 'Grid', 'Triangle']
+ 'CutPattern': ['Circular', 'CircularZigZag', 'Line', 'Offset', 'Spiral', 'ZigZag'], # Additional goals ['Offset', 'ZigZagOffset', 'Grid', 'Triangle']
'DropCutterDir': ['X', 'Y'],
'HandleMultipleFeatures': ['Collectively', 'Individually'],
'LayerMode': ['Single-pass', 'Multi-pass'],
diff --git a/src/Mod/Path/PathScripts/PathWaterline.py b/src/Mod/Path/PathScripts/PathWaterline.py
index 0693a27edd..804125de3f 100644
--- a/src/Mod/Path/PathScripts/PathWaterline.py
+++ b/src/Mod/Path/PathScripts/PathWaterline.py
@@ -191,9 +191,9 @@ class ObjectWaterline(PathOp.ObjectOp):
'Algorithm': ['OCL Dropcutter', 'Experimental'],
'BoundBox': ['BaseBoundBox', 'Stock'],
'PatternCenterAt': ['CenterOfMass', 'CenterOfBoundBox', 'XminYmin', 'Custom'],
- 'ClearLastLayer': ['Off', 'Line', 'Circular', 'CircularZigZag', 'Offset', 'Spiral', 'ZigZag'],
+ 'ClearLastLayer': ['Off', 'Circular', 'CircularZigZag', 'Line', 'Offset', 'Spiral', 'ZigZag'],
'CutMode': ['Conventional', 'Climb'],
- 'CutPattern': ['None', 'Line', 'Circular', 'CircularZigZag', 'Offset', 'Spiral', 'ZigZag'], # Additional goals ['Offset', 'Spiral', 'ZigZagOffset', 'Grid', 'Triangle']
+ 'CutPattern': ['None', 'Circular', 'CircularZigZag', 'Line', 'Offset', 'Spiral', 'ZigZag'], # Additional goals ['Offset', 'Spiral', 'ZigZagOffset', 'Grid', 'Triangle']
'HandleMultipleFeatures': ['Collectively', 'Individually'],
'LayerMode': ['Single-pass', 'Multi-pass'],
}
From 7fd047a9beebe8400ff2bebecc5b314254b45487 Mon Sep 17 00:00:00 2001
From: Russell Johnson <47639332+Russ4262@users.noreply.github.com>
Date: Wed, 3 Jun 2020 01:29:08 -0500
Subject: [PATCH 2/9] Path: Make missing connections between UI panel and
operation
---
.../Gui/Resources/panels/PageOpSurfaceEdit.ui | 2 +-
src/Mod/Path/PathScripts/PathSurfaceGui.py | 20 +++++++++++++------
2 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/src/Mod/Path/Gui/Resources/panels/PageOpSurfaceEdit.ui b/src/Mod/Path/Gui/Resources/panels/PageOpSurfaceEdit.ui
index 45902b44ff..e39c46b7bc 100644
--- a/src/Mod/Path/Gui/Resources/panels/PageOpSurfaceEdit.ui
+++ b/src/Mod/Path/Gui/Resources/panels/PageOpSurfaceEdit.ui
@@ -156,7 +156,7 @@
-
-
+
<html><head/><body><p>Profile the edges of the selection.</p></body></html>
diff --git a/src/Mod/Path/PathScripts/PathSurfaceGui.py b/src/Mod/Path/PathScripts/PathSurfaceGui.py
index a26b290827..ab09c33d6f 100644
--- a/src/Mod/Path/PathScripts/PathSurfaceGui.py
+++ b/src/Mod/Path/PathScripts/PathSurfaceGui.py
@@ -52,24 +52,24 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
self.updateToolController(obj, self.form.toolController)
self.updateCoolant(obj, self.form.coolantController)
- PathGui.updateInputField(obj, 'DepthOffset', self.form.depthOffset)
- PathGui.updateInputField(obj, 'SampleInterval', self.form.sampleInterval)
-
if obj.BoundBox != str(self.form.boundBoxSelect.currentText()):
obj.BoundBox = str(self.form.boundBoxSelect.currentText())
if obj.ScanType != str(self.form.scanType.currentText()):
obj.ScanType = str(self.form.scanType.currentText())
- if obj.StepOver != self.form.stepOver.value():
- obj.StepOver = self.form.stepOver.value()
-
if obj.LayerMode != str(self.form.layerMode.currentText()):
obj.LayerMode = str(self.form.layerMode.currentText())
if obj.CutPattern != str(self.form.cutPattern.currentText()):
obj.CutPattern = str(self.form.cutPattern.currentText())
+ if obj.ProfileEdges != str(self.form.profileEdges.currentText()):
+ obj.ProfileEdges = str(self.form.profileEdges.currentText())
+
+ if obj.AvoidLastX_Faces != self.form.avoidLastX_Faces.value():
+ obj.AvoidLastX_Faces = self.form.avoidLastX_Faces.value()
+
obj.DropCutterExtraOffset.x = FreeCAD.Units.Quantity(self.form.boundBoxExtraOffsetX.text()).Value
obj.DropCutterExtraOffset.y = FreeCAD.Units.Quantity(self.form.boundBoxExtraOffsetY.text()).Value
@@ -77,6 +77,10 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
obj.DropCutterDir = str(self.form.dropCutterDirSelect.currentText())
PathGui.updateInputField(obj, 'DepthOffset', self.form.depthOffset)
+
+ if obj.StepOver != self.form.stepOver.value():
+ obj.StepOver = self.form.stepOver.value()
+
PathGui.updateInputField(obj, 'SampleInterval', self.form.sampleInterval)
if obj.UseStartPoint != self.form.useStartPoint.isChecked():
@@ -96,6 +100,8 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
self.selectInComboBox(obj.ScanType, self.form.scanType)
self.selectInComboBox(obj.LayerMode, self.form.layerMode)
self.selectInComboBox(obj.CutPattern, self.form.cutPattern)
+ self.selectInComboBox(obj.ProfileEdges, self.form.profileEdges)
+ self.form.avoidLastX_Faces.setValue(obj.AvoidLastX_Faces)
self.form.boundBoxExtraOffsetX.setText(FreeCAD.Units.Quantity(obj.DropCutterExtraOffset.x, FreeCAD.Units.Length).UserString)
self.form.boundBoxExtraOffsetY.setText(FreeCAD.Units.Quantity(obj.DropCutterExtraOffset.y, FreeCAD.Units.Length).UserString)
self.selectInComboBox(obj.DropCutterDir, self.form.dropCutterDirSelect)
@@ -129,6 +135,8 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
signals.append(self.form.scanType.currentIndexChanged)
signals.append(self.form.layerMode.currentIndexChanged)
signals.append(self.form.cutPattern.currentIndexChanged)
+ signals.append(self.form.profileEdges.currentIndexChanged)
+ signals.append(self.form.avoidLastX_Faces.editingFinished)
signals.append(self.form.boundBoxExtraOffsetX.editingFinished)
signals.append(self.form.boundBoxExtraOffsetY.editingFinished)
signals.append(self.form.dropCutterDirSelect.currentIndexChanged)
From d94ae6e813a94f27580ed4a4c90c416ddc2f9630 Mon Sep 17 00:00:00 2001
From: Russell Johnson <47639332+Russ4262@users.noreply.github.com>
Date: Wed, 3 Jun 2020 02:12:24 -0500
Subject: [PATCH 3/9] Path: Simplify creation of debug objects
Path: Improve debug messages
---
src/Mod/Path/PathScripts/PathSurface.py | 19 ++++---
.../Path/PathScripts/PathSurfaceSupport.py | 8 +--
src/Mod/Path/PathScripts/PathWaterline.py | 52 +++++--------------
3 files changed, 27 insertions(+), 52 deletions(-)
diff --git a/src/Mod/Path/PathScripts/PathSurface.py b/src/Mod/Path/PathScripts/PathSurface.py
index 824f8b0254..315119788b 100644
--- a/src/Mod/Path/PathScripts/PathSurface.py
+++ b/src/Mod/Path/PathScripts/PathSurface.py
@@ -753,11 +753,7 @@ class ObjectSurface(PathOp.ObjectOp):
if prflShp is False:
PathLog.error('No profile shape is False.')
return list()
- if self.showDebugObjects:
- P = FreeCAD.ActiveDocument.addObject('Part::Feature', 'tmpNewProfileShape')
- P.Shape = prflShp
- P.purgeTouched()
- self.tempGroup.addObject(P)
+ self.showDebugObject(prflShp, 'NewProfileShape')
# get offset path geometry and perform OCL scan with that geometry
pathOffsetGeom = self._offsetFacesToPointData(obj, prflShp)
if pathOffsetGeom is False:
@@ -767,11 +763,7 @@ class ObjectSurface(PathOp.ObjectOp):
geoScan = list()
if obj.ProfileEdges != 'Only':
- if self.showDebugObjects:
- F = FreeCAD.ActiveDocument.addObject('Part::Feature', 'tmpCutArea')
- F.Shape = cmpdShp
- F.purgeTouched()
- self.tempGroup.addObject(F)
+ self.showDebugObject(cmpdShp, 'CutArea')
# get internal path geometry and perform OCL scan with that geometry
PGG = PathSurfaceSupport.PathGeometryGenerator(obj, cmpdShp, obj.CutPattern)
if self.showDebugObjects:
@@ -2108,6 +2100,13 @@ class ObjectSurface(PathOp.ObjectOp):
zMax = minDep
return zMax
+ def showDebugObject(self, objShape, objName):
+ if self.showDebugObjects:
+ do = FreeCAD.ActiveDocument.addObject('Part::Feature', 'tmp_' + objName)
+ do.Shape = objShape
+ do.purgeTouched()
+ self.tempGroup.addObject(do)
+
def SetupProperties():
''' SetupProperties() ... Return list of properties required for operation.'''
diff --git a/src/Mod/Path/PathScripts/PathSurfaceSupport.py b/src/Mod/Path/PathScripts/PathSurfaceSupport.py
index fcaface258..3ee6e70cec 100644
--- a/src/Mod/Path/PathScripts/PathSurfaceSupport.py
+++ b/src/Mod/Path/PathScripts/PathSurfaceSupport.py
@@ -1348,9 +1348,9 @@ def pathGeomToLinesPointSet(obj, compGeoShp, cutClimb, toolDiam, closedGap, gaps
isEven = lnCnt % 2
if isEven == 0:
- PathLog.debug('Line count is ODD.')
+ PathLog.debug('Line count is ODD: {}.'.format(lnCnt))
else:
- PathLog.debug('Line count is even.')
+ PathLog.debug('Line count is even: {}.'.format(lnCnt))
return LINES
@@ -1432,9 +1432,9 @@ def pathGeomToZigzagPointSet(obj, compGeoShp, cutClimb, toolDiam, closedGap, gap
# Fix directional issue with LAST line when line count is even
isEven = lnCnt % 2
if isEven == 0: # Changed to != with 90 degree CutPatternAngle
- PathLog.debug('Line count is even.')
+ PathLog.debug('Line count is even: {}.'.format(lnCnt))
else:
- PathLog.debug('Line count is ODD.')
+ PathLog.debug('Line count is ODD: {}.'.format(lnCnt))
dirFlg = -1 * dirFlg
if not obj.CutPatternReversed:
if cutClimb:
diff --git a/src/Mod/Path/PathScripts/PathWaterline.py b/src/Mod/Path/PathScripts/PathWaterline.py
index 804125de3f..8492aa8491 100644
--- a/src/Mod/Path/PathScripts/PathWaterline.py
+++ b/src/Mod/Path/PathScripts/PathWaterline.py
@@ -488,7 +488,6 @@ class ObjectWaterline(PathOp.ObjectOp):
self.opApplyPropertyLimits(obj)
# Create temporary group for temporary objects, removing existing
- # if self.showDebugObjects is True:
tempGroupName = 'tempPathWaterlineGroup'
if FCAD.getObject(tempGroupName):
for to in FCAD.getObject(tempGroupName).Group:
@@ -1238,11 +1237,7 @@ class ObjectWaterline(PathOp.ObjectOp):
bbFace = PathSurfaceSupport.getCrossSection(baseEnv) # returned at Z=0.0
trimFace = borderFace.cut(bbFace)
- if self.showDebugObjects is True:
- TF = FreeCAD.ActiveDocument.addObject('Part::Feature', 'trimFace')
- TF.Shape = trimFace
- TF.purgeTouched()
- self.tempGroup.addObject(TF)
+ self.showDebugObject(trimFace, 'TrimFace')
# Cycle through layer depths
CUTAREAS = self._getCutAreas(base.Shape, depthparams, bbFace, trimFace, borderFace)
@@ -1267,11 +1262,7 @@ class ObjectWaterline(PathOp.ObjectOp):
if area.Area > 0.0:
cont = True
caWireCnt = len(area.Wires) - 1 # first wire is boundFace wire
- if self.showDebugObjects:
- CA = FreeCAD.ActiveDocument.addObject('Part::Feature', 'cutArea_{}'.format(caCnt))
- CA.Shape = area
- CA.purgeTouched()
- self.tempGroup.addObject(CA)
+ self.showDebugObject(area, 'CutArea_{}'.format(caCnt))
else:
data = FreeCAD.Units.Quantity(csHght, FreeCAD.Units.Length).UserString
PathLog.debug('Cut area at {} is zero.'.format(data))
@@ -1281,11 +1272,7 @@ class ObjectWaterline(PathOp.ObjectOp):
area.translate(FreeCAD.Vector(0.0, 0.0, 0.0 - area.BoundBox.ZMin))
activeArea = area.cut(trimFace)
activeAreaWireCnt = len(activeArea.Wires) # first wire is boundFace wire
- if self.showDebugObjects:
- CA = FreeCAD.ActiveDocument.addObject('Part::Feature', 'activeArea_{}'.format(caCnt))
- CA.Shape = activeArea
- CA.purgeTouched()
- self.tempGroup.addObject(CA)
+ self.showDebugObject(activeArea, 'ActiveArea_{}'.format(caCnt))
ofstArea = PathSurfaceSupport.extractFaceOffset(activeArea, ofst, self.wpc, makeComp=False)
if not ofstArea:
data = FreeCAD.Units.Quantity(csHght, FreeCAD.Units.Length).UserString
@@ -1297,11 +1284,7 @@ class ObjectWaterline(PathOp.ObjectOp):
ofstSolidFacesList = self._getSolidAreasFromPlanarFaces(ofstArea)
if ofstSolidFacesList:
clearArea = Part.makeCompound(ofstSolidFacesList)
- if self.showDebugObjects is True:
- CA = FreeCAD.ActiveDocument.addObject('Part::Feature', 'clearArea_{}'.format(caCnt))
- CA.Shape = clearArea
- CA.purgeTouched()
- self.tempGroup.addObject(CA)
+ self.showDebugObject(clearArea, 'ClearArea_{}'.format(caCnt))
else:
cont = False
data = FreeCAD.Units.Quantity(csHght, FreeCAD.Units.Length).UserString
@@ -1363,13 +1346,7 @@ class ObjectWaterline(PathOp.ObjectOp):
if useFaces:
compAdjFaces = Part.makeCompound(useFaces)
-
- if self.showDebugObjects is True:
- CA = FreeCAD.ActiveDocument.addObject('Part::Feature', 'tmpSolids_{}'.format(dp + 1))
- CA.Shape = compAdjFaces
- CA.purgeTouched()
- self.tempGroup.addObject(CA)
-
+ self.showDebugObject(compAdjFaces, 'Solids_{}'.format(dp + 1))
if isFirst:
allPrevComp = compAdjFaces
cutArea = borderFace.cut(compAdjFaces)
@@ -1395,11 +1372,7 @@ class ObjectWaterline(PathOp.ObjectOp):
# Translate path geometry to layer height
ofstPlnrShp.translate(FreeCAD.Vector(0.0, 0.0, csHght - ofstPlnrShp.BoundBox.ZMin))
- if self.showDebugObjects is True:
- OA = FreeCAD.ActiveDocument.addObject('Part::Feature', 'waterlinePathArea_{}'.format(round(csHght, 2)))
- OA.Shape = ofstPlnrShp
- OA.purgeTouched()
- self.tempGroup.addObject(OA)
+ self.showDebugObject(ofstPlnrShp, 'WaterlinePathArea_{}'.format(round(csHght, 2)))
commands.append(Path.Command('N (Cut Area {}.)'.format(round(csHght, 2))))
start = 1
@@ -1442,11 +1415,7 @@ class ObjectWaterline(PathOp.ObjectOp):
return commands
pathGeom.translate(FreeCAD.Vector(0.0, 0.0, csHght - pathGeom.BoundBox.ZMin))
- if self.showDebugObjects is True:
- OA = FreeCAD.ActiveDocument.addObject('Part::Feature', 'pathGeom_{}'.format(round(csHght, 2)))
- OA.Shape = pathGeom
- OA.purgeTouched()
- self.tempGroup.addObject(OA)
+ self.showDebugObject(pathGeom, 'PathGeom_{}'.format(round(csHght, 2)))
if cutPattern == 'Line':
pntSet = PathSurfaceSupport.pathGeomToLinesPointSet(obj, pathGeom, self.CutClimb, self.toolDiam, self.closedGap, self.gaps)
@@ -1855,6 +1824,13 @@ class ObjectWaterline(PathOp.ObjectOp):
PathLog.warning("Defaulting cutter to standard end mill.")
return ocl.CylCutter(diam_1, (CEH + lenOfst))
+ def showDebugObject(self, objShape, objName):
+ if self.showDebugObjects:
+ do = FreeCAD.ActiveDocument.addObject('Part::Feature', 'tmp_' + objName)
+ do.Shape = objShape
+ do.purgeTouched()
+ self.tempGroup.addObject(do)
+
def SetupProperties():
''' SetupProperties() ... Return list of properties required for operation.'''
From 7ba218f417443f9ea8df00e4329a98ad4934bc76 Mon Sep 17 00:00:00 2001
From: Russell Johnson <47639332+Russ4262@users.noreply.github.com>
Date: Wed, 3 Jun 2020 01:14:26 -0500
Subject: [PATCH 4/9] Path: Fix paths through model
All cut patterns except Offset were cutting through model.
---
src/Mod/Path/PathScripts/PathSurfaceSupport.py | 9 ++++-----
src/Mod/Path/PathScripts/PathWaterline.py | 17 ++++++++++-------
2 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/src/Mod/Path/PathScripts/PathSurfaceSupport.py b/src/Mod/Path/PathScripts/PathSurfaceSupport.py
index 3ee6e70cec..5599eb4ac3 100644
--- a/src/Mod/Path/PathScripts/PathSurfaceSupport.py
+++ b/src/Mod/Path/PathScripts/PathSurfaceSupport.py
@@ -91,12 +91,11 @@ class PathGeometryGenerator:
if shape.BoundBox.ZMin != 0.0:
shape.translate(FreeCAD.Vector(0.0, 0.0, 0.0 - shape.BoundBox.ZMin))
- if shape.BoundBox.ZLength == 0.0:
- self.shape = shape
- else:
+ if shape.BoundBox.ZLength > 1.0e-8:
FreeCAD.Console.PrintWarning('Shape appears to not be horizontal planar. ZMax is {}.\n'.format(shape.BoundBox.ZMax))
-
- self._prepareConstants()
+ else:
+ self.shape = shape
+ self._prepareConstants()
def _prepareConstants(self):
# Apply drop cutter extra offset and set the max and min XY area of the operation
diff --git a/src/Mod/Path/PathScripts/PathWaterline.py b/src/Mod/Path/PathScripts/PathWaterline.py
index 8492aa8491..0344350b59 100644
--- a/src/Mod/Path/PathScripts/PathWaterline.py
+++ b/src/Mod/Path/PathScripts/PathWaterline.py
@@ -1281,14 +1281,17 @@ class ObjectWaterline(PathOp.ObjectOp):
if cont:
# Identify solid areas in the offset data
- ofstSolidFacesList = self._getSolidAreasFromPlanarFaces(ofstArea)
- if ofstSolidFacesList:
- clearArea = Part.makeCompound(ofstSolidFacesList)
- self.showDebugObject(clearArea, 'ClearArea_{}'.format(caCnt))
+ if obj.CutPattern == 'Offset' or obj.CutPattern == 'None':
+ ofstSolidFacesList = self._getSolidAreasFromPlanarFaces(ofstArea)
+ if ofstSolidFacesList:
+ clearArea = Part.makeCompound(ofstSolidFacesList)
+ self.showDebugObject(clearArea, 'ClearArea_{}'.format(caCnt))
+ else:
+ cont = False
+ data = FreeCAD.Units.Quantity(csHght, FreeCAD.Units.Length).UserString
+ PathLog.error('Could not determine solid faces at {}.'.format(data))
else:
- cont = False
- data = FreeCAD.Units.Quantity(csHght, FreeCAD.Units.Length).UserString
- PathLog.error('Could not determine solid faces at {}.'.format(data))
+ clearArea = activeArea
if cont:
# Make waterline path for current CUTAREA depth (csHght)
From 2fe53c58bffb052fbcc8126000c14775d16e2602 Mon Sep 17 00:00:00 2001
From: Russell Johnson <47639332+Russ4262@users.noreply.github.com>
Date: Wed, 3 Jun 2020 12:47:10 -0500
Subject: [PATCH 5/9] Path: Fix failure to create model STL when selecting
faces
---
src/Mod/Path/PathScripts/PathSurfaceSupport.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Mod/Path/PathScripts/PathSurfaceSupport.py b/src/Mod/Path/PathScripts/PathSurfaceSupport.py
index 5599eb4ac3..ae891d3503 100644
--- a/src/Mod/Path/PathScripts/PathSurfaceSupport.py
+++ b/src/Mod/Path/PathScripts/PathSurfaceSupport.py
@@ -425,7 +425,7 @@ class PathGeometryGenerator:
'''_getFaceOffset(shape, offset) ... internal function.
Original _buildPathArea() version copied from PathAreaOp.py module. This version is modified.
Adjustments made based on notes by @sliptonic at this webpage: https://github.com/sliptonic/FreeCAD/wiki/PathArea-notes.'''
- PathLog.debug('_getFaceOffset()')
+ # PathLog.debug('_getFaceOffset()')
areaParams = {}
areaParams['Offset'] = offset
@@ -559,7 +559,7 @@ class ProcessSelectedFaces:
# Process each model base, as a whole, as needed
# PathLog.debug(' -Pre-processing all models in Job.')
for m in range(0, lenGRP):
- if fShapes[m] is False:
+ if self.modelSTLs[m] and not fShapes[m]:
PathLog.debug(' -Pre-processing {} as a whole.'.format(GRP[m].Label))
if self.obj.BoundBox == 'BaseBoundBox':
base = GRP[m]
From 4b9b1e3c761d787acc61f26350c94a85783609f6 Mon Sep 17 00:00:00 2001
From: Russell Johnson <47639332+Russ4262@users.noreply.github.com>
Date: Wed, 3 Jun 2020 18:42:19 -0500
Subject: [PATCH 6/9] Path: Clean up messaging and add `translation()` usage
---
src/Mod/Path/PathScripts/PathSurface.py | 31 ++++---
.../Path/PathScripts/PathSurfaceSupport.py | 85 ++++++++++---------
2 files changed, 65 insertions(+), 51 deletions(-)
diff --git a/src/Mod/Path/PathScripts/PathSurface.py b/src/Mod/Path/PathScripts/PathSurface.py
index 315119788b..3c879430c3 100644
--- a/src/Mod/Path/PathScripts/PathSurface.py
+++ b/src/Mod/Path/PathScripts/PathSurface.py
@@ -38,7 +38,8 @@ from PySide import QtCore
try:
import ocl
except ImportError:
- msg = QtCore.QCoreApplication.translate("PathSurface", "This operation requires OpenCamLib to be installed.")
+ msg = QtCore.QCoreApplication.translate("PathSurface",
+ "This operation requires OpenCamLib to be installed.")
FreeCAD.Console.PrintError(msg + "\n")
raise ImportError
# import sys
@@ -575,18 +576,18 @@ class ObjectSurface(PathOp.ObjectOp):
PathSurfaceSupport._prepareModelSTLs(self, JOB, obj, m, ocl)
Mdl = JOB.Model.Group[m]
- if FACES[m] is False:
- PathLog.error('No data for model base: {}'.format(JOB.Model.Group[m].Label))
- else:
+ if FACES[m]:
+ PathLog.debug('Working on Model.Group[{}]: {}'.format(m, Mdl.Label))
if m > 0:
# Raise to clearance between models
CMDS.append(Path.Command('N (Transition to base: {}.)'.format(Mdl.Label)))
CMDS.append(Path.Command('G0', {'Z': obj.ClearanceHeight.Value, 'F': self.vertRapid}))
- PathLog.info('Working on Model.Group[{}]: {}'.format(m, Mdl.Label))
# make stock-model-voidShapes STL model for avoidance detection on transitions
PathSurfaceSupport._makeSafeSTL(self, JOB, obj, m, FACES[m], VOIDS[m], ocl)
# Process model/faces - OCL objects must be ready
CMDS.extend(self._processCutAreas(JOB, obj, m, FACES[m], VOIDS[m]))
+ else:
+ PathLog.debug('No data for model base: {}'.format(JOB.Model.Group[m].Label))
# Save gcode produced
self.commandlist.extend(CMDS)
@@ -659,7 +660,8 @@ class ObjectSurface(PathOp.ObjectOp):
exTime = str(tMins) + ' min. ' + str(round(tSecs, 5)) + ' sec.'
else:
exTime = str(round(execTime, 5)) + ' sec.'
- FreeCAD.Console.PrintMessage('3D Surface operation time is {}\n'.format(exTime))
+ msg = translate('PathSurface', 'operation time is')
+ FreeCAD.Console.PrintMessage('3D Surface ' + msg + '{}\n'.format(exTime))
if self.cancelOperation:
FreeCAD.ActiveDocument.openTransaction(translate("PathSurface", "Canceled 3D Surface operation."))
@@ -751,13 +753,15 @@ class ObjectSurface(PathOp.ObjectOp):
if obj.ProfileEdges != 'None':
prflShp = self.profileShapes[mdlIdx][fsi]
if prflShp is False:
- PathLog.error('No profile shape is False.')
+ msg = translate('PathSurface', 'No profile geometry shape returned.')
+ PathLog.error(msg)
return list()
self.showDebugObject(prflShp, 'NewProfileShape')
# get offset path geometry and perform OCL scan with that geometry
pathOffsetGeom = self._offsetFacesToPointData(obj, prflShp)
if pathOffsetGeom is False:
- PathLog.error('No profile geometry returned.')
+ msg = translate('PathSurface', 'No profile path geometry returned.')
+ PathLog.error(msg)
return list()
profScan = [self._planarPerformOclScan(obj, pdc, pathOffsetGeom, True)]
@@ -771,12 +775,14 @@ class ObjectSurface(PathOp.ObjectOp):
self.tmpCOM = PGG.getCenterOfPattern()
pathGeom = PGG.generatePathGeometry()
if pathGeom is False:
- PathLog.error('No path geometry returned.')
+ msg = translate('PathSurface', 'No clearing shape returned.')
+ PathLog.error(msg)
return list()
if obj.CutPattern == 'Offset':
useGeom = self._offsetFacesToPointData(obj, pathGeom, profile=False)
if useGeom is False:
- PathLog.error('No profile geometry returned.')
+ msg = translate('PathSurface', 'No clearing path geometry returned.')
+ PathLog.error(msg)
return list()
geoScan = [self._planarPerformOclScan(obj, pdc, useGeom, True)]
else:
@@ -795,7 +801,8 @@ class ObjectSurface(PathOp.ObjectOp):
SCANDATA.extend(profScan)
if len(SCANDATA) == 0:
- PathLog.error('No scan data to convert to Gcode.')
+ msg = translate('PathSuface', 'No scan data to convert to Gcode.')
+ PathLog.error(msg)
return list()
# Apply depth offset
@@ -1165,7 +1172,6 @@ class ObjectSurface(PathOp.ObjectOp):
# Manage step over transition and CircularZigZag direction
if so > 0:
- # PathLog.debug(' stepover index: {}'.format(so))
# Control ZigZag direction
if obj.CutPattern == 'CircularZigZag':
if odd is True:
@@ -1187,7 +1193,6 @@ class ObjectSurface(PathOp.ObjectOp):
for i in range(0, lenAdjPrts):
prt = ADJPRTS[i]
lenPrt = len(prt)
- # PathLog.debug(' adj parts index - lenPrt: {} - {}'.format(i, lenPrt))
if prt == 'BRK' and prtsHasCmds is True:
nxtStart = ADJPRTS[i + 1][0]
minSTH = self._getMinSafeTravelHeight(safePDC, last, nxtStart, minDep=None) # Check safe travel height against fullSTL
diff --git a/src/Mod/Path/PathScripts/PathSurfaceSupport.py b/src/Mod/Path/PathScripts/PathSurfaceSupport.py
index ae891d3503..16865b2e38 100644
--- a/src/Mod/Path/PathScripts/PathSurfaceSupport.py
+++ b/src/Mod/Path/PathScripts/PathSurfaceSupport.py
@@ -92,7 +92,10 @@ class PathGeometryGenerator:
if shape.BoundBox.ZMin != 0.0:
shape.translate(FreeCAD.Vector(0.0, 0.0, 0.0 - shape.BoundBox.ZMin))
if shape.BoundBox.ZLength > 1.0e-8:
- FreeCAD.Console.PrintWarning('Shape appears to not be horizontal planar. ZMax is {}.\n'.format(shape.BoundBox.ZMax))
+ msg = translate('PathSurfaceSupport',
+ 'Shape appears to not be horizontal planar.')
+ msg += ' ZMax == {} mm.\n'.format(shape.BoundBox.ZMax)
+ FreeCAD.Console.PrintWarning(msg)
else:
self.shape = shape
self._prepareConstants()
@@ -117,8 +120,11 @@ class PathGeometryGenerator:
fCnt += 1
zeroCOM = zeroCOM.add(FreeCAD.Vector(comF.x, comF.y, 0.0).multiply(areaF))
if fCnt == 0:
- msg = translate(self.module, 'Cannot calculate the Center Of Mass. Using Center of Boundbox instead.')
- FreeCAD.Console.PrintError(msg + '\n')
+ msg = translate('PathSurfaceSupport',
+ 'Cannot calculate the Center Of Mass.')
+ msg += ' ' + translate('PathSurfaceSupport',
+ 'Using Center of Boundbox instead.') + '\n'
+ FreeCAD.Console.PrintError(msg)
bbC = self.shape.BoundBox.Center
zeroCOM = FreeCAD.Vector(bbC.x, bbC.y, 0.0)
else:
@@ -155,11 +161,9 @@ class PathGeometryGenerator:
'''generatePathGeometry()...
Call this function to obtain the path geometry shape, generated by this class.'''
if self.pattern == 'None':
- # FreeCAD.Console.PrintWarning('PGG: No pattern set.\n')
return False
if self.shape is None:
- # FreeCAD.Console.PrintWarning('PGG: No shape set.\n')
return False
cmd = 'self._' + self.pattern + '()'
@@ -407,7 +411,6 @@ class PathGeometryGenerator:
while cont:
ofstArea = self._getFaceOffset(shape, ofst)
if not ofstArea:
- # FreeCAD.Console.PrintWarning('PGG: No offset clearing area returned.\n')
cont = False
True if cont else False # cont used for LGTM
break
@@ -425,9 +428,8 @@ class PathGeometryGenerator:
'''_getFaceOffset(shape, offset) ... internal function.
Original _buildPathArea() version copied from PathAreaOp.py module. This version is modified.
Adjustments made based on notes by @sliptonic at this webpage: https://github.com/sliptonic/FreeCAD/wiki/PathArea-notes.'''
- # PathLog.debug('_getFaceOffset()')
-
areaParams = {}
+
areaParams['Offset'] = offset
areaParams['Fill'] = 1 # 1
areaParams['Coplanar'] = 0
@@ -438,7 +440,6 @@ class PathGeometryGenerator:
areaParams['Project'] = True
area = Path.Area() # Create instance of Area() class object
- # area.setPlane(PathUtils.makeWorkplane(shape)) # Set working plane
area.setPlane(PathUtils.makeWorkplane(self.wpc)) # Set working plane to normal at Z=1
area.add(shape)
area.setParams(**areaParams) # set parameters
@@ -474,7 +475,10 @@ class ProcessSelectedFaces:
self.module = None
self.radius = None
self.depthParams = None
- self.msgNoFaces = translate(self.module, 'Face selection is unavailable for Rotational scans. Ignoring selected faces.') + '\n'
+ self.msgNoFaces = translate('PathSurfaceSupport',
+ 'Face selection is unavailable for Rotational scans.') + '\n'
+ self.msgNoFaces += ' ' + translate('PathSurfaceSupport',
+ 'Ignoring selected faces.') + '\n'
self.JOB = JOB
self.obj = obj
self.profileEdges = 'None'
@@ -557,7 +561,6 @@ class ProcessSelectedFaces:
self.modelSTLs[m] = True
# Process each model base, as a whole, as needed
- # PathLog.debug(' -Pre-processing all models in Job.')
for m in range(0, lenGRP):
if self.modelSTLs[m] and not fShapes[m]:
PathLog.debug(' -Pre-processing {} as a whole.'.format(GRP[m].Label))
@@ -568,7 +571,9 @@ class ProcessSelectedFaces:
pPEB = self._preProcessEntireBase(base, m)
if pPEB is False:
- FreeCAD.Console.PrintError(' -Failed to pre-process base as a whole.\n')
+ msg = translate('PathSurfaceSupport',
+ 'Failed to pre-process base as a whole.') + '\n'
+ FreeCAD.Console.PrintError(msg)
else:
(fcShp, prflShp) = pPEB
if fcShp is not False:
@@ -677,7 +682,8 @@ class ProcessSelectedFaces:
PathLog.debug('Attempting to get cross-section of collective faces.')
if len(outFCS) == 0:
- msg = translate('PathSurfaceSupport', 'Cannot process selected faces. Check horizontal surface exposure.')
+ msg = translate('PathSurfaceSupport',
+ 'Cannot process selected faces. Check horizontal surface exposure.')
FreeCAD.Console.PrintError(msg + '\n')
cont = False
else:
@@ -693,7 +699,6 @@ class ProcessSelectedFaces:
mFS = True
cont = False
else:
- # FreeCAD.Console.PrintError(' -Failed to create profile geometry for selected faces.\n')
cont = False
if cont:
@@ -705,8 +710,10 @@ class ProcessSelectedFaces:
ofstVal = self._calculateOffsetValue(isHole)
faceOfstShp = extractFaceOffset(cfsL, ofstVal, self.wpc)
- if faceOfstShp is False:
- FreeCAD.Console.PrintError(' -Failed to create offset face.\n')
+ if not faceOfstShp:
+ msg = translate('PathSurfaceSupport',
+ 'Failed to create offset face.') + '\n'
+ FreeCAD.Console.PrintError(msg)
cont = False
if cont:
@@ -763,7 +770,6 @@ class ProcessSelectedFaces:
mFS.append(True)
cont = False
else:
- # PathLog.error(' -Failed to create profile geometry for Face{}.'.format(fNum))
cont = False
if cont:
@@ -824,7 +830,6 @@ class ProcessSelectedFaces:
avoid = Part.makeCompound(outFCS)
if self.showDebugObjects:
- PathLog.debug('*** tmpAvoidArea')
P = FreeCAD.ActiveDocument.addObject('Part::Feature', 'tmpVoidEnvelope')
P.Shape = avoid
P.purgeTouched()
@@ -832,7 +837,6 @@ class ProcessSelectedFaces:
if cont:
if self.showDebugObjects:
- PathLog.debug('*** tmpVoidCompound')
P = FreeCAD.ActiveDocument.addObject('Part::Feature', 'tmpVoidCompound')
P.Shape = avoid
P.purgeTouched()
@@ -840,13 +844,15 @@ class ProcessSelectedFaces:
ofstVal = self._calculateOffsetValue(isHole, isVoid=True)
avdOfstShp = extractFaceOffset(avoid, ofstVal, self.wpc)
if avdOfstShp is False:
- FreeCAD.Console.PrintError('Failed to create collective offset avoid face.\n')
+ msg = translate('PathSurfaceSupport',
+ 'Failed to create collective offset avoid face.')
+ FreeCAD.Console.PrintError(msg + '\n')
cont = False
if cont:
avdShp = avdOfstShp
- if self.obj.AvoidLastX_InternalFeatures is False and len(intFEAT) > 0:
+ if not self.obj.AvoidLastX_InternalFeatures and len(intFEAT) > 0:
if len(intFEAT) > 1:
ifc = Part.makeCompound(intFEAT)
else:
@@ -854,7 +860,9 @@ class ProcessSelectedFaces:
ofstVal = self._calculateOffsetValue(isHole=True)
ifOfstShp = extractFaceOffset(ifc, ofstVal, self.wpc)
if ifOfstShp is False:
- FreeCAD.Console.PrintError('Failed to create collective offset avoid internal features.\n')
+ msg = translate('PathSurfaceSupport',
+ 'Failed to create collective offset avoid internal features.') + '\n'
+ FreeCAD.Console.PrintError(msg)
else:
avdShp = avdOfstShp.cut(ifOfstShp)
@@ -890,10 +898,10 @@ class ProcessSelectedFaces:
if csFaceShape is False:
csFaceShape = getSliceFromEnvelope(baseEnv)
if csFaceShape is False:
- PathLog.error('Failed to slice baseEnv shape.')
+ PathLog.debug('Failed to slice baseEnv shape.')
cont = False
- if cont is True and self.profileEdges != 'None':
+ if cont and self.profileEdges != 'None':
PathLog.debug(' -Attempting profile geometry for model base.')
ofstVal = self._calculateOffsetValue(isHole)
psOfst = extractFaceOffset(csFaceShape, ofstVal, self.wpc)
@@ -902,14 +910,13 @@ class ProcessSelectedFaces:
return (True, psOfst)
prflShp = psOfst
else:
- # FreeCAD.Console.PrintError(' -Failed to create profile geometry.\n')
cont = False
if cont:
ofstVal = self._calculateOffsetValue(isHole)
faceOffsetShape = extractFaceOffset(csFaceShape, ofstVal, self.wpc)
if faceOffsetShape is False:
- PathLog.error('extractFaceOffset() failed for entire base.')
+ PathLog.debug('extractFaceOffset() failed for entire base.')
else:
faceOffsetShape.translate(FreeCAD.Vector(0.0, 0.0, 0.0 - faceOffsetShape.BoundBox.ZMin))
return (faceOffsetShape, prflShp)
@@ -1023,7 +1030,6 @@ def getProjectedFace(tempGroup, wire):
else:
pWire = Part.Wire(prj.Shape.Edges)
if pWire.isClosed() is False:
- # PathLog.debug(' -pWire.isClosed() is False')
return False
slc = Part.Face(pWire)
slc.translate(FreeCAD.Vector(0.0, 0.0, 0.0 - slc.BoundBox.ZMin))
@@ -1068,7 +1074,7 @@ def getShapeEnvelope(shape):
try:
env = PathUtils.getEnvelope(partshape=shape, depthparams=dep_par) # Produces .Shape
except Exception as ee:
- FreeCAD.Console.PrintError('try: PathUtils.getEnvelope() failed.\n' + str(ee) + '\n')
+ FreeCAD.Console.PrintError('PathUtils.getEnvelope() failed.\n' + str(ee) + '\n')
return False
else:
return env
@@ -1195,7 +1201,9 @@ def _makeSafeSTL(self, JOB, obj, mdlIdx, faceShapes, voidShapes, ocl):
adjStckWst = stckWst
fuseShapes.append(adjStckWst)
else:
- PathLog.warning('Path transitions might not avoid the model. Verify paths.')
+ msg = translate('PathSurfaceSupport',
+ 'Path transitions might not avoid the model. Verify paths.')
+ FreeCAD.Console.PrintWarning(msg + '\n')
else:
# If boundbox is Job.Stock, add hidden pad under stock as base plate
toolDiam = self.cutter.getDiameter()
@@ -1318,7 +1326,6 @@ def pathGeomToLinesPointSet(obj, compGeoShp, cutClimb, toolDiam, closedGap, gaps
closedGap = True
True if closedGap else False # used closedGap for LGTM
else:
- # PathLog.debug('---- Gap: {} mm'.format(gap))
gap = round(gap, 6)
if gap < gaps[0]:
gaps.insert(0, gap)
@@ -1651,7 +1658,6 @@ def pathGeomToCircularPointSet(obj, compGeoShp, cutClimb, toolDiam, closedGap, g
arc = (vA, arc[1], vC)
closedGap = True
else:
- # PathLog.debug('---- Gap: {} mm'.format(gap))
gap = round(gap, 6)
if gap < gaps[0]:
gaps.insert(0, gap)
@@ -1837,7 +1843,9 @@ class FindUnifiedRegions:
tfBB_Area = tfBB.XLength * tfBB.YLength
# self._showShape(topFace, 'topFaceAlt_2_{}'.format(fNum))
if tfBB_Area < (fBB_Area * 0.9):
- FreeCAD.Console.PrintError('Faild to extract processing region for Face{}.\n'.format(fNum))
+ msg = translate('PathSurfaceSupport',
+ 'Faild to extract processing region for Face')
+ FreeCAD.Console.PrintError(msg + '{}.\n'.format(fNum))
cont = False
if cont:
@@ -2103,7 +2111,7 @@ class FindUnifiedRegions:
remList.append(s)
break
else:
- FreeCAD.Console.PrintWarning(' - No common area.\n')
+ PathLog.debug(' - No common area.\n')
remList.sort(reverse=True)
for ri in remList:
@@ -2213,7 +2221,9 @@ class FindUnifiedRegions:
of tuples (faceShape, faceIndex) received at instantiation of the class object.'''
self.INTERNALS = list()
if len(self.FACES) == 0:
- FreeCAD.Console.PrintError('No (faceShp, faceIdx) tuples received at instantiation of class.')
+ msg = translate('PathSurfaceSupport',
+ 'No FACE data tuples received at instantiation of class.')
+ FreeCAD.Console.PrintError(msg + '\n')
return []
self._extractTopFaces()
@@ -2253,11 +2263,8 @@ class FindUnifiedRegions:
return [topFace for (topFace, fcIdx) in self.topFaces]
else:
# Delete shared edges from edgeData list
- # FreeCAD.Console.PrintWarning('self.sharedEdgeIdxs: {}\n'.format(self.sharedEdgeIdxs))
self.sharedEdgeIdxs.sort(reverse=True)
for se in self.sharedEdgeIdxs:
- # seShp = self.edgeData[se][2]
- # self._showShape(seShp, 'SharedEdge')
self.edgeData.pop(se)
self._extractWiresFromEdges()
@@ -2273,6 +2280,8 @@ class FindUnifiedRegions:
after calling getUnifiedRegions().'''
if self.INTERNALS:
return self.INTERNALS
- FreeCAD.Console.PrintError('getUnifiedRegions() must be called before getInternalFeatures().\n')
+ msg = translate('PathSurfaceSupport',
+ 'getUnifiedRegions() must be called before getInternalFeatures().')
+ FreeCAD.Console.PrintError(msg + '\n')
return False
# Eclass
From c7222a51a79a4c5450032ee17bf39b5aa090a956 Mon Sep 17 00:00:00 2001
From: Russell Johnson <47639332+Russ4262@users.noreply.github.com>
Date: Wed, 3 Jun 2020 20:13:39 -0500
Subject: [PATCH 7/9] Path: Fix duplication of gcode for Single-pass layer
mode..
---
src/Mod/Path/PathScripts/PathWaterline.py | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/src/Mod/Path/PathScripts/PathWaterline.py b/src/Mod/Path/PathScripts/PathWaterline.py
index 0344350b59..98465b0171 100644
--- a/src/Mod/Path/PathScripts/PathWaterline.py
+++ b/src/Mod/Path/PathScripts/PathWaterline.py
@@ -575,7 +575,6 @@ class ObjectWaterline(PathOp.ObjectOp):
self.modelSTLs = PSF.modelSTLs
self.profileShapes = PSF.profileShapes
-
for m in range(0, len(JOB.Model.Group)):
# Create OCL.stl model objects
if obj.Algorithm == 'OCL Dropcutter':
@@ -661,7 +660,8 @@ class ObjectWaterline(PathOp.ObjectOp):
del self.midDep
execTime = time.time() - startTime
- PathLog.info('Operation time: {} sec.'.format(execTime))
+ msg = translate('PathWaterline', 'operation time is')
+ PathLog.info('Waterline ' + msg + ' {} sec.'.format(execTime))
return True
@@ -1294,6 +1294,8 @@ class ObjectWaterline(PathOp.ObjectOp):
clearArea = activeArea
if cont:
+ data = FreeCAD.Units.Quantity(csHght, FreeCAD.Units.Length).UserString
+ PathLog.debug('... Clearning area at {}.'.format(data))
# Make waterline path for current CUTAREA depth (csHght)
commands.extend(self._wiresToWaterlinePath(obj, clearArea, csHght))
clearArea.translate(FreeCAD.Vector(0.0, 0.0, 0.0 - clearArea.BoundBox.ZMin))
@@ -1311,7 +1313,8 @@ class ObjectWaterline(PathOp.ObjectOp):
commands.extend(self._makeCutPatternLayerPaths(JOB, obj, clearArea, csHght, cutPattern))
# Efor
- if clearLastLayer:
+ if clearLastLayer and obj.ClearLastLayer != 'Off':
+ PathLog.debug('... Clearning last layer')
(clrLyr, cLL) = self._clearLayer(obj, 1, 1, False)
lastClearArea.translate(FreeCAD.Vector(0.0, 0.0, 0.0 - lastClearArea.BoundBox.ZMin))
if clrLyr == 'Offset':
@@ -1319,7 +1322,6 @@ class ObjectWaterline(PathOp.ObjectOp):
elif clrLyr:
commands.extend(self._makeCutPatternLayerPaths(JOB, obj, lastClearArea, lastCsHght, obj.ClearLastLayer))
- PathLog.info("Waterline: All layer scans combined took " + str(time.time() - t_begin) + " s")
return commands
def _getCutAreas(self, shape, depthparams, bbFace, trimFace, borderFace):
@@ -1453,6 +1455,8 @@ class ObjectWaterline(PathOp.ObjectOp):
if cnt == 0:
ofst = 0.0 - self.cutOut
cnt += 1
+ PathLog.debug(' -Offset path count: {} at height: {}'.format(cnt, round(csHght, 2)))
+
return cmds
def _clearGeomToPaths(self, JOB, obj, safePDC, stpOVRS, cutPattern):
From c8f654e7a191a503fd0a5bb8ee90788d15aae3d7 Mon Sep 17 00:00:00 2001
From: Russell Johnson <47639332+Russ4262@users.noreply.github.com>
Date: Wed, 3 Jun 2020 21:24:18 -0500
Subject: [PATCH 8/9] Path: Fix error with multi-language usage of QComboBox
inputs
The methods here might need to be applied throughout PathWB to allow language translations of GUI combobox inputs.
---
src/Mod/Path/PathScripts/PathSurfaceGui.py | 42 ++++++++++++++++++----
1 file changed, 36 insertions(+), 6 deletions(-)
diff --git a/src/Mod/Path/PathScripts/PathSurfaceGui.py b/src/Mod/Path/PathScripts/PathSurfaceGui.py
index ab09c33d6f..d3bff733b7 100644
--- a/src/Mod/Path/PathScripts/PathSurfaceGui.py
+++ b/src/Mod/Path/PathScripts/PathSurfaceGui.py
@@ -42,6 +42,8 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
def initPage(self, obj):
self.setTitle("3D Surface")
# self.updateVisibility()
+ # retrieve property enumerations
+ self.propEnums = PathSurface.ObjectSurface.opPropertyEnumerations(False)
def getForm(self):
'''getForm() ... returns UI'''
@@ -61,11 +63,25 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
if obj.LayerMode != str(self.form.layerMode.currentText()):
obj.LayerMode = str(self.form.layerMode.currentText())
- if obj.CutPattern != str(self.form.cutPattern.currentText()):
- obj.CutPattern = str(self.form.cutPattern.currentText())
+ """
+ The following method of getting values from the UI form
+ allows for translations of combobox options in the UI.
+ The requirement is that the enumeration lists must
+ be in the same order in both the opPropertyEnumerations() method
+ and the UI panel QComboBox list.
+ Another step to ensure sychronization of the two lists is to
+ populate the list dynamically in this Gui module in `initPage()`
+ using the property enumerations list when loading the UI panel.
+ This type of dynamic combobox population is done for the
+ Tool Controller selection.
+ """
+ val = self.propEnums['CutPattern'][self.form.cutPattern.currentIndex()]
+ if obj.CutPattern != val:
+ obj.CutPattern = val
- if obj.ProfileEdges != str(self.form.profileEdges.currentText()):
- obj.ProfileEdges = str(self.form.profileEdges.currentText())
+ val = self.propEnums['ProfileEdges'][self.form.profileEdges.currentIndex()]
+ if obj.ProfileEdges != val:
+ obj.ProfileEdges = val
if obj.AvoidLastX_Faces != self.form.avoidLastX_Faces.value():
obj.AvoidLastX_Faces = self.form.avoidLastX_Faces.value()
@@ -99,8 +115,22 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
self.selectInComboBox(obj.BoundBox, self.form.boundBoxSelect)
self.selectInComboBox(obj.ScanType, self.form.scanType)
self.selectInComboBox(obj.LayerMode, self.form.layerMode)
- self.selectInComboBox(obj.CutPattern, self.form.cutPattern)
- self.selectInComboBox(obj.ProfileEdges, self.form.profileEdges)
+
+ """
+ The following method of setting values in the UI form
+ allows for translations of combobox options in the UI.
+ The requirement is that the enumeration lists must
+ be in the same order in both the opPropertyEnumerations() method
+ and the UI panel QComboBox list.
+ The original method is commented out below.
+ """
+ idx = self.propEnums['CutPattern'].index(obj.CutPattern)
+ self.form.cutPattern.setCurrentIndex(idx)
+ idx = self.propEnums['ProfileEdges'].index(obj.ProfileEdges)
+ self.form.profileEdges.setCurrentIndex(idx)
+ # self.selectInComboBox(obj.CutPattern, self.form.cutPattern)
+ # self.selectInComboBox(obj.ProfileEdges, self.form.profileEdges)
+
self.form.avoidLastX_Faces.setValue(obj.AvoidLastX_Faces)
self.form.boundBoxExtraOffsetX.setText(FreeCAD.Units.Quantity(obj.DropCutterExtraOffset.x, FreeCAD.Units.Length).UserString)
self.form.boundBoxExtraOffsetY.setText(FreeCAD.Units.Quantity(obj.DropCutterExtraOffset.y, FreeCAD.Units.Length).UserString)
From 1d18ad5e0a5f99645b39ccb482561bbce52389fd Mon Sep 17 00:00:00 2001
From: Russell Johnson <47639332+Russ4262@users.noreply.github.com>
Date: Thu, 4 Jun 2020 00:03:31 -0500
Subject: [PATCH 9/9] Path: Fix for single selected non-planar face
---
.../Path/PathScripts/PathSurfaceSupport.py | 31 +++++++++++++------
1 file changed, 22 insertions(+), 9 deletions(-)
diff --git a/src/Mod/Path/PathScripts/PathSurfaceSupport.py b/src/Mod/Path/PathScripts/PathSurfaceSupport.py
index 16865b2e38..3e5856a1bc 100644
--- a/src/Mod/Path/PathScripts/PathSurfaceSupport.py
+++ b/src/Mod/Path/PathScripts/PathSurfaceSupport.py
@@ -650,11 +650,13 @@ class ProcessSelectedFaces:
if F[m] is False:
F[m] = list()
F[m].append((shape, faceIdx))
+ PathLog.debug('.. Cutting {}'.format(sub))
hasFace = True
else:
if V[m] is False:
V[m] = list()
V[m].append((shape, faceIdx))
+ PathLog.debug('.. Avoiding {}'.format(sub))
hasVoid = True
return (hasFace, hasVoid)
@@ -690,7 +692,8 @@ class ProcessSelectedFaces:
cfsL = Part.makeCompound(outFCS)
# Handle profile edges request
- if cont is True and self.profileEdges != 'None':
+ if cont and self.profileEdges != 'None':
+ PathLog.debug('.. include Profile Edge')
ofstVal = self._calculateOffsetValue(isHole)
psOfst = extractFaceOffset(cfsL, ofstVal, self.wpc)
if psOfst is not False:
@@ -2228,24 +2231,34 @@ class FindUnifiedRegions:
self._extractTopFaces()
lenFaces = len(self.topFaces)
+ PathLog.debug('getUnifiedRegions() lenFaces: {}.'.format(lenFaces))
if lenFaces == 0:
return []
# if single topFace, return it
if lenFaces == 1:
topFace = self.topFaces[0][0]
- # self._showShape(topFace, 'TopFace')
+ self._showShape(topFace, 'TopFace')
# prepare inner wires as faces for internal features
lenWrs = len(topFace.Wires)
if lenWrs > 1:
for w in range(1, lenWrs):
- self.INTERNALS.append(Part.Face(topFace.Wires[w]))
- # prepare outer wire as face for return value in list
- if hasattr(topFace, 'OuterWire'):
- ow = topFace.OuterWire
- else:
- ow = topFace.Wires[0]
- face = Part.Face(ow)
+ # Any internal wires need to be flattened
+ # before appending to self.INTERNALS
+ # A problem exists that inner wires are not all recognized as wires.
+ # Some are single circular edges.
+ # Face.Edges.__len_() - Face.OuterWire.Edges.__len__() = edges for inner wire(s)
+
+ # extWire = getExtrudedShape(wr)
+ # wCS = getCrossSection(extWire)
+ # wCS.translate(FreeCAD.Vector(0.0, 0.0, wr.BoundBox.ZMin))
+ wr = topFace.Wires[w]
+ self.INTERNALS.append(Part.Face(wr))
+ # Flatten face and extract outer wire, then convert to face
+ extWire = getExtrudedShape(topFace)
+ wCS = getCrossSection(extWire)
+ wCS.translate(FreeCAD.Vector(0.0, 0.0, topFace.BoundBox.ZMin))
+ face = Part.Face(wCS)
return [face]
# process multiple top faces, unifying if possible