Path: Added Spiral cut pattern; Adjusted tooltip language

This commit is contained in:
Russell Johnson
2020-04-13 03:47:53 -05:00
parent c8ece0c437
commit 75ad65ecf1

View File

@@ -21,11 +21,7 @@
# * USA *
# * *
# ***************************************************************************
# * *
# * Additional modifications and contributions beginning 2019 *
# * by Russell Johnson <russ4262@gmail.com> 2020-04-10 11:46 CST *
# * *
# ***************************************************************************
from __future__ import print_function
@@ -44,7 +40,7 @@ try:
except ImportError:
msg = QtCore.QCoreApplication.translate("PathSurface", "This operation requires OpenCamLib to be installed.")
FreeCAD.Console.PrintError(msg + "\n")
raise
raise ImportError
# import sys
# sys.exit(msg)
@@ -132,7 +128,7 @@ class ObjectSurface(PathOp.ObjectOp):
("App::PropertyFloat", "CutterTilt", "Rotation",
QtCore.QT_TRANSLATE_NOOP("App::Property", "Stop index(angle) for rotational scan")),
("App::PropertyEnumeration", "DropCutterDir", "Rotation",
QtCore.QT_TRANSLATE_NOOP("App::Property", "The direction along which dropcutter lines are created")),
QtCore.QT_TRANSLATE_NOOP("App::Property", "Dropcutter lines are created parallel to this axis.")),
("App::PropertyVectorDistance", "DropCutterExtraOffset", "Rotation",
QtCore.QT_TRANSLATE_NOOP("App::Property", "Additional offset to the selected bounding box")),
("App::PropertyEnumeration", "RotationAxis", "Rotation",
@@ -161,7 +157,7 @@ class ObjectSurface(PathOp.ObjectOp):
QtCore.QT_TRANSLATE_NOOP("App::Property", "Ignore internal feature areas within a larger selected face.")),
("App::PropertyEnumeration", "BoundBox", "Clearing Options",
QtCore.QT_TRANSLATE_NOOP("App::Property", "Select the overall boundary for the operation. ")),
QtCore.QT_TRANSLATE_NOOP("App::Property", "Select the overall boundary for the operation.")),
("App::PropertyVectorDistance", "CircularCenterCustom", "Clearing Options",
QtCore.QT_TRANSLATE_NOOP("App::Property", "Set the start point for circular cut patterns.")),
("App::PropertyEnumeration", "CircularCenterAt", "Clearing Options",
@@ -208,7 +204,7 @@ class ObjectSurface(PathOp.ObjectOp):
'BoundBox': ['BaseBoundBox', 'Stock'],
'CircularCenterAt': ['CenterOfMass', 'CenterOfBoundBox', 'XminYmin', 'Custom'],
'CutMode': ['Conventional', 'Climb'],
'CutPattern': ['Line', 'Circular', 'CircularZigZag', 'ZigZag'], # Additional goals ['Offset', 'Spiral', 'ZigZagOffset', 'Grid', 'Triangle']
'CutPattern': ['Line', 'Circular', 'CircularZigZag', 'Spiral', 'ZigZag'], # Additional goals ['Offset', 'ZigZagOffset', 'Grid', 'Triangle']
'DropCutterDir': ['X', 'Y'],
'HandleMultipleFeatures': ['Collectively', 'Individually'],
'LayerMode': ['Single-pass', 'Multi-pass'],
@@ -227,7 +223,6 @@ class ObjectSurface(PathOp.ObjectOp):
if obj.CutPattern in ['Circular', 'CircularZigZag']:
P0 = 2
P2 = 0
R0 = 0
elif obj.ScanType == 'Rotational':
R2 = P0 = P2 = 2
R0 = 0
@@ -1687,6 +1682,16 @@ class ObjectSurface(PathOp.ObjectOp):
PathLog.debug('_planarMakePathGeom()')
GeoSet = list()
def getSpiralPoint(move, b, radAng):
x = b * radAng * math.cos(radAng)
y = b * radAng * math.sin(radAng)
return FreeCAD.Vector(x, y, 0.0).add(move)
def getOppositeSpiralPoint(move, b, radAng):
x = b * radAng * math.cos(radAng)
y = b * radAng * math.sin(radAng)
return FreeCAD.Vector(-1 * x, y, 0.0).add(move)
# Apply drop cutter extra offset and set the max and min XY area of the operation
xmin = faceShp.BoundBox.XMin
xmax = faceShp.BoundBox.XMax
@@ -1816,6 +1821,107 @@ class ObjectSurface(PathOp.ObjectOp):
GeoSet.append(circle)
# Efor
COM = cntr.Base
elif obj.CutPattern in ['Spiral']:
SEGS = list()
loopRadians = 0.0 # Used to keep track of complete loops/cycles
sumRadians = 0.0
loopCnt = 0
segCnt = 0
twoPi = 2.0 * math.pi
maxDist = halfLL
move = COM # FreeCAD.Vector(0.0, 0.0, 0.0) # Use to translate the center of the spiral
# Set tool properties and calculate cutout
effectiveCut = self.cutter.getDiameter() * float(obj.StepOver) / 100.0
cutOut = effectiveCut / twoPi
segLen = obj.SampleInterval.Value # CutterDiameter / 10.0 # SampleInterval.Value
stepAng = segLen / ((loopCnt + 1) * effectiveCut) # math.pi / 18.0 # 10 degrees
stopRadians = maxDist / cutOut
draw = True
lastPoint = FreeCAD.Vector(0.0, 0.0, 0.0)
if obj.CutPatternReversed:
if obj.CutMode == 'Conventional':
while draw:
radAng = sumRadians + stepAng
p1 = lastPoint
p2 = getOppositeSpiralPoint(move, cutOut, radAng) # cutOut is 'b' in the equation r = b * radAng
sumRadians += stepAng # Increment sumRadians
loopRadians += stepAng # Increment loopRadians
if loopRadians > twoPi:
loopCnt += 1
loopRadians -= twoPi
stepAng = segLen / ((loopCnt + 1) * effectiveCut) # adjust stepAng with each loop/cycle
segCnt += 1
lastPoint = p2
if sumRadians > stopRadians:
draw = False
# Create line and show in Object tree
lineSeg = Part.makeLine(p2, p1)
SEGS.append(lineSeg)
else:
while draw:
radAng = sumRadians + stepAng
p1 = lastPoint
p2 = getSpiralPoint(move, cutOut, radAng) # cutOut is 'b' in the equation r = b * radAng
sumRadians += stepAng # Increment sumRadians
loopRadians += stepAng # Increment loopRadians
if loopRadians > twoPi:
loopCnt += 1
loopRadians -= twoPi
stepAng = segLen / ((loopCnt + 1) * effectiveCut) # adjust stepAng with each loop/cycle
segCnt += 1
lastPoint = p2
if sumRadians > stopRadians:
draw = False
# Create line and show in Object tree
lineSeg = Part.makeLine(p2, p1)
SEGS.append(lineSeg)
# Eif
SEGS.reverse()
else:
if obj.CutMode == 'Climb':
while draw:
radAng = sumRadians + stepAng
p1 = lastPoint
p2 = getOppositeSpiralPoint(move, cutOut, radAng) # cutOut is 'b' in the equation r = b * radAng
sumRadians += stepAng # Increment sumRadians
loopRadians += stepAng # Increment loopRadians
if loopRadians > twoPi:
loopCnt += 1
loopRadians -= twoPi
stepAng = segLen / ((loopCnt + 1) * effectiveCut) # adjust stepAng with each loop/cycle
segCnt += 1
lastPoint = p2
if sumRadians > stopRadians:
draw = False
# Create line and show in Object tree
lineSeg = Part.makeLine(p1, p2)
SEGS.append(lineSeg)
else:
while draw:
radAng = sumRadians + stepAng
p1 = lastPoint
p2 = getSpiralPoint(move, cutOut, radAng) # cutOut is 'b' in the equation r = b * radAng
sumRadians += stepAng # Increment sumRadians
loopRadians += stepAng # Increment loopRadians
if loopRadians > twoPi:
loopCnt += 1
loopRadians -= twoPi
stepAng = segLen / ((loopCnt + 1) * effectiveCut) # adjust stepAng with each loop/cycle
segCnt += 1
lastPoint = p2
if sumRadians > stopRadians:
draw = False
# Create line and show in Object tree
lineSeg = Part.makeLine(p1, p2)
SEGS.append(lineSeg)
# Eif
spiral = Part.Wire([ls.Edges[0] for ls in SEGS])
GeoSet.append(spiral)
elif obj.CutPattern in ['Offset']:
pass
# Eif
if obj.CutPatternReversed is True:
@@ -1950,6 +2056,20 @@ class ObjectSurface(PathOp.ObjectOp):
stpOvr.append(scan)
if erFlg is False:
SCANS.append(stpOvr)
elif obj.CutPattern == 'Spiral':
stpOvr = list()
PNTSET = self._pathGeomToSpiralPointSet(obj, pathGeom)
for D in PNTSET:
for I in D:
if I == 'BRK':
stpOvr.append(I)
else:
# D format is ((p1, p2), (p3, p4))
(A, B) = I
stpOvr.append(self._planarDropCutScan(pdc, A, B))
SCANS.append(stpOvr)
stpOvr = list()
# Eif
return SCANS
@@ -2426,6 +2546,51 @@ class ObjectSurface(PathOp.ObjectOp):
return ARCS
def _pathGeomToSpiralPointSet(self, obj, compGeoShp):
'''_pathGeomToSpiralPointSet(obj, compGeoShp)...
Convert a compound set of sequential line segments to directional, connected groupings.'''
PathLog.debug('_pathGeomToSpiralPointSet()')
# Extract intersection line segments for return value as list()
LINES = list()
inLine = list()
lnCnt = 0
ec = len(compGeoShp.Edges)
start = 2
if obj.CutPatternReversed:
edg1 = compGeoShp.Edges[0] # Skip first edge, as it is the closing edge: center to outer tail
ec -= 1
start = 1
else:
edg1 = compGeoShp.Edges[1] # Skip first edge, as it is the closing edge: center to outer tail
p1 = FreeCAD.Vector(edg1.Vertexes[0].X, edg1.Vertexes[0].Y, 0.0)
p2 = FreeCAD.Vector(edg1.Vertexes[1].X, edg1.Vertexes[1].Y, 0.0)
tup = ((p1.x, p1.y), (p2.x, p2.y))
inLine.append(tup)
lst = p2
for ei in range(start, ec): # Skipped first edge, started with second edge above as edg1
edg = compGeoShp.Edges[ei] # Get edge for vertexes
sp = FreeCAD.Vector(edg.Vertexes[0].X, edg.Vertexes[0].Y, 0.0) # check point (first / middle point)
ep = FreeCAD.Vector(edg.Vertexes[1].X, edg.Vertexes[1].Y, 0.0) # end point
tup = ((sp.x, sp.y), (ep.x, ep.y))
if sp.sub(p2).Length < 0.000001:
inLine.append(tup)
else:
LINES.append(inLine) # Save inLine segments
lnCnt += 1
inLine = list() # reset container
inLine.append(tup)
p1 = sp
p2 = ep
# Efor
lnCnt += 1
LINES.append(inLine) # Save inLine segments
return LINES
def _planarDropCutScan(self, pdc, A, B):
#PNTS = list()
(x1, y1) = A