Skip to content

Commit

Permalink
4th-axis update (#2311)
Browse files Browse the repository at this point in the history
Improve property creation
Improve property setup
Implement PathLog.debug() for troubleshooting.
Improve default property values.
Remove unused and incomplete method
Remove unnecessary comments; fix final depth issue
4th-axis improvements
rotation method improvements
remove extra comment blocks
fix incorrect variable references
fix -0.0 re-introduction after initial filter
negative zero re-introduced causes problems with naming method for temp clones
Update faceRotationAnalaysis() method
update opFeatures()
Commented out call to PathOp.FeatureRotation
This feature not yet implemented.
delete call to removed method - self.reportThis()
Remove unnecessary comments
  • Loading branch information
Russ4262 authored and sliptonic committed Jul 1, 2019
1 parent e9f3551 commit 1ac8f4c
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 114 deletions.
133 changes: 63 additions & 70 deletions src/Mod/Path/PathScripts/PathAreaOp.py
Expand Up @@ -21,16 +21,6 @@
# * USA *
# * *
# ***************************************************************************
# * *
# * Additional modifications and contributions beginning 2019 *
# * Focus: 4th-axis integration *
# * by Russell Johnson <russ4262@gmail.com> *
# * *
# ***************************************************************************

# SCRIPT NOTES:
# - FUTURE: Relocate rotational calculations to Job setup tool, creating a Machine section
# with axis & rotation toggles and associated min/max values

import FreeCAD
import Path
Expand All @@ -51,10 +41,10 @@
__author__ = "sliptonic (Brad Collette)"
__url__ = "http://www.freecadweb.org"
__doc__ = "Base class and properties for Path.Area based operations."
__contributors__ = "mlampert [FreeCAD], russ4262 (Russell Johnson)"
__contributors__ = "russ4262 (Russell Johnson)"
__createdDate__ = "2017"
__scriptVersion__ = "2g testing"
__lastModified__ = "2019-06-13 15:37 CST"
__scriptVersion__ = "2h testing"
__lastModified__ = "2019-06-30 17:17 CST"

LOGLEVEL = False

Expand All @@ -64,9 +54,8 @@
else:
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())

# Qt translation handling


# Qt translation handling
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)

Expand Down Expand Up @@ -113,8 +102,6 @@ def initOperation(self, obj):
# obj.Proxy = self

self.setupAdditionalProperties(obj)


self.initAreaOp(obj)

def setupAdditionalProperties(self, obj):
Expand Down Expand Up @@ -176,8 +163,6 @@ def opOnDocumentRestored(self, obj):
self.initOpFinalDepth = obj.OpFinalDepth.Value
self.initOpStartDepth = obj.OpStartDepth.Value
self.docRestored = True
# PathLog.debug("Imported existing OpFinalDepth of " + str(self.initOpFinalDepth) + " for recompute() purposes.")
# PathLog.debug("Imported existing StartDepth of " + str(self.initOpStartDepth) + " for recompute() purposes.")

self.setupAdditionalProperties(obj)
self.areaOpOnDocumentRestored(obj)
Expand Down Expand Up @@ -225,7 +210,7 @@ def opSetDefaultValues(self, obj, job):
# Calculate rotational distances/radii
opHeights = self.opDetermineRotationRadii(obj) # return is list with tuples [(xRotRad, yRotRad, zRotRad), (clrOfst, safOfset)]
(xRotRad, yRotRad, zRotRad) = opHeights[0]
# (self.safOfset, self.safOfst) = opHeights[1]
# (clrOfset, safOfst) = opHeights[1]
PathLog.debug("opHeights[0]: " + str(opHeights[0]))
PathLog.debug("opHeights[1]: " + str(opHeights[1]))

Expand Down Expand Up @@ -334,9 +319,6 @@ def opExecute(self, obj, getsim=False):
areaOpUseProjection(obj) ... return true if operation can use projection
instead.'''
PathLog.track()
# PathLog.debug("OpDepths are Start: {}, and Final: {}".format(obj.OpStartDepth.Value, obj.OpFinalDepth.Value))
# PathLog.debug("Depths are Start: {}, and Final: {}".format(obj.StartDepth.Value, obj.FinalDepth.Value))
# PathLog.debug("initOpDepths are Start: {}, and Final: {}".format(self.initOpStartDepth, self.initOpFinalDepth))

# Instantiate class variables for operation reference
self.endVector = None
Expand Down Expand Up @@ -365,7 +347,7 @@ def opExecute(self, obj, getsim=False):
# Calculate operation heights based upon rotation radii
opHeights = self.opDetermineRotationRadii(obj)
(self.xRotRad, self.yRotRad, self.zRotRad) = opHeights[0]
(self.safOfset, self.safOfst) = opHeights[1]
(self.clrOfset, self.safOfst) = opHeights[1]

# Set clearnance and safe heights based upon rotation radii
if obj.EnableRotation == 'A(x)':
Expand All @@ -376,7 +358,7 @@ def opExecute(self, obj, getsim=False):
self.strDep = max(self.xRotRad, self.yRotRad)
self.finDep = -1 * self.strDep

obj.ClearanceHeight.Value = self.strDep + self.safOfset
obj.ClearanceHeight.Value = self.strDep + self.clrOfset
obj.SafeHeight.Value = self.strDep + self.safOfst

if self.initWithRotation is False:
Expand Down Expand Up @@ -513,7 +495,7 @@ def opExecute(self, obj, getsim=False):

self.useTempJobClones('Delete') # Delete temp job clone group and contents
self.guiMessage('title', None, show=True) # Process GUI messages to user
PathLog.debug("obj.Name: " + str(obj.Name))
PathLog.debug("obj.Name: " + str(obj.Name) + "\n\n")
return sims

def areaOpRetractTool(self, obj):
Expand Down Expand Up @@ -542,6 +524,7 @@ def areaOpUseProjection(self, obj):
Can safely be overwritten by subclasses.'''
return False

# Rotation-related methods
def opDetermineRotationRadii(self, obj):
'''opDetermineRotationRadii(obj)
Determine rotational radii for 4th-axis rotations, for clearance/safe heights '''
Expand Down Expand Up @@ -577,7 +560,7 @@ def opDetermineRotationRadii(self, obj):
zRotRad = math.sqrt(xlim**2 + ylim**2)

clrOfst = parentJob.SetupSheet.ClearanceHeightOffset.Value
safOfst = parentJob.SetupSheet.ClearanceHeightOffset.Value
safOfst = parentJob.SetupSheet.SafeHeightOffset.Value

return [(xRotRad, yRotRad, zRotRad), (clrOfst, safOfst)]

Expand All @@ -586,7 +569,7 @@ def faceRotationAnalysis(self, obj, norm, surf):
Determine X and Y independent rotation necessary to make normalAt = Z=1 (0,0,1) '''
PathLog.track()

praInfo = "faceRotationAnalysis() in PathAreaOp.py"
praInfo = "faceRotationAnalysis()"
rtn = True
axis = 'X'
orientation = 'X'
Expand Down Expand Up @@ -676,24 +659,39 @@ def roundRoughValues(precision, val):
angle = -1 * angle

# Enforce enabled rotation in settings
praInfo += "\n -Initial orientation: {}".format(orientation)
if orientation == 'Y':
axis = 'X'
if obj.EnableRotation == 'B(y)': # Required axis disabled
rtn = False
else:
if angle == 180.0 or angle == -180.0:
axis = 'Y'
else:
rtn = False
elif orientation == 'X':
axis = 'Y'
if obj.EnableRotation == 'A(x)': # Required axis disabled
rtn = False
if angle == 180.0 or angle == -180.0:
axis = 'X'
else:
rtn = False

if angle == 500.0:
if math.fabs(angle) == 0.0:
angle = 0.0
rtn = False

if angle == 0.0:
if angle == 500.0:
angle == 0.0
rtn = False

if rtn is False:
if orientation == 'Z' and angle == 0.0 and obj.ReverseDirection is True:
if obj.EnableRotation == 'B(y)':
axis = 'Y'
rtn = True

if rtn is True:
self.rotateFlag = True
rtn = True
# rtn = True
if obj.ReverseDirection is True:
if angle < 180.0:
angle = angle + 180.0
Expand All @@ -717,18 +715,20 @@ def guiMessage(self, title, msg, show=False):
if msg is not None:
self.guiMsgs.append((title, msg))
if show is True:
if FreeCAD.GuiUp and len(self.guiMsgs) > 0:
# self.guiMsgs.pop(0) # remove formatted place holder.
from PySide.QtGui import QMessageBox
# from PySide import QtGui
for entry in self.guiMsgs:
(title, msg) = entry
QMessageBox.warning(None, title, msg)
# QtGui.QMessageBox.warning(None, title, msg)
self.guiMsgs = [] # Reset messages
return True

# Types: information, warning, critical, question
if len(self.guiMsgs) > 0:
if FreeCAD.GuiUp:
from PySide.QtGui import QMessageBox
for entry in self.guiMsgs:
(title, msg) = entry
QMessageBox.warning(None, title, msg)
self.guiMsgs = [] # Reset messages
return True
else:
for entry in self.guiMsgs:
(title, msg) = entry
PathLog.warning("{}:: {}".format(title, msg))
self.guiMsgs = [] # Reset messages
return True
return False

def visualAxis(self):
Expand Down Expand Up @@ -773,21 +773,6 @@ def visualAxis(self):
cylGui.Visibility = False
vaGrp.addObject(cyl)

# if False:
# FreeCAD.ActiveDocument.addObject("Part::Cylinder", zAx)
# cyl = FreeCAD.ActiveDocument.getObject(zAx)
# cyl.Label = zAx
# cyl.Radius = self.yRotRad
# cyl.Height = 0.01
# # cyl.Placement = FreeCAD.Placement(FreeCAD.Vector(0,0,0),FreeCAD.Rotation(FreeCAD.Vector(1,0,0),90))
# cyl.purgeTouched()
# if FreeCAD.GuiUp:
# cylGui = FreeCADGui.ActiveDocument.getObject(zAx)
# cylGui.ShapeColor = (0.000, 0.000, 0.498)
# cylGui.Transparency = 85
# cylGui.Visibility = False
# vaGrp.addObject(cyl)

def useTempJobClones(self, cloneName):
'''useTempJobClones(cloneName)
Manage use of temporary model clones for rotational operation calculations.
Expand Down Expand Up @@ -828,16 +813,18 @@ def cloneBaseAndStock(self, obj, base, angle, axis, subCount):
self.cloneNames.append(clnNm)
self.cloneNames.append(stckClnNm)
if FreeCAD.ActiveDocument.getObject(clnNm):
FreeCAD.ActiveDocument.removeObject(clnNm)
FreeCAD.ActiveDocument.getObject(clnNm).Shape = base.Shape
else:
FreeCAD.ActiveDocument.addObject('Part::Feature', clnNm).Shape = base.Shape
self.useTempJobClones(clnNm)
if FreeCAD.ActiveDocument.getObject(stckClnNm):
FreeCAD.ActiveDocument.removeObject(stckClnNm)
FreeCAD.ActiveDocument.addObject('Part::Feature', clnNm).Shape = base.Shape
FreeCAD.ActiveDocument.addObject('Part::Feature', stckClnNm).Shape = PathUtils.findParentJob(obj).Stock.Shape
FreeCAD.ActiveDocument.getObject(stckClnNm).Shape = PathUtils.findParentJob(obj).Stock.Shape
else:
FreeCAD.ActiveDocument.addObject('Part::Feature', stckClnNm).Shape = PathUtils.findParentJob(obj).Stock.Shape
self.useTempJobClones(stckClnNm)
if FreeCAD.GuiUp:
FreeCADGui.ActiveDocument.getObject(stckClnNm).Transparency = 90
FreeCADGui.ActiveDocument.getObject(clnNm).ShapeColor = (1.000, 0.667, 0.000)
self.useTempJobClones(clnNm)
self.useTempJobClones(stckClnNm)
clnBase = FreeCAD.ActiveDocument.getObject(clnNm)
clnStock = FreeCAD.ActiveDocument.getObject(stckClnNm)
tag = base.Name + '_' + tag
Expand Down Expand Up @@ -878,6 +865,8 @@ def applyRotationalAnalysis(self, obj, base, angle, axis, subCount):

if obj.InverseAngle is True:
angle = -1 * angle
if math.fabs(angle) == 0.0:
angle = 0.0

# Create a temporary clone of model for rotational use.
(clnBase, clnStock, tag) = self.cloneBaseAndStock(obj, base, angle, axis, subCount)
Expand Down Expand Up @@ -952,14 +941,18 @@ def sortTuplesByIndex(self, TupleList, tagIdx):
GroupList.pop(0)
return (TagList, GroupList)

def warnDisabledAxis(self, obj, axis):
def warnDisabledAxis(self, obj, axis, sub=''):
'''warnDisabledAxis(self, obj, axis)
Provide user feedback if required axis is disabled'''
if axis == 'X' and obj.EnableRotation == 'B(y)':
PathLog.warning(translate('Path', "Part feature is inaccessible. Selected feature(s) require 'A(x)' for access."))
msg = translate('Path', "{}:: {} is inaccessible.".format(obj.Name, sub)) + " "
msg += translate('Path', "Selected feature(s) require 'Enable Rotation: A(x)' for access.")
PathLog.warning(msg)
return True
elif axis == 'Y' and obj.EnableRotation == 'A(x)':
PathLog.warning(translate('Path', "Part feature is inaccessible. Selected feature(s) require 'B(y)' for access."))
msg = translate('Path', "{}:: {} is inaccessible.".format(obj.Name, sub)) + " "
msg += translate('Path', "Selected feature(s) require 'Enable Rotation: B(y)' for access.")
PathLog.warning(msg)
return True
else:
return False

0 comments on commit 1ac8f4c

Please sign in to comment.