diff --git a/FlatCAMApp.py b/FlatCAMApp.py index 7249c5e2..439b1a39 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -2478,6 +2478,7 @@ class App(QtCore.QObject): # variable to store coordinates self.pos = (0, 0) + self.pos_canvas = (0, 0) self.pos_jump = (0, 0) # variable to store mouse coordinates @@ -8441,23 +8442,17 @@ class App(QtCore.QObject): was clicked, the pixel coordinates and the axes coordinates. :return: None """ - self.pos = [] + self.pos = list() if self.is_legacy is False: event_pos = event.pos - if self.defaults["global_pan_button"] == '2': - pan_button = 2 - else: - pan_button = 3 + pan_button = 2 if self.defaults["global_pan_button"] == '2'else 3 # Set the mouse button for panning self.plotcanvas.view.camera.pan_button_setting = pan_button else: event_pos = (event.xdata, event.ydata) # Matplotlib has the middle and right buttons mapped in reverse compared with VisPy - if self.defaults["global_pan_button"] == '2': - pan_button = 3 - else: - pan_button = 2 + pan_button = 3 if self.defaults["global_pan_button"] == '2'else 2 # So it can receive key presses self.plotcanvas.native.setFocus() diff --git a/FlatCAMObj.py b/FlatCAMObj.py index 43f9661d..8d9d8abc 100644 --- a/FlatCAMObj.py +++ b/FlatCAMObj.py @@ -625,6 +625,8 @@ class FlatCAMGerber(FlatCAMObj, Gerber): # Mouse events self.mr = None + self.mm = None + self.mp = None # dict to store the polygons selected for isolation; key is the shape added to be plotted and value is the poly self.poly_dict = dict() @@ -1066,11 +1068,11 @@ class FlatCAMGerber(FlatCAMObj, Gerber): if self.app.is_legacy is False: event_pos = event.pos right_button = 2 - event_is_dragging = self.app.event_is_dragging + self.app.event_is_dragging = self.app.event_is_dragging else: event_pos = (event.xdata, event.ydata) right_button = 3 - event_is_dragging = self.app.ui.popMenu.mouse_is_panning + self.app.event_is_dragging = self.app.ui.popMenu.mouse_is_panning try: x = float(event_pos[0]) @@ -1080,11 +1082,18 @@ class FlatCAMGerber(FlatCAMObj, Gerber): event_pos = (x, y) curr_pos = self.app.plotcanvas.translate_coords(event_pos) + if self.app.grid_status(): + curr_pos = self.app.geo_editor.snap(curr_pos[0], curr_pos[1]) + else: + curr_pos = (curr_pos[0], curr_pos[1]) if event.button == 1: clicked_poly = self.find_polygon(point=(curr_pos[0], curr_pos[1])) - if clicked_poly: + if self.app.selection_type is not None: + self.selection_area_handler(self.app.pos, curr_pos, self.app.selection_type) + self.app.selection_type = None + elif clicked_poly: if clicked_poly not in self.poly_dict.values(): shape_id = self.app.tool_shapes.add(tolerance=self.drawing_tolerance, layer=0, shape=clicked_poly, color=self.app.defaults['global_sel_draw_color'] + 'AF', @@ -1113,8 +1122,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber): self.app.tool_shapes.redraw() else: self.app.inform.emit(_("No polygon detected under click position.")) - - elif event.button == right_button and event_is_dragging is False: + elif event.button == right_button and self.app.event_is_dragging is False: # restore the Grid snapping if it was active before if self.grid_status_memory is True: self.app.ui.grid_snap_btn.trigger() @@ -1136,6 +1144,75 @@ class FlatCAMGerber(FlatCAMObj, Gerber): else: self.app.inform.emit('[ERROR_NOTCL] %s' % _("List of single polygons is empty. Aborting.")) + def selection_area_handler(self, start_pos, end_pos, sel_type): + """ + :param start_pos: mouse position when the selection LMB click was done + :param end_pos: mouse position when the left mouse button is released + :param sel_type: if True it's a left to right selection (enclosure), if False it's a 'touch' selection + :return: + """ + poly_selection = Polygon([start_pos, (end_pos[0], start_pos[1]), end_pos, (start_pos[0], end_pos[1])]) + + # delete previous selection shape + self.app.delete_selection_shape() + + added_poly_count = 0 + try: + for geo in self.solid_geometry: + if geo not in self.poly_dict.values(): + if sel_type is True: + if geo.within(poly_selection): + shape_id = self.app.tool_shapes.add(tolerance=self.drawing_tolerance, layer=0, + shape=geo, + color=self.app.defaults['global_sel_draw_color'] + 'AF', + face_color=self.app.defaults[ + 'global_sel_draw_color'] + 'AF', + visible=True) + self.poly_dict[shape_id] = geo + added_poly_count += 1 + else: + if poly_selection.intersects(geo): + shape_id = self.app.tool_shapes.add(tolerance=self.drawing_tolerance, layer=0, + shape=geo, + color=self.app.defaults['global_sel_draw_color'] + 'AF', + face_color=self.app.defaults[ + 'global_sel_draw_color'] + 'AF', + visible=True) + self.poly_dict[shape_id] = geo + added_poly_count += 1 + except TypeError: + if self.solid_geometry not in self.poly_dict.values(): + if sel_type is True: + if self.solid_geometry.within(poly_selection): + shape_id = self.app.tool_shapes.add(tolerance=self.drawing_tolerance, layer=0, + shape=self.solid_geometry, + color=self.app.defaults['global_sel_draw_color'] + 'AF', + face_color=self.app.defaults[ + 'global_sel_draw_color'] + 'AF', + visible=True) + self.poly_dict[shape_id] = self.solid_geometry + added_poly_count += 1 + else: + if poly_selection.intersects(self.solid_geometry): + shape_id = self.app.tool_shapes.add(tolerance=self.drawing_tolerance, layer=0, + shape=self.solid_geometry, + color=self.app.defaults['global_sel_draw_color'] + 'AF', + face_color=self.app.defaults[ + 'global_sel_draw_color'] + 'AF', + visible=True) + self.poly_dict[shape_id] = self.solid_geometry + added_poly_count += 1 + + if added_poly_count > 0: + self.app.tool_shapes.redraw() + self.app.inform.emit( + '%s: %d. %s' % (_("Added polygon"), + int(added_poly_count), + _("Click to add next polygon or right click to start isolation.")) + ) + else: + self.app.inform.emit(_("No polygon in selection.")) + def isolate(self, iso_type=None, geometry=None, dia=None, passes=None, overlap=None, outname=None, combine=None, milling_type=None, follow=None, plot=True): """ diff --git a/README.md b/README.md index 5b496e4d..c9022369 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ CAD program, and create G-Code for Isolation routing. - small changes in the Geometry UI - now extracut option in the Geometry Object will recut as many points as many they are within the specified re-cut length - if extracut_length is zero then the extracut will cut up until the first point in path no matter what the distance is +- in Gerber isolation when selection mode is checked now area selection works too 9.12.2019