Merge branch 'master' into bugfix/path-invalid-base-geometry-robustness

This commit is contained in:
mlampert
2021-02-14 18:16:12 -08:00
committed by GitHub
22 changed files with 239 additions and 162 deletions

View File

@@ -34,6 +34,11 @@ import math
import area
from pivy import coin
# lazily loaded modules
from lazy_loader.lazy_loader import LazyLoader
Part = LazyLoader('Part', globals(), 'Part')
TechDraw = LazyLoader('TechDraw', globals(), 'TechDraw')
__doc__ = "Class and implementation of the Adaptive path operation."
def convertTo2d(pathArray):
@@ -399,14 +404,9 @@ def Execute(op,obj):
if obj.Tolerance < 0.001:
obj.Tolerance = 0.001
pathArray = []
for base, subs in obj.Base:
for sub in subs:
shape = base.Shape.getElement(sub)
for edge in shape.Edges:
pathArray.append([discretize(edge)])
# Get list of working edges for adaptive algorithm
pathArray = _get_working_edges(op, obj)
#pathArray=connectEdges(edges)
path2d = convertTo2d(pathArray)
stockPaths = []
@@ -529,6 +529,35 @@ def Execute(op,obj):
sceneClean()
def _get_working_edges(op, obj):
"""_get_working_edges(op, obj)...
Compile all working edges from the Base Geometry selection (obj.Base)
for the current operation.
Additional modifications to selected region(face), such as extensions,
should be placed within this function.
"""
pathArray = list()
for base, subs in obj.Base:
for sub in subs:
if obj.UseOutline:
face = base.Shape.getElement(sub)
zmin = face.BoundBox.ZMin
# get face outline with same method in PocketShape
wire = TechDraw.findShapeOutline(face, 1, FreeCAD.Vector(0.0, 0.0, 1.0))
shape = Part.Face(wire)
# translate to face height if necessary
if shape.BoundBox.ZMin != zmin:
shape.translate(FreeCAD.Vector(0.0, 0.0, zmin - shape.BoundBox.ZMin))
else:
shape = base.Shape.getElement(sub)
for edge in shape.Edges:
pathArray.append([discretize(edge)])
return pathArray
class PathAdaptive(PathOp.ObjectOp):
def opFeatures(self, obj):
'''opFeatures(obj) ... returns the OR'ed list of features used and supported by the operation.
@@ -574,6 +603,11 @@ class PathAdaptive(PathOp.ObjectOp):
obj.addProperty("App::PropertyAngle", "HelixConeAngle", "Adaptive", "Helix cone angle (degrees)")
obj.addProperty("App::PropertyLength", "HelixDiameterLimit", "Adaptive", "Limit helix entry diameter, if limit larger than tool diameter or 0, tool diameter is used")
if not hasattr(obj, "UseOutline"):
obj.addProperty("App::PropertyBool",
"UseOutline",
"Adaptive",
"Uses the outline of the base geometry.")
def opSetDefaultValues(self, obj, job):
obj.Side="Inside"
@@ -594,6 +628,7 @@ class PathAdaptive(PathOp.ObjectOp):
obj.StockToLeave = 0
obj.KeepToolDownRatio = 3.0
obj.UseHelixArcs = False
obj.UseOutline = False
def opExecute(self, obj):
'''opExecute(obj) ... called whenever the receiver needs to be recalculated.

View File

@@ -140,6 +140,11 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
form.FinishingProfile.setChecked(True)
formLayout.addRow(QtGui.QLabel("Finishing Profile"), form.FinishingProfile)
# Use outline checkbox
form.useOutline = QtGui.QCheckBox()
form.useOutline.setChecked(False)
formLayout.addRow(QtGui.QLabel("Use outline"), form.useOutline)
layout.addLayout(formLayout)
# stop button
@@ -170,6 +175,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
# signals.append(self.form.ProcessHoles.stateChanged)
signals.append(self.form.ForceInsideOut.stateChanged)
signals.append(self.form.FinishingProfile.stateChanged)
signals.append(self.form.useOutline.stateChanged)
signals.append(self.form.StopButton.toggled)
return signals
@@ -191,6 +197,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
# self.form.ProcessHoles.setChecked(obj.ProcessHoles)
self.form.ForceInsideOut.setChecked(obj.ForceInsideOut)
self.form.FinishingProfile.setChecked(obj.FinishingProfile)
self.form.useOutline.setChecked(obj.UseOutline)
self.setupToolController(obj, self.form.ToolController)
self.setupCoolant(obj, self.form.coolantController)
self.form.StopButton.setChecked(obj.Stopped)
@@ -221,6 +228,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
obj.ForceInsideOut = self.form.ForceInsideOut.isChecked()
obj.FinishingProfile = self.form.FinishingProfile.isChecked()
obj.UseOutline = self.form.useOutline.isChecked()
obj.Stopped = self.form.StopButton.isChecked()
if(obj.Stopped):
self.form.StopButton.setChecked(False) # reset the button

View File

@@ -284,29 +284,21 @@ def cmdsForEdge(edge, flip = False, useHelixForBSpline = True, segm = 50, hSpeed
else:
# We're dealing with a helix or a more complex shape and it has to get approximated
# by a number of straight segments
eStraight = Part.Edge(Part.LineSegment(p1, p3))
esP2 = eStraight.valueAt((eStraight.FirstParameter + eStraight.LastParameter)/2)
deviation = (p2 - esP2).Length
if isRoughly(deviation, 0):
return [ Path.Command('G1', {'X': p3.x, 'Y': p3.y, 'Z': p3.z}) ]
# at this point pixellation is all we can do
points = edge.discretize(Deflection=0.01)
if flip:
points = points[::-1]
commands = []
segments = int(math.ceil((deviation / eStraight.Length) * segm))
#print("**** pixellation with %d segments" % segments)
dParameter = (edge.LastParameter - edge.FirstParameter) / segments
# starting point
p0 = edge.valueAt(edge.LastParameter) if flip else edge.valueAt(edge.FirstParameter)
for i in range(0, segments):
if flip:
p = edge.valueAt(edge.LastParameter - (i + 1) * dParameter)
else:
p = edge.valueAt(edge.FirstParameter + (i + 1) * dParameter)
if hSpeed > 0 and vSpeed > 0:
params.update({'F': speedBetweenPoints(p0, p, hSpeed, vSpeed)})
cmd = Path.Command('G1', {'X': p.x, 'Y': p.y, 'Z': p.z})
#print("***** %s" % cmd)
commands.append(cmd)
p0 = p
if points:
p0 = points[0]
for p in points[1:]:
params = {'X': p.x, 'Y': p.y, 'Z': p.z}
if hSpeed > 0 and vSpeed > 0:
params['F'] = speedBetweenPoints(p0, p, hSpeed, vSpeed)
cmd = Path.Command('G1', params)
# print("***** {}".format(cmd))
commands.append(cmd)
p0 = p
#print commands
return commands
@@ -542,13 +534,18 @@ def flipEdge(edge):
flipped.buildFromPolesMultsKnots(poles, mults , knots, perio, degree, weights, ratio)
return Part.Edge(flipped)
elif type(edge.Curve) == Part.OffsetCurve:
return edge.reversed()
global OddsAndEnds # pylint: disable=global-statement
OddsAndEnds.append(edge)
PathLog.warning(translate('PathGeom', "%s not support for flipping") % type(edge.Curve))
PathLog.warning(translate('PathGeom', "%s not supported for flipping") % type(edge.Curve))
Wire = []
def flipWire(wire):
'''Flip the entire wire and all its edges so it is being processed the other way around.'''
Wire.append(wire)
edges = [flipEdge(e) for e in wire.Edges]
edges.reverse()
PathLog.debug(edges)