Merge pull request #5410 from sliptonic/bug/translateDeburr
[Path] Bug/translate deburr, fixture, inspect, probe
This commit is contained in:
@@ -29,54 +29,68 @@ import PathScripts.PathOp as PathOp
|
||||
import PathScripts.PathOpTools as PathOpTools
|
||||
import math
|
||||
|
||||
from PySide import QtCore
|
||||
from PySide.QtCore import QT_TRANSLATE_NOOP
|
||||
|
||||
# lazily loaded modules
|
||||
from lazy_loader.lazy_loader import LazyLoader
|
||||
Part = LazyLoader('Part', globals(), 'Part')
|
||||
|
||||
Part = LazyLoader("Part", globals(), "Part")
|
||||
|
||||
__title__ = "Path Deburr Operation"
|
||||
__author__ = "sliptonic (Brad Collette), Schildkroet"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
__doc__ = "Deburr operation."
|
||||
|
||||
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
|
||||
# PathLog.trackModule(PathLog.thisModule())
|
||||
|
||||
if False:
|
||||
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
|
||||
PathLog.trackModule(PathLog.thisModule())
|
||||
else:
|
||||
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
|
||||
|
||||
# Qt translation handling
|
||||
def translate(context, text, disambig=None):
|
||||
return QtCore.QCoreApplication.translate(context, text, disambig)
|
||||
translate = FreeCAD.Qt.translate
|
||||
|
||||
|
||||
def toolDepthAndOffset(width, extraDepth, tool, printInfo):
|
||||
'''toolDepthAndOffset(width, extraDepth, tool) ... return tuple for given\n
|
||||
parameters.'''
|
||||
"""toolDepthAndOffset(width, extraDepth, tool) ... return tuple for given\n
|
||||
parameters."""
|
||||
|
||||
if not hasattr(tool, 'Diameter'):
|
||||
raise ValueError('Deburr requires tool with diameter\n')
|
||||
if not hasattr(tool, "Diameter"):
|
||||
raise ValueError("Deburr requires tool with diameter\n")
|
||||
|
||||
suppressInfo = False
|
||||
if hasattr(tool, 'CuttingEdgeAngle'):
|
||||
if hasattr(tool, "CuttingEdgeAngle"):
|
||||
angle = float(tool.CuttingEdgeAngle)
|
||||
if PathGeom.isRoughly(angle, 180) or PathGeom.isRoughly(angle, 0):
|
||||
angle = 180
|
||||
toolOffset = float(tool.Diameter) / 2
|
||||
else:
|
||||
if hasattr(tool, 'TipDiameter'):
|
||||
if hasattr(tool, "TipDiameter"):
|
||||
toolOffset = float(tool.TipDiameter) / 2
|
||||
elif hasattr(tool, 'FlatRadius'):
|
||||
elif hasattr(tool, "FlatRadius"):
|
||||
toolOffset = float(tool.FlatRadius)
|
||||
else:
|
||||
toolOffset = 0.0
|
||||
if printInfo and not suppressInfo:
|
||||
FreeCAD.Console.PrintMessage(translate('PathDeburr', "The selected tool has no FlatRadius and no TipDiameter property. Assuming {}\n".format("Endmill" if angle == 180 else "V-Bit")))
|
||||
FreeCAD.Console.PrintMessage(
|
||||
translate(
|
||||
"PathDeburr",
|
||||
"The selected tool has no FlatRadius and no TipDiameter property. Assuming {}\n".format(
|
||||
"Endmill" if angle == 180 else "V-Bit"
|
||||
),
|
||||
)
|
||||
)
|
||||
suppressInfo = True
|
||||
else:
|
||||
angle = 180
|
||||
toolOffset = float(tool.Diameter) / 2
|
||||
if printInfo:
|
||||
FreeCAD.Console.PrintMessage(translate('PathDeburr', 'The selected tool has no CuttingEdgeAngle property. Assuming Endmill\n'))
|
||||
FreeCAD.Console.PrintMessage(
|
||||
translate(
|
||||
"PathDeburr",
|
||||
"The selected tool has no CuttingEdgeAngle property. Assuming Endmill\n",
|
||||
)
|
||||
)
|
||||
suppressInfo = True
|
||||
|
||||
tan = math.tan(math.radians(angle / 2))
|
||||
@@ -90,40 +104,119 @@ def toolDepthAndOffset(width, extraDepth, tool, printInfo):
|
||||
|
||||
|
||||
class ObjectDeburr(PathEngraveBase.ObjectOp):
|
||||
'''Proxy class for Deburr operation.'''
|
||||
"""Proxy class for Deburr operation."""
|
||||
|
||||
def opFeatures(self, obj):
|
||||
return PathOp.FeatureTool | PathOp.FeatureHeights | PathOp.FeatureStepDown | PathOp.FeatureBaseEdges | PathOp.FeatureBaseFaces | PathOp.FeatureCoolant | PathOp.FeatureBaseGeometry
|
||||
return (
|
||||
PathOp.FeatureTool
|
||||
| PathOp.FeatureHeights
|
||||
| PathOp.FeatureStepDown
|
||||
| PathOp.FeatureBaseEdges
|
||||
| PathOp.FeatureBaseFaces
|
||||
| PathOp.FeatureCoolant
|
||||
| PathOp.FeatureBaseGeometry
|
||||
)
|
||||
|
||||
def initOperation(self, obj):
|
||||
PathLog.track(obj.Label)
|
||||
obj.addProperty('App::PropertyDistance', 'Width', 'Deburr',
|
||||
QtCore.QT_TRANSLATE_NOOP('PathDeburr', 'The desired width of the chamfer'))
|
||||
obj.addProperty('App::PropertyDistance', 'ExtraDepth', 'Deburr',
|
||||
QtCore.QT_TRANSLATE_NOOP('PathDeburr', 'The additional depth of the tool path'))
|
||||
obj.addProperty('App::PropertyEnumeration', 'Join', 'Deburr',
|
||||
QtCore.QT_TRANSLATE_NOOP('PathDeburr', 'How to join chamfer segments'))
|
||||
obj.Join = ['Round', 'Miter']
|
||||
obj.setEditorMode('Join', 2) # hide for now
|
||||
obj.addProperty('App::PropertyEnumeration', 'Direction', 'Deburr',
|
||||
QtCore.QT_TRANSLATE_NOOP('PathDeburr', 'Direction of Operation'))
|
||||
obj.Direction = ['CW', 'CCW']
|
||||
obj.addProperty('App::PropertyEnumeration', 'Side', 'Deburr',
|
||||
QtCore.QT_TRANSLATE_NOOP('PathDeburr', 'Side of Operation'))
|
||||
obj.Side = ['Outside', 'Inside']
|
||||
obj.setEditorMode('Side', 2) # Hide property, it's calculated by op
|
||||
obj.addProperty('App::PropertyInteger', 'EntryPoint', 'Deburr',
|
||||
QtCore.QT_TRANSLATE_NOOP('PathDeburr', 'Select the segment, there the operations starts'))
|
||||
obj.addProperty(
|
||||
"App::PropertyDistance",
|
||||
"Width",
|
||||
"Deburr",
|
||||
QT_TRANSLATE_NOOP("App::Property", "The desired width of the chamfer"),
|
||||
)
|
||||
obj.addProperty(
|
||||
"App::PropertyDistance",
|
||||
"ExtraDepth",
|
||||
"Deburr",
|
||||
QT_TRANSLATE_NOOP("App::Property", "The additional depth of the tool path"),
|
||||
)
|
||||
obj.addProperty(
|
||||
"App::PropertyEnumeration",
|
||||
"Join",
|
||||
"Deburr",
|
||||
QT_TRANSLATE_NOOP("App::Property", "How to join chamfer segments"),
|
||||
)
|
||||
# obj.Join = ["Round", "Miter"]
|
||||
obj.setEditorMode("Join", 2) # hide for now
|
||||
obj.addProperty(
|
||||
"App::PropertyEnumeration",
|
||||
"Direction",
|
||||
"Deburr",
|
||||
QT_TRANSLATE_NOOP("App::Property", "Direction of Operation"),
|
||||
)
|
||||
# obj.Direction = ["CW", "CCW"]
|
||||
obj.addProperty(
|
||||
"App::PropertyEnumeration",
|
||||
"Side",
|
||||
"Deburr",
|
||||
QT_TRANSLATE_NOOP("App::Property", "Side of Operation"),
|
||||
)
|
||||
obj.Side = ["Outside", "Inside"]
|
||||
obj.setEditorMode("Side", 2) # Hide property, it's calculated by op
|
||||
obj.addProperty(
|
||||
"App::PropertyInteger",
|
||||
"EntryPoint",
|
||||
"Deburr",
|
||||
QT_TRANSLATE_NOOP(
|
||||
"App::Property", "Select the segment, there the operations starts"
|
||||
),
|
||||
)
|
||||
|
||||
ENUMS = self.propertyEnumerations()
|
||||
for n in ENUMS:
|
||||
setattr(obj, n[0], n[1])
|
||||
|
||||
@classmethod
|
||||
def propertyEnumerations(self, dataType="data"):
|
||||
|
||||
"""opPropertyEnumerations(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", "CW"), "CW"),
|
||||
(translate("Path", "CCW"), "CCW"),
|
||||
], # this is the direction that the profile runs
|
||||
"Join": [
|
||||
(translate("PathDeburr", "Round"), "Round"),
|
||||
(translate("PathDeburr", "Miter"), "Miter"),
|
||||
], # this is the direction that the profile runs
|
||||
}
|
||||
|
||||
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 opOnDocumentRestored(self, obj):
|
||||
obj.setEditorMode('Join', 2) # hide for now
|
||||
obj.setEditorMode("Join", 2) # hide for now
|
||||
|
||||
def opExecute(self, obj):
|
||||
PathLog.track(obj.Label)
|
||||
if not hasattr(self, 'printInfo'):
|
||||
if not hasattr(self, "printInfo"):
|
||||
self.printInfo = True
|
||||
try:
|
||||
(depth, offset, extraOffset, suppressInfo) = toolDepthAndOffset(obj.Width.Value, obj.ExtraDepth.Value, self.tool, self.printInfo)
|
||||
(depth, offset, extraOffset, suppressInfo) = toolDepthAndOffset(
|
||||
obj.Width.Value, obj.ExtraDepth.Value, self.tool, self.printInfo
|
||||
)
|
||||
self.printInfo = not suppressInfo
|
||||
except ValueError as e:
|
||||
msg = "{} \n No path will be generated".format(e)
|
||||
@@ -147,13 +240,15 @@ class ObjectDeburr(PathEngraveBase.ObjectOp):
|
||||
for f in subs:
|
||||
sub = base.Shape.getElement(f)
|
||||
|
||||
if type(sub) == Part.Edge: # Edge
|
||||
if type(sub) == Part.Edge: # Edge
|
||||
edges.append(sub)
|
||||
|
||||
elif type(sub) == Part.Face and sub.normalAt(0, 0) != FreeCAD.Vector(0, 0, 1): # Angled face
|
||||
|
||||
elif type(sub) == Part.Face and sub.normalAt(0, 0) != FreeCAD.Vector(
|
||||
0, 0, 1
|
||||
): # Angled face
|
||||
# If an angled face is selected, the lower edge is projected to the height of the upper edge,
|
||||
# to simulate an edge
|
||||
|
||||
|
||||
# Find z value of upper edge
|
||||
for edge in sub.Edges:
|
||||
for p0 in edge.Vertexes:
|
||||
@@ -161,7 +256,7 @@ class ObjectDeburr(PathEngraveBase.ObjectOp):
|
||||
max_h = p0.Point.z
|
||||
|
||||
# Find biggest radius for top/bottom
|
||||
for edge in sub.Edges:
|
||||
for edge in sub.Edges:
|
||||
if Part.Circle == type(edge.Curve):
|
||||
if edge.Vertexes[0].Point.z == max_h:
|
||||
if edge.Curve.Radius > radius_top:
|
||||
@@ -169,63 +264,139 @@ class ObjectDeburr(PathEngraveBase.ObjectOp):
|
||||
else:
|
||||
if edge.Curve.Radius > radius_bottom:
|
||||
radius_bottom = edge.Curve.Radius
|
||||
|
||||
|
||||
# Search for lower edge and raise it to height of upper edge
|
||||
for edge in sub.Edges:
|
||||
if Part.Circle == type(edge.Curve): # Edge is a circle
|
||||
if Part.Circle == type(edge.Curve): # Edge is a circle
|
||||
if edge.Vertexes[0].Point.z < max_h:
|
||||
|
||||
if edge.Closed: # Circle
|
||||
|
||||
if edge.Closed: # Circle
|
||||
# New center
|
||||
center = FreeCAD.Vector(edge.Curve.Center.x, edge.Curve.Center.y, max_h)
|
||||
new_edge = Part.makeCircle(edge.Curve.Radius, center, FreeCAD.Vector(0, 0, 1))
|
||||
center = FreeCAD.Vector(
|
||||
edge.Curve.Center.x, edge.Curve.Center.y, max_h
|
||||
)
|
||||
new_edge = Part.makeCircle(
|
||||
edge.Curve.Radius,
|
||||
center,
|
||||
FreeCAD.Vector(0, 0, 1),
|
||||
)
|
||||
edges.append(new_edge)
|
||||
|
||||
|
||||
# Modify offset for inner angled faces
|
||||
if radius_bottom < radius_top:
|
||||
offset -= 2 * extraOffset
|
||||
|
||||
|
||||
break
|
||||
|
||||
else: # Arc
|
||||
if edge.Vertexes[0].Point.z == edge.Vertexes[1].Point.z:
|
||||
else: # Arc
|
||||
if (
|
||||
edge.Vertexes[0].Point.z
|
||||
== edge.Vertexes[1].Point.z
|
||||
):
|
||||
# Arc vertexes are on same layer
|
||||
l1 = math.sqrt((edge.Vertexes[0].Point.x - edge.Curve.Center.x)**2 + (edge.Vertexes[0].Point.y - edge.Curve.Center.y)**2)
|
||||
l2 = math.sqrt((edge.Vertexes[1].Point.x - edge.Curve.Center.x)**2 + (edge.Vertexes[1].Point.y - edge.Curve.Center.y)**2)
|
||||
|
||||
l1 = math.sqrt(
|
||||
(
|
||||
edge.Vertexes[0].Point.x
|
||||
- edge.Curve.Center.x
|
||||
)
|
||||
** 2
|
||||
+ (
|
||||
edge.Vertexes[0].Point.y
|
||||
- edge.Curve.Center.y
|
||||
)
|
||||
** 2
|
||||
)
|
||||
l2 = math.sqrt(
|
||||
(
|
||||
edge.Vertexes[1].Point.x
|
||||
- edge.Curve.Center.x
|
||||
)
|
||||
** 2
|
||||
+ (
|
||||
edge.Vertexes[1].Point.y
|
||||
- edge.Curve.Center.y
|
||||
)
|
||||
** 2
|
||||
)
|
||||
|
||||
# New center
|
||||
center = FreeCAD.Vector(edge.Curve.Center.x, edge.Curve.Center.y, max_h)
|
||||
center = FreeCAD.Vector(
|
||||
edge.Curve.Center.x,
|
||||
edge.Curve.Center.y,
|
||||
max_h,
|
||||
)
|
||||
|
||||
# Calculate angles based on x-axis (0 - PI/2)
|
||||
start_angle = math.acos((edge.Vertexes[0].Point.x - edge.Curve.Center.x) / l1)
|
||||
end_angle = math.acos((edge.Vertexes[1].Point.x - edge.Curve.Center.x) / l2)
|
||||
start_angle = math.acos(
|
||||
(
|
||||
edge.Vertexes[0].Point.x
|
||||
- edge.Curve.Center.x
|
||||
)
|
||||
/ l1
|
||||
)
|
||||
end_angle = math.acos(
|
||||
(
|
||||
edge.Vertexes[1].Point.x
|
||||
- edge.Curve.Center.x
|
||||
)
|
||||
/ l2
|
||||
)
|
||||
|
||||
# Angles are based on x-axis (Mirrored on x-axis) -> negative y value means negative angle
|
||||
if edge.Vertexes[0].Point.y < edge.Curve.Center.y:
|
||||
if (
|
||||
edge.Vertexes[0].Point.y
|
||||
< edge.Curve.Center.y
|
||||
):
|
||||
start_angle *= -1
|
||||
if edge.Vertexes[1].Point.y < edge.Curve.Center.y:
|
||||
if (
|
||||
edge.Vertexes[1].Point.y
|
||||
< edge.Curve.Center.y
|
||||
):
|
||||
end_angle *= -1
|
||||
|
||||
# Create new arc
|
||||
new_edge = Part.ArcOfCircle(Part.Circle(center, FreeCAD.Vector(0,0,1), edge.Curve.Radius), start_angle, end_angle).toShape()
|
||||
new_edge = Part.ArcOfCircle(
|
||||
Part.Circle(
|
||||
center,
|
||||
FreeCAD.Vector(0, 0, 1),
|
||||
edge.Curve.Radius,
|
||||
),
|
||||
start_angle,
|
||||
end_angle,
|
||||
).toShape()
|
||||
edges.append(new_edge)
|
||||
|
||||
|
||||
# Modify offset for inner angled faces
|
||||
if radius_bottom < radius_top:
|
||||
offset -= 2 * extraOffset
|
||||
|
||||
break
|
||||
|
||||
else: # Line
|
||||
if edge.Vertexes[0].Point.z == edge.Vertexes[1].Point.z and edge.Vertexes[0].Point.z < max_h:
|
||||
new_edge = Part.Edge(Part.LineSegment(FreeCAD.Vector(edge.Vertexes[0].Point.x, edge.Vertexes[0].Point.y, max_h), FreeCAD.Vector(edge.Vertexes[1].Point.x, edge.Vertexes[1].Point.y, max_h)))
|
||||
else: # Line
|
||||
if (
|
||||
edge.Vertexes[0].Point.z == edge.Vertexes[1].Point.z
|
||||
and edge.Vertexes[0].Point.z < max_h
|
||||
):
|
||||
new_edge = Part.Edge(
|
||||
Part.LineSegment(
|
||||
FreeCAD.Vector(
|
||||
edge.Vertexes[0].Point.x,
|
||||
edge.Vertexes[0].Point.y,
|
||||
max_h,
|
||||
),
|
||||
FreeCAD.Vector(
|
||||
edge.Vertexes[1].Point.x,
|
||||
edge.Vertexes[1].Point.y,
|
||||
max_h,
|
||||
),
|
||||
)
|
||||
)
|
||||
edges.append(new_edge)
|
||||
|
||||
|
||||
elif sub.Wires:
|
||||
basewires.extend(sub.Wires)
|
||||
|
||||
else: # Flat face
|
||||
|
||||
else: # Flat face
|
||||
basewires.append(Part.Wire(sub.Edges))
|
||||
|
||||
self.edges = edges # pylint: disable=attribute-defined-outside-init
|
||||
@@ -244,7 +415,7 @@ class ObjectDeburr(PathEngraveBase.ObjectOp):
|
||||
wires.append(wire)
|
||||
|
||||
# Set direction of op
|
||||
forward = (obj.Direction == 'CW')
|
||||
forward = obj.Direction == "CW"
|
||||
|
||||
# Set value of side
|
||||
obj.Side = side[0]
|
||||
@@ -258,7 +429,7 @@ class ObjectDeburr(PathEngraveBase.ObjectOp):
|
||||
while z + obj.StepDown.Value < depth:
|
||||
z = z + obj.StepDown.Value
|
||||
zValues.append(z)
|
||||
|
||||
|
||||
zValues.append(depth)
|
||||
PathLog.track(obj.Label, depth, zValues)
|
||||
|
||||
@@ -269,30 +440,30 @@ class ObjectDeburr(PathEngraveBase.ObjectOp):
|
||||
self.buildpathocc(obj, wires, zValues, True, forward, obj.EntryPoint)
|
||||
|
||||
def opRejectAddBase(self, obj, base, sub):
|
||||
'''The chamfer op can only deal with features of the base model, all others are rejected.'''
|
||||
"""The chamfer op can only deal with features of the base model, all others are rejected."""
|
||||
return base not in self.model
|
||||
|
||||
def opSetDefaultValues(self, obj, job):
|
||||
PathLog.track(obj.Label, job.Label)
|
||||
obj.Width = '1 mm'
|
||||
obj.ExtraDepth = '0.5 mm'
|
||||
obj.Join = 'Round'
|
||||
obj.setExpression('StepDown', '0 mm')
|
||||
obj.StepDown = '0 mm'
|
||||
obj.Direction = 'CW'
|
||||
obj.Width = "1 mm"
|
||||
obj.ExtraDepth = "0.5 mm"
|
||||
obj.Join = "Round"
|
||||
obj.setExpression("StepDown", "0 mm")
|
||||
obj.StepDown = "0 mm"
|
||||
obj.Direction = "CW"
|
||||
obj.Side = "Outside"
|
||||
obj.EntryPoint = 0
|
||||
|
||||
|
||||
def SetupProperties():
|
||||
setup = []
|
||||
setup.append('Width')
|
||||
setup.append('ExtraDepth')
|
||||
setup.append("Width")
|
||||
setup.append("ExtraDepth")
|
||||
return setup
|
||||
|
||||
|
||||
def Create(name, obj=None, parentJob=None):
|
||||
'''Create(name) ... Creates and returns a Deburr operation.'''
|
||||
"""Create(name) ... Creates and returns a Deburr operation."""
|
||||
if obj is None:
|
||||
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name)
|
||||
obj.Proxy = ObjectDeburr(obj, name, parentJob)
|
||||
|
||||
@@ -27,6 +27,7 @@ import PathScripts.PathGui as PathGui
|
||||
import PathScripts.PathLog as PathLog
|
||||
import PathScripts.PathOpGui as PathOpGui
|
||||
from PySide import QtCore, QtGui
|
||||
from PySide.QtCore import QT_TRANSLATE_NOOP
|
||||
|
||||
__title__ = "Path Deburr Operation UI"
|
||||
__author__ = "sliptonic (Brad Collette), Schildkroet"
|
||||
@@ -34,16 +35,18 @@ __url__ = "https://www.freecadweb.org"
|
||||
__doc__ = "Deburr operation page controller and command implementation."
|
||||
|
||||
|
||||
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
|
||||
# PathLog.trackModule(PathLog.thisModule())
|
||||
if False:
|
||||
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
|
||||
PathLog.trackModule(PathLog.thisModule())
|
||||
else:
|
||||
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
|
||||
|
||||
|
||||
def translate(context, text, disambig=None):
|
||||
return QtCore.QCoreApplication.translate(context, text, disambig)
|
||||
translate = FreeCAD.Qt.translate
|
||||
|
||||
|
||||
class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage):
|
||||
'''Enhanced base geometry page to also allow special base objects.'''
|
||||
"""Enhanced base geometry page to also allow special base objects."""
|
||||
|
||||
def super(self):
|
||||
return super(TaskPanelBaseGeometryPage, self)
|
||||
@@ -53,51 +56,69 @@ class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage):
|
||||
|
||||
|
||||
class TaskPanelOpPage(PathOpGui.TaskPanelPage):
|
||||
'''Page controller class for the Deburr operation.'''
|
||||
"""Page controller class for the Deburr operation."""
|
||||
|
||||
_ui_form = ":/panels/PageOpDeburrEdit.ui"
|
||||
|
||||
def getForm(self):
|
||||
return FreeCADGui.PySideUic.loadUi(":/panels/PageOpDeburrEdit.ui")
|
||||
form = FreeCADGui.PySideUic.loadUi(self._ui_form)
|
||||
comboToPropertyMap = [("direction", "Direction")]
|
||||
enumTups = PathDeburr.ObjectDeburr.propertyEnumerations(dataType="raw")
|
||||
|
||||
self.populateCombobox(form, enumTups, comboToPropertyMap)
|
||||
|
||||
return form
|
||||
|
||||
def initPage(self, obj):
|
||||
self.opImagePath = "{}Mod/Path/Images/Ops/{}".format(FreeCAD.getHomePath(), 'chamfer.svg') # pylint: disable=attribute-defined-outside-init
|
||||
self.opImage = QtGui.QPixmap(self.opImagePath) # pylint: disable=attribute-defined-outside-init
|
||||
self.opImagePath = "{}Mod/Path/Images/Ops/{}".format(
|
||||
FreeCAD.getHomePath(), "chamfer.svg"
|
||||
) # pylint: disable=attribute-defined-outside-init
|
||||
self.opImage = QtGui.QPixmap(
|
||||
self.opImagePath
|
||||
) # pylint: disable=attribute-defined-outside-init
|
||||
self.form.opImage.setPixmap(self.opImage)
|
||||
iconMiter = QtGui.QIcon(':/icons/edge-join-miter-not.svg')
|
||||
iconMiter.addFile(':/icons/edge-join-miter.svg', state=QtGui.QIcon.On)
|
||||
iconRound = QtGui.QIcon(':/icons/edge-join-round-not.svg')
|
||||
iconRound.addFile(':/icons/edge-join-round.svg', state=QtGui.QIcon.On)
|
||||
iconMiter = QtGui.QIcon(":/icons/edge-join-miter-not.svg")
|
||||
iconMiter.addFile(":/icons/edge-join-miter.svg", state=QtGui.QIcon.On)
|
||||
iconRound = QtGui.QIcon(":/icons/edge-join-round-not.svg")
|
||||
iconRound.addFile(":/icons/edge-join-round.svg", state=QtGui.QIcon.On)
|
||||
self.form.joinMiter.setIcon(iconMiter)
|
||||
self.form.joinRound.setIcon(iconRound)
|
||||
|
||||
def getFields(self, obj):
|
||||
PathGui.updateInputField(obj, 'Width', self.form.value_W)
|
||||
PathGui.updateInputField(obj, 'ExtraDepth', self.form.value_h)
|
||||
PathGui.updateInputField(obj, "Width", self.form.value_W)
|
||||
PathGui.updateInputField(obj, "ExtraDepth", self.form.value_h)
|
||||
if self.form.joinRound.isChecked():
|
||||
obj.Join = 'Round'
|
||||
obj.Join = "Round"
|
||||
elif self.form.joinMiter.isChecked():
|
||||
obj.Join = 'Miter'
|
||||
obj.Join = "Miter"
|
||||
|
||||
if obj.Direction != str(self.form.direction.currentText()):
|
||||
obj.Direction = str(self.form.direction.currentText())
|
||||
if obj.Direction != str(self.form.direction.currentData()):
|
||||
obj.Direction = str(self.form.direction.currentData())
|
||||
|
||||
self.updateToolController(obj, self.form.toolController)
|
||||
self.updateCoolant(obj, self.form.coolantController)
|
||||
|
||||
def setFields(self, obj):
|
||||
self.form.value_W.setText(FreeCAD.Units.Quantity(obj.Width.Value, FreeCAD.Units.Length).UserString)
|
||||
self.form.value_h.setText(FreeCAD.Units.Quantity(obj.ExtraDepth.Value, FreeCAD.Units.Length).UserString)
|
||||
self.form.value_W.setText(
|
||||
FreeCAD.Units.Quantity(obj.Width.Value, FreeCAD.Units.Length).UserString
|
||||
)
|
||||
self.form.value_h.setText(
|
||||
FreeCAD.Units.Quantity(
|
||||
obj.ExtraDepth.Value, FreeCAD.Units.Length
|
||||
).UserString
|
||||
)
|
||||
self.setupToolController(obj, self.form.toolController)
|
||||
self.setupCoolant(obj, self.form.coolantController)
|
||||
self.form.joinRound.setChecked('Round' == obj.Join)
|
||||
self.form.joinMiter.setChecked('Miter' == obj.Join)
|
||||
self.form.joinRound.setChecked("Round" == obj.Join)
|
||||
self.form.joinMiter.setChecked("Miter" == obj.Join)
|
||||
self.form.joinFrame.hide()
|
||||
self.selectInComboBox(obj.Direction, self.form.direction)
|
||||
|
||||
def updateWidth(self):
|
||||
PathGui.updateInputField(self.obj, 'Width', self.form.value_W)
|
||||
PathGui.updateInputField(self.obj, "Width", self.form.value_W)
|
||||
|
||||
def updateExtraDepth(self):
|
||||
PathGui.updateInputField(self.obj, 'ExtraDepth', self.form.value_h)
|
||||
PathGui.updateInputField(self.obj, "ExtraDepth", self.form.value_h)
|
||||
|
||||
def getSignalsForUpdate(self, obj):
|
||||
signals = []
|
||||
@@ -114,16 +135,20 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
|
||||
self.form.value_h.editingFinished.connect(self.updateExtraDepth)
|
||||
|
||||
def taskPanelBaseGeometryPage(self, obj, features):
|
||||
'''taskPanelBaseGeometryPage(obj, features) ... return page for adding base geometries.'''
|
||||
"""taskPanelBaseGeometryPage(obj, features) ... return page for adding base geometries."""
|
||||
return TaskPanelBaseGeometryPage(obj, features)
|
||||
|
||||
|
||||
Command = PathOpGui.SetupOperation('Deburr',
|
||||
PathDeburr.Create,
|
||||
TaskPanelOpPage,
|
||||
'Path_Deburr',
|
||||
QtCore.QT_TRANSLATE_NOOP("PathDeburr", "Deburr"),
|
||||
QtCore.QT_TRANSLATE_NOOP("PathDeburr", "Creates a Deburr Path along Edges or around Faces"),
|
||||
PathDeburr.SetupProperties)
|
||||
Command = PathOpGui.SetupOperation(
|
||||
"Deburr",
|
||||
PathDeburr.Create,
|
||||
TaskPanelOpPage,
|
||||
"Path_Deburr",
|
||||
QT_TRANSLATE_NOOP("Path_Deburr", "Deburr"),
|
||||
QT_TRANSLATE_NOOP(
|
||||
"Path_Deburr", "Creates a Deburr Path along Edges or around Faces"
|
||||
),
|
||||
PathDeburr.SetupProperties,
|
||||
)
|
||||
|
||||
FreeCAD.Console.PrintLog("Loading PathDeburrGui... done\n")
|
||||
|
||||
@@ -189,7 +189,7 @@ PathUtils.addToJob(obj)
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
# register the FreeCAD command
|
||||
FreeCADGui.addCommand("PathFixture", CommandPathFixture())
|
||||
FreeCADGui.addCommand("Path_Fixture", CommandPathFixture())
|
||||
|
||||
|
||||
FreeCAD.Console.PrintLog("Loading PathFixture... done\n")
|
||||
|
||||
@@ -27,19 +27,17 @@ from PySide import QtCore, QtGui
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
import Path
|
||||
from PySide.QtCore import QT_TRANSLATE_NOOP
|
||||
|
||||
|
||||
# Qt translation handling
|
||||
def translate(context, text, disambig=None):
|
||||
return QtCore.QCoreApplication.translate(context, text, disambig)
|
||||
translate = FreeCAD.Qt.translate
|
||||
|
||||
|
||||
class GCodeHighlighter(QtGui.QSyntaxHighlighter):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
|
||||
def convertcolor(c):
|
||||
return QtGui.QColor(int((c >> 24) & 0xFF), int((c >> 16) & 0xFF), int((c >> 8) & 0xFF))
|
||||
return QtGui.QColor(
|
||||
int((c >> 24) & 0xFF), int((c >> 16) & 0xFF), int((c >> 8) & 0xFF)
|
||||
)
|
||||
|
||||
super(GCodeHighlighter, self).__init__(parent)
|
||||
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Editor")
|
||||
@@ -63,19 +61,18 @@ class GCodeHighlighter(QtGui.QSyntaxHighlighter):
|
||||
self.highlightingRules = []
|
||||
numberFormat = QtGui.QTextCharFormat()
|
||||
numberFormat.setForeground(colors[0])
|
||||
self.highlightingRules.append(
|
||||
(QtCore.QRegExp("[\\-0-9\\.]"), numberFormat))
|
||||
self.highlightingRules.append((QtCore.QRegExp("[\\-0-9\\.]"), numberFormat))
|
||||
keywordFormat = QtGui.QTextCharFormat()
|
||||
keywordFormat.setForeground(colors[1])
|
||||
keywordFormat.setFontWeight(QtGui.QFont.Bold)
|
||||
keywordPatterns = ["\\bG[0-9]+\\b", "\\bM[0-9]+\\b"]
|
||||
self.highlightingRules.extend(
|
||||
[(QtCore.QRegExp(pattern), keywordFormat) for pattern in keywordPatterns])
|
||||
[(QtCore.QRegExp(pattern), keywordFormat) for pattern in keywordPatterns]
|
||||
)
|
||||
speedFormat = QtGui.QTextCharFormat()
|
||||
speedFormat.setFontWeight(QtGui.QFont.Bold)
|
||||
speedFormat.setForeground(colors[2])
|
||||
self.highlightingRules.append(
|
||||
(QtCore.QRegExp("\\bF[0-9\\.]+\\b"), speedFormat))
|
||||
self.highlightingRules.append((QtCore.QRegExp("\\bF[0-9\\.]+\\b"), speedFormat))
|
||||
|
||||
def highlightBlock(self, text):
|
||||
|
||||
@@ -93,7 +90,7 @@ class GCodeEditorDialog(QtGui.QDialog):
|
||||
|
||||
def __init__(self, PathObj, parent=FreeCADGui.getMainWindow()):
|
||||
self.PathObj = PathObj.Path
|
||||
if hasattr(PathObj, 'ToolController'):
|
||||
if hasattr(PathObj, "ToolController"):
|
||||
self.tool = PathObj.ToolController.Tool
|
||||
else:
|
||||
self.tool = None
|
||||
@@ -103,10 +100,19 @@ class GCodeEditorDialog(QtGui.QDialog):
|
||||
|
||||
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path")
|
||||
c = p.GetUnsigned("DefaultHighlightPathColor", 4286382335)
|
||||
Q = QtGui.QColor(int((c >> 24) & 0xFF), int((c >> 16) & 0xFF), int((c >> 8) & 0xFF))
|
||||
highlightcolor = (Q.red() / 255., Q.green() / 255., Q.blue() / 255., Q.alpha() / 255.)
|
||||
Q = QtGui.QColor(
|
||||
int((c >> 24) & 0xFF), int((c >> 16) & 0xFF), int((c >> 8) & 0xFF)
|
||||
)
|
||||
highlightcolor = (
|
||||
Q.red() / 255.0,
|
||||
Q.green() / 255.0,
|
||||
Q.blue() / 255.0,
|
||||
Q.alpha() / 255.0,
|
||||
)
|
||||
|
||||
self.selectionobj = FreeCAD.ActiveDocument.addObject("Path::Feature", "selection")
|
||||
self.selectionobj = FreeCAD.ActiveDocument.addObject(
|
||||
"Path::Feature", "selection"
|
||||
)
|
||||
self.selectionobj.ViewObject.LineWidth = 4
|
||||
self.selectionobj.ViewObject.NormalColor = highlightcolor
|
||||
|
||||
@@ -123,14 +129,21 @@ class GCodeEditorDialog(QtGui.QDialog):
|
||||
|
||||
# Note
|
||||
lab = QtGui.QLabel()
|
||||
lab.setText(translate("Path_Inspect", "<b>Note</b>: Pressing OK will commit any change you make above to the object, but if the object is parametric, these changes will be overridden on recompute."))
|
||||
lab.setText(
|
||||
translate(
|
||||
"Path_Inspect",
|
||||
"<b>Note</b>: Pressing OK will commit any change you make above to the object, but if the object is parametric, these changes will be overridden on recompute.",
|
||||
)
|
||||
)
|
||||
lab.setWordWrap(True)
|
||||
layout.addWidget(lab)
|
||||
|
||||
# OK and Cancel buttons
|
||||
self.buttons = QtGui.QDialogButtonBox(
|
||||
QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel,
|
||||
QtCore.Qt.Horizontal, self)
|
||||
QtCore.Qt.Horizontal,
|
||||
self,
|
||||
)
|
||||
layout.addWidget(self.buttons)
|
||||
self.buttons.accepted.connect(self.accept)
|
||||
self.buttons.rejected.connect(self.reject)
|
||||
@@ -138,19 +151,19 @@ class GCodeEditorDialog(QtGui.QDialog):
|
||||
self.finished.connect(self.cleanup)
|
||||
|
||||
prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path")
|
||||
Xpos = int(prefs.GetString('inspecteditorX', "0"))
|
||||
Ypos = int(prefs.GetString('inspecteditorY', "0"))
|
||||
height = int(prefs.GetString('inspecteditorH', "500"))
|
||||
width = int(prefs.GetString('inspecteditorW', "600"))
|
||||
Xpos = int(prefs.GetString("inspecteditorX", "0"))
|
||||
Ypos = int(prefs.GetString("inspecteditorY", "0"))
|
||||
height = int(prefs.GetString("inspecteditorH", "500"))
|
||||
width = int(prefs.GetString("inspecteditorW", "600"))
|
||||
self.move(Xpos, Ypos)
|
||||
self.resize(width, height)
|
||||
|
||||
def cleanup(self):
|
||||
prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path")
|
||||
prefs.SetString('inspecteditorX', str(self.x()))
|
||||
prefs.SetString('inspecteditorY', str(self.y()))
|
||||
prefs.SetString('inspecteditorW', str(self.width()))
|
||||
prefs.SetString('inspecteditorH', str(self.height()))
|
||||
prefs.SetString("inspecteditorX", str(self.x()))
|
||||
prefs.SetString("inspecteditorY", str(self.y()))
|
||||
prefs.SetString("inspecteditorW", str(self.width()))
|
||||
prefs.SetString("inspecteditorH", str(self.height()))
|
||||
FreeCAD.ActiveDocument.removeObject(self.selectionobj.Name)
|
||||
|
||||
def highlightpath(self):
|
||||
@@ -191,7 +204,7 @@ class GCodeEditorDialog(QtGui.QDialog):
|
||||
p = Path.Path()
|
||||
firstrapid = Path.Command("G0", {"X": prevX, "Y": prevY, "Z": prevZ})
|
||||
|
||||
selectionpath = [firstrapid] + commands[startrow:endrow + 1]
|
||||
selectionpath = [firstrapid] + commands[startrow : endrow + 1]
|
||||
p.Commands = selectionpath
|
||||
self.selectionobj.Path = p
|
||||
|
||||
@@ -207,21 +220,28 @@ def show(obj):
|
||||
prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path")
|
||||
# default Max Highlighter Size = 512 Ko
|
||||
defaultMHS = 512 * 1024
|
||||
mhs = prefs.GetUnsigned('inspecteditorMaxHighlighterSize', defaultMHS)
|
||||
mhs = prefs.GetUnsigned("inspecteditorMaxHighlighterSize", defaultMHS)
|
||||
|
||||
if hasattr(obj, "Path"):
|
||||
if obj.Path:
|
||||
dia = GCodeEditorDialog(obj)
|
||||
dia.editor.setText(obj.Path.toGCode())
|
||||
gcodeSize = len(dia.editor.toPlainText())
|
||||
if (gcodeSize <= mhs):
|
||||
if gcodeSize <= mhs:
|
||||
# because of poor performance, syntax highlighting is
|
||||
# limited to mhs octets (default 512 KB).
|
||||
# It seems than the response time curve has an inflexion near 500 KB
|
||||
# beyond 500 KB, the response time increases exponentially.
|
||||
dia.highlighter = GCodeHighlighter(dia.editor.document())
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage(translate("Path", "GCode size too big ({} o), disabling syntax highlighter.".format(gcodeSize)))
|
||||
FreeCAD.Console.PrintMessage(
|
||||
translate(
|
||||
"Path",
|
||||
"GCode size too big ({} o), disabling syntax highlighter.".format(
|
||||
gcodeSize
|
||||
),
|
||||
)
|
||||
)
|
||||
result = dia.exec_()
|
||||
# exec_() returns 0 or 1 depending on the button pressed (Ok or
|
||||
# Cancel)
|
||||
@@ -234,12 +254,15 @@ def show(obj):
|
||||
|
||||
|
||||
class CommandPathInspect:
|
||||
|
||||
def GetResources(self):
|
||||
return {'Pixmap': 'Path_Inspect',
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Inspect", "Inspect G-code"),
|
||||
'Accel': "P, I",
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Inspect", "Inspects the G-code contents of a path")}
|
||||
return {
|
||||
"Pixmap": "Path_Inspect",
|
||||
"MenuText": QT_TRANSLATE_NOOP("Path_Inspect", "Inspect G-code"),
|
||||
"Accel": "P, I",
|
||||
"ToolTip": QT_TRANSLATE_NOOP(
|
||||
"Path_Inspect", "Inspects the G-code contents of a path"
|
||||
),
|
||||
}
|
||||
|
||||
def IsActive(self):
|
||||
if FreeCAD.ActiveDocument is not None:
|
||||
@@ -253,19 +276,26 @@ class CommandPathInspect:
|
||||
selection = FreeCADGui.Selection.getSelection()
|
||||
if len(selection) != 1:
|
||||
FreeCAD.Console.PrintError(
|
||||
translate("Path_Inspect", "Please select exactly one path object") + "\n")
|
||||
translate("Path_Inspect", "Please select exactly one path object")
|
||||
+ "\n"
|
||||
)
|
||||
return
|
||||
if not(selection[0].isDerivedFrom("Path::Feature")):
|
||||
if not (selection[0].isDerivedFrom("Path::Feature")):
|
||||
FreeCAD.Console.PrintError(
|
||||
translate("Path_Inspect", "Please select exactly one path object") + "\n")
|
||||
translate("Path_Inspect", "Please select exactly one path object")
|
||||
+ "\n"
|
||||
)
|
||||
return
|
||||
|
||||
# if everything is ok, execute
|
||||
FreeCADGui.addModule("PathScripts.PathInspect")
|
||||
FreeCADGui.doCommand(
|
||||
'PathScripts.PathInspect.show(FreeCAD.ActiveDocument.' + selection[0].Name + ')')
|
||||
"PathScripts.PathInspect.show(FreeCAD.ActiveDocument."
|
||||
+ selection[0].Name
|
||||
+ ")"
|
||||
)
|
||||
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
# register the FreeCAD command
|
||||
FreeCADGui.addCommand('Path_Inspect', CommandPathInspect())
|
||||
FreeCADGui.addCommand("Path_Inspect", CommandPathInspect())
|
||||
|
||||
@@ -27,8 +27,8 @@ import Path
|
||||
import PathScripts.PathLog as PathLog
|
||||
import PathScripts.PathOp as PathOp
|
||||
import PathScripts.PathUtils as PathUtils
|
||||
from PySide.QtCore import QT_TRANSLATE_NOOP
|
||||
|
||||
from PySide import QtCore
|
||||
|
||||
__title__ = "Path Probing Operation"
|
||||
__author__ = "sliptonic (Brad Collette)"
|
||||
@@ -42,63 +42,106 @@ else:
|
||||
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
|
||||
|
||||
|
||||
# Qt translation handling
|
||||
def translate(context, text, disambig=None):
|
||||
return QtCore.QCoreApplication.translate(context, text, disambig)
|
||||
|
||||
|
||||
class ObjectProbing(PathOp.ObjectOp):
|
||||
'''Proxy object for Probing operation.'''
|
||||
"""Proxy object for Probing operation."""
|
||||
|
||||
def opFeatures(self, obj):
|
||||
'''opFeatures(obj) ... Probing works on the stock object.'''
|
||||
"""opFeatures(obj) ... Probing works on the stock object."""
|
||||
return PathOp.FeatureDepths | PathOp.FeatureHeights | PathOp.FeatureTool
|
||||
|
||||
def initOperation(self, obj):
|
||||
obj.addProperty("App::PropertyLength", "Xoffset", "Probe", QtCore.QT_TRANSLATE_NOOP("App::Property", "X offset between tool and probe"))
|
||||
obj.addProperty("App::PropertyLength", "Yoffset", "Probe", QtCore.QT_TRANSLATE_NOOP("App::Property", "Y offset between tool and probe"))
|
||||
obj.addProperty("App::PropertyInteger", "PointCountX", "Probe", QtCore.QT_TRANSLATE_NOOP("App::Property", "Number of points to probe in X direction"))
|
||||
obj.addProperty("App::PropertyInteger", "PointCountY", "Probe", QtCore.QT_TRANSLATE_NOOP("App::Property", "Number of points to probe in Y direction"))
|
||||
obj.addProperty("App::PropertyFile", "OutputFileName", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "The output location for the probe data to be written"))
|
||||
obj.addProperty(
|
||||
"App::PropertyLength",
|
||||
"Xoffset",
|
||||
"Probe",
|
||||
QT_TRANSLATE_NOOP("App::Property", "X offset between tool and probe"),
|
||||
)
|
||||
obj.addProperty(
|
||||
"App::PropertyLength",
|
||||
"Yoffset",
|
||||
"Probe",
|
||||
QT_TRANSLATE_NOOP("App::Property", "Y offset between tool and probe"),
|
||||
)
|
||||
obj.addProperty(
|
||||
"App::PropertyInteger",
|
||||
"PointCountX",
|
||||
"Probe",
|
||||
QT_TRANSLATE_NOOP(
|
||||
"App::Property", "Number of points to probe in X direction"
|
||||
),
|
||||
)
|
||||
obj.addProperty(
|
||||
"App::PropertyInteger",
|
||||
"PointCountY",
|
||||
"Probe",
|
||||
QT_TRANSLATE_NOOP(
|
||||
"App::Property", "Number of points to probe in Y direction"
|
||||
),
|
||||
)
|
||||
obj.addProperty(
|
||||
"App::PropertyFile",
|
||||
"OutputFileName",
|
||||
"Path",
|
||||
QT_TRANSLATE_NOOP(
|
||||
"App::Property", "The output location for the probe data to be written"
|
||||
),
|
||||
)
|
||||
|
||||
def nextpoint(self, startpoint=0.0, endpoint=0.0, count=3):
|
||||
curstep = 0
|
||||
dist = (endpoint - startpoint) / (count - 1)
|
||||
while curstep <= count-1:
|
||||
while curstep <= count - 1:
|
||||
yield startpoint + (curstep * dist)
|
||||
curstep += 1
|
||||
|
||||
def opExecute(self, obj):
|
||||
'''opExecute(obj) ... generate probe locations.'''
|
||||
"""opExecute(obj) ... generate probe locations."""
|
||||
PathLog.track()
|
||||
self.commandlist.append(Path.Command("(Begin Probing)"))
|
||||
|
||||
stock = PathUtils.findParentJob(obj).Stock
|
||||
bb = stock.Shape.BoundBox
|
||||
|
||||
openstring = '(PROBEOPEN {})'.format(obj.OutputFileName)
|
||||
openstring = "(PROBEOPEN {})".format(obj.OutputFileName)
|
||||
self.commandlist.append(Path.Command(openstring))
|
||||
self.commandlist.append(Path.Command("G0", {"Z": obj.ClearanceHeight.Value}))
|
||||
|
||||
for y in self.nextpoint(bb.YMin, bb.YMax, obj.PointCountY):
|
||||
for x in self.nextpoint(bb.XMin, bb.XMax, obj.PointCountX):
|
||||
self.commandlist.append(Path.Command("G0", {"X": x + obj.Xoffset.Value, "Y": y + obj.Yoffset.Value, "Z": obj.SafeHeight.Value}))
|
||||
self.commandlist.append(Path.Command("G38.2", {"Z": obj.FinalDepth.Value, "F": obj.ToolController.VertFeed.Value}))
|
||||
self.commandlist.append(
|
||||
Path.Command(
|
||||
"G0",
|
||||
{
|
||||
"X": x + obj.Xoffset.Value,
|
||||
"Y": y + obj.Yoffset.Value,
|
||||
"Z": obj.SafeHeight.Value,
|
||||
},
|
||||
)
|
||||
)
|
||||
self.commandlist.append(
|
||||
Path.Command(
|
||||
"G38.2",
|
||||
{
|
||||
"Z": obj.FinalDepth.Value,
|
||||
"F": obj.ToolController.VertFeed.Value,
|
||||
},
|
||||
)
|
||||
)
|
||||
self.commandlist.append(Path.Command("G0", {"Z": obj.SafeHeight.Value}))
|
||||
|
||||
self.commandlist.append(Path.Command("(PROBECLOSE)"))
|
||||
|
||||
def opSetDefaultValues(self, obj, job):
|
||||
'''opSetDefaultValues(obj, job) ... set default value for RetractHeight'''
|
||||
"""opSetDefaultValues(obj, job) ... set default value for RetractHeight"""
|
||||
|
||||
|
||||
def SetupProperties():
|
||||
setup = ['Xoffset', 'Yoffset', 'PointCountX', 'PointCountY', 'OutputFileName']
|
||||
setup = ["Xoffset", "Yoffset", "PointCountX", "PointCountY", "OutputFileName"]
|
||||
return setup
|
||||
|
||||
|
||||
def Create(name, obj=None, parentJob=None):
|
||||
'''Create(name) ... Creates and returns a Probing operation.'''
|
||||
"""Create(name) ... Creates and returns a Probing operation."""
|
||||
if obj is None:
|
||||
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name)
|
||||
proxy = ObjectProbing(obj, name, parentJob)
|
||||
|
||||
@@ -22,11 +22,13 @@
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
import PathGui as PGui # ensure Path/Gui/Resources are loaded
|
||||
import PathGui as PGui # ensure Path/Gui/Resources are loaded
|
||||
import PathScripts.PathProbe as PathProbe
|
||||
import PathScripts.PathOpGui as PathOpGui
|
||||
import PathScripts.PathGui as PathGui
|
||||
import PathScripts.PathLog as PathLog
|
||||
|
||||
from PySide.QtCore import QT_TRANSLATE_NOOP
|
||||
from PySide import QtCore, QtGui
|
||||
|
||||
__title__ = "Path Probing Operation UI"
|
||||
@@ -35,38 +37,46 @@ __url__ = "http://www.freecadweb.org"
|
||||
__doc__ = "Probing operation page controller and command implementation."
|
||||
|
||||
|
||||
# Qt translation handling
|
||||
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 TaskPanelOpPage(PathOpGui.TaskPanelPage):
|
||||
'''Page controller class for the Probing operation.'''
|
||||
"""Page controller class for the Probing operation."""
|
||||
|
||||
def getForm(self):
|
||||
'''getForm() ... returns UI'''
|
||||
"""getForm() ... returns UI"""
|
||||
return FreeCADGui.PySideUic.loadUi(":/panels/PageOpProbeEdit.ui")
|
||||
|
||||
def getFields(self, obj):
|
||||
'''getFields(obj) ... transfers values from UI to obj's proprties'''
|
||||
"""getFields(obj) ... transfers values from UI to obj's proprties"""
|
||||
self.updateToolController(obj, self.form.toolController)
|
||||
PathGui.updateInputField(obj, 'Xoffset', self.form.Xoffset)
|
||||
PathGui.updateInputField(obj, 'Yoffset', self.form.Yoffset)
|
||||
PathGui.updateInputField(obj, "Xoffset", self.form.Xoffset)
|
||||
PathGui.updateInputField(obj, "Yoffset", self.form.Yoffset)
|
||||
obj.PointCountX = self.form.PointCountX.value()
|
||||
obj.PointCountY = self.form.PointCountY.value()
|
||||
obj.OutputFileName = str(self.form.OutputFileName.text())
|
||||
|
||||
def setFields(self, obj):
|
||||
'''setFields(obj) ... transfers obj's property values to UI'''
|
||||
"""setFields(obj) ... transfers obj's property values to UI"""
|
||||
self.setupToolController(obj, self.form.toolController)
|
||||
self.form.Xoffset.setText(FreeCAD.Units.Quantity(obj.Xoffset.Value, FreeCAD.Units.Length).UserString)
|
||||
self.form.Yoffset.setText(FreeCAD.Units.Quantity(obj.Yoffset.Value, FreeCAD.Units.Length).UserString)
|
||||
self.form.Xoffset.setText(
|
||||
FreeCAD.Units.Quantity(obj.Xoffset.Value, FreeCAD.Units.Length).UserString
|
||||
)
|
||||
self.form.Yoffset.setText(
|
||||
FreeCAD.Units.Quantity(obj.Yoffset.Value, FreeCAD.Units.Length).UserString
|
||||
)
|
||||
self.form.OutputFileName.setText(obj.OutputFileName)
|
||||
self.form.PointCountX.setValue(obj.PointCountX)
|
||||
self.form.PointCountY.setValue(obj.PointCountY)
|
||||
|
||||
def getSignalsForUpdate(self, obj):
|
||||
'''getSignalsForUpdate(obj) ... return list of signals for updating obj'''
|
||||
"""getSignalsForUpdate(obj) ... return list of signals for updating obj"""
|
||||
signals = []
|
||||
signals.append(self.form.toolController.currentIndexChanged)
|
||||
signals.append(self.form.PointCountX.valueChanged)
|
||||
@@ -78,16 +88,25 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
|
||||
return signals
|
||||
|
||||
def SetOutputFileName(self):
|
||||
filename = QtGui.QFileDialog.getSaveFileName(self.form, translate("Path_Probe", "Select Output File"), None, translate("Path_Probe", "All Files (*.*)"))
|
||||
filename = QtGui.QFileDialog.getSaveFileName(
|
||||
self.form,
|
||||
translate("Path_Probe", "Select Output File"),
|
||||
None,
|
||||
translate("Path_Probe", "All Files (*.*)"),
|
||||
)
|
||||
if filename and filename[0]:
|
||||
self.obj.OutputFileName = str(filename[0])
|
||||
self.setFields(self.obj)
|
||||
|
||||
|
||||
Command = PathOpGui.SetupOperation('Probe', PathProbe.Create, TaskPanelOpPage,
|
||||
'Path_Probe',
|
||||
QtCore.QT_TRANSLATE_NOOP("Probe", "Probe"),
|
||||
QtCore.QT_TRANSLATE_NOOP("Probe", "Create a Probing Grid from a job stock"),
|
||||
PathProbe.SetupProperties)
|
||||
Command = PathOpGui.SetupOperation(
|
||||
"Probe",
|
||||
PathProbe.Create,
|
||||
TaskPanelOpPage,
|
||||
"Path_Probe",
|
||||
QtCore.QT_TRANSLATE_NOOP("Path_Probe", "Probe"),
|
||||
QtCore.QT_TRANSLATE_NOOP("Path_Probe", "Create a Probing Grid from a job stock"),
|
||||
PathProbe.SetupProperties,
|
||||
)
|
||||
|
||||
FreeCAD.Console.PrintLog("Loading PathProbeGui... done\n")
|
||||
|
||||
Reference in New Issue
Block a user