| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | import datetime |
| | import os |
| | from typing import Any, Dict, List |
| |
|
| | import FreeCAD |
| | import Path.Base.Util as PathUtil |
| | import Path.Post.Utils as PostUtils |
| | import Path.Post.UtilsParse as PostUtilsParse |
| | import Path.Tool.Controller as PathToolController |
| |
|
| | |
| | Gcode = List[str] |
| | Values = Dict[str, Any] |
| |
|
| |
|
| | def check_canned_cycles(values: Values) -> None: |
| | """Check canned cycles for drilling.""" |
| | if values["TRANSLATE_DRILL_CYCLES"]: |
| | if len(values["SUPPRESS_COMMANDS"]) == 0: |
| | values["SUPPRESS_COMMANDS"] = ["G99", "G98", "G80"] |
| | else: |
| | values["SUPPRESS_COMMANDS"] += ["G99", "G98", "G80"] |
| |
|
| |
|
| | def output_coolant_off(values: Values, gcode: Gcode, coolant_mode: str) -> None: |
| | """Output the commands to turn coolant off if necessary.""" |
| | comment: str |
| |
|
| | if values["ENABLE_COOLANT"] and coolant_mode != "None": |
| | if values["OUTPUT_COMMENTS"]: |
| | comment = PostUtilsParse.create_comment(values, f"Coolant Off: {coolant_mode}") |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}") |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}M9") |
| |
|
| |
|
| | def output_coolant_on(values: Values, gcode: Gcode, coolant_mode: str) -> None: |
| | """Output the commands to turn coolant on if necessary.""" |
| | comment: str |
| |
|
| | if values["ENABLE_COOLANT"]: |
| | if values["OUTPUT_COMMENTS"] and coolant_mode != "None": |
| | comment = PostUtilsParse.create_comment(values, f"Coolant On: {coolant_mode}") |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}") |
| | if coolant_mode == "Flood": |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}M8") |
| | elif coolant_mode == "Mist": |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}M7") |
| |
|
| |
|
| | def output_end_bcnc(values: Values, gcode: Gcode) -> None: |
| | """Output the ending BCNC header.""" |
| | comment: str |
| |
|
| | if values["OUTPUT_BCNC"]: |
| | comment = PostUtilsParse.create_comment(values, "Block-name: post_amble") |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}") |
| | comment = PostUtilsParse.create_comment(values, "Block-expand: 0") |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}") |
| | comment = PostUtilsParse.create_comment(values, "Block-enable: 1") |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}") |
| |
|
| |
|
| | def output_header(values: Values, gcode: Gcode) -> None: |
| | """Output the header.""" |
| | cam_file: str |
| | comment: str |
| |
|
| | if not values["OUTPUT_HEADER"]: |
| | return |
| | comment = PostUtilsParse.create_comment(values, "Exported by FreeCAD") |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}") |
| | comment = PostUtilsParse.create_comment( |
| | values, f'Post Processor: {values["POSTPROCESSOR_FILE_NAME"]}' |
| | ) |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}") |
| | if FreeCAD.ActiveDocument: |
| | cam_file = os.path.basename(FreeCAD.ActiveDocument.FileName) |
| | else: |
| | cam_file = "<None>" |
| | comment = PostUtilsParse.create_comment(values, f"Cam File: {cam_file}") |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}") |
| | comment = PostUtilsParse.create_comment(values, f"Output Time: {str(datetime.datetime.now())}") |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}") |
| |
|
| |
|
| | def output_motion_mode(values: Values, gcode: Gcode) -> None: |
| | """Verify if PREAMBLE or SAFETYBLOCK have changed MOTION_MODE.""" |
| |
|
| | if "G90" in values["PREAMBLE"] or "G90" in values["SAFETYBLOCK"]: |
| | values["MOTION_MODE"] = "G90" |
| | elif "G91" in values["PREAMBLE"] or "G91" in values["SAFETYBLOCK"]: |
| | values["MOTION_MODE"] = "G91" |
| | else: |
| | gcode.append(f'{PostUtilsParse.linenumber(values)}{values["MOTION_MODE"]}') |
| |
|
| |
|
| | def output_postamble_header(values: Values, gcode: Gcode) -> None: |
| | """Output the postamble header.""" |
| | comment: str = "" |
| |
|
| | if values["OUTPUT_COMMENTS"]: |
| | comment = PostUtilsParse.create_comment(values, "Begin postamble") |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}") |
| |
|
| |
|
| | def output_postamble(values: Values, gcode: Gcode) -> None: |
| | """Output the postamble.""" |
| | line: str |
| |
|
| | for line in values["POSTAMBLE"].splitlines(False): |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{line}") |
| |
|
| |
|
| | def output_postop(values: Values, gcode: Gcode, obj) -> None: |
| | """Output the post-operation information.""" |
| | comment: str |
| | line: str |
| |
|
| | if values["OUTPUT_COMMENTS"]: |
| | if values["SHOW_OPERATION_LABELS"]: |
| | comment = PostUtilsParse.create_comment( |
| | values, f'{values["FINISH_LABEL"]} operation: {obj.Label}' |
| | ) |
| | else: |
| | comment = PostUtilsParse.create_comment(values, f'{values["FINISH_LABEL"]} operation') |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}") |
| | for line in values["POST_OPERATION"].splitlines(False): |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{line}") |
| |
|
| |
|
| | def output_preamble(values: Values, gcode: Gcode) -> None: |
| | """Output the preamble.""" |
| | comment: str |
| | line: str |
| |
|
| | if values["OUTPUT_COMMENTS"]: |
| | comment = PostUtilsParse.create_comment(values, "Begin preamble") |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}") |
| | for line in values["PREAMBLE"].splitlines(False): |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{line}") |
| |
|
| |
|
| | def output_preop(values: Values, gcode: Gcode, obj) -> None: |
| | """Output the pre-operation information.""" |
| | comment: str |
| | line: str |
| |
|
| | if values["OUTPUT_COMMENTS"]: |
| | if values["SHOW_OPERATION_LABELS"]: |
| | comment = PostUtilsParse.create_comment(values, f"Begin operation: {obj.Label}") |
| | else: |
| | comment = PostUtilsParse.create_comment(values, "Begin operation") |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}") |
| | if values["SHOW_MACHINE_UNITS"]: |
| | comment = PostUtilsParse.create_comment( |
| | values, f'Machine units: {values["UNIT_SPEED_FORMAT"]}' |
| | ) |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}") |
| | if values["OUTPUT_MACHINE_NAME"]: |
| | comment = PostUtilsParse.create_comment( |
| | values, |
| | f'Machine: {values["MACHINE_NAME"]}, {values["UNIT_SPEED_FORMAT"]}', |
| | ) |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}") |
| | for line in values["PRE_OPERATION"].splitlines(False): |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{line}") |
| |
|
| |
|
| | def output_return_to(values: Values, gcode: Gcode) -> None: |
| | """Output the RETURN_TO command.""" |
| | cmd: str |
| | num_x: str |
| | num_y: str |
| | num_z: str |
| |
|
| | if values["RETURN_TO"]: |
| | num_x = values["RETURN_TO"][0] |
| | num_y = values["RETURN_TO"][1] |
| | num_z = values["RETURN_TO"][2] |
| | cmd = PostUtilsParse.format_command_line( |
| | values, ["G0", f"X{num_x}", f"Y{num_y}", f"Z{num_z}"] |
| | ) |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{cmd}") |
| |
|
| |
|
| | def output_safetyblock(values: Values, gcode: Gcode) -> None: |
| | """Output the safety block.""" |
| | line: str |
| |
|
| | for line in values["SAFETYBLOCK"].splitlines(False): |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{line}") |
| |
|
| |
|
| | def output_start_bcnc(values: Values, gcode: Gcode, obj) -> None: |
| | """Output the starting BCNC header.""" |
| | comment: str |
| |
|
| | if values["OUTPUT_BCNC"]: |
| | comment = PostUtilsParse.create_comment(values, f"Block-name: {obj.Label}") |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}") |
| | comment = PostUtilsParse.create_comment(values, "Block-expand: 0") |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}") |
| | comment = PostUtilsParse.create_comment(values, "Block-enable: 1") |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}") |
| |
|
| |
|
| | def output_tool_list(values: Values, gcode: Gcode, objectslist) -> None: |
| | """Output a list of the tools used in the objects.""" |
| | comment: str |
| |
|
| | if values["OUTPUT_COMMENTS"] and values["LIST_TOOLS_IN_PREAMBLE"]: |
| | for item in objectslist: |
| | if hasattr(item, "Proxy") and isinstance(item.Proxy, PathToolController.ToolController): |
| | comment = PostUtilsParse.create_comment(values, f"T{item.ToolNumber}={item.Name}") |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}") |
| |
|
| |
|
| | def output_tool_return(values: Values, gcode: Gcode) -> None: |
| | """Output the tool return block.""" |
| | line: str |
| |
|
| | for line in values["TOOLRETURN"].splitlines(False): |
| | gcode.append(f"{PostUtilsParse.linenumber(values)}{line}") |
| |
|
| |
|
| | def output_units(values: Values, gcode: Gcode) -> None: |
| | """Verify if PREAMBLE or SAFETYBLOCK have changed UNITS.""" |
| |
|
| | if "G21" in values["PREAMBLE"] or "G21" in values["SAFETYBLOCK"]: |
| | values["UNITS"] = "G21" |
| | values["UNIT_FORMAT"] = "mm" |
| | values["UNIT_SPEED_FORMAT"] = "mm/min" |
| | elif "G20" in values["PREAMBLE"] or "G20" in values["SAFETYBLOCK"]: |
| | values["UNITS"] = "G20" |
| | values["UNIT_FORMAT"] = "in" |
| | values["UNIT_SPEED_FORMAT"] = "in/min" |
| | else: |
| | gcode.append(f'{PostUtilsParse.linenumber(values)}{values["UNITS"]}') |
| |
|
| |
|
| | def export_common(values: Values, objectslist, filename: str) -> str: |
| | """Do the common parts of postprocessing the objects in objectslist to filename.""" |
| | coolant_mode: str |
| | dia: PostUtils.GCodeEditorDialog |
| | final: str |
| | final_for_editor: str |
| | gcode: Gcode = [] |
| | editor_result: int = 1 |
| |
|
| | for obj in objectslist: |
| | if not hasattr(obj, "Path"): |
| | print(f"The object {obj.Name} is not a path.") |
| | print("Please select only path and Compounds.") |
| | return "" |
| |
|
| | print(f'PostProcessor: {values["POSTPROCESSOR_FILE_NAME"]} postprocessing...') |
| |
|
| | check_canned_cycles(values) |
| | output_header(values, gcode) |
| | output_safetyblock(values, gcode) |
| | output_tool_list(values, gcode, objectslist) |
| | output_preamble(values, gcode) |
| | output_motion_mode(values, gcode) |
| | output_units(values, gcode) |
| |
|
| | for obj in objectslist: |
| | |
| | if not PathUtil.activeForOp(obj): |
| | continue |
| | coolant_mode = PathUtil.coolantModeForOp(obj) |
| | output_start_bcnc(values, gcode, obj) |
| | output_preop(values, gcode, obj) |
| | output_coolant_on(values, gcode, coolant_mode) |
| | |
| | PostUtilsParse.parse_a_group(values, gcode, obj) |
| | output_postop(values, gcode, obj) |
| | output_coolant_off(values, gcode, coolant_mode) |
| |
|
| | output_return_to(values, gcode) |
| | |
| | |
| | |
| | |
| | |
| | |
| | output_end_bcnc(values, gcode) |
| | output_postamble_header(values, gcode) |
| | output_tool_return(values, gcode) |
| | output_safetyblock(values, gcode) |
| | output_postamble(values, gcode) |
| |
|
| | |
| | gcode.append("") |
| | if values["END_OF_LINE_CHARACTERS"] == "\n\n": |
| | |
| | |
| | final = "\n\n" + "\n".join(gcode) |
| | else: |
| | |
| | |
| | |
| | |
| | final = values["END_OF_LINE_CHARACTERS"].join(gcode) |
| |
|
| | if FreeCAD.GuiUp and values["SHOW_EDITOR"]: |
| | if len(final) > 100000: |
| | print("Skipping editor since output is greater than 100kb") |
| | else: |
| | |
| | if values["END_OF_LINE_CHARACTERS"] == "\n": |
| | dia = PostUtils.GCodeEditorDialog(final, refactored=True) |
| | editor_result = dia.exec_() |
| | if editor_result == 1: |
| | final = dia.editor.toPlainText() |
| | else: |
| | final_for_editor = "\n".join(gcode) |
| | dia = PostUtils.GCodeEditorDialog(final_for_editor, refactored=True) |
| | editor_result = dia.exec_() |
| | if editor_result == 1: |
| | final_for_editor = dia.editor.toPlainText() |
| | |
| | if values["END_OF_LINE_CHARACTERS"] == "\n\n": |
| | |
| | |
| | |
| | final = "\n\n" + final_for_editor |
| | else: |
| | |
| | |
| | |
| | final = final_for_editor.replace("\n", values["END_OF_LINE_CHARACTERS"]) |
| |
|
| | if editor_result == 0: |
| | print("aborted postprocessing.") |
| | return None |
| |
|
| | if not filename == "-": |
| | if final[0:2] == "\n\n": |
| | |
| | with open(filename, "w", encoding="utf-8", newline="") as gfile: |
| | gfile.write(final[2:]) |
| | elif "\r" in final: |
| | with open(filename, "w", encoding="utf-8", newline="") as gfile: |
| | |
| | |
| | gfile.write(final) |
| | else: |
| | with open(filename, "w", encoding="utf-8", newline=None) as gfile: |
| | |
| | |
| | |
| | gfile.write(final) |
| |
|
| | print("done postprocessing.") |
| | return final |
| |
|