Kaynağa Gözat

- in NCC tool there is now a depth of cut parameter named 'Cut Z' which will dictate how deep the tool will enter into the PCB material
- in NCC tool added possibility to choose between the type of tools to be used and when V-shape is used then the tool diameter is calculated from the desired depth of cut and from the V-tip parameters

Marius Stanciu 6 yıl önce
ebeveyn
işleme
7ff8d893c0
5 değiştirilmiş dosya ile 252 ekleme ve 60 silme
  1. 9 1
      FlatCAMApp.py
  2. 3 1
      FlatCAMObj.py
  3. 5 0
      README.md
  4. 87 26
      flatcamGUI/FlatCAMGUI.py
  5. 148 32
      flatcamTools/ToolNonCopperClear.py

+ 9 - 1
FlatCAMApp.py

@@ -631,6 +631,10 @@ class App(QtCore.QObject):
             "tools_ncc_offset_value": self.ui.tools_defaults_form.tools_ncc_group.ncc_offset_spinner,
             "tools_ncc_offset_value": self.ui.tools_defaults_form.tools_ncc_group.ncc_offset_spinner,
             "tools_nccref": self.ui.tools_defaults_form.tools_ncc_group.reference_radio,
             "tools_nccref": self.ui.tools_defaults_form.tools_ncc_group.reference_radio,
             "tools_nccmilling_type": self.ui.tools_defaults_form.tools_ncc_group.milling_type_radio,
             "tools_nccmilling_type": self.ui.tools_defaults_form.tools_ncc_group.milling_type_radio,
+            "tools_ncctool_type": self.ui.tools_defaults_form.tools_ncc_group.tool_type_radio,
+            "tools_ncccutz": self.ui.tools_defaults_form.tools_ncc_group.cutz_entry,
+            "tools_ncctipdia": self.ui.tools_defaults_form.tools_ncc_group.tipdia_entry,
+            "tools_ncctipangle": self.ui.tools_defaults_form.tools_ncc_group.tipangle_entry,
 
 
             # CutOut Tool
             # CutOut Tool
             "tools_cutouttooldia": self.ui.tools_defaults_form.tools_cutout_group.cutout_tooldia_entry,
             "tools_cutouttooldia": self.ui.tools_defaults_form.tools_cutout_group.cutout_tooldia_entry,
@@ -1014,6 +1018,10 @@ class App(QtCore.QObject):
             "tools_ncc_offset_value": 0.0000,
             "tools_ncc_offset_value": 0.0000,
             "tools_nccref": 'itself',
             "tools_nccref": 'itself',
             "tools_nccmilling_type": 'cl',
             "tools_nccmilling_type": 'cl',
+            "tools_ncctool_type": 'V',
+            "tools_ncccutz": -0.001968504,
+            "tools_ncctipdia": 0.00393701,
+            "tools_ncctipangle": 30,
 
 
             "tools_cutouttooldia": 0.0944882,
             "tools_cutouttooldia": 0.0944882,
             "tools_cutoutkind": "single",
             "tools_cutoutkind": "single",
@@ -4123,7 +4131,7 @@ class App(QtCore.QObject):
                       'cncjob_tooldia',
                       'cncjob_tooldia',
 
 
                       'tools_paintmargin', 'tools_painttooldia', 'tools_paintoverlap',
                       'tools_paintmargin', 'tools_painttooldia', 'tools_paintoverlap',
-                      "tools_ncctools", "tools_nccoverlap", "tools_nccmargin",
+                      "tools_ncctools", "tools_nccoverlap", "tools_nccmargin", "tools_ncccutz", "tools_ncctipdia"
                       "tools_2sided_drilldia", "tools_film_boundary",
                       "tools_2sided_drilldia", "tools_film_boundary",
                       "tools_cutouttooldia", 'tools_cutoutmargin', 'tools_cutoutgapsize',
                       "tools_cutouttooldia", 'tools_cutoutmargin', 'tools_cutoutgapsize',
                       "tools_panelize_constrainx", "tools_panelize_constrainy",
                       "tools_panelize_constrainx", "tools_panelize_constrainy",

+ 3 - 1
FlatCAMObj.py

@@ -5687,6 +5687,7 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
         self.app.inform.emit(_("[success] Machine Code file saved to: %s") % filename)
         self.app.inform.emit(_("[success] Machine Code file saved to: %s") % filename)
 
 
     def on_edit_code_click(self, *args):
     def on_edit_code_click(self, *args):
+
         preamble = str(self.ui.prepend_text.get_value())
         preamble = str(self.ui.prepend_text.get_value())
         postamble = str(self.ui.append_text.get_value())
         postamble = str(self.ui.append_text.get_value())
         gc = self.export_gcode(preamble=preamble, postamble=postamble, to_file=True)
         gc = self.export_gcode(preamble=preamble, postamble=postamble, to_file=True)
@@ -5706,13 +5707,14 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
                 self.app.ui.code_editor.append(proc_line)
                 self.app.ui.code_editor.append(proc_line)
         except Exception as e:
         except Exception as e:
             log.debug('FlatCAMCNNJob.on_edit_code_click() -->%s' % str(e))
             log.debug('FlatCAMCNNJob.on_edit_code_click() -->%s' % str(e))
-            self.app.inform.emit(_('[ERROR]FlatCAMCNNJob.on_edit_code_click() -->%s') % str(e))
+            self.app.inform.emit(_('[ERROR] FlatCAMCNNJob.on_edit_code_click() -->%s') % str(e))
             return
             return
 
 
         self.app.ui.code_editor.moveCursor(QtGui.QTextCursor.Start)
         self.app.ui.code_editor.moveCursor(QtGui.QTextCursor.Start)
 
 
         self.app.handleTextChanged()
         self.app.handleTextChanged()
         self.app.ui.show()
         self.app.ui.show()
+        self.app.inform.emit(_('[success] Loaded Machine Code into Code Editor ...'))
 
 
     def gcode_header(self):
     def gcode_header(self):
         log.debug("FlatCAMCNCJob.gcode_header()")
         log.debug("FlatCAMCNCJob.gcode_header()")

+ 5 - 0
README.md

@@ -9,6 +9,11 @@ CAD program, and create G-Code for Isolation routing.
 
 
 =================================================
 =================================================
 
 
+3.09.2019
+
+- in NCC tool there is now a depth of cut parameter named 'Cut Z' which will dictate how deep the tool will enter into the PCB material
+- in NCC tool added possibility to choose between the type of tools to be used and when V-shape is used then the tool diameter is calculated from the desired depth of cut and from the V-tip parameters
+
 2.09.2019
 2.09.2019
 
 
 - fixed issue in NCC Tool when using area option
 - fixed issue in NCC Tool when using area option

+ 87 - 26
flatcamGUI/FlatCAMGUI.py

@@ -3448,7 +3448,6 @@ class ToolsPreferencesUI(QtWidgets.QWidget):
         self.vlay = QtWidgets.QVBoxLayout()
         self.vlay = QtWidgets.QVBoxLayout()
         self.vlay.addWidget(self.tools_ncc_group)
         self.vlay.addWidget(self.tools_ncc_group)
         self.vlay.addWidget(self.tools_paint_group)
         self.vlay.addWidget(self.tools_paint_group)
-        self.vlay.addWidget(self.tools_film_group)
 
 
         self.vlay1 = QtWidgets.QVBoxLayout()
         self.vlay1 = QtWidgets.QVBoxLayout()
         self.vlay1.addWidget(self.tools_cutout_group)
         self.vlay1.addWidget(self.tools_cutout_group)
@@ -3462,6 +3461,7 @@ class ToolsPreferencesUI(QtWidgets.QWidget):
         self.vlay3 = QtWidgets.QVBoxLayout()
         self.vlay3 = QtWidgets.QVBoxLayout()
         self.vlay3.addWidget(self.tools_solderpaste_group)
         self.vlay3.addWidget(self.tools_solderpaste_group)
         self.vlay3.addWidget(self.tools_sub_group)
         self.vlay3.addWidget(self.tools_sub_group)
+        self.vlay3.addWidget(self.tools_film_group)
 
 
         self.layout.addLayout(self.vlay)
         self.layout.addLayout(self.vlay)
         self.layout.addLayout(self.vlay1)
         self.layout.addLayout(self.vlay1)
@@ -6394,6 +6394,44 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
         self.ncc_tool_dia_entry = FCEntry()
         self.ncc_tool_dia_entry = FCEntry()
         grid0.addWidget(self.ncc_tool_dia_entry, 0, 1)
         grid0.addWidget(self.ncc_tool_dia_entry, 0, 1)
 
 
+        # Tool Type Radio Button
+        self.tool_type_label = QtWidgets.QLabel('%s:' % _('Tool Type'))
+        self.tool_type_label.setToolTip(
+            _("Default tool type:\n"
+              "- 'V-shape'\n"
+              "- Circular")
+        )
+
+        self.tool_type_radio = RadioSet([{'label': _('V-shape'), 'value': 'V'},
+                                         {'label': _('Circular'), 'value': 'C1'}])
+        self.tool_type_radio.setToolTip(
+            _("Default tool type:\n"
+              "- 'V-shape'\n"
+              "- Circular")
+        )
+
+        grid0.addWidget(self.tool_type_label, 1, 0)
+        grid0.addWidget(self.tool_type_radio, 1, 1)
+
+        # Tip Dia
+        self.tipdialabel = QtWidgets.QLabel('%s:' % _('V-Tip Dia'))
+        self.tipdialabel.setToolTip(
+            _("The tip diameter for V-Shape Tool"))
+        self.tipdia_entry = LengthEntry()
+
+        grid0.addWidget(self.tipdialabel, 2, 0)
+        grid0.addWidget(self.tipdia_entry, 2, 1)
+
+        # Tip Angle
+        self.tipanglelabel = QtWidgets.QLabel('%s:' % _('V-Tip Angle'))
+        self.tipanglelabel.setToolTip(
+            _("The tip angle for V-Shape Tool.\n"
+              "In degree."))
+        self.tipangle_entry = LengthEntry()
+
+        grid0.addWidget(self.tipanglelabel, 3, 0)
+        grid0.addWidget(self.tipangle_entry, 3, 1)
+
         # Milling Type Radio Button
         # Milling Type Radio Button
         self.milling_type_label = QtWidgets.QLabel('%s:' % _('Milling Type'))
         self.milling_type_label = QtWidgets.QLabel('%s:' % _('Milling Type'))
         self.milling_type_label.setToolTip(
         self.milling_type_label.setToolTip(
@@ -6410,9 +6448,10 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
               "- conventional / useful when there is no backlash compensation")
               "- conventional / useful when there is no backlash compensation")
         )
         )
 
 
-        grid0.addWidget(self.milling_type_label, 1, 0)
-        grid0.addWidget(self.milling_type_radio, 1, 1)
+        grid0.addWidget(self.milling_type_label, 4, 0)
+        grid0.addWidget(self.milling_type_radio, 4, 1)
 
 
+        # Tool order Radio Button
         self.ncc_order_label = QtWidgets.QLabel('%s:' % _('Tool order'))
         self.ncc_order_label = QtWidgets.QLabel('%s:' % _('Tool order'))
         self.ncc_order_label.setToolTip(_("This set the way that the tools in the tools table are used.\n"
         self.ncc_order_label.setToolTip(_("This set the way that the tools in the tools table are used.\n"
                                           "'No' --> means that the used order is the one in the tool table\n"
                                           "'No' --> means that the used order is the one in the tool table\n"
@@ -6430,9 +6469,25 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
                                           "'Reverse' --> menas that the tools will ordered from big to small\n\n"
                                           "'Reverse' --> menas that the tools will ordered from big to small\n\n"
                                           "WARNING: using rest machining will automatically set the order\n"
                                           "WARNING: using rest machining will automatically set the order\n"
                                           "in reverse and disable this control."))
                                           "in reverse and disable this control."))
-        grid0.addWidget(self.ncc_order_label, 2, 0)
-        grid0.addWidget(self.ncc_order_radio, 2, 1)
+        grid0.addWidget(self.ncc_order_label, 5, 0)
+        grid0.addWidget(self.ncc_order_radio, 5, 1)
+
+        # Cut Z entry
+        cutzlabel = QtWidgets.QLabel('%s:' % _('Cut Z'))
+        cutzlabel.setToolTip(
+           _("Depth of cut into material. Negative value.\n"
+             "In FlatCAM units.")
+        )
+        self.cutz_entry = FloatEntry()
+        self.cutz_entry.setToolTip(
+           _("Depth of cut into material. Negative value.\n"
+             "In FlatCAM units.")
+        )
+
+        grid0.addWidget(cutzlabel, 6, 0)
+        grid0.addWidget(self.cutz_entry, 6, 1)
 
 
+        # Overlap Entry
         nccoverlabel = QtWidgets.QLabel('%s:' % _('Overlap Rate'))
         nccoverlabel = QtWidgets.QLabel('%s:' % _('Overlap Rate'))
         nccoverlabel.setToolTip(
         nccoverlabel.setToolTip(
            _("How much (fraction) of the tool width to overlap each tool pass.\n"
            _("How much (fraction) of the tool width to overlap each tool pass.\n"
@@ -6445,17 +6500,18 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
              "Higher values = slow processing and slow execution on CNC\n"
              "Higher values = slow processing and slow execution on CNC\n"
              "due of too many paths.")
              "due of too many paths.")
         )
         )
-        grid0.addWidget(nccoverlabel, 3, 0)
+        grid0.addWidget(nccoverlabel, 7, 0)
         self.ncc_overlap_entry = FloatEntry()
         self.ncc_overlap_entry = FloatEntry()
-        grid0.addWidget(self.ncc_overlap_entry, 3, 1)
+        grid0.addWidget(self.ncc_overlap_entry, 7, 1)
 
 
+        # Margin entry
         nccmarginlabel = QtWidgets.QLabel('%s:' % _('Margin'))
         nccmarginlabel = QtWidgets.QLabel('%s:' % _('Margin'))
         nccmarginlabel.setToolTip(
         nccmarginlabel.setToolTip(
             _("Bounding box margin.")
             _("Bounding box margin.")
         )
         )
-        grid0.addWidget(nccmarginlabel, 4, 0)
+        grid0.addWidget(nccmarginlabel, 8, 0)
         self.ncc_margin_entry = FloatEntry()
         self.ncc_margin_entry = FloatEntry()
-        grid0.addWidget(self.ncc_margin_entry, 4, 1)
+        grid0.addWidget(self.ncc_margin_entry, 8, 1)
 
 
         # Method
         # Method
         methodlabel = QtWidgets.QLabel('%s:' % _('Method'))
         methodlabel = QtWidgets.QLabel('%s:' % _('Method'))
@@ -6465,13 +6521,13 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
               "<B>Seed-based</B>: Outwards from seed.<BR>"
               "<B>Seed-based</B>: Outwards from seed.<BR>"
               "<B>Line-based</B>: Parallel lines.")
               "<B>Line-based</B>: Parallel lines.")
         )
         )
-        grid0.addWidget(methodlabel, 5, 0)
+        grid0.addWidget(methodlabel, 9, 0)
         self.ncc_method_radio = RadioSet([
         self.ncc_method_radio = RadioSet([
             {"label": _("Standard"), "value": "standard"},
             {"label": _("Standard"), "value": "standard"},
             {"label": _("Seed-based"), "value": "seed"},
             {"label": _("Seed-based"), "value": "seed"},
             {"label": _("Straight lines"), "value": "lines"}
             {"label": _("Straight lines"), "value": "lines"}
         ], orientation='vertical', stretch=False)
         ], orientation='vertical', stretch=False)
-        grid0.addWidget(self.ncc_method_radio, 5, 1)
+        grid0.addWidget(self.ncc_method_radio, 9, 1)
 
 
         # Connect lines
         # Connect lines
         pathconnectlabel = QtWidgets.QLabel('%s:' % _("Connect"))
         pathconnectlabel = QtWidgets.QLabel('%s:' % _("Connect"))
@@ -6479,19 +6535,21 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
             _("Draw lines between resulting\n"
             _("Draw lines between resulting\n"
               "segments to minimize tool lifts.")
               "segments to minimize tool lifts.")
         )
         )
-        grid0.addWidget(pathconnectlabel, 6, 0)
+        grid0.addWidget(pathconnectlabel, 10, 0)
         self.ncc_connect_cb = FCCheckBox()
         self.ncc_connect_cb = FCCheckBox()
-        grid0.addWidget(self.ncc_connect_cb, 6, 1)
+        grid0.addWidget(self.ncc_connect_cb, 10, 1)
 
 
+        # Contour Checkbox
         contourlabel = QtWidgets.QLabel('%s:' % _("Contour"))
         contourlabel = QtWidgets.QLabel('%s:' % _("Contour"))
         contourlabel.setToolTip(
         contourlabel.setToolTip(
            _("Cut around the perimeter of the polygon\n"
            _("Cut around the perimeter of the polygon\n"
              "to trim rough edges.")
              "to trim rough edges.")
         )
         )
-        grid0.addWidget(contourlabel, 7, 0)
+        grid0.addWidget(contourlabel, 11, 0)
         self.ncc_contour_cb = FCCheckBox()
         self.ncc_contour_cb = FCCheckBox()
-        grid0.addWidget(self.ncc_contour_cb, 7, 1)
+        grid0.addWidget(self.ncc_contour_cb, 11, 1)
 
 
+        # Rest machining CheckBox
         restlabel = QtWidgets.QLabel('%s:' % _("Rest M."))
         restlabel = QtWidgets.QLabel('%s:' % _("Rest M."))
         restlabel.setToolTip(
         restlabel.setToolTip(
             _("If checked, use 'rest machining'.\n"
             _("If checked, use 'rest machining'.\n"
@@ -6502,9 +6560,9 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
               "no more copper to clear or there are no more tools.\n"
               "no more copper to clear or there are no more tools.\n"
               "If not checked, use the standard algorithm.")
               "If not checked, use the standard algorithm.")
         )
         )
-        grid0.addWidget(restlabel, 8, 0)
+        grid0.addWidget(restlabel, 12, 0)
         self.ncc_rest_cb = FCCheckBox()
         self.ncc_rest_cb = FCCheckBox()
-        grid0.addWidget(self.ncc_rest_cb, 8, 1)
+        grid0.addWidget(self.ncc_rest_cb, 12, 1)
 
 
         # ## NCC Offset choice
         # ## NCC Offset choice
         self.ncc_offset_choice_label = QtWidgets.QLabel('%s:' % _("Offset"))
         self.ncc_offset_choice_label = QtWidgets.QLabel('%s:' % _("Offset"))
@@ -6514,9 +6572,9 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
               "from the copper features.\n"
               "from the copper features.\n"
               "The value can be between 0 and 10 FlatCAM units.")
               "The value can be between 0 and 10 FlatCAM units.")
         )
         )
-        grid0.addWidget(self.ncc_offset_choice_label, 9, 0)
+        grid0.addWidget(self.ncc_offset_choice_label, 13, 0)
         self.ncc_choice_offset_cb = FCCheckBox()
         self.ncc_choice_offset_cb = FCCheckBox()
-        grid0.addWidget(self.ncc_choice_offset_cb, 9, 1)
+        grid0.addWidget(self.ncc_choice_offset_cb, 13, 1)
 
 
         # ## NCC Offset value
         # ## NCC Offset value
         self.ncc_offset_label = QtWidgets.QLabel('%s:' % _("Offset value"))
         self.ncc_offset_label = QtWidgets.QLabel('%s:' % _("Offset value"))
@@ -6526,14 +6584,14 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
               "from the copper features.\n"
               "from the copper features.\n"
               "The value can be between 0 and 10 FlatCAM units.")
               "The value can be between 0 and 10 FlatCAM units.")
         )
         )
-        grid0.addWidget(self.ncc_offset_label, 10, 0)
+        grid0.addWidget(self.ncc_offset_label, 14, 0)
         self.ncc_offset_spinner = FCDoubleSpinner()
         self.ncc_offset_spinner = FCDoubleSpinner()
         self.ncc_offset_spinner.set_range(0.00, 10.00)
         self.ncc_offset_spinner.set_range(0.00, 10.00)
         self.ncc_offset_spinner.set_precision(4)
         self.ncc_offset_spinner.set_precision(4)
         self.ncc_offset_spinner.setWrapping(True)
         self.ncc_offset_spinner.setWrapping(True)
         self.ncc_offset_spinner.setSingleStep(0.1)
         self.ncc_offset_spinner.setSingleStep(0.1)
 
 
-        grid0.addWidget(self.ncc_offset_spinner, 10, 1)
+        grid0.addWidget(self.ncc_offset_spinner, 14, 1)
 
 
         # ## Reference
         # ## Reference
         self.reference_radio = RadioSet([{'label': _('Itself'), 'value': 'itself'},
         self.reference_radio = RadioSet([{'label': _('Itself'), 'value': 'itself'},
@@ -6548,8 +6606,8 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
               "- 'Reference Object' -  will do non copper clearing within the area\n"
               "- 'Reference Object' -  will do non copper clearing within the area\n"
               "specified by another object.")
               "specified by another object.")
         )
         )
-        grid0.addWidget(reference_label, 11, 0)
-        grid0.addWidget(self.reference_radio, 11, 1)
+        grid0.addWidget(reference_label, 15, 0)
+        grid0.addWidget(self.reference_radio, 15, 1)
 
 
         self.layout.addStretch()
         self.layout.addStretch()
 
 
@@ -7460,7 +7518,8 @@ class FAExcPrefGroupUI(OptionsGroupUI):
         self.layout.addWidget(self.exc_list_text)
         self.layout.addWidget(self.exc_list_text)
 
 
         self.exc_list_btn = FCButton("Apply")
         self.exc_list_btn = FCButton("Apply")
-        self.exc_list_btn.setToolTip(_("Apply the file associations.\n"
+        self.exc_list_btn.setToolTip(_("Apply the file associations between\n"
+                                       "FlatCAM and the files with above extensions.\n"
                                        "They will be active after next logon.\n"
                                        "They will be active after next logon.\n"
                                        "This work only in Windows."))
                                        "This work only in Windows."))
         self.layout.addWidget(self.exc_list_btn)
         self.layout.addWidget(self.exc_list_btn)
@@ -7492,7 +7551,8 @@ class FAGcoPrefGroupUI(OptionsGroupUI):
         self.layout.addWidget(self.gco_list_text)
         self.layout.addWidget(self.gco_list_text)
 
 
         self.gco_list_btn = FCButton("Apply")
         self.gco_list_btn = FCButton("Apply")
-        self.gco_list_btn.setToolTip(_("Apply the file associations.\n"
+        self.gco_list_btn.setToolTip(_("Apply the file associations between\n"
+                                       "FlatCAM and the files with above extensions.\n"
                                        "They will be active after next logon.\n"
                                        "They will be active after next logon.\n"
                                        "This work only in Windows."))
                                        "This work only in Windows."))
         self.layout.addWidget(self.gco_list_btn)
         self.layout.addWidget(self.gco_list_btn)
@@ -7523,7 +7583,8 @@ class FAGrbPrefGroupUI(OptionsGroupUI):
         self.grb_list_text.setFont(font)
         self.grb_list_text.setFont(font)
 
 
         self.grb_list_btn = FCButton("Apply")
         self.grb_list_btn = FCButton("Apply")
-        self.grb_list_btn.setToolTip(_("Apply the file associations.\n"
+        self.grb_list_btn.setToolTip(_("Apply the file associations between\n"
+                                       "FlatCAM and the files with above extensions.\n"
                                        "They will be active after next logon.\n"
                                        "They will be active after next logon.\n"
                                        "This work only in Windows."))
                                        "This work only in Windows."))
         self.layout.addWidget(self.grb_list_btn)
         self.layout.addWidget(self.grb_list_btn)

+ 148 - 32
flatcamTools/ToolNonCopperClear.py

@@ -184,6 +184,23 @@ class NonCopperClear(FlatCAMTool, Gerber):
         self.milling_type_label.hide()
         self.milling_type_label.hide()
         self.milling_type_radio.hide()
         self.milling_type_radio.hide()
 
 
+        # Tool Type Radio Button
+        self.tool_type_label = QtWidgets.QLabel('%s:' % _('Tool Type'))
+        self.tool_type_label.setToolTip(
+            _("Default tool type:\n"
+              "- 'V-shape'\n"
+              "- Circular")
+        )
+
+        self.tool_type_radio = RadioSet([{'label': _('V-shape'), 'value': 'V'},
+                                         {'label': _('Circular'), 'value': 'C1'}])
+        self.tool_type_radio.setToolTip(
+            _("Default tool type:\n"
+              "- 'V-shape'\n"
+              "- Circular")
+        )
+        form.addRow(self.tool_type_label, self.tool_type_radio)
+
         # ### Add a new Tool ####
         # ### Add a new Tool ####
         self.addtool_entry_lbl = QtWidgets.QLabel('<b>%s:</b>' % _('Tool Dia'))
         self.addtool_entry_lbl = QtWidgets.QLabel('<b>%s:</b>' % _('Tool Dia'))
         self.addtool_entry_lbl.setToolTip(
         self.addtool_entry_lbl.setToolTip(
@@ -192,6 +209,21 @@ class NonCopperClear(FlatCAMTool, Gerber):
         self.addtool_entry = FCEntry2()
         self.addtool_entry = FCEntry2()
         form.addRow(self.addtool_entry_lbl, self.addtool_entry)
         form.addRow(self.addtool_entry_lbl, self.addtool_entry)
 
 
+        # Tip Dia
+        self.tipdialabel = QtWidgets.QLabel('%s:' % _('V-Tip Dia'))
+        self.tipdialabel.setToolTip(
+            _("The tip diameter for V-Shape Tool"))
+        self.tipdia_entry = LengthEntry()
+        form.addRow(self.tipdialabel, self.tipdia_entry)
+
+        # Tip Angle
+        self.tipanglelabel = QtWidgets.QLabel('%s:' % _('V-Tip Angle'))
+        self.tipanglelabel.setToolTip(
+            _("The tip angle for V-Shape Tool.\n"
+              "In degree."))
+        self.tipangle_entry = LengthEntry()
+        form.addRow(self.tipanglelabel, self.tipangle_entry)
+
         grid2 = QtWidgets.QGridLayout()
         grid2 = QtWidgets.QGridLayout()
         self.tools_box.addLayout(grid2)
         self.tools_box.addLayout(grid2)
 
 
@@ -226,6 +258,21 @@ class NonCopperClear(FlatCAMTool, Gerber):
         e_lab_1 = QtWidgets.QLabel('<b>%s:</b>' % _("Parameters"))
         e_lab_1 = QtWidgets.QLabel('<b>%s:</b>' % _("Parameters"))
         grid3.addWidget(e_lab_1, 0, 0)
         grid3.addWidget(e_lab_1, 0, 0)
 
 
+        # Cut Z entry
+        cutzlabel = QtWidgets.QLabel('%s:' % _('Cut Z'))
+        cutzlabel.setToolTip(
+           _("Depth of cut into material. Negative value.\n"
+             "In FlatCAM units.")
+        )
+        self.cutz_entry = FloatEntry()
+        self.cutz_entry.setToolTip(
+           _("Depth of cut into material. Negative value.\n"
+             "In FlatCAM units.")
+        )
+        grid3.addWidget(cutzlabel, 1, 0)
+        grid3.addWidget(self.cutz_entry, 1, 1)
+
+        # Overlap Entry
         nccoverlabel = QtWidgets.QLabel('%s:' % _('Overlap Rate'))
         nccoverlabel = QtWidgets.QLabel('%s:' % _('Overlap Rate'))
         nccoverlabel.setToolTip(
         nccoverlabel.setToolTip(
             _("How much (fraction) of the tool width to overlap each tool pass.\n"
             _("How much (fraction) of the tool width to overlap each tool pass.\n"
@@ -238,17 +285,17 @@ class NonCopperClear(FlatCAMTool, Gerber):
               "Higher values = slow processing and slow execution on CNC\n"
               "Higher values = slow processing and slow execution on CNC\n"
               "due of too many paths.")
               "due of too many paths.")
         )
         )
-        grid3.addWidget(nccoverlabel, 1, 0)
         self.ncc_overlap_entry = FCEntry()
         self.ncc_overlap_entry = FCEntry()
-        grid3.addWidget(self.ncc_overlap_entry, 1, 1)
+        grid3.addWidget(nccoverlabel, 2, 0)
+        grid3.addWidget(self.ncc_overlap_entry, 2, 1)
 
 
         nccmarginlabel = QtWidgets.QLabel('%s:' % _('Margin'))
         nccmarginlabel = QtWidgets.QLabel('%s:' % _('Margin'))
         nccmarginlabel.setToolTip(
         nccmarginlabel.setToolTip(
             _("Bounding box margin.")
             _("Bounding box margin.")
         )
         )
-        grid3.addWidget(nccmarginlabel, 2, 0)
+        grid3.addWidget(nccmarginlabel, 3, 0)
         self.ncc_margin_entry = FCEntry()
         self.ncc_margin_entry = FCEntry()
-        grid3.addWidget(self.ncc_margin_entry, 2, 1)
+        grid3.addWidget(self.ncc_margin_entry, 3, 1)
 
 
         # Method
         # Method
         methodlabel = QtWidgets.QLabel('%s:' % _('Method'))
         methodlabel = QtWidgets.QLabel('%s:' % _('Method'))
@@ -258,13 +305,13 @@ class NonCopperClear(FlatCAMTool, Gerber):
               "<B>Seed-based</B>: Outwards from seed.<BR>"
               "<B>Seed-based</B>: Outwards from seed.<BR>"
               "<B>Line-based</B>: Parallel lines.")
               "<B>Line-based</B>: Parallel lines.")
         )
         )
-        grid3.addWidget(methodlabel, 3, 0)
+        grid3.addWidget(methodlabel, 4, 0)
         self.ncc_method_radio = RadioSet([
         self.ncc_method_radio = RadioSet([
             {"label": _("Standard"), "value": "standard"},
             {"label": _("Standard"), "value": "standard"},
             {"label": _("Seed-based"), "value": "seed"},
             {"label": _("Seed-based"), "value": "seed"},
             {"label": _("Straight lines"), "value": "lines"}
             {"label": _("Straight lines"), "value": "lines"}
         ], orientation='vertical', stretch=False)
         ], orientation='vertical', stretch=False)
-        grid3.addWidget(self.ncc_method_radio, 3, 1)
+        grid3.addWidget(self.ncc_method_radio, 4, 1)
 
 
         # Connect lines
         # Connect lines
         pathconnectlabel = QtWidgets.QLabel('%s:' % _("Connect"))
         pathconnectlabel = QtWidgets.QLabel('%s:' % _("Connect"))
@@ -272,18 +319,18 @@ class NonCopperClear(FlatCAMTool, Gerber):
             _("Draw lines between resulting\n"
             _("Draw lines between resulting\n"
               "segments to minimize tool lifts.")
               "segments to minimize tool lifts.")
         )
         )
-        grid3.addWidget(pathconnectlabel, 4, 0)
+        grid3.addWidget(pathconnectlabel, 5, 0)
         self.ncc_connect_cb = FCCheckBox()
         self.ncc_connect_cb = FCCheckBox()
-        grid3.addWidget(self.ncc_connect_cb, 4, 1)
+        grid3.addWidget(self.ncc_connect_cb, 5, 1)
 
 
         contourlabel = QtWidgets.QLabel('%s:' % _("Contour"))
         contourlabel = QtWidgets.QLabel('%s:' % _("Contour"))
         contourlabel.setToolTip(
         contourlabel.setToolTip(
             _("Cut around the perimeter of the polygon\n"
             _("Cut around the perimeter of the polygon\n"
               "to trim rough edges.")
               "to trim rough edges.")
         )
         )
-        grid3.addWidget(contourlabel, 5, 0)
+        grid3.addWidget(contourlabel, 6, 0)
         self.ncc_contour_cb = FCCheckBox()
         self.ncc_contour_cb = FCCheckBox()
-        grid3.addWidget(self.ncc_contour_cb, 5, 1)
+        grid3.addWidget(self.ncc_contour_cb, 6, 1)
 
 
         restlabel = QtWidgets.QLabel('%s:' % _("Rest M."))
         restlabel = QtWidgets.QLabel('%s:' % _("Rest M."))
         restlabel.setToolTip(
         restlabel.setToolTip(
@@ -295,9 +342,9 @@ class NonCopperClear(FlatCAMTool, Gerber):
               "no more copper to clear or there are no more tools.\n"
               "no more copper to clear or there are no more tools.\n"
               "If not checked, use the standard algorithm.")
               "If not checked, use the standard algorithm.")
         )
         )
-        grid3.addWidget(restlabel, 6, 0)
+        grid3.addWidget(restlabel, 7, 0)
         self.ncc_rest_cb = FCCheckBox()
         self.ncc_rest_cb = FCCheckBox()
-        grid3.addWidget(self.ncc_rest_cb, 6, 1)
+        grid3.addWidget(self.ncc_rest_cb, 7, 1)
 
 
         # ## NCC Offset choice
         # ## NCC Offset choice
         self.ncc_offset_choice_label = QtWidgets.QLabel('%s:' % _("Offset"))
         self.ncc_offset_choice_label = QtWidgets.QLabel('%s:' % _("Offset"))
@@ -307,9 +354,9 @@ class NonCopperClear(FlatCAMTool, Gerber):
               "from the copper features.\n"
               "from the copper features.\n"
               "The value can be between 0 and 10 FlatCAM units.")
               "The value can be between 0 and 10 FlatCAM units.")
         )
         )
-        grid3.addWidget(self.ncc_offset_choice_label, 7, 0)
+        grid3.addWidget(self.ncc_offset_choice_label, 8, 0)
         self.ncc_choice_offset_cb = FCCheckBox()
         self.ncc_choice_offset_cb = FCCheckBox()
-        grid3.addWidget(self.ncc_choice_offset_cb, 7, 1)
+        grid3.addWidget(self.ncc_choice_offset_cb, 8, 1)
 
 
         # ## NCC Offset value
         # ## NCC Offset value
         self.ncc_offset_label = QtWidgets.QLabel('%s:' % _("Offset value"))
         self.ncc_offset_label = QtWidgets.QLabel('%s:' % _("Offset value"))
@@ -319,7 +366,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
               "from the copper features.\n"
               "from the copper features.\n"
               "The value can be between 0 and 10 FlatCAM units.")
               "The value can be between 0 and 10 FlatCAM units.")
         )
         )
-        grid3.addWidget(self.ncc_offset_label, 8, 0)
+        grid3.addWidget(self.ncc_offset_label, 9, 0)
         self.ncc_offset_spinner = FCDoubleSpinner()
         self.ncc_offset_spinner = FCDoubleSpinner()
         self.ncc_offset_spinner.set_range(0.00, 10.00)
         self.ncc_offset_spinner.set_range(0.00, 10.00)
         self.ncc_offset_spinner.set_precision(4)
         self.ncc_offset_spinner.set_precision(4)
@@ -331,7 +378,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
         else:
         else:
             self.ncc_offset_spinner.setSingleStep(0.01)
             self.ncc_offset_spinner.setSingleStep(0.01)
 
 
-        grid3.addWidget(self.ncc_offset_spinner, 8, 1)
+        grid3.addWidget(self.ncc_offset_spinner, 9, 1)
 
 
         self.ncc_offset_label.hide()
         self.ncc_offset_label.hide()
         self.ncc_offset_spinner.hide()
         self.ncc_offset_spinner.hide()
@@ -351,8 +398,8 @@ class NonCopperClear(FlatCAMTool, Gerber):
               "- 'Reference Object' -  will do non copper clearing within the area\n"
               "- 'Reference Object' -  will do non copper clearing within the area\n"
               "specified by another object.")
               "specified by another object.")
         )
         )
-        grid3.addWidget(self.reference_label, 9, 0)
-        grid3.addWidget(self.reference_radio, 9, 1)
+        grid3.addWidget(self.reference_label, 10, 0)
+        grid3.addWidget(self.reference_radio, 10, 1)
 
 
         form1 = QtWidgets.QFormLayout()
         form1 = QtWidgets.QFormLayout()
         self.tools_box.addLayout(form1)
         self.tools_box.addLayout(form1)
@@ -488,14 +535,20 @@ class NonCopperClear(FlatCAMTool, Gerber):
         self.ncc_rest_cb.set_value(self.app.defaults["tools_nccrest"])
         self.ncc_rest_cb.set_value(self.app.defaults["tools_nccrest"])
         self.reference_radio.set_value(self.app.defaults["tools_nccref"])
         self.reference_radio.set_value(self.app.defaults["tools_nccref"])
         self.milling_type_radio.set_value(self.app.defaults["tools_nccmilling_type"])
         self.milling_type_radio.set_value(self.app.defaults["tools_nccmilling_type"])
+        self.cutz_entry.set_value(self.app.defaults["tools_ncccutz"])
+        self.tool_type_radio.set_value(self.app.defaults["tools_ncctool_type"])
+        self.tipdia_entry.set_value(self.app.defaults["tools_ncctipdia"])
+        self.tipangle_entry.set_value(self.app.defaults["tools_ncctipangle"])
+
+        self.on_tool_type(val=self.tool_type_radio.get_value())
 
 
         # init the working variables
         # init the working variables
         self.default_data.clear()
         self.default_data.clear()
         self.default_data.update({
         self.default_data.update({
             "name": '_ncc',
             "name": '_ncc',
             "plot": self.app.defaults["geometry_plot"],
             "plot": self.app.defaults["geometry_plot"],
-            "cutz": self.app.defaults["geometry_cutz"],
-            "vtipdia": 0.1,
+            "cutz": float(self.cutz_entry.get_value()),
+            "vtipdia": 0.2,
             "vtipangle": 30,
             "vtipangle": 30,
             "travelz": self.app.defaults["geometry_travelz"],
             "travelz": self.app.defaults["geometry_travelz"],
             "feedrate": self.app.defaults["geometry_feedrate"],
             "feedrate": self.app.defaults["geometry_feedrate"],
@@ -548,9 +601,9 @@ class NonCopperClear(FlatCAMTool, Gerber):
                     'offset': 'Path',
                     'offset': 'Path',
                     'offset_value': 0.0,
                     'offset_value': 0.0,
                     'type': 'Iso',
                     'type': 'Iso',
-                    'tool_type': 'V',
+                    'tool_type': self.tool_type_radio.get_value(),
                     'operation': 'clear_op',
                     'operation': 'clear_op',
-                    'data': dict(self.default_data),
+                    'data': deepcopy(self.default_data),
                     'solid_geometry': []
                     'solid_geometry': []
                 }
                 }
             })
             })
@@ -671,6 +724,8 @@ class NonCopperClear(FlatCAMTool, Gerber):
             for col in [2, 4]:
             for col in [2, 4]:
                 self.tools_table.cellWidget(row, col).currentIndexChanged.connect(self.on_tooltable_cellwidget_change)
                 self.tools_table.cellWidget(row, col).currentIndexChanged.connect(self.on_tooltable_cellwidget_change)
 
 
+        self.tool_type_radio.activated_custom.connect(self.on_tool_type)
+
     def ui_disconnect(self):
     def ui_disconnect(self):
         try:
         try:
             # if connected, disconnect the signal from the slot on item_changed as it creates issues
             # if connected, disconnect the signal from the slot on item_changed as it creates issues
@@ -678,6 +733,12 @@ class NonCopperClear(FlatCAMTool, Gerber):
         except (TypeError, AttributeError):
         except (TypeError, AttributeError):
             pass
             pass
 
 
+        try:
+            # if connected, disconnect the signal from the slot on item_changed as it creates issues
+            self.tool_type_radio.activated_custom.disconnect(self.on_tool_type)
+        except (TypeError, AttributeError):
+            pass
+
         for row in range(self.tools_table.rowCount()):
         for row in range(self.tools_table.rowCount()):
             for col in [2, 4]:
             for col in [2, 4]:
                 try:
                 try:
@@ -757,6 +818,22 @@ class NonCopperClear(FlatCAMTool, Gerber):
                 'tool_type': tt,
                 'tool_type': tt,
             })
             })
 
 
+    def on_tool_type(self, val):
+        if val == 'V':
+            self.addtool_entry_lbl.hide()
+            self.addtool_entry.hide()
+            self.tipdialabel.show()
+            self.tipdia_entry.show()
+            self.tipanglelabel.show()
+            self.tipangle_entry.show()
+        else:
+            self.addtool_entry_lbl.show()
+            self.addtool_entry.show()
+            self.tipdialabel.hide()
+            self.tipdia_entry.hide()
+            self.tipanglelabel.hide()
+            self.tipangle_entry.hide()
+
     def on_tool_add(self, dia=None, muted=None):
     def on_tool_add(self, dia=None, muted=None):
 
 
         self.ui_disconnect()
         self.ui_disconnect()
@@ -764,16 +841,55 @@ class NonCopperClear(FlatCAMTool, Gerber):
         if dia:
         if dia:
             tool_dia = dia
             tool_dia = dia
         else:
         else:
-            try:
-                tool_dia = float(self.addtool_entry.get_value())
-            except ValueError:
-                # try to convert comma to decimal point. if it's still not working error message and return
+            if self.tool_type_radio.get_value() == 'V':
+
                 try:
                 try:
-                    tool_dia = float(self.addtool_entry.get_value().replace(',', '.'))
+                    tip_dia = float(self.tipdia_entry.get_value())
                 except ValueError:
                 except ValueError:
-                    self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
-                                           "use a number."))
-                    return
+                    # try to convert comma to decimal point. if it's still not working error message and return
+                    try:
+                        tip_dia = float(self.tipdia_entry.get_value().replace(',', '.'))
+                    except ValueError:
+                        self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
+                                               "use a number."))
+                        return
+
+                try:
+                    tip_angle = float(self.tipangle_entry.get_value()) / 2
+                except ValueError:
+                    # try to convert comma to decimal point. if it's still not working error message and return
+                    try:
+                        tip_angle = float(self.tipangle_entry.get_value().replace(',', '.')) / 2
+                    except ValueError:
+                        self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
+                                               "use a number."))
+                        return
+
+                try:
+                    cut_z = float(self.cutz_entry.get_value())
+                except ValueError:
+                    # try to convert comma to decimal point. if it's still not working error message and return
+                    try:
+                        cut_z = float(self.cutz_entry.get_value().replace(',', '.'))
+                    except ValueError:
+                        self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
+                                               "use a number."))
+                        return
+
+                tool_dia = tip_dia + 2 * cut_z * math.tan(math.radians(tip_angle))
+                tool_dia = float('%.4f' % tool_dia)
+            else:
+                try:
+                    tool_dia = float(self.addtool_entry.get_value())
+                except ValueError:
+                    # try to convert comma to decimal point. if it's still not working error message and return
+                    try:
+                        tool_dia = float(self.addtool_entry.get_value().replace(',', '.'))
+                    except ValueError:
+                        self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
+                                               "use a number."))
+                        return
+
             if tool_dia is None:
             if tool_dia is None:
                 self.build_ui()
                 self.build_ui()
                 self.app.inform.emit(_("[WARNING_NOTCL] Please enter a tool diameter to add, in Float format."))
                 self.app.inform.emit(_("[WARNING_NOTCL] Please enter a tool diameter to add, in Float format."))
@@ -817,9 +933,9 @@ class NonCopperClear(FlatCAMTool, Gerber):
                     'offset': 'Path',
                     'offset': 'Path',
                     'offset_value': 0.0,
                     'offset_value': 0.0,
                     'type': 'Iso',
                     'type': 'Iso',
-                    'tool_type': 'V',
+                    'tool_type': self.tool_type_radio.get_value(),
                     'operation': 'clear_op',
                     'operation': 'clear_op',
-                    'data': dict(self.default_data),
+                    'data': deepcopy(self.default_data),
                     'solid_geometry': []
                     'solid_geometry': []
                 }
                 }
             })
             })