Merge pull request #26324 from tarman3/array_refactor_PathArray

CAM: Array - Refactor class PathArray
This commit is contained in:
sliptonic
2025-12-27 11:26:48 -06:00
committed by GitHub

View File

@@ -299,7 +299,7 @@ class PathArray:
def __init__(
self,
baseList,
base,
arrayType,
copies,
offsetVector,
@@ -308,33 +308,44 @@ class PathArray:
angle,
centre,
swapDirection,
jitterMagnitude=FreeCAD.Vector(0, 0, 0),
jitterPercent=0,
seed="FreeCAD",
jitterMagnitude,
jitterPercent,
seed,
):
self.baseList = list()
self.base = base
self.arrayType = arrayType # ['Linear1D', 'Linear2D', 'Polar']
self.copies = copies
self.offsetVector = offsetVector
self.copiesX = copiesX
self.copiesY = copiesY
self.angle = angle
self.centre = centre
self.polarAngle = angle
self.polarCentre = centre
self.swapDirection = swapDirection
self.jitterMagnitude = jitterMagnitude
self.jitterPercent = jitterPercent
self.seed = seed
if baseList:
if isinstance(baseList, list):
self.baseList = baseList
else:
self.baseList = [baseList]
def getPath(self):
"""getPath() ... Call this method on an instance of the class to generate and return
path data for the requested path array."""
# Private method
def _calculateJitter(self, pos):
"""_calculateJitter(pos) ...
Returns the position argument with a random vector shift applied."""
commands = []
random.seed(self.seed)
if self.arrayType == "Polar":
self.getPolarArray(commands)
elif self.arrayType == "Linear2D":
if self.swapDirection:
self.getLinear2DXYArray(commands)
else:
self.getLinear2DYXArray(commands)
else:
self.getLinear1DArray(commands)
return Path.Path(commands)
def calculateJitter(self, pos):
"""Returns the position argument with a random vector shift applied."""
if self.jitterPercent == 0:
pass
elif random.randint(0, 100) < self.jitterPercent:
@@ -343,117 +354,92 @@ class PathArray:
pos.z = pos.z + random.uniform(-self.jitterMagnitude.z, self.jitterMagnitude.z)
return pos
# Public method
def getPath(self):
"""getPath() ... Call this method on an instance of the class to generate and return
path data for the requested path array."""
def getLinear1DArray(self, commands):
"""Array type Linear1D"""
for i in range(self.copies):
pos = FreeCAD.Vector(
self.offsetVector.x * (i + 1),
self.offsetVector.y * (i + 1),
self.offsetVector.z * (i + 1),
)
pos = self.calculateJitter(pos)
base = self.baseList
for b in base:
if not b.isDerivedFrom("Path::Feature"):
return
if not b.Path:
return
for b in self.base:
pl = FreeCAD.Placement()
pl.move(pos)
path = PathUtils.getPathWithPlacement(b)
path = PathUtils.applyPlacementToPath(pl, path)
commands.extend(path.Commands)
b_tool_controller = toolController(b)
if not b_tool_controller:
return
# build copies
output = ""
random.seed(self.seed)
if self.arrayType == "Linear1D":
for i in range(self.copies):
pos = FreeCAD.Vector(
self.offsetVector.x * (i + 1),
self.offsetVector.y * (i + 1),
self.offsetVector.z * (i + 1),
)
pos = self._calculateJitter(pos)
for b in base:
pl = FreeCAD.Placement()
pl.move(pos)
np = Path.Path(
[cm.transform(pl) for cm in PathUtils.getPathWithPlacement(b).Commands]
def getLinear2DXYArray(self, commands):
"""Array type Linear2D with initial X direction"""
for i in range(self.copiesY + 1):
for j in range(self.copiesX + 1):
if (i % 2) == 0:
pos = FreeCAD.Vector(
self.offsetVector.x * j,
self.offsetVector.y * i,
self.offsetVector.z * i,
)
output += np.toGCode()
elif self.arrayType == "Linear2D":
if self.swapDirection:
for i in range(self.copiesY + 1):
for j in range(self.copiesX + 1):
if (i % 2) == 0:
pos = FreeCAD.Vector(
self.offsetVector.x * j,
self.offsetVector.y * i,
self.offsetVector.z * i,
)
else:
pos = FreeCAD.Vector(
self.offsetVector.x * (self.copiesX - j),
self.offsetVector.y * i,
self.offsetVector.z * i,
)
pos = self._calculateJitter(pos)
for b in base:
pl = FreeCAD.Placement()
# do not process the index 0,0. It will be processed by the base Paths themselves
if not (i == 0 and j == 0):
pl.move(pos)
np = Path.Path(
[
cm.transform(pl)
for cm in PathUtils.getPathWithPlacement(b).Commands
]
)
output += np.toGCode()
else:
for i in range(self.copiesX + 1):
for j in range(self.copiesY + 1):
if (i % 2) == 0:
pos = FreeCAD.Vector(
self.offsetVector.x * i,
self.offsetVector.y * j,
self.offsetVector.z * i,
)
else:
pos = FreeCAD.Vector(
self.offsetVector.x * i,
self.offsetVector.y * (self.copiesY - j),
self.offsetVector.z * i,
)
pos = self._calculateJitter(pos)
for b in base:
pl = FreeCAD.Placement()
# do not process the index 0,0. It will be processed by the base Paths themselves
if not (i == 0 and j == 0):
pl.move(pos)
np = Path.Path(
[
cm.transform(pl)
for cm in PathUtils.getPathWithPlacement(b).Commands
]
)
output += np.toGCode()
# Eif
else:
for i in range(self.copies):
for b in base:
ang = 360
if self.copies > 0:
ang = self.angle / self.copies * (1 + i)
else:
pos = FreeCAD.Vector(
self.offsetVector.x * (self.copiesX - j),
self.offsetVector.y * i,
self.offsetVector.z * i,
)
pos = self.calculateJitter(pos)
for b in self.base:
pl = FreeCAD.Placement()
pl.rotate(self.centre, FreeCAD.Vector(0, 0, 1), ang)
np = PathUtils.applyPlacementToPath(pl, PathUtils.getPathWithPlacement(b))
output += np.toGCode()
# index 0,0 will be processed by the base Paths themselves
if i != 0 or j != 0:
pl.move(pos)
path = PathUtils.getPathWithPlacement(b)
path = PathUtils.applyPlacementToPath(pl, path)
commands.extend(path.Commands)
# return output
return Path.Path(output)
def getLinear2DYXArray(self, commands):
"""Array type Linear2D with initial Y direction"""
for i in range(self.copiesX + 1):
for j in range(self.copiesY + 1):
if (i % 2) == 0:
pos = FreeCAD.Vector(
self.offsetVector.x * i,
self.offsetVector.y * j,
self.offsetVector.z * i,
)
else:
pos = FreeCAD.Vector(
self.offsetVector.x * i,
self.offsetVector.y * (self.copiesY - j),
self.offsetVector.z * i,
)
pos = self.calculateJitter(pos)
for b in self.base:
pl = FreeCAD.Placement()
# index 0,0 will be processed by the base Paths themselves
if i != 0 or j != 0:
pl.move(pos)
path = PathUtils.getPathWithPlacement(b)
path = PathUtils.applyPlacementToPath(pl, path)
commands.extend(path.Commands)
def getPolarArray(self, commands):
"""Array type Polar"""
for i in range(self.copies):
ang = 360
if self.copies > 0:
ang = self.polarAngle / self.copies * (1 + i)
# prepare placement for polar pattern
pl = FreeCAD.Placement()
pl.rotate(self.polarCentre, FreeCAD.Vector(0, 0, 1), ang)
for b in self.base:
path = PathUtils.getPathWithPlacement(b)
path = PathUtils.applyPlacementToPath(pl, path)
commands.extend(path.Commands)
class ViewProviderArray: