def parse(pathobj): global AXIS_PRECISION global FEED_PRECISION out = "" lastcommand = None axis_precision_string = '.' + str(AXIS_PRECISION) +'f' feed_precision_string = '.' + str(FEED_PRECISION) +'f' # params = ['X','Y','Z','A','B','I','J','K','F','S'] #This list control # the order of parameters # centroid doesn't want K properties on XY plane Arcs need work. params = ['X', 'Y', 'Z', 'A', 'B', 'I', 'J', 'F', 'S', 'T', 'Q', 'R', 'L', 'H'] if hasattr(pathobj, "Group"): # We have a compound or project. # if OUTPUT_COMMENTS: # out += linenumber() + "(compound: " + pathobj.Label + ")\n" for p in pathobj.Group: out += parse(p) return out else: # parsing simple path # groups might contain non-path things like stock. if not hasattr(pathobj, "Path"): return out # if OUTPUT_COMMENTS: # out += linenumber() + "(" + pathobj.Label + ")\n" for c in pathobj.Path.Commands: commandlist = [] #list of elements in the command, code and params. command = c.Name #command M or G code or comment string if command[0]=='(': command = PostUtils.fcoms(command, COMMENT) commandlist.append(command) # if modal: only print the command if it is not the same as the # last one if MODAL is True: if command == lastcommand: commandlist.pop(0) # Now add the remaining parameters in order for param in params: if param in c.Parameters: if param == 'F': if c.Name not in ["G0", "G00"]: #centroid doesn't use rapid speeds speed = Units.Quantity(c.Parameters['F'], FreeCAD.Units.Velocity) commandlist.append( param + format(float(speed.getValueAs(UNIT_FORMAT)), feed_precision_string) ) elif param == 'H': commandlist.append(param + str(int(c.Parameters['H']))) elif param == 'S': commandlist.append(param + PostUtils.fmt(c.Parameters['S'], SPINDLE_DECIMALS, "G21")) elif param == 'T': commandlist.append(param + str(int(c.Parameters['T']))) else: commandlist.append( param + format(c.Parameters[param], axis_precision_string)) outstr = str(commandlist) outstr =outstr.replace('[','') outstr =outstr.replace(']','') outstr =outstr.replace("'",'') outstr =outstr.replace(",",'') #out += outstr + '\n' # store the latest command lastcommand = command # Check for Tool Change: if command == 'M6': # if OUTPUT_COMMENTS: # out += linenumber() + "(begin toolchange)\n" for line in TOOL_CHANGE.splitlines(True): out += linenumber() + line # if command == "message": # if OUTPUT_COMMENTS is False: # out = [] # else: # commandlist.pop(0) # remove the command # prepend a line number and append a newline if len(commandlist) >= 1: if OUTPUT_LINE_NUMBERS: commandlist.insert(0, (linenumber())) # append the line to the final output for w in commandlist: out += w + COMMAND_SPACE out = out.strip() + "\n" return out
def parse(pathobj): out = "" lastcommand = None axis_precision_string = '.' + str(AXIS_PRECISION) + 'f' feed_precision_string = '.' + str(FEED_PRECISION) + 'f' # params = ['X','Y','Z','A','B','I','J','K','F','S'] #This list control # the order of parameters # centroid doesn't want K properties on XY plane Arcs need work. params = [ 'X', 'Y', 'Z', 'A', 'B', 'I', 'J', 'F', 'S', 'T', 'Q', 'R', 'L', 'H' ] if hasattr(pathobj, "Group"): # We have a compound or project. # if OUTPUT_COMMENTS: # out += linenumber() + "(compound: " + pathobj.Label + ")\n" for p in pathobj.Group: out += parse(p) return out else: # parsing simple path # groups might contain non-path things like stock. if not hasattr(pathobj, "Path"): return out # if OUTPUT_COMMENTS: # out += linenumber() + "(" + pathobj.Label + ")\n" for c in pathobj.Path.Commands: commandlist = [ ] # list of elements in the command, code and params. command = c.Name # command M or G code or comment string if command[0] == '(': command = PostUtils.fcoms(command, COMMENT) commandlist.append(command) # if modal: only print the command if it is not the same as the # last one if MODAL is True: if command == lastcommand: commandlist.pop(0) # Now add the remaining parameters in order for param in params: if param in c.Parameters: if param == 'F': if c.Name not in [ "G0", "G00" ]: # centroid doesn't use rapid speeds speed = Units.Quantity(c.Parameters['F'], FreeCAD.Units.Velocity) commandlist.append( param + format(float(speed.getValueAs(UNIT_FORMAT)), feed_precision_string)) elif param == 'H': commandlist.append(param + str(int(c.Parameters['H']))) elif param == 'S': commandlist.append(param + PostUtils.fmt( c.Parameters['S'], SPINDLE_DECIMALS, "G21")) elif param == 'T': commandlist.append(param + str(int(c.Parameters['T']))) else: commandlist.append( param + format(c.Parameters[param], axis_precision_string)) outstr = str(commandlist) outstr = outstr.replace('[', '') outstr = outstr.replace(']', '') outstr = outstr.replace("'", '') outstr = outstr.replace(",", '') # store the latest command lastcommand = command # Check for Tool Change: if command == 'M6': # if OUTPUT_COMMENTS: # out += linenumber() + "(begin toolchange)\n" for line in TOOL_CHANGE.splitlines(True): out += linenumber() + line # if command == "message": # if OUTPUT_COMMENTS is False: # out = [] # else: # commandlist.pop(0) # remove the command # prepend a line number and append a newline if len(commandlist) >= 1: if OUTPUT_LINE_NUMBERS: commandlist.insert(0, (linenumber())) # append the line to the final output for w in commandlist: out += w + COMMAND_SPACE out = out.strip() + "\n" return out
def export(selection, filename, argstring): global linenr linenr = STARTLINENR lastX = 0 lastY = 0 lastZ = 0 params = [ 'X', 'Y', 'Z', 'A', 'B', 'I', 'J', 'F', 'H', 'S', 'T', 'Q', 'R', 'L' ] #Using XY plane most of the time so skipping K modalParamsDict = dict() for mp in MODALPARAMS: modalParamsDict[mp] = None for obj in selection: if not hasattr(obj, "Path"): print "the object " + obj.Name + " is not a path. Please select only path and Compounds." return myMachine = None for pathobj in selection: if hasattr(pathobj, "MachineName"): myMachine = pathobj.MachineName if hasattr(pathobj, "MachineUnits"): if pathobj.MachineUnits == "Metric": UNITS = "G21" else: UNITS = "G20" if myMachine is None: print "No machine found in this selection" gcode = '' gcode += mkHeader(selection) gcode += linenumberify(GCODE_HEADER) if UNITS_INCLUDED: gcode += linenumberify(mapGCode(UNITS)) lastcommand = None gobjects = [] for g in selection[0].Group: if g.Name <> 'Machine': #filtering out gcode home position from Machine object gobjects.append(g) for obj in gobjects: if hasattr(obj, 'Comment'): gcode += linenumberify('(' + obj.Comment + ')') for c in obj.Path.Commands: outstring = [] command = c.Name if (command != UNITS or UNITS_INCLUDED): if command[0] == '(': command = PostUtils.fcoms(command, COMMENT) mappedCommand = mapGCode( command ) # the mapping is done for output only! For internal things we still use the old value. if not MODAL or command != lastcommand: outstring.append(mappedCommand) # if MODAL == True: ) # #\better: append iff MODAL == False ) # if command == lastcommand: ) # outstring.pop(0!#\ ) if c.Parameters >= 1: for param in params: if param in c.Parameters: if (param in MODALPARAMS) and ( modalParamsDict[str(param)] == c.Parameters[str(param)]): # do nothing or append white space outstring.append(' ') elif param == 'F': outstring.append(param + PostUtils.fmt( c.Parameters['F'], FEED_DECIMALS, UNITS)) elif param == 'H': outstring.append(param + str(int(c.Parameters['H']))) elif param == 'S': outstring.append( param + PostUtils.fmt(c.Parameters['S'], SPINDLE_DECIMALS, 'G21') ) #rpm is unitless-therefore I had to 'fake it out' by using metric units which don't get converted from entered value elif param == 'T': outstring.append(param + str(int(c.Parameters['T']))) elif param == 'I' and (command == 'G2' or command == 'G3'): # this is the special case for circular paths, where relative coordinates have to be changed to absolute i = c.Parameters['I'] # calculate the radius r j = c.Parameters['J'] r = math.sqrt(i**2 + j**2) if USE_RADIUS_IF_POSSIBLE and angleUnder180( command, lastX, lastY, c.Parameters['X'], c.Parameters['Y'], i, j): outstring.append( 'R' + PostUtils.fmt(r, AXIS_DECIMALS, UNITS)) else: if RADIUS_COMMENT: outstring.append('(R' + PostUtils.fmt( r, AXIS_DECIMALS, UNITS) + ')') if ABSOLUTE_CIRCLE_CENTER: i += lastX outstring.append( param + PostUtils.fmt(i, AXIS_DECIMALS, UNITS)) elif param == 'J' and (command == 'G2' or command == 'G3'): # this is the special case for circular paths, where incremental center has to be changed to absolute center i = c.Parameters['I'] j = c.Parameters['J'] if USE_RADIUS_IF_POSSIBLE and angleUnder180( command, lastX, lastY, c.Parameters['X'], c.Parameters['Y'], i, j): # R is handled with the I parameter, here: do nothing at all, keep the structure as with I command pass else: if ABSOLUTE_CIRCLE_CENTER: j += lastY if SWAP_Y_Z: # we have to swap j and k as well outstring.append('K' + PostUtils.fmt( j, AXIS_DECIMALS, UNITS)) else: outstring.append(param + PostUtils.fmt( j, AXIS_DECIMALS, UNITS)) elif param == 'K' and (command == 'G2' or command == 'G3'): # this is the special case for circular paths, where incremental center has to be changed to absolute center outstring.append( '(' + param + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS) + ')') z = c.Parameters['Z'] k = c.Parameters['K'] if USE_RADIUS_IF_POSSIBLE and angleUnder180( command, lastX, lastY, c.Parameters['X'], c.Parameters['Y'], i, j): # R is handled with the I parameter, here: do nothing at all, keep the structure as with I command pass else: if ABSOLUTE_CIRCLE_CENTER: k += lastZ if SWAP_Y_Z: # we have to swap j and k as well outstring.append( 'J' + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) else: outstring.append( param + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) elif param == 'Y' and SWAP_Y_Z: outstring.append('Z' + PostUtils.fmt( c.Parameters[param], AXIS_DECIMALS, UNITS)) elif param == 'Z' and SWAP_Y_Z: outstring.append('Y' + PostUtils.fmt( c.Parameters[param], AXIS_DECIMALS, UNITS)) else: outstring.append(param + PostUtils.fmt( c.Parameters[param], AXIS_DECIMALS, UNITS)) if param in MODALPARAMS: modalParamsDict[str( param)] = c.Parameters[param] # save the last X, Y, Z values if 'X' in c.Parameters: lastX = c.Parameters['X'] if 'Y' in c.Parameters: lastY = c.Parameters['Y'] if 'Z' in c.Parameters: lastZ = c.Parameters['Z'] outstr = str(outstring) outstr = outstr.replace(']', '') outstr = outstr.replace('[', '') outstr = outstr.replace("'", '') outstr = outstr.replace(",", '') if LINENUMBERS: gcode += "N" + str(linenr) + " " linenr += LINENUMBER_INCREMENT gcode += outstr + '\n' lastcommand = c.Name gcode += linenumberify(GCODE_FOOTER) if SHOW_EDITOR: PostUtils.editor(gcode) gfile = pythonopen(filename, "wb") gfile.write(gcode) gfile.close()
def export(objectslist, filename, argstring): global UNITS global linenr linenr = STARTLINENR lastX = 0 lastY = 0 lastZ = 0 params = [ "X", "Y", "Z", "A", "B", "I", "J", "F", "H", "S", "T", "Q", "R", "L", ] # Using XY plane most of the time so skipping K modalParamsDict = dict() for mp in MODALPARAMS: modalParamsDict[mp] = None for obj in objectslist: if not hasattr(obj, "Path"): print("the object " + obj.Name + " is not a path. Please select only path and Compounds.") return myMachine = None for pathobj in objectslist: if hasattr(pathobj, "MachineName"): myMachine = pathobj.MachineName if hasattr(pathobj, "MachineUnits"): if pathobj.MachineUnits == "Metric": UNITS = "G21" else: UNITS = "G20" if myMachine is None: print("philips_post: No machine found in this selection") gcode = "" gcode += mkHeader(objectslist) gcode += linenumberify(GCODE_HEADER) if UNITS_INCLUDED: gcode += linenumberify(mapGCode(UNITS)) lastcommand = None for obj in objectslist: if hasattr(obj, "Comment"): gcode += linenumberify("(" + obj.Comment + ")") for c in obj.Path.Commands: outstring = [] command = c.Name if command != "G0": command = command.replace("G0", "G") # normalize: G01 -> G1 if command != UNITS or UNITS_INCLUDED: if command[0] == "(": command = PostUtils.fcoms(command, COMMENT) # the mapping is done for output only! For internal things we # still use the old value. mappedCommand = mapGCode(command) if not MODAL or command != lastcommand: outstring.append(mappedCommand) # if MODAL: # #\better: append iff MODAL == False # if command == lastcommand: # outstring.pop(0) if len(c.Parameters) >= 1: for param in params: # test print("param: " + param + ", command: " + command) if param in c.Parameters: if (param in MODALPARAMS) and ( modalParamsDict[str(param)] == c.Parameters[str(param)]): # do nothing or append white space outstring.append(" ") elif param == "F": feed = c.Parameters["F"] if SUPPRESS_ZERO_FEED and feed == 0: pass else: outstring.append(param + PostUtils.fmt( feed, FEED_DECIMALS, UNITS)) elif param == "H": outstring.append(param + str(int(c.Parameters["H"]))) elif param == "S": # rpm is unitless-therefore I had to 'fake it # out' by using metric units which don't get # converted from entered value outstring.append( param + PostUtils.fmt(c.Parameters["S"], SPINDLE_DECIMALS, "G21")) elif param == "T": outstring.append(param + str(int(c.Parameters["T"]))) elif param == "I" and (command == "G2" or command == "G3"): # test print("param = 'I'") # this is the special case for circular paths, # where relative coordinates have to be changed # to absolute i = c.Parameters["I"] # calculate the radius r j = c.Parameters["J"] r = math.sqrt(i**2 + j**2) if USE_RADIUS_IF_POSSIBLE and angleUnder180( command, lastX, lastY, c.Parameters["X"], c.Parameters["Y"], i, j, ): outstring.append( "R" + PostUtils.fmt(r, AXIS_DECIMALS, UNITS)) else: if RADIUS_COMMENT: outstring.append("(R" + PostUtils.fmt( r, AXIS_DECIMALS, UNITS) + ")") if ABSOLUTE_CIRCLE_CENTER: i += lastX outstring.append( param + PostUtils.fmt(i, AXIS_DECIMALS, UNITS)) elif param == "J" and (command == "G2" or command == "G3"): # this is the special case for circular paths, # where incremental center has to be changed to # absolute center i = c.Parameters["I"] j = c.Parameters["J"] if USE_RADIUS_IF_POSSIBLE and angleUnder180( command, lastX, lastY, c.Parameters["X"], c.Parameters["Y"], i, j, ): # R is handled with the I parameter, here: # do nothing at all, keep the structure as # with I command pass else: if ABSOLUTE_CIRCLE_CENTER: j += lastY if SWAP_Y_Z: # we have to swap j and k as well outstring.append("K" + PostUtils.fmt( j, AXIS_DECIMALS, UNITS)) else: outstring.append(param + PostUtils.fmt( j, AXIS_DECIMALS, UNITS)) elif param == "K" and (command == "G2" or command == "G3"): # this is the special case for circular paths, # where incremental center has to be changed to # absolute center outstring.append( "(" + param + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS) + ")") z = c.Parameters["Z"] k = c.Parameters["K"] if USE_RADIUS_IF_POSSIBLE and angleUnder180( command, lastX, lastY, c.Parameters["X"], c.Parameters["Y"], i, j, ): # R is handled with the I parameter, here: # do nothing at all, keep the structure as # with I command pass else: if ABSOLUTE_CIRCLE_CENTER: k += lastZ if SWAP_Y_Z: # we have to swap j and k as well outstring.append( "J" + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) else: outstring.append( param + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) elif param == "Y" and SWAP_Y_Z: outstring.append("Z" + PostUtils.fmt( c.Parameters[param], AXIS_DECIMALS, UNITS)) elif param == "Z" and SWAP_Y_Z: outstring.append("Y" + PostUtils.fmt( c.Parameters[param], AXIS_DECIMALS, UNITS)) else: # To Do: suppress unknown commands, if this is done here, all X parameters are suppressed # this is an unknown command, don't create GCode for it # print("parameter " + param + " for command " + command + " ignored") outstring.append(param + PostUtils.fmt( c.Parameters[param], AXIS_DECIMALS, UNITS)) if param in MODALPARAMS: modalParamsDict[str( param)] = c.Parameters[param] # save the last X, Y, Z values if "X" in c.Parameters: lastX = c.Parameters["X"] if "Y" in c.Parameters: lastY = c.Parameters["Y"] if "Z" in c.Parameters: lastZ = c.Parameters["Z"] outstr = "" for w in outstring: outstr += w + COMMAND_SPACE outstr = outstr.replace("]", "") outstr = outstr.replace("[", "") outstr = outstr.replace("'", "") outstr = outstr.replace(",", ".") if LINENUMBERS: gcode += "N" + str(linenr) + " " linenr += LINENUMBER_INCREMENT gcode += outstr + "\n" lastcommand = c.Name gcode = gcode.replace("_", "-") gcode += linenumberify(GCODE_FOOTER) if SHOW_EDITOR: PostUtils.editor(gcode) gfile = pythonopen(filename, "w") gfile.write(gcode) gfile.close()
def export(objectslist, filename, argstring): global UNITS global linenr global ABSOLUTE_CIRCLE_CENTER global USE_RADIUS_IF_POSSIBLE global RADIUS_COMMENT linenr = STARTLINENR lastX = 0 lastY = 0 lastZ = 0 params = [ 'X', 'Y', 'Z', 'A', 'B', 'I', 'J', 'F', 'H', 'S', 'T', 'Q', 'R', 'L' ] # Using XY plane most of the time so skipping K modalParamsDict = dict() for mp in MODALPARAMS: modalParamsDict[mp] = None for obj in objectslist: if not hasattr(obj, "Path"): print("the object " + obj.Name + " is not a path. Please select only path and Compounds.") return myMachine = None for pathobj in objectslist: if hasattr(pathobj, "MachineName"): myMachine = pathobj.MachineName if hasattr(pathobj, "MachineUnits"): if pathobj.MachineUnits == "Metric": UNITS = "G21" else: UNITS = "G20" if myMachine is None: print("philips_post: No machine found in this selection") gcode = '' gcode += mkHeader(objectslist) gcode += linenumberify(GCODE_HEADER) if UNITS_INCLUDED: gcode += linenumberify(mapGCode(UNITS)) lastcommand = None for obj in objectslist: if hasattr(obj, 'Comment'): gcode += linenumberify('(' + obj.Comment + ')') for c in obj.Path.Commands: outstring = [] command = c.Name if command != 'G0': command = command.replace('G0', 'G') # normalize: G01 -> G1 if (command != UNITS or UNITS_INCLUDED): if command[0] == '(': command = PostUtils.fcoms(command, COMMENT) # the mapping is done for output only! For internal things we # still use the old value. mappedCommand = mapGCode(command) if not MODAL or command != lastcommand: outstring.append(mappedCommand) # if MODAL == True: # #\better: append iff MODAL == False # if command == lastcommand: # outstring.pop(0) if c.Parameters >= 1: for param in params: # test print("param: " + param + ", command: " + command) if param in c.Parameters: if (param in MODALPARAMS) and ( modalParamsDict[str(param)] == c.Parameters[str(param)]): # do nothing or append white space outstring.append(' ') elif param == 'F': feed = c.Parameters['F'] if SUPPRESS_ZERO_FEED and feed == 0: pass else: outstring.append(param + PostUtils.fmt( feed, FEED_DECIMALS, UNITS)) elif param == 'H': outstring.append(param + str(int(c.Parameters['H']))) elif param == 'S': # rpm is unitless-therefore I had to 'fake it # out' by using metric units which don't get # converted from entered value outstring.append( param + PostUtils.fmt(c.Parameters['S'], SPINDLE_DECIMALS, 'G21')) elif param == 'T': outstring.append(param + str(int(c.Parameters['T']))) elif param == 'I' and (command == 'G2' or command == 'G3'): #test print("param = 'I'") # this is the special case for circular paths, # where relative coordinates have to be changed # to absolute i = c.Parameters['I'] # calculate the radius r j = c.Parameters['J'] r = math.sqrt(i**2 + j**2) if USE_RADIUS_IF_POSSIBLE and angleUnder180( command, lastX, lastY, c.Parameters['X'], c.Parameters['Y'], i, j): outstring.append( 'R' + PostUtils.fmt(r, AXIS_DECIMALS, UNITS)) else: if RADIUS_COMMENT: outstring.append('(R' + PostUtils.fmt( r, AXIS_DECIMALS, UNITS) + ')') if ABSOLUTE_CIRCLE_CENTER: i += lastX outstring.append( param + PostUtils.fmt(i, AXIS_DECIMALS, UNITS)) elif param == 'J' and (command == 'G2' or command == 'G3'): # this is the special case for circular paths, # where incremental center has to be changed to # absolute center i = c.Parameters['I'] j = c.Parameters['J'] if USE_RADIUS_IF_POSSIBLE and angleUnder180( command, lastX, lastY, c.Parameters['X'], c.Parameters['Y'], i, j): # R is handled with the I parameter, here: # do nothing at all, keep the structure as # with I command pass else: if ABSOLUTE_CIRCLE_CENTER: j += lastY if SWAP_Y_Z: # we have to swap j and k as well outstring.append('K' + PostUtils.fmt( j, AXIS_DECIMALS, UNITS)) else: outstring.append(param + PostUtils.fmt( j, AXIS_DECIMALS, UNITS)) elif param == 'K' and (command == 'G2' or command == 'G3'): # this is the special case for circular paths, # where incremental center has to be changed to # absolute center outstring.append( '(' + param + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS) + ')') z = c.Parameters['Z'] k = c.Parameters['K'] if USE_RADIUS_IF_POSSIBLE and angleUnder180( command, lastX, lastY, c.Parameters['X'], c.Parameters['Y'], i, j): # R is handled with the I parameter, here: # do nothing at all, keep the structure as # with I command pass else: if ABSOLUTE_CIRCLE_CENTER: k += lastZ if SWAP_Y_Z: # we have to swap j and k as well outstring.append( 'J' + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) else: outstring.append( param + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) elif param == 'Y' and SWAP_Y_Z: outstring.append('Z' + PostUtils.fmt( c.Parameters[param], AXIS_DECIMALS, UNITS)) elif param == 'Z' and SWAP_Y_Z: outstring.append('Y' + PostUtils.fmt( c.Parameters[param], AXIS_DECIMALS, UNITS)) else: # To Do: suppress unknown commands, if this is done here, all X parameters are suppressed # this is an unknown command, don't create GCode for it # print("parameter " + param + " for command " + command + " ignored") outstring.append(param + PostUtils.fmt( c.Parameters[param], AXIS_DECIMALS, UNITS)) if param in MODALPARAMS: modalParamsDict[str( param)] = c.Parameters[param] # save the last X, Y, Z values if 'X' in c.Parameters: lastX = c.Parameters['X'] if 'Y' in c.Parameters: lastY = c.Parameters['Y'] if 'Z' in c.Parameters: lastZ = c.Parameters['Z'] outstr = '' for w in outstring: outstr += w + COMMAND_SPACE outstr = outstr.replace(']', '') outstr = outstr.replace('[', '') outstr = outstr.replace("'", '') outstr = outstr.replace(",", '.') if LINENUMBERS: gcode += "N" + str(linenr) + " " linenr += LINENUMBER_INCREMENT gcode += outstr + '\n' lastcommand = c.Name gcode = gcode.replace("_", "-") gcode += linenumberify(GCODE_FOOTER) if SHOW_EDITOR: PostUtils.editor(gcode) gfile = pythonopen(filename, "wb") gfile.write(gcode) gfile.close()
def export(selection, filename, argstring): params = [ 'X', 'Y', 'Z', 'A', 'B', 'I', 'J', 'F', 'H', 'S', 'T', 'Q', 'R', 'L' ] #Using XY plane most of the time so skipping K for obj in selection: if not hasattr(obj, "Path"): print("the object " + obj.Name + " is not a path. Please select only path and Compounds.") return myMachine = None for pathobj in selection: if hasattr(pathobj, "MachineName"): myMachine = pathobj.MachineName if hasattr(pathobj, "MachineUnits"): if pathobj.MachineUnits == "Metric": UNITS = "G21" else: UNITS = "G20" if myMachine is None: print("No machine found in this selection") gcode = '' gcode += HEADER % (FreeCAD.ActiveDocument.FileName) gcode += SAFETYBLOCK gcode += UNITS + '\n' lastcommand = None gcode += COMMENT + selection[0].Description + '\n' gobjects = [] for g in selection[0].Group: gobjects.append(g) for obj in gobjects: for c in obj.Path.Commands: outstring = [] command = c.Name if command[0] == '(': command = PostUtils.fcoms(command, COMMENT) outstring.append(command) if MODAL == True: if command == lastcommand: outstring.pop(0) if c.Parameters >= 1: for param in params: if param in c.Parameters: if param == 'F': outstring.append(param + PostUtils.fmt( c.Parameters['F'], FEED_DECIMALS, UNITS)) elif param == 'H': outstring.append(param + str(int(c.Parameters['H']))) elif param == 'S': outstring.append( param + PostUtils.fmt(c.Parameters['S'], SPINDLE_DECIMALS, 'G21') ) #rpm is unitless-therefore I had to 'fake it out' by using metric units which don't get converted from entered value elif param == 'T': outstring.append(param + str(int(c.Parameters['T']))) else: outstring.append(param + PostUtils.fmt( c.Parameters[param], AXIS_DECIMALS, UNITS)) outstr = str(outstring) outstr = outstr.replace('[', '') outstr = outstr.replace(']', '') outstr = outstr.replace("'", '') outstr = outstr.replace(",", '') gcode += outstr + '\n' lastcommand = c.Name gcode += TOOLRETURN gcode += SAFETYBLOCK gcode += FOOTER if SHOW_EDITOR: PostUtils.editor(gcode) gfile = pythonopen(filename, "wb") gfile.write(gcode) gfile.close()
def export(objectslist, filename, argstring): global UNITS global linenr global ABSOLUTE_CIRCLE_CENTER global USE_RADIUS_IF_POSSIBLE global RADIUS_COMMENT linenr = STARTLINENR lastX = 0 lastY = 0 lastZ = 0 params = ['X', 'Y', 'Z', 'A', 'B', 'I', 'J', 'F', 'H', 'S', 'T', 'Q', 'R', 'L'] # Using XY plane most of the time so skipping K modalParamsDict = dict() for mp in MODALPARAMS: modalParamsDict[mp] = None for obj in objectslist: if not hasattr(obj, "Path"): print("the object " + obj.Name + " is not a path. Please select only path and Compounds.") return myMachine = None for pathobj in objectslist: if hasattr(pathobj, "MachineName"): myMachine = pathobj.MachineName if hasattr(pathobj, "MachineUnits"): if pathobj.MachineUnits == "Metric": UNITS = "G21" else: UNITS = "G20" if myMachine is None: print("philips_post: No machine found in this selection") gcode = '' gcode += mkHeader(objectslist) gcode += linenumberify(GCODE_HEADER) if UNITS_INCLUDED: gcode += linenumberify(mapGCode(UNITS)) lastcommand = None for obj in objectslist: if hasattr(obj, 'Comment'): gcode += linenumberify('(' + obj.Comment + ')') for c in obj.Path.Commands: outstring = [] command = c.Name if command != 'G0': command = command.replace('G0','G') # normalize: G01 -> G1 if (command != UNITS or UNITS_INCLUDED): if command[0] == '(': command = PostUtils.fcoms(command, COMMENT) # the mapping is done for output only! For internal things we # still use the old value. mappedCommand = mapGCode(command) if not MODAL or command != lastcommand: outstring.append(mappedCommand) # if MODAL == True: # #\better: append iff MODAL == False # if command == lastcommand: # outstring.pop(0) if c.Parameters >= 1: for param in params: # test print("param: " + param + ", command: " + command) if param in c.Parameters: if (param in MODALPARAMS) and (modalParamsDict[str(param)] == c.Parameters[str(param)]): # do nothing or append white space outstring.append(' ') elif param == 'F': feed = c.Parameters['F'] if SUPPRESS_ZERO_FEED and feed == 0: pass else: outstring.append( param + PostUtils.fmt(feed, FEED_DECIMALS, UNITS)) elif param == 'H': outstring.append( param + str(int(c.Parameters['H']))) elif param == 'S': # rpm is unitless-therefore I had to 'fake it # out' by using metric units which don't get # converted from entered value outstring.append( param + PostUtils.fmt(c.Parameters['S'], SPINDLE_DECIMALS, 'G21')) elif param == 'T': outstring.append( param + str(int(c.Parameters['T']))) elif param == 'I' and (command == 'G2' or command == 'G3'): #test print("param = 'I'") # this is the special case for circular paths, # where relative coordinates have to be changed # to absolute i = c.Parameters['I'] # calculate the radius r j = c.Parameters['J'] r = math.sqrt(i**2 + j**2) if USE_RADIUS_IF_POSSIBLE and angleUnder180(command, lastX, lastY, c.Parameters['X'], c.Parameters['Y'], i, j): outstring.append( 'R' + PostUtils.fmt(r, AXIS_DECIMALS, UNITS)) else: if RADIUS_COMMENT: outstring.append( '(R' + PostUtils.fmt(r, AXIS_DECIMALS, UNITS) + ')') if ABSOLUTE_CIRCLE_CENTER: i += lastX outstring.append( param + PostUtils.fmt(i, AXIS_DECIMALS, UNITS)) elif param == 'J' and (command == 'G2' or command == 'G3'): # this is the special case for circular paths, # where incremental center has to be changed to # absolute center i = c.Parameters['I'] j = c.Parameters['J'] if USE_RADIUS_IF_POSSIBLE and angleUnder180(command, lastX, lastY, c.Parameters['X'], c.Parameters['Y'], i, j): # R is handled with the I parameter, here: # do nothing at all, keep the structure as # with I command pass else: if ABSOLUTE_CIRCLE_CENTER: j += lastY if SWAP_Y_Z: # we have to swap j and k as well outstring.append( 'K' + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) else: outstring.append( param + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) elif param == 'K' and (command == 'G2' or command == 'G3'): # this is the special case for circular paths, # where incremental center has to be changed to # absolute center outstring.append( '(' + param + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS) + ')') z = c.Parameters['Z'] k = c.Parameters['K'] if USE_RADIUS_IF_POSSIBLE and angleUnder180(command, lastX, lastY, c.Parameters['X'], c.Parameters['Y'], i, j): # R is handled with the I parameter, here: # do nothing at all, keep the structure as # with I command pass else: if ABSOLUTE_CIRCLE_CENTER: k += lastZ if SWAP_Y_Z: # we have to swap j and k as well outstring.append( 'J' + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) else: outstring.append( param + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) elif param == 'Y' and SWAP_Y_Z: outstring.append( 'Z' + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS)) elif param == 'Z' and SWAP_Y_Z: outstring.append( 'Y' + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS)) else: # To Do: suppress unknown commands, if this is done here, all X parameters are suppressed # this is an unknown command, don't create GCode for it # print("parameter " + param + " for command " + command + " ignored") outstring.append( param + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS)) if param in MODALPARAMS: modalParamsDict[str(param)] = c.Parameters[ param] # save the last X, Y, Z values if 'X' in c.Parameters: lastX = c.Parameters['X'] if 'Y' in c.Parameters: lastY = c.Parameters['Y'] if 'Z' in c.Parameters: lastZ = c.Parameters['Z'] outstr = '' for w in outstring: outstr += w + COMMAND_SPACE outstr = outstr.replace(']', '') outstr = outstr.replace('[', '') outstr = outstr.replace("'", '') outstr = outstr.replace(",", '.') if LINENUMBERS: gcode += "N" + str(linenr) + " " linenr += LINENUMBER_INCREMENT gcode += outstr + '\n' lastcommand = c.Name gcode = gcode.replace("_","-") gcode += linenumberify(GCODE_FOOTER) if SHOW_EDITOR: PostUtils.editor(gcode) gfile = pythonopen(filename, "w") gfile.write(gcode) gfile.close()
def export(selection, filename, argstring): global linenr linenr = STARTLINENR lastX = 0 lastY = 0 lastZ = 0 params = [ "X", "Y", "Z", "A", "B", "I", "J", "F", "H", "S", "T", "Q", "R", "L", ] # Using XY plane most of the time so skipping K modalParamsDict = dict() for mp in MODALPARAMS: modalParamsDict[mp] = None for obj in selection: if not hasattr(obj, "Path"): print "the object " + obj.Name + " is not a path. Please select only path and Compounds." return myMachine = None for pathobj in selection: if hasattr(pathobj, "MachineName"): myMachine = pathobj.MachineName if hasattr(pathobj, "MachineUnits"): if pathobj.MachineUnits == "Metric": UNITS = "G21" else: UNITS = "G20" if myMachine is None: print "No machine found in this selection" gcode = "" gcode += mkHeader(selection) gcode += linenumberify(GCODE_HEADER) if UNITS_INCLUDED: gcode += linenumberify(mapGCode(UNITS)) lastcommand = None gobjects = [] for g in selection[0].Group: gobjects.append(g) for obj in gobjects: if hasattr(obj, "GComment"): gcode += linenumberify("(" + obj.GComment + ")") for c in obj.Path.Commands: outstring = [] command = c.Name if command != UNITS or UNITS_INCLUDED: if command[0] == "(": command = PostUtils.fcoms(command, COMMENT) mappedCommand = mapGCode( command ) # the mapping is done for output only! For internal things we still use the old value. if not MODAL or command != lastcommand: outstring.append(mappedCommand) # if MODAL == True: ) # #\better: append iff MODAL == False ) # if command == lastcommand: ) # outstring.pop(0!#\ ) if c.Parameters >= 1: for param in params: if param in c.Parameters: if (param in MODALPARAMS) and (modalParamsDict[str(param)] == c.Parameters[str(param)]): # do nothing or append white space outstring.append(" ") elif param == "F": outstring.append(param + PostUtils.fmt(c.Parameters["F"], FEED_DECIMALS, UNITS)) elif param == "H": outstring.append(param + str(int(c.Parameters["H"]))) elif param == "S": outstring.append( param + PostUtils.fmt(c.Parameters["S"], SPINDLE_DECIMALS, "G21") ) # rpm is unitless-therefore I had to 'fake it out' by using metric units which don't get converted from entered value elif param == "T": outstring.append(param + str(int(c.Parameters["T"]))) elif param == "I" and (command == "G2" or command == "G3"): # this is the special case for circular paths, where relative coordinates have to be changed to absolute i = c.Parameters["I"] # calculate the radius r j = c.Parameters["J"] r = math.sqrt(i ** 2 + j ** 2) if USE_RADIUS_IF_POSSIBLE and angleUnder180( command, lastX, lastY, c.Parameters["X"], c.Parameters["Y"], i, j ): outstring.append("R" + PostUtils.fmt(r, AXIS_DECIMALS, UNITS)) else: if RADIUS_COMMENT: outstring.append("(R" + PostUtils.fmt(r, AXIS_DECIMALS, UNITS) + ")") if ABSOLUTE_CIRCLE_CENTER: i += lastX outstring.append(param + PostUtils.fmt(i, AXIS_DECIMALS, UNITS)) elif param == "J" and (command == "G2" or command == "G3"): # this is the special case for circular paths, where incremental center has to be changed to absolute center i = c.Parameters["I"] j = c.Parameters["J"] if USE_RADIUS_IF_POSSIBLE and angleUnder180( command, lastX, lastY, c.Parameters["X"], c.Parameters["Y"], i, j ): # R is handled with the I parameter, here: do nothing at all, keep the structure as with I command pass else: if ABSOLUTE_CIRCLE_CENTER: j += lastY if SWAP_Y_Z: # we have to swap j and k as well outstring.append("K" + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) else: outstring.append(param + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) elif param == "K" and (command == "G2" or command == "G3"): # this is the special case for circular paths, where incremental center has to be changed to absolute center outstring.append( "(" + param + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS) + ")" ) z = c.Parameters["Z"] k = c.Parameters["K"] if USE_RADIUS_IF_POSSIBLE and angleUnder180( command, lastX, lastY, c.Parameters["X"], c.Parameters["Y"], i, j ): # R is handled with the I parameter, here: do nothing at all, keep the structure as with I command pass else: if ABSOLUTE_CIRCLE_CENTER: k += lastZ if SWAP_Y_Z: # we have to swap j and k as well outstring.append("J" + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) else: outstring.append(param + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) elif param == "Y" and SWAP_Y_Z: outstring.append("Z" + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS)) elif param == "Z" and SWAP_Y_Z: outstring.append("Y" + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS)) else: outstring.append(param + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS)) if param in MODALPARAMS: modalParamsDict[str(param)] = c.Parameters[param] # save the last X, Y, Z values if "X" in c.Parameters: lastX = c.Parameters["X"] if "Y" in c.Parameters: lastY = c.Parameters["Y"] if "Z" in c.Parameters: lastZ = c.Parameters["Z"] outstr = str(outstring) outstr = outstr.replace("]", "") outstr = outstr.replace("[", "") outstr = outstr.replace("'", "") outstr = outstr.replace(",", "") if LINENUMBERS: gcode += "N" + str(linenr) + " " linenr += LINENUMBER_INCREMENT gcode += outstr + "\n" lastcommand = c.Name gcode += linenumberify(GCODE_FOOTER) if SHOW_EDITOR: PostUtils.editor(gcode) gfile = pythonopen(filename, "wb") gfile.write(gcode) gfile.close()
def export(selection, filename, argstring): params = [ "X", "Y", "Z", "A", "B", "I", "J", "F", "H", "S", "T", "Q", "R", "L", ] # Using XY plane most of the time so skipping K for obj in selection: if not hasattr(obj, "Path"): print "the object " + obj.Name + " is not a path. Please select only path and Compounds." return myMachine = None for pathobj in selection: if hasattr(pathobj, "MachineName"): myMachine = pathobj.MachineName if hasattr(pathobj, "MachineUnits"): if pathobj.MachineUnits == "Metric": UNITS = "G21" else: UNITS = "G20" if myMachine is None: print "No machine found in this selection" gcode = "" gcode += HEADER % (FreeCAD.ActiveDocument.FileName) gcode += SAFETYBLOCK gcode += UNITS + "\n" lastcommand = None gcode += COMMENT + selection[0].Description + "\n" gobjects = [] for g in selection[0].Group: gobjects.append(g) for obj in gobjects: for c in obj.Path.Commands: outstring = [] command = c.Name if command[0] == "(": command = PostUtils.fcoms(command, COMMENT) outstring.append(command) if MODAL == True: if command == lastcommand: outstring.pop(0) if c.Parameters >= 1: for param in params: if param in c.Parameters: if param == "F": outstring.append(param + PostUtils.fmt(c.Parameters["F"], FEED_DECIMALS, UNITS)) elif param == "H": outstring.append(param + str(int(c.Parameters["H"]))) elif param == "S": outstring.append( param + PostUtils.fmt(c.Parameters["S"], SPINDLE_DECIMALS, "G21") ) # rpm is unitless-therefore I had to 'fake it out' by using metric units which don't get converted from entered value elif param == "T": outstring.append(param + str(int(c.Parameters["T"]))) else: outstring.append(param + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS)) outstr = str(outstring) outstr = outstr.replace("[", "") outstr = outstr.replace("]", "") outstr = outstr.replace("'", "") outstr = outstr.replace(",", "") gcode += outstr + "\n" lastcommand = c.Name gcode += TOOLRETURN gcode += SAFETYBLOCK gcode += FOOTER if SHOW_EDITOR: PostUtils.editor(gcode) gfile = pythonopen(filename, "wb") gfile.write(gcode) gfile.close()
def export(selection,filename): params = ['X','Y','Z','A','B','I','J','F','H','S','T','Q','R','L'] #Using XY plane most of the time so skipping K for obj in selection: if not hasattr(obj,"Path"): print "the object " + obj.Name + " is not a path. Please select only path and Compounds." return myMachine = None for pathobj in selection: if hasattr(pathobj,"Group"): #We have a compound or selection. for p in pathobj.Group: if p.Name == "Machine": myMachine = p if myMachine is None: print "No machine found in this selection" else: if myMachine.MachineUnits == "Metric": UNITS = "G21" else: UNITS = "G20" gcode ='' gcode+= HEADER gcode+= SAFETYBLOCK gcode+= UNITS+'\n' lastcommand = None gcode+= COMMENT+ selection[0].Description +'\n' gobjects = [] for g in selection[0].Group: if g.Name <>'Machine': #filtering out gcode home position from Machine object gobjects.append(g) for obj in gobjects: for c in obj.Path.Commands: outstring = [] command = c.Name if command[0]=='(': command = PostUtils.fcoms(command, COMMENT) outstring.append(command) if MODAL == True: if command == lastcommand: outstring.pop(0) if c.Parameters >= 1: for param in params: if param in c.Parameters: if param == 'F': outstring.append(param + PostUtils.fmt(c.Parameters['F'], FEED_DECIMALS,UNITS)) elif param == 'H': outstring.append(param + str(int(c.Parameters['H']))) elif param == 'S': outstring.append(param + PostUtils.fmt(c.Parameters['S'], SPINDLE_DECIMALS,'G21')) #rpm is unitless-therefore I had to 'fake it out' by using metric units which don't get converted from entered value elif param == 'T': outstring.append(param + str(int(c.Parameters['T']))) else: outstring.append(param + PostUtils.fmt(c.Parameters[param],AXIS_DECIMALS,UNITS)) outstr = str(outstring) outstr =outstr.replace('[','') outstr =outstr.replace(']','') outstr =outstr.replace("'",'') outstr =outstr.replace(",",'') gcode+= outstr + '\n' lastcommand = c.Name gcode+= TOOLRETURN gcode+= SAFETYBLOCK gcode+= FOOTER if SHOW_EDITOR: PostUtils.editor(gcode) gfile = pythonopen(filename,"wb") gfile.write(gcode) gfile.close()
def export(selection,filename,argstring): global linenr linenr = STARTLINENR lastX = 0 lastY = 0 lastZ = 0 params = ['X','Y','Z','A','B','I','J','F','H','S','T','Q','R','L'] #Using XY plane most of the time so skipping K modalParamsDict = dict() for mp in MODALPARAMS: modalParamsDict[mp] = None for obj in selection: if not hasattr(obj,"Path"): print "the object " + obj.Name + " is not a path. Please select only path and Compounds." return myMachine = None for pathobj in selection: if hasattr(pathobj,"MachineName"): myMachine = pathobj.MachineName if hasattr(pathobj, "MachineUnits"): if pathobj.MachineUnits == "Metric": UNITS = "G21" else: UNITS = "G20" if myMachine is None: print "No machine found in this selection" gcode ='' gcode+= mkHeader(selection) gcode+= linenumberify(GCODE_HEADER) if UNITS_INCLUDED: gcode += linenumberify(mapGCode(UNITS)) lastcommand = None gobjects = [] for g in selection[0].Group: if g.Name <>'Machine': #filtering out gcode home position from Machine object gobjects.append(g) for obj in gobjects: if hasattr(obj,'Comment'): gcode += linenumberify('(' + obj.Comment + ')') for c in obj.Path.Commands: outstring = [] command = c.Name if (command != UNITS or UNITS_INCLUDED): if command[0]=='(': command = PostUtils.fcoms(command, COMMENT) mappedCommand = mapGCode(command) # the mapping is done for output only! For internal things we still use the old value. if not MODAL or command != lastcommand: outstring.append(mappedCommand) # if MODAL == True: ) # #\better: append iff MODAL == False ) # if command == lastcommand: ) # outstring.pop(0!#\ ) if c.Parameters >= 1: for param in params: if param in c.Parameters: if (param in MODALPARAMS) and (modalParamsDict[str(param)] == c.Parameters[str(param)]): # do nothing or append white space outstring.append(' ') elif param == 'F': outstring.append(param + PostUtils.fmt(c.Parameters['F'], FEED_DECIMALS,UNITS)) elif param == 'H': outstring.append(param + str(int(c.Parameters['H']))) elif param == 'S': outstring.append(param + PostUtils.fmt(c.Parameters['S'], SPINDLE_DECIMALS,'G21')) #rpm is unitless-therefore I had to 'fake it out' by using metric units which don't get converted from entered value elif param == 'T': outstring.append(param + str(int(c.Parameters['T']))) elif param == 'I' and (command == 'G2' or command == 'G3'): # this is the special case for circular paths, where relative coordinates have to be changed to absolute i = c.Parameters['I'] # calculate the radius r j = c.Parameters['J'] r = math.sqrt(i**2 + j**2) if USE_RADIUS_IF_POSSIBLE and angleUnder180(command,lastX,lastY,c.Parameters['X'],c.Parameters['Y'],i,j): outstring.append('R' + PostUtils.fmt(r,AXIS_DECIMALS,UNITS)) else: if RADIUS_COMMENT: outstring.append('(R' + PostUtils.fmt(r,AXIS_DECIMALS,UNITS) + ')') if ABSOLUTE_CIRCLE_CENTER: i += lastX outstring.append(param + PostUtils.fmt(i,AXIS_DECIMALS,UNITS)) elif param == 'J' and (command == 'G2' or command == 'G3'): # this is the special case for circular paths, where incremental center has to be changed to absolute center i = c.Parameters['I'] j = c.Parameters['J'] if USE_RADIUS_IF_POSSIBLE and angleUnder180(command,lastX,lastY,c.Parameters['X'],c.Parameters['Y'],i,j): # R is handled with the I parameter, here: do nothing at all, keep the structure as with I command pass else: if ABSOLUTE_CIRCLE_CENTER: j += lastY if SWAP_Y_Z: # we have to swap j and k as well outstring.append('K' + PostUtils.fmt(j,AXIS_DECIMALS,UNITS)) else: outstring.append(param + PostUtils.fmt(j,AXIS_DECIMALS,UNITS)) elif param == 'K' and (command == 'G2' or command == 'G3'): # this is the special case for circular paths, where incremental center has to be changed to absolute center outstring.append('(' + param + PostUtils.fmt(c.Parameters[param],AXIS_DECIMALS,UNITS) + ')') z = c.Parameters['Z'] k = c.Parameters['K'] if USE_RADIUS_IF_POSSIBLE and angleUnder180(command,lastX,lastY,c.Parameters['X'],c.Parameters['Y'],i,j): # R is handled with the I parameter, here: do nothing at all, keep the structure as with I command pass else: if ABSOLUTE_CIRCLE_CENTER: k += lastZ if SWAP_Y_Z: # we have to swap j and k as well outstring.append('J' + PostUtils.fmt(j,AXIS_DECIMALS,UNITS)) else: outstring.append(param + PostUtils.fmt(j,AXIS_DECIMALS,UNITS)) elif param == 'Y' and SWAP_Y_Z: outstring.append('Z' + PostUtils.fmt(c.Parameters[param],AXIS_DECIMALS,UNITS)) elif param == 'Z' and SWAP_Y_Z: outstring.append('Y' + PostUtils.fmt(c.Parameters[param],AXIS_DECIMALS,UNITS)) else: outstring.append(param + PostUtils.fmt(c.Parameters[param],AXIS_DECIMALS,UNITS)) if param in MODALPARAMS: modalParamsDict[str(param)] = c.Parameters[param] # save the last X, Y, Z values if 'X' in c.Parameters: lastX = c.Parameters['X'] if 'Y' in c.Parameters: lastY = c.Parameters['Y'] if 'Z' in c.Parameters: lastZ = c.Parameters['Z'] outstr = str(outstring) outstr =outstr.replace(']','') outstr =outstr.replace('[','') outstr =outstr.replace("'",'') outstr =outstr.replace(",",'') if LINENUMBERS: gcode += "N" + str(linenr) + " " linenr += LINENUMBER_INCREMENT gcode+= outstr + '\n' lastcommand = c.Name gcode+= linenumberify(GCODE_FOOTER) if SHOW_EDITOR: PostUtils.editor(gcode) gfile = pythonopen(filename,"wb") gfile.write(gcode) gfile.close()
def parse(values, pathobj): """Parse a Path.""" out = "" lastcommand = None axis_precision_string = "." + str(values["AXIS_PRECISION"]) + "f" feed_precision_string = "." + str(values["FEED_PRECISION"]) + "f" currLocation = {} # keep track for no doubles firstmove = Path.Command("G0", {"X": -1, "Y": -1, "Z": -1, "F": 0.0}) currLocation.update(firstmove.Parameters) # set First location Parameters if hasattr(pathobj, "Group"): # We have a compound or project. if values["OUTPUT_COMMENTS"]: comment = create_comment("Compound: " + pathobj.Label, values["COMMENT_SYMBOL"]) out += linenumber(values) + comment + "\n" for p in pathobj.Group: out += parse(values, p) return out else: # parsing simple path # groups might contain non-path things like stock. if not hasattr(pathobj, "Path"): return out if values["OUTPUT_PATH_LABELS"] and values["OUTPUT_COMMENTS"]: comment = create_comment("Path: " + pathobj.Label, values["COMMENT_SYMBOL"]) out += linenumber(values) + comment + "\n" if values["OUTPUT_ADAPTIVE"]: adaptiveOp = False opHorizRapid = 0 opVertRapid = 0 if "Adaptive" in pathobj.Name: adaptiveOp = True if hasattr(pathobj, "ToolController"): if (hasattr(pathobj.ToolController, "HorizRapid") and pathobj.ToolController.HorizRapid > 0): opHorizRapid = Units.Quantity( pathobj.ToolController.HorizRapid, FreeCAD.Units.Velocity) else: FreeCAD.Console.PrintWarning( "Tool Controller Horizontal Rapid Values are unset" + "\n") if (hasattr(pathobj.ToolController, "VertRapid") and pathobj.ToolController.VertRapid > 0): opVertRapid = Units.Quantity( pathobj.ToolController.VertRapid, FreeCAD.Units.Velocity) else: FreeCAD.Console.PrintWarning( "Tool Controller Vertical Rapid Values are unset" + "\n") for c in pathobj.Path.Commands: # List of elements in the command, code, and params. outstring = [] # command M or G code or comment string command = c.Name if command[0] == "(": if values["OUTPUT_COMMENTS"]: if values["COMMENT_SYMBOL"] != "(": command = PostUtils.fcoms(command, values["COMMENT_SYMBOL"]) else: continue if values["OUTPUT_ADAPTIVE"]: if adaptiveOp and command in values["RAPID_MOVES"]: if opHorizRapid and opVertRapid: command = "G1" else: outstring.append( "(Tool Controller Rapid Values are unset)" + "\n") outstring.append(command) # if modal: suppress the command if it is the same as the last one if values["MODAL"]: if command == lastcommand: outstring.pop(0) # Now add the remaining parameters in order for param in values["PARAMETER_ORDER"]: if param in c.Parameters: if param == "F" and ( currLocation[param] != c.Parameters[param] or values["OUTPUT_DOUBLES"]): # centroid and linuxcnc don't use rapid speeds if command not in values["RAPID_MOVES"]: speed = Units.Quantity(c.Parameters["F"], FreeCAD.Units.Velocity) if speed.getValueAs( values["UNIT_SPEED_FORMAT"]) > 0.0: outstring.append(param + format( float( speed.getValueAs( values["UNIT_SPEED_FORMAT"])), feed_precision_string, )) else: continue elif param in ["H", "L", "T"]: outstring.append(param + str(int(c.Parameters[param]))) elif param == "D": if command in ["G41", "G42"]: outstring.append(param + str(int(c.Parameters[param]))) elif command in ["G96", "G97"]: outstring.append(param + PostUtils.fmt( c.Parameters[param], values["SPINDLE_DECIMALS"], "G21", )) else: # anything else that is supported (G41.1?, G42.1?) outstring.append(param + str(float(c.Parameters[param]))) elif param == "P": if command in [ "G2", "G02", "G3", "G03", "G5.2", "G5.3", "G10" ]: outstring.append(param + str(int(c.Parameters[param]))) elif command in [ "G4", "G04", "G64", "G76", "G82", "G86", "G89", ]: outstring.append(param + str(float(c.Parameters[param]))) elif command in ["G5", "G05"]: pos = Units.Quantity(c.Parameters[param], FreeCAD.Units.Length) outstring.append(param + format( float(pos.getValueAs(values["UNIT_FORMAT"])), axis_precision_string, )) else: # anything else that is supported outstring.append(param + str(c.Parameters[param])) elif param == "S": outstring.append( param + PostUtils.fmt(c.Parameters[param], values["SPINDLE_DECIMALS"], "G21")) else: if ((not values["OUTPUT_DOUBLES"]) and (param in currLocation) and (currLocation[param] == c.Parameters[param])): continue else: pos = Units.Quantity(c.Parameters[param], FreeCAD.Units.Length) outstring.append(param + format( float(pos.getValueAs(values["UNIT_FORMAT"])), axis_precision_string, )) if values["OUTPUT_ADAPTIVE"]: if adaptiveOp and command in values["RAPID_MOVES"]: if opHorizRapid and opVertRapid: if "Z" not in c.Parameters: outstring.append("F" + format( float( opHorizRapid.getValueAs( values["UNIT_SPEED_FORMAT"])), axis_precision_string, )) else: outstring.append("F" + format( float( opVertRapid.getValueAs( values["UNIT_SPEED_FORMAT"])), axis_precision_string, )) # store the latest command lastcommand = command currLocation.update(c.Parameters) # Memorizes the current position for calculating the related movements # and the withdrawal plan if command in values["MOTION_COMMANDS"]: if "X" in c.Parameters: values["CURRENT_X"] = Units.Quantity( c.Parameters["X"], FreeCAD.Units.Length) if "Y" in c.Parameters: values["CURRENT_Y"] = Units.Quantity( c.Parameters["Y"], FreeCAD.Units.Length) if "Z" in c.Parameters: values["CURRENT_Z"] = Units.Quantity( c.Parameters["Z"], FreeCAD.Units.Length) if command in ("G98", "G99"): values["DRILL_RETRACT_MODE"] = command if command in ("G90", "G91"): values["MOTION_MODE"] = command if values["TRANSLATE_DRILL_CYCLES"]: if command in values["DRILL_CYCLES_TO_TRANSLATE"]: out += drill_translate(values, outstring, command, c.Parameters) # Erase the line we just translated outstring = [] if values["SPINDLE_WAIT"] > 0: if command in ("M3", "M03", "M4", "M04"): out += (linenumber(values) + format_outstring(values, outstring) + "\n") out += (linenumber(values) + format_outstring( values, ["G4", "P%s" % values["SPINDLE_WAIT"]]) + "\n") outstring = [] # Check for Tool Change: if command in ("M6", "M06"): if values["OUTPUT_COMMENTS"]: comment = create_comment("Begin toolchange", values["COMMENT_SYMBOL"]) out += linenumber(values) + comment + "\n" if values["OUTPUT_TOOL_CHANGE"]: if values["STOP_SPINDLE_FOR_TOOL_CHANGE"]: # stop the spindle out += linenumber(values) + "M5\n" for line in values["TOOL_CHANGE"].splitlines(False): out += linenumber(values) + line + "\n" else: if values["OUTPUT_COMMENTS"]: # convert the tool change to a comment comment = create_comment( values["COMMAND_SPACE"] + format_outstring(values, outstring) + values["COMMAND_SPACE"], values["COMMENT_SYMBOL"], ) out += linenumber(values) + comment + "\n" outstring = [] if command == "message" and values["REMOVE_MESSAGES"]: if values["OUTPUT_COMMENTS"] is False: out = [] else: outstring.pop(0) # remove the command if command in values["SUPPRESS_COMMANDS"]: if values["OUTPUT_COMMENTS"]: # convert the command to a comment comment = create_comment( values["COMMAND_SPACE"] + format_outstring(values, outstring) + values["COMMAND_SPACE"], values["COMMENT_SYMBOL"], ) out += linenumber(values) + comment + "\n" # remove the command outstring = [] # prepend a line number and append a newline if len(outstring) >= 1: if values["OUTPUT_LINE_NUMBERS"]: # In this case we don't want a space after the line number # because the space is added in the join just below. outstring.insert(0, (linenumber(values, ""))) # append the line to the final output out += values["COMMAND_SPACE"].join(outstring) # Note: Do *not* strip `out`, since that forces the allocation # of a contiguous string & thus quadratic complexity. out += "\n" # add height offset if command in ("M6", "M06") and values["USE_TLO"]: out += linenumber(values) + "G43 H" + str( int(c.Parameters["T"])) + "\n" # Check for comments containing machine-specific commands # to pass literally to the controller if values["ENABLE_MACHINE_SPECIFIC_COMMANDS"]: m = re.match(r"^\(MC_RUN_COMMAND: ([^)]+)\)$", command) if m: raw_command = m.group(1) out += linenumber(values) + raw_command + "\n" return out