Kaynağa Gözat

- now extracut option in the Geometry Object will recut as many points as many they are within the specified re-cut length

Marius Stanciu 6 yıl önce
ebeveyn
işleme
511ebc274f

+ 2 - 0
FlatCAMApp.py

@@ -668,6 +668,7 @@ class App(QtCore.QObject):
             "geometry_startz": None,
             "geometry_feedrate_rapid": 1500,
             "geometry_extracut": False,
+            "geometry_extracut_length": 0.1,
             "geometry_z_pdepth": -0.02,
             "geometry_f_plunge": False,
             "geometry_spindledir": 'CW',
@@ -1260,6 +1261,7 @@ class App(QtCore.QObject):
             "geometry_startz": self.ui.geometry_defaults_form.geometry_adv_opt_group.gstartz_entry,
             "geometry_feedrate_rapid": self.ui.geometry_defaults_form.geometry_adv_opt_group.cncfeedrate_rapid_entry,
             "geometry_extracut": self.ui.geometry_defaults_form.geometry_adv_opt_group.extracut_cb,
+            "geometry_extracut_length": self.ui.geometry_defaults_form.geometry_adv_opt_group.e_cut_entry,
             "geometry_z_pdepth": self.ui.geometry_defaults_form.geometry_adv_opt_group.pdepth_entry,
             "geometry_feedrate_probe": self.ui.geometry_defaults_form.geometry_adv_opt_group.feedrate_probe_entry,
             "geometry_spindledir": self.ui.geometry_defaults_form.geometry_adv_opt_group.spindledir_radio,

+ 27 - 10
FlatCAMCommon.py

@@ -505,7 +505,7 @@ class ToolsDB(QtWidgets.QWidget):
         self.table_widget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
         table_hlay.addWidget(self.table_widget)
 
-        self.table_widget.setColumnCount(26)
+        self.table_widget.setColumnCount(27)
         # self.table_widget.setColumnWidth(0, 20)
         self.table_widget.setHorizontalHeaderLabels(
             [
@@ -530,6 +530,7 @@ class ToolsDB(QtWidgets.QWidget):
                 _("Dwelltime"),
                 _("Preprocessor"),
                 _("ExtraCut"),
+                _("E-Cut Length"),
                 _("Toolchange"),
                 _("Toolchange XY"),
                 _("Toolchange Z"),
@@ -620,23 +621,30 @@ class ToolsDB(QtWidgets.QWidget):
               "such as that this point is covered by this extra cut to\n"
               "ensure a complete isolation."))
         self.table_widget.horizontalHeaderItem(21).setToolTip(
+            _("Extra Cut length.\n"
+              "If checked, after a isolation is finished an extra cut\n"
+              "will be added where the start and end of isolation meet\n"
+              "such as that this point is covered by this extra cut to\n"
+              "ensure a complete isolation. This is the length of\n"
+              "the extra cut."))
+        self.table_widget.horizontalHeaderItem(22).setToolTip(
             _("Toolchange.\n"
               "It will create a toolchange event.\n"
               "The kind of toolchange is determined by\n"
               "the preprocessor file."))
-        self.table_widget.horizontalHeaderItem(22).setToolTip(
+        self.table_widget.horizontalHeaderItem(23).setToolTip(
             _("Toolchange XY.\n"
               "A set of coordinates in the format (x, y).\n"
               "Will determine the cartesian position of the point\n"
               "where the tool change event take place."))
-        self.table_widget.horizontalHeaderItem(23).setToolTip(
+        self.table_widget.horizontalHeaderItem(24).setToolTip(
             _("Toolchange Z.\n"
               "The position on Z plane where the tool change event take place."))
-        self.table_widget.horizontalHeaderItem(24).setToolTip(
+        self.table_widget.horizontalHeaderItem(25).setToolTip(
             _("Start Z.\n"
               "If it's left empty it will not be used.\n"
               "A position on Z plane to move immediately after job start."))
-        self.table_widget.horizontalHeaderItem(25).setToolTip(
+        self.table_widget.horizontalHeaderItem(26).setToolTip(
             _("End Z.\n"
               "A position on Z plane to move immediately after job stop."))
 
@@ -913,12 +921,18 @@ class ToolsDB(QtWidgets.QWidget):
         ecut_item.set_value(data['extracut'])
         widget.setCellWidget(row, 20, ecut_item)
 
+        ecut_length_item = FCDoubleSpinner()
+        ecut_length_item.set_precision(self.decimals)
+        ecut_length_item.set_range(0.0, 9999.9999)
+        ecut_length_item.set_value(data['extracut_length'])
+        widget.setCellWidget(row, 21, ecut_length_item)
+
         toolchange_item = FCCheckBox()
         toolchange_item.set_value(data['toolchange'])
-        widget.setCellWidget(row, 21, toolchange_item)
+        widget.setCellWidget(row, 22, toolchange_item)
 
         toolchangexy_item = QtWidgets.QTableWidgetItem(str(data['toolchangexy']) if data['toolchangexy'] else '')
-        widget.setItem(row, 22, toolchangexy_item)
+        widget.setItem(row, 23, toolchangexy_item)
 
         toolchangez_item = FCDoubleSpinner()
         toolchangez_item.set_precision(self.decimals)
@@ -929,10 +943,10 @@ class ToolsDB(QtWidgets.QWidget):
             toolchangez_item.set_range(0.0000, 9999.9999)
 
         toolchangez_item.set_value(float(data['toolchangez']))
-        widget.setCellWidget(row, 23, toolchangez_item)
+        widget.setCellWidget(row, 24, toolchangez_item)
 
         startz_item = QtWidgets.QTableWidgetItem(str(data['startz']) if data['startz'] else '')
-        widget.setItem(row, 24, startz_item)
+        widget.setItem(row, 25, startz_item)
 
         endz_item = FCDoubleSpinner()
         endz_item.set_precision(self.decimals)
@@ -943,7 +957,7 @@ class ToolsDB(QtWidgets.QWidget):
             endz_item.set_range(0.0000, 9999.9999)
 
         endz_item.set_value(float(data['endz']))
-        widget.setCellWidget(row, 25, endz_item)
+        widget.setCellWidget(row, 26, endz_item)
 
     def on_tool_add(self):
         """
@@ -970,6 +984,7 @@ class ToolsDB(QtWidgets.QWidget):
             "dwelltime": float(self.app.defaults["geometry_dwelltime"]),
             "ppname_g": self.app.defaults["geometry_ppname_g"],
             "extracut": self.app.defaults["geometry_extracut"],
+            "extracut_length": self.app.defaults["geometry_extracut_length"],
             "toolchange": self.app.defaults["geometry_toolchange"],
             "toolchangexy": self.app.defaults["geometry_toolchangexy"],
             "toolchangez": float(self.app.defaults["geometry_toolchangez"]),
@@ -1267,6 +1282,8 @@ class ToolsDB(QtWidgets.QWidget):
                         default_data['ppname_g'] = self.table_widget.cellWidget(row, col).get_value()
                     elif column_header_text == 'ExtraCut':
                         default_data['extracut'] = self.table_widget.cellWidget(row, col).get_value()
+                    elif column_header_text == "E-Cut Length":
+                        default_data['extracut_length'] = self.table_widget.cellWidget(row, col).get_value()
                     elif column_header_text == 'Toolchange':
                         default_data['toolchange'] = self.table_widget.cellWidget(row, col).get_value()
                     elif column_header_text == 'Toolchange XY':

+ 15 - 4
FlatCAMObj.py

@@ -1242,6 +1242,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
                         "ppname_g": self.app.defaults['geometry_ppname_g'],
                         "depthperpass": self.app.defaults['geometry_depthperpass'],
                         "extracut": self.app.defaults['geometry_extracut'],
+                        "extracut_length": self.app.defaults['geometry_extracut_length'],
                         "toolchange": self.app.defaults['geometry_toolchange'],
                         "toolchangez": self.app.defaults['geometry_toolchangez'],
                         "endz": self.app.defaults['geometry_endz'],
@@ -3445,6 +3446,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
             "multidepth": False,
             "depthperpass": 0.002,
             "extracut": False,
+            "extracut_length": 0.1,
             "endz": 2.0,
             "startz": None,
             "toolchange": False,
@@ -3684,6 +3686,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
             "feedrate_probe": self.ui.feedrate_probe_entry,
             "depthperpass": self.ui.maxdepth_entry,
             "extracut": self.ui.extracut_cb,
+            "extracut_length": self.ui.e_cut_entry,
             "toolchange": self.ui.toolchangeg_cb,
             "toolchangez": self.ui.toolchangez_entry,
             "endz": self.ui.gendz_entry,
@@ -3722,6 +3725,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
             "ppname_g": None,
             "depthperpass": None,
             "extracut": None,
+            "extracut_length": None,
             "toolchange": None,
             "toolchangez": None,
             "endz": None,
@@ -3814,6 +3818,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
             self.ui.fr_rapidlabel.hide()
             self.ui.cncfeedrate_rapid_entry.hide()
             self.ui.extracut_cb.hide()
+            self.ui.e_cut_entry.hide()
             self.ui.pdepth_label.hide()
             self.ui.pdepth_entry.hide()
             self.ui.feedrate_probe_label.hide()
@@ -3821,6 +3826,8 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
         else:
             self.ui.level.setText('<span style="color:red;"><b>%s</b></span>' % _('Advanced'))
 
+        self.ui.e_cut_entry.setDisabled(True)
+
         self.ui.plot_cb.stateChanged.connect(self.on_plot_cb_click)
         self.ui.generate_cnc_button.clicked.connect(self.on_generatecnc_button_click)
         self.ui.paint_tool_button.clicked.connect(lambda: self.app.paint_tool.run(toggle=False))
@@ -4975,6 +4982,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
                 feedrate_rapid = tools_dict[tooluid_key]['data']["feedrate_rapid"]
                 multidepth = tools_dict[tooluid_key]['data']["multidepth"]
                 extracut = tools_dict[tooluid_key]['data']["extracut"]
+                extracut_length = tools_dict[tooluid_key]['data']["extracut_length"]
                 depthpercut = tools_dict[tooluid_key]['data']["depthperpass"]
                 toolchange = tools_dict[tooluid_key]['data']["toolchange"]
                 toolchangez = tools_dict[tooluid_key]['data']["toolchangez"]
@@ -5006,7 +5014,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
                     feedrate=feedrate, feedrate_z=feedrate_z, feedrate_rapid=feedrate_rapid,
                     spindlespeed=spindlespeed, spindledir=spindledir, dwell=dwell, dwelltime=dwelltime,
                     multidepth=multidepth, depthpercut=depthpercut,
-                    extracut=extracut, startz=startz, endz=endz,
+                    extracut=extracut, extracut_length=extracut_length, startz=startz, endz=endz,
                     toolchange=toolchange, toolchangez=toolchangez, toolchangexy=toolchangexy,
                     pp_geometry_name=pp_geometry_name,
                     tool_no=tool_cnt)
@@ -5127,6 +5135,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
                 feedrate_rapid = tools_dict[tooluid_key]['data']["feedrate_rapid"]
                 multidepth = tools_dict[tooluid_key]['data']["multidepth"]
                 extracut = tools_dict[tooluid_key]['data']["extracut"]
+                extracut_length = tools_dict[tooluid_key]['data']["extracut_length"]
                 depthpercut = tools_dict[tooluid_key]['data']["depthperpass"]
                 toolchange = tools_dict[tooluid_key]['data']["toolchange"]
                 toolchangez = tools_dict[tooluid_key]['data']["toolchangez"]
@@ -5158,7 +5167,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
                     feedrate=feedrate, feedrate_z=feedrate_z, feedrate_rapid=feedrate_rapid,
                     spindlespeed=spindlespeed, spindledir=spindledir, dwell=dwell, dwelltime=dwelltime,
                     multidepth=multidepth, depthpercut=depthpercut,
-                    extracut=extracut, startz=startz, endz=endz,
+                    extracut=extracut, extracut_length=extracut_length, startz=startz, endz=endz,
                     toolchange=toolchange, toolchangez=toolchangez, toolchangexy=toolchangexy,
                     pp_geometry_name=pp_geometry_name,
                     tool_no=tool_cnt)
@@ -5226,7 +5235,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
             spindlespeed=None, dwell=None, dwelltime=None,
             multidepth=None, depthperpass=None,
             toolchange=None, toolchangez=None, toolchangexy=None,
-            extracut=None, startz=None, endz=None,
+            extracut=None, extracut_length=None, startz=None, endz=None,
             pp=None,
             segx=None, segy=None,
             use_thread=True,
@@ -5266,6 +5275,8 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
         segy = segy if segy is not None else float(self.app.defaults['geometry_segy'])
 
         extracut = extracut if extracut is not None else float(self.options["extracut"])
+        extracut_length = extracut_length if extracut_length is not None else float(self.options["extracut_length"])
+
         startz = startz if startz is not None else self.options["startz"]
         endz = endz if endz is not None else float(self.options["endz"])
 
@@ -5320,7 +5331,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
                 spindlespeed=spindlespeed, dwell=dwell, dwelltime=dwelltime,
                 multidepth=multidepth, depthpercut=depthperpass,
                 toolchange=toolchange, toolchangez=toolchangez, toolchangexy=toolchangexy,
-                extracut=extracut, startz=startz, endz=endz,
+                extracut=extracut, extracut_length=extracut_length, startz=startz, endz=endz,
                 pp_geometry_name=ppname_g
             )
 

+ 1 - 0
README.md

@@ -12,6 +12,7 @@ CAD program, and create G-Code for Isolation routing.
 10.12.2019
 
 - small changes in the Geometry UI
+- now extracut option in the Geometry Object will recut as many points as many they are within the specified re-cut length
 
 9.12.2019 
 

+ 44 - 21
camlib.py

@@ -2962,7 +2962,7 @@ class CNCjob(Geometry):
             feedrate=2.0, feedrate_z=2.0, feedrate_rapid=30,
             spindlespeed=None, spindledir='CW', dwell=False, dwelltime=1.0,
             multidepth=False, depthpercut=None,
-            toolchange=False, toolchangez=1.0, toolchangexy="0.0, 0.0", extracut=False,
+            toolchange=False, toolchangez=1.0, toolchangexy="0.0, 0.0", extracut=False, extracut_length=0.2,
             startz=None, endz=2.0, pp_geometry_name=None, tool_no=1):
         """
         Algorithm to generate from multitool Geometry.
@@ -2992,6 +2992,7 @@ class CNCjob(Geometry):
         :param toolchangexy:
         :param extracut:            Adds (or not) an extra cut at the end of each path overlapping the
                                     first point in path to ensure complete copper removal
+        :param extracut_length:     Extra cut legth at the end of the path
         :param startz:
         :param endz:
         :param pp_geometry_name:
@@ -3213,7 +3214,8 @@ class CNCjob(Geometry):
                     # calculate the cut distance
                     total_cut = total_cut + geo.length
 
-                    self.gcode += self.create_gcode_single_pass(geo, extracut, tolerance, old_point=current_pt)
+                    self.gcode += self.create_gcode_single_pass(geo, extracut, extracut_length, tolerance,
+                                                                old_point=current_pt)
 
                 # --------- Multi-pass ---------
                 else:
@@ -3227,7 +3229,7 @@ class CNCjob(Geometry):
 
                     total_cut += (geo.length * nr_cuts)
 
-                    self.gcode += self.create_gcode_multi_pass(geo, extracut, tolerance,
+                    self.gcode += self.create_gcode_multi_pass(geo, extracut, extracut_length, tolerance,
                                                                postproc=p, old_point=current_pt)
 
                 # calculate the total distance
@@ -3270,7 +3272,7 @@ class CNCjob(Geometry):
             spindlespeed=None, spindledir='CW', dwell=False, dwelltime=1.0,
             multidepth=False, depthpercut=None,
             toolchange=False, toolchangez=1.0, toolchangexy="0.0, 0.0",
-            extracut=False, startz=None, endz=2.0,
+            extracut=False, extracut_length=0.1, startz=None, endz=2.0,
             pp_geometry_name=None, tool_no=1):
         """
         Second algorithm to generate from Geometry.
@@ -3288,6 +3290,7 @@ class CNCjob(Geometry):
         :param depthpercut: Maximum depth in each pass.
         :param extracut: Adds (or not) an extra cut at the end of each path
             overlapping the first point in path to ensure complete copper removal
+        :param extracut_length: The extra cut length
         :return: None
         """
 
@@ -3559,7 +3562,8 @@ class CNCjob(Geometry):
                 if not multidepth:
                     # calculate the cut distance
                     total_cut += geo.length
-                    self.gcode += self.create_gcode_single_pass(geo, extracut, tolerance, old_point=current_pt)
+                    self.gcode += self.create_gcode_single_pass(geo, extracut, extracut_length, tolerance,
+                                                                old_point=current_pt)
 
                 # --------- Multi-pass ---------
                 else:
@@ -3573,7 +3577,7 @@ class CNCjob(Geometry):
 
                     total_cut += (geo.length * nr_cuts)
 
-                    self.gcode += self.create_gcode_multi_pass(geo, extracut, tolerance,
+                    self.gcode += self.create_gcode_multi_pass(geo, extracut, extracut_length, tolerance,
                                                                postproc=p, old_point=current_pt)
 
                 # calculate the travel distance
@@ -3798,7 +3802,7 @@ class CNCjob(Geometry):
             gcode += self.doformat(p.lift_code)
         return gcode
 
-    def create_gcode_single_pass(self, geometry, extracut, tolerance, old_point=(0, 0)):
+    def create_gcode_single_pass(self, geometry, extracut, extracut_length, tolerance, old_point=(0, 0)):
         # G-code. Note: self.linear2gcode() and self.point2gcode() will lower and raise the tool every time.
         gcode_single_pass = ''
 
@@ -3807,7 +3811,8 @@ class CNCjob(Geometry):
                 gcode_single_pass = self.linear2gcode(geometry, tolerance=tolerance, old_point=old_point)
             else:
                 if geometry.is_ring:
-                    gcode_single_pass = self.linear2gcode_extra(geometry, tolerance=tolerance, old_point=old_point)
+                    gcode_single_pass = self.linear2gcode_extra(geometry, extracut_length, tolerance=tolerance,
+                                                                old_point=old_point)
                 else:
                     gcode_single_pass = self.linear2gcode(geometry, tolerance=tolerance, old_point=old_point)
         elif type(geometry) == Point:
@@ -3818,7 +3823,7 @@ class CNCjob(Geometry):
 
         return gcode_single_pass
 
-    def create_gcode_multi_pass(self, geometry, extracut, tolerance, postproc, old_point=(0, 0)):
+    def create_gcode_multi_pass(self, geometry, extracut, extracut_length, tolerance, postproc, old_point=(0, 0)):
 
         gcode_multi_pass = ''
 
@@ -3851,8 +3856,8 @@ class CNCjob(Geometry):
                                                           old_point=old_point)
                 else:
                     if geometry.is_ring:
-                        gcode_multi_pass += self.linear2gcode_extra(geometry, tolerance=tolerance, z_cut=depth,
-                                                                    up=False, old_point=old_point)
+                        gcode_multi_pass += self.linear2gcode_extra(geometry, extracut_length, tolerance=tolerance,
+                                                                    z_cut=depth, up=False, old_point=old_point)
                     else:
                         gcode_multi_pass += self.linear2gcode(geometry, tolerance=tolerance, z_cut=depth, up=False,
                                                               old_point=old_point)
@@ -4513,13 +4518,14 @@ class CNCjob(Geometry):
             gcode += self.doformat(p.lift_code, x=prev_x, y=prev_y, z_move=z_move)  # Stop cutting
         return gcode
 
-    def linear2gcode_extra(self, linear, tolerance=0, down=True, up=True,
+    def linear2gcode_extra(self, linear, extracut_length, tolerance=0, down=True, up=True,
                      z_cut=None, z_move=None, zdownrate=None,
                      feedrate=None, feedrate_z=None, feedrate_rapid=None, cont=False, old_point=(0, 0)):
         """
         Generates G-code to cut along the linear feature.
 
         :param linear: The path to cut along.
+        :param extracut_length: how much to cut extra over the first point at the end of the path
         :type: Shapely.LinearRing or Shapely.Linear String
         :param tolerance: All points in the simplified object will be within the
             tolerance distance of the original geometry.
@@ -4613,19 +4619,36 @@ class CNCjob(Geometry):
         # this line is added to create an extra cut over the first point in patch
         # to make sure that we remove the copper leftovers
         # Linear motion to the 1st point in the cut path
-        if self.coordinates_type == "G90":
-            # For Absolute coordinates type G90
-            last_x = path[1][0]
-            last_y = path[1][1]
+        # if self.coordinates_type == "G90":
+        #     # For Absolute coordinates type G90
+        #     last_x = path[1][0]
+        #     last_y = path[1][1]
+        # else:
+        #     # For Incremental coordinates type G91
+        #     last_x = path[1][0] - first_x
+        #     last_y = path[1][1] - first_y
+        # gcode += self.doformat(p.linear_code, x=last_x, y=last_y)
+
+        # the first point for extracut is always mandatory if the extracut is enabled. But if the length of distance
+        # between point 0 and point 1 is more than the distance we set for the extra cut then make an interpolation
+        # along the path and find the point at the distance extracut_length
+
+        if abs(distance(path[1], path[0])) > extracut_length:
+            i_point = LineString([path[0], path[1]]).interpolate(extracut_length)
+            gcode += self.doformat(p.linear_code, x=i_point.x, y=i_point.y)
         else:
-            # For Incremental coordinates type G91
-            last_x = path[1][0] - first_x
-            last_y = path[1][1] - first_y
-        gcode += self.doformat(p.linear_code, x=last_x, y=last_y)
+            last_pt = path[0]
+            for pt in path[1:]:
+                extracut_distance = abs(distance(pt, last_pt))
+                if extracut_distance <= extracut_length:
+                    gcode += self.doformat(p.linear_code, x=pt[0], y=pt[1])
+                    last_pt = pt
+                else:
+                    break
 
         # Up to travelling height.
         if up:
-            gcode += self.doformat(p.lift_code, x=last_x, y=last_y, z_move=z_move)  # Stop cutting
+            gcode += self.doformat(p.lift_code, x=pt[0], y=pt[1], z_move=z_move)  # Stop cutting
 
         return gcode
 

+ 16 - 1
flatcamGUI/ObjectUI.py

@@ -1520,14 +1520,29 @@ class GeometryObjectUI(ObjectUI):
         self.cncfeedrate_rapid_entry.hide()
 
         # Cut over 1st point in path
-        self.extracut_cb = FCCheckBox('%s' % _('Re-cut 1st pt.'))
+        self.extracut_cb = FCCheckBox('%s' % _('Re-cut'))
         self.extracut_cb.setToolTip(
             _("In order to remove possible\n"
               "copper leftovers where first cut\n"
               "meet with last cut, we generate an\n"
               "extended cut over the first cut section.")
         )
+
+        self.e_cut_entry = FCDoubleSpinner()
+        self.e_cut_entry.set_range(0, 99999)
+        self.e_cut_entry.set_precision(self.decimals)
+        self.e_cut_entry.setSingleStep(0.1)
+        self.e_cut_entry.setWrapping(True)
+        self.e_cut_entry.setToolTip(
+            _("In order to remove possible\n"
+              "copper leftovers where first cut\n"
+              "meet with last cut, we generate an\n"
+              "extended cut over the first cut section.")
+        )
         self.grid3.addWidget(self.extracut_cb, 13, 0)
+        self.grid3.addWidget(self.e_cut_entry, 13, 1)
+
+        self.ois_e_cut = OptionalInputSection(self.extracut_cb, [self.e_cut_entry])
 
         # Spindlespeed
         spdlabel = QtWidgets.QLabel('%s:' % _('Spindle speed'))

+ 14 - 1
flatcamGUI/PreferencesUI.py

@@ -3440,14 +3440,27 @@ class GeometryAdvOptPrefGroupUI(OptionsGroupUI):
         grid1.addWidget(self.cncfeedrate_rapid_entry, 4, 1)
 
         # End move extra cut
-        self.extracut_cb = FCCheckBox(label='%s' % _('Re-cut 1st pt.'))
+        self.extracut_cb = FCCheckBox('%s' % _('Re-cut'))
         self.extracut_cb.setToolTip(
             _("In order to remove possible\n"
               "copper leftovers where first cut\n"
               "meet with last cut, we generate an\n"
               "extended cut over the first cut section.")
         )
+
+        self.e_cut_entry = FCDoubleSpinner()
+        self.e_cut_entry.set_range(0, 99999)
+        self.e_cut_entry.set_precision(self.decimals)
+        self.e_cut_entry.setSingleStep(0.1)
+        self.e_cut_entry.setWrapping(True)
+        self.e_cut_entry.setToolTip(
+            _("In order to remove possible\n"
+              "copper leftovers where first cut\n"
+              "meet with last cut, we generate an\n"
+              "extended cut over the first cut section.")
+        )
         grid1.addWidget(self.extracut_cb, 5, 0)
+        grid1.addWidget(self.e_cut_entry, 5, 1)
 
         # Probe depth
         self.pdepth_label = QtWidgets.QLabel('%s:' % _("Probe Z depth"))

+ 1 - 0
flatcamTools/ToolNonCopperClear.py

@@ -681,6 +681,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
             "ppname_g": self.app.defaults["geometry_ppname_g"],
             "depthperpass": self.app.defaults["geometry_depthperpass"],
             "extracut": self.app.defaults["geometry_extracut"],
+            "extracut_length": self.app.defaults["geometry_extracut_length"],
             "toolchange": self.app.defaults["geometry_toolchange"],
             "toolchangez": self.app.defaults["geometry_toolchangez"],
             "endz": self.app.defaults["geometry_endz"],

+ 2 - 0
flatcamTools/ToolPaint.py

@@ -440,6 +440,7 @@ class ToolPaint(FlatCAMTool, Gerber):
             "ppname_g": self.app.defaults["geometry_ppname_g"],
             "depthperpass": self.app.defaults["geometry_depthperpass"],
             "extracut": self.app.defaults["geometry_extracut"],
+            "extracut_length": self.app.defaults["geometry_extracut_length"],
             "toolchange": self.app.defaults["geometry_toolchange"],
             "toolchangez": self.app.defaults["geometry_toolchangez"],
             "endz": self.app.defaults["geometry_endz"],
@@ -633,6 +634,7 @@ class ToolPaint(FlatCAMTool, Gerber):
             "ppname_g": self.app.defaults["geometry_ppname_g"],
             "depthperpass": float(self.app.defaults["geometry_depthperpass"]),
             "extracut": self.app.defaults["geometry_extracut"],
+            "extracut_length": self.app.defaults["geometry_extracut_length"],
             "toolchange": self.app.defaults["geometry_toolchange"],
             "toolchangez": float(self.app.defaults["geometry_toolchangez"]),
             "endz": float(self.app.defaults["geometry_endz"]),

+ 5 - 0
tclCommands/TclCommandCncjob.py

@@ -35,6 +35,7 @@ class TclCommandCncjob(TclCommandSignaled):
         ('feedrate_rapid', float),
         ('multidepth', bool),
         ('extracut', bool),
+        ('extracut_length', float),
         ('depthperpass', float),
         ('toolchange', int),
         ('toolchangez', float),
@@ -65,6 +66,7 @@ class TclCommandCncjob(TclCommandSignaled):
             ('feedrate_rapid', 'Rapid moving at speed when cutting.'),
             ('multidepth', 'Use or not multidepth cnc cut. (True or False)'),
             ('extracut', 'Use or not an extra cnccut over the first point in path,in the job end (example: True)'),
+            ('extracut', 'The value for extra cnccut over the first point in path,in the job end; float'),
             ('depthperpass', 'Height of one layer for multidepth.'),
             ('toolchange', 'Enable tool changes (example: True).'),
             ('toolchangez', 'Z distance for toolchange (example: 30.0).'),
@@ -136,6 +138,8 @@ class TclCommandCncjob(TclCommandSignaled):
 
         args["multidepth"] = bool(args["multidepth"]) if "multidepth" in args else obj.options["multidepth"]
         args["extracut"] = bool(args["extracut"]) if "extracut" in args else obj.options["extracut"]
+        args["extracut_length"] = float(args["extracut_length"]) if "extracut_length" in args else \
+            obj.options["extracut_length"]
         args["depthperpass"] = args["depthperpass"] if "depthperpass" in args and args["depthperpass"] else \
             obj.options["depthperpass"]
 
@@ -189,6 +193,7 @@ class TclCommandCncjob(TclCommandSignaled):
                     local_tools_dict[tool_uid]['data']['feedrate_rapid'] = args["feedrate_rapid"]
                     local_tools_dict[tool_uid]['data']['multidepth'] = args["multidepth"]
                     local_tools_dict[tool_uid]['data']['extracut'] = args["extracut"]
+                    local_tools_dict[tool_uid]['data']['extracut_length'] = args["extracut_length"]
                     local_tools_dict[tool_uid]['data']['depthperpass'] = args["depthperpass"]
                     local_tools_dict[tool_uid]['data']['toolchange'] = args["toolchange"]
                     local_tools_dict[tool_uid]['data']['toolchangez'] = args["toolchangez"]

+ 1 - 0
tclCommands/TclCommandCopperClear.py

@@ -170,6 +170,7 @@ class TclCommandCopperClear(TclCommand):
             "ppname_g": self.app.defaults["geometry_ppname_g"],
             "depthperpass": self.app.defaults["geometry_depthperpass"],
             "extracut": self.app.defaults["geometry_extracut"],
+            "extracut_length": self.app.defaults["geometry_extracut_length"],
             "toolchange": self.app.defaults["geometry_toolchange"],
             "toolchangez": self.app.defaults["geometry_toolchangez"],
             "endz": self.app.defaults["geometry_endz"],

+ 1 - 0
tclCommands/TclCommandPaint.py

@@ -159,6 +159,7 @@ class TclCommandPaint(TclCommand):
             "ppname_g": self.app.defaults["geometry_ppname_g"],
             "depthperpass": self.app.defaults["geometry_depthperpass"],
             "extracut": self.app.defaults["geometry_extracut"],
+            "extracut_length": self.app.defaults["geometry_extracut_length"],
             "toolchange": self.app.defaults["geometry_toolchange"],
             "toolchangez": self.app.defaults["geometry_toolchangez"],
             "endz": self.app.defaults["geometry_endz"],