PathHelix: Fixes for clearance, non-aligned centers

The safe Z value was calculated with respect to the current hole, but
the tool should better be always retracted to the safe Z value with
respect to the first hole of a series of holes.

Another fix concerns the detection of holes-within-holes, previously it
was assumed that there the centers must align perfectly, this seems to
be the case only up to some numerical precision. Fixed by just allowing
any hole that is wholly contained in the first hole, even it is not
centered.
This commit is contained in:
Lorenz Hüdepohl 2016-06-09 23:48:28 +02:00
parent 20af62cb9e
commit 00226a9c47

View File

@ -103,11 +103,13 @@ def helix_cut(center, r_out, r_in, dr, zmax, zmin, dz, safe_z, tool_diameter, vf
if (zmax <= zmin): if (zmax <= zmin):
return return
out = "(helix_cut <{0}, {1}>, {2})".format(center[0], center[1], ", ".join(map(str, (r_out, r_in, dr, zmax, zmin, dz, safe_z, tool_diameter)))) out = "(helix_cut <{0}, {1}>, {2})".format(center[0], center[1],
", ".join(map(str, (r_out, r_in, dr, zmax, zmin, dz, safe_z, tool_diameter, vfeed, hfeed, direction, startside))))
x0, y0 = center x0, y0 = center
nz = int(ceil(2*(zmax - zmin)/dz)) nz = max(int(ceil((zmax - zmin)/dz)), 2)
dz = (zmax - zmin) / nz zi = linspace(zmax, zmin, 2 * nz + 1)
if dr > tool_diameter: if dr > tool_diameter:
FreeCAD.Console.PrintWarning("PathHelix: Warning, shortening dr to tool diameter!\n") FreeCAD.Console.PrintWarning("PathHelix: Warning, shortening dr to tool diameter!\n")
dr = tool_diameter dr = tool_diameter
@ -143,9 +145,12 @@ def helix_cut(center, r_out, r_in, dr, zmax, zmin, dz, safe_z, tool_diameter, vf
out += rapid(x=x0+r,y=y0) out += rapid(x=x0+r,y=y0)
out += rapid(z=zmax + tool_diameter) out += rapid(z=zmax + tool_diameter)
out += feed(z=zmax,f=vfeed) out += feed(z=zmax,f=vfeed)
for i in range(1,nz+2): z=zmin
out += arc(x0-r, y0, i=-r, j=0.0, z = max(zmax - (i - 0.5) * dz, zmin), f=hfeed) for i in range(1,nz+1):
out += arc(x0+r, y0, i=r, j=0.0, z = max(zmax - i * dz, zmin), f=hfeed) out += arc(x0-r, y0, i=-r, j=0.0, z = zi[2*i-1], f=hfeed)
out += arc(x0+r, y0, i= r, j=0.0, z = zi[2*i], f=hfeed)
out += arc(x0-r, y0, i=-r, j=0.0, z = zmin, f=hfeed)
out += arc(x0+r, y0, i=r, j=0.0, z = zmin, f=hfeed)
out += feed(z=zmax + tool_diameter, f=vfeed) out += feed(z=zmax + tool_diameter, f=vfeed)
out += rapid(z=safe_z) out += rapid(z=safe_z)
return out return out
@ -260,6 +265,7 @@ class ObjectPathHelix(object):
def execute(self,obj): def execute(self,obj):
from Part import Circle, Cylinder, Plane from Part import Circle, Cylinder, Plane
from math import sqrt
if obj.Base: if obj.Base:
if not obj.Active: if not obj.Active:
obj.Path = Path.Path("(helix cut operation inactive)") obj.Path = Path.Path("(helix cut operation inactive)")
@ -318,6 +324,7 @@ class ObjectPathHelix(object):
drill_jobs = [] drill_jobs = []
for base, cylinder in cylinders: for base, cylinder in cylinders:
zsafe = cylinder.BoundBox.ZMax + obj.Clearance.Value
xc, yc, zc = cylinder.Surface.Center xc, yc, zc = cylinder.Surface.Center
if obj.Recursive: if obj.Recursive:
@ -337,7 +344,7 @@ class ObjectPathHelix(object):
r = cylinder.Surface.Radius r = cylinder.Surface.Radius
if dz < 0: if dz < 0:
# This is a closed hole if the face connecting to the current cylinder at next_z has # This is a closed hole if the face connected to the current cylinder at next_z has
# the cylinder's edge as its OuterWire # the cylinder's edge as its OuterWire
closed = None closed = None
for face in base.Shape.Faces: for face in base.Shape.Faces:
@ -351,7 +358,7 @@ class ObjectPathHelix(object):
if closed is None: if closed is None:
raise Exception("Cannot determine if this cylinder is closed on the z = {0} side".format(next_z)) raise Exception("Cannot determine if this cylinder is closed on the z = {0} side".format(next_z))
jobs.append(dict(xc=xc, yc=yc, zmin=next_z, zmax=cur_z, r_out=r, r_in=0.0, closed=closed)) jobs.append(dict(xc=xc, yc=yc, zmin=next_z, zmax=cur_z, r_out=r, r_in=0.0, closed=closed, zsafe=zsafe))
elif dz > 0: elif dz > 0:
new_jobs = [] new_jobs = []
@ -379,11 +386,15 @@ class ObjectPathHelix(object):
if connected(other_edge, face): if connected(other_edge, face):
if isinstance(face.Surface, Plane): if isinstance(face.Surface, Plane):
faces.append(face) faces.append(face)
# should only be one
face, = faces face, = faces
for edge in face.Edges: for edge in face.Edges:
if not edge.isSame(other_edge): if not edge.isSame(other_edge):
for base, other_cylinder in connected_cylinders(base, edge): for base, other_cylinder in connected_cylinders(base, edge):
if other_cylinder.Surface.Center.x == xc and other_cylinder.Surface.Center.y == yc and other_cylinder.Surface.Radius < r: xo = other_cylinder.Surface.Center.x
yo = other_cylinder.Surface.Center.y
center_dist = sqrt((xo - xc)**2 + (yo - yc)**2)
if center_dist + other_cylinder.Surface.Radius < r:
cylinder = other_cylinder cylinder = other_cylinder
break break
@ -409,12 +420,12 @@ class ObjectPathHelix(object):
zmin = obj.FinalDepth.Value zmin = obj.FinalDepth.Value
else: else:
zmin = cylinder.BoundBox.ZMin - obj.ThroughDepth.Value zmin = cylinder.BoundBox.ZMin - obj.ThroughDepth.Value
drill_jobs.append(dict(xc=xc, yc=yc, zmin=zmin, zmax=zmax, r_out=cylinder.Surface.Radius, r_in=0.0)) drill_jobs.append(dict(xc=xc, yc=yc, zmin=zmin, zmax=zmax, r_out=cylinder.Surface.Radius, r_in=0.0, zsafe=zsafe))
for job in drill_jobs: for job in drill_jobs:
output += helix_cut((job["xc"], job["yc"]), job["r_out"], job["r_in"], obj.DeltaR.Value, output += helix_cut((job["xc"], job["yc"]), job["r_out"], job["r_in"], obj.DeltaR.Value,
job["zmax"], job["zmin"], obj.StepDown.Value, job["zmax"], job["zmin"], obj.StepDown.Value,
job["zmax"] + obj.Clearance.Value, tool.Diameter, job["zsafe"], tool.Diameter,
obj.VertFeed.Value, obj.HorizFeed.Value, obj.Direction, obj.StartSide) obj.VertFeed.Value, obj.HorizFeed.Value, obj.Direction, obj.StartSide)
output += '\n' output += '\n'