From a25a70c0e1f8d77c275f72b1c0bd1d77baf9217b Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Sun, 15 Sep 2019 05:00:20 +0300 Subject: [PATCH] - refactored FlatCAMGeometry.mtool_gen_cncjob() method - fixed the TclCommandCncjob to work for multigeometry Geometry objects; still I had to fix the list of tools parameter, right now I am setting it to an empty list --- FlatCAMObj.py | 370 ++++++++++---------------------- README.md | 5 + tclCommands/TclCommandCncjob.py | 21 +- 3 files changed, 133 insertions(+), 263 deletions(-) diff --git a/FlatCAMObj.py b/FlatCAMObj.py index 05d933ab..b42635f6 100644 --- a/FlatCAMObj.py +++ b/FlatCAMObj.py @@ -2923,16 +2923,16 @@ class FlatCAMExcellon(FlatCAMObj, Excellon): # job_obj.options["tooldia"] = tools_csv = ','.join(tools) - ret_val = job_obj.generate_from_excellon_by_tool(self, tools_csv, - drillz=float(self.options['drillz']), - toolchange=self.options["toolchange"], - toolchangexy=self.app.defaults["excellon_toolchangexy"], - toolchangez=float(self.options["toolchangez"]), - startz=float(self.options["startz"]) if - self.options["startz"] else None, - endz=float(self.options["endz"]), - excellon_optimization_type=self.app.defaults[ - "excellon_optimization_type"]) + ret_val = job_obj.generate_from_excellon_by_tool( + self, tools_csv, + drillz=float(self.options['drillz']), + toolchange=self.options["toolchange"], + toolchangexy=self.app.defaults["excellon_toolchangexy"], + toolchangez=float(self.options["toolchangez"]), + startz=float(self.options["startz"]) if self.options["startz"] else None, + endz=float(self.options["endz"]), + excellon_optimization_type=self.app.defaults["excellon_optimization_type"]) + if ret_val == 'fail': return 'fail' app_obj.progress.emit(50) @@ -4462,6 +4462,8 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): def on_generatecnc_button_click(self, *args): log.debug("Generating CNCJob from Geometry ...") self.app.report_usage("geometry_on_generatecnc_button") + + # this reads the values in the UI form to the self.options dictionary self.read_form() self.sel_tools = {} @@ -4516,30 +4518,29 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed. No tool selected in the tool table ...")) - def mtool_gen_cncjob(self, segx=None, segy=None, use_thread=True): + def mtool_gen_cncjob(self, tools_dict=None, tools_in_use=None, segx=None, segy=None, use_thread=True): """ Creates a multi-tool CNCJob out of this Geometry object. The actual work is done by the target FlatCAMCNCjob object's `generate_from_geometry_2()` method. - :param z_cut: Cut depth (negative) - :param z_move: Hight of the tool when travelling (not cutting) - :param feedrate: Feed rate while cutting on X - Y plane - :param feedrate_z: Feed rate while cutting on Z plane - :param feedrate_rapid: Feed rate while moving with rapids - :param tooldia: Tool diameter - :param outname: Name of the new object - :param spindlespeed: Spindle speed (RPM) - :param ppname_g Name of the postprocessor + :param tools_dict: a dictionary that holds the whole data needed to create the Gcode + (including the solid_geometry) + + :param tools_in_use: the tools that are used, needed by some postprocessors + :type list of lists, each list in the list is made out of row elements of tools table from GUI + + :param segx: number of segments on the X axis, for auto-levelling + :param segy: number of segments on the Y axis, for auto-levelling + :param use_thread: if True use threading :return: None """ - offset_str = '' - multitool_gcode = '' - # use the name of the first tool selected in self.geo_tools_table which has the diameter passed as tool_dia outname = "%s_%s" % (self.options["name"], 'cnc') + tools_dict = self.sel_tools if tools_dict is None else tools_dict + tools_in_use = tools_in_use if tools_in_use is not None else self.get_selected_tools_table_items() segx = segx if segx is not None else float(self.app.defaults['geometry_segx']) segy = segy if segy is not None else float(self.app.defaults['geometry_segy']) @@ -4564,6 +4565,11 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): assert isinstance(job_obj, FlatCAMCNCjob), \ "Initializer expected a FlatCAMCNCjob, got %s" % type(job_obj) + job_obj.options['xmin'] = xmin + job_obj.options['ymin'] = ymin + job_obj.options['xmax'] = xmax + job_obj.options['ymax'] = ymax + # count the tools tool_cnt = 0 @@ -4573,121 +4579,28 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): job_obj.multitool = True job_obj.multigeo = False job_obj.cnc_tools.clear() - # job_obj.create_geometry() - job_obj.options['Tools_in_use'] = self.get_selected_tools_table_items() - job_obj.segx = segx - job_obj.segy = segy + job_obj.options['Tools_in_use'] = tools_in_use + job_obj.segx = segx if segx else float(self.app.defaults["geometry_segx"]) + job_obj.segy = segy if segy else float(self.app.defaults["geometry_segy"]) - try: - job_obj.z_pdepth = float(self.options["z_pdepth"]) - except ValueError: - # try to convert comma to decimal point. if it's still not working error message and return - try: - job_obj.z_pdepth = float(self.options["z_pdepth"].replace(',', '.')) - except ValueError: - self.app.inform.emit('[ERROR_NOTCL] %s' % - _('Wrong value format for self.defaults["z_pdepth"] or ' - 'self.options["z_pdepth"]')) + job_obj.z_pdepth = float(self.app.defaults["geometry_z_pdepth"]) + job_obj.feedrate_probe = float(self.app.defaults["geometry_feedrate_probe"]) - try: - job_obj.feedrate_probe = float(self.options["feedrate_probe"]) - except ValueError: - # try to convert comma to decimal point. if it's still not working error message and return - try: - job_obj.feedrate_rapid = float(self.options["feedrate_probe"].replace(',', '.')) - except ValueError: - self.app.inform.emit('[ERROR_NOTCL] %s' % - _('Wrong value format for self.defaults["feedrate_probe"] or ' - 'self.options["feedrate_probe"]')) - - for tooluid_key in self.sel_tools: + for tooluid_key in list(tools_dict.keys()): tool_cnt += 1 - app_obj.progress.emit(20) - for diadict_key, diadict_value in self.sel_tools[tooluid_key].items(): - if diadict_key == 'tooldia': - tooldia_val = float('%.4f' % float(diadict_value)) - dia_cnc_dict.update({ - diadict_key: tooldia_val - }) - if diadict_key == 'offset': - o_val = diadict_value.lower() - dia_cnc_dict.update({ - diadict_key: o_val - }) - - if diadict_key == 'type': - t_val = diadict_value - dia_cnc_dict.update({ - diadict_key: t_val - }) - - if diadict_key == 'tool_type': - tt_val = diadict_value - dia_cnc_dict.update({ - diadict_key: tt_val - }) - - if diadict_key == 'data': - for data_key, data_value in diadict_value.items(): - if data_key == "multidepth": - multidepth = data_value - if data_key == "depthperpass": - depthpercut = data_value - - if data_key == "extracut": - extracut = data_value - if data_key == "startz": - startz = data_value - if data_key == "endz": - endz = data_value - - if data_key == "toolchangez": - toolchangez = data_value - if data_key == "toolchangexy": - toolchangexy = data_value - if data_key == "toolchange": - toolchange = data_value - - if data_key == "cutz": - z_cut = data_value - if data_key == "travelz": - z_move = data_value - - if data_key == "feedrate": - feedrate = data_value - if data_key == "feedrate_z": - feedrate_z = data_value - if data_key == "feedrate_rapid": - feedrate_rapid = data_value - - if data_key == "ppname_g": - pp_geometry_name = data_value - - if data_key == "spindlespeed": - spindlespeed = data_value - if data_key == "dwell": - dwell = data_value - if data_key == "dwelltime": - dwelltime = data_value - - datadict = deepcopy(diadict_value) - dia_cnc_dict.update({ - diadict_key: datadict - }) + dia_cnc_dict = deepcopy(tools_dict[tooluid_key]) + tooldia_val = float('%.4f' % float(tools_dict[tooluid_key]['tooldia'])) + dia_cnc_dict.update({ + 'tooldia': tooldia_val + }) if dia_cnc_dict['offset'] == 'in': tool_offset = -dia_cnc_dict['tooldia'] / 2 - offset_str = 'inside' elif dia_cnc_dict['offset'].lower() == 'out': tool_offset = dia_cnc_dict['tooldia'] / 2 - offset_str = 'outside' - elif dia_cnc_dict['offset'].lower() == 'path': - offset_str = 'onpath' - tool_offset = 0.0 - else: - offset_str = 'custom' + elif dia_cnc_dict['offset'].lower() == 'custom': try: offset_value = float(self.ui.tool_offset_entry.get_value()) except ValueError: @@ -4705,10 +4618,31 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): "no value is provided.\n" "Add a Tool Offset or change the Offset Type.")) return + else: + tool_offset = 0.0 + dia_cnc_dict.update({ 'offset_value': tool_offset }) + z_cut = tools_dict[tooluid_key]['data']["cutz"] + z_move = tools_dict[tooluid_key]['data']["travelz"] + feedrate = tools_dict[tooluid_key]['data']["feedrate"] + feedrate_z = tools_dict[tooluid_key]['data']["feedrate_z"] + feedrate_rapid = tools_dict[tooluid_key]['data']["feedrate_rapid"] + multidepth = tools_dict[tooluid_key]['data']["multidepth"] + extracut = tools_dict[tooluid_key]['data']["extracut"] + depthpercut = tools_dict[tooluid_key]['data']["depthperpass"] + toolchange = tools_dict[tooluid_key]['data']["toolchange"] + toolchangez = tools_dict[tooluid_key]['data']["toolchangez"] + toolchangexy = tools_dict[tooluid_key]['data']["toolchangexy"] + startz = tools_dict[tooluid_key]['data']["startz"] + endz = tools_dict[tooluid_key]['data']["endz"] + spindlespeed = tools_dict[tooluid_key]['data']["spindlespeed"] + dwell = tools_dict[tooluid_key]['data']["dwell"] + dwelltime = tools_dict[tooluid_key]['data']["dwelltime"] + pp_geometry_name = tools_dict[tooluid_key]['data']["ppname_g"] + spindledir = self.app.defaults['geometry_spindledir'] tool_solid_geometry = self.solid_geometry @@ -4720,13 +4654,6 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): job_obj.options['type'] = 'Geometry' job_obj.options['tool_dia'] = tooldia_val - job_obj.options['xmin'] = xmin - job_obj.options['ymin'] = ymin - job_obj.options['xmax'] = xmax - job_obj.options['ymax'] = ymax - - app_obj.progress.emit(40) - # it seems that the tolerance needs to be a lot lower value than 0.01 and it was hardcoded initially # to a value of 0.0005 which is 20 times less than 0.01 tol = float(self.app.defaults['global_tolerance']) / 20 @@ -4780,44 +4707,29 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): assert isinstance(job_obj, FlatCAMCNCjob), \ "Initializer expected a FlatCAMCNCjob, got %s" % type(job_obj) - # count the tools - tool_cnt = 0 - - dia_cnc_dict = {} - current_uid = int(1) - # this turn on the FlatCAMCNCJob plot for multiple tools - job_obj.multitool = True - job_obj.multigeo = True - job_obj.cnc_tools.clear() - job_obj.options['xmin'] = xmin job_obj.options['ymin'] = ymin job_obj.options['xmax'] = xmax job_obj.options['ymax'] = ymax - try: - job_obj.z_pdepth = float(self.options["z_pdepth"]) - except ValueError: - # try to convert comma to decimal point. if it's still not working error message and return - try: - job_obj.z_pdepth = float(self.options["z_pdepth"].replace(',', '.')) - except ValueError: - self.app.inform.emit('[ERROR_NOTCL] %s' % - _('Wrong value format for self.defaults["z_pdepth"] or ' - 'self.options["z_pdepth"]')) + # count the tools + tool_cnt = 0 - try: - job_obj.feedrate_probe = float(self.options["feedrate_probe"]) - except ValueError: - # try to convert comma to decimal point. if it's still not working error message and return - try: - job_obj.feedrate_rapid = float(self.options["feedrate_probe"].replace(',', '.')) - except ValueError: - self.app.inform.emit('[ERROR_NOTCL]%s' % - _(' Wrong value format for self.defaults["feedrate_probe"] or ' - 'self.options["feedrate_probe"]')) + dia_cnc_dict = {} + + # this turn on the FlatCAMCNCJob plot for multiple tools + job_obj.multitool = True + job_obj.multigeo = True + job_obj.cnc_tools.clear() + + job_obj.options['Tools_in_use'] = tools_in_use + job_obj.segx = segx if segx else float(self.app.defaults["geometry_segx"]) + job_obj.segy = segy if segy else float(self.app.defaults["geometry_segy"]) + + job_obj.z_pdepth = float(self.app.defaults["geometry_z_pdepth"]) + job_obj.feedrate_probe = float(self.app.defaults["geometry_feedrate_probe"]) # make sure that trying to make a CNCJob from an empty file is not creating an app crash if not self.solid_geometry: @@ -4830,103 +4742,28 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): _('Cancelled. Empty file, it has no geometry')) return 'fail' - for tooluid_key in self.sel_tools: + for tooluid_key in list(tools_dict.keys()): tool_cnt += 1 - app_obj.progress.emit(20) + dia_cnc_dict = deepcopy(tools_dict[tooluid_key]) + tooldia_val = float('%.4f' % float(tools_dict[tooluid_key]['tooldia'])) + + dia_cnc_dict.update({ + 'tooldia': tooldia_val + }) # find the tool_dia associated with the tooluid_key - sel_tool_dia = self.sel_tools[tooluid_key]['tooldia'] - # search in the self.tools for the sel_tool_dia and when found see what tooluid has # on the found tooluid in self.tools we also have the solid_geometry that interest us for k, v in self.tools.items(): - if float('%.4f' % float(v['tooldia'])) == float('%.4f' % float(sel_tool_dia)): + if float('%.4f' % float(v['tooldia'])) == tooldia_val: current_uid = int(k) break - for diadict_key, diadict_value in self.sel_tools[tooluid_key].items(): - if diadict_key == 'tooldia': - tooldia_val = float('%.4f' % float(diadict_value)) - dia_cnc_dict.update({ - diadict_key: tooldia_val - }) - if diadict_key == 'offset': - o_val = diadict_value.lower() - dia_cnc_dict.update({ - diadict_key: o_val - }) - - if diadict_key == 'type': - t_val = diadict_value - dia_cnc_dict.update({ - diadict_key: t_val - }) - - if diadict_key == 'tool_type': - tt_val = diadict_value - dia_cnc_dict.update({ - diadict_key: tt_val - }) - - if diadict_key == 'data': - for data_key, data_value in diadict_value.items(): - if data_key == "multidepth": - multidepth = data_value - if data_key == "depthperpass": - depthpercut = data_value - - if data_key == "extracut": - extracut = data_value - if data_key == "startz": - startz = data_value - if data_key == "endz": - endz = data_value - - if data_key == "toolchangez": - toolchangez = data_value - if data_key == "toolchangexy": - toolchangexy = data_value - if data_key == "toolchange": - toolchange = data_value - - if data_key == "cutz": - z_cut = data_value - if data_key == "travelz": - z_move = data_value - - if data_key == "feedrate": - feedrate = data_value - if data_key == "feedrate_z": - feedrate_z = data_value - if data_key == "feedrate_rapid": - feedrate_rapid = data_value - - if data_key == "ppname_g": - pp_geometry_name = data_value - - if data_key == "spindlespeed": - spindlespeed = data_value - if data_key == "dwell": - dwell = data_value - if data_key == "dwelltime": - dwelltime = data_value - - datadict = deepcopy(diadict_value) - dia_cnc_dict.update({ - diadict_key: datadict - }) - if dia_cnc_dict['offset'] == 'in': - tool_offset = -dia_cnc_dict['tooldia'] / 2 - offset_str = 'inside' + tool_offset = -tooldia_val / 2 elif dia_cnc_dict['offset'].lower() == 'out': - tool_offset = dia_cnc_dict['tooldia'] / 2 - offset_str = 'outside' - elif dia_cnc_dict['offset'].lower() == 'path': - offset_str = 'onpath' - tool_offset = 0.0 - else: - offset_str = 'custom' + tool_offset = tooldia_val / 2 + elif dia_cnc_dict['offset'].lower() == 'custom': try: offset_value = float(self.ui.tool_offset_entry.get_value()) except ValueError: @@ -4945,10 +4782,34 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): "no value is provided.\n" "Add a Tool Offset or change the Offset Type.")) return + else: + tool_offset = 0.0 + dia_cnc_dict.update({ 'offset_value': tool_offset }) + z_cut = tools_dict[tooluid_key]['data']["cutz"] + z_move = tools_dict[tooluid_key]['data']["travelz"] + feedrate = tools_dict[tooluid_key]['data']["feedrate"] + feedrate_z = tools_dict[tooluid_key]['data']["feedrate_z"] + feedrate_rapid = tools_dict[tooluid_key]['data']["feedrate_rapid"] + multidepth = tools_dict[tooluid_key]['data']["multidepth"] + extracut = tools_dict[tooluid_key]['data']["extracut"] + depthpercut = tools_dict[tooluid_key]['data']["depthperpass"] + toolchange = tools_dict[tooluid_key]['data']["toolchange"] + toolchangez = tools_dict[tooluid_key]['data']["toolchangez"] + toolchangexy = tools_dict[tooluid_key]['data']["toolchangexy"] + startz = tools_dict[tooluid_key]['data']["startz"] + endz = tools_dict[tooluid_key]['data']["endz"] + spindlespeed = tools_dict[tooluid_key]['data']["spindlespeed"] + dwell = tools_dict[tooluid_key]['data']["dwell"] + dwelltime = tools_dict[tooluid_key]['data']["dwelltime"] + pp_geometry_name = tools_dict[tooluid_key]['data']["ppname_g"] + + spindledir = self.app.defaults['geometry_spindledir'] + tool_solid_geometry = self.tools[current_uid]['solid_geometry'] + job_obj.coords_decimals = self.app.defaults["cncjob_coords_decimals"] job_obj.fr_decimals = self.app.defaults["cncjob_fr_decimals"] @@ -4957,11 +4818,6 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): job_obj.options['type'] = 'Geometry' job_obj.options['tool_dia'] = tooldia_val - app_obj.progress.emit(40) - - spindledir = self.app.defaults['geometry_spindledir'] - tool_solid_geometry = self.tools[current_uid]['solid_geometry'] - # it seems that the tolerance needs to be a lot lower value than 0.01 and it was hardcoded initially # to a value of 0.0005 which is 20 times less than 0.01 tol = float(self.app.defaults['global_tolerance']) / 20 @@ -4993,7 +4849,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): # geo['geom'] for geo in dia_cnc_dict['gcode_parsed'] if geo['geom'].is_valid is True # ]) try: - dia_cnc_dict['solid_geometry'] = tool_solid_geometry + dia_cnc_dict['solid_geometry'] = deepcopy(tool_solid_geometry) self.app.inform.emit('[success] %s' % _("Finished G-Code processing...")) except Exception as e: self.app.inform.emit('[ERROR] %s: %s' % (_("G-Code processing failed with error"), str(e))) diff --git a/README.md b/README.md index 5cd168f1..7c6667f1 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,11 @@ CAD program, and create G-Code for Isolation routing. ================================================= +15.09.2019 + +- refactored FlatCAMGeometry.mtool_gen_cncjob() method +- fixed the TclCommandCncjob to work for multigeometry Geometry objects; still I had to fix the list of tools parameter, right now I am setting it to an empty list + 14.09.2019 - more string changes diff --git a/tclCommands/TclCommandCncjob.py b/tclCommands/TclCommandCncjob.py index bf56649e..1fd73bd9 100644 --- a/tclCommands/TclCommandCncjob.py +++ b/tclCommands/TclCommandCncjob.py @@ -28,15 +28,19 @@ class TclCommandCncjob(TclCommandSignaled): ('z_cut', float), ('z_move', float), ('feedrate', float), + ('feedrate_z', float), ('feedrate_rapid', float), - ('spindlespeed', int), ('multidepth', bool), ('extracut', bool), ('depthperpass', float), ('toolchange', int), ('toolchangez', float), ('toolchangexy', tuple), + ('startz', float), ('endz', float), + ('spindlespeed', int), + ('dwell', bool), + ('dwelltime', float), ('ppname_g', str), ('outname', str) ]) @@ -52,16 +56,20 @@ class TclCommandCncjob(TclCommandSignaled): ('tooldia', 'Tool diameter to show on screen.'), ('z_cut', 'Z-axis cutting position.'), ('z_move', 'Z-axis moving position.'), - ('feedrate', 'Moving speed when cutting.'), + ('feedrate', 'Moving speed on X-Y plane when cutting.'), + ('feedrate_z', 'Moving speed on Z plane when cutting.'), ('feedrate_rapid', 'Rapid moving at speed when cutting.'), - ('spindlespeed', 'Speed of the spindle in rpm (example: 4000).'), ('multidepth', 'Use or not multidepth cnccut. (True or False)'), - ('depthperpass', 'Height of one layer for multidepth.'), ('extracut', 'Use or not an extra cnccut over the first point in path,in the job end (example: True)'), + ('depthperpass', 'Height of one layer for multidepth.'), ('toolchange', 'Enable tool changes (example: True).'), ('toolchangez', 'Z distance for toolchange (example: 30.0).'), ('toolchangexy', 'X, Y coordonates for toolchange in format (x, y) (example: (2.0, 3.1) ).'), + ('startz', 'Height before the first move.'), ('endz', 'Height where the last move will park.'), + ('spindlespeed', 'Speed of the spindle in rpm (example: 4000).'), + ('dwell', 'True or False; use (or not) the dwell'), + ('dwelltime', 'Time to pause to allow the spindle to reach the full speed'), ('outname', 'Name of the resulting Geometry object.'), ('ppname_g', 'Name of the Geometry postprocessor. No quotes, case sensitive') ]), @@ -99,7 +107,7 @@ class TclCommandCncjob(TclCommandSignaled): args["multidepth"] = args["multidepth"] if "multidepth" in args else obj.options["multidepth"] args["depthperpass"] = args["depthperpass"] if "depthperpass" in args else obj.options["depthperpass"] args["extracut"] = args["extracut"] if "extracut" in args else obj.options["extracut"] - args["endz"]= args["endz"] if "endz" in args else obj.options["endz"] + args["endz"] = args["endz"] if "endz" in args else obj.options["endz"] args["ppname_g"] = args["ppname_g"] if "ppname_g" in args else obj.options["ppname_g"] args["toolchange"] = True if "toolchange" in args and args["toolchange"] == 1 else False @@ -114,4 +122,5 @@ class TclCommandCncjob(TclCommandSignaled): if not obj.multigeo: obj.generatecncjob(use_thread=False, **args) else: - self.raise_tcl_error('The object is a multi-geo geometry which is not supported in cncjob Tcl Command') \ No newline at end of file + obj.mtool_gen_cncjob(tools_dict=obj.tools, tools_in_use=[], use_thread=False) + # self.raise_tcl_error('The object is a multi-geo geometry which is not supported in cncjob Tcl Command')