From 4bb609d123e876e9f0683cce2eea62949f3a7a6a Mon Sep 17 00:00:00 2001 From: sliptonic Date: Fri, 30 Oct 2020 15:57:40 -0500 Subject: [PATCH 1/4] dxf post --- src/Mod/Path/PathScripts/post/dxf_post.py | 137 ++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 src/Mod/Path/PathScripts/post/dxf_post.py diff --git a/src/Mod/Path/PathScripts/post/dxf_post.py b/src/Mod/Path/PathScripts/post/dxf_post.py new file mode 100644 index 0000000000..ee2198803c --- /dev/null +++ b/src/Mod/Path/PathScripts/post/dxf_post.py @@ -0,0 +1,137 @@ +# *************************************************************************** +# * Copyright (c) 2020 sliptonic * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * FreeCAD is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Lesser General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with FreeCAD; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# ***************************************************************************/ +from __future__ import print_function +import FreeCAD +# from FreeCAD import Units +import datetime +# import PathScripts +# import PathScripts.PostUtils as PostUtils +import PathScripts.PathGeom as PathGeom +import Part +# import Draft +import importDXF +import Path + +TOOLTIP = ''' +This is a postprocessor file for the Path workbench. It is used to +take a pseudo-gcode fragment outputted by a Path object, and output +a dxf file. +Operations are output to layers. +vertical moves are ignore +All path moves are flattened to z=0 + +Does NOT remove redundant lines. If you have multiple step-downs in your +operation, you'll get multiple redundant lines in your dxf. + +import dxf_post +''' + +TOOLTIP_ARGS = ''' +Arguments for dxf: +''' +now = datetime.datetime.now() + +# # These globals set common customization preferences +OUTPUT_HEADER = True + + +# to distinguish python built-in open function from the one declared below +if open.__module__ in ['__builtin__', 'io']: + pythonopen = open + + +def processArguments(argstring): + pass + # global OUTPUT_HEADER + + +def export(objectslist, filename, argstring): + doc = FreeCAD.ActiveDocument + print("postprocessing...") + layers = [] + processArguments(argstring) + for i in objectslist: + result = parse(i) + if len(result) > 0: + layername = i.Name + grp = doc.addObject("App::DocumentObjectGroup", layername) + for o in result: + o.adjustRelativeLinks(grp) + grp.addObject(o) + layers.append(grp) + + dxfWrite(layers, filename) + + +def dxfWrite(objlist, filename): + importDXF.export(objlist, filename) + + +def parse(pathobj): + ''' accepts a Path object. Returns a list of wires''' + + feedcommands = ['G01', 'G1', 'G2', 'G3', 'G02', 'G03'] + rapidcommands = ['G0', 'G00'] + + edges = [] + objlist = [] + + # Gotta start somewhere. Assume 0,0,0 + curPoint = FreeCAD.Vector(0, 0, 0) + for c in pathobj.Path.Commands: + if 'Z' in c.Parameters: + newparams = c.Parameters + newparams.pop('Z', None) + flatcommand = Path.Command(c.Name, newparams) + c.Parameters = newparams + else: + flatcommand = c + + # ignore gcode that isn't moving + if flatcommand.Name not in feedcommands + rapidcommands: + continue + + # ignore pure vertical feed and rapid + if (flatcommand.Parameters.get('X', curPoint.x) == curPoint.x and + flatcommand.Parameters.get('Y ', curPoint.y) == curPoint.y): + continue + + # feeding move. Build an edge + if flatcommand.Name in feedcommands: + edges.append(PathGeom.edgeForCmd(flatcommand, curPoint)) + + # update the curpoint + curPoint.x = flatcommand.Parameters['X'] + curPoint.y = flatcommand.Parameters['Y'] + + if len(edges) > 0: + candidates = Part.sortEdges(edges) + for c in candidates: + obj = FreeCAD.ActiveDocument.addObject("Part::Feature", "Wire") + obj.Shape = Part.Wire(c) + objlist.append(obj) + + return objlist + + +print(__name__ + " gcode postprocessor loaded.") From b2e015f0354f0a8e27e1af98a149a2ad02a54674 Mon Sep 17 00:00:00 2001 From: sliptonic Date: Fri, 30 Oct 2020 15:57:04 -0500 Subject: [PATCH 2/4] Fix bug in where wiresForPath would error on empty list --- src/Mod/Path/PathScripts/PathGeom.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathGeom.py b/src/Mod/Path/PathScripts/PathGeom.py index 69f116f594..5c70b63701 100644 --- a/src/Mod/Path/PathScripts/PathGeom.py +++ b/src/Mod/Path/PathScripts/PathGeom.py @@ -400,8 +400,9 @@ def wiresForPath(path, startPoint = Vector(0, 0, 0)): edges.append(edgeForCmd(cmd, startPoint)) startPoint = commandEndPoint(cmd, startPoint) elif cmd.Name in CmdMoveRapid: - wires.append(Part.Wire(edges)) - edges = [] + if len(edges) > 0: + wires.append(Part.Wire(edges)) + edges = [] startPoint = commandEndPoint(cmd, startPoint) if edges: wires.append(Part.Wire(edges)) From bcdc245a4cd74e3e4102dc1da7256391d8f63fe3 Mon Sep 17 00:00:00 2001 From: sliptonic Date: Sun, 13 Dec 2020 14:15:56 -0600 Subject: [PATCH 3/4] add debug. Fix arc error --- src/Mod/Path/PathScripts/post/dxf_post.py | 33 +++++++++++++---------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/Mod/Path/PathScripts/post/dxf_post.py b/src/Mod/Path/PathScripts/post/dxf_post.py index ee2198803c..dca4792650 100644 --- a/src/Mod/Path/PathScripts/post/dxf_post.py +++ b/src/Mod/Path/PathScripts/post/dxf_post.py @@ -22,15 +22,12 @@ # ***************************************************************************/ from __future__ import print_function import FreeCAD -# from FreeCAD import Units import datetime -# import PathScripts -# import PathScripts.PostUtils as PostUtils import PathScripts.PathGeom as PathGeom import Part -# import Draft import importDXF import Path +import PathScripts.PathLog as PathLog TOOLTIP = ''' This is a postprocessor file for the Path workbench. It is used to @@ -55,6 +52,10 @@ now = datetime.datetime.now() OUTPUT_HEADER = True +PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) +# PathLog.trackModule(PathLog.thisModule()) + + # to distinguish python built-in open function from the one declared below if open.__module__ in ['__builtin__', 'io']: pythonopen = open @@ -99,6 +100,7 @@ def parse(pathobj): # Gotta start somewhere. Assume 0,0,0 curPoint = FreeCAD.Vector(0, 0, 0) for c in pathobj.Path.Commands: + PathLog.debug('{} -> {}'.format(curPoint, c)) if 'Z' in c.Parameters: newparams = c.Parameters newparams.pop('Z', None) @@ -109,27 +111,30 @@ def parse(pathobj): # ignore gcode that isn't moving if flatcommand.Name not in feedcommands + rapidcommands: - continue + PathLog.debug('non move') + continue # ignore pure vertical feed and rapid - if (flatcommand.Parameters.get('X', curPoint.x) == curPoint.x and - flatcommand.Parameters.get('Y ', curPoint.y) == curPoint.y): - continue + if (flatcommand.Parameters.get('X', curPoint.x) == curPoint.x + and flatcommand.Parameters.get('Y', curPoint.y) == curPoint.y): + PathLog.debug('vertical') + continue # feeding move. Build an edge if flatcommand.Name in feedcommands: - edges.append(PathGeom.edgeForCmd(flatcommand, curPoint)) + edges.append(PathGeom.edgeForCmd(flatcommand, curPoint)) + PathLog.debug('feeding move') # update the curpoint curPoint.x = flatcommand.Parameters['X'] curPoint.y = flatcommand.Parameters['Y'] if len(edges) > 0: - candidates = Part.sortEdges(edges) - for c in candidates: - obj = FreeCAD.ActiveDocument.addObject("Part::Feature", "Wire") - obj.Shape = Part.Wire(c) - objlist.append(obj) + candidates = Part.sortEdges(edges) + for c in candidates: + obj = FreeCAD.ActiveDocument.addObject("Part::Feature", "Wire") + obj.Shape = Part.Wire(c) + objlist.append(obj) return objlist From 933413b14eda41f947feb6eb0c75b630931764ad Mon Sep 17 00:00:00 2001 From: sliptonic Date: Wed, 16 Dec 2020 16:54:55 -0600 Subject: [PATCH 4/4] add post to Cmakelists.txt for install --- src/Mod/Path/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Mod/Path/CMakeLists.txt b/src/Mod/Path/CMakeLists.txt index db02b58762..ea1e717501 100644 --- a/src/Mod/Path/CMakeLists.txt +++ b/src/Mod/Path/CMakeLists.txt @@ -140,6 +140,7 @@ SET(PathScripts_post_SRCS PathScripts/post/centroid_post.py PathScripts/post/comparams_post.py PathScripts/post/dynapath_post.py + PathScripts/post/dxf_post.py PathScripts/post/example_pre.py PathScripts/post/gcode_pre.py PathScripts/post/grbl_post.py