From 43cb92e1d839eadf5eadc5aca661e207bc4cb651 Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Sat, 13 Jul 2019 21:40:33 +0300 Subject: [PATCH] - fixed a possible issue in Gerber Object class - added a new tool in Gerber Editor: Mark Area Tool. It will mark the polygons in a edited Gerber object with areas within a defined range, allowing to delete some of the not necessary copper features - added new menu links in the Gerber Editor menu for Eraser Tool and Mark Area Tool - added key shortcuts for Eraser Tool (CTRL+E) and Mark Area Tool (ALT+A) and updated the shortcuts list --- FlatCAMObj.py | 6 +- README.md | 7 ++ flatcamEditors/FlatCAMGrbEditor.py | 195 ++++++++++++++++++++++++++--- flatcamGUI/FlatCAMGUI.py | 32 ++++- share/markarea32.png | Bin 0 -> 699 bytes 5 files changed, 218 insertions(+), 22 deletions(-) create mode 100644 share/markarea32.png diff --git a/FlatCAMObj.py b/FlatCAMObj.py index b88a28e2..ecbb0acb 100644 --- a/FlatCAMObj.py +++ b/FlatCAMObj.py @@ -1215,7 +1215,11 @@ class FlatCAMGerber(FlatCAMObj, Gerber): cw_row = 0 self.marked_rows[:] = [] - aperture = self.ui.apertures_table.item(cw_row, 1).text() + + try: + aperture = self.ui.apertures_table.item(cw_row, 1).text() + except AttributeError: + return if self.ui.apertures_table.cellWidget(cw_row, 5).isChecked(): self.marked_rows.append(True) diff --git a/README.md b/README.md index 6e83d73e..aa7353ae 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,13 @@ CAD program, and create G-Code for Isolation routing. ================================================= +13.07.2019 + +- fixed a possible issue in Gerber Object class +- added a new tool in Gerber Editor: Mark Area Tool. It will mark the polygons in a edited Gerber object with areas within a defined range, allowing to delete some of the not necessary copper features +- added new menu links in the Gerber Editor menu for Eraser Tool and Mark Area Tool +- added key shortcuts for Eraser Tool (CTRL+E) and Mark Area Tool (ALT+A) and updated the shortcuts list + 9.07.2019 - some changes in the app.on_togle_units() to make sure we don't try to convert empty parameters which may cause crashes on FlatCAM units change diff --git a/flatcamEditors/FlatCAMGrbEditor.py b/flatcamEditors/FlatCAMGrbEditor.py index 43c84084..311918d7 100644 --- a/flatcamEditors/FlatCAMGrbEditor.py +++ b/flatcamEditors/FlatCAMGrbEditor.py @@ -1755,6 +1755,48 @@ class FCBuffer(FCShapeTool): self.draw_app.plot_all() +class FCMarkArea(FCShapeTool): + def __init__(self, draw_app): + FCShapeTool.__init__(self, draw_app) + self.name = 'markarea' + + # self.shape_buffer = self.draw_app.shape_buffer + self.draw_app = draw_app + self.app = draw_app.app + + self.draw_app.app.inform.emit(_("Mark polygon areas in the edited Gerber ...")) + self.origin = (0, 0) + + if self.draw_app.app.ui.splitter.sizes()[0] == 0: + self.draw_app.app.ui.splitter.setSizes([1, 1]) + self.activate_markarea() + + def activate_markarea(self): + self.draw_app.hide_tool('all') + self.draw_app.ma_tool_frame.show() + + try: + self.draw_app.ma_threshold__button.clicked.disconnect() + except TypeError: + pass + self.draw_app.ma_threshold__button.clicked.connect(self.on_markarea_click) + + def deactivate_markarea(self): + self.draw_app.ma_threshold__button.clicked.disconnect() + self.complete = True + self.draw_app.select_tool("select") + self.draw_app.hide_tool(self.name) + + def on_markarea_click(self): + self.draw_app.on_markarea() + self.deactivate_markarea() + + def clean_up(self): + self.draw_app.selected = [] + self.draw_app.apertures_table.clearSelection() + self.draw_app.plot_all() + + class FCApertureMove(FCShapeTool): def __init__(self, draw_app): DrawTool.__init__(self, draw_app) @@ -2273,8 +2315,9 @@ class FlatCAMGrbEditor(QtCore.QObject): self.custom_box = QtWidgets.QVBoxLayout() layout.addLayout(self.custom_box) - - # # ## Gerber Apertures ## ## + # ######################### + # ### Gerber Apertures #### + # ######################### self.apertures_table_label = QtWidgets.QLabel(_('Apertures:')) self.apertures_table_label.setToolTip( _("Apertures Table for the Gerber Object.") @@ -2390,8 +2433,9 @@ class FlatCAMGrbEditor(QtCore.QObject): hlay_ad.addWidget(self.addaperture_btn) hlay_ad.addWidget(self.delaperture_btn) - # # ## BUFFER TOOL # ## - + # ################### + # ### BUFFER TOOL ### + # ################### self.buffer_tool_frame = QtWidgets.QFrame() self.buffer_tool_frame.setContentsMargins(0, 0, 0, 0) self.custom_box.addWidget(self.buffer_tool_frame) @@ -2434,8 +2478,9 @@ class FlatCAMGrbEditor(QtCore.QObject): self.buffer_button = QtWidgets.QPushButton(_("Buffer")) hlay_buf.addWidget(self.buffer_button) - # # ## SCALE TOOL # ## - + # ################## + # ### SCALE TOOL ### + # ################## self.scale_tool_frame = QtWidgets.QFrame() self.scale_tool_frame.setContentsMargins(0, 0, 0, 0) self.custom_box.addWidget(self.scale_tool_frame) @@ -2471,6 +2516,58 @@ class FlatCAMGrbEditor(QtCore.QObject): self.scale_button = QtWidgets.QPushButton(_("Scale")) hlay_scale.addWidget(self.scale_button) + # ###################### + # ### Mark Area TOOL ### + # ###################### + self.ma_tool_frame = QtWidgets.QFrame() + self.ma_tool_frame.setContentsMargins(0, 0, 0, 0) + self.custom_box.addWidget(self.ma_tool_frame) + self.ma_tools_box = QtWidgets.QVBoxLayout() + self.ma_tools_box.setContentsMargins(0, 0, 0, 0) + self.ma_tool_frame.setLayout(self.ma_tools_box) + self.ma_tool_frame.hide() + + # Title + ma_title_lbl = QtWidgets.QLabel('%s' % _('Mark polygon areas:')) + ma_title_lbl.setToolTip( + _("Mark the polygon areas.") + ) + self.ma_tools_box.addWidget(ma_title_lbl) + + # Form Layout + ma_form_layout = QtWidgets.QFormLayout() + self.ma_tools_box.addLayout(ma_form_layout) + + self.ma_upper_threshold_lbl = QtWidgets.QLabel(_("Area UPPER threshold:")) + self.ma_upper_threshold_lbl.setToolTip( + _("The threshold value, all areas less than this are marked.\n" + "Can have a value between 0.0000 and 9999.9999") + ) + self.ma_upper_threshold_entry = FCEntry() + self.ma_upper_threshold_entry.setValidator(QtGui.QDoubleValidator(0.0000, 9999.9999, 4)) + + self.ma_lower_threshold_lbl = QtWidgets.QLabel(_("Area LOWER threshold:")) + self.ma_lower_threshold_lbl.setToolTip( + _("The threshold value, all areas more than this are marked.\n" + "Can have a value between 0.0000 and 9999.9999") + ) + self.ma_lower_threshold_entry = FCEntry() + self.ma_lower_threshold_entry.setValidator(QtGui.QDoubleValidator(0.0000, 9999.9999, 4)) + + ma_form_layout.addRow(self.ma_upper_threshold_lbl, self.ma_upper_threshold_entry) + ma_form_layout.addRow(self.ma_lower_threshold_lbl, self.ma_lower_threshold_entry) + + # Buttons + hlay_ma = QtWidgets.QHBoxLayout() + self.ma_tools_box.addLayout(hlay_ma) + + self.ma_threshold__button = QtWidgets.QPushButton(_("Go")) + hlay_ma.addWidget(self.ma_threshold__button) + + # ###################### + # ### Add Pad Array #### + # ###################### + # add a frame and inside add a vertical box layout. Inside this vbox layout I add # all the add Pad array widgets # this way I can hide/show the frame @@ -2481,7 +2578,6 @@ class FlatCAMGrbEditor(QtCore.QObject): self.array_box.setContentsMargins(0, 0, 0, 0) self.array_frame.setLayout(self.array_box) - # # ## Add Pad Array ## ## self.emptyarray_label = QtWidgets.QLabel('') self.array_box.addWidget(self.emptyarray_label) @@ -2623,6 +2719,8 @@ class FlatCAMGrbEditor(QtCore.QObject): "constructor": FCBuffer}, "scale": {"button": self.app.ui.aperture_scale_btn, "constructor": FCScale}, + "markarea": {"button": self.app.ui.aperture_markarea_btn, + "constructor": FCMarkArea}, "eraser": {"button": self.app.ui.aperture_eraser_btn, "constructor": FCEraser}, "copy": {"button": self.app.ui.aperture_copy_btn, @@ -2670,12 +2768,11 @@ class FlatCAMGrbEditor(QtCore.QObject): self.gerber_obj = None self.gerber_obj_options = dict() - self.buffer_distance_entry.set_value(0.01) - self.scale_factor_entry.set_value(1.0) - # VisPy Visuals self.shapes = self.canvas.new_shape_collection(layers=1) self.tool_shape = self.canvas.new_shape_collection(layers=1) + self.ma_annotation = self.canvas.new_text_group() + self.app.pool_recreated.connect(self.pool_recreated) # Remove from scene @@ -2768,6 +2865,9 @@ class FlatCAMGrbEditor(QtCore.QObject): self.app.ui.grb_add_disc_menuitem.triggered.connect(self.on_disc_add) self.app.ui.grb_add_buffer_menuitem.triggered.connect(self.on_buffer) self.app.ui.grb_add_scale_menuitem.triggered.connect(self.on_scale) + self.app.ui.grb_add_eraser_menuitem.triggered.connect(self.on_eraser) + self.app.ui.grb_add_markarea_menuitem.triggered.connect(self.on_markarea) + self.app.ui.grb_transform_menuitem.triggered.connect(self.transform_tool.run) self.app.ui.grb_copy_menuitem.triggered.connect(self.on_copy_button) @@ -2810,12 +2910,19 @@ class FlatCAMGrbEditor(QtCore.QObject): tt_aperture = self.sorted_apid[i] self.tool2tooldia[i + 1] = tt_aperture - if self.units == "IN": - self.apsize_entry.set_value(0.039) - else: - self.apsize_entry.set_value(1.00) - # Init GUI + if self.units == 'MM': + self.buffer_distance_entry.set_value(0.01) + self.scale_factor_entry.set_value(1.0) + self.ma_upper_threshold_entry.set_value(1.0) + self.apsize_entry.set_value(1.00) + else: + self.buffer_distance_entry.set_value(0.0003937) + self.scale_factor_entry.set_value(0.03937) + self.ma_upper_threshold_entry.set_value(0.00155) + self.apsize_entry.set_value(0.039) + self.ma_lower_threshold_entry.set_value(0.0) + self.pad_array_size_entry.set_value(5) self.pad_pitch_entry.set_value(2.54) self.pad_angle_entry.set_value(12) @@ -2827,12 +2934,12 @@ class FlatCAMGrbEditor(QtCore.QObject): try: # if connected, disconnect the signal from the slot on item_changed as it creates issues self.apertures_table.itemChanged.disconnect() - except: + except Exception as e: pass try: self.apertures_table.cellPressed.disconnect() - except: + except Exception as e: pass # updated units @@ -3426,6 +3533,7 @@ class FlatCAMGrbEditor(QtCore.QObject): self.shapes.clear(update=True) self.tool_shape.clear(update=True) + self.ma_annotation.clear(update=True) def edit_fcgerber(self, orig_grb_obj): """ @@ -3561,9 +3669,12 @@ class FlatCAMGrbEditor(QtCore.QObject): self.set_ui() # do the delayed plot only if there is something to plot (the gerber is not empty) - if bool(self.gerber_obj.apertures): - self.start_delayed_plot(check_period=1000) - else: + try: + if bool(self.gerber_obj.apertures): + self.start_delayed_plot(check_period=1000) + else: + raise AttributeError + except AttributeError: # now that we have data (empty data actually), create the GUI interface and add it to the Tool Tab self.build_ui(first_run=True) # and add the first aperture to have something to play with @@ -4509,6 +4620,48 @@ class FlatCAMGrbEditor(QtCore.QObject): self.plot_all() self.app.inform.emit(_("[success] Done. Scale Tool completed.")) + def on_markarea(self): + # clear previous marking + self.ma_annotation.clear(update=True) + + self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper() + upper_threshold_val = None + lower_threshold_val = None + text = [] + position = [] + + for apid in self.gerber_obj.apertures: + if 'geometry' in self.gerber_obj.apertures[apid]: + for geo_el in self.gerber_obj.apertures[apid]['geometry']: + if 'solid' in geo_el: + area = geo_el['solid'].area + try: + upper_threshold_val = self.ma_upper_threshold_entry.get_value() + except Exception as e: + return + + try: + lower_threshold_val = self.ma_lower_threshold_entry.get_value() + except Exception as e: + lower_threshold_val = 0.0 + + if area < float(upper_threshold_val) and area > float(lower_threshold_val): + current_pos = geo_el['solid'].exterior.coords[-1] + text_elem = '%.4f' % area + text.append(text_elem) + position.append(current_pos) + + if text: + self.ma_annotation.set(text=text, pos=position, visible=True, + font_size=self.app.defaults["cncjob_annotation_fontsize"], + color=self.app.defaults["global_sel_draw_color"]) + self.app.inform.emit(_("[success] Polygon areas marked.")) + else: + self.app.inform.emit(_("[WARNING_NOTCL] There are no polygons to mark area.")) + + def on_eraser(self): + self.select_tool('eraser') + def on_transform(self): if type(self.active_tool) == FCTransform: self.select_tool('select') @@ -4526,6 +4679,8 @@ class FlatCAMGrbEditor(QtCore.QObject): self.buffer_tool_frame.hide() if tool_name == 'scale' or tool_name == 'all': self.scale_tool_frame.hide() + if tool_name == 'markarea' or tool_name == 'all': + self.ma_tool_frame.hide() except Exception as e: log.debug("FlatCAMGrbEditor.hide_tool() --> %s" % str(e)) self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab) diff --git a/flatcamGUI/FlatCAMGUI.py b/flatcamGUI/FlatCAMGUI.py index 51feb37f..fe54cf74 100644 --- a/flatcamGUI/FlatCAMGUI.py +++ b/flatcamGUI/FlatCAMGUI.py @@ -488,6 +488,10 @@ class FlatCAMGUI(QtWidgets.QMainWindow): _('Buffer\tB')) self.grb_add_scale_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/scale32.png'), _('Scale\tS')) + self.grb_add_markarea_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/markarea32.png'), + _('Mark Area\tALT+A')) + self.grb_add_eraser_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/eraser26.png'), + _('Eraser\tCTRL+E')) self.grb_transform_menuitem = self.grb_editor_menu.addAction( QtGui.QIcon('share/transform.png'),_( "Transform\tALT+R") ) @@ -716,6 +720,9 @@ class FlatCAMGUI(QtWidgets.QMainWindow): self.aperture_buffer_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/buffer16-2.png'), _('Buffer')) self.aperture_scale_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/scale32.png'), _('Scale')) + self.aperture_markarea_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/markarea32.png'), + _('Mark Area')) + self.aperture_eraser_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/eraser26.png'), _('Eraser')) self.grb_edit_toolbar.addSeparator() @@ -1546,6 +1553,10 @@ class FlatCAMGUI(QtWidgets.QMainWindow): ESC  Abort and return to Select + + CTRL+E +  Eraser Tool + CTRL+S  Save Object and Exit Editor @@ -1553,6 +1564,14 @@ class FlatCAMGUI(QtWidgets.QMainWindow):     + + + ALT+A +  Mark Area Tool + + + ALT+N +  Poligonize Tool ALT+R @@ -1945,6 +1964,8 @@ class FlatCAMGUI(QtWidgets.QMainWindow): self.aperture_buffer_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/buffer16-2.png'), _('Buffer')) self.aperture_scale_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/scale32.png'), _('Scale')) + self.aperture_markarea_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/markarea32.png'), + _('Mark Area')) self.aperture_eraser_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/eraser26.png'), _('Eraser')) self.grb_edit_toolbar.addSeparator() @@ -2604,6 +2625,11 @@ class FlatCAMGUI(QtWidgets.QMainWindow): self.app.on_shortcut_list() elif self.app.call_source == 'grb_editor': if modifiers == QtCore.Qt.ControlModifier: + # Eraser Tool + if key == QtCore.Qt.Key_E or key == 'E': + self.app.grb_editor.on_eraser() + return + # save (update) the current geometry and return to the App if key == QtCore.Qt.Key_S or key == 'S': self.app.editor2object() @@ -2617,11 +2643,15 @@ class FlatCAMGUI(QtWidgets.QMainWindow): elif modifiers == QtCore.Qt.ShiftModifier: pass elif modifiers == QtCore.Qt.AltModifier: + # Mark Area Tool + if key == QtCore.Qt.Key_A or key == 'A': + self.app.grb_editor.on_markarea() + return + # Poligonize Tool if key == QtCore.Qt.Key_N or key == 'N': self.app.grb_editor.on_poligonize() return - # Transformation Tool if key == QtCore.Qt.Key_R or key == 'R': self.app.grb_editor.on_transform() diff --git a/share/markarea32.png b/share/markarea32.png new file mode 100644 index 0000000000000000000000000000000000000000..028548ba581b93098c9a4b0979d6815090fe33cb GIT binary patch literal 699 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE0wix1Z>k4UEa{HEjtmSN`?>!lvVtU&J%W50 z7^>757#dm_7=8hT8eT9klo~KFyh>nTu$sZZAYL$MSD+10f+@+{-G$+Qd;gjJKptm- zM`SSr19v9~Gn$_~y%s3QUgGKN%Kn(0S3poFF;n{x0|VnaPZ!4!kK=o<*k=R>im-i% zkDHuj9kTI8)?aq9mD?UEI61fo?y~5xTJd1P3XN_+E)Ks69SITbQ8M# zVw3y&1CGX*HcoUEK9q5NgRAJmO+jmPt1_Kq*!}-ZDLrERxM{|(#yLBq7T*!Dy1#<$ zzMGn8S3MVbfIFzX`vhkkX+OI-6#!0)~gDmo{ zoQz^QYjnx%wu-}Qzt>-^a~9vOx{$b9_oLFbo!UnNx#dntU&y`Gk<28@y2{*0Hqt(O zzh}OT(UaYVm49!|G5DKa@P$M3eoWap-LvR|9@-lyx1=?8NcJUDZ<1sHP-swJ)wB`Jv|saDBFsX&Us$iUE2 z*T7uY&^W}<%*xQ*%EUz5z`)ADAnv~bP0l+XkK D6*U-& literal 0 HcmV?d00001