def main(filename): try: opf = open(filename, encoding='utf-8') except TypeError: try: opf = open(filename) except IOError: error("Could not read input file {}".format(filename)) return except IOError: error("Could not read input file {}".format(filename)) return v.rawfile = opf.readlines() opf.close() v.rawfile = [item.strip() for item in v.rawfile] v.filename = filename gui.setfilename(filename) mcf.process_file()
def save_code(): output_file = v.filename.replace(".gcode", ".mcf.gcode") comment("saving output to " + output_file) header = omegaheader() comment(" number of lines: {}".format(len(header) + len(v.output_code))) try: opf = open(output_file, "w", encoding='utf-8') except TypeError: try: opf = open(output_file, "w") except IOError: error("Could not open output file {}".format(output_file)) return except IOError: error("Could not read open output {}".format(output_file)) return opf.writelines(header) opf.writelines(v.output_code) opf.close() pass
def parse_comment(line): m = v.regex_layer.match(line) if m: v.process_layer = int(m.group(1)) v.process_layer_z = float(m.group(2)) v.layer_toolchange_count.append(0) v.layer_purge_volume.append(0.0) v.layer_purge_structure.append(0) m = v.regex_p2pp.match(line) if m: p2pp_command(m.group(1), m.group(2)) m = v.regex_bed_size.match(line) if m: if m.group(1) == "X": v.bed_size_x = int(m.group(2)) else: v.bed_size_y = int(m.group(2)) m = v.regex_bed_origin.match(line) if m: if m.group(1) == "X": v.bed_min_x = int(m.group(2)) else: v.bed_min_y = int(m.group(2)) m = v.regex_layer_height.match(line) if m: lh = float(m.group(1)) if not v.layer_height: v.layer_height = lh else: if not lh == v.layer_height: error("Layer Height of all processes should be the same") m = v.regex_primepillar.match(line) if m: v.pillarposition = int(m.group(1)) m = v.regex_tower_width.match(line) if m: v.pillarwidth = int(m.group(1)) m = v.regex_extrusion_width.match(line) if m: ew = float(m.group(1)) if not v.extrusion_width: v.extrusion_width = ew else: if not ew == v.extrusion_width: error("Extruder Width of all processes should be the same") m = v.regex_use_prime_pillar.match(line) if m: if m.group(1) == "1": v.prime_pillar += 1 if line.startswith("; feature"): if "prime pillar" in line: v.mode = MODE_PURGE else: v.mode = MODE_OTHER if line.startswith("; process Input"): v.mode = MODE_OTHER return line
comment("Use: p2pp_s3d [filename]") if __name__ == "__main__": number_of_args = len(sys.argv) if number_of_args == 1: platformD = platform.system() if platformD == 'Darwin': comment('{}/p2pp_s3d.command "[output_filepath]"'.format( os.path.dirname(sys.argv[0]))) elif platformD == 'Windows': if " " in os.path.dirname(sys.argv[0]): warning("Your path contains spaces!!!") comment('"{}\\p2pp_s3d.bat" "[output_filepath]"'.format( os.path.dirname(sys.argv[0]))) else: comment('{}\\p2pp_s3d.bat "[output_filepath]"'.format( os.path.dirname(sys.argv[0]))) elif number_of_args == 2: main(filename=sys.argv[1]) else: error("[err {}] - Invalid usage:".format(number_of_args)) usage() gui.close_button_enable()
def omegaheader(): header = [] header.append('O21 ' + hexify_short(20) + "\n") if v.printerid: header.append('O22 D' + v.printerid.strip("\n") + "\n") else: error(";P2PP PRINTERPROFILE command is missing from configuration") header.append('O23 D0001' + "\n") # unused header.append('O24 D0000' + "\n") # unused toolinfo = ["D0", "D0", "D0", "D0" ] materials = {} for i in range(4): if v.toolsused[i] and v.filament_type[i] not in materials.keys(): materials[v.filament_type[i]] = len(materials.keys())+1 for i in range(4): if v.toolsused[i]: toolinfo[i] = "D{}000000input{}_{}".format(materials[v.filament_type[i]], i,v.filament_type[i]) header.append('O25 {} {} {} {}'.format(toolinfo[0],toolinfo[1],toolinfo[2],toolinfo[3]) + "\n") header.append('O26 ' + hexify_short(len(v.toolchangeinfo)) + "\n") header.append('O27 ' + hexify_short(len(v.pingpositions)) + "\n") header.append('O28 ' + hexify_short(len(v.algooverview)) + "\n") previous_change = 0 header.append('O29 ' + hexify_short(0) + "\n") v.processcomments.append("\n") v.processcomments.append(";------------------------------------\n") v.processcomments.append(";SPLICE INFORMATION - {} SPLICES\n".format(len(v.toolchangeinfo))) v.processcomments.append(";------------------------------------\n") previoussplice = 0 for i in range(len(v.toolchangeinfo)): nextpos = v.toolchangeinfo[i]["E"] if previous_change==0 and nextpos < 100: error("First splice is {:.1f}mm too short. Try adding brim or skirt".format(100-nextpos)) else: splicelength = nextpos - previous_change if splicelength < 70: error("Short splice {} is {:.1f}mm too short. Try increasing purge".format(i+1, 70-splicelength)) previous_change = nextpos header.append("O30 D{:0>1d} {}\n".format(v.toolchangeinfo[i]["Tool"], hexify_float(nextpos))) v.processcomments.append(";Tool {} Length {:.2f}mm\n".format(v.toolchangeinfo[i]["Tool"], nextpos-previoussplice)) previoussplice = nextpos v.processcomments.append("\n") v.processcomments.append("\n") v.processcomments.append(";------------------------------------\n") v.processcomments.append(";PING INFORMATION - {} PINGS\n".format(len(v.pingpositions))) v.processcomments.append(";------------------------------------\n") for i in range( len(v.pingpositions)): v.processcomments.append(";PING {:>4} at {:8.2f}mm\n".format(i,v.pingpositions[i])) v.processcomments.append("\n") if not "DEFAULT" in v.algorithm.keys(): v.algorithm['DEFAULT'] = (0,0,0) if check_tooldefs(): for algo in v.algooverview: fils = algo.split("_") if algo in v.algorithm.keys(): info = v.algorithm[algo] else: info = v.algorithm["DEFAULT"] process = "{} {} {}".format(hexify_short(int(info[0])), hexify_short(int(info[1])), hexify_short(int(info[2])) ) header.append("O32 D{}{} {}\n".format(materials[fils[0]],materials[fils[1]],process)) header.append("O1 D{} {}\n" .format("_S3D_P2PP_PRINT_", hexify_long(int(v.total_extrusion + v.extra_extrusion_at_end)))) header.append("M0\nT0\n\n") header = header + v.processcomments header.append(";--- END OF P2 HEADER ---\n") header.append("\n") return header
def process_gcode(): gui.comment("Processing " + v.filename) line_count = len(v.rawfile) line_idx = 0 for line in v.rawfile: line_idx += 1 gui.setprogress(int(50 * line_idx / line_count)) # skip fully empty lines if len(line) == 0: continue # parse comments if line.startswith(";"): line = parameters.parse_comment(line) tmp = gcode.GCodeCommand(line) # we calculate the purge for tower position # afterwards this code is removed ######################################################### if v.mode == parameters.MODE_PURGE: if tmp.E: v.purge_minx = min(v.purge_minx, tmp.get_parameter("X", 9999)) v.purge_maxx = max(v.purge_maxx, tmp.get_parameter("X", -9999)) v.purge_miny = min(v.purge_miny, tmp.get_parameter("Y", 9999)) v.purge_maxy = max(v.purge_maxy, tmp.get_parameter("Y", -9999)) if tmp.is_comment() and tmp.comment.startswith(' process'): v.gcodes.append(tmp) else: v.gcodes.append(tmp) toolchange = tmp.is_toolchange() if toolchange in [0, 1, 2, 3]: # keep track of the tools used if not v.toolsused[toolchange]: if not v.filament_type[toolchange]: error( "TOOL_{} setting command missing - output file cannot be created" .format(toolchange)) v.toolsused[toolchange] = True # calculate the purge if not (v.parse_curtool == -1): v.layer_toolchange_count[-1] += 1 if v.filament_type[toolchange] and v.filament_type[ v.parse_curtool] and not (v.parse_curtool == toolchange): v.layer_purge_volume[-1] += purgetower.calc_purge_length( v.parse_curtool, toolchange) v.parse_prevtool = v.parse_curtool v.parse_curtool = toolchange else: v.parse_curtool = v.parse_prevtool = toolchange comment("filament Info: " + v.filament_type.__str__()) comment("Tool unload info: " + v.unloadinfo.__str__()) comment("Tool load info: " + v.loadinfo.__str__()) comment("Algorithms:" + v.algorithm.__str__()) comment("Maximum purge needed per layer: {}mm".format( max(v.layer_purge_volume))) comment("Autotower function active: {}".format(v.autotower)) if v.autotower: autotower.init_autotower() _x = 0.0 _y = 0.0 for g in v.gcodes: if g.is_movement_command(): _ux = g.get_parameter("X", _x) _uy = g.get_parameter("Y", _y) _ue = g.get_parameter("E", 0) if _ue > 0: autotower.filament_mark(_x, _y, _ux, _uy) _x = _ux _y = _uy autotower.calculate_purgevolume() tower_fits = False while not tower_fits: purgetower.purge_create_layers( autotower.purge_minx - 1, autotower.purge_miny - 1, autotower.purge_maxx - autotower.purge_minx + 2, autotower.purge_maxy - autotower.purge_miny + 2) tower_fits = purgetower.simulate_tower( purgetower.sequence_length_solid, purgetower.sequence_length_empty, purgetower.sequence_length_fill, 5) if not tower_fits: if not autotower.tower_expand(): error("COULD NOT GENERATE SUITABLE TOWER") tower_fits = True v.purge_minx = autotower.purge_minx v.purge_miny = autotower.purge_miny v.purge_maxx = autotower.purge_maxx v.purge_maxy = autotower.purge_maxy else: expand = 0 tower_fits = False while not tower_fits: purgetower.purge_create_layers(v.purge_minx - 1, v.purge_miny - 1, v.purge_maxx - v.purge_minx + 2, v.purge_maxy - v.purge_miny + 2) tower_fits = purgetower.simulate_tower( purgetower.sequence_length_solid, purgetower.sequence_length_empty, purgetower.sequence_length_fill, 5) if not tower_fits: purgetower.tower_auto_expand(10) expand += 10 if expand > 0: warning("Tower expanded by {}mm".format(expand)) comment('Calculated purge volume : {:.3f},{:.3f} -> {:.3f},{:.3f}'.format( v.purge_minx, v.purge_miny, v.purge_maxx, v.purge_maxy)) line_idx = 0 line_count = len(v.gcodes) layer = -1 for g in v.gcodes: if g.layer != layer: layer = g.layer purgetower.checkfill(g.layer, v.maxtowerdelta / v.layer_height) line_idx += 1 gui.setprogress(50 + int(50 * line_idx / line_count)) if g.command in ["M220"]: g.move_to_comment("IGNORED COMMAND") g.issue_command() continue # no further mcf required if g.command == "M221": v.extrusion_multiplier = g.get_parameter( "S", v.extrusion_multiplier * 100) / 100 g.issue_command() continue # no further mcf required if g.command in ["T0", "T1", "T2", "T3"]: gcode.GCodeCommand(";---- {} TOOLCHANGE -----".format( g.command)).issue_command() process_tool_change(g) g.issue_command() continue # no further mcf required if g.command in [ "M104", "M106", "M109", "M140", "M190", "M73", "M900", "M84" ]: g.issue_command() continue # no further mcf required if g.is_movement_command(): v.current_position_x = g.get_parameter("X", v.current_position_x) v.current_position_y = g.get_parameter("Y", v.current_position_y) v.current_position_z = g.get_parameter("Z", v.current_position_z) if purgetower.moveintower(): error("MODEL COLLIDES WITH TOWER.") g.issue_command() process_tool_change(None) if v.maxdelta > 1 or v.mindelta < -1: warning( "Tower hight deviates {:.2f}mm above and {:.2f}mm below print level" .format(-v.mindelta, v.maxdelta)) warning( "Make sure to keep enough distance between tower and object to avoid collisions" ) warning( "If the tower grows over the print height, consider increasing the prime pillar width in S3D" ) gui.completed()