소스 검색

- 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 년 전
부모
커밋
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_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_nccmilling_type": self.ui.tools_defaults_form.tools_ncc_group.milling_type_radio,
 
             # CutOut Tool
             "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_value": 0.0000,
             "tools_nccref": 'itself',
+            "tools_nccmilling_type": 'cl',
 
             "tools_cutouttooldia": 0.0944882,
             "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
 - in Excellon and Gerber Seleted tab made the Plot (mark) columns not selectable
 - 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
 

+ 39 - 20
flatcamGUI/FlatCAMGUI.py

@@ -6394,6 +6394,25 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
         self.ncc_tool_dia_entry = FCEntry()
         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.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"
@@ -6411,8 +6430,8 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
                                           "'Reverse' --> menas that the tools will ordered from big to small\n\n"
                                           "WARNING: using rest machining will automatically set the order\n"
                                           "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.setToolTip(
@@ -6426,17 +6445,17 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
              "Higher values = slow processing and slow execution on CNC\n"
              "due of too many paths.")
         )
-        grid0.addWidget(nccoverlabel, 2, 0)
+        grid0.addWidget(nccoverlabel, 3, 0)
         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.setToolTip(
             _("Bounding box margin.")
         )
-        grid0.addWidget(nccmarginlabel, 3, 0)
+        grid0.addWidget(nccmarginlabel, 4, 0)
         self.ncc_margin_entry = FloatEntry()
-        grid0.addWidget(self.ncc_margin_entry, 3, 1)
+        grid0.addWidget(self.ncc_margin_entry, 4, 1)
 
         # Method
         methodlabel = QtWidgets.QLabel('%s:' % _('Method'))
@@ -6446,13 +6465,13 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
               "<B>Seed-based</B>: Outwards from seed.<BR>"
               "<B>Line-based</B>: Parallel lines.")
         )
-        grid0.addWidget(methodlabel, 4, 0)
+        grid0.addWidget(methodlabel, 5, 0)
         self.ncc_method_radio = RadioSet([
             {"label": _("Standard"), "value": "standard"},
             {"label": _("Seed-based"), "value": "seed"},
             {"label": _("Straight lines"), "value": "lines"}
         ], orientation='vertical', stretch=False)
-        grid0.addWidget(self.ncc_method_radio, 4, 1)
+        grid0.addWidget(self.ncc_method_radio, 5, 1)
 
         # Connect lines
         pathconnectlabel = QtWidgets.QLabel('%s:' % _("Connect"))
@@ -6460,18 +6479,18 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
             _("Draw lines between resulting\n"
               "segments to minimize tool lifts.")
         )
-        grid0.addWidget(pathconnectlabel, 5, 0)
+        grid0.addWidget(pathconnectlabel, 6, 0)
         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.setToolTip(
            _("Cut around the perimeter of the polygon\n"
              "to trim rough edges.")
         )
-        grid0.addWidget(contourlabel, 6, 0)
+        grid0.addWidget(contourlabel, 7, 0)
         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.setToolTip(
@@ -6483,9 +6502,9 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
               "no more copper to clear or there are no more tools.\n"
               "If not checked, use the standard algorithm.")
         )
-        grid0.addWidget(restlabel, 7, 0)
+        grid0.addWidget(restlabel, 8, 0)
         self.ncc_rest_cb = FCCheckBox()
-        grid0.addWidget(self.ncc_rest_cb, 7, 1)
+        grid0.addWidget(self.ncc_rest_cb, 8, 1)
 
         # ## NCC Offset choice
         self.ncc_offset_choice_label = QtWidgets.QLabel('%s:' % _("Offset"))
@@ -6495,9 +6514,9 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
               "from the copper features.\n"
               "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()
-        grid0.addWidget(self.ncc_choice_offset_cb, 8, 1)
+        grid0.addWidget(self.ncc_choice_offset_cb, 9, 1)
 
         # ## NCC Offset value
         self.ncc_offset_label = QtWidgets.QLabel('%s:' % _("Offset value"))
@@ -6507,14 +6526,14 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
               "from the copper features.\n"
               "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.set_range(0.00, 10.00)
         self.ncc_offset_spinner.set_precision(4)
         self.ncc_offset_spinner.setWrapping(True)
         self.ncc_offset_spinner.setSingleStep(0.1)
 
-        grid0.addWidget(self.ncc_offset_spinner, 9, 1)
+        grid0.addWidget(self.ncc_offset_spinner, 10, 1)
 
         # ## Reference
         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"
               "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()
 

+ 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"
               "- 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.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"
@@ -159,9 +176,14 @@ class NonCopperClear(FlatCAMTool, Gerber):
                                           "in reverse and disable this control."))
         form = QtWidgets.QFormLayout()
         self.tools_box.addLayout(form)
+
         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)
 
+        self.milling_type_label.hide()
+        self.milling_type_radio.hide()
+
         # ### Add a new Tool ####
         self.addtool_entry_lbl = QtWidgets.QLabel('<b>%s:</b>' % _('Tool Dia'))
         self.addtool_entry_lbl.setToolTip(
@@ -397,6 +419,8 @@ class NonCopperClear(FlatCAMTool, Gerber):
         # store here solid_geometry when there are tool with isolation job
         self.solid_geometry = []
 
+        self.tool_type_item_options = []
+
         self.addtool_btn.clicked.connect(self.on_tool_add)
         self.addtool_entry.returnPressed.connect(self.on_tool_add)
         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_rest_cb.set_value(self.app.defaults["tools_nccrest"])
         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
         self.default_data.clear()
@@ -524,7 +549,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
                     'offset_value': 0.0,
                     'type': 'Iso',
                     'tool_type': 'V',
-                    'operation': 'clear',
+                    'operation': 'clear_op',
                     'data': dict(self.default_data),
                     'solid_geometry': []
                 }
@@ -594,9 +619,9 @@ class NonCopperClear(FlatCAMTool, Gerber):
                     tool_uid_item = QtWidgets.QTableWidgetItem(str(int(tooluid_key)))
 
                     operation_type = QtWidgets.QComboBox()
-                    operation_type.addItem('iso')
+                    operation_type.addItem('iso_op')
                     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)')
                     op_idx = operation_type.findText(tooluid_value['operation'])
                     operation_type.setCurrentIndex(op_idx)
@@ -642,6 +667,10 @@ class NonCopperClear(FlatCAMTool, Gerber):
     def ui_connect(self):
         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):
         try:
             # 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):
             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):
         obj_type = self.box_combo_type.currentIndex()
         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_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):
 
         self.ui_disconnect()
@@ -748,7 +818,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
                     'offset_value': 0.0,
                     'type': 'Iso',
                     'tool_type': 'V',
-                    'operation': 'clear',
+                    'operation': 'clear_op',
                     'data': dict(self.default_data),
                     'solid_geometry': []
                 }
@@ -759,6 +829,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
     def on_tool_edit(self):
         self.ui_disconnect()
 
+        old_tool_dia = ''
         tool_dias = []
         for k, v in self.ncc_tools.items():
             for tool_v in v.keys():
@@ -901,7 +972,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
                                                "use a number."))
                         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)
                 else:
                     ncc_dia_list.append(tooldia)
@@ -1167,7 +1238,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
                     sorted_tools = ncctooldia
         else:
             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()))
 
         # ##############################################################################################################
@@ -1287,7 +1358,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
                 self.solid_geometry = ncc_obj.solid_geometry
 
                 # 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:
                     new_geometry = []
@@ -1503,7 +1574,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
                 self.solid_geometry = ncc_obj.solid_geometry
 
                 # 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:
                     new_geometry = []

+ 42 - 19
flatcamTools/ToolProperties.py

@@ -21,9 +21,10 @@ if '_' not in builtins.__dict__:
 
 
 class Properties(FlatCAMTool):
-
     toolName = _("Properties")
 
+    area_finished = pyqtSignal(float, object)
+
     def __init__(self, app):
         FlatCAMTool.__init__(self, app)
 
@@ -64,6 +65,8 @@ class Properties(FlatCAMTool):
         self.vlay.addWidget(self.treeWidget)
         self.vlay.setStretch(0, 0)
 
+        self.area_finished.connect(self.show_area_chull)
+
     def run(self, toggle=True):
         self.app.report_usage("ToolProperties()")
 
@@ -170,25 +173,38 @@ class Properties(FlatCAMTool):
             self.addChild(dims, ['%s:' % _('Box Area'), '%.4f %s' % (area, 'in2')], True)
 
         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,
                       ['FlatCAM units:',
@@ -294,4 +310,11 @@ class Properties(FlatCAMTool):
         if column1 is not None:
             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