Просмотр исходного кода

- in Properties Tool made threaded the calculation of convex_hull area and to work for multi-geo objects
- in NCC tool the type of tool that is used is transferred to the Geometry object
- in NCC tool the type of isolation done with the tools selected as isolation tools can now be selected and it has also an Edit -> Preferences entry

Marius Stanciu 6 лет назад
Родитель
Сommit
60512f09a7
5 измененных файлов с 165 добавлено и 47 удалено
  1. 2 0
      FlatCAMApp.py
  2. 3 0
      README.md
  3. 39 20
      flatcamGUI/FlatCAMGUI.py
  4. 79 8
      flatcamTools/ToolNonCopperClear.py
  5. 42 19
      flatcamTools/ToolProperties.py

+ 2 - 0
FlatCAMApp.py

@@ -630,6 +630,7 @@ class App(QtCore.QObject):
             "tools_ncc_offset_choice": self.ui.tools_defaults_form.tools_ncc_group.ncc_choice_offset_cb,
             "tools_ncc_offset_choice": self.ui.tools_defaults_form.tools_ncc_group.ncc_choice_offset_cb,
             "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,
 
 
             # 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,
@@ -1012,6 +1013,7 @@ class App(QtCore.QObject):
             "tools_ncc_offset_choice": False,
             "tools_ncc_offset_choice": False,
             "tools_ncc_offset_value": 0.0000,
             "tools_ncc_offset_value": 0.0000,
             "tools_nccref": 'itself',
             "tools_nccref": 'itself',
+            "tools_nccmilling_type": 'cl',
 
 
             "tools_cutouttooldia": 0.0944882,
             "tools_cutouttooldia": 0.0944882,
             "tools_cutoutkind": "single",
             "tools_cutoutkind": "single",

+ 3 - 0
README.md

@@ -16,6 +16,9 @@ CAD program, and create G-Code for Isolation routing.
 - made changes in the Excellon Tools Table to make it more clear that the tools are selected in the # column and not in the Plot column
 - made changes in the Excellon Tools Table to make it more clear that the tools are selected in the # column and not in the Plot column
 - in Excellon and Gerber Seleted tab made the Plot (mark) columns not selectable
 - in Excellon and Gerber Seleted tab made the Plot (mark) columns not selectable
 - some ToolTips were modified
 - some ToolTips were modified
+- in Properties Tool made threaded the calculation of convex_hull area and to work for multi-geo objects
+- in NCC tool the type of tool that is used is transferred to the Geometry object
+- in NCC tool the type of isolation done with the tools selected as isolation tools can now be selected and it has also an Edit -> Preferences entry
 
 
 1.09.2019
 1.09.2019
 
 

+ 39 - 20
flatcamGUI/FlatCAMGUI.py

@@ -6394,6 +6394,25 @@ 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)
 
 
+        # Milling Type Radio Button
+        self.milling_type_label = QtWidgets.QLabel('%s:' % _('Milling Type'))
+        self.milling_type_label.setToolTip(
+            _("Milling type when the selected tool is of type: 'iso_op':\n"
+              "- climb / best for precision milling and to reduce tool usage\n"
+              "- conventional / useful when there is no backlash compensation")
+        )
+
+        self.milling_type_radio = RadioSet([{'label': _('Climb'), 'value': 'cl'},
+                                            {'label': _('Conv.'), 'value': 'cv'}])
+        self.milling_type_radio.setToolTip(
+            _("Milling type when the selected tool is of type: 'iso_op':\n"
+              "- climb / best for precision milling and to reduce tool usage\n"
+              "- conventional / useful when there is no backlash compensation")
+        )
+
+        grid0.addWidget(self.milling_type_label, 1, 0)
+        grid0.addWidget(self.milling_type_radio, 1, 1)
+
         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"
@@ -6411,8 +6430,8 @@ 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, 1, 0)
-        grid0.addWidget(self.ncc_order_radio, 1, 1)
+        grid0.addWidget(self.ncc_order_label, 2, 0)
+        grid0.addWidget(self.ncc_order_radio, 2, 1)
 
 
         nccoverlabel = QtWidgets.QLabel('%s:' % _('Overlap Rate'))
         nccoverlabel = QtWidgets.QLabel('%s:' % _('Overlap Rate'))
         nccoverlabel.setToolTip(
         nccoverlabel.setToolTip(
@@ -6426,17 +6445,17 @@ 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, 2, 0)
+        grid0.addWidget(nccoverlabel, 3, 0)
         self.ncc_overlap_entry = FloatEntry()
         self.ncc_overlap_entry = FloatEntry()
-        grid0.addWidget(self.ncc_overlap_entry, 2, 1)
+        grid0.addWidget(self.ncc_overlap_entry, 3, 1)
 
 
         nccmarginlabel = QtWidgets.QLabel('%s:' % _('Margin'))
         nccmarginlabel = QtWidgets.QLabel('%s:' % _('Margin'))
         nccmarginlabel.setToolTip(
         nccmarginlabel.setToolTip(
             _("Bounding box margin.")
             _("Bounding box margin.")
         )
         )
-        grid0.addWidget(nccmarginlabel, 3, 0)
+        grid0.addWidget(nccmarginlabel, 4, 0)
         self.ncc_margin_entry = FloatEntry()
         self.ncc_margin_entry = FloatEntry()
-        grid0.addWidget(self.ncc_margin_entry, 3, 1)
+        grid0.addWidget(self.ncc_margin_entry, 4, 1)
 
 
         # Method
         # Method
         methodlabel = QtWidgets.QLabel('%s:' % _('Method'))
         methodlabel = QtWidgets.QLabel('%s:' % _('Method'))
@@ -6446,13 +6465,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, 4, 0)
+        grid0.addWidget(methodlabel, 5, 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, 4, 1)
+        grid0.addWidget(self.ncc_method_radio, 5, 1)
 
 
         # Connect lines
         # Connect lines
         pathconnectlabel = QtWidgets.QLabel('%s:' % _("Connect"))
         pathconnectlabel = QtWidgets.QLabel('%s:' % _("Connect"))
@@ -6460,18 +6479,18 @@ 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, 5, 0)
+        grid0.addWidget(pathconnectlabel, 6, 0)
         self.ncc_connect_cb = FCCheckBox()
         self.ncc_connect_cb = FCCheckBox()
-        grid0.addWidget(self.ncc_connect_cb, 5, 1)
+        grid0.addWidget(self.ncc_connect_cb, 6, 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.")
         )
         )
-        grid0.addWidget(contourlabel, 6, 0)
+        grid0.addWidget(contourlabel, 7, 0)
         self.ncc_contour_cb = FCCheckBox()
         self.ncc_contour_cb = FCCheckBox()
-        grid0.addWidget(self.ncc_contour_cb, 6, 1)
+        grid0.addWidget(self.ncc_contour_cb, 7, 1)
 
 
         restlabel = QtWidgets.QLabel('%s:' % _("Rest M."))
         restlabel = QtWidgets.QLabel('%s:' % _("Rest M."))
         restlabel.setToolTip(
         restlabel.setToolTip(
@@ -6483,9 +6502,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, 7, 0)
+        grid0.addWidget(restlabel, 8, 0)
         self.ncc_rest_cb = FCCheckBox()
         self.ncc_rest_cb = FCCheckBox()
-        grid0.addWidget(self.ncc_rest_cb, 7, 1)
+        grid0.addWidget(self.ncc_rest_cb, 8, 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"))
@@ -6495,9 +6514,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, 8, 0)
+        grid0.addWidget(self.ncc_offset_choice_label, 9, 0)
         self.ncc_choice_offset_cb = FCCheckBox()
         self.ncc_choice_offset_cb = FCCheckBox()
-        grid0.addWidget(self.ncc_choice_offset_cb, 8, 1)
+        grid0.addWidget(self.ncc_choice_offset_cb, 9, 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"))
@@ -6507,14 +6526,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, 9, 0)
+        grid0.addWidget(self.ncc_offset_label, 10, 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, 9, 1)
+        grid0.addWidget(self.ncc_offset_spinner, 10, 1)
 
 
         # ## Reference
         # ## Reference
         self.reference_radio = RadioSet([{'label': _('Itself'), 'value': 'itself'},
         self.reference_radio = RadioSet([{'label': _('Itself'), 'value': 'itself'},
@@ -6529,8 +6548,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, 10, 0)
-        grid0.addWidget(self.reference_radio, 10, 1)
+        grid0.addWidget(reference_label, 11, 0)
+        grid0.addWidget(self.reference_radio, 11, 1)
 
 
         self.layout.addStretch()
         self.layout.addStretch()
 
 

+ 79 - 8
flatcamTools/ToolNonCopperClear.py

@@ -140,6 +140,23 @@ class NonCopperClear(FlatCAMTool, Gerber):
               "If it's not successful then the non-copper clearing will fail, too.\n"
               "If it's not successful then the non-copper clearing will fail, too.\n"
               "- Clear -> the regular non-copper clearing."))
               "- Clear -> the regular non-copper clearing."))
 
 
+        # Milling Type Radio Button
+        self.milling_type_label = QtWidgets.QLabel('%s:' % _('Milling Type'))
+        self.milling_type_label.setToolTip(
+            _("Milling type when the selected tool is of type: 'iso_op':\n"
+              "- climb / best for precision milling and to reduce tool usage\n"
+              "- conventional / useful when there is no backlash compensation")
+        )
+
+        self.milling_type_radio = RadioSet([{'label': _('Climb'), 'value': 'cl'},
+                                            {'label': _('Conv.'), 'value': 'cv'}])
+        self.milling_type_radio.setToolTip(
+            _("Milling type when the selected tool is of type: 'iso_op':\n"
+              "- climb / best for precision milling and to reduce tool usage\n"
+              "- conventional / useful when there is no backlash compensation")
+        )
+
+        # Tool order
         self.ncc_order_label = QtWidgets.QLabel('<b>%s:</b>' % _('Tool order'))
         self.ncc_order_label = QtWidgets.QLabel('<b>%s:</b>' % _('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"
@@ -159,9 +176,14 @@ class NonCopperClear(FlatCAMTool, Gerber):
                                           "in reverse and disable this control."))
                                           "in reverse and disable this control."))
         form = QtWidgets.QFormLayout()
         form = QtWidgets.QFormLayout()
         self.tools_box.addLayout(form)
         self.tools_box.addLayout(form)
+
         form.addRow(QtWidgets.QLabel(''), QtWidgets.QLabel(''))
         form.addRow(QtWidgets.QLabel(''), QtWidgets.QLabel(''))
+        form.addRow(self.milling_type_label, self.milling_type_radio)
         form.addRow(self.ncc_order_label, self.ncc_order_radio)
         form.addRow(self.ncc_order_label, self.ncc_order_radio)
 
 
+        self.milling_type_label.hide()
+        self.milling_type_radio.hide()
+
         # ### 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(
@@ -397,6 +419,8 @@ class NonCopperClear(FlatCAMTool, Gerber):
         # store here solid_geometry when there are tool with isolation job
         # store here solid_geometry when there are tool with isolation job
         self.solid_geometry = []
         self.solid_geometry = []
 
 
+        self.tool_type_item_options = []
+
         self.addtool_btn.clicked.connect(self.on_tool_add)
         self.addtool_btn.clicked.connect(self.on_tool_add)
         self.addtool_entry.returnPressed.connect(self.on_tool_add)
         self.addtool_entry.returnPressed.connect(self.on_tool_add)
         self.deltool_btn.clicked.connect(self.on_tool_delete)
         self.deltool_btn.clicked.connect(self.on_tool_delete)
@@ -463,6 +487,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
         self.ncc_contour_cb.set_value(self.app.defaults["tools_ncccontour"])
         self.ncc_contour_cb.set_value(self.app.defaults["tools_ncccontour"])
         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"])
 
 
         # init the working variables
         # init the working variables
         self.default_data.clear()
         self.default_data.clear()
@@ -524,7 +549,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
                     'offset_value': 0.0,
                     'offset_value': 0.0,
                     'type': 'Iso',
                     'type': 'Iso',
                     'tool_type': 'V',
                     'tool_type': 'V',
-                    'operation': 'clear',
+                    'operation': 'clear_op',
                     'data': dict(self.default_data),
                     'data': dict(self.default_data),
                     'solid_geometry': []
                     'solid_geometry': []
                 }
                 }
@@ -594,9 +619,9 @@ class NonCopperClear(FlatCAMTool, Gerber):
                     tool_uid_item = QtWidgets.QTableWidgetItem(str(int(tooluid_key)))
                     tool_uid_item = QtWidgets.QTableWidgetItem(str(int(tooluid_key)))
 
 
                     operation_type = QtWidgets.QComboBox()
                     operation_type = QtWidgets.QComboBox()
-                    operation_type.addItem('iso')
+                    operation_type.addItem('iso_op')
                     operation_type.setStyleSheet('background-color: rgb(255,255,255)')
                     operation_type.setStyleSheet('background-color: rgb(255,255,255)')
-                    operation_type.addItem('clear')
+                    operation_type.addItem('clear_op')
                     operation_type.setStyleSheet('background-color: rgb(255,255,255)')
                     operation_type.setStyleSheet('background-color: rgb(255,255,255)')
                     op_idx = operation_type.findText(tooluid_value['operation'])
                     op_idx = operation_type.findText(tooluid_value['operation'])
                     operation_type.setCurrentIndex(op_idx)
                     operation_type.setCurrentIndex(op_idx)
@@ -642,6 +667,10 @@ class NonCopperClear(FlatCAMTool, Gerber):
     def ui_connect(self):
     def ui_connect(self):
         self.tools_table.itemChanged.connect(self.on_tool_edit)
         self.tools_table.itemChanged.connect(self.on_tool_edit)
 
 
+        for row in range(self.tools_table.rowCount()):
+            for col in [2, 4]:
+                self.tools_table.cellWidget(row, col).currentIndexChanged.connect(self.on_tooltable_cellwidget_change)
+
     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
@@ -649,6 +678,13 @@ class NonCopperClear(FlatCAMTool, Gerber):
         except (TypeError, AttributeError):
         except (TypeError, AttributeError):
             pass
             pass
 
 
+        for row in range(self.tools_table.rowCount()):
+            for col in [2, 4]:
+                try:
+                    self.ui.geo_tools_table.cellWidget(row, col).currentIndexChanged.disconnect()
+                except (TypeError, AttributeError):
+                    pass
+
     def on_combo_box_type(self):
     def on_combo_box_type(self):
         obj_type = self.box_combo_type.currentIndex()
         obj_type = self.box_combo_type.currentIndex()
         self.box_combo.setRootModelIndex(self.app.collection.index(obj_type, 0, QtCore.QModelIndex()))
         self.box_combo.setRootModelIndex(self.app.collection.index(obj_type, 0, QtCore.QModelIndex()))
@@ -687,6 +723,40 @@ class NonCopperClear(FlatCAMTool, Gerber):
             self.ncc_order_label.setDisabled(False)
             self.ncc_order_label.setDisabled(False)
             self.ncc_order_radio.setDisabled(False)
             self.ncc_order_radio.setDisabled(False)
 
 
+    def on_tooltable_cellwidget_change(self):
+        cw = self.sender()
+        cw_index = self.tools_table.indexAt(cw.pos())
+        cw_row = cw_index.row()
+        cw_col = cw_index.column()
+
+        current_uid = int(self.tools_table.item(cw_row, 3).text())
+
+        hide_iso_type = True
+        for row in range(self.tools_table.rowCount()):
+            if self.tools_table.cellWidget(row, 4).currentText() == 'iso_op':
+                hide_iso_type = False
+                break
+
+        if hide_iso_type is False:
+            self.milling_type_label.show()
+            self.milling_type_radio.show()
+        else:
+            self.milling_type_label.hide()
+            self.milling_type_radio.hide()
+
+        # if the sender is in the column with index 2 then we update the tool_type key
+        if cw_col == 2:
+            tt = cw.currentText()
+            if tt == 'V':
+                typ = 'Iso'
+            else:
+                typ = "Rough"
+
+            self.ncc_tools[current_uid].update({
+                'type': typ,
+                'tool_type': tt,
+            })
+
     def on_tool_add(self, dia=None, muted=None):
     def on_tool_add(self, dia=None, muted=None):
 
 
         self.ui_disconnect()
         self.ui_disconnect()
@@ -748,7 +818,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
                     'offset_value': 0.0,
                     'offset_value': 0.0,
                     'type': 'Iso',
                     'type': 'Iso',
                     'tool_type': 'V',
                     'tool_type': 'V',
-                    'operation': 'clear',
+                    'operation': 'clear_op',
                     'data': dict(self.default_data),
                     'data': dict(self.default_data),
                     'solid_geometry': []
                     'solid_geometry': []
                 }
                 }
@@ -759,6 +829,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
     def on_tool_edit(self):
     def on_tool_edit(self):
         self.ui_disconnect()
         self.ui_disconnect()
 
 
+        old_tool_dia = ''
         tool_dias = []
         tool_dias = []
         for k, v in self.ncc_tools.items():
         for k, v in self.ncc_tools.items():
             for tool_v in v.keys():
             for tool_v in v.keys():
@@ -901,7 +972,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
                                                "use a number."))
                                                "use a number."))
                         continue
                         continue
 
 
-                if self.tools_table.cellWidget(x.row(), 4).currentText() == 'iso':
+                if self.tools_table.cellWidget(x.row(), 4).currentText() == 'iso_op':
                     iso_dia_list.append(tooldia)
                     iso_dia_list.append(tooldia)
                 else:
                 else:
                     ncc_dia_list.append(tooldia)
                     ncc_dia_list.append(tooldia)
@@ -1167,7 +1238,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
                     sorted_tools = ncctooldia
                     sorted_tools = ncctooldia
         else:
         else:
             for row in range(self.tools_table.rowCount()):
             for row in range(self.tools_table.rowCount()):
-                if self.tools_table.cellWidget(row, 1).currentText() == 'clear':
+                if self.tools_table.cellWidget(row, 1).currentText() == 'clear_op':
                     sorted_tools.append(float(self.tools_table.item(row, 1).text()))
                     sorted_tools.append(float(self.tools_table.item(row, 1).text()))
 
 
         # ##############################################################################################################
         # ##############################################################################################################
@@ -1287,7 +1358,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
                 self.solid_geometry = ncc_obj.solid_geometry
                 self.solid_geometry = ncc_obj.solid_geometry
 
 
                 # if milling type is climb then the move is counter-clockwise around features
                 # if milling type is climb then the move is counter-clockwise around features
-                milling_type = 'cl'
+                milling_type = self.milling_type_radio.get_value()
 
 
                 for tool_iso in isotooldia:
                 for tool_iso in isotooldia:
                     new_geometry = []
                     new_geometry = []
@@ -1503,7 +1574,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
                 self.solid_geometry = ncc_obj.solid_geometry
                 self.solid_geometry = ncc_obj.solid_geometry
 
 
                 # if milling type is climb then the move is counter-clockwise around features
                 # if milling type is climb then the move is counter-clockwise around features
-                milling_type = 'cl'
+                milling_type = self.milling_type_radio.get_value()
 
 
                 for tool_iso in isotooldia:
                 for tool_iso in isotooldia:
                     new_geometry = []
                     new_geometry = []

+ 42 - 19
flatcamTools/ToolProperties.py

@@ -21,9 +21,10 @@ if '_' not in builtins.__dict__:
 
 
 
 
 class Properties(FlatCAMTool):
 class Properties(FlatCAMTool):
-
     toolName = _("Properties")
     toolName = _("Properties")
 
 
+    area_finished = pyqtSignal(float, object)
+
     def __init__(self, app):
     def __init__(self, app):
         FlatCAMTool.__init__(self, app)
         FlatCAMTool.__init__(self, app)
 
 
@@ -64,6 +65,8 @@ class Properties(FlatCAMTool):
         self.vlay.addWidget(self.treeWidget)
         self.vlay.addWidget(self.treeWidget)
         self.vlay.setStretch(0, 0)
         self.vlay.setStretch(0, 0)
 
 
+        self.area_finished.connect(self.show_area_chull)
+
     def run(self, toggle=True):
     def run(self, toggle=True):
         self.app.report_usage("ToolProperties()")
         self.app.report_usage("ToolProperties()")
 
 
@@ -170,25 +173,38 @@ class Properties(FlatCAMTool):
             self.addChild(dims, ['%s:' % _('Box Area'), '%.4f %s' % (area, 'in2')], True)
             self.addChild(dims, ['%s:' % _('Box Area'), '%.4f %s' % (area, 'in2')], True)
 
 
         if not isinstance(obj, FlatCAMCNCjob):
         if not isinstance(obj, FlatCAMCNCjob):
-            # calculate and add convex hull area
-            geo = obj.solid_geometry
-            if isinstance(geo, MultiPolygon):
-                env_obj = geo.convex_hull
-            elif (isinstance(geo, MultiPolygon) and len(geo) == 1) or \
-                    (isinstance(geo, list) and len(geo) == 1) and isinstance(geo[0], Polygon):
-                env_obj = cascaded_union(obj.solid_geometry)
-                env_obj = env_obj.convex_hull
-            else:
-                env_obj = cascaded_union(obj.solid_geometry)
-                env_obj = env_obj.convex_hull
 
 
-            area_chull = env_obj.area
-            if self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower() == 'mm':
-                area_chull = area_chull / 100
-                self.addChild(dims, ['%s:' % _('Convex_Hull Area'), '%.4f %s' % (area_chull, 'cm2')], True)
-            else:
-                area_chull = area_chull
-                self.addChild(dims, ['%s:' % _('Convex_Hull Area'), '%.4f %s' % (area_chull, 'in2')], True)
+            def job_thread():
+                proc = self.app.proc_container.new(_("Calculating area ... Please wait."))
+
+                # calculate and add convex hull area
+                geo = obj.solid_geometry
+                if geo:
+                    if isinstance(geo, MultiPolygon):
+                        env_obj = geo.convex_hull
+                    elif (isinstance(geo, MultiPolygon) and len(geo) == 1) or \
+                            (isinstance(geo, list) and len(geo) == 1) and isinstance(geo[0], Polygon):
+                        env_obj = cascaded_union(obj.solid_geometry)
+                        env_obj = env_obj.convex_hull
+                    else:
+                        env_obj = cascaded_union(obj.solid_geometry)
+                        env_obj = env_obj.convex_hull
+
+                    area_chull = env_obj.area
+                else:
+                    try:
+                        area_chull = []
+                        for tool in obj.tools:
+                            area_el = cascaded_union(obj.tools[tool]['solid_geometry']).convex_hull
+                            area_chull.append(area_el.area)
+                        area_chull = max(area_chull)
+                    except Exception as e:
+                        area_chull = None
+                        log.debug("Properties.addItems() --> %s" % str(e))
+
+                self.area_finished.emit(area_chull, dims)
+
+            self.app.worker_task.emit({'fcn': job_thread, 'params': []})
 
 
         self.addChild(units,
         self.addChild(units,
                       ['FlatCAM units:',
                       ['FlatCAM units:',
@@ -294,4 +310,11 @@ class Properties(FlatCAMTool):
         if column1 is not None:
         if column1 is not None:
             item.setText(1, str(title[1]))
             item.setText(1, str(title[1]))
 
 
+    def show_area_chull(self, area, location):
+        if self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower() == 'mm':
+            area_chull = area / 100
+            self.addChild(location, ['%s:' % _('Convex_Hull Area'), '%.4f %s' % (area_chull, 'cm2')], True)
+        else:
+            area_chull = area
+            self.addChild(location, ['%s:' % _('Convex_Hull Area'), '%.4f %s' % (area_chull, 'in2')], True)
 # end of file
 # end of file