فهرست منبع

- in NCC Tool added area selection feature

Marius Stanciu 6 سال پیش
والد
کامیت
47cd3dd043
3فایلهای تغییر یافته به همراه129 افزوده شده و 28 حذف شده
  1. 1 0
      README.md
  2. 4 2
      flatcamGUI/FlatCAMGUI.py
  3. 124 26
      flatcamTools/ToolNonCopperClear.py

+ 1 - 0
README.md

@@ -16,6 +16,7 @@ CAD program, and create G-Code for Isolation routing.
 - added Edit -> Preferences GUI entries for the above just added features
 - added new entry in Properties Tool which is the calculated Convex Hull Area (should give a more precise area for the irregular shapes than the box area)
 - added some more strings in Properties Tool for the translation
+- in NCC Tool added area selection feature
 
 20.08.2019
 

+ 4 - 2
flatcamGUI/FlatCAMGUI.py

@@ -6469,12 +6469,14 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
 
         # ## Reference
         self.reference_radio = RadioSet([{'label': _('Itself'), 'value': 'itself'},
-                                         {'label': _('Box'), 'value': 'box'}])
+                                         {"label": _("Area"), "value": "area"},
+                                         {'label': _('Ref'), 'value': 'box'}])
         reference_label = QtWidgets.QLabel('%s:' % _("Reference"))
         reference_label.setToolTip(
             _("When choosing the 'Itself' option the non copper clearing extent\n"
               "is based on the object that is copper cleared.\n "
-              "Choosing the 'Box' option will do non copper clearing within the box\n"
+              "Area Selection - left mouse click to start selection of the area to be painted.\n"
+              "Choosing the 'Ref' option will do non copper clearing within the box\n"
               "specified by another object different than the one that is copper cleared.")
         )
         grid0.addWidget(reference_label, 10, 0)

+ 124 - 26
flatcamTools/ToolNonCopperClear.py

@@ -309,13 +309,17 @@ class NonCopperClear(FlatCAMTool, Gerber):
         self.ncc_offset_spinner.hide()
 
         # ## Reference
-        self.reference_radio = RadioSet([{'label': _('Itself'), 'value': 'itself'},
-                                         {'label': _('Box'), 'value': 'box'}])
+        self.reference_radio = RadioSet([
+            {'label': _('Itself'), 'value': 'itself'},
+            {"label": _("Area Selection"), "value": "area"},
+            {'label':  _("Reference Object"), 'value': 'box'}
+        ], orientation='vertical', stretch=False)
         self.reference_label = QtWidgets.QLabel(_("Reference:"))
         self.reference_label.setToolTip(
             _("When choosing the 'Itself' option the non copper clearing extent\n"
               "is based on the object that is copper cleared.\n "
-              "Choosing the 'Box' option will do non copper clearing within the box\n"
+              "Area Selection - left mouse click to start selection of the area to be painted.\n"
+              "Choosing the 'Reference Object' option will do non copper clearing within the box\n"
               "specified by another object different than the one that is copper cleared.")
         )
         grid3.addWidget(self.reference_label, 9, 0)
@@ -356,6 +360,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
               "for non-copper routing.")
         )
         self.tools_box.addWidget(self.generate_ncc_button)
+        self.tools_box.addStretch()
 
         self.units = ''
         self.ncc_tools = {}
@@ -366,15 +371,18 @@ class NonCopperClear(FlatCAMTool, Gerber):
         self.obj_name = ""
         self.ncc_obj = None
 
+        self.sel_rect = []
+
         self.bound_obj_name = ""
         self.bound_obj = None
 
-        self.tools_box.addStretch()
+        self.first_click = False
+        self.cursor_pos = None
 
         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)
-        self.generate_ncc_button.clicked.connect(self.on_ncc)
+        self.generate_ncc_button.clicked.connect(self.on_ncc_click)
 
         self.box_combo_type.currentIndexChanged.connect(self.on_combo_box_type)
         self.reference_radio.group_toggle_fn = self.on_toggle_reference
@@ -620,7 +628,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
         self.box_combo.setCurrentIndex(0)
 
     def on_toggle_reference(self):
-        if self.reference_radio.get_value() == "itself":
+        if self.reference_radio.get_value() == "itself" or self.reference_radio.get_value() == "area":
             self.box_combo.hide()
             self.box_combo_label.hide()
             self.box_combo_type.hide()
@@ -806,6 +814,109 @@ class NonCopperClear(FlatCAMTool, Gerber):
         self.app.inform.emit(_("[success] Tool(s) deleted from Tool Table."))
         self.build_ui()
 
+    def on_ncc_click(self):
+        if self.reference_radio.get_value() == 'itself':
+            self.bound_obj_name = self.object_combo.currentText()
+            # Get source object.
+            try:
+                self.bound_obj = self.app.collection.get_by_name(self.bound_obj_name)
+            except Exception as e:
+                self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") % self.obj_name)
+                return "Could not retrieve object: %s" % self.obj_name
+            self.on_ncc()
+        elif self.reference_radio.get_value() == 'box':
+            self.bound_obj_name = self.box_combo.currentText()
+            # Get source object.
+            try:
+                self.bound_obj = self.app.collection.get_by_name(self.bound_obj_name)
+            except Exception as e:
+                self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") % self.bound_obj_name)
+                return "Could not retrieve object: %s. Error: %s" % (self.bound_obj_name, str(e))
+            self.on_ncc()
+        else:
+            self.app.inform.emit(_("[WARNING_NOTCL] Click the start point of the area."))
+
+            # use the first tool in the tool table; get the diameter
+            tooldia = float('%.4f' % float(self.tools_table.item(0, 1).text()))
+
+            # To be called after clicking on the plot.
+            def on_mouse_press(event):
+                # do paint single only for left mouse clicks
+                if event.button == 1:
+                    if not self.first_click:
+                        self.first_click = True
+                        self.app.inform.emit(_("[WARNING_NOTCL] Click the end point of the paint area."))
+
+                        self.cursor_pos = self.app.plotcanvas.vispy_canvas.translate_coords(event.pos)
+                        if self.app.grid_status() == True:
+                            self.cursor_pos = self.app.geo_editor.snap(self.cursor_pos[0], self.cursor_pos[1])
+                    else:
+                        self.app.inform.emit(_("Done."))
+                        self.first_click = False
+                        self.app.delete_selection_shape()
+
+                        curr_pos = self.app.plotcanvas.vispy_canvas.translate_coords(event.pos)
+                        if self.app.grid_status() == True:
+                            curr_pos = self.app.geo_editor.snap(curr_pos[0], curr_pos[1])
+
+                        x0, y0 = self.cursor_pos[0], self.cursor_pos[1]
+                        x1, y1 = curr_pos[0], curr_pos[1]
+                        pt1 = (x0, y0)
+                        pt2 = (x1, y0)
+                        pt3 = (x1, y1)
+                        pt4 = (x0, y1)
+                        self.sel_rect = [Polygon([pt1, pt2, pt3, pt4])]
+
+                        # def initialize(geo_obj, app_obj):
+                        #     geo_obj.solid_geometry = self.sel_rect
+                        #     geo_obj.multigeo = False
+                        #
+                        # self.app.new_object("geometry", "bound_ncc", initialize=initialize,
+                        #                     plot=True, autoselected=False)
+                        #
+                        # self.bound_obj_name = "bound_ncc"
+                        # # Get source object.
+                        # try:
+                        #     self.bound_obj = self.app.collection.get_by_name(self.bound_obj_name)
+                        # except Exception as e:
+                        #     self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") %
+                        #                          self.bound_obj_name)
+                        #     return "Could not retrieve object: %s. Error: %s" % (self.bound_obj_name, str(e))
+
+                        self.app.plotcanvas.vis_disconnect('mouse_press', on_mouse_press)
+                        self.app.plotcanvas.vis_disconnect('mouse_move', on_mouse_move)
+
+                        self.app.plotcanvas.vis_connect('mouse_press', self.app.on_mouse_click_over_plot)
+                        self.app.plotcanvas.vis_connect('mouse_move', self.app.on_mouse_move_over_plot)
+                        self.app.plotcanvas.vis_connect('mouse_release', self.app.on_mouse_click_release_over_plot)
+
+                        self.on_ncc()
+
+            # called on mouse move
+            def on_mouse_move(event):
+                curr_pos = self.app.plotcanvas.vispy_canvas.translate_coords(event.pos)
+                self.app.app_cursor.enabled = False
+
+                if self.app.grid_status() == True:
+                    self.app.app_cursor.enabled = True
+                    # Update cursor
+                    curr_pos = self.app.geo_editor.snap(curr_pos[0], curr_pos[1])
+                    self.app.app_cursor.set_data(np.asarray([(curr_pos[0], curr_pos[1])]),
+                                                 symbol='++', edge_color='black', size=20)
+
+                if self.first_click:
+                    self.app.delete_selection_shape()
+                    self.app.draw_moving_selection_shape(old_coords=(self.cursor_pos[0], self.cursor_pos[1]),
+                                                         coords=(curr_pos[0], curr_pos[1]),
+                                                         face_alpha=0.0)
+
+            self.app.plotcanvas.vis_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
+            self.app.plotcanvas.vis_disconnect('mouse_move', self.app.on_mouse_move_over_plot)
+            self.app.plotcanvas.vis_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
+
+            self.app.plotcanvas.vis_connect('mouse_press', on_mouse_press)
+            self.app.plotcanvas.vis_connect('mouse_move', on_mouse_move)
+
     def on_ncc(self):
         self.bound_obj = None
         self.ncc_obj = None
@@ -860,23 +971,6 @@ class NonCopperClear(FlatCAMTool, Gerber):
         pol_method = self.ncc_method_radio.get_value()
         pol_method = pol_method if pol_method else self.app.defaults["tools_nccmethod"]
 
-        if self.reference_radio.get_value() == 'itself':
-            self.bound_obj_name = self.object_combo.currentText()
-            # Get source object.
-            try:
-                self.bound_obj = self.app.collection.get_by_name(self.bound_obj_name)
-            except Exception as e:
-                self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") % self.obj_name)
-                return "Could not retrieve object: %s" % self.obj_name
-        else:
-            self.bound_obj_name = self.box_combo.currentText()
-            # Get source object.
-            try:
-                self.bound_obj = self.app.collection.get_by_name(self.bound_obj_name)
-            except Exception as e:
-                self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") % self.obj_name)
-                return "Could not retrieve object: %s" % self.obj_name
-
         self.obj_name = self.obj_combo.currentText()
         # Get source object.
         try:
@@ -886,15 +980,19 @@ class NonCopperClear(FlatCAMTool, Gerber):
             return "Could not retrieve object: %s" % self.obj_name
 
         # Prepare non-copper polygons
-        geo_n = self.bound_obj.solid_geometry
+        if self.reference_radio.get_value() == 'area':
+            geo_n = self.sel_rect
+        else:
+            geo_n = self.bound_obj.solid_geometry
+
         try:
             if isinstance(geo_n, MultiPolygon):
                 env_obj = geo_n.convex_hull
             elif (isinstance(geo_n, MultiPolygon) and len(geo_n) == 1) or \
                     (isinstance(geo_n, list) and len(geo_n) == 1) and isinstance(geo_n[0], Polygon):
-                env_obj = cascaded_union(self.bound_obj.solid_geometry)
+                env_obj = cascaded_union(geo_n)
             else:
-                env_obj = cascaded_union(self.bound_obj.solid_geometry)
+                env_obj = cascaded_union(geo_n)
                 env_obj = env_obj.convex_hull
             bounding_box = env_obj.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre)
         except Exception as e: