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 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)) 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..dca4792650 --- /dev/null +++ b/src/Mod/Path/PathScripts/post/dxf_post.py @@ -0,0 +1,142 @@ +# *************************************************************************** +# * 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 +import datetime +import PathScripts.PathGeom as PathGeom +import Part +import importDXF +import Path +import PathScripts.PathLog as PathLog + +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 + + +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 + + +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: + PathLog.debug('{} -> {}'.format(curPoint, c)) + 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: + 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): + PathLog.debug('vertical') + continue + + # feeding move. Build an edge + if flatcommand.Name in feedcommands: + 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) + + return objlist + + +print(__name__ + " gcode postprocessor loaded.")