Path: Initialize OCL_Tool class and implement in OCL-based operations
The purpose of this class is to properly translate both, Legacy and ToolBit, tools into OCL tool types where possible. message fix
This commit is contained in:
@@ -494,14 +494,29 @@ class ObjectSurface(PathOp.ObjectOp):
|
||||
else:
|
||||
self.CutClimb = True
|
||||
|
||||
# Instantiate additional class operation variables
|
||||
self.resetOpVariables()
|
||||
|
||||
# Setup cutter for OCL and cutout value for operation - based on tool controller properties
|
||||
oclTool = PathSurfaceSupport.OCL_Tool(ocl, obj)
|
||||
self.cutter = oclTool.getOclTool()
|
||||
if not self.cutter:
|
||||
PathLog.error(translate('PathSurface', "Canceling 3D Surface operation. Error creating OCL cutter."))
|
||||
return
|
||||
self.toolDiam = self.cutter.getDiameter() # oclTool.diameter
|
||||
self.radius = self.toolDiam / 2.0
|
||||
self.useTiltCutter = oclTool.useTiltCutter()
|
||||
self.cutOut = (self.toolDiam * (float(obj.StepOver) / 100.0))
|
||||
self.gaps = [self.toolDiam, self.toolDiam, self.toolDiam]
|
||||
|
||||
# Begin GCode for operation with basic information
|
||||
# ... and move cutter to clearance height and startpoint
|
||||
output = ''
|
||||
if obj.Comment != '':
|
||||
self.commandlist.append(Path.Command('N ({})'.format(str(obj.Comment)), {}))
|
||||
self.commandlist.append(Path.Command('N ({})'.format(obj.Label), {}))
|
||||
self.commandlist.append(Path.Command('N (Tool type: {})'.format(str(obj.ToolController.Tool.ToolType)), {}))
|
||||
self.commandlist.append(Path.Command('N (Compensated Tool Path. Diameter: {})'.format(str(obj.ToolController.Tool.Diameter)), {}))
|
||||
self.commandlist.append(Path.Command('N (Tool type: {})'.format(oclTool.toolType), {}))
|
||||
self.commandlist.append(Path.Command('N (Compensated Tool Path. Diameter: {})'.format(oclTool.diameter), {}))
|
||||
self.commandlist.append(Path.Command('N (Sample interval: {})'.format(str(obj.SampleInterval.Value)), {}))
|
||||
self.commandlist.append(Path.Command('N (Step over %: {})'.format(str(obj.StepOver)), {}))
|
||||
self.commandlist.append(Path.Command('N ({})'.format(output), {}))
|
||||
@@ -509,9 +524,6 @@ class ObjectSurface(PathOp.ObjectOp):
|
||||
if obj.UseStartPoint is True:
|
||||
self.commandlist.append(Path.Command('G0', {'X': obj.StartPoint.x, 'Y': obj.StartPoint.y, 'F': self.horizRapid}))
|
||||
|
||||
# Instantiate additional class operation variables
|
||||
self.resetOpVariables()
|
||||
|
||||
# Impose property limits
|
||||
self.opApplyPropertyLimits(obj)
|
||||
|
||||
@@ -532,16 +544,6 @@ class ObjectSurface(PathOp.ObjectOp):
|
||||
# Add temp object to temp group folder with following code:
|
||||
# ... self.tempGroup.addObject(OBJ)
|
||||
|
||||
# Setup cutter for OCL and cutout value for operation - based on tool controller properties
|
||||
self.cutter = self.setOclCutter(obj)
|
||||
if self.cutter is False:
|
||||
PathLog.error(translate('PathSurface', "Canceling 3D Surface operation. Error creating OCL cutter."))
|
||||
return
|
||||
self.toolDiam = self.cutter.getDiameter()
|
||||
self.radius = self.toolDiam / 2.0
|
||||
self.cutOut = (self.toolDiam * (float(obj.StepOver) / 100.0))
|
||||
self.gaps = [self.toolDiam, self.toolDiam, self.toolDiam]
|
||||
|
||||
# Get height offset values for later use
|
||||
self.SafeHeightOffset = JOB.SetupSheet.SafeHeightOffset.Value
|
||||
self.ClearHeightOffset = JOB.SetupSheet.ClearanceHeightOffset.Value
|
||||
@@ -610,6 +612,9 @@ class ObjectSurface(PathOp.ObjectOp):
|
||||
|
||||
# Save gcode produced
|
||||
self.commandlist.extend(CMDS)
|
||||
else:
|
||||
PathLog.error('Failed to pre-process model and/or selected face(s).')
|
||||
|
||||
|
||||
# ###### CLOSING COMMANDS FOR OPERATION ######
|
||||
|
||||
@@ -2006,7 +2011,6 @@ class ObjectSurface(PathOp.ObjectOp):
|
||||
self.stl = None
|
||||
self.fullSTL = None
|
||||
self.cutOut = 0.0
|
||||
self.radius = 0.0
|
||||
self.useTiltCutter = False
|
||||
return True
|
||||
|
||||
@@ -2123,7 +2127,7 @@ class ObjectSurface(PathOp.ObjectOp):
|
||||
do.Shape = objShape
|
||||
do.purgeTouched()
|
||||
self.tempGroup.addObject(do)
|
||||
|
||||
# Eclass
|
||||
|
||||
def SetupProperties():
|
||||
''' SetupProperties() ... Return list of properties required for operation.'''
|
||||
|
||||
@@ -584,17 +584,21 @@ class ProcessSelectedFaces:
|
||||
def _isReady(self, module):
|
||||
'''_isReady(module)... Internal method.
|
||||
Checks if required attributes are available for processing obj.Base (the Base Geometry).'''
|
||||
PathLog.debug('ProcessSelectedFaces _isReady({})'.format(module))
|
||||
if hasattr(self, module):
|
||||
self.module = module
|
||||
modMethod = getattr(self, module) # gets the attribute only
|
||||
modMethod() # executes as method
|
||||
else:
|
||||
PathLog.error('PSF._isReady() no "{}" method.'.format(module))
|
||||
return False
|
||||
|
||||
if not self.radius:
|
||||
PathLog.error('PSF._isReady() no cutter radius available.')
|
||||
return False
|
||||
|
||||
if not self.depthParams:
|
||||
PathLog.error('PSF._isReady() no depth params available.')
|
||||
return False
|
||||
|
||||
return True
|
||||
@@ -932,7 +936,6 @@ class ProcessSelectedFaces:
|
||||
offset += self.radius + tolrnc
|
||||
|
||||
return offset
|
||||
|
||||
# Eclass
|
||||
|
||||
|
||||
@@ -2304,6 +2307,333 @@ class FindUnifiedRegions:
|
||||
return False
|
||||
# Eclass
|
||||
|
||||
class OCL_Tool():
|
||||
"""The OCL_Tool class is designed to translate a FreeCAD standard ToolBit shape,
|
||||
or Legacy tool type, in the active Tool Controller, into an OCL tool type."""
|
||||
|
||||
def __init__(self, ocl, obj, safe=False):
|
||||
self.ocl = ocl
|
||||
self.obj = obj
|
||||
self.tool = None
|
||||
self.tiltCutter = False
|
||||
self.safe = safe
|
||||
self.oclTool = None
|
||||
self.toolType = None
|
||||
self.toolMode = None
|
||||
self.toolMethod = None
|
||||
|
||||
self.diameter = -1.0
|
||||
self.cornerRadius = -1.0
|
||||
self.flatRadius = -1.0
|
||||
self.cutEdgeHeight = -1.0
|
||||
self.cutEdgeAngle = -1.0
|
||||
# Default to zero. ToolBit likely is without.
|
||||
self.lengthOffset = 0.0
|
||||
|
||||
if hasattr(obj, 'ToolController'):
|
||||
if hasattr(obj.ToolController, 'Tool'):
|
||||
self.tool = obj.ToolController.Tool
|
||||
if hasattr(self.tool, 'ShapeName'):
|
||||
self.toolType = self.tool.ShapeName # Indicates ToolBit tool
|
||||
self.toolMode = 'ToolBit'
|
||||
elif hasattr(self.tool, 'ToolType'):
|
||||
self.toolType = self.tool.ToolType # Indicates Legacy tool
|
||||
self.toolMode = 'Legacy'
|
||||
if self.toolType:
|
||||
PathLog.debug('OCL_Tool tool mode, type: {}, {}'.format(self.toolMode, self.toolType))
|
||||
|
||||
'''
|
||||
#### FreeCAD Legacy tool shape properties per tool type
|
||||
shape = EndMill
|
||||
Diameter
|
||||
CuttingEdgeHeight
|
||||
LengthOffset
|
||||
|
||||
shape = Drill
|
||||
Diameter
|
||||
CuttingEdgeAngle # TipAngle from above, center shaft. 180 = flat tip (endmill)
|
||||
CuttingEdgeHeight
|
||||
LengthOffset
|
||||
|
||||
shape = CenterDrill
|
||||
Diameter
|
||||
FlatRadius
|
||||
CornerRadius
|
||||
CuttingEdgeAngle # TipAngle from above, center shaft. 180 = flat tip (endmill)
|
||||
CuttingEdgeHeight
|
||||
LengthOffset
|
||||
|
||||
shape = CounterSink
|
||||
Diameter
|
||||
FlatRadius
|
||||
CornerRadius
|
||||
CuttingEdgeAngle # TipAngle from above, center shaft. 180 = flat tip (endmill)
|
||||
CuttingEdgeHeight
|
||||
LengthOffset
|
||||
|
||||
shape = CounterBore
|
||||
Diameter
|
||||
FlatRadius
|
||||
CornerRadius
|
||||
CuttingEdgeAngle # TipAngle from above, center shaft. 180 = flat tip (endmill)
|
||||
CuttingEdgeHeight
|
||||
LengthOffset
|
||||
|
||||
shape = FlyCutter
|
||||
Diameter
|
||||
FlatRadius
|
||||
CornerRadius
|
||||
CuttingEdgeAngle # TipAngle from above, center shaft. 180 = flat tip (endmill)
|
||||
CuttingEdgeHeight
|
||||
LengthOffset
|
||||
|
||||
shape = Reamer
|
||||
Diameter
|
||||
FlatRadius
|
||||
CornerRadius
|
||||
CuttingEdgeAngle # TipAngle from above, center shaft. 180 = flat tip (endmill)
|
||||
CuttingEdgeHeight
|
||||
LengthOffset
|
||||
|
||||
shape = Tap
|
||||
Diameter
|
||||
FlatRadius
|
||||
CornerRadius
|
||||
CuttingEdgeAngle # TipAngle from above, center shaft. 180 = flat tip (endmill)
|
||||
CuttingEdgeHeight
|
||||
LengthOffset
|
||||
|
||||
shape = SlotCutter
|
||||
Diameter
|
||||
FlatRadius
|
||||
CornerRadius
|
||||
CuttingEdgeAngle # TipAngle from above, center shaft. 180 = flat tip (endmill)
|
||||
CuttingEdgeHeight
|
||||
LengthOffset
|
||||
|
||||
shape = BallEndMill
|
||||
Diameter
|
||||
FlatRadius
|
||||
CornerRadius
|
||||
CuttingEdgeAngle # TipAngle from above, center shaft. 180 = flat tip (endmill)
|
||||
CuttingEdgeHeight
|
||||
LengthOffset
|
||||
|
||||
shape = ChamferMill
|
||||
Diameter
|
||||
FlatRadius
|
||||
CornerRadius
|
||||
CuttingEdgeAngle # TipAngle from above, center shaft. 180 = flat tip (endmill)
|
||||
CuttingEdgeHeight
|
||||
LengthOffset
|
||||
|
||||
shape = CornerRound
|
||||
Diameter
|
||||
FlatRadius
|
||||
CornerRadius
|
||||
CuttingEdgeAngle # TipAngle from above, center shaft. 180 = flat tip (endmill)
|
||||
CuttingEdgeHeight
|
||||
LengthOffset
|
||||
|
||||
shape = Engraver
|
||||
Diameter
|
||||
CuttingEdgeAngle # TipAngle from above, center shaft. 180 = flat tip (endmill)
|
||||
CuttingEdgeHeight
|
||||
LengthOffset
|
||||
|
||||
|
||||
#### FreeCAD packaged ToolBit named constaints per shape files
|
||||
shape = endmill
|
||||
Diameter; Endmill diameter
|
||||
Length; Overall length of the endmill
|
||||
ShankDiameter; diameter of the shank
|
||||
CuttingEdgeHeight
|
||||
|
||||
shape = ballend
|
||||
Diameter; Endmill diameter
|
||||
Length; Overall length of the endmill
|
||||
ShankDiameter; diameter of the shank
|
||||
CuttingEdgeHeight
|
||||
|
||||
shape = bullnose
|
||||
Diameter; Endmill diameter
|
||||
Length; Overall length of the endmill
|
||||
ShankDiameter; diameter of the shank
|
||||
FlatRadius;Radius of the bottom flat part.
|
||||
CuttingEdgeHeight
|
||||
|
||||
shape = drill
|
||||
TipAngle; Full angle of the drill tip
|
||||
Diameter; Drill bit diameter
|
||||
Length; Overall length of the drillbit
|
||||
|
||||
shape = v-bit
|
||||
Diameter; Overall diameter of the V-bit
|
||||
CuttingEdgeAngle;Full angle of the v-bit
|
||||
Length; Overall bit length
|
||||
ShankDiameter
|
||||
FlatHeight;Height of the flat extension of the v-bit
|
||||
FlatRadius; Diameter of the flat end of the tip
|
||||
'''
|
||||
|
||||
# Private methods
|
||||
def _setDimensions(self):
|
||||
'''_setDimensions() ... Set values for possible dimensions.'''
|
||||
if hasattr(self.tool, 'Diameter'):
|
||||
self.diameter = float(self.tool.Diameter)
|
||||
else:
|
||||
msg = translate('PathSurfaceSupport',
|
||||
'Diameter dimension missing from ToolBit shape.')
|
||||
FreeCAD.Console.PrintError(msg + '\n')
|
||||
return False
|
||||
if hasattr(self.tool, 'LengthOffset'):
|
||||
self.lengthOffset = float(self.tool.LengthOffset)
|
||||
if hasattr(self.tool, 'FlatRadius'):
|
||||
self.flatRadius = float(self.tool.FlatRadius)
|
||||
if hasattr(self.tool, 'CuttingEdgeHeight'):
|
||||
self.cutEdgeHeight = float(self.tool.CuttingEdgeHeight)
|
||||
if hasattr(self.tool, 'CuttingEdgeAngle'):
|
||||
self.cutEdgeAngle = float(self.tool.CuttingEdgeAngle)
|
||||
return True
|
||||
|
||||
def _makeSafeCutter(self):
|
||||
# Make safeCutter with 25% buffer around physical cutter
|
||||
if self.safe:
|
||||
self.diameter = self.diameter * 1.25
|
||||
if self.flatRadius == 0.0:
|
||||
self.flatRadius = self.diameter * 0.25
|
||||
elif self.flatRadius > 0.0:
|
||||
self.flatRadius = self.flatRadius * 1.25
|
||||
|
||||
def _oclCylCutter(self):
|
||||
# Standard End Mill, Slot cutter, or Fly cutter
|
||||
# OCL -> CylCutter::CylCutter(diameter, length)
|
||||
if (self.diameter == -1.0 or self.cutEdgeHeight == -1.0):
|
||||
return
|
||||
self.oclTool = self.ocl.CylCutter(
|
||||
self.diameter,
|
||||
self.cutEdgeHeight + self.lengthOffset
|
||||
)
|
||||
|
||||
def _oclBallCutter(self):
|
||||
# Standard Ball End Mill
|
||||
# OCL -> BallCutter::BallCutter(diameter, length)
|
||||
if (self.diameter == -1.0 or self.cutEdgeHeight == -1.0):
|
||||
return
|
||||
self.tiltCutter = True
|
||||
self.oclTool = self.ocl.BallCutter(
|
||||
self.diameter,
|
||||
self.cutEdgeHeight + self.lengthOffset
|
||||
)
|
||||
|
||||
def _oclBullCutter(self):
|
||||
# Standard Bull Nose cutter
|
||||
# Reference: https://www.fine-tools.com/halbstabfraeser.html
|
||||
# OCL -> BullCutter::BullCutter(diameter, minor radius, length)
|
||||
if (self.diameter == -1.0 or
|
||||
self.flatRadius == -1.0 or
|
||||
self.cutEdgeHeight == -1.0):
|
||||
return
|
||||
self.oclTool = self.ocl.BullCutter(
|
||||
self.diameter,
|
||||
self.diameter - self.flatRadius,
|
||||
self.cutEdgeHeight + self.lengthOffset
|
||||
)
|
||||
|
||||
def _oclConeCutter(self):
|
||||
# Engraver or V-bit cutter
|
||||
# OCL -> ConeCutter::ConeCutter(diameter, angle, length)
|
||||
if (self.diameter == -1.0 or
|
||||
self.cuttingEdgeAngle == -1.0 or self.cutEdgeHeight == -1.0):
|
||||
return
|
||||
self.oclTool = self.ocl.ConeCutter(
|
||||
self.diameter,
|
||||
self.cuttingEdgeAngle,
|
||||
self.cutEdgeHeight + self.lengthOffset
|
||||
)
|
||||
|
||||
def _setToolMethod(self):
|
||||
toolMap = dict()
|
||||
|
||||
if self.toolMode == 'Legacy':
|
||||
# Set cutter details
|
||||
# https://www.freecadweb.org/api/dd/dfe/classPath_1_1Tool.html#details
|
||||
toolMap = {
|
||||
'EndMill': 'CylCutter',
|
||||
'BallEndMill': 'BallCutter',
|
||||
'SlotCutter': 'CylCutter',
|
||||
'Engraver': 'ConeCutter',
|
||||
'Drill': 'ConeCutter',
|
||||
'CounterSink': 'ConeCutter',
|
||||
'FlyCutter': 'CylCutter',
|
||||
'CenterDrill': 'None',
|
||||
'CounterBore': 'None',
|
||||
'Reamer': 'None',
|
||||
'Tap': 'None',
|
||||
'ChamferMill': 'None',
|
||||
'CornerRound': 'None'
|
||||
}
|
||||
elif self.toolMode == 'ToolBit':
|
||||
toolMap = {
|
||||
'endmill': 'CylCutter',
|
||||
'ballend': 'BallCutter',
|
||||
'bullnose': 'BullCutter',
|
||||
'drill': 'ConeCutter',
|
||||
'engraver': 'ConeCutter',
|
||||
'v-bit': 'ConeCutter',
|
||||
'chamfer': 'None'
|
||||
}
|
||||
self.toolMethod = 'None'
|
||||
if self.toolType in toolMap:
|
||||
self.toolMethod = toolMap[self.toolType]
|
||||
|
||||
# Public methods
|
||||
def getOclTool(self):
|
||||
"""getOclTool()... Call this method after class instantiation
|
||||
to return OCL tool object."""
|
||||
# Check for tool controller and tool object
|
||||
if not self.tool or not self.toolMode:
|
||||
msg = translate('PathSurface',
|
||||
'Failed to identify tool for operation.')
|
||||
FreeCAD.Console.PrintError(msg + '\n')
|
||||
return False
|
||||
|
||||
if not self._setDimensions():
|
||||
return False
|
||||
|
||||
self._setToolMethod()
|
||||
|
||||
if self.toolMethod == 'None':
|
||||
err = translate('PathSurface',
|
||||
'Failed to map selected tool to an OCL tool type.')
|
||||
FreeCAD.Console.PrintError(err + '\n')
|
||||
return False
|
||||
else:
|
||||
PathLog.debug('OCL_Tool tool method: {}'.format(self.toolMethod))
|
||||
oclToolMethod = getattr(self, '_ocl' + self.toolMethod)
|
||||
oclToolMethod()
|
||||
|
||||
if self.oclTool:
|
||||
return self.oclTool
|
||||
|
||||
# Set error messages
|
||||
err = translate('PathSurface',
|
||||
'Failed to translate active tool to OCL tool type.')
|
||||
FreeCAD.Console.PrintError(err + '\n')
|
||||
return False
|
||||
|
||||
def useTiltCutter(self):
|
||||
"""useTiltCutter()... Call this method after getOclTool() method
|
||||
to return status of cutter tilt availability - generally this
|
||||
is for a ball end mill."""
|
||||
if not self.tool or not self.oclTool:
|
||||
err = translate('PathSurface',
|
||||
'OCL tool not available. Cannot determine is cutter has tilt available.')
|
||||
FreeCAD.Console.PrintError(err + '\n')
|
||||
return False
|
||||
return self.tiltCutter
|
||||
# Eclass
|
||||
|
||||
# Support functions
|
||||
def makeExtendedBoundBox(wBB, bbBfr, zDep):
|
||||
PathLog.debug('makeExtendedBoundBox()')
|
||||
|
||||
@@ -466,14 +466,28 @@ class ObjectWaterline(PathOp.ObjectOp):
|
||||
else:
|
||||
self.CutClimb = True
|
||||
|
||||
# Instantiate additional class operation variables
|
||||
self.resetOpVariables()
|
||||
|
||||
# Setup cutter for OCL and cutout value for operation - based on tool controller properties
|
||||
oclTool = PathSurfaceSupport.OCL_Tool(ocl, obj)
|
||||
self.cutter = oclTool.getOclTool()
|
||||
if not self.cutter:
|
||||
PathLog.error(translate('PathWaterline', "Canceling Waterline operation. Error creating OCL cutter."))
|
||||
return
|
||||
self.toolDiam = self.cutter.getDiameter()
|
||||
self.radius = self.toolDiam / 2.0
|
||||
self.cutOut = (self.toolDiam * (float(obj.StepOver) / 100.0))
|
||||
self.gaps = [self.toolDiam, self.toolDiam, self.toolDiam]
|
||||
|
||||
# Begin GCode for operation with basic information
|
||||
# ... and move cutter to clearance height and startpoint
|
||||
output = ''
|
||||
if obj.Comment != '':
|
||||
self.commandlist.append(Path.Command('N ({})'.format(str(obj.Comment)), {}))
|
||||
self.commandlist.append(Path.Command('N ({})'.format(obj.Label), {}))
|
||||
self.commandlist.append(Path.Command('N (Tool type: {})'.format(str(obj.ToolController.Tool.ToolType)), {}))
|
||||
self.commandlist.append(Path.Command('N (Compensated Tool Path. Diameter: {})'.format(str(obj.ToolController.Tool.Diameter)), {}))
|
||||
self.commandlist.append(Path.Command('N (Tool type: {})'.format(oclTool.toolType), {}))
|
||||
self.commandlist.append(Path.Command('N (Compensated Tool Path. Diameter: {})'.format(oclTool.diameter), {}))
|
||||
self.commandlist.append(Path.Command('N (Sample interval: {})'.format(str(obj.SampleInterval.Value)), {}))
|
||||
self.commandlist.append(Path.Command('N (Step over %: {})'.format(str(obj.StepOver)), {}))
|
||||
self.commandlist.append(Path.Command('N ({})'.format(output), {}))
|
||||
@@ -481,9 +495,6 @@ class ObjectWaterline(PathOp.ObjectOp):
|
||||
if obj.UseStartPoint:
|
||||
self.commandlist.append(Path.Command('G0', {'X': obj.StartPoint.x, 'Y': obj.StartPoint.y, 'F': self.horizRapid}))
|
||||
|
||||
# Instantiate additional class operation variables
|
||||
self.resetOpVariables()
|
||||
|
||||
# Impose property limits
|
||||
self.opApplyPropertyLimits(obj)
|
||||
|
||||
@@ -504,16 +515,6 @@ class ObjectWaterline(PathOp.ObjectOp):
|
||||
# Add temp object to temp group folder with following code:
|
||||
# ... self.tempGroup.addObject(OBJ)
|
||||
|
||||
# Setup cutter for OCL and cutout value for operation - based on tool controller properties
|
||||
self.cutter = self.setOclCutter(obj)
|
||||
if self.cutter is False:
|
||||
PathLog.error(translate('PathWaterline', "Canceling Waterline operation. Error creating OCL cutter."))
|
||||
return
|
||||
self.toolDiam = self.cutter.getDiameter()
|
||||
self.radius = self.toolDiam / 2.0
|
||||
self.cutOut = (self.toolDiam * (float(obj.StepOver) / 100.0))
|
||||
self.gaps = [self.toolDiam, self.toolDiam, self.toolDiam]
|
||||
|
||||
# Get height offset values for later use
|
||||
self.SafeHeightOffset = JOB.SetupSheet.SafeHeightOffset.Value
|
||||
self.ClearHeightOffset = JOB.SetupSheet.ClearanceHeightOffset.Value
|
||||
@@ -1752,7 +1753,6 @@ class ObjectWaterline(PathOp.ObjectOp):
|
||||
self.stl = None
|
||||
self.fullSTL = None
|
||||
self.cutOut = 0.0
|
||||
self.radius = 0.0
|
||||
self.useTiltCutter = False
|
||||
return True
|
||||
|
||||
@@ -1782,55 +1782,6 @@ class ObjectWaterline(PathOp.ObjectOp):
|
||||
del self.useTiltCutter
|
||||
return True
|
||||
|
||||
def setOclCutter(self, obj, safe=False):
|
||||
''' setOclCutter(obj) ... Translation function to convert FreeCAD tool definition to OCL formatted tool. '''
|
||||
# Set cutter details
|
||||
# https://www.freecadweb.org/api/dd/dfe/classPath_1_1Tool.html#details
|
||||
diam_1 = float(obj.ToolController.Tool.Diameter)
|
||||
lenOfst = obj.ToolController.Tool.LengthOffset if hasattr(obj.ToolController.Tool, 'LengthOffset') else 0
|
||||
FR = obj.ToolController.Tool.FlatRadius if hasattr(obj.ToolController.Tool, 'FlatRadius') else 0
|
||||
CEH = obj.ToolController.Tool.CuttingEdgeHeight if hasattr(obj.ToolController.Tool, 'CuttingEdgeHeight') else 0
|
||||
CEA = obj.ToolController.Tool.CuttingEdgeAngle if hasattr(obj.ToolController.Tool, 'CuttingEdgeAngle') else 0
|
||||
|
||||
# Make safeCutter with 2 mm buffer around physical cutter
|
||||
if safe is True:
|
||||
diam_1 += 4.0
|
||||
if FR != 0.0:
|
||||
FR += 2.0
|
||||
|
||||
PathLog.debug('ToolType: {}'.format(obj.ToolController.Tool.ToolType))
|
||||
if obj.ToolController.Tool.ToolType == 'EndMill':
|
||||
# Standard End Mill
|
||||
return ocl.CylCutter(diam_1, (CEH + lenOfst))
|
||||
|
||||
elif obj.ToolController.Tool.ToolType == 'BallEndMill' and FR == 0.0:
|
||||
# Standard Ball End Mill
|
||||
# OCL -> BallCutter::BallCutter(diameter, length)
|
||||
self.useTiltCutter = True
|
||||
return ocl.BallCutter(diam_1, (diam_1 / 2 + lenOfst))
|
||||
|
||||
elif obj.ToolController.Tool.ToolType == 'BallEndMill' and FR > 0.0:
|
||||
# Bull Nose or Corner Radius cutter
|
||||
# Reference: https://www.fine-tools.com/halbstabfraeser.html
|
||||
# OCL -> BallCutter::BallCutter(diameter, length)
|
||||
return ocl.BullCutter(diam_1, FR, (CEH + lenOfst))
|
||||
|
||||
elif obj.ToolController.Tool.ToolType == 'Engraver' and FR > 0.0:
|
||||
# Bull Nose or Corner Radius cutter
|
||||
# Reference: https://www.fine-tools.com/halbstabfraeser.html
|
||||
# OCL -> ConeCutter::ConeCutter(diameter, angle, lengthOffset)
|
||||
return ocl.ConeCutter(diam_1, (CEA / 2), lenOfst)
|
||||
|
||||
elif obj.ToolController.Tool.ToolType == 'ChamferMill':
|
||||
# Bull Nose or Corner Radius cutter
|
||||
# Reference: https://www.fine-tools.com/halbstabfraeser.html
|
||||
# OCL -> ConeCutter::ConeCutter(diameter, angle, lengthOffset)
|
||||
return ocl.ConeCutter(diam_1, (CEA / 2), lenOfst)
|
||||
else:
|
||||
# Default to standard end mill
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user