Merge pull request #8459 from cam72cam/gcode_apply_gcode_placement

Path: Apply Placement to simulated/exported GCode
This commit is contained in:
sliptonic
2023-04-15 10:43:37 -05:00
committed by GitHub
38 changed files with 160 additions and 115 deletions

View File

@@ -149,7 +149,8 @@ class PathBoundary:
):
return None
if len(self.baseOp.Path.Commands) == 0:
path = PathUtils.getPathWithPlacement(self.baseOp)
if len(path.Commands) == 0:
Path.Log.warning("No Path Commands for %s" % self.baseOp.Label)
return []
@@ -164,13 +165,13 @@ class PathBoundary:
)
self.strG0ZclearanceHeight = Path.Command("G0", {"Z": self.clearanceHeight})
cmd = self.baseOp.Path.Commands[0]
cmd = path.Commands[0]
pos = cmd.Placement.Base # bogus m/c position to create first edge
bogusX = True
bogusY = True
commands = [cmd]
lastExit = None
for cmd in self.baseOp.Path.Commands[1:]:
for cmd in path.Commands[1:]:
if cmd.Name in Path.Geom.CmdMoveAll:
if bogusX:
bogusX = "X" not in cmd.Parameters

View File

@@ -25,6 +25,7 @@ import FreeCAD
import Path
import Path.Base.Generator.dogboneII as dogboneII
import Path.Base.Language as PathLanguage
import PathScripts.PathUtils as PathUtils
import math
if False:
@@ -294,7 +295,7 @@ class Proxy(object):
dressingUpDogbone = hasattr(obj.Base, "BoneBlacklist")
if obj.Base and obj.Base.Path and obj.Base.Path.Commands:
for i, instr in enumerate(
PathLanguage.Maneuver.FromPath(obj.Base.Path).instr
PathLanguage.Maneuver.FromPath(PathUtils.getPathWithPlacement(obj.Base)).instr
):
# Path.Log.debug(f"instr: {instr}")
if instr.isMove():

View File

@@ -114,7 +114,7 @@ class ObjectDressup:
if obj.Base.isDerivedFrom("Path::Feature"):
if obj.Base.Path:
if obj.Base.Path.Commands:
pp = obj.Base.Path.Commands
pp = PathUtils.getPathWithPlacement(obj.Base).Commands
if len([i for i in pp if i.Name in Path.Geom.CmdMoveArc]) == 0:
pathlist = pp
else:

View File

@@ -910,7 +910,7 @@ class ObjectDressup(object):
self.length = 0
# boneIserted = False
for (i, thisCommand) in enumerate(obj.Base.Path.Commands):
for (i, thisCommand) in enumerate(PathUtils.getPathWithPlacement(obj.Base).Commands):
# if i > 14:
# if lastCommand:
# commands.append(lastCommand)

View File

@@ -388,7 +388,7 @@ class ObjectDressup:
queue = []
for curCommand in obj.Base.Path.Commands:
for curCommand in PathUtils.getPathWithPlacement(obj.Base).Commands:
replace = None
# don't worry about non-move commands, just add to output
if curCommand.Name not in movecommands + rapidcommands:

View File

@@ -188,7 +188,7 @@ class ObjectDressup:
+ "\n"
)
obj.Length = 0.1
self.wire, self.rapids = Path.Geom.wireForPath(obj.Base.Path)
self.wire, self.rapids = Path.Geom.wireForPath(PathUtils.getPathWithPlacement(obj.Base))
obj.Path = self.generateLeadInOutCurve(obj)
def getDirectionOfPath(self, obj):
@@ -556,7 +556,7 @@ class ObjectDressup:
layers = []
# Read in all commands
for curCommand in obj.Base.Path.Commands:
for curCommand in PathUtils.getPathWithPlacement(obj.Base).Commands:
Path.Log.debug("CurCMD: {}".format(curCommand))
if curCommand.Name not in movecommands + rapidcommands:
# Don't worry about non-move commands, just add to output

View File

@@ -222,7 +222,7 @@ class ObjectDressup:
self.angle = obj.Angle
self.method = obj.Method
self.wire, self.rapids = Path.Geom.wireForPath(obj.Base.Path)
self.wire, self.rapids = Path.Geom.wireForPath(PathUtils.getPathWithPlacement(obj.Base))
if self.method in ["RampMethod1", "RampMethod2", "RampMethod3"]:
self.outedges = self.generateRamps()
else:

View File

@@ -155,7 +155,7 @@ class ObjectDressup:
curveD = obj.ArcInterpolate.Value
if obj.interpSurface.isNull(): # No valid probe data. return unchanged path
obj.Path = obj.Base.Path
obj.Path = PathUtils.getPathWithPlacement(obj.Base)
return
surface = obj.interpSurface.toNurbs().Faces[0].Surface
@@ -163,8 +163,9 @@ class ObjectDressup:
if obj.Base:
if obj.Base.isDerivedFrom("Path::Feature"):
if obj.Base.Path:
if obj.Base.Path.Commands:
pathlist = obj.Base.Path.Commands
path = PathUtils.getPathWithPlacement(obj.Base)
if path.Commands:
pathlist = path.Commands
newcommandlist = []
currLocation = {"X": 0, "Y": 0, "Z": 0, "F": 0}

View File

@@ -674,7 +674,8 @@ class PathData:
def __init__(self, obj):
Path.Log.track(obj.Base.Name)
self.obj = obj
self.wire, rapid = Path.Geom.wireForPath(obj.Base.Path)
path = PathUtils.getPathWithPlacement(obj.Base)
self.wire, rapid = Path.Geom.wireForPath(path)
self.rapid = _RapidEdges(rapid)
if self.wire:
self.edges = self.wire.Edges
@@ -1255,7 +1256,7 @@ class ObjectTagDressup:
if not self.tags:
Path.Log.debug("execute - no tags")
obj.Path = obj.Base.Path
obj.Path = PathUtils.getPathWithPlacement(obj.Base)
return
try:
@@ -1264,7 +1265,7 @@ class ObjectTagDressup:
Path.Log.error(
"processing tags failed clearing all tags ... '%s'" % (e.args[0])
)
obj.Path = obj.Base.Path
obj.Path = PathUtils.getPathWithPlacement(obj.Base)
# update disabled in case there are some additional ones
disabled = copy.copy(self.obj.Disabled)

View File

@@ -182,7 +182,7 @@ class GCodeEditorDialog(QtGui.QDialog):
cursor.setPosition(ep)
endrow = cursor.blockNumber()
commands = self.PathObj.Commands
commands = PathUtils.getPathWithPlacement(self.PathObj).Commands
# Derive the starting position for the first selected command
prevX = prevY = prevZ = None

View File

@@ -24,6 +24,7 @@ import FreeCAD
import Path
import Path.Base.Util as PathUtil
import Path.Dressup.Utils as PathDressup
import PathScripts.PathUtils as PathUtils
import Path.Main.Job as PathJob
import PathGui
import PathSimulator
@@ -202,7 +203,7 @@ class PathSimulation:
self.icmd = 0
self.curpos = FreeCAD.Placement(self.initialPos, self.stdrot)
self.cutTool.Placement = self.curpos
self.opCommands = self.operation.Path.Commands
self.opCommands = PathUtils.getPathWithPlacement(self.operation).Commands
def SimulateMill(self):
self.job = self.jobs[self.taskForm.form.comboJobs.currentIndex()]
@@ -258,7 +259,7 @@ class PathSimulation:
return
self.busy = True
cmd = self.operation.Path.Commands[self.icmd]
cmd = self.opCommands[self.icmd]
pathSolid = None
if cmd.Name in ["G0"]:
@@ -302,7 +303,7 @@ class PathSimulation:
self.icmd += 1
self.iprogress += 1
self.UpdateProgress()
if self.icmd >= len(self.operation.Path.Commands):
if self.icmd >= len(self.opCommands):
self.ioperation += 1
if self.ioperation >= len(self.activeOps):
self.EndSimulation()

View File

@@ -24,6 +24,7 @@ import FreeCAD
import FreeCADGui
import Path
import PathScripts
import PathScripts.PathUtils as PathUtils
from Path.Dressup.Utils import toolController
from PySide import QtCore
import math
@@ -285,69 +286,6 @@ class PathArray:
else:
self.baseList = [baseList]
def rotatePath(self, path, angle, centre):
"""
Rotates Path around given centre vector
Only X and Y is considered
"""
CmdMoveRapid = ["G0", "G00"]
CmdMoveStraight = ["G1", "G01"]
CmdMoveCW = ["G2", "G02"]
CmdMoveCCW = ["G3", "G03"]
CmdDrill = ["G73", "G81", "G82", "G83"]
CmdMoveArc = CmdMoveCW + CmdMoveCCW
CmdMove = CmdMoveStraight + CmdMoveArc
commands = []
ang = angle / 180 * math.pi
currX = 0
currY = 0
for cmd in path.Commands:
if (
(cmd.Name in CmdMoveRapid)
or (cmd.Name in CmdMove)
or (cmd.Name in CmdDrill)
):
params = cmd.Parameters
x = params.get("X")
if x is None:
x = currX
currX = x
y = params.get("Y")
if y is None:
y = currY
currY = y
# "move" the centre to origin
x = x - centre.x
y = y - centre.y
# rotation around origin:
nx = x * math.cos(ang) - y * math.sin(ang)
ny = y * math.cos(ang) + x * math.sin(ang)
# "move" the centre back and update
params.update({"X": nx + centre.x, "Y": ny + centre.y})
# Arcs need to have the I and J params rotated as well
if cmd.Name in CmdMoveArc:
i = params.get("I")
if i is None:
i = 0
j = params.get("J")
if j is None:
j = 0
ni = i * math.cos(ang) - j * math.sin(ang)
nj = j * math.cos(ang) + i * math.sin(ang)
params.update({"I": ni, "J": nj})
cmd.Parameters = params
commands.append(cmd)
newPath = Path.Path(commands)
return newPath
# Private method
def _calculateJitter(self, pos):
"""_calculateJitter(pos) ...
@@ -411,7 +349,7 @@ class PathArray:
for b in base:
pl = FreeCAD.Placement()
pl.move(pos)
np = Path.Path([cm.transform(pl) for cm in b.Path.Commands])
np = Path.Path([cm.transform(pl) for cm in PathUtils.getPathWithPlacement(b).Commands])
output += np.toGCode()
elif self.arrayType == "Linear2D":
@@ -438,7 +376,7 @@ class PathArray:
if not (i == 0 and j == 0):
pl.move(pos)
np = Path.Path(
[cm.transform(pl) for cm in b.Path.Commands]
[cm.transform(pl) for cm in PathUtils.getPathWithPlacement(b).Commands]
)
output += np.toGCode()
else:
@@ -464,7 +402,7 @@ class PathArray:
if not (i == 0 and j == 0):
pl.move(pos)
np = Path.Path(
[cm.transform(pl) for cm in b.Path.Commands]
[cm.transform(pl) for cm in PathUtils.getPathWithPlacement(b).Commands]
)
output += np.toGCode()
# Eif
@@ -474,7 +412,10 @@ class PathArray:
ang = 360
if self.copies > 0:
ang = self.angle / self.copies * (1 + i)
np = self.rotatePath(b.Path, ang, self.centre)
pl = FreeCAD.Placement()
pl.rotate(self.centre, FreeCAD.Vector(0, 0, 1), ang)
np = PathUtils.applyPlacementToPath(pl, PathUtils.getPathWithPlacement(b))
output += np.toGCode()
# return output

View File

@@ -63,6 +63,8 @@ class ObjectPathCopy:
obj.ToolController = obj.Base.ToolController
if obj.Base.Path:
obj.Path = obj.Base.Path.copy()
if obj.Base.Placement:
obj.Placement = obj.Base.Placement
class ViewProviderPathCopy:

View File

@@ -68,10 +68,13 @@ class CommandPathSimpleCopy:
FreeCAD.ActiveDocument.openTransaction("Simple Copy")
FreeCADGui.doCommand(
"srcpath = FreeCADGui.Selection.getSelectionEx()[0].Object.Path\n"
"srcobj = FreeCADGui.Selection.getSelectionEx()[0].Object\n"
)
FreeCADGui.addModule("PathScripts.PathUtils")
FreeCADGui.doCommand(
"srcpath = PathScripts.PathUtils.getPathWithPlacement(srcobj)\n"
)
FreeCADGui.addModule("Path.Op.Custom")
FreeCADGui.doCommand(
'obj = Path.Op.Custom.Create("' + selection[0].Name + '_SimpleCopy")'

View File

@@ -34,6 +34,7 @@ from FreeCAD import Units
import Path
import Path.Post.Utils as PostUtils
import PathScripts.PathUtils as PathUtils
def create_comment(values, comment_string):
"""Create a comment from a string using the correct comment symbol."""
@@ -354,7 +355,7 @@ def parse_a_path(values, pathobj):
f"Tool Controller Vertical Rapid Values are unset{nl}"
)
for c in pathobj.Path.Commands:
for c in PathUtils.getPathWithPlacement(pathobj).Commands:
# List of elements in the command, code, and params.
outstring = []

View File

@@ -39,6 +39,7 @@ import argparse
import datetime
import shlex
from PathScripts import PathUtils
import PathScripts.PathUtils as PathUtils
TOOLTIP = """
This is a postprocessor file for the Path workbench. It is used to
@@ -344,7 +345,7 @@ def parse(pathobj):
# if OUTPUT_COMMENTS:
# out += linenumber() + "(" + pathobj.Label + ")\n"
for c in pathobj.Path.Commands:
for c in PathUtils.getPathWithPlacement(pathobj).Commands:
outstring = []
command = c.Name

View File

@@ -27,6 +27,7 @@ import os
import FreeCAD
from FreeCAD import Units
import Path.Post.Utils as PostUtils
import PathScripts.PathUtils as PathUtils
import datetime
import Path
@@ -276,7 +277,7 @@ def parse(pathobj):
# if OUTPUT_COMMENTS:
# out += linenumber() + "(" + pathobj.Label + ")\n"
for c in pathobj.Path.Commands:
for c in PathUtils.getPathWithPlacement(pathobj).Commands:
commandlist = [] # list of elements in the command, code and params.
command = c.Name # command M or G code or comment string

View File

@@ -23,6 +23,7 @@
import FreeCAD
import Path
import Path.Post.Utils as PostUtils
import PathScripts.PathUtils as PathUtils
TOOLTIP = """Example Post, using Path.Commands instead of Path.toGCode strings for Path gcode output."""
@@ -95,7 +96,7 @@ def export(obj, filename, argstring):
gcode += firstcommand.Name
if hasattr(fp, "Path"):
for c in fp.Path.Commands:
for c in PathUtils.getPathWithPlacement(fp).Commands:
gcode += lineout(c, oldvals, modal) + "\n"
oldvals = saveVals(c)
gcode += "M2\n"

View File

@@ -30,6 +30,7 @@ shows the dialog so you can see it. Useful for debugging, but not much else.
"""
import datetime
import Path.Post.Utils as PostUtils
import PathScripts.PathUtils as PathUtils
now = datetime.datetime.now()
SHOW_EDITOR = True
@@ -94,7 +95,7 @@ def parse(pathobj):
out += "(Path: " + pathobj.Label + ")\n"
for c in pathobj.Path.Commands:
for c in PathUtils.getPathWithPlacement(pathobj).Commands:
out += str(c) + "\n"
return out

View File

@@ -24,6 +24,7 @@
import FreeCAD
import Part
import Path
import PathScripts.PathUtils as PathUtils
import datetime
import importDXF
@@ -100,7 +101,7 @@ def parse(pathobj):
# Gotta start somewhere. Assume 0,0,0
curPoint = FreeCAD.Vector(0, 0, 0)
for c in pathobj.Path.Commands:
for c in PathUtils.getPathWithPlacement(pathobj).Commands:
Path.Log.debug("{} -> {}".format(curPoint, c))
if "Z" in c.Parameters:
newparams = c.Parameters

View File

@@ -32,6 +32,7 @@ import argparse
import datetime
import shlex
import Path.Post.Utils as PostUtils
import PathScripts.PathUtils as PathUtils
TOOLTIP = """
This is a post processor file for the FreeCAD Path workbench. It is used to
@@ -420,7 +421,7 @@ def parse(pathobj):
if not hasattr(pathobj, "Path"):
return out
for c in pathobj.Path.Commands:
for c in PathUtils.getPathWithPlacement(pathobj).Commands:
outstring = []
command = c.Name
# Convert G54-G59 Fixture offsets to E01-E06 for Dynapath Delta Control

View File

@@ -34,6 +34,7 @@
import FreeCAD
from FreeCAD import Units
import Path.Post.Utils as PostUtils
import PathScripts.PathUtils as PathUtils
import argparse
import datetime
import shlex
@@ -325,7 +326,7 @@ def parse(pathobj):
if OUTPUT_COMMENTS:
out += linenumber() + "(Path: " + pathobj.Label + ")\n"
for c in pathobj.Path.Commands:
for c in PathUtils.getPathWithPlacement(pathobj).Commands:
outstring = []
command = c.Name
outstring.append(command)

View File

@@ -26,6 +26,7 @@
import datetime
import Path.Post.Utils as PostUtils
import PathScripts.PathUtils as PathUtils
now = datetime.datetime.now()
@@ -253,7 +254,7 @@ def parse(pathobj):
if OUTPUT_COMMENTS:
out += linenumber() + "(Path: " + pathobj.Label + ")\n"
for c in pathobj.Path.Commands:
for c in PathUtils.getPathWithPlacement(pathobj).Commands:
outstring = []
command = c.Name

View File

@@ -30,6 +30,7 @@ import datetime
import shlex
import os.path
import Path.Post.Utils as PostUtils
import PathScripts.PathUtils as PathUtils
TOOLTIP = """
This is a postprocessor file for the Path workbench. It is used to
@@ -410,14 +411,15 @@ def parse(pathobj):
"Tool Controller Vertical Rapid Values are unset" + "\n"
)
for index, c in enumerate(pathobj.Path.Commands):
commands = PathUtils.getPathWithPlacement(pathobj).Commands
for index, c in enumerate(commands):
outstring = []
command = c.Name
if index + 1 == len(pathobj.Path.Commands):
if index + 1 == len(commands):
nextcommand = ""
else:
nextcommand = pathobj.Path.Commands[index + 1].Name
nextcommand = commands[index + 1].Name
if adaptiveOp and c.Name in ["G0", "G00"]:
if opHorizRapid and opVertRapid:

View File

@@ -29,6 +29,7 @@ from FreeCAD import Units
import Path
import Path.Base.Util as PathUtil
import Path.Post.Utils as PostUtils
import PathScripts.PathUtils as PathUtils
import argparse
import datetime
import shlex
@@ -481,7 +482,7 @@ def parse(pathobj):
if OUTPUT_COMMENTS:
out += linenumber() + "(Path: " + pathobj.Label + ")\n"
for c in pathobj.Path.Commands:
for c in PathUtils.getPathWithPlacement(pathobj).Commands:
outstring = []
command = c.Name

View File

@@ -22,6 +22,7 @@
import argparse
import Path.Post.Utils as PostUtils
import PathScripts.PathUtils as PathUtils
import Path
import PathScripts
import shlex
@@ -361,12 +362,14 @@ def export(objectslist, filename, argstring):
elif isinstance(obj.Proxy, Path.Op.Helix.ObjectHelix):
Object_Kind = "HELIX"
commands = PathUtils.getPathWithPlacement(obj).Commands
# If used compensated path, store, recompute and diff when asked
if hasattr(obj, "UseComp") and SOLVE_COMPENSATION_ACTIVE:
if obj.UseComp:
if hasattr(obj.Path, "Commands") and Object_Kind == "PROFILE":
# Take a copy of compensated path
STORED_COMPENSATED_OBJ = obj.Path.Commands
STORED_COMPENSATED_OBJ = commands
# Find mill compensation
if hasattr(obj, "Side") and hasattr(obj, "Direction"):
if obj.Side == "Outside" and obj.Direction == "CW":
@@ -380,14 +383,16 @@ def export(objectslist, filename, argstring):
# set obj.UseComp to false and recompute() to get uncompensated path
obj.UseComp = False
obj.recompute()
commands = PathUtils.getPathWithPlacement(obj).Commands
# small edges could be skipped and movements joints can add edges
NameStr = ""
if hasattr(obj, "Label"):
NameStr = str(obj.Label)
if len(obj.Path.Commands) != len(STORED_COMPENSATED_OBJ):
if len(commands) != len(STORED_COMPENSATED_OBJ):
# not same number of edges
obj.UseComp = True
obj.recompute()
commands = PathUtils.getPathWithPlacement(obj).Commands
POSTGCODE.append("; MISSING EDGES UNABLE TO GET COMPENSATION")
if not SKIP_WARNS:
(
@@ -422,7 +427,7 @@ def export(objectslist, filename, argstring):
POSTGCODE.append("; COMPENSATION ACTIVE")
COMPENSATION_DIFF_STATUS[0] = True
for c in obj.Path.Commands:
for c in commands:
Cmd_Count += 1
command = c.Name
if command != "G0":
@@ -458,7 +463,7 @@ def export(objectslist, filename, argstring):
Spindle_Status += str(MACHINE_SPINDLE_DIRECTION) # Activate spindle
Spindle_Active = True
else: # At last rapid movement we turn off spindle
if Cmd_Count == len(obj.Path.Commands):
if Cmd_Count == len(commands):
Spindle_Status += "5" # Deactivate spindle
Spindle_Active = False
else:

View File

@@ -28,6 +28,7 @@ import argparse
import datetime
import shlex
import Path.Post.Utils as PostUtils
import PathScripts.PathUtils as PathUtils
TOOLTIP = """
This is a postprocessor file for the Path workbench. It is used to
@@ -307,7 +308,7 @@ def parse(pathobj):
if not hasattr(pathobj, "Path"):
return out
for c in pathobj.Path.Commands:
for c in PathUtils.getPathWithPlacement(pathobj).Commands:
outstring = []
command = c.Name

View File

@@ -28,6 +28,7 @@ import argparse
import datetime
import shlex
import Path.Post.Utils as PostUtils
import PathScripts.PathUtils as PathUtils
TOOLTIP = """
This is a postprocessor file for the Path workbench. It is used to
@@ -355,7 +356,7 @@ def parse(pathobj):
# if OUTPUT_COMMENTS:
# out += linenumber() + "(" + pathobj.Label + ")\n"
for c in pathobj.Path.Commands:
for c in PathUtils.getPathWithPlacement(pathobj).Commands:
outstring = []
command = c.Name

View File

@@ -28,6 +28,7 @@ import argparse
import datetime
import shlex
import Path.Post.Utils as PostUtils
import PathScripts.PathUtils as PathUtils
TOOLTIP = """
This is a postprocessor file for the Path workbench. It is used to
@@ -387,7 +388,7 @@ def parse(pathobj):
"Tool Controller Vertical Rapid Values are unset" + "\n"
)
for c in pathobj.Path.Commands:
for c in PathUtils.getPathWithPlacement(pathobj).Commands:
outstring = []
command = c.Name

View File

@@ -35,6 +35,7 @@ from FreeCAD import Units
import Path
import Path.Base.Util as PathUtil
import Path.Post.Utils as PostUtils
import PathScripts.PathUtils as PathUtils
Revised = "2020-11-03" # Revision date for this file.
@@ -542,7 +543,7 @@ def parse(pathobj):
if OUTPUT_COMMENTS and OUTPUT_PATH:
out += linenumber() + "(Path: " + pathobj.Label + ")\n"
for c in pathobj.Path.Commands:
for c in PathUtils.getPathWithPlacement(pathobj).Commands:
outlist = []
command = c.Name
outlist.append(command)

View File

@@ -23,6 +23,7 @@
"""Postprocessor to output real GCode for Max Computer GmbH nccad9."""
import FreeCAD
import Path.Post.Utils as PostUtils
import PathScripts.PathUtils as PathUtils
import datetime
@@ -89,7 +90,7 @@ def export(objectslist, filename, argstring):
gcode = HEADER
for obj in objectslist:
for command in obj.Path.Commands:
for command in PathUtils.getPathWithPlacement(obj).Commands:
# Manipulate tool change commands
if "M6" == command.Name:
gcode += TOOL_CHANGE.replace("TOOL", str(int(command.Parameters["T"])))

View File

@@ -23,6 +23,7 @@
import datetime
import Path.Post.Utils as PostUtils
import PathScripts.PathUtils as PathUtils
TOOLTIP = """
@@ -351,7 +352,7 @@ def parse(pathobj):
return output
if OUTPUT_COMMENTS:
output += linenumber() + "'(Path: " + pathobj.Label + ")\n"
for c in pathobj.Path.Commands:
for c in PathUtils.getPathWithPlacement(pathobj).Commands:
command = c.Name
if command in scommands:
output += scommands[command](c)

View File

@@ -28,6 +28,7 @@ import FreeCAD
import argparse
import time
import Path.Post.Utils as PostUtils
import PathScripts.PathUtils as PathUtils
import math
TOOLTIP = """Post processor for Maho M 600E mill
@@ -416,7 +417,7 @@ def export(objectslist, filename, argstring):
for obj in objectslist:
if hasattr(obj, "Comment"):
gcode += linenumberify("(" + obj.Comment + ")")
for c in obj.Path.Commands:
for c in PathUtils.getPathWithPlacement(obj).Commands:
outstring = []
command = c.Name
if command != "G0":

View File

@@ -28,6 +28,7 @@
import Path.Post.UtilsArguments as PostUtilsArguments
import Path.Post.UtilsExport as PostUtilsExport
#
# The following variables need to be global variables
# to keep the PathPostProcessor.load method happy:

View File

@@ -34,6 +34,7 @@ from FreeCAD import Units
import Path
import Path.Base.Util as PathUtil
import Path.Post.Utils as PostUtils
import PathScripts.PathUtils as PathUtils
Revised = "2021-10-21" # Revision date for this file.
@@ -533,7 +534,7 @@ def parse(pathobj):
if OUTPUT_COMMENTS and OUTPUT_PATH:
out += linenumber() + "(Path: " + pathobj.Label + ")\n"
for c in pathobj.Path.Commands:
for c in PathUtils.getPathWithPlacement(pathobj).Commands:
outlist = []
command = c.Name
outlist.append(command)

View File

@@ -25,6 +25,7 @@
import argparse
import datetime
import Path.Post.Utils as PostUtils
import PathScripts.PathUtils as PathUtils
import FreeCAD
from FreeCAD import Units
import shlex
@@ -398,7 +399,7 @@ def parse(pathobj):
# if OUTPUT_COMMENTS:
# out += linenumber() + "(" + pathobj.Label + ")\n"
for c in pathobj.Path.Commands:
for c in PathUtils.getPathWithPlacement(pathobj).Commands:
outstring = []
command = c.Name
outstring.append(command)

View File

@@ -33,6 +33,7 @@
import FreeCAD
from FreeCAD import Units
import Path
import PathScripts.PathUtils as PathUtils
import argparse
import datetime
@@ -602,7 +603,7 @@ def parse(pathobj):
# if OUTPUT_COMMENTS:
# out += linenumber() + "(" + pathobj.Label + ")\n"
for c in pathobj.Path.Commands:
for c in PathUtils.getPathWithPlacement(pathobj).Commands:
commandlist = [] # list of elements in the command, code and params.
command = c.Name.strip() # command M or G code or comment string
commandlist.append(command)

View File

@@ -838,3 +838,69 @@ def RtoIJ(startpoint, command):
newcommand.Parameters = params
return newcommand
def getPathWithPlacement(pathobj):
"""
Applies the rotation, and then postition of the obj's Placement
to the obj's path
"""
if not hasattr(pathobj, "Placement") or pathobj.Path is None:
return pathobj.Path
return applyPlacementToPath(pathobj.Placement, pathobj.Path)
def applyPlacementToPath(placement, path):
"""
Applies the rotation, and then postition of the placement to path
"""
CmdMoveRapid = ["G0", "G00"]
CmdMoveStraight = ["G1", "G01"]
CmdMoveCW = ["G2", "G02"]
CmdMoveCCW = ["G3", "G03"]
CmdDrill = ["G73", "G81", "G82", "G83"]
CmdMoveArc = CmdMoveCW + CmdMoveCCW
CmdMove = CmdMoveStraight + CmdMoveArc
commands = []
currX = 0
currY = 0
currZ = 0
for cmd in path.Commands:
if (
(cmd.Name in CmdMoveRapid)
or (cmd.Name in CmdMove)
or (cmd.Name in CmdDrill)
):
params = cmd.Parameters
currX = x = params.get("X", currX)
currY = y = params.get("Y", currY)
currZ = z = params.get("Z", currZ)
x, y, z = placement.Rotation.multVec(FreeCAD.Vector(x, y ,z))
if x != currX:
params.update({"X": x})
if y != currY:
params.update({"Y": y})
if z != currZ:
params.update({"Z": z})
# Arcs need to have the I and J params rotated as well
if cmd.Name in CmdMoveArc:
currI = i = params.get("I", 0)
currJ = j = params.get("J", 0)
i, j, k = placement.Rotation.multVec(FreeCAD.Vector(i, j, 0))
if currI != i:
params.update({"I": i})
if currJ != j:
params.update({"J": j})
cmd.Parameters = params
commands.append(cmd.transform(placement))
newPath = Path.Path(commands)
return newPath