Merge branch 'master' into remove-dead-code
This commit is contained in:
@@ -32,7 +32,6 @@ import PathScripts.PathPost as PathPost
|
||||
import camotics
|
||||
import io
|
||||
import json
|
||||
import os
|
||||
import queue
|
||||
import subprocess
|
||||
|
||||
@@ -245,7 +244,6 @@ class CamoticsSimulation(QtCore.QObject):
|
||||
def cancel(self):
|
||||
pass
|
||||
|
||||
|
||||
def buildproject(self): # , files=[]):
|
||||
PathLog.track()
|
||||
|
||||
|
||||
@@ -609,10 +609,6 @@ class MapWireToTag:
|
||||
"Exception during processing tag @(%.2f, %.2f) (%s) - disabling the tag"
|
||||
% (self.tag.x, self.tag.y, e.args[0])
|
||||
)
|
||||
# if sys.version_info.major < 3:
|
||||
# traceback.print_exc(e)
|
||||
# else:
|
||||
# traceback.print_exc()
|
||||
self.tag.enabled = False
|
||||
commands = []
|
||||
for e in self.edges:
|
||||
@@ -705,10 +701,6 @@ class PathData:
|
||||
if wire.isClosed():
|
||||
return wire
|
||||
except Exception:
|
||||
# if sys.version_info.major < 3:
|
||||
# traceback.print_exc(e)
|
||||
# else:
|
||||
# traceback.print_exc()
|
||||
return None
|
||||
|
||||
def supportsTagGeneration(self):
|
||||
@@ -1275,10 +1267,6 @@ class ObjectTagDressup:
|
||||
PathLog.error(
|
||||
"processing tags failed clearing all tags ... '%s'" % (e.args[0])
|
||||
)
|
||||
# if sys.version_info.major < 3:
|
||||
# traceback.print_exc(e)
|
||||
# else:
|
||||
# traceback.print_exc()
|
||||
obj.Path = obj.Base.Path
|
||||
|
||||
# update disabled in case there are some additional ones
|
||||
@@ -1323,10 +1311,6 @@ class ObjectTagDressup:
|
||||
)
|
||||
+ "\n"
|
||||
)
|
||||
# if sys.version_info.major < 3:
|
||||
# traceback.print_exc(e)
|
||||
# else:
|
||||
# traceback.print_exc()
|
||||
return None
|
||||
|
||||
self.toolRadius = float(PathDressup.toolController(obj.Base).Tool.Diameter) / 2
|
||||
|
||||
@@ -174,7 +174,7 @@ class PathBoundary:
|
||||
lastExit = None
|
||||
for cmd in self.baseOp.Path.Commands[1:]:
|
||||
if cmd.Name in PathGeom.CmdMoveAll:
|
||||
if bogusX == True:
|
||||
if bogusX:
|
||||
bogusX = "X" not in cmd.Parameters
|
||||
if bogusY:
|
||||
bogusY = "Y" not in cmd.Parameters
|
||||
|
||||
@@ -51,7 +51,7 @@ class ObjectEngrave(PathEngraveBase.ObjectOp):
|
||||
self.wires = []
|
||||
|
||||
def opFeatures(self, obj):
|
||||
"""opFeatures(obj) ... return all standard features and edges based geomtries"""
|
||||
"""opFeatures(obj) ... return all standard features and edges based geometries"""
|
||||
return (
|
||||
PathOp.FeatureTool
|
||||
| PathOp.FeatureDepths
|
||||
|
||||
@@ -29,6 +29,7 @@ import PathScripts.PathLog as PathLog
|
||||
import PathScripts.PathPreferences as PathPreferences
|
||||
import PathScripts.PathUtil as PathUtil
|
||||
import PathScripts.PathUtils as PathUtils
|
||||
import math
|
||||
import time
|
||||
|
||||
|
||||
@@ -867,7 +868,7 @@ class ObjectOp(object):
|
||||
# Get the cycle time in seconds
|
||||
seconds = obj.Path.getCycleTime(hFeedrate, vFeedrate, hRapidrate, vRapidrate)
|
||||
|
||||
if not seconds:
|
||||
if not seconds or math.isnan(seconds):
|
||||
return translate("Path", "Cycletime Error")
|
||||
|
||||
# Convert the cycle time to a HH:MM:SS format
|
||||
|
||||
@@ -115,7 +115,7 @@ def processFileNameSubstitutions(
|
||||
j = job.Label
|
||||
filename = filename.replace("%j", j)
|
||||
|
||||
# Use the sequnce number if explicitly called
|
||||
# Use the sequence number if explicitly called
|
||||
if "%S" in filename:
|
||||
j = job.Label
|
||||
filename = filename.replace("%S", str(sequencenumber))
|
||||
|
||||
@@ -124,7 +124,7 @@ class CHAMFERGate(PathBaseGate):
|
||||
class DRILLGate(PathBaseGate):
|
||||
def allow(self, doc, obj, sub):
|
||||
PathLog.debug("obj: {} sub: {}".format(obj, sub))
|
||||
if not hasattr(obj, "Shape") and sub:
|
||||
if not hasattr(obj, "Shape"):
|
||||
return False
|
||||
shape = obj.Shape
|
||||
subobj = shape.getElement(sub)
|
||||
|
||||
@@ -48,10 +48,108 @@ else:
|
||||
|
||||
translate = FreeCAD.Qt.translate
|
||||
|
||||
# Constants
|
||||
LeftHand = "LeftHand"
|
||||
RightHand = "RightHand"
|
||||
ThreadTypeCustomExternal = "CustomExternal"
|
||||
ThreadTypeCustomInternal = "CustomInternal"
|
||||
ThreadTypeImperialExternal2A = "ImperialExternal2A"
|
||||
ThreadTypeImperialExternal3A = "ImperialExternal3A"
|
||||
ThreadTypeImperialInternal2B = "ImperialInternal2B"
|
||||
ThreadTypeImperialInternal3B = "ImperialInternal3B"
|
||||
ThreadTypeMetricExternal4G6G = "MetricExternal4G6G"
|
||||
ThreadTypeMetricExternal6G = "MetricExternal6G"
|
||||
ThreadTypeMetricInternal6H = "MetricInternal6H"
|
||||
DirectionClimb = "Climb"
|
||||
DirectionConventional = "Conventional"
|
||||
|
||||
ThreadOrientations = [LeftHand, RightHand]
|
||||
|
||||
ThreadTypeData = {
|
||||
ThreadTypeImperialExternal2A: "imperial-external-2A.csv",
|
||||
ThreadTypeImperialExternal3A: "imperial-external-3A.csv",
|
||||
ThreadTypeImperialInternal2B: "imperial-internal-2B.csv",
|
||||
ThreadTypeImperialInternal3B: "imperial-internal-3B.csv",
|
||||
ThreadTypeMetricExternal4G6G: "metric-external-4G6G.csv",
|
||||
ThreadTypeMetricExternal6G: "metric-external-6G.csv",
|
||||
ThreadTypeMetricInternal6H: "metric-internal-6H.csv",
|
||||
}
|
||||
|
||||
ThreadTypesExternal = [
|
||||
ThreadTypeCustomExternal,
|
||||
ThreadTypeImperialExternal2A,
|
||||
ThreadTypeImperialExternal3A,
|
||||
ThreadTypeMetricExternal4G6G,
|
||||
ThreadTypeMetricExternal6G,
|
||||
]
|
||||
ThreadTypesInternal = [
|
||||
ThreadTypeCustomInternal,
|
||||
ThreadTypeImperialInternal2B,
|
||||
ThreadTypeImperialInternal3B,
|
||||
ThreadTypeMetricInternal6H,
|
||||
]
|
||||
ThreadTypesImperial = [
|
||||
ThreadTypeImperialExternal2A,
|
||||
ThreadTypeImperialExternal3A,
|
||||
ThreadTypeImperialInternal2B,
|
||||
ThreadTypeImperialInternal3B,
|
||||
]
|
||||
ThreadTypesMetric = [
|
||||
ThreadTypeMetricExternal4G6G,
|
||||
ThreadTypeMetricExternal6G,
|
||||
ThreadTypeMetricInternal6H,
|
||||
]
|
||||
ThreadTypes = ThreadTypesInternal + ThreadTypesExternal
|
||||
Directions = [DirectionClimb, DirectionConventional]
|
||||
|
||||
def _isThreadInternal(obj):
|
||||
return obj.ThreadType in ThreadTypesInternal
|
||||
|
||||
def threadSetupInternal(obj, zTop, zBottom):
|
||||
PathLog.track()
|
||||
if obj.ThreadOrientation == RightHand:
|
||||
# Right hand thread, G2, top down -> conventional milling
|
||||
if obj.Direction == DirectionConventional:
|
||||
return ("G2", zTop, zBottom)
|
||||
# For climb milling we need to cut the thread from the bottom up
|
||||
# in the opposite direction -> G3
|
||||
return ("G3", zBottom, zTop)
|
||||
# Left hand thread, G3, top down -> climb milling
|
||||
if obj.Direction == DirectionClimb:
|
||||
return ("G3", zTop, zBottom)
|
||||
# for conventional milling, cut bottom up with G2
|
||||
return ("G2", zBottom, zTop)
|
||||
|
||||
def threadSetupExternal(obj, zTop, zBottom):
|
||||
PathLog.track()
|
||||
if obj.ThreadOrientation == RightHand:
|
||||
# right hand thread, G2, top down -> climb milling
|
||||
if obj.Direction == DirectionClimb:
|
||||
return ("G2", zTop, zBottom)
|
||||
# for conventional, mill bottom up the other way around
|
||||
return ("G3", zBottom, zTop)
|
||||
# left hand thread, G3, top down -> conventional milling
|
||||
if obj.Direction == DirectionConventional:
|
||||
return ("G3", zTop, zBottom)
|
||||
# for climb milling need to go bottom up and the other way
|
||||
return ("G2", zBottom, zTop)
|
||||
|
||||
def threadSetup(obj):
|
||||
"""Return (cmd, zbegin, zend) of thread milling operation"""
|
||||
PathLog.track()
|
||||
|
||||
zTop = obj.StartDepth.Value
|
||||
zBottom = obj.FinalDepth.Value
|
||||
|
||||
if _isThreadInternal(obj):
|
||||
return threadSetupInternal(obj, zTop, zBottom)
|
||||
else:
|
||||
return threadSetupExternal(obj, zTop, zBottom)
|
||||
|
||||
|
||||
def threadRadii(internal, majorDia, minorDia, toolDia, toolCrest):
|
||||
"""threadRadii(majorDia, minorDia, toolDia, toolCrest) ... returns the minimum and maximum radius for thread."""
|
||||
PathLog.track(majorDia, minorDia, toolDia, toolCrest)
|
||||
PathLog.track(internal, majorDia, minorDia, toolDia, toolCrest)
|
||||
if toolCrest is None:
|
||||
toolCrest = 0.0
|
||||
# As it turns out metric and imperial standard threads follow the same rules.
|
||||
@@ -66,12 +164,15 @@ def threadRadii(internal, majorDia, minorDia, toolDia, toolCrest):
|
||||
outerTip = majorDia / 2.0 + H / 8.0
|
||||
# Compensate for the crest of the tool
|
||||
toolTip = outerTip - toolCrest * SQRT_3_DIVIDED_BY_2
|
||||
return ((minorDia - toolDia) / 2.0, toolTip - toolDia / 2.0)
|
||||
# mill outside in
|
||||
innerTip = minorDia / 2.0 - H / 4.0
|
||||
# Compensate for the crest of the tool
|
||||
toolTip = innerTip - toolCrest * SQRT_3_DIVIDED_BY_2
|
||||
return ((majorDia + toolDia) / 2.0, toolTip + toolDia / 2.0)
|
||||
radii = ((minorDia - toolDia) / 2.0, toolTip - toolDia / 2.0)
|
||||
else:
|
||||
# mill outside in
|
||||
innerTip = minorDia / 2.0 - H / 4.0
|
||||
# Compensate for the crest of the tool
|
||||
toolTip = innerTip - toolCrest * SQRT_3_DIVIDED_BY_2
|
||||
radii = ((majorDia + toolDia) / 2.0, toolTip + toolDia / 2.0)
|
||||
PathLog.track(radii)
|
||||
return radii
|
||||
|
||||
|
||||
def threadPasses(count, radii, internal, majorDia, minorDia, toolDia, toolCrest):
|
||||
@@ -92,11 +193,14 @@ def threadPasses(count, radii, internal, majorDia, minorDia, toolDia, toolCrest)
|
||||
minor, major = radii(internal, majorDia, minorDia, toolDia, toolCrest)
|
||||
H = float(major - minor)
|
||||
Hi = [H * math.sqrt((i + 1) / count) for i in range(count)]
|
||||
PathLog.debug("threadPasses({}, {}) -> H={} : {}".format(minor, major, H, Hi))
|
||||
|
||||
if internal:
|
||||
return [minor + h for h in Hi]
|
||||
return [major - h for h in Hi]
|
||||
# For external threads threadRadii returns the radii in reverse order because that's
|
||||
# the order in which they have to get milled. As a result H ends up being negative
|
||||
# and the math for internal and external threads is identical.
|
||||
passes = [minor + h for h in Hi]
|
||||
PathLog.debug(f"threadPasses({minor}, {major}) -> H={H} : {Hi} --> {passes}")
|
||||
|
||||
return passes
|
||||
|
||||
|
||||
def elevatorRadius(obj, center, internal, tool):
|
||||
@@ -121,59 +225,6 @@ def elevatorRadius(obj, center, internal, tool):
|
||||
class ObjectThreadMilling(PathCircularHoleBase.ObjectOp):
|
||||
"""Proxy object for thread milling operation."""
|
||||
|
||||
LeftHand = "LeftHand"
|
||||
RightHand = "RightHand"
|
||||
ThreadTypeCustomExternal = "CustomExternal"
|
||||
ThreadTypeCustomInternal = "CustomInternal"
|
||||
ThreadTypeImperialExternal2A = "ImperialExternal2A"
|
||||
ThreadTypeImperialExternal3A = "ImperialExternal3A"
|
||||
ThreadTypeImperialInternal2B = "ImperialInternal2B"
|
||||
ThreadTypeImperialInternal3B = "ImperialInternal3B"
|
||||
ThreadTypeMetricExternal4G6G = "MetricExternal4G6G"
|
||||
ThreadTypeMetricExternal6G = "MetricExternal6G"
|
||||
ThreadTypeMetricInternal6H = "MetricInternal6H"
|
||||
DirectionClimb = "Climb"
|
||||
DirectionConventional = "Conventional"
|
||||
|
||||
ThreadOrientations = [LeftHand, RightHand]
|
||||
|
||||
ThreadTypeData = {
|
||||
ThreadTypeImperialExternal2A: "imperial-external-2A.csv",
|
||||
ThreadTypeImperialExternal3A: "imperial-external-3A.csv",
|
||||
ThreadTypeImperialInternal2B: "imperial-internal-2B.csv",
|
||||
ThreadTypeImperialInternal3B: "imperial-internal-3B.csv",
|
||||
ThreadTypeMetricExternal4G6G: "metric-external-4G6G.csv",
|
||||
ThreadTypeMetricExternal6G: "metric-external-6G.csv",
|
||||
ThreadTypeMetricInternal6H: "metric-internal-6H.csv",
|
||||
}
|
||||
|
||||
ThreadTypesExternal = [
|
||||
ThreadTypeCustomExternal,
|
||||
ThreadTypeImperialExternal2A,
|
||||
ThreadTypeImperialExternal3A,
|
||||
ThreadTypeMetricExternal4G6G,
|
||||
ThreadTypeMetricExternal6G,
|
||||
]
|
||||
ThreadTypesInternal = [
|
||||
ThreadTypeCustomInternal,
|
||||
ThreadTypeImperialInternal2B,
|
||||
ThreadTypeImperialInternal3B,
|
||||
ThreadTypeMetricInternal6H,
|
||||
]
|
||||
ThreadTypesImperial = [
|
||||
ThreadTypeImperialExternal2A,
|
||||
ThreadTypeImperialExternal3A,
|
||||
ThreadTypeImperialInternal2B,
|
||||
ThreadTypeImperialInternal3B,
|
||||
]
|
||||
ThreadTypesMetric = [
|
||||
ThreadTypeMetricExternal4G6G,
|
||||
ThreadTypeMetricExternal6G,
|
||||
ThreadTypeMetricInternal6H,
|
||||
]
|
||||
ThreadTypes = ThreadTypesInternal + ThreadTypesExternal
|
||||
Directions = [DirectionClimb, DirectionConventional]
|
||||
|
||||
@classmethod
|
||||
def propertyEnumerations(self, dataType="data"):
|
||||
"""helixOpPropertyEnumerations(dataType="data")... return property enumeration lists of specified dataType.
|
||||
@@ -191,59 +242,59 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp):
|
||||
"ThreadType": [
|
||||
(
|
||||
translate("Path_ThreadMilling", "Custom External"),
|
||||
ObjectThreadMilling.ThreadTypeCustomExternal,
|
||||
ThreadTypeCustomExternal,
|
||||
),
|
||||
(
|
||||
translate("Path_ThreadMilling", "Custom Internal"),
|
||||
ObjectThreadMilling.ThreadTypeCustomInternal,
|
||||
ThreadTypeCustomInternal,
|
||||
),
|
||||
(
|
||||
translate("Path_ThreadMilling", "Imperial External (2A)"),
|
||||
ObjectThreadMilling.ThreadTypeImperialExternal2A,
|
||||
ThreadTypeImperialExternal2A,
|
||||
),
|
||||
(
|
||||
translate("Path_ThreadMilling", "Imperial External (3A)"),
|
||||
ObjectThreadMilling.ThreadTypeImperialExternal3A,
|
||||
ThreadTypeImperialExternal3A,
|
||||
),
|
||||
(
|
||||
translate("Path_ThreadMilling", "Imperial Internal (2B)"),
|
||||
ObjectThreadMilling.ThreadTypeImperialInternal2B,
|
||||
ThreadTypeImperialInternal2B,
|
||||
),
|
||||
(
|
||||
translate("Path_ThreadMilling", "Imperial Internal (3B)"),
|
||||
ObjectThreadMilling.ThreadTypeImperialInternal3B,
|
||||
ThreadTypeImperialInternal3B,
|
||||
),
|
||||
(
|
||||
translate("Path_ThreadMilling", "Metric External (4G6G)"),
|
||||
ObjectThreadMilling.ThreadTypeMetricExternal4G6G,
|
||||
ThreadTypeMetricExternal4G6G,
|
||||
),
|
||||
(
|
||||
translate("Path_ThreadMilling", "Metric External (6G)"),
|
||||
ObjectThreadMilling.ThreadTypeMetricExternal6G,
|
||||
ThreadTypeMetricExternal6G,
|
||||
),
|
||||
(
|
||||
translate("Path_ThreadMilling", "Metric Internal (6H)"),
|
||||
ObjectThreadMilling.ThreadTypeMetricInternal6H,
|
||||
ThreadTypeMetricInternal6H,
|
||||
),
|
||||
],
|
||||
"ThreadOrientation": [
|
||||
(
|
||||
translate("Path_ThreadMilling", "LeftHand"),
|
||||
ObjectThreadMilling.LeftHand,
|
||||
LeftHand,
|
||||
),
|
||||
(
|
||||
translate("Path_ThreadMilling", "RightHand"),
|
||||
ObjectThreadMilling.RightHand,
|
||||
RightHand,
|
||||
),
|
||||
],
|
||||
"Direction": [
|
||||
(
|
||||
translate("Path_ThreadMilling", "Climb"),
|
||||
ObjectThreadMilling.DirectionClimb,
|
||||
DirectionClimb,
|
||||
),
|
||||
(
|
||||
translate("Path_ThreadMilling", "Conventional"),
|
||||
ObjectThreadMilling.DirectionConventional,
|
||||
DirectionConventional,
|
||||
),
|
||||
],
|
||||
}
|
||||
@@ -274,14 +325,14 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp):
|
||||
"Thread",
|
||||
QT_TRANSLATE_NOOP("App::Property", "Set thread orientation"),
|
||||
)
|
||||
# obj.ThreadOrientation = self.ThreadOrientations
|
||||
# obj.ThreadOrientation = ThreadOrientations
|
||||
obj.addProperty(
|
||||
"App::PropertyEnumeration",
|
||||
"ThreadType",
|
||||
"Thread",
|
||||
QT_TRANSLATE_NOOP("App::Property", "Currently only internal"),
|
||||
)
|
||||
# obj.ThreadType = self.ThreadTypes
|
||||
# obj.ThreadType = ThreadTypes
|
||||
obj.addProperty(
|
||||
"App::PropertyString",
|
||||
"ThreadName",
|
||||
@@ -362,32 +413,6 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp):
|
||||
for n in self.propertyEnumerations():
|
||||
setattr(obj, n[0], n[1])
|
||||
|
||||
def _isThreadInternal(self, obj):
|
||||
return obj.ThreadType in self.ThreadTypesInternal
|
||||
|
||||
def _threadSetupInternal(self, obj):
|
||||
PathLog.track()
|
||||
# the thing to remember is that Climb, for an internal thread must always be G3
|
||||
if obj.Direction == self.DirectionClimb:
|
||||
if obj.ThreadOrientation == self.RightHand:
|
||||
return ("G3", obj.FinalDepth.Value, obj.StartDepth.Value)
|
||||
return ("G3", obj.StartDepth.Value, obj.FinalDepth.Value)
|
||||
if obj.ThreadOrientation == self.RightHand:
|
||||
return ("G2", obj.StartDepth.Value, obj.FinalDepth.Value)
|
||||
return ("G2", obj.FinalDepth.Value, obj.StartDepth.Value)
|
||||
|
||||
def threadSetup(self, obj):
|
||||
PathLog.track()
|
||||
cmd, zbegin, zend = self._threadSetupInternal(obj)
|
||||
|
||||
if obj.ThreadType in self.ThreadTypesInternal:
|
||||
return (cmd, zbegin, zend)
|
||||
|
||||
# need to reverse direction for external threads
|
||||
if cmd == "G2":
|
||||
return ("G3", zbegin, zend)
|
||||
return ("G2", zbegin, zend)
|
||||
|
||||
def threadPassRadii(self, obj):
|
||||
PathLog.track(obj.Label)
|
||||
rMajor = (obj.MajorDiameter.Value - self.tool.Diameter) / 2.0
|
||||
@@ -402,7 +427,7 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp):
|
||||
|
||||
def executeThreadMill(self, obj, loc, gcode, zStart, zFinal, pitch):
|
||||
PathLog.track(obj.Label, loc, gcode, zStart, zFinal, pitch)
|
||||
elevator = elevatorRadius(obj, loc, self._isThreadInternal(obj), self.tool)
|
||||
elevator = elevatorRadius(obj, loc, _isThreadInternal(obj), self.tool)
|
||||
|
||||
move2clearance = Path.Command(
|
||||
"G0", {"Z": obj.ClearanceHeight.Value, "F": self.vertRapid}
|
||||
@@ -413,7 +438,7 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp):
|
||||
for radius in threadPasses(
|
||||
obj.Passes,
|
||||
threadRadii,
|
||||
self._isThreadInternal(obj),
|
||||
_isThreadInternal(obj),
|
||||
obj.MajorDiameter.Value,
|
||||
obj.MinorDiameter.Value,
|
||||
float(self.tool.Diameter),
|
||||
@@ -421,7 +446,7 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp):
|
||||
):
|
||||
if (
|
||||
not start is None
|
||||
and not self._isThreadInternal(obj)
|
||||
and not _isThreadInternal(obj)
|
||||
and not obj.LeadInOut
|
||||
):
|
||||
# external thread without lead in/out have to go up and over
|
||||
@@ -459,7 +484,7 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp):
|
||||
if self.isToolSupported(obj, self.tool):
|
||||
self.commandlist.append(Path.Command("(Begin Thread Milling)"))
|
||||
|
||||
(cmd, zStart, zFinal) = self.threadSetup(obj)
|
||||
(cmd, zStart, zFinal) = threadSetup(obj)
|
||||
pitch = obj.Pitch.Value
|
||||
if obj.TPI > 0:
|
||||
pitch = 25.4 / obj.TPI
|
||||
@@ -482,13 +507,13 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp):
|
||||
|
||||
def opSetDefaultValues(self, obj, job):
|
||||
PathLog.track()
|
||||
obj.ThreadOrientation = self.RightHand
|
||||
obj.ThreadType = self.ThreadTypeMetricInternal6H
|
||||
obj.ThreadOrientation = RightHand
|
||||
obj.ThreadType = ThreadTypeMetricInternal6H
|
||||
obj.ThreadFit = 50
|
||||
obj.Pitch = 1
|
||||
obj.TPI = 0
|
||||
obj.Passes = 1
|
||||
obj.Direction = self.DirectionClimb
|
||||
obj.Direction = DirectionClimb
|
||||
obj.LeadInOut = False
|
||||
|
||||
def isToolSupported(self, obj, tool):
|
||||
|
||||
@@ -140,32 +140,32 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage):
|
||||
|
||||
def _isThreadCustom(self):
|
||||
return self.form.threadType.currentData() in [
|
||||
PathThreadMilling.ObjectThreadMilling.ThreadTypeCustomInternal,
|
||||
PathThreadMilling.ObjectThreadMilling.ThreadTypeCustomExternal,
|
||||
PathThreadMilling.ThreadTypeCustomInternal,
|
||||
PathThreadMilling.ThreadTypeCustomExternal,
|
||||
]
|
||||
|
||||
def _isThreadImperial(self):
|
||||
return (
|
||||
self.form.threadType.currentData()
|
||||
in PathThreadMilling.ObjectThreadMilling.ThreadTypesImperial
|
||||
in PathThreadMilling.ThreadTypesImperial
|
||||
)
|
||||
|
||||
def _isThreadMetric(self):
|
||||
return (
|
||||
self.form.threadType.currentData()
|
||||
in PathThreadMilling.ObjectThreadMilling.ThreadTypesMetric
|
||||
in PathThreadMilling.ThreadTypesMetric
|
||||
)
|
||||
|
||||
def _isThreadInternal(self):
|
||||
return (
|
||||
self.form.threadType.currentData()
|
||||
in PathThreadMilling.ObjectThreadMilling.ThreadTypesInternal
|
||||
in PathThreadMilling.ThreadTypesInternal
|
||||
)
|
||||
|
||||
def _isThreadExternal(self):
|
||||
return (
|
||||
self.form.threadType.currentData()
|
||||
in PathThreadMilling.ObjectThreadMilling.ThreadTypesExternal
|
||||
in PathThreadMilling.ThreadTypesExternal
|
||||
)
|
||||
|
||||
def _updateFromThreadType(self):
|
||||
@@ -195,7 +195,7 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage):
|
||||
self.pitch.updateSpinBox(0)
|
||||
fillThreads(
|
||||
self.form,
|
||||
PathThreadMilling.ObjectThreadMilling.ThreadTypeData[
|
||||
PathThreadMilling.ThreadTypeData[
|
||||
self.form.threadType.currentData()
|
||||
],
|
||||
self.obj.ThreadName,
|
||||
|
||||
@@ -286,6 +286,9 @@ class ToolBit(object):
|
||||
break
|
||||
if doc is None:
|
||||
p = findToolShape(p, path if path else obj.File)
|
||||
if p is None:
|
||||
raise FileNotFoundError
|
||||
|
||||
if not path and p != obj.BitShape:
|
||||
obj.BitShape = p
|
||||
PathLog.debug("ToolBit {} using shape file: {}".format(obj.Label, p))
|
||||
@@ -482,6 +485,9 @@ class ToolBitFactory(object):
|
||||
|
||||
def CreateFrom(self, path, name="ToolBit"):
|
||||
PathLog.track(name, path)
|
||||
|
||||
if not os.path.isfile(path):
|
||||
raise FileNotFoundError(f"{path} not found")
|
||||
try:
|
||||
data = Declaration(path)
|
||||
bit = Factory.CreateFromAttrs(data, name, path)
|
||||
|
||||
@@ -73,7 +73,10 @@ def checkWorkingDir():
|
||||
|
||||
qm = PySide.QtGui.QMessageBox
|
||||
ret = qm.question(
|
||||
None, "", translate("Path_ToolBit","Toolbit working directory not set up. Do that now?"), qm.Yes | qm.No
|
||||
None,
|
||||
"",
|
||||
translate("Path_ToolBit", "Toolbit working directory not set up. Do that now?"),
|
||||
qm.Yes | qm.No,
|
||||
)
|
||||
|
||||
if ret == qm.No:
|
||||
@@ -117,9 +120,10 @@ def checkWorkingDir():
|
||||
ret = qm.question(
|
||||
None,
|
||||
"",
|
||||
translate("Path_ToolBit","Toolbit Working directory {} needs these sudirectories:\n {} \n Create them?").format(
|
||||
workingdir, needed
|
||||
),
|
||||
translate(
|
||||
"Path_ToolBit",
|
||||
"Toolbit Working directory {} needs these sudirectories:\n {} \n Create them?",
|
||||
).format(workingdir, needed),
|
||||
qm.Yes | qm.No,
|
||||
)
|
||||
|
||||
@@ -136,7 +140,9 @@ def checkWorkingDir():
|
||||
ret = qm.question(
|
||||
None,
|
||||
"",
|
||||
translate("Path_ToolBit","Copy example files to new {} directory?").format(dir),
|
||||
translate(
|
||||
"Path_ToolBit", "Copy example files to new {} directory?"
|
||||
).format(dir),
|
||||
qm.Yes | qm.No,
|
||||
)
|
||||
if ret == qm.Yes:
|
||||
@@ -788,12 +794,15 @@ class ToolBitLibrary(object):
|
||||
|
||||
TooltableTypeJSON = translate("Path_ToolBit", "Tooltable JSON (*.fctl)")
|
||||
TooltableTypeLinuxCNC = translate("Path_ToolBit", "LinuxCNC tooltable (*.tbl)")
|
||||
TooltableTypeCamotics = translate("Path_ToolBit", "Camotics tooltable (*.json)")
|
||||
|
||||
filename = PySide.QtGui.QFileDialog.getSaveFileName(
|
||||
self.form,
|
||||
translate("Path_ToolBit", "Save toolbit library"),
|
||||
PathPreferences.lastPathToolLibrary(),
|
||||
"{};;{}".format(TooltableTypeJSON, TooltableTypeLinuxCNC),
|
||||
"{};;{};;{}".format(
|
||||
TooltableTypeJSON, TooltableTypeLinuxCNC, TooltableTypeCamotics
|
||||
),
|
||||
)
|
||||
if filename and filename[0]:
|
||||
if filename[1] == TooltableTypeLinuxCNC:
|
||||
@@ -803,6 +812,13 @@ class ToolBitLibrary(object):
|
||||
else "{}.tbl".format(filename[0])
|
||||
)
|
||||
self.libararySaveLinuxCNC(path)
|
||||
elif filename[1] == TooltableTypeCamotics:
|
||||
path = (
|
||||
filename[0]
|
||||
if filename[0].endswith(".json")
|
||||
else "{}.json".format(filename[0])
|
||||
)
|
||||
self.libararySaveCamotics(path)
|
||||
else:
|
||||
path = (
|
||||
filename[0]
|
||||
@@ -878,3 +894,73 @@ class ToolBitLibrary(object):
|
||||
|
||||
else:
|
||||
PathLog.error("Could not find tool #{} ".format(toolNr))
|
||||
|
||||
def libararySaveCamotics(self, path):
|
||||
|
||||
SHAPEMAP = {
|
||||
"ballend": "Ballnose",
|
||||
"endmill": "Cylindrical",
|
||||
"v-bit": "Conical",
|
||||
"chamfer": "Snubnose",
|
||||
}
|
||||
|
||||
tooltemplate = {
|
||||
"units": "metric",
|
||||
"shape": "cylindrical",
|
||||
"length": 10,
|
||||
"diameter": 3.125,
|
||||
"description": "",
|
||||
}
|
||||
toollist = {}
|
||||
|
||||
unitstring = (
|
||||
"imperial" if FreeCAD.Units.getSchema() in [2, 3, 5, 7] else "metric"
|
||||
)
|
||||
|
||||
for row in range(self.toolModel.rowCount()):
|
||||
toolNr = self.toolModel.data(
|
||||
self.toolModel.index(row, 0), PySide.QtCore.Qt.EditRole
|
||||
)
|
||||
|
||||
toolPath = self.toolModel.data(self.toolModel.index(row, 0), _PathRole)
|
||||
PathLog.debug(toolPath)
|
||||
try:
|
||||
bit = PathToolBit.Factory.CreateFrom(toolPath)
|
||||
except FileNotFoundError as e:
|
||||
FreeCAD.Console.PrintError(e)
|
||||
continue
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
if not bit:
|
||||
continue
|
||||
|
||||
PathLog.track(bit)
|
||||
|
||||
toolitem = tooltemplate.copy()
|
||||
|
||||
toolitem["diameter"] = (
|
||||
float(bit.Diameter.getUserPreferred()[0].split()[0])
|
||||
if hasattr(bit, "Diameter")
|
||||
else 2
|
||||
)
|
||||
toolitem["description"] = bit.Label
|
||||
toolitem["length"] = (
|
||||
float(bit.Length.getUserPreferred()[0].split()[0])
|
||||
if hasattr(bit, "Length")
|
||||
else 10
|
||||
)
|
||||
|
||||
if hasattr(bit, "Camotics"):
|
||||
toolitem["shape"] = bit.Camotics
|
||||
else:
|
||||
toolitem["shape"] = SHAPEMAP.get(bit.ShapeName, "Cylindrical")
|
||||
|
||||
toolitem["units"] = unitstring
|
||||
FreeCAD.ActiveDocument.removeObject(bit.Name)
|
||||
|
||||
toollist[toolNr] = toolitem
|
||||
|
||||
if len(toollist) > 0:
|
||||
with open(path, "w") as fp:
|
||||
fp.write(json.dumps(toollist, indent=2))
|
||||
|
||||
@@ -43,6 +43,7 @@ EXTERIOR1 = 2
|
||||
EXTERIOR2 = 3
|
||||
COLINEAR = 4
|
||||
TWIN = 5
|
||||
BORDERLINE = 6
|
||||
|
||||
if False:
|
||||
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
|
||||
@@ -196,7 +197,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp):
|
||||
"""Proxy class for Vcarve operation."""
|
||||
|
||||
def opFeatures(self, obj):
|
||||
"""opFeatures(obj) ... return all standard features and edges based geomtries"""
|
||||
"""opFeatures(obj) ... return all standard features and edges based geometries"""
|
||||
return (
|
||||
PathOp.FeatureTool
|
||||
| PathOp.FeatureHeights
|
||||
@@ -291,13 +292,19 @@ class ObjectVcarve(PathEngraveBase.ObjectOp):
|
||||
|
||||
voronoiWires = []
|
||||
for f in faces:
|
||||
vd = Path.Voronoi()
|
||||
vd = Path.Voronoi.Diagram()
|
||||
insert_many_wires(vd, f.Wires)
|
||||
|
||||
vd.construct()
|
||||
|
||||
for e in vd.Edges:
|
||||
e.Color = PRIMARY if e.isPrimary() else SECONDARY
|
||||
if e.isPrimary():
|
||||
if e.isBorderline():
|
||||
e.Color = BORDERLINE
|
||||
else:
|
||||
e.Color = PRIMARY
|
||||
else:
|
||||
e.Color = SECONDARY
|
||||
vd.colorExterior(EXTERIOR1)
|
||||
vd.colorExterior(
|
||||
EXTERIOR2,
|
||||
|
||||
@@ -465,7 +465,7 @@ def export(objectslist, filename, argstring):
|
||||
parsedElem = HEIDEN_Line(
|
||||
c.Parameters, Compensation, Feed, True, Spindle_Status, Cmd_Count
|
||||
)
|
||||
if parsedElem != None:
|
||||
if parsedElem is not None:
|
||||
POSTGCODE.append(parsedElem)
|
||||
|
||||
# Linear movement
|
||||
@@ -473,7 +473,7 @@ def export(objectslist, filename, argstring):
|
||||
parsedElem = HEIDEN_Line(
|
||||
c.Parameters, Compensation, Feed, False, "", Cmd_Count
|
||||
)
|
||||
if parsedElem != None:
|
||||
if parsedElem is not None:
|
||||
POSTGCODE.append(parsedElem)
|
||||
|
||||
# Arc movement
|
||||
@@ -481,7 +481,7 @@ def export(objectslist, filename, argstring):
|
||||
parsedElem = HEIDEN_Arc(
|
||||
c.Parameters, command, Compensation, Feed, False, "", Cmd_Count
|
||||
)
|
||||
if parsedElem != None:
|
||||
if parsedElem is not None:
|
||||
POSTGCODE.extend(parsedElem)
|
||||
|
||||
if command == "G80": # Reset Canned Cycles
|
||||
@@ -492,13 +492,13 @@ def export(objectslist, filename, argstring):
|
||||
# Drilling, Dwell Drilling, Peck Drilling
|
||||
if command == "G81" or command == "G82" or command == "G83":
|
||||
parsedElem = HEIDEN_Drill(obj, c.Parameters, command, Feed)
|
||||
if parsedElem != None:
|
||||
if parsedElem is not None:
|
||||
POSTGCODE.extend(parsedElem)
|
||||
|
||||
# Tool change
|
||||
if command == "M6":
|
||||
parsedElem = HEIDEN_ToolCall(obj)
|
||||
if parsedElem != None:
|
||||
if parsedElem is not None:
|
||||
POSTGCODE.append(parsedElem)
|
||||
|
||||
if COMPENSATION_DIFF_STATUS[0]: # Restore the compensation if removed
|
||||
@@ -666,9 +666,9 @@ def HEIDEN_Line(
|
||||
H_Line += " " + H_Line_Params[1][0]
|
||||
|
||||
# F parameter (check rapid o feed)
|
||||
if line_rapid == True:
|
||||
if line_rapid:
|
||||
H_Line_Params[1][1] = FEED_MAX_SPEED
|
||||
if MACHINE_USE_FMAX == True and line_rapid == True:
|
||||
if MACHINE_USE_FMAX and line_rapid:
|
||||
H_Line += " FMAX"
|
||||
else:
|
||||
if (
|
||||
@@ -837,9 +837,9 @@ def HEIDEN_Arc(
|
||||
H_ArcPoint += " " + H_Arc_Params[1][0]
|
||||
|
||||
# F parameter
|
||||
if arc_rapid == True:
|
||||
if arc_rapid:
|
||||
H_Arc_Params[1][1] = FEED_MAX_SPEED
|
||||
if MACHINE_USE_FMAX == True and arc_rapid == True:
|
||||
if MACHINE_USE_FMAX and arc_rapid:
|
||||
H_ArcPoint += " FMAX"
|
||||
else:
|
||||
if (
|
||||
@@ -961,7 +961,7 @@ def HEIDEN_Drill(
|
||||
else:
|
||||
drill_SafePoint = drill_Params["R"]
|
||||
# Surface equals to theoric start point of drilling
|
||||
if drill_Surface != None and drill_SafePoint > drill_Surface:
|
||||
if drill_Surface is not None and drill_SafePoint > drill_Surface:
|
||||
drill_Defs["DIST"] = drill_Surface - drill_SafePoint
|
||||
drill_StartPoint = drill_Surface
|
||||
else:
|
||||
@@ -1108,7 +1108,7 @@ def HEIDEN_LBL_Get(GetPoint=None, GetLevel=None, GetAddit=0):
|
||||
global STORED_LBL
|
||||
global LBLIZE_PATH_LEVEL
|
||||
|
||||
if GetPoint != None:
|
||||
if GetPoint is not None:
|
||||
if LBLIZE_PATH_LEVEL != GetLevel:
|
||||
LBLIZE_PATH_LEVEL = GetLevel
|
||||
if len(STORED_LBL) != 0 and len(STORED_LBL[-1][-1]) == 0:
|
||||
|
||||
@@ -431,7 +431,7 @@ def export(objectslist, filename, argstring):
|
||||
|
||||
if not MODAL or command != lastcommand:
|
||||
outstring.append(mappedCommand)
|
||||
# if MODAL == True:
|
||||
# if MODAL:
|
||||
# #\better: append iff MODAL == False
|
||||
# if command == lastcommand:
|
||||
# outstring.pop(0)
|
||||
|
||||
Reference in New Issue
Block a user