translation fixes

This commit is contained in:
sliptonic
2022-01-20 17:17:29 -06:00
parent b3e52226fe
commit 3cf2a2cb69
2 changed files with 278 additions and 134 deletions

View File

@@ -20,18 +20,17 @@
# * *
# ***************************************************************************
from Generators import helix_generator
from PathScripts.PathUtils import fmt
from PathScripts.PathUtils import sort_locations
from PySide.QtCore import QT_TRANSLATE_NOOP
import FreeCAD
import Part
import Path
import PathScripts.PathCircularHoleBase as PathCircularHoleBase
import PathScripts.PathLog as PathLog
import PathScripts.PathOp as PathOp
from PathScripts.PathUtils import fmt
from PathScripts.PathUtils import findParentJob
from PathScripts.PathUtils import sort_locations
from PySide import QtCore
__title__ = "Path Helix Drill Operation"
__author__ = "Lorenz Hüdepohl"
__url__ = "https://www.freecadweb.org"
@@ -42,167 +41,287 @@ __scriptVersion__ = "1b testing"
__lastModified__ = "2019-07-12 09:50 CST"
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
if False:
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
PathLog.trackModule(PathLog.thisModule())
else:
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
translate = FreeCAD.Qt.translate
class ObjectHelix(PathCircularHoleBase.ObjectOp):
'''Proxy class for Helix operations.'''
"""Proxy class for Helix operations."""
@classmethod
def helixOpPropertyEnumerations(self, dataType="data"):
"""helixOpPropertyEnumerations(dataType="data")... return property enumeration lists of specified dataType.
Args:
dataType = 'data', 'raw', 'translated'
Notes:
'data' is list of internal string literals used in code
'raw' is list of (translated_text, data_string) tuples
'translated' is list of translated string literals
"""
# Enumeration lists for App::PropertyEnumeration properties
enums = {
"Direction": [
(translate("Path_Helix", "CW"), "CW"),
(translate("Path_Helix", "CCW"), "CCW"),
], # this is the direction that the profile runs
"StartSide": [
(translate("PathProfile", "Outside"), "Outside"),
(translate("PathProfile", "Inside"), "Inside"),
], # side of profile that cutter is on in relation to direction of profile
}
if dataType == "raw":
return enums
data = list()
idx = 0 if dataType == "translated" else 1
PathLog.debug(enums)
for k, v in enumerate(enums):
# data[k] = [tup[idx] for tup in v]
data.append((v, [tup[idx] for tup in enums[v]]))
PathLog.debug(data)
return data
def circularHoleFeatures(self, obj):
'''circularHoleFeatures(obj) ... enable features supported by Helix.'''
return PathOp.FeatureStepDown | PathOp.FeatureBaseEdges | PathOp.FeatureBaseFaces
"""circularHoleFeatures(obj) ... enable features supported by Helix."""
return (
PathOp.FeatureStepDown | PathOp.FeatureBaseEdges | PathOp.FeatureBaseFaces
)
def initCircularHoleOperation(self, obj):
'''initCircularHoleOperation(obj) ... create helix specific properties.'''
obj.addProperty("App::PropertyEnumeration", "Direction", "Helix Drill", translate("PathHelix", "The direction of the circular cuts, ClockWise (CW), or CounterClockWise (CCW)"))
obj.Direction = ['CW', 'CCW']
"""initCircularHoleOperation(obj) ... create helix specific properties."""
obj.addProperty(
"App::PropertyEnumeration",
"Direction",
"Helix Drill",
QT_TRANSLATE_NOOP(
"App::Property",
"The direction of the circular cuts, ClockWise (CW), or CounterClockWise (CCW)",
),
)
# obj.Direction = ["CW", "CCW"]
obj.addProperty("App::PropertyEnumeration", "StartSide", "Helix Drill", translate("PathHelix", "Start cutting from the inside or outside"))
obj.StartSide = ['Inside', 'Outside']
obj.addProperty(
"App::PropertyEnumeration",
"StartSide",
"Helix Drill",
QT_TRANSLATE_NOOP(
"App::Property", "Start cutting from the inside or outside"
),
)
# obj.StartSide = ["Inside", "Outside"]
obj.addProperty("App::PropertyLength", "StepOver", "Helix Drill", translate("PathHelix", "Radius increment (must be smaller than tool diameter)"))
obj.addProperty("App::PropertyLength", "StartRadius", "Helix Drill", translate("PathHelix", "Starting Radius"))
obj.addProperty(
"App::PropertyPercent",
"StepOver",
"Helix Drill",
QT_TRANSLATE_NOOP(
"App::Property", "Percent of cutter diameter to step over on each pass"
),
)
obj.addProperty(
"App::PropertyLength",
"StartRadius",
"Helix Drill",
QT_TRANSLATE_NOOP("App::Property", "Starting Radius"),
)
ENUMS = self.helixOpPropertyEnumerations()
for n in ENUMS:
setattr(obj, n[0], n[1])
def opOnDocumentRestored(self, obj):
if not hasattr(obj, 'StartRadius'):
obj.addProperty("App::PropertyLength", "StartRadius", "Helix Drill", translate("PathHelix", "Starting Radius"))
if not hasattr(obj, "StartRadius"):
obj.addProperty(
"App::PropertyLength",
"StartRadius",
"Helix Drill",
QT_TRANSLATE_NOOP("App::Property", "Starting Radius"),
)
def circularHoleExecute(self, obj, holes):
'''circularHoleExecute(obj, holes) ... generate helix commands for each hole in holes'''
"""circularHoleExecute(obj, holes) ... generate helix commands for each hole in holes"""
PathLog.track()
self.commandlist.append(Path.Command('(helix cut operation)'))
self.commandlist.append(Path.Command("(helix cut operation)"))
self.commandlist.append(Path.Command('G0', {'Z': obj.ClearanceHeight.Value, 'F': self.vertRapid}))
self.commandlist.append(
Path.Command("G0", {"Z": obj.ClearanceHeight.Value, "F": self.vertRapid})
)
zsafe = max(baseobj.Shape.BoundBox.ZMax for baseobj, features in obj.Base) + obj.ClearanceHeight.Value
output = ''
zsafe = (
max(baseobj.Shape.BoundBox.ZMax for baseobj, features in obj.Base)
+ obj.ClearanceHeight.Value
)
output = ""
output += "G0 Z" + fmt(zsafe)
holes = sort_locations(holes, ['x', 'y'])
holes = sort_locations(holes, ["x", "y"])
tool = obj.ToolController.Tool
tooldiamter = (
tool.Diameter.Value if hasattr(tool.Diameter, "Value") else tool.Diameter
)
args = {
"edge": None,
"hole_radius": None,
"step_down": obj.StepDown.Value,
"step_over": obj.StepOver / 100,
"tool_diameter": tooldiamter,
"inner_radius": obj.StartRadius.Value,
"direction": obj.Direction,
"startAt": obj.StartSide,
}
for hole in holes:
output += self.helix_cut(obj, hole['x'], hole['y'], hole['r'] / 2, float(obj.StartRadius.Value), (float(obj.StepOver.Value) / 50.0) * self.radius)
args["hole_radius"] = hole["r"] / 2
startPoint = FreeCAD.Vector(hole["x"], hole["y"], obj.StartDepth.Value)
endPoint = FreeCAD.Vector(hole["x"], hole["y"], obj.FinalDepth.Value)
args["edge"] = Part.makeLine(startPoint, endPoint)
results = helix_generator.generate(**args)
for command in results:
self.commandlist.append(command)
# output += self.helix_cut(
# obj,
# hole["x"],
# hole["y"],
# hole["r"] / 2,
# float(obj.StartRadius.Value),
# (float(obj.StepOver.Value) / 50.0) * self.radius,
# )
PathLog.debug(output)
def helix_cut(self, obj, x0, y0, r_out, r_in, dr):
'''helix_cut(obj, x0, y0, r_out, r_in, dr) ... generate helix commands for specified hole.
x0, y0: coordinates of center
r_out, r_in: outer and inner radius of the hole
dr: step over radius value'''
from numpy import ceil, linspace
# def helix_cut(self, obj, x0, y0, r_out, r_in, dr):
# '''helix_cut(obj, x0, y0, r_out, r_in, dr) ... generate helix commands for specified hole.
# x0, y0: coordinates of center
# r_out, r_in: outer and inner radius of the hole
# dr: step over radius value'''
# from numpy import ceil, linspace
if (obj.StartDepth.Value <= obj.FinalDepth.Value):
return ""
# if (obj.StartDepth.Value <= obj.FinalDepth.Value):
# return ""
out = "(helix_cut <{0}, {1}>, {2})".format(
x0, y0, ", ".join(map(str, (r_out, r_in, dr, obj.StartDepth.Value,
obj.FinalDepth.Value, obj.StepDown.Value, obj.SafeHeight.Value,
self.radius, self.vertFeed, self.horizFeed, obj.Direction, obj.StartSide))))
# out = "(helix_cut <{0}, {1}>, {2})".format(
# x0, y0, ", ".join(map(str, (r_out, r_in, dr, obj.StartDepth.Value,
# obj.FinalDepth.Value, obj.StepDown.Value, obj.SafeHeight.Value,
# self.radius, self.vertFeed, self.horizFeed, obj.Direction, obj.StartSide))))
nz = max(int(ceil((obj.StartDepth.Value - obj.FinalDepth.Value) / obj.StepDown.Value)), 2)
zi = linspace(obj.StartDepth.Value, obj.FinalDepth.Value, 2 * nz + 1)
# nz = max(int(ceil((obj.StartDepth.Value - obj.FinalDepth.Value) / obj.StepDown.Value)), 2)
# zi = linspace(obj.StartDepth.Value, obj.FinalDepth.Value, 2 * nz + 1)
def xyz(x=None, y=None, z=None):
out = ""
if x is not None:
out += " X" + fmt(x)
if y is not None:
out += " Y" + fmt(y)
if z is not None:
out += " Z" + fmt(z)
return out
# def xyz(x=None, y=None, z=None):
# out = ""
# if x is not None:
# out += " X" + fmt(x)
# if y is not None:
# out += " Y" + fmt(y)
# if z is not None:
# out += " Z" + fmt(z)
# return out
def rapid(x=None, y=None, z=None):
return "G0" + xyz(x, y, z) + "\n"
# def rapid(x=None, y=None, z=None):
# return "G0" + xyz(x, y, z) + "\n"
def F(f=None):
return (" F" + fmt(f) if f else "")
# def F(f=None):
# return (" F" + fmt(f) if f else "")
def feed(x=None, y=None, z=None, f=None):
return "G1" + xyz(x, y, z) + F(f) + "\n"
# def feed(x=None, y=None, z=None, f=None):
# return "G1" + xyz(x, y, z) + F(f) + "\n"
def arc(x, y, i, j, z, f):
if obj.Direction == "CW":
code = "G2"
elif obj.Direction == "CCW":
code = "G3"
return code + " I" + fmt(i) + " J" + fmt(j) + " X" + fmt(x) + " Y" + fmt(y) + " Z" + fmt(z) + F(f) + "\n"
# def arc(x, y, i, j, z, f):
# if obj.Direction == "CW":
# code = "G2"
# elif obj.Direction == "CCW":
# code = "G3"
# return code + " I" + fmt(i) + " J" + fmt(j) + " X" + fmt(x) + " Y" + fmt(y) + " Z" + fmt(z) + F(f) + "\n"
def helix_cut_r(r):
arc_cmd = 'G2' if obj.Direction == 'CW' else 'G3'
out = ""
out += rapid(x=x0 + r, y=y0)
self.commandlist.append(Path.Command('G0', {'X': x0 + r, 'Y': y0, 'F': self.horizRapid}))
out += rapid(z=obj.StartDepth.Value + 2 * self.radius)
self.commandlist.append(Path.Command('G0', {'Z': obj.SafeHeight.Value, 'F': self.vertRapid}))
out += feed(z=obj.StartDepth.Value, f=self.vertFeed)
self.commandlist.append(Path.Command('G1', {'Z': obj.StartDepth.Value, 'F': self.vertFeed}))
# z = obj.FinalDepth.Value
for i in range(1, nz + 1):
out += arc(x0 - r, y0, i=-r, j=0.0, z=zi[2 * i - 1], f=self.horizFeed)
self.commandlist.append(Path.Command(arc_cmd, {'X': x0 - r, 'Y': y0, 'Z': zi[2 * i - 1], 'I': -r, 'J': 0.0, 'F': self.horizFeed}))
out += arc(x0 + r, y0, i=r, j=0.0, z=zi[2 * i], f=self.horizFeed)
self.commandlist.append(Path.Command(arc_cmd, {'X': x0 + r, 'Y': y0, 'Z': zi[2 * i], 'I': r, 'J': 0.0, 'F': self.horizFeed}))
out += arc(x0 - r, y0, i=-r, j=0.0, z=obj.FinalDepth.Value, f=self.horizFeed)
self.commandlist.append(Path.Command(arc_cmd, {'X': x0 - r, 'Y': y0, 'Z': obj.FinalDepth.Value, 'I': -r, 'J': 0.0, 'F': self.horizFeed}))
out += arc(x0 + r, y0, i=r, j=0.0, z=obj.FinalDepth.Value, f=self.horizFeed)
self.commandlist.append(Path.Command(arc_cmd, {'X': x0 + r, 'Y': y0, 'Z': obj.FinalDepth.Value, 'I': r, 'J': 0.0, 'F': self.horizFeed}))
out += feed(z=obj.StartDepth.Value + 2 * self.radius, f=self.vertFeed)
out += rapid(z=obj.SafeHeight.Value)
self.commandlist.append(Path.Command('G0', {'Z': obj.SafeHeight.Value, 'F': self.vertRapid}))
return out
# def helix_cut_r(r):
# arc_cmd = 'G2' if obj.Direction == 'CW' else 'G3'
# out = ""
# out += rapid(x=x0 + r, y=y0)
# self.commandlist.append(Path.Command('G0', {'X': x0 + r, 'Y': y0, 'F': self.horizRapid}))
# out += rapid(z=obj.StartDepth.Value + 2 * self.radius)
# self.commandlist.append(Path.Command('G0', {'Z': obj.SafeHeight.Value, 'F': self.vertRapid}))
# out += feed(z=obj.StartDepth.Value, f=self.vertFeed)
# self.commandlist.append(Path.Command('G1', {'Z': obj.StartDepth.Value, 'F': self.vertFeed}))
# # z = obj.FinalDepth.Value
# for i in range(1, nz + 1):
# out += arc(x0 - r, y0, i=-r, j=0.0, z=zi[2 * i - 1], f=self.horizFeed)
# self.commandlist.append(Path.Command(arc_cmd, {'X': x0 - r, 'Y': y0, 'Z': zi[2 * i - 1], 'I': -r, 'J': 0.0, 'F': self.horizFeed}))
# out += arc(x0 + r, y0, i=r, j=0.0, z=zi[2 * i], f=self.horizFeed)
# self.commandlist.append(Path.Command(arc_cmd, {'X': x0 + r, 'Y': y0, 'Z': zi[2 * i], 'I': r, 'J': 0.0, 'F': self.horizFeed}))
# out += arc(x0 - r, y0, i=-r, j=0.0, z=obj.FinalDepth.Value, f=self.horizFeed)
# self.commandlist.append(Path.Command(arc_cmd, {'X': x0 - r, 'Y': y0, 'Z': obj.FinalDepth.Value, 'I': -r, 'J': 0.0, 'F': self.horizFeed}))
# out += arc(x0 + r, y0, i=r, j=0.0, z=obj.FinalDepth.Value, f=self.horizFeed)
# self.commandlist.append(Path.Command(arc_cmd, {'X': x0 + r, 'Y': y0, 'Z': obj.FinalDepth.Value, 'I': r, 'J': 0.0, 'F': self.horizFeed}))
# out += feed(z=obj.StartDepth.Value + 2 * self.radius, f=self.vertFeed)
# out += rapid(z=obj.SafeHeight.Value)
# self.commandlist.append(Path.Command('G0', {'Z': obj.SafeHeight.Value, 'F': self.vertRapid}))
# return out
msg = None
if r_out < 0.0:
msg = "r_out < 0"
elif r_in > 0 and r_out - r_in < 2 * self.radius:
msg = "r_out - r_in = {0} is < tool diameter of {1}".format(r_out - r_in, 2 * self.radius)
elif r_in == 0.0 and not r_out > self.radius / 2.:
msg = "Cannot helix a hole of diameter {0} with a tool of diameter {1}".format(2 * r_out, 2 * self.radius)
elif obj.StartSide not in ["Inside", "Outside"]:
msg = "Invalid value for parameter 'obj.StartSide'"
elif r_in > 0:
out += "(annulus mode)\n"
r_out = r_out - self.radius
r_in = r_in + self.radius
if abs((r_out - r_in) / dr) < 1e-5:
radii = [(r_out + r_in) / 2]
else:
nr = max(int(ceil((r_out - r_in) / dr)), 2)
radii = linspace(r_out, r_in, nr)
elif r_out <= 2 * dr:
out += "(single helix mode)\n"
radii = [r_out - self.radius]
if radii[0] <= 0:
msg = "Cannot helix a hole of diameter {0} with a tool of diameter {1}".format(2 * r_out, 2 * self.radius)
else:
out += "(full hole mode)\n"
r_out = r_out - self.radius
r_in = dr / 2
# msg = None
# if r_out < 0.0:
# msg = "r_out < 0"
# elif r_in > 0 and r_out - r_in < 2 * self.radius:
# msg = "r_out - r_in = {0} is < tool diameter of {1}".format(r_out - r_in, 2 * self.radius)
# elif r_in == 0.0 and not r_out > self.radius / 2.:
# msg = "Cannot helix a hole of diameter {0} with a tool of diameter {1}".format(2 * r_out, 2 * self.radius)
# elif obj.StartSide not in ["Inside", "Outside"]:
# msg = "Invalid value for parameter 'obj.StartSide'"
# elif r_in > 0:
# out += "(annulus mode)\n"
# r_out = r_out - self.radius
# r_in = r_in + self.radius
# if abs((r_out - r_in) / dr) < 1e-5:
# radii = [(r_out + r_in) / 2]
# else:
# nr = max(int(ceil((r_out - r_in) / dr)), 2)
# radii = linspace(r_out, r_in, nr)
# elif r_out <= 2 * dr:
# out += "(single helix mode)\n"
# radii = [r_out - self.radius]
# if radii[0] <= 0:
# msg = "Cannot helix a hole of diameter {0} with a tool of diameter {1}".format(2 * r_out, 2 * self.radius)
# else:
# out += "(full hole mode)\n"
# r_out = r_out - self.radius
# r_in = dr / 2
nr = max(1 + int(ceil((r_out - r_in) / dr)), 2)
radii = [r for r in linspace(r_out, r_in, nr) if r > 0]
if not radii:
msg = "Cannot helix a hole of diameter {0} with a tool of diameter {1}".format(2 * r_out, 2 * self.radius)
# nr = max(1 + int(ceil((r_out - r_in) / dr)), 2)
# radii = [r for r in linspace(r_out, r_in, nr) if r > 0]
# if not radii:
# msg = "Cannot helix a hole of diameter {0} with a tool of diameter {1}".format(2 * r_out, 2 * self.radius)
if msg:
out += "(ERROR: Hole at {0}: ".format((x0, y0, obj.StartDepth.Value)) + msg + ")\n"
PathLog.error("{0} - ".format((x0, y0, obj.StartDepth.Value)) + msg)
return out
# if msg:
# out += "(ERROR: Hole at {0}: ".format((x0, y0, obj.StartDepth.Value)) + msg + ")\n"
# PathLog.error("{0} - ".format((x0, y0, obj.StartDepth.Value)) + msg)
# return out
if obj.StartSide == "Inside":
radii = radii[::-1]
# if obj.StartSide == "Inside":
# radii = radii[::-1]
for r in radii:
out += "(radius {0})\n".format(r)
out += helix_cut_r(r)
# for r in radii:
# out += "(radius {0})\n".format(r)
# out += helix_cut_r(r)
return out
# return out
def opSetDefaultValues(self, obj, job):
obj.Direction = "CW"
obj.StartSide = "Inside"
obj.StepOver = 100
# def opSetDefaultValues(self, obj, job):
# obj.Direction = "CW"
# obj.StartSide = "Inside"
# obj.StepOver = 100
def SetupProperties():
@@ -215,7 +334,7 @@ def SetupProperties():
def Create(name, obj=None, parentJob=None):
'''Create(name) ... Creates and returns a Helix operation.'''
"""Create(name) ... Creates and returns a Helix operation."""
if obj is None:
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name)
obj.Proxy = ObjectHelix(obj, name, parentJob)

View File

@@ -27,6 +27,9 @@ import PathScripts.PathCircularHoleBaseGui as PathCircularHoleBaseGui
import PathScripts.PathHelix as PathHelix
import PathScripts.PathLog as PathLog
import PathScripts.PathOpGui as PathOpGui
from PySide.QtCore import QT_TRANSLATE_NOOP
translate = FreeCAD.Qt.translate
from PySide import QtCore
@@ -46,7 +49,29 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage):
def getForm(self):
'''getForm() ... return UI'''
return FreeCADGui.PySideUic.loadUi(":/panels/PageOpHelixEdit.ui")
form = FreeCADGui.PySideUic.loadUi(":/panels/PageOpHelixEdit.ui")
comboToPropertyMap = [("startSide", "StartSide"), ("direction", "Direction")]
enumTups = PathHelix.ObjectHelix.helixOpPropertyEnumerations(dataType="raw")
self.populateCombobox(form, enumTups, comboToPropertyMap)
return form
def populateCombobox(self, form, enumTups, comboBoxesPropertyMap):
"""fillComboboxes(form, comboBoxesPropertyMap) ... populate comboboxes with translated enumerations
** comboBoxesPropertyMap will be unnecessary if UI files use strict combobox naming protocol.
Args:
form = UI form
enumTups = list of (translated_text, data_string) tuples
comboBoxesPropertyMap = list of (translated_text, data_string) tuples
"""
# Load appropriate enumerations in each combobox
for cb, prop in comboBoxesPropertyMap:
box = getattr(form, cb) # Get the combobox
box.clear() # clear the combobox
for text, data in enumTups[prop]: # load enumerations
box.addItem(text, data)
def getFields(self, obj):
'''getFields(obj) ... transfers values from UI to obj's proprties'''
@@ -88,8 +113,8 @@ Command = PathOpGui.SetupOperation('Helix',
PathHelix.Create,
TaskPanelOpPage,
'Path_Helix',
QtCore.QT_TRANSLATE_NOOP("Path_Helix", "Helix"),
QtCore.QT_TRANSLATE_NOOP("Path_Helix", "Creates a Path Helix object from a features of a base object"),
QT_TRANSLATE_NOOP("Path_Helix", "Helix"),
QT_TRANSLATE_NOOP("Path_Helix", "Creates a Path Helix object from a features of a base object"),
PathHelix.SetupProperties)
FreeCAD.Console.PrintLog("Loading PathHelixGui... done\n")