[PATH] Improved deburr
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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])
|
||||
|
||||
Reference in New Issue
Block a user