[PATH] Improved deburr

This commit is contained in:
Patrick F
2021-02-13 15:41:37 +01:00
parent f79075110a
commit c821b09c81
3 changed files with 54 additions and 21 deletions

View File

@@ -86,7 +86,7 @@ def toolDepthAndOffset(width, extraDepth, tool, printInfo):
extraOffset = -width if angle == 180 else (extraDepth / tan)
offset = toolOffset + extraOffset
return (depth, offset, suppressInfo)
return (depth, offset, extraOffset, suppressInfo)
class ObjectDeburr(PathEngraveBase.ObjectOp):
@@ -123,7 +123,7 @@ class ObjectDeburr(PathEngraveBase.ObjectOp):
if not hasattr(self, 'printInfo'):
self.printInfo = True
try:
(depth, offset, 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)
@@ -136,10 +136,13 @@ class ObjectDeburr(PathEngraveBase.ObjectOp):
self.basewires = [] # pylint: disable=attribute-defined-outside-init
self.adjusted_basewires = [] # pylint: disable=attribute-defined-outside-init
wires = []
for base, subs in obj.Base:
edges = []
basewires = []
max_h = -99999
radius_top = 0
radius_bottom = 0
for f in subs:
sub = base.Shape.getElement(f)
@@ -148,11 +151,24 @@ class ObjectDeburr(PathEngraveBase.ObjectOp):
edges.append(sub)
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:
if p0.Point.z > max_h:
max_h = p0.Point.z
# Find biggest radius for top/bottom
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:
radius_top = edge.Curve.Radius
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:
@@ -160,24 +176,44 @@ class ObjectDeburr(PathEngraveBase.ObjectOp):
if edge.Vertexes[0].Point.z < max_h:
if edge.Closed: # Circle
v = FreeCAD.Vector(edge.Curve.Center.x, edge.Curve.Center.y, max_h)
new_edge = Part.makeCircle(edge.Curve.Radius, v, FreeCAD.Vector(0, 0, 1))
# 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))
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:
# 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)
# New center
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)
# 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:
start_angle *= -1
if edge.Vertexes[1].Point.y < edge.Curve.Center.y:
end_angle *= -1
edge = Part.ArcOfCircle(Part.Circle(edge.Curve.Center, FreeCAD.Vector(0,0,1), edge.Curve.Radius), start_angle, end_angle).toShape()
# Create new arc
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
@@ -201,7 +237,7 @@ class ObjectDeburr(PathEngraveBase.ObjectOp):
for w in basewires:
self.adjusted_basewires.append(w)
wire = PathOpTools.offsetWire(w, base.Shape, offset, True) #, obj.Side)
wire = PathOpTools.offsetWire(w, base.Shape, offset, True)
if wire:
wires.append(wire)
@@ -214,6 +250,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)
@@ -250,5 +287,6 @@ def Create(name, obj=None):
'''Create(name) ... Creates and returns a Deburr operation.'''
if obj is None:
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name)
obj.Proxy = ObjectDeburr(obj, name)
return obj

View File

@@ -55,15 +55,6 @@ class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage):
return super(TaskPanelBaseGeometryPage, self)
def addBaseGeometry(self, selection):
#for sel in selection:
#if sel.HasSubObjects:
# selectively add some elements of the drawing to the Base
#for sub in sel.SubObjects:
# if isinstance(sub, Part.Face):
# if sub.normalAt(0, 0) != FreeCAD.Vector(0, 0, 1):
# PathLog.info(translate("Path", "Ignoring non-horizontal Face"))
# return
self.super().addBaseGeometry(selection)

View File

@@ -143,7 +143,7 @@ def orientWire(w, forward=True):
PathLog.track('orientWire - ok')
return wire
def offsetWire(wire, base, offset, forward):#, Side = None):
def offsetWire(wire, base, offset, forward):
'''offsetWire(wire, base, offset, forward) ... offsets the wire away from base and orients the wire accordingly.
The function tries to avoid most of the pitfalls of Part.makeOffset2D which is possible because all offsetting
happens in the XY plane.
@@ -158,14 +158,14 @@ def offsetWire(wire, base, offset, forward):#, Side = None):
# https://www.freecadweb.org/wiki/Part%20Offset2D
# it's easy to construct them manually though
z = -1 if forward else 1
edge = Part.makeCircle(curve.Radius + offset, curve.Center, FreeCAD.Vector(0, 0, z))
if base.isInside(edge.Vertexes[0].Point, offset/2, True):
new_edge = Part.makeCircle(curve.Radius + offset, curve.Center, FreeCAD.Vector(0, 0, z))
if base.isInside(new_edge.Vertexes[0].Point, offset/2, True):
if offset > curve.Radius or PathGeom.isRoughly(offset, curve.Radius):
# offsetting a hole by its own radius (or more) makes the hole vanish
return None
edge = Part.makeCircle(curve.Radius - offset, curve.Center, FreeCAD.Vector(0, 0, -z))
w = Part.Wire([edge])
return w
new_edge = Part.makeCircle(curve.Radius - offset, curve.Center, FreeCAD.Vector(0, 0, -z))
return Part.Wire([new_edge])
if Part.Circle == type(curve) and not wire.isClosed():
# Process arc segment
@@ -173,17 +173,21 @@ def offsetWire(wire, base, offset, forward):#, Side = None):
l1 = math.sqrt((edge.Vertexes[0].Point.x - curve.Center.x)**2 + (edge.Vertexes[0].Point.y - curve.Center.y)**2)
l2 = math.sqrt((edge.Vertexes[1].Point.x - curve.Center.x)**2 + (edge.Vertexes[1].Point.y - curve.Center.y)**2)
# Calculate angles based on x-axis (0 - PI/2)
start_angle = math.acos((edge.Vertexes[0].Point.x - curve.Center.x) / l1)
end_angle = math.acos((edge.Vertexes[1].Point.x - 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 < curve.Center.y:
start_angle *= -1
if edge.Vertexes[1].Point.y < curve.Center.y:
end_angle *= -1
# Inside / Outside
if base.isInside(edge.Vertexes[0].Point, offset/2, True):
offset *= -1
# Create new arc
edge = Part.ArcOfCircle(Part.Circle(curve.Center, FreeCAD.Vector(0,0,1), curve.Radius+offset), start_angle, end_angle).toShape()
return Part.Wire([edge])