Merge pull request #1 from Russ4262/4th-axis-improve
4th-axis fixes and improvements
This commit is contained in:
@@ -392,15 +392,7 @@ class ObjectOp(PathOp.ObjectOp):
|
|||||||
self.axialRapid = 360 / safeCircum * self.horizRapid # pylint: disable=attribute-defined-outside-init
|
self.axialRapid = 360 / safeCircum * self.horizRapid # pylint: disable=attribute-defined-outside-init
|
||||||
|
|
||||||
# Initiate depthparams and calculate operation heights for rotational operation
|
# Initiate depthparams and calculate operation heights for rotational operation
|
||||||
finish_step = obj.FinishDepth.Value if hasattr(obj, "FinishDepth") else 0.0
|
self.depthparams = self._customDepthParams(obj, obj.StartDepth.Value, obj.FinalDepth.Value)
|
||||||
self.depthparams = PathUtils.depth_params( # pylint: disable=attribute-defined-outside-init
|
|
||||||
clearance_height=obj.ClearanceHeight.Value,
|
|
||||||
safe_height=obj.SafeHeight.Value,
|
|
||||||
start_depth=obj.StartDepth.Value,
|
|
||||||
step_down=obj.StepDown.Value,
|
|
||||||
z_finish_step=finish_step,
|
|
||||||
final_depth=obj.FinalDepth.Value,
|
|
||||||
user_depths=None)
|
|
||||||
|
|
||||||
# Set start point
|
# Set start point
|
||||||
if PathOp.FeatureStartPoint & self.opFeatures(obj) and obj.UseStartPoint:
|
if PathOp.FeatureStartPoint & self.opFeatures(obj) and obj.UseStartPoint:
|
||||||
@@ -446,15 +438,7 @@ class ObjectOp(PathOp.ObjectOp):
|
|||||||
else:
|
else:
|
||||||
nextAxis = 'L'
|
nextAxis = 'L'
|
||||||
|
|
||||||
finish_step = obj.FinishDepth.Value if hasattr(obj, "FinishDepth") else 0.0
|
self.depthparams = self._customDepthParams(obj, strDep, finDep)
|
||||||
self.depthparams = PathUtils.depth_params( # pylint: disable=attribute-defined-outside-init
|
|
||||||
clearance_height=obj.ClearanceHeight.Value,
|
|
||||||
safe_height=obj.SafeHeight.Value,
|
|
||||||
start_depth=strDep, # obj.StartDepth.Value,
|
|
||||||
step_down=obj.StepDown.Value,
|
|
||||||
z_finish_step=finish_step,
|
|
||||||
final_depth=finDep, # obj.FinalDepth.Value,
|
|
||||||
user_depths=None)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if self.profileEdgesIsOpen is True:
|
if self.profileEdgesIsOpen is True:
|
||||||
@@ -475,22 +459,16 @@ class ObjectOp(PathOp.ObjectOp):
|
|||||||
axisOfRot = 'A'
|
axisOfRot = 'A'
|
||||||
elif axis == 'Y':
|
elif axis == 'Y':
|
||||||
axisOfRot = 'B'
|
axisOfRot = 'B'
|
||||||
# Reverse angle temporarily to match model. Error in FreeCAD render of B axis rotations
|
|
||||||
if obj.B_AxisErrorOverride is True:
|
|
||||||
angle = -1 * angle
|
|
||||||
elif axis == 'Z':
|
elif axis == 'Z':
|
||||||
axisOfRot = 'C'
|
axisOfRot = 'C'
|
||||||
else:
|
else:
|
||||||
axisOfRot = 'A'
|
axisOfRot = 'A'
|
||||||
|
|
||||||
# Rotate Model to correct angle
|
# Rotate Model to correct angle
|
||||||
ppCmds.insert(0, Path.Command('G0', {axisOfRot: angle, 'F': self.axialFeed}))
|
ppCmds.insert(0, Path.Command('G0', {axisOfRot: angle, 'F': self.axialRapid}))
|
||||||
#ppCmds.insert(0, Path.Command('N100', {}))
|
|
||||||
|
|
||||||
# Raise cutter to safe depth and return index to starting position
|
# Raise cutter to safe depth and return index to starting position
|
||||||
#ppCmds.append(Path.Command('N200', {}))
|
|
||||||
ppCmds.append(Path.Command('G0', {'Z': obj.SafeHeight.Value, 'F': self.vertRapid}))
|
ppCmds.append(Path.Command('G0', {'Z': obj.SafeHeight.Value, 'F': self.vertRapid}))
|
||||||
if 'L' != nextAxis:
|
if axis != nextAxis:
|
||||||
ppCmds.append(Path.Command('G0', {axisOfRot: 0.0, 'F': self.axialRapid}))
|
ppCmds.append(Path.Command('G0', {axisOfRot: 0.0, 'F': self.axialRapid}))
|
||||||
# Eif
|
# Eif
|
||||||
|
|
||||||
@@ -762,7 +740,7 @@ class ObjectOp(PathOp.ObjectOp):
|
|||||||
xAx = 'xAxCyl'
|
xAx = 'xAxCyl'
|
||||||
yAx = 'yAxCyl'
|
yAx = 'yAxCyl'
|
||||||
# zAx = 'zAxCyl'
|
# zAx = 'zAxCyl'
|
||||||
FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup", "visualAxis")
|
VA = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup", "visualAxis")
|
||||||
if FreeCAD.GuiUp:
|
if FreeCAD.GuiUp:
|
||||||
FreeCADGui.ActiveDocument.getObject('visualAxis').Visibility = False
|
FreeCADGui.ActiveDocument.getObject('visualAxis').Visibility = False
|
||||||
vaGrp = FreeCAD.ActiveDocument.getObject("visualAxis")
|
vaGrp = FreeCAD.ActiveDocument.getObject("visualAxis")
|
||||||
@@ -794,6 +772,7 @@ class ObjectOp(PathOp.ObjectOp):
|
|||||||
cylGui.Transparency = 85
|
cylGui.Transparency = 85
|
||||||
cylGui.Visibility = False
|
cylGui.Visibility = False
|
||||||
vaGrp.addObject(cyl)
|
vaGrp.addObject(cyl)
|
||||||
|
VA.purgeTouched()
|
||||||
|
|
||||||
def useTempJobClones(self, cloneName):
|
def useTempJobClones(self, cloneName):
|
||||||
'''useTempJobClones(cloneName)
|
'''useTempJobClones(cloneName)
|
||||||
@@ -809,6 +788,8 @@ class ObjectOp(PathOp.ObjectOp):
|
|||||||
for cln in FreeCAD.ActiveDocument.getObject('rotJobClones').Group:
|
for cln in FreeCAD.ActiveDocument.getObject('rotJobClones').Group:
|
||||||
FreeCAD.ActiveDocument.removeObject(cln.Name)
|
FreeCAD.ActiveDocument.removeObject(cln.Name)
|
||||||
FreeCAD.ActiveDocument.removeObject('rotJobClones')
|
FreeCAD.ActiveDocument.removeObject('rotJobClones')
|
||||||
|
else:
|
||||||
|
FreeCAD.ActiveDocument.getObject('rotJobClones').purgeTouched()
|
||||||
else:
|
else:
|
||||||
FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup", "rotJobClones")
|
FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup", "rotJobClones")
|
||||||
if FreeCAD.GuiUp:
|
if FreeCAD.GuiUp:
|
||||||
@@ -918,7 +899,7 @@ class ObjectOp(PathOp.ObjectOp):
|
|||||||
obj.AttemptInverseAngle = False
|
obj.AttemptInverseAngle = False
|
||||||
angle = -1 * angle
|
angle = -1 * angle
|
||||||
|
|
||||||
PathLog.info(translate("Path", "Rotated to inverse angle."))
|
PathLog.debug(translate("Path", "Rotated to inverse angle."))
|
||||||
return (clnBase, clnStock, angle)
|
return (clnBase, clnStock, angle)
|
||||||
|
|
||||||
def sortTuplesByIndex(self, TupleList, tagIdx):
|
def sortTuplesByIndex(self, TupleList, tagIdx):
|
||||||
@@ -961,3 +942,28 @@ class ObjectOp(PathOp.ObjectOp):
|
|||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def isFaceUp(self, base, face):
|
||||||
|
up = face.extrude(FreeCAD.Vector(0.0, 0.0, 5.0))
|
||||||
|
dwn = face.extrude(FreeCAD.Vector(0.0, 0.0, -5.0))
|
||||||
|
upCmn = base.Shape.common(up)
|
||||||
|
dwnCmn = base.Shape.common(dwn)
|
||||||
|
if upCmn.Volume == 0.0:
|
||||||
|
return True
|
||||||
|
elif dwnCmn.Volume == 0.0:
|
||||||
|
return False
|
||||||
|
if dwnCmn.Volume > upCmn.Volume:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _customDepthParams(self, obj, strDep, finDep):
|
||||||
|
finish_step = obj.FinishDepth.Value if hasattr(obj, "FinishDepth") else 0.0
|
||||||
|
cdp = PathUtils.depth_params(
|
||||||
|
clearance_height=obj.ClearanceHeight.Value,
|
||||||
|
safe_height=obj.SafeHeight.Value,
|
||||||
|
start_depth=strDep,
|
||||||
|
step_down=obj.StepDown.Value,
|
||||||
|
z_finish_step=finish_step,
|
||||||
|
final_depth=finDep,
|
||||||
|
user_depths=None)
|
||||||
|
return cdp
|
||||||
|
|||||||
@@ -45,11 +45,9 @@ __url__ = "http://www.freecadweb.org"
|
|||||||
__doc__ = "Path Drilling operation."
|
__doc__ = "Path Drilling operation."
|
||||||
__contributors__ = "russ4262 (Russell Johnson), IMBack!"
|
__contributors__ = "russ4262 (Russell Johnson), IMBack!"
|
||||||
__created__ = "2014"
|
__created__ = "2014"
|
||||||
__scriptVersion__ = "1c testing"
|
|
||||||
__lastModified__ = "2019-06-25 14:49 CST"
|
|
||||||
|
|
||||||
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
|
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
|
||||||
#PathLog.trackModule(PathLog.thisModule())
|
# PathLog.trackModule(PathLog.thisModule())
|
||||||
|
|
||||||
|
|
||||||
# Qt translation handling
|
# Qt translation handling
|
||||||
@@ -84,8 +82,6 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp):
|
|||||||
obj.addProperty('App::PropertyBool', 'ReverseDirection', 'Rotation', QtCore.QT_TRANSLATE_NOOP('App::Property', 'Reverse direction of pocket operation.'))
|
obj.addProperty('App::PropertyBool', 'ReverseDirection', 'Rotation', QtCore.QT_TRANSLATE_NOOP('App::Property', 'Reverse direction of pocket operation.'))
|
||||||
if not hasattr(obj, 'InverseAngle'):
|
if not hasattr(obj, 'InverseAngle'):
|
||||||
obj.addProperty('App::PropertyBool', 'InverseAngle', 'Rotation', QtCore.QT_TRANSLATE_NOOP('App::Property', 'Inverse the angle. Example: -22.5 -> 22.5 degrees.'))
|
obj.addProperty('App::PropertyBool', 'InverseAngle', 'Rotation', QtCore.QT_TRANSLATE_NOOP('App::Property', 'Inverse the angle. Example: -22.5 -> 22.5 degrees.'))
|
||||||
if not hasattr(obj, 'B_AxisErrorOverride'):
|
|
||||||
obj.addProperty('App::PropertyBool', 'B_AxisErrorOverride', 'Rotation', QtCore.QT_TRANSLATE_NOOP('App::Property', 'Match B rotations to model (error in FreeCAD rendering).'))
|
|
||||||
if not hasattr(obj, 'AttemptInverseAngle'):
|
if not hasattr(obj, 'AttemptInverseAngle'):
|
||||||
obj.addProperty('App::PropertyBool', 'AttemptInverseAngle', 'Rotation', QtCore.QT_TRANSLATE_NOOP('App::Property', 'Attempt the inverse angle for face access if original rotation fails.'))
|
obj.addProperty('App::PropertyBool', 'AttemptInverseAngle', 'Rotation', QtCore.QT_TRANSLATE_NOOP('App::Property', 'Attempt the inverse angle for face access if original rotation fails.'))
|
||||||
|
|
||||||
@@ -135,9 +131,6 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp):
|
|||||||
axisOfRot = 'A'
|
axisOfRot = 'A'
|
||||||
elif axis == 'Y':
|
elif axis == 'Y':
|
||||||
axisOfRot = 'B'
|
axisOfRot = 'B'
|
||||||
# Reverse angle temporarily to match model. Error in FreeCAD render of B axis rotations
|
|
||||||
if obj.B_AxisErrorOverride is True:
|
|
||||||
angle = -1 * angle
|
|
||||||
elif axis == 'Z':
|
elif axis == 'Z':
|
||||||
axisOfRot = 'C'
|
axisOfRot = 'C'
|
||||||
else:
|
else:
|
||||||
@@ -163,12 +156,10 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp):
|
|||||||
# Perform canned drilling cycle
|
# Perform canned drilling cycle
|
||||||
self.commandlist.append(Path.Command(cmd, params))
|
self.commandlist.append(Path.Command(cmd, params))
|
||||||
|
|
||||||
# cancel canned drilling cycle
|
# Cancel canned drilling cycle
|
||||||
self.commandlist.append(Path.Command('G80'))
|
self.commandlist.append(Path.Command('G80'))
|
||||||
self.commandlist.append(Path.Command('G0', {'Z': obj.SafeHeight.Value}))
|
self.commandlist.append(Path.Command('G0', {'Z': obj.SafeHeight.Value}))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# shift axis and angle values
|
# shift axis and angle values
|
||||||
if obj.EnableRotation != 'Off':
|
if obj.EnableRotation != 'Off':
|
||||||
lastAxis = axisOfRot
|
lastAxis = axisOfRot
|
||||||
@@ -178,7 +169,6 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp):
|
|||||||
self.commandlist.append(Path.Command('G0', {'Z': obj.SafeHeight.Value, 'F': self.vertRapid}))
|
self.commandlist.append(Path.Command('G0', {'Z': obj.SafeHeight.Value, 'F': self.vertRapid}))
|
||||||
self.commandlist.append(Path.Command('G0', {lastAxis: 0.0, 'F': self.axialRapid}))
|
self.commandlist.append(Path.Command('G0', {lastAxis: 0.0, 'F': self.axialRapid}))
|
||||||
|
|
||||||
|
|
||||||
def opSetDefaultValues(self, obj, job):
|
def opSetDefaultValues(self, obj, job):
|
||||||
'''opSetDefaultValues(obj, job) ... set default value for RetractHeight'''
|
'''opSetDefaultValues(obj, job) ... set default value for RetractHeight'''
|
||||||
|
|
||||||
@@ -201,7 +191,6 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp):
|
|||||||
|
|
||||||
obj.ReverseDirection = False
|
obj.ReverseDirection = False
|
||||||
obj.InverseAngle = False
|
obj.InverseAngle = False
|
||||||
obj.B_AxisErrorOverride = False
|
|
||||||
obj.AttemptInverseAngle = False
|
obj.AttemptInverseAngle = False
|
||||||
|
|
||||||
# Initial setting for EnableRotation is taken from Job SetupSheet
|
# Initial setting for EnableRotation is taken from Job SetupSheet
|
||||||
@@ -224,7 +213,6 @@ def SetupProperties():
|
|||||||
setup.append("EnableRotation")
|
setup.append("EnableRotation")
|
||||||
setup.append("ReverseDirection")
|
setup.append("ReverseDirection")
|
||||||
setup.append("InverseAngle")
|
setup.append("InverseAngle")
|
||||||
setup.append("B_AxisErrorOverride")
|
|
||||||
setup.append("AttemptInverseAngle")
|
setup.append("AttemptInverseAngle")
|
||||||
return setup
|
return setup
|
||||||
|
|
||||||
|
|||||||
@@ -34,12 +34,14 @@ __url__ = "http://www.freecadweb.org"
|
|||||||
__doc__ = "Base class and implementation for Path pocket operations."
|
__doc__ = "Base class and implementation for Path pocket operations."
|
||||||
|
|
||||||
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
|
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
|
||||||
#PathLog.trackModule(PathLog.thisModule())
|
# PathLog.trackModule(PathLog.thisModule())
|
||||||
|
|
||||||
|
|
||||||
# Qt translation handling
|
# Qt translation handling
|
||||||
def translate(context, text, disambig=None):
|
def translate(context, text, disambig=None):
|
||||||
return QtCore.QCoreApplication.translate(context, text, disambig)
|
return QtCore.QCoreApplication.translate(context, text, disambig)
|
||||||
|
|
||||||
|
|
||||||
class ObjectPocket(PathAreaOp.ObjectOp):
|
class ObjectPocket(PathAreaOp.ObjectOp):
|
||||||
'''Base class for proxy objects of all pocket operations.'''
|
'''Base class for proxy objects of all pocket operations.'''
|
||||||
|
|
||||||
@@ -130,6 +132,7 @@ class ObjectPocket(PathAreaOp.ObjectOp):
|
|||||||
params['threshold'] = self.radius * 2
|
params['threshold'] = self.radius * 2
|
||||||
return params
|
return params
|
||||||
|
|
||||||
|
|
||||||
def SetupProperties():
|
def SetupProperties():
|
||||||
setup = []
|
setup = []
|
||||||
setup.append('CutMode')
|
setup.append('CutMode')
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
# ***************************************************************************
|
# ***************************************************************************
|
||||||
# * *
|
# * *
|
||||||
# * Copyright (c) 2017 sliptonic <shopinthewoods@gmail.com> *
|
# * Copyright (c) 2017 sliptonic <shopinthewoods@gmail.com> *
|
||||||
# * Copyright (c) 2020 russ4262 (Russell Johnson) *
|
|
||||||
# * Copyright (c) 2020 Schildkroet *
|
# * Copyright (c) 2020 Schildkroet *
|
||||||
# * *
|
# * *
|
||||||
# * This program is free software; you can redistribute it and/or modify *
|
# * This program is free software; you can redistribute it and/or modify *
|
||||||
@@ -33,6 +32,7 @@ import PathScripts.PathPocketBase as PathPocketBase
|
|||||||
import PathScripts.PathUtils as PathUtils
|
import PathScripts.PathUtils as PathUtils
|
||||||
import TechDraw
|
import TechDraw
|
||||||
import math
|
import math
|
||||||
|
import Draft
|
||||||
|
|
||||||
from PySide import QtCore
|
from PySide import QtCore
|
||||||
|
|
||||||
@@ -41,9 +41,10 @@ __author__ = "sliptonic (Brad Collette)"
|
|||||||
__url__ = "http://www.freecadweb.org"
|
__url__ = "http://www.freecadweb.org"
|
||||||
__doc__ = "Class and implementation of shape based Pocket operation."
|
__doc__ = "Class and implementation of shape based Pocket operation."
|
||||||
|
|
||||||
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
|
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
|
||||||
# PathLog.trackModule(PathLog.thisModule())
|
# PathLog.trackModule(PathLog.thisModule())
|
||||||
|
|
||||||
|
|
||||||
# Qt translation handling
|
# Qt translation handling
|
||||||
def translate(context, text, disambig=None):
|
def translate(context, text, disambig=None):
|
||||||
return QtCore.QCoreApplication.translate(context, text, disambig)
|
return QtCore.QCoreApplication.translate(context, text, disambig)
|
||||||
@@ -254,20 +255,41 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
|
|||||||
obj.addProperty('App::PropertyBool', 'ExtensionCorners', 'Extension', QtCore.QT_TRANSLATE_NOOP('PathPocketShape', 'When enabled connected extension edges are combined to wires.'))
|
obj.addProperty('App::PropertyBool', 'ExtensionCorners', 'Extension', QtCore.QT_TRANSLATE_NOOP('PathPocketShape', 'When enabled connected extension edges are combined to wires.'))
|
||||||
obj.ExtensionCorners = True
|
obj.ExtensionCorners = True
|
||||||
|
|
||||||
|
obj.setEditorMode('ExtensionFeature', 2)
|
||||||
|
self.initRotationOp(obj)
|
||||||
|
|
||||||
|
def initRotationOp(self, obj):
|
||||||
|
'''initRotationOp(obj) ... setup receiver for rotation'''
|
||||||
if not hasattr(obj, 'ReverseDirection'):
|
if not hasattr(obj, 'ReverseDirection'):
|
||||||
obj.addProperty('App::PropertyBool', 'ReverseDirection', 'Rotation', QtCore.QT_TRANSLATE_NOOP('App::Property', 'Reverse direction of pocket operation.'))
|
obj.addProperty('App::PropertyBool', 'ReverseDirection', 'Rotation', QtCore.QT_TRANSLATE_NOOP('App::Property', 'Reverse direction of pocket operation.'))
|
||||||
if not hasattr(obj, 'InverseAngle'):
|
if not hasattr(obj, 'InverseAngle'):
|
||||||
obj.addProperty('App::PropertyBool', 'InverseAngle', 'Rotation', QtCore.QT_TRANSLATE_NOOP('App::Property', 'Inverse the angle. Example: -22.5 -> 22.5 degrees.'))
|
obj.addProperty('App::PropertyBool', 'InverseAngle', 'Rotation', QtCore.QT_TRANSLATE_NOOP('App::Property', 'Inverse the angle. Example: -22.5 -> 22.5 degrees.'))
|
||||||
if not hasattr(obj, 'B_AxisErrorOverride'):
|
|
||||||
obj.addProperty('App::PropertyBool', 'B_AxisErrorOverride', 'Rotation', QtCore.QT_TRANSLATE_NOOP('App::Property', 'Match B rotations to model (error in FreeCAD rendering).'))
|
|
||||||
if not hasattr(obj, 'AttemptInverseAngle'):
|
if not hasattr(obj, 'AttemptInverseAngle'):
|
||||||
obj.addProperty('App::PropertyBool', 'AttemptInverseAngle', 'Rotation', QtCore.QT_TRANSLATE_NOOP('App::Property', 'Attempt the inverse angle for face access if original rotation fails.'))
|
obj.addProperty('App::PropertyBool', 'AttemptInverseAngle', 'Rotation', QtCore.QT_TRANSLATE_NOOP('App::Property', 'Attempt the inverse angle for face access if original rotation fails.'))
|
||||||
|
if not hasattr(obj, 'LimitDepthToFace'):
|
||||||
|
obj.addProperty('App::PropertyBool', 'LimitDepthToFace', 'Rotation', QtCore.QT_TRANSLATE_NOOP('App::Property', 'Enforce the Z-depth of the selected face as the lowest value for final depth. Higher user values will be observed.'))
|
||||||
|
|
||||||
obj.setEditorMode('ExtensionFeature', 2)
|
def areaOpOnChanged(self, obj, prop):
|
||||||
|
'''areaOpOnChanged(obj, porp) ... process operation specific changes to properties.'''
|
||||||
|
if prop == 'EnableRotation':
|
||||||
|
self.setEditorProperties(obj)
|
||||||
|
|
||||||
|
def setEditorProperties(self, obj):
|
||||||
|
if obj.EnableRotation == 'Off':
|
||||||
|
obj.setEditorMode('ReverseDirection', 2)
|
||||||
|
obj.setEditorMode('InverseAngle', 2)
|
||||||
|
obj.setEditorMode('AttemptInverseAngle', 2)
|
||||||
|
obj.setEditorMode('LimitDepthToFace', 2)
|
||||||
|
else:
|
||||||
|
obj.setEditorMode('ReverseDirection', 0)
|
||||||
|
obj.setEditorMode('InverseAngle', 0)
|
||||||
|
obj.setEditorMode('AttemptInverseAngle', 0)
|
||||||
|
obj.setEditorMode('LimitDepthToFace', 0)
|
||||||
|
|
||||||
def areaOpOnDocumentRestored(self, obj):
|
def areaOpOnDocumentRestored(self, obj):
|
||||||
'''opOnDocumentRestored(obj) ... adds the UseOutline property if it doesn't exist.'''
|
'''opOnDocumentRestored(obj) ... adds the UseOutline property, others, if they doesn't exist.'''
|
||||||
self.initPocketOp(obj)
|
self.initPocketOp(obj)
|
||||||
|
self.setEditorProperties(obj)
|
||||||
|
|
||||||
def pocketInvertExtraOffset(self):
|
def pocketInvertExtraOffset(self):
|
||||||
return False
|
return False
|
||||||
@@ -415,12 +437,18 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
|
|||||||
if type(face.Surface) == Part.Plane:
|
if type(face.Surface) == Part.Plane:
|
||||||
if not PathGeom.isHorizontal(face.Surface.Axis):
|
if not PathGeom.isHorizontal(face.Surface.Axis):
|
||||||
rtn = False
|
rtn = False
|
||||||
|
PathLog.warning(translate("PathPocketShape", "Face appears to NOT be horizontal AFTER rotation applied."))
|
||||||
break
|
break
|
||||||
if rtn is False:
|
if rtn is False:
|
||||||
if obj.AttemptInverseAngle is True and obj.InverseAngle is False:
|
if obj.InverseAngle is False:
|
||||||
(clnBase, clnStock, angle) = self.applyInverseAngle(obj, clnBase, clnStock, axis, angle)
|
if obj.AttemptInverseAngle is True:
|
||||||
else:
|
PathLog.debug("Applying the inverse angle.")
|
||||||
PathLog.info(translate("Path", "Consider toggling the InverseAngle property and recomputing the operation."))
|
(clnBase, clnStock, angle) = self.applyInverseAngle(obj, clnBase, clnStock, axis, angle)
|
||||||
|
else:
|
||||||
|
PathLog.warning(translate("Path", "Consider toggling the InverseAngle property and recomputing the operation."))
|
||||||
|
|
||||||
|
if angle < -180.0:
|
||||||
|
angle += 360.0
|
||||||
|
|
||||||
tup = clnBase, subsList, angle, axis, clnStock
|
tup = clnBase, subsList, angle, axis, clnStock
|
||||||
else:
|
else:
|
||||||
@@ -465,17 +493,21 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
|
|||||||
faceIA = clnBase.Shape.getElement(sub)
|
faceIA = clnBase.Shape.getElement(sub)
|
||||||
(norm, surf) = self.getFaceNormAndSurf(faceIA)
|
(norm, surf) = self.getFaceNormAndSurf(faceIA)
|
||||||
(rtn, praAngle, praAxis, praInfo) = self.faceRotationAnalysis(obj, norm, surf) # pylint: disable=unused-variable
|
(rtn, praAngle, praAxis, praInfo) = self.faceRotationAnalysis(obj, norm, surf) # pylint: disable=unused-variable
|
||||||
|
|
||||||
if rtn is True:
|
if rtn is True:
|
||||||
PathLog.debug("Face not aligned after initial rotation.")
|
PathLog.debug("Face not aligned after initial rotation.")
|
||||||
if obj.AttemptInverseAngle is True and obj.InverseAngle is False:
|
if obj.InverseAngle is False:
|
||||||
(clnBase, clnStock, angle) = self.applyInverseAngle(obj, clnBase, clnStock, axis, angle)
|
if obj.AttemptInverseAngle is True:
|
||||||
else:
|
PathLog.debug("Applying the inverse angle.")
|
||||||
PathLog.info(translate("Path", "Consider toggling the InverseAngle property and recomputing the operation."))
|
(clnBase, clnStock, angle) = self.applyInverseAngle(obj, clnBase, clnStock, axis, angle)
|
||||||
|
else:
|
||||||
|
PathLog.warning(translate("Path", "Consider toggling the InverseAngle property and recomputing the operation."))
|
||||||
else:
|
else:
|
||||||
PathLog.debug("Face appears to be oriented correctly.")
|
PathLog.debug("Face appears to be oriented correctly.")
|
||||||
|
|
||||||
if angle < -180:
|
if angle < -180.0:
|
||||||
angle += 360
|
angle += 360.0
|
||||||
|
|
||||||
tup = clnBase, [sub], angle, axis, clnStock
|
tup = clnBase, [sub], angle, axis, clnStock
|
||||||
else:
|
else:
|
||||||
if self.warnDisabledAxis(obj, axis) is False:
|
if self.warnDisabledAxis(obj, axis) is False:
|
||||||
@@ -487,7 +519,6 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
|
|||||||
# Eif
|
# Eif
|
||||||
allTuples.append(tup)
|
allTuples.append(tup)
|
||||||
baseSubsTuples.append(tup)
|
baseSubsTuples.append(tup)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
ignoreSub = base.Name + '.' + sub
|
ignoreSub = base.Name + '.' + sub
|
||||||
PathLog.error(translate('Path', "Selected feature is not a Face. Ignoring: {}".format(ignoreSub)))
|
PathLog.error(translate('Path', "Selected feature is not a Face. Ignoring: {}".format(ignoreSub)))
|
||||||
@@ -506,14 +537,13 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
|
|||||||
if clasifySub(self, subBase, sub) is False:
|
if clasifySub(self, subBase, sub) is False:
|
||||||
PathLog.error(translate('PathPocket', 'Pocket does not support shape %s.%s') % (subBase.Label, sub))
|
PathLog.error(translate('PathPocket', 'Pocket does not support shape %s.%s') % (subBase.Label, sub))
|
||||||
if obj.EnableRotation != 'Off':
|
if obj.EnableRotation != 'Off':
|
||||||
PathLog.info(translate('PathPocket', 'Face might not be within rotation accessibility limits.'))
|
PathLog.warning(translate('PathPocket', 'Face might not be within rotation accessibility limits.'))
|
||||||
|
|
||||||
# Determine final depth as highest value of bottom boundbox of vertical face,
|
# Determine final depth as highest value of bottom boundbox of vertical face,
|
||||||
# in case of uneven faces on bottom
|
# in case of uneven faces on bottom
|
||||||
if len(self.vert) > 0:
|
if len(self.vert) > 0:
|
||||||
vFinDep = self.vert[0].BoundBox.ZMin
|
vFinDep = self.vert[0].BoundBox.ZMin
|
||||||
for vFace in self.vert:
|
for vFace in self.vert:
|
||||||
#print("vFinDep: {}".format(vFinDep))
|
|
||||||
if vFace.BoundBox.ZMin > vFinDep:
|
if vFace.BoundBox.ZMin > vFinDep:
|
||||||
vFinDep = vFace.BoundBox.ZMin
|
vFinDep = vFace.BoundBox.ZMin
|
||||||
# Determine if vertical faces for a loop: Extract planar loop wire as new horizontal face.
|
# Determine if vertical faces for a loop: Extract planar loop wire as new horizontal face.
|
||||||
@@ -546,37 +576,54 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
|
|||||||
self.exts.append(face)
|
self.exts.append(face)
|
||||||
|
|
||||||
# move all horizontal faces to FinalDepth
|
# move all horizontal faces to FinalDepth
|
||||||
for f in self.horiz:
|
# for f in self.horiz:
|
||||||
if obj.EnableRotation == 'Off':
|
# f.translate(FreeCAD.Vector(0, 0, obj.FinalDepth.Value - f.BoundBox.ZMin))
|
||||||
finDep = obj.FinalDepth.Value # max(obj.FinalDepth.Value, f.BoundBox.ZMin)
|
|
||||||
print("NO_ROT: ObjDep: {}, FinDep: {}, BBmin: {}".format(obj.FinalDepth.Value, finDep, f.BoundBox.ZMin))
|
|
||||||
f.translate(FreeCAD.Vector(0, 0, finDep-f.BoundBox.ZMin))
|
|
||||||
else:
|
|
||||||
finDep = f.BoundBox.ZMin
|
|
||||||
print("ROT: ObjDep: {}, FinDep: {}, BBmin: {}".format(obj.FinalDepth.Value, finDep, f.BoundBox.ZMin))
|
|
||||||
f.translate(FreeCAD.Vector(0, 0, 0))
|
|
||||||
obj.FinalDepth.Value = finDep
|
|
||||||
|
|
||||||
# check all faces and see if they are touching/overlapping and combine those into a compound
|
# check all faces and see if they are touching/overlapping and combine those into a compound
|
||||||
self.horizontal = [] # pylint: disable=attribute-defined-outside-init
|
self.horizontal = [] # pylint: disable=attribute-defined-outside-init
|
||||||
for shape in PathGeom.combineConnectedShapes(self.horiz):
|
for shape in PathGeom.combineConnectedShapes(self.horiz):
|
||||||
shape.sewShape()
|
shape.sewShape()
|
||||||
# shape.tessellate(0.1)
|
# shape.tessellate(0.1)
|
||||||
|
shpZMin = shape.BoundBox.ZMin
|
||||||
|
PathLog.debug('PathGeom.combineConnectedShapes shape.BoundBox.ZMin: {}'.format(shape.BoundBox.ZMin))
|
||||||
if obj.UseOutline:
|
if obj.UseOutline:
|
||||||
wire = TechDraw.findShapeOutline(shape, 1, FreeCAD.Vector(0, 0, 1))
|
wire = TechDraw.findShapeOutline(shape, 1, FreeCAD.Vector(0, 0, 1))
|
||||||
wire.translate(FreeCAD.Vector(0, 0, obj.FinalDepth.Value - wire.BoundBox.ZMin))
|
wFace = Part.Face(wire)
|
||||||
self.horizontal.append(Part.Face(wire))
|
if wFace.BoundBox.ZMin != shpZMin:
|
||||||
print("2: FinDep: {}, WireBB: {}, Sub: {}".format(obj.FinalDepth.Value, wire.BoundBox.ZMin, obj.FinalDepth.Value - wire.BoundBox.ZMin))
|
wFace.translate(FreeCAD.Vector(0, 0, shpZMin - wFace.BoundBox.ZMin))
|
||||||
|
self.horizontal.append(wFace)
|
||||||
|
PathLog.debug('PathGeom.combineConnectedShapes shape.BoundBox.ZMin: {}'.format(wFace.BoundBox.ZMin))
|
||||||
else:
|
else:
|
||||||
self.horizontal.append(shape)
|
self.horizontal.append(shape)
|
||||||
|
|
||||||
# extrude all faces up to StartDepth and those are the removal shapes
|
# extrude all faces up to StartDepth and those are the removal shapes
|
||||||
sD = obj.StartDepth.Value
|
sD = obj.StartDepth.Value
|
||||||
fD = obj.FinalDepth.Value
|
fD = obj.FinalDepth.Value
|
||||||
extent = FreeCAD.Vector(0, 0, sD - fD)
|
clrnc = 0.5
|
||||||
for face in self.horizontal:
|
for face in self.horizontal:
|
||||||
self.removalshapes.append((face.removeSplitter().extrude(extent), False, 'pathPocketShape', angle, axis, sD, fD))
|
afD = fD
|
||||||
PathLog.debug("Extent depths are str: {}, and fin: {}".format(sD, fD))
|
useAngle = angle
|
||||||
|
shpZMin = face.BoundBox.ZMin
|
||||||
|
PathLog.debug('self.horizontal shpZMin: {}'.format(shpZMin))
|
||||||
|
if self.isFaceUp(subBase, face) is False:
|
||||||
|
useAngle += 180.0
|
||||||
|
invZ = (-2 * shpZMin) - clrnc
|
||||||
|
face.translate(FreeCAD.Vector(0.0, 0.0, invZ))
|
||||||
|
shpZMin = -1 * shpZMin
|
||||||
|
else:
|
||||||
|
face.translate(FreeCAD.Vector(0.0, 0.0, -1 * clrnc))
|
||||||
|
if obj.LimitDepthToFace is True and obj.EnableRotation != 'Off':
|
||||||
|
if shpZMin > obj.FinalDepth.Value:
|
||||||
|
afD = shpZMin
|
||||||
|
if sD <= afD:
|
||||||
|
PathLog.error('Start Depth is lower than face depth.')
|
||||||
|
sD = afD + 1.0
|
||||||
|
else:
|
||||||
|
face.translate(FreeCAD.Vector(0, 0, obj.FinalDepth.Value - shpZMin))
|
||||||
|
extent = FreeCAD.Vector(0, 0, sD - afD + clrnc)
|
||||||
|
extShp = face.removeSplitter().extrude(extent)
|
||||||
|
self.removalshapes.append((extShp, False, 'pathPocketShape', useAngle, axis, sD, afD))
|
||||||
|
PathLog.debug("Extent values are strDep: {}, finDep: {}, extrd: {}".format(sD, afD, extent))
|
||||||
# Efor face
|
# Efor face
|
||||||
# Efor
|
# Efor
|
||||||
|
|
||||||
@@ -612,8 +659,8 @@ class ObjectPocket(PathPocketBase.ObjectPocket):
|
|||||||
obj.UseOutline = False
|
obj.UseOutline = False
|
||||||
obj.ReverseDirection = False
|
obj.ReverseDirection = False
|
||||||
obj.InverseAngle = False
|
obj.InverseAngle = False
|
||||||
obj.B_AxisErrorOverride = False
|
|
||||||
obj.AttemptInverseAngle = True
|
obj.AttemptInverseAngle = True
|
||||||
|
obj.LimitDepthToFace = True
|
||||||
obj.setExpression('ExtensionLengthDefault', 'OpToolDiameter / 2')
|
obj.setExpression('ExtensionLengthDefault', 'OpToolDiameter / 2')
|
||||||
|
|
||||||
def createExtension(self, obj, extObj, extFeature, extSub):
|
def createExtension(self, obj, extObj, extFeature, extSub):
|
||||||
@@ -800,8 +847,8 @@ def SetupProperties():
|
|||||||
setup.append('ExtensionCorners')
|
setup.append('ExtensionCorners')
|
||||||
setup.append("ReverseDirection")
|
setup.append("ReverseDirection")
|
||||||
setup.append("InverseAngle")
|
setup.append("InverseAngle")
|
||||||
setup.append("B_AxisErrorOverride")
|
|
||||||
setup.append("AttemptInverseAngle")
|
setup.append("AttemptInverseAngle")
|
||||||
|
setup.append("LimitDepthToFace")
|
||||||
return setup
|
return setup
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ __url__ = "http://www.freecadweb.org"
|
|||||||
__doc__ = "Base class and implementation for Path profile operations."
|
__doc__ = "Base class and implementation for Path profile operations."
|
||||||
|
|
||||||
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
|
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
|
||||||
#PathLog.trackModule(PathLog.thisModule())
|
# PathLog.trackModule(PathLog.thisModule())
|
||||||
|
|
||||||
|
|
||||||
# Qt translation handling
|
# Qt translation handling
|
||||||
def translate(context, text, disambig=None):
|
def translate(context, text, disambig=None):
|
||||||
@@ -75,9 +76,22 @@ class ObjectProfile(PathAreaOp.ObjectOp):
|
|||||||
else:
|
else:
|
||||||
obj.setEditorMode('MiterLimit', 2)
|
obj.setEditorMode('MiterLimit', 2)
|
||||||
|
|
||||||
|
self.extraOpOnChanged(obj, prop)
|
||||||
|
|
||||||
|
def extraOpOnChanged(self, obj, prop):
|
||||||
|
'''otherOpOnChanged(obj, porp) ... overwrite to process onChange() events.
|
||||||
|
Can safely be overwritten by subclasses.'''
|
||||||
|
pass # pylint: disable=unnecessary-pass
|
||||||
|
|
||||||
|
def setOpEditorProperties(self, obj):
|
||||||
|
'''setOpEditorProperties(obj, porp) ... overwrite to process operation specific changes to properties.
|
||||||
|
Can safely be overwritten by subclasses.'''
|
||||||
|
pass # pylint: disable=unnecessary-pass
|
||||||
|
|
||||||
def areaOpOnDocumentRestored(self, obj):
|
def areaOpOnDocumentRestored(self, obj):
|
||||||
for prop in ['UseComp', 'JoinType']:
|
for prop in ['UseComp', 'JoinType']:
|
||||||
self.areaOpOnChanged(obj, prop)
|
self.areaOpOnChanged(obj, prop)
|
||||||
|
self.setOpEditorProperties(obj)
|
||||||
|
|
||||||
def areaOpAreaParams(self, obj, isHole):
|
def areaOpAreaParams(self, obj, isHole):
|
||||||
'''areaOpAreaParams(obj, isHole) ... returns dictionary with area parameters.
|
'''areaOpAreaParams(obj, isHole) ... returns dictionary with area parameters.
|
||||||
@@ -141,6 +155,7 @@ class ObjectProfile(PathAreaOp.ObjectOp):
|
|||||||
obj.JoinType = "Round"
|
obj.JoinType = "Round"
|
||||||
obj.MiterLimit = 0.1
|
obj.MiterLimit = 0.1
|
||||||
|
|
||||||
|
|
||||||
def SetupProperties():
|
def SetupProperties():
|
||||||
setup = []
|
setup = []
|
||||||
setup.append('Side')
|
setup.append('Side')
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
# ***************************************************************************
|
# ***************************************************************************
|
||||||
# * *
|
# * *
|
||||||
# * Copyright (c) 2014 Yorik van Havre <yorik@uncreated.net> *
|
# * Copyright (c) 2014 Yorik van Havre <yorik@uncreated.net> *
|
||||||
# * Copyright (c) 2019 russ4262 (Russell Johnson, russ4262@gmail.com) *
|
|
||||||
# * Copyright (c) 2020 Schildkroet *
|
# * Copyright (c) 2020 Schildkroet *
|
||||||
# * *
|
# * *
|
||||||
# * This program is free software; you can redistribute it and/or modify *
|
# * This program is free software; you can redistribute it and/or modify *
|
||||||
@@ -37,7 +36,7 @@ import numpy
|
|||||||
from PySide import QtCore
|
from PySide import QtCore
|
||||||
|
|
||||||
__title__ = "Path Profile Faces Operation"
|
__title__ = "Path Profile Faces Operation"
|
||||||
__author__ = "sliptonic (Brad Collette), russ4262, Schildkroet"
|
__author__ = "sliptonic (Brad Collette), Schildkroet"
|
||||||
__url__ = "http://www.freecadweb.org"
|
__url__ = "http://www.freecadweb.org"
|
||||||
__doc__ = "Path Profile operation based on faces."
|
__doc__ = "Path Profile operation based on faces."
|
||||||
|
|
||||||
@@ -69,20 +68,41 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
|
|||||||
obj.addProperty("App::PropertyBool", "processPerimeter", "Profile", QtCore.QT_TRANSLATE_NOOP("App::Property", "Profile the outline"))
|
obj.addProperty("App::PropertyBool", "processPerimeter", "Profile", QtCore.QT_TRANSLATE_NOOP("App::Property", "Profile the outline"))
|
||||||
obj.addProperty("App::PropertyBool", "processCircles", "Profile", QtCore.QT_TRANSLATE_NOOP("App::Property", "Profile round holes"))
|
obj.addProperty("App::PropertyBool", "processCircles", "Profile", QtCore.QT_TRANSLATE_NOOP("App::Property", "Profile round holes"))
|
||||||
|
|
||||||
if not hasattr(obj, 'ReverseDirection'):
|
|
||||||
obj.addProperty('App::PropertyBool', 'ReverseDirection', 'Rotation', QtCore.QT_TRANSLATE_NOOP('App::Property', 'Reverse direction of pocket operation.'))
|
|
||||||
if not hasattr(obj, 'InverseAngle'):
|
|
||||||
obj.addProperty('App::PropertyBool', 'InverseAngle', 'Rotation', QtCore.QT_TRANSLATE_NOOP('App::Property', 'Inverse the angle. Example: -22.5 -> 22.5 degrees.'))
|
|
||||||
if not hasattr(obj, 'B_AxisErrorOverride'):
|
|
||||||
obj.addProperty('App::PropertyBool', 'B_AxisErrorOverride', 'Rotation', QtCore.QT_TRANSLATE_NOOP('App::Property', 'Match B rotations to model (error in FreeCAD rendering).'))
|
|
||||||
if not hasattr(obj, 'AttemptInverseAngle'):
|
|
||||||
obj.addProperty('App::PropertyBool', 'AttemptInverseAngle', 'Rotation', QtCore.QT_TRANSLATE_NOOP('App::Property', 'Attempt the inverse angle for face access if original rotation fails.'))
|
|
||||||
|
|
||||||
if not hasattr(obj, 'HandleMultipleFeatures'):
|
if not hasattr(obj, 'HandleMultipleFeatures'):
|
||||||
obj.addProperty('App::PropertyEnumeration', 'HandleMultipleFeatures', 'Profile', QtCore.QT_TRANSLATE_NOOP('PathPocket', 'Choose how to process multiple Base Geometry features.'))
|
obj.addProperty('App::PropertyEnumeration', 'HandleMultipleFeatures', 'Profile', QtCore.QT_TRANSLATE_NOOP('PathPocket', 'Choose how to process multiple Base Geometry features.'))
|
||||||
obj.HandleMultipleFeatures = ['Collectively', 'Individually']
|
obj.HandleMultipleFeatures = ['Collectively', 'Individually']
|
||||||
|
|
||||||
|
self.initRotationOp(obj)
|
||||||
self.baseObject().initAreaOp(obj)
|
self.baseObject().initAreaOp(obj)
|
||||||
|
self.setOpEditorProperties(obj)
|
||||||
|
|
||||||
|
def initRotationOp(self, obj):
|
||||||
|
'''initRotationOp(obj) ... setup receiver for rotation'''
|
||||||
|
if not hasattr(obj, 'ReverseDirection'):
|
||||||
|
obj.addProperty('App::PropertyBool', 'ReverseDirection', 'Rotation', QtCore.QT_TRANSLATE_NOOP('App::Property', 'Reverse direction of pocket operation.'))
|
||||||
|
if not hasattr(obj, 'InverseAngle'):
|
||||||
|
obj.addProperty('App::PropertyBool', 'InverseAngle', 'Rotation', QtCore.QT_TRANSLATE_NOOP('App::Property', 'Inverse the angle. Example: -22.5 -> 22.5 degrees.'))
|
||||||
|
if not hasattr(obj, 'AttemptInverseAngle'):
|
||||||
|
obj.addProperty('App::PropertyBool', 'AttemptInverseAngle', 'Rotation', QtCore.QT_TRANSLATE_NOOP('App::Property', 'Attempt the inverse angle for face access if original rotation fails.'))
|
||||||
|
if not hasattr(obj, 'LimitDepthToFace'):
|
||||||
|
obj.addProperty('App::PropertyBool', 'LimitDepthToFace', 'Rotation', QtCore.QT_TRANSLATE_NOOP('App::Property', 'Enforce the Z-depth of the selected face as the lowest value for final depth. Higher user values will be observed.'))
|
||||||
|
|
||||||
|
def extraOpOnChanged(self, obj, prop):
|
||||||
|
'''extraOpOnChanged(obj, porp) ... process operation specific changes to properties.'''
|
||||||
|
if prop == 'EnableRotation':
|
||||||
|
self.setOpEditorProperties(obj)
|
||||||
|
|
||||||
|
def setOpEditorProperties(self, obj):
|
||||||
|
if obj.EnableRotation == 'Off':
|
||||||
|
obj.setEditorMode('ReverseDirection', 2)
|
||||||
|
obj.setEditorMode('InverseAngle', 2)
|
||||||
|
obj.setEditorMode('AttemptInverseAngle', 2)
|
||||||
|
obj.setEditorMode('LimitDepthToFace', 2)
|
||||||
|
else:
|
||||||
|
obj.setEditorMode('ReverseDirection', 0)
|
||||||
|
obj.setEditorMode('InverseAngle', 0)
|
||||||
|
obj.setEditorMode('AttemptInverseAngle', 0)
|
||||||
|
obj.setEditorMode('LimitDepthToFace', 0)
|
||||||
|
|
||||||
def areaOpShapes(self, obj):
|
def areaOpShapes(self, obj):
|
||||||
'''areaOpShapes(obj) ... returns envelope for all base shapes or wires for Arch.Panels.'''
|
'''areaOpShapes(obj) ... returns envelope for all base shapes or wires for Arch.Panels.'''
|
||||||
@@ -179,25 +199,14 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
|
|||||||
PathLog.error(msg)
|
PathLog.error(msg)
|
||||||
FreeCAD.Console.PrintWarning(msg)
|
FreeCAD.Console.PrintWarning(msg)
|
||||||
|
|
||||||
# Raise FinalDepth to lowest face in list on Inside profile ops
|
|
||||||
finDep = obj.FinalDepth.Value
|
|
||||||
if obj.EnableRotation != 'Off':
|
|
||||||
finDep = faceDepths[0]
|
|
||||||
|
|
||||||
|
# Set initial Start and Final Depths and recalculate depthparams
|
||||||
|
finDep = obj.FinalDepth.Value
|
||||||
strDep = obj.StartDepth.Value
|
strDep = obj.StartDepth.Value
|
||||||
if strDep > stock.Shape.BoundBox.ZMax:
|
if strDep > stock.Shape.BoundBox.ZMax:
|
||||||
strDep = stock.Shape.BoundBox.ZMax
|
strDep = stock.Shape.BoundBox.ZMax
|
||||||
startDepths.append(strDep)
|
startDepths.append(strDep)
|
||||||
|
self.depthparams = self._customDepthParams(obj, strDep, finDep)
|
||||||
# Recalculate depthparams
|
|
||||||
self.depthparams = PathUtils.depth_params( # pylint: disable=attribute-defined-outside-init
|
|
||||||
clearance_height=obj.ClearanceHeight.Value,
|
|
||||||
safe_height=obj.SafeHeight.Value,
|
|
||||||
start_depth=strDep, # obj.StartDepth.Value,
|
|
||||||
step_down=obj.StepDown.Value,
|
|
||||||
z_finish_step=finish_step,
|
|
||||||
final_depth=finDep, # obj.FinalDepth.Value,
|
|
||||||
user_depths=None)
|
|
||||||
|
|
||||||
for shape, wire in holes:
|
for shape, wire in holes:
|
||||||
f = Part.makeFace(wire, 'Part::FaceMakerSimple')
|
f = Part.makeFace(wire, 'Part::FaceMakerSimple')
|
||||||
@@ -213,8 +222,13 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
|
|||||||
|
|
||||||
if obj.processPerimeter:
|
if obj.processPerimeter:
|
||||||
if obj.HandleMultipleFeatures == 'Collectively':
|
if obj.HandleMultipleFeatures == 'Collectively':
|
||||||
|
custDepthparams = self.depthparams
|
||||||
|
if obj.LimitDepthToFace is True and obj.EnableRotation != 'Off':
|
||||||
|
if profileshape.BoundBox.ZMin > obj.FinalDepth.Value:
|
||||||
|
finDep = profileshape.BoundBox.ZMin
|
||||||
|
custDepthparams = self._customDepthParams(obj, strDep, finDep - 0.5) # only an envelope
|
||||||
try:
|
try:
|
||||||
env = PathUtils.getEnvelope(base.Shape, subshape=profileshape, depthparams=self.depthparams)
|
env = PathUtils.getEnvelope(base.Shape, subshape=profileshape, depthparams=custDepthparams)
|
||||||
except Exception: # pylint: disable=broad-except
|
except Exception: # pylint: disable=broad-except
|
||||||
# PathUtils.getEnvelope() failed to return an object.
|
# PathUtils.getEnvelope() failed to return an object.
|
||||||
PathLog.error(translate('Path', 'Unable to create path for face(s).'))
|
PathLog.error(translate('Path', 'Unable to create path for face(s).'))
|
||||||
@@ -230,14 +244,7 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
|
|||||||
if finalDep < shape.BoundBox.ZMin:
|
if finalDep < shape.BoundBox.ZMin:
|
||||||
# Recalculate depthparams
|
# Recalculate depthparams
|
||||||
finalDep = shape.BoundBox.ZMin
|
finalDep = shape.BoundBox.ZMin
|
||||||
custDepthparams = PathUtils.depth_params(
|
custDepthparams = self._customDepthParams(obj, strDep, finalDep - 0.5)
|
||||||
clearance_height=obj.ClearanceHeight.Value,
|
|
||||||
safe_height=obj.SafeHeight.Value,
|
|
||||||
start_depth=strDep, # obj.StartDepth.Value,
|
|
||||||
step_down=obj.StepDown.Value,
|
|
||||||
z_finish_step=finish_step,
|
|
||||||
final_depth=finalDep, # obj.FinalDepth.Value,
|
|
||||||
user_depths=None)
|
|
||||||
env = PathUtils.getEnvelope(base.Shape, subshape=profShape, depthparams=custDepthparams)
|
env = PathUtils.getEnvelope(base.Shape, subshape=profShape, depthparams=custDepthparams)
|
||||||
tup = env, False, 'pathProfileFaces', angle, axis, strDep, finalDep
|
tup = env, False, 'pathProfileFaces', angle, axis, strDep, finalDep
|
||||||
shapes.append(tup)
|
shapes.append(tup)
|
||||||
@@ -284,7 +291,7 @@ class ObjectProfile(PathProfileBase.ObjectProfile):
|
|||||||
obj.ReverseDirection = False
|
obj.ReverseDirection = False
|
||||||
obj.InverseAngle = False
|
obj.InverseAngle = False
|
||||||
obj.AttemptInverseAngle = True
|
obj.AttemptInverseAngle = True
|
||||||
obj.B_AxisErrorOverride = False
|
obj.LimitDepthToFace = True
|
||||||
obj.HandleMultipleFeatures = 'Collectively'
|
obj.HandleMultipleFeatures = 'Collectively'
|
||||||
|
|
||||||
|
|
||||||
@@ -295,7 +302,6 @@ def SetupProperties():
|
|||||||
setup.append("processCircles")
|
setup.append("processCircles")
|
||||||
setup.append("ReverseDirection")
|
setup.append("ReverseDirection")
|
||||||
setup.append("InverseAngle")
|
setup.append("InverseAngle")
|
||||||
setup.append("B_AxisErrorOverride")
|
|
||||||
setup.append("AttemptInverseAngle")
|
setup.append("AttemptInverseAngle")
|
||||||
setup.append("HandleMultipleFeatures")
|
setup.append("HandleMultipleFeatures")
|
||||||
return setup
|
return setup
|
||||||
|
|||||||
Reference in New Issue
Block a user