Merged in marius_stanciu/flatcam_beta/Beta (pull request #282)
Beta - updates
This commit is contained in:
commit
ea00ec4e2f
|
@ -141,8 +141,8 @@ class App(QtCore.QObject):
|
||||||
# ##########################################################################
|
# ##########################################################################
|
||||||
# ################## Version and VERSION DATE ##############################
|
# ################## Version and VERSION DATE ##############################
|
||||||
# ##########################################################################
|
# ##########################################################################
|
||||||
version = 8.991
|
version = 8.992
|
||||||
version_date = "2019/12/27"
|
version_date = "2020/01/02"
|
||||||
beta = True
|
beta = True
|
||||||
engine = '3D'
|
engine = '3D'
|
||||||
|
|
||||||
|
@ -843,6 +843,7 @@ class App(QtCore.QObject):
|
||||||
"tools_transform_mirror_reference": False,
|
"tools_transform_mirror_reference": False,
|
||||||
"tools_transform_mirror_point": (0, 0),
|
"tools_transform_mirror_point": (0, 0),
|
||||||
"tools_transform_buffer_dis": 0.0,
|
"tools_transform_buffer_dis": 0.0,
|
||||||
|
"tools_transform_buffer_factor": 100.0,
|
||||||
"tools_transform_buffer_corner": True,
|
"tools_transform_buffer_corner": True,
|
||||||
|
|
||||||
# SolderPaste Tool
|
# SolderPaste Tool
|
||||||
|
@ -1465,6 +1466,7 @@ class App(QtCore.QObject):
|
||||||
"tools_transform_mirror_reference": self.ui.tools_defaults_form.tools_transform_group.mirror_reference_cb,
|
"tools_transform_mirror_reference": self.ui.tools_defaults_form.tools_transform_group.mirror_reference_cb,
|
||||||
"tools_transform_mirror_point": self.ui.tools_defaults_form.tools_transform_group.flip_ref_entry,
|
"tools_transform_mirror_point": self.ui.tools_defaults_form.tools_transform_group.flip_ref_entry,
|
||||||
"tools_transform_buffer_dis": self.ui.tools_defaults_form.tools_transform_group.buffer_entry,
|
"tools_transform_buffer_dis": self.ui.tools_defaults_form.tools_transform_group.buffer_entry,
|
||||||
|
"tools_transform_buffer_factor": self.ui.tools_defaults_form.tools_transform_group.buffer_factor_entry,
|
||||||
"tools_transform_buffer_corner": self.ui.tools_defaults_form.tools_transform_group.buffer_rounded_cb,
|
"tools_transform_buffer_corner": self.ui.tools_defaults_form.tools_transform_group.buffer_rounded_cb,
|
||||||
|
|
||||||
# SolderPaste Dispensing Tool
|
# SolderPaste Dispensing Tool
|
||||||
|
@ -1793,12 +1795,14 @@ class App(QtCore.QObject):
|
||||||
|
|
||||||
if self.cmd_line_headless == 1:
|
if self.cmd_line_headless == 1:
|
||||||
self.trayIcon = FlatCAMSystemTray(app=self,
|
self.trayIcon = FlatCAMSystemTray(app=self,
|
||||||
icon=QtGui.QIcon(self.resource_location + '/flatcam_icon32_green.png'),
|
icon=QtGui.QIcon(self.resource_location +
|
||||||
|
'/flatcam_icon32_green.png'),
|
||||||
headless=True,
|
headless=True,
|
||||||
parent=self.parent_w)
|
parent=self.parent_w)
|
||||||
else:
|
else:
|
||||||
self.trayIcon = FlatCAMSystemTray(app=self,
|
self.trayIcon = FlatCAMSystemTray(app=self,
|
||||||
icon=QtGui.QIcon(self.resource_location + '/flatcam_icon32_green.png'),
|
icon=QtGui.QIcon(self.resource_location +
|
||||||
|
'/flatcam_icon32_green.png'),
|
||||||
parent=self.parent_w)
|
parent=self.parent_w)
|
||||||
|
|
||||||
# #############################################################################
|
# #############################################################################
|
||||||
|
@ -2919,7 +2923,6 @@ class App(QtCore.QObject):
|
||||||
# self.defaults_form_fields[option].set_value(self.defaults[option])
|
# self.defaults_form_fields[option].set_value(self.defaults[option])
|
||||||
# except KeyError:
|
# except KeyError:
|
||||||
# #self.log.debug("defaults_write_form(): No field for: %s" % option)
|
# #self.log.debug("defaults_write_form(): No field for: %s" % option)
|
||||||
# # TODO: Rethink this?
|
|
||||||
# pass
|
# pass
|
||||||
|
|
||||||
def defaults_write_form_field(self, field, factor=None, units=None, defaults_dict=None):
|
def defaults_write_form_field(self, field, factor=None, units=None, defaults_dict=None):
|
||||||
|
@ -2929,6 +2932,7 @@ class App(QtCore.QObject):
|
||||||
:param field: the GUI element in Preferences GUI to be updated
|
:param field: the GUI element in Preferences GUI to be updated
|
||||||
:param factor: factor to be applied to the field parameter
|
:param factor: factor to be applied to the field parameter
|
||||||
:param units: current FLatCAM measuring units
|
:param units: current FLatCAM measuring units
|
||||||
|
:param defaults_dict: the defaults storage
|
||||||
:return: None, it updates GUI elements
|
:return: None, it updates GUI elements
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -2949,8 +2953,6 @@ class App(QtCore.QObject):
|
||||||
elif units == 'MM' and (field == 'global_gridx' or field == 'global_gridy'):
|
elif units == 'MM' and (field == 'global_gridx' or field == 'global_gridy'):
|
||||||
self.defaults_form_fields[field].set_value((def_dict[field] * factor))
|
self.defaults_form_fields[field].set_value((def_dict[field] * factor))
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# self.log.debug("defaults_write_form(): No field for: %s" % option)
|
|
||||||
# TODO: Rethink this?
|
|
||||||
pass
|
pass
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
log.debug(field)
|
log.debug(field)
|
||||||
|
@ -3258,6 +3260,10 @@ class App(QtCore.QObject):
|
||||||
# set call source to the Editor we go into
|
# set call source to the Editor we go into
|
||||||
self.call_source = 'grb_editor'
|
self.call_source = 'grb_editor'
|
||||||
|
|
||||||
|
# reset the following variables so the UI is built again after edit
|
||||||
|
edited_object.ui_build = False
|
||||||
|
edited_object.build_aperture_storage = False
|
||||||
|
|
||||||
# make sure that we can't select another object while in Editor Mode:
|
# make sure that we can't select another object while in Editor Mode:
|
||||||
# self.collection.view.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
|
# self.collection.view.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
|
||||||
self.ui.project_frame.setDisabled(True)
|
self.ui.project_frame.setDisabled(True)
|
||||||
|
@ -3267,8 +3273,7 @@ class App(QtCore.QObject):
|
||||||
|
|
||||||
self.ui.plot_tab_area.setTabText(0, "EDITOR Area")
|
self.ui.plot_tab_area.setTabText(0, "EDITOR Area")
|
||||||
self.ui.plot_tab_area.protectTab(0)
|
self.ui.plot_tab_area.protectTab(0)
|
||||||
self.inform.emit('[WARNING_NOTCL] %s' %
|
self.inform.emit('[WARNING_NOTCL] %s' % _("Editor is activated ..."))
|
||||||
_("Editor is activated ..."))
|
|
||||||
|
|
||||||
self.should_we_save = True
|
self.should_we_save = True
|
||||||
|
|
||||||
|
@ -6828,6 +6833,9 @@ class App(QtCore.QObject):
|
||||||
if self.ui.plot_tab_area.tabText(idx) == _("Preferences"):
|
if self.ui.plot_tab_area.tabText(idx) == _("Preferences"):
|
||||||
self.ui.plot_tab_area.tabBar.setTabTextColor(idx, QtGui.QColor('black'))
|
self.ui.plot_tab_area.tabBar.setTabTextColor(idx, QtGui.QColor('black'))
|
||||||
|
|
||||||
|
# restore the default stylesheet by setting a blank one
|
||||||
|
self.ui.pref_apply_button.setStyleSheet("")
|
||||||
|
|
||||||
self.inform.emit('%s' % _("Preferences applied."))
|
self.inform.emit('%s' % _("Preferences applied."))
|
||||||
|
|
||||||
# make sure we update the self.current_defaults dict used to undo changes to self.defaults
|
# make sure we update the self.current_defaults dict used to undo changes to self.defaults
|
||||||
|
@ -6902,7 +6910,7 @@ class App(QtCore.QObject):
|
||||||
|
|
||||||
# work only if the notebook tab on focus is the Selected_Tab and only if the object is Geometry
|
# work only if the notebook tab on focus is the Selected_Tab and only if the object is Geometry
|
||||||
if notebook_widget_name == 'selected_tab':
|
if notebook_widget_name == 'selected_tab':
|
||||||
if str(type(self.collection.get_active())) == "<class 'FlatCAMObj.FlatCAMGeometry'>":
|
if self.collection.get_active().kind == 'geometry':
|
||||||
# Tool add works for Geometry only if Advanced is True in Preferences
|
# Tool add works for Geometry only if Advanced is True in Preferences
|
||||||
if self.defaults["global_app_level"] == 'a':
|
if self.defaults["global_app_level"] == 'a':
|
||||||
tool_add_popup = FCInputDialog(title="New Tool ...",
|
tool_add_popup = FCInputDialog(title="New Tool ...",
|
||||||
|
@ -6918,8 +6926,7 @@ class App(QtCore.QObject):
|
||||||
return
|
return
|
||||||
self.collection.get_active().on_tool_add(dia=float(val))
|
self.collection.get_active().on_tool_add(dia=float(val))
|
||||||
else:
|
else:
|
||||||
self.inform.emit('[WARNING_NOTCL] %s...' %
|
self.inform.emit('[WARNING_NOTCL] %s...' % _("Adding Tool cancelled"))
|
||||||
_("Adding Tool cancelled"))
|
|
||||||
else:
|
else:
|
||||||
msgbox = QtWidgets.QMessageBox()
|
msgbox = QtWidgets.QMessageBox()
|
||||||
msgbox.setText(_("Adding Tool works only when Advanced is checked.\n"
|
msgbox.setText(_("Adding Tool works only when Advanced is checked.\n"
|
||||||
|
@ -7616,12 +7623,15 @@ class App(QtCore.QObject):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def on_preferences_edited(self):
|
def on_preferences_edited(self):
|
||||||
|
if self.preferences_changed_flag is False:
|
||||||
self.inform.emit('[WARNING_NOTCL] %s' % _("Preferences edited but not saved."))
|
self.inform.emit('[WARNING_NOTCL] %s' % _("Preferences edited but not saved."))
|
||||||
|
|
||||||
for idx in range(self.ui.plot_tab_area.count()):
|
for idx in range(self.ui.plot_tab_area.count()):
|
||||||
if self.ui.plot_tab_area.tabText(idx) == _("Preferences"):
|
if self.ui.plot_tab_area.tabText(idx) == _("Preferences"):
|
||||||
self.ui.plot_tab_area.tabBar.setTabTextColor(idx, QtGui.QColor('red'))
|
self.ui.plot_tab_area.tabBar.setTabTextColor(idx, QtGui.QColor('red'))
|
||||||
|
|
||||||
|
self.ui.pref_apply_button.setStyleSheet("QPushButton {color: red;}")
|
||||||
|
|
||||||
self.preferences_changed_flag = True
|
self.preferences_changed_flag = True
|
||||||
|
|
||||||
def on_tools_database(self):
|
def on_tools_database(self):
|
||||||
|
@ -9908,9 +9918,34 @@ class App(QtCore.QObject):
|
||||||
self.toggle_codeeditor = False
|
self.toggle_codeeditor = False
|
||||||
|
|
||||||
def on_code_editor_close(self):
|
def on_code_editor_close(self):
|
||||||
print("closed")
|
|
||||||
self.toggle_codeeditor = False
|
self.toggle_codeeditor = False
|
||||||
|
|
||||||
|
def goto_text_line(self):
|
||||||
|
"""
|
||||||
|
Will scroll a text to the specified text line.
|
||||||
|
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
dia_box = Dialog_box(title=_("Go to Line ..."),
|
||||||
|
label=_("Line:"),
|
||||||
|
icon=QtGui.QIcon(self.resource_location + '/jump_to16.png'),
|
||||||
|
initial_text='')
|
||||||
|
try:
|
||||||
|
line = int(dia_box.location) - 1
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
line = 0
|
||||||
|
|
||||||
|
if dia_box.ok:
|
||||||
|
# make sure to move first the cursor at the end so after finding the line the line will be positioned
|
||||||
|
# at the top of the window
|
||||||
|
self.ui.plot_tab_area.currentWidget().code_editor.moveCursor(QTextCursor.End)
|
||||||
|
# get the document() of the TextEditor
|
||||||
|
doc = self.ui.plot_tab_area.currentWidget().code_editor.document()
|
||||||
|
# create a Text Cursor based on the searched line
|
||||||
|
cursor = QTextCursor(doc.findBlockByLineNumber(line))
|
||||||
|
# set cursor of the code editor with the cursor at the searcehd line
|
||||||
|
self.ui.plot_tab_area.currentWidget().code_editor.setTextCursor(cursor)
|
||||||
|
|
||||||
def on_filenewscript(self, silent=False, name=None, text=None):
|
def on_filenewscript(self, silent=False, name=None, text=None):
|
||||||
"""
|
"""
|
||||||
Will create a new script file and open it in the Code Editor
|
Will create a new script file and open it in the Code Editor
|
||||||
|
@ -9921,8 +9956,7 @@ class App(QtCore.QObject):
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
if silent is False:
|
if silent is False:
|
||||||
self.inform.emit('[success] %s' %
|
self.inform.emit('[success] %s' % _("New TCL script file created in Code Editor."))
|
||||||
_("New TCL script file created in Code Editor."))
|
|
||||||
|
|
||||||
# delete the absolute and relative position and messages in the infobar
|
# delete the absolute and relative position and messages in the infobar
|
||||||
self.ui.position_label.setText("")
|
self.ui.position_label.setText("")
|
||||||
|
@ -10025,8 +10059,7 @@ class App(QtCore.QObject):
|
||||||
self.shell._sysShell.exec_command(cmd_line_shellfile_content, no_echo=True)
|
self.shell._sysShell.exec_command(cmd_line_shellfile_content, no_echo=True)
|
||||||
|
|
||||||
if silent is False:
|
if silent is False:
|
||||||
self.inform.emit('[success] %s' %
|
self.inform.emit('[success] %s' % _("TCL script file opened in Code Editor and executed."))
|
||||||
_("TCL script file opened in Code Editor and executed."))
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug("App.on_filerunscript() -> %s" % str(e))
|
log.debug("App.on_filerunscript() -> %s" % str(e))
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
|
|
@ -662,6 +662,12 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
||||||
self.fill_color = self.app.defaults['gerber_plot_fill']
|
self.fill_color = self.app.defaults['gerber_plot_fill']
|
||||||
self.outline_color = self.app.defaults['gerber_plot_line']
|
self.outline_color = self.app.defaults['gerber_plot_line']
|
||||||
|
|
||||||
|
# keep track if the UI is built so we don't have to build it every time
|
||||||
|
self.ui_build = False
|
||||||
|
|
||||||
|
# build only once the aperture storage (takes time)
|
||||||
|
self.build_aperture_storage = False
|
||||||
|
|
||||||
# Attributes to be included in serialization
|
# Attributes to be included in serialization
|
||||||
# Always append to it because it carries contents
|
# Always append to it because it carries contents
|
||||||
# from predecessors.
|
# from predecessors.
|
||||||
|
@ -834,6 +840,9 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
||||||
def build_ui(self):
|
def build_ui(self):
|
||||||
FlatCAMObj.build_ui(self)
|
FlatCAMObj.build_ui(self)
|
||||||
|
|
||||||
|
if self.ui.aperture_table_visibility_cb.get_value() and self.ui_build is False:
|
||||||
|
self.ui_build = True
|
||||||
|
|
||||||
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
|
||||||
self.ui.apertures_table.itemChanged.disconnect()
|
self.ui.apertures_table.itemChanged.disconnect()
|
||||||
|
@ -847,12 +856,6 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
||||||
sort.append(int(k))
|
sort.append(int(k))
|
||||||
sorted_apertures = sorted(sort)
|
sorted_apertures = sorted(sort)
|
||||||
|
|
||||||
# sort = []
|
|
||||||
# for k, v in list(self.aperture_macros.items()):
|
|
||||||
# sort.append(k)
|
|
||||||
# sorted_macros = sorted(sort)
|
|
||||||
|
|
||||||
# n = len(sorted_apertures) + len(sorted_macros)
|
|
||||||
n = len(sorted_apertures)
|
n = len(sorted_apertures)
|
||||||
self.ui.apertures_table.setRowCount(n)
|
self.ui.apertures_table.setRowCount(n)
|
||||||
|
|
||||||
|
@ -1615,6 +1618,9 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
||||||
def on_aperture_table_visibility_change(self):
|
def on_aperture_table_visibility_change(self):
|
||||||
if self.ui.aperture_table_visibility_cb.isChecked():
|
if self.ui.aperture_table_visibility_cb.isChecked():
|
||||||
# add the shapes storage for marking apertures
|
# add the shapes storage for marking apertures
|
||||||
|
if self.build_aperture_storage is False:
|
||||||
|
self.build_aperture_storage = True
|
||||||
|
|
||||||
if self.app.is_legacy is False:
|
if self.app.is_legacy is False:
|
||||||
for ap_code in self.apertures:
|
for ap_code in self.apertures:
|
||||||
self.mark_shapes[ap_code] = self.app.plotcanvas.new_shape_collection(layers=1)
|
self.mark_shapes[ap_code] = self.app.plotcanvas.new_shape_collection(layers=1)
|
||||||
|
@ -1629,6 +1635,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
||||||
|
|
||||||
self.ui.mark_all_cb.setVisible(True)
|
self.ui.mark_all_cb.setVisible(True)
|
||||||
self.ui.mark_all_cb.setChecked(False)
|
self.ui.mark_all_cb.setChecked(False)
|
||||||
|
self.build_ui()
|
||||||
else:
|
else:
|
||||||
self.ui.apertures_table.setVisible(False)
|
self.ui.apertures_table.setVisible(False)
|
||||||
|
|
||||||
|
@ -1640,9 +1647,9 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
||||||
self.ui.apertures_table.cellWidget(row, 5).set_value(False)
|
self.ui.apertures_table.cellWidget(row, 5).set_value(False)
|
||||||
self.clear_plot_apertures()
|
self.clear_plot_apertures()
|
||||||
|
|
||||||
for ap in list(self.mark_shapes.keys()):
|
# for ap in list(self.mark_shapes.keys()):
|
||||||
# self.mark_shapes[ap].enabled = False
|
# # self.mark_shapes[ap].enabled = False
|
||||||
del self.mark_shapes[ap]
|
# del self.mark_shapes[ap]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug(" FlatCAMGerber.on_aperture_visibility_changed() --> %s" % str(e))
|
log.debug(" FlatCAMGerber.on_aperture_visibility_changed() --> %s" % str(e))
|
||||||
|
|
||||||
|
@ -2208,8 +2215,8 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
||||||
Gerber.skew(self, angle_x=angle_x, angle_y=angle_y, point=point)
|
Gerber.skew(self, angle_x=angle_x, angle_y=angle_y, point=point)
|
||||||
self.replotApertures.emit()
|
self.replotApertures.emit()
|
||||||
|
|
||||||
def buffer(self, distance, join):
|
def buffer(self, distance, join, factor=None):
|
||||||
Gerber.buffer(self, distance=distance, join=join)
|
Gerber.buffer(self, distance=distance, join=join, factor=factor)
|
||||||
self.replotApertures.emit()
|
self.replotApertures.emit()
|
||||||
|
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
|
|
17
README.md
17
README.md
|
@ -9,6 +9,23 @@ CAD program, and create G-Code for Isolation routing.
|
||||||
|
|
||||||
=================================================
|
=================================================
|
||||||
|
|
||||||
|
30.12.2019
|
||||||
|
|
||||||
|
- Buffer sub-tool in Transform Tool: added the possibility to apply a factor effectively scaling the aperture size thus the copper features sizes
|
||||||
|
- in Transform Tool adjusted the GUI
|
||||||
|
- fixed some decimals issues in NCC Tool, Paint Tool and Excellon Editor (they were still using the harcoded values)
|
||||||
|
- some small updates in the NCC Tool
|
||||||
|
|
||||||
|
29.12.2019
|
||||||
|
|
||||||
|
- the Apply button text in Preferences is now made red when changes were made and require to be applied
|
||||||
|
- the Gerber UI is built only once now so the process is lighter on CPU
|
||||||
|
- the Gerber apertures marking shapes storage is now built only once because the more are built the more sluggish is the interface
|
||||||
|
- added a new function called by shortcut key combo CTRL+G when the current widget in Plot Area is an Code Editor. It will jump to the specified line in the text.
|
||||||
|
- fixed a small where the app tried to hide a label that I've removed previously
|
||||||
|
- in Paint Tool Preferences allowed to add a list of initial tools separated by comma
|
||||||
|
- in Geometry Paint Tool fixed the Overlap rate to work between 0 and 99.9999%
|
||||||
|
|
||||||
28.12.2019
|
28.12.2019
|
||||||
|
|
||||||
- more updates to the Preferences window and in some other parts of the GUI
|
- more updates to the Preferences window and in some other parts of the GUI
|
||||||
|
|
25
camlib.py
25
camlib.py
|
@ -2118,11 +2118,11 @@ class Geometry(object):
|
||||||
# self.solid_geometry = affinity.skew(self.solid_geometry, angle_x, angle_y,
|
# self.solid_geometry = affinity.skew(self.solid_geometry, angle_x, angle_y,
|
||||||
# origin=(px, py))
|
# origin=(px, py))
|
||||||
|
|
||||||
def buffer(self, distance, join):
|
def buffer(self, distance, join, factor):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
:param distance:
|
:param distance: if 'factor' is True then distance is the factor
|
||||||
:param join:
|
:param factor: True or False (None)
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -2145,7 +2145,10 @@ class Geometry(object):
|
||||||
self.app.proc_container.update_view_text(' %d%%' % disp_number)
|
self.app.proc_container.update_view_text(' %d%%' % disp_number)
|
||||||
self.old_disp_number = disp_number
|
self.old_disp_number = disp_number
|
||||||
|
|
||||||
|
if factor is None:
|
||||||
return obj.buffer(distance, resolution=self.geo_steps_per_circle, join_style=join)
|
return obj.buffer(distance, resolution=self.geo_steps_per_circle, join_style=join)
|
||||||
|
else:
|
||||||
|
return affinity.scale(obj, xfact=distance, yfact=distance, origin='center')
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
@ -2155,20 +2158,23 @@ class Geometry(object):
|
||||||
# variables to display the percentage of work done
|
# variables to display the percentage of work done
|
||||||
self.geo_len = 0
|
self.geo_len = 0
|
||||||
try:
|
try:
|
||||||
for __ in self.tools[tool]['solid_geometry']:
|
self.geo_len += len(self.tools[tool]['solid_geometry'])
|
||||||
self.geo_len += 1
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
self.geo_len = 1
|
self.geo_len += 1
|
||||||
self.old_disp_number = 0
|
self.old_disp_number = 0
|
||||||
self.el_count = 0
|
self.el_count = 0
|
||||||
|
|
||||||
self.tools[tool]['solid_geometry'] = buffer_geom(self.tools[tool]['solid_geometry'])
|
res = buffer_geom(self.tools[tool]['solid_geometry'])
|
||||||
|
try:
|
||||||
|
__ = iter(res)
|
||||||
|
self.tools[tool]['solid_geometry'] = res
|
||||||
|
except TypeError:
|
||||||
|
self.tools[tool]['solid_geometry'] = [res]
|
||||||
|
|
||||||
# variables to display the percentage of work done
|
# variables to display the percentage of work done
|
||||||
self.geo_len = 0
|
self.geo_len = 0
|
||||||
try:
|
try:
|
||||||
for __ in self.solid_geometry:
|
self.geo_len = len(self.solid_geometry)
|
||||||
self.geo_len += 1
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
self.geo_len = 1
|
self.geo_len = 1
|
||||||
self.old_disp_number = 0
|
self.old_disp_number = 0
|
||||||
|
@ -2182,6 +2188,7 @@ class Geometry(object):
|
||||||
|
|
||||||
self.app.proc_container.new_text = ''
|
self.app.proc_container.new_text = ''
|
||||||
|
|
||||||
|
|
||||||
class AttrDict(dict):
|
class AttrDict(dict):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(AttrDict, self).__init__(*args, **kwargs)
|
super(AttrDict, self).__init__(*args, **kwargs)
|
||||||
|
|
|
@ -2227,11 +2227,6 @@ class FlatCAMExcEditor(QtCore.QObject):
|
||||||
# updated units
|
# updated units
|
||||||
self.units = self.app.defaults['units'].upper()
|
self.units = self.app.defaults['units'].upper()
|
||||||
|
|
||||||
if self.units == "IN":
|
|
||||||
self.decimals = 4
|
|
||||||
else:
|
|
||||||
self.decimals = 2
|
|
||||||
|
|
||||||
self.olddia_newdia.clear()
|
self.olddia_newdia.clear()
|
||||||
self.tool2tooldia.clear()
|
self.tool2tooldia.clear()
|
||||||
|
|
||||||
|
|
|
@ -441,8 +441,7 @@ class PaintOptionsTool(FlatCAMTool):
|
||||||
# Tool dia
|
# Tool dia
|
||||||
ptdlabel = QtWidgets.QLabel('%s:' % _('Tool dia'))
|
ptdlabel = QtWidgets.QLabel('%s:' % _('Tool dia'))
|
||||||
ptdlabel.setToolTip(
|
ptdlabel.setToolTip(
|
||||||
_("Diameter of the tool to\n"
|
_("Diameter of the tool to be used in the operation.")
|
||||||
"be used in the operation.")
|
|
||||||
)
|
)
|
||||||
grid.addWidget(ptdlabel, 0, 0)
|
grid.addWidget(ptdlabel, 0, 0)
|
||||||
|
|
||||||
|
@ -463,10 +462,10 @@ class PaintOptionsTool(FlatCAMTool):
|
||||||
"due of too many paths.")
|
"due of too many paths.")
|
||||||
)
|
)
|
||||||
self.paintoverlap_entry = FCDoubleSpinner(suffix='%')
|
self.paintoverlap_entry = FCDoubleSpinner(suffix='%')
|
||||||
self.paintoverlap_entry.set_range(0.0000, 1.0000)
|
self.paintoverlap_entry.set_range(0.0000, 99.9999)
|
||||||
self.paintoverlap_entry.set_precision(self.decimals)
|
self.paintoverlap_entry.set_precision(self.decimals)
|
||||||
self.paintoverlap_entry.setWrapping(True)
|
self.paintoverlap_entry.setWrapping(True)
|
||||||
self.paintoverlap_entry.setSingleStep(0.1)
|
self.paintoverlap_entry.setSingleStep(1)
|
||||||
|
|
||||||
grid.addWidget(ovlabel, 1, 0)
|
grid.addWidget(ovlabel, 1, 0)
|
||||||
grid.addWidget(self.paintoverlap_entry, 1, 1)
|
grid.addWidget(self.paintoverlap_entry, 1, 1)
|
||||||
|
@ -525,7 +524,6 @@ class PaintOptionsTool(FlatCAMTool):
|
||||||
# Buttons
|
# Buttons
|
||||||
hlay = QtWidgets.QHBoxLayout()
|
hlay = QtWidgets.QHBoxLayout()
|
||||||
self.layout.addLayout(hlay)
|
self.layout.addLayout(hlay)
|
||||||
hlay.addStretch()
|
|
||||||
self.paint_button = QtWidgets.QPushButton(_("Paint"))
|
self.paint_button = QtWidgets.QPushButton(_("Paint"))
|
||||||
hlay.addWidget(self.paint_button)
|
hlay.addWidget(self.paint_button)
|
||||||
|
|
||||||
|
@ -584,9 +582,9 @@ class PaintOptionsTool(FlatCAMTool):
|
||||||
_("Paint cancelled. No shape selected."))
|
_("Paint cancelled. No shape selected."))
|
||||||
return
|
return
|
||||||
|
|
||||||
tooldia = float(self.painttooldia_entry.get_value())
|
tooldia = self.painttooldia_entry.get_value()
|
||||||
overlap = float(self.paintoverlap_entry.get_value())
|
overlap = self.paintoverlap_entry.get_value() / 100.0
|
||||||
margin = float(self.paintmargin_entry.get_value())
|
margin = self.paintmargin_entry.get_value()
|
||||||
|
|
||||||
method = self.paintmethod_combo.get_value()
|
method = self.paintmethod_combo.get_value()
|
||||||
contour = self.paintcontour_cb.get_value()
|
contour = self.paintcontour_cb.get_value()
|
||||||
|
@ -4749,9 +4747,9 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
||||||
|
|
||||||
def paint(self, tooldia, overlap, margin, connect, contour, method):
|
def paint(self, tooldia, overlap, margin, connect, contour, method):
|
||||||
|
|
||||||
if overlap >= 1:
|
if overlap >= 100:
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
||||||
_("Could not do Paint. Overlap value has to be less than 1.00 (100%%)."))
|
_("Could not do Paint. Overlap value has to be less than 100%%."))
|
||||||
return
|
return
|
||||||
|
|
||||||
self.paint_tooldia = tooldia
|
self.paint_tooldia = tooldia
|
||||||
|
|
|
@ -2723,6 +2723,10 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
||||||
|
|
||||||
# Open Gerber file
|
# Open Gerber file
|
||||||
if key == QtCore.Qt.Key_G:
|
if key == QtCore.Qt.Key_G:
|
||||||
|
widget_name = self.plot_tab_area.currentWidget().objectName()
|
||||||
|
if 'editor' in widget_name.lower():
|
||||||
|
self.app.goto_text_line()
|
||||||
|
else:
|
||||||
self.app.on_fileopengerber()
|
self.app.on_fileopengerber()
|
||||||
|
|
||||||
# Distance Tool
|
# Distance Tool
|
||||||
|
|
|
@ -1729,7 +1729,6 @@ class GeneralAppPrefGroupUI(OptionsGroupUI):
|
||||||
self.layout.addStretch()
|
self.layout.addStretch()
|
||||||
|
|
||||||
if sys.platform != 'win32':
|
if sys.platform != 'win32':
|
||||||
self.portability_label.hide()
|
|
||||||
self.portability_cb.hide()
|
self.portability_cb.hide()
|
||||||
|
|
||||||
# splash screen button signal
|
# splash screen button signal
|
||||||
|
@ -2521,7 +2520,9 @@ class GerberEditorPrefGroupUI(OptionsGroupUI):
|
||||||
|
|
||||||
self.adddim_label = QtWidgets.QLabel('%s:' % _('Aperture Dimensions'))
|
self.adddim_label = QtWidgets.QLabel('%s:' % _('Aperture Dimensions'))
|
||||||
self.adddim_label.setToolTip(
|
self.adddim_label.setToolTip(
|
||||||
_("Diameters of the cutting tools, separated by ','")
|
_("Diameters of the cutting tools, separated by comma.\n"
|
||||||
|
"The value of the diameter has to use the dot decimals separator.\n"
|
||||||
|
"Valid values: 0.3, 1.0")
|
||||||
)
|
)
|
||||||
grid0.addWidget(self.adddim_label, 5, 0)
|
grid0.addWidget(self.adddim_label, 5, 0)
|
||||||
self.adddim_entry = FCEntry()
|
self.adddim_entry = FCEntry()
|
||||||
|
@ -3874,7 +3875,9 @@ class GeometryGenPrefGroupUI(OptionsGroupUI):
|
||||||
# Tooldia
|
# Tooldia
|
||||||
tdlabel = QtWidgets.QLabel('%s:' % _('Tool dia'))
|
tdlabel = QtWidgets.QLabel('%s:' % _('Tool dia'))
|
||||||
tdlabel.setToolTip(
|
tdlabel.setToolTip(
|
||||||
_("Diameters of the cutting tools, separated by ','")
|
_("Diameters of the cutting tools, separated by comma.\n"
|
||||||
|
"The value of the diameter has to use the dot decimals separator.\n"
|
||||||
|
"Valid values: 0.3, 1.0")
|
||||||
)
|
)
|
||||||
self.cnctooldia_entry = FCEntry()
|
self.cnctooldia_entry = FCEntry()
|
||||||
|
|
||||||
|
@ -5026,7 +5029,9 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI):
|
||||||
|
|
||||||
ncctdlabel = QtWidgets.QLabel('%s:' % _('Tools dia'))
|
ncctdlabel = QtWidgets.QLabel('%s:' % _('Tools dia'))
|
||||||
ncctdlabel.setToolTip(
|
ncctdlabel.setToolTip(
|
||||||
_("Diameters of the cutting tools, separated by ','")
|
_("Diameters of the cutting tools, separated by comma.\n"
|
||||||
|
"The value of the diameter has to use the dot decimals separator.\n"
|
||||||
|
"Valid values: 0.3, 1.0")
|
||||||
)
|
)
|
||||||
grid0.addWidget(ncctdlabel, 0, 0)
|
grid0.addWidget(ncctdlabel, 0, 0)
|
||||||
self.ncc_tool_dia_entry = FCEntry()
|
self.ncc_tool_dia_entry = FCEntry()
|
||||||
|
@ -5534,8 +5539,9 @@ class ToolsPaintPrefGroupUI(OptionsGroupUI):
|
||||||
# Tool dia
|
# Tool dia
|
||||||
ptdlabel = QtWidgets.QLabel('%s:' % _('Tool dia'))
|
ptdlabel = QtWidgets.QLabel('%s:' % _('Tool dia'))
|
||||||
ptdlabel.setToolTip(
|
ptdlabel.setToolTip(
|
||||||
_("Diameter of the tool to\n"
|
_("Diameters of the cutting tools, separated by comma.\n"
|
||||||
"be used in the operation.")
|
"The value of the diameter has to use the dot decimals separator.\n"
|
||||||
|
"Valid values: 0.3, 1.0")
|
||||||
)
|
)
|
||||||
grid0.addWidget(ptdlabel, 0, 0)
|
grid0.addWidget(ptdlabel, 0, 0)
|
||||||
|
|
||||||
|
@ -6410,6 +6416,23 @@ class ToolsTransformPrefGroupUI(OptionsGroupUI):
|
||||||
grid0.addWidget(self.buffer_label, 17, 0)
|
grid0.addWidget(self.buffer_label, 17, 0)
|
||||||
grid0.addWidget(self.buffer_entry, 17, 1)
|
grid0.addWidget(self.buffer_entry, 17, 1)
|
||||||
|
|
||||||
|
self.buffer_factor_label = QtWidgets.QLabel('%s:' % _("Factor"))
|
||||||
|
self.buffer_factor_label.setToolTip(
|
||||||
|
_("A positive value will create the effect of dilation,\n"
|
||||||
|
"while a negative value will create the effect of erosion.\n"
|
||||||
|
"Each geometry element of the object will be increased\n"
|
||||||
|
"or decreased by the 'factor'.")
|
||||||
|
)
|
||||||
|
|
||||||
|
self.buffer_factor_entry = FCDoubleSpinner(suffix='%')
|
||||||
|
self.buffer_factor_entry.set_range(-100.0000, 1000.0000)
|
||||||
|
self.buffer_factor_entry.set_precision(self.decimals)
|
||||||
|
self.buffer_factor_entry.setWrapping(True)
|
||||||
|
self.buffer_factor_entry.setSingleStep(1)
|
||||||
|
|
||||||
|
grid0.addWidget(self.buffer_factor_label, 18, 0)
|
||||||
|
grid0.addWidget(self.buffer_factor_entry, 18, 1)
|
||||||
|
|
||||||
self.buffer_rounded_cb = FCCheckBox()
|
self.buffer_rounded_cb = FCCheckBox()
|
||||||
self.buffer_rounded_cb.setText('%s' % _("Rounded"))
|
self.buffer_rounded_cb.setText('%s' % _("Rounded"))
|
||||||
self.buffer_rounded_cb.setToolTip(
|
self.buffer_rounded_cb.setToolTip(
|
||||||
|
@ -6419,9 +6442,8 @@ class ToolsTransformPrefGroupUI(OptionsGroupUI):
|
||||||
"of the buffered shape.")
|
"of the buffered shape.")
|
||||||
)
|
)
|
||||||
|
|
||||||
grid0.addWidget(self.buffer_rounded_cb, 18, 0, 1, 2)
|
grid0.addWidget(self.buffer_rounded_cb, 19, 0, 1, 2)
|
||||||
|
|
||||||
grid0.addWidget(QtWidgets.QLabel(''), 19, 0, 1, 2)
|
|
||||||
|
|
||||||
self.layout.addStretch()
|
self.layout.addStretch()
|
||||||
|
|
||||||
|
|
|
@ -1459,11 +1459,11 @@ class Excellon(Geometry):
|
||||||
self.create_geometry()
|
self.create_geometry()
|
||||||
self.app.proc_container.new_text = ''
|
self.app.proc_container.new_text = ''
|
||||||
|
|
||||||
def buffer(self, distance, join):
|
def buffer(self, distance, join, factor):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
:param distance:
|
:param distance: if 'factor' is True then distance is the factor
|
||||||
:param join:
|
:param factor: True or False (None)
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
log.debug("flatcamParsers.ParseExcellon.Excellon.buffer()")
|
log.debug("flatcamParsers.ParseExcellon.Excellon.buffer()")
|
||||||
|
@ -1479,13 +1479,24 @@ class Excellon(Geometry):
|
||||||
return new_obj
|
return new_obj
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
|
if factor is None:
|
||||||
return obj.buffer(distance, resolution=self.geo_steps_per_circle)
|
return obj.buffer(distance, resolution=self.geo_steps_per_circle)
|
||||||
|
else:
|
||||||
|
return affinity.scale(obj, xfact=distance, yfact=distance, origin='center')
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
# buffer solid_geometry
|
# buffer solid_geometry
|
||||||
for tool, tool_dict in list(self.tools.items()):
|
for tool, tool_dict in list(self.tools.items()):
|
||||||
self.tools[tool]['solid_geometry'] = buffer_geom(tool_dict['solid_geometry'])
|
res = buffer_geom(tool_dict['solid_geometry'])
|
||||||
|
try:
|
||||||
|
__ = iter(res)
|
||||||
|
self.tools[tool]['solid_geometry'] = res
|
||||||
|
except TypeError:
|
||||||
|
self.tools[tool]['solid_geometry'] = [res]
|
||||||
|
if factor is None:
|
||||||
self.tools[tool]['C'] += distance
|
self.tools[tool]['C'] += distance
|
||||||
|
else:
|
||||||
|
self.tools[tool]['C'] *= distance
|
||||||
|
|
||||||
self.create_geometry()
|
self.create_geometry()
|
||||||
|
|
|
@ -2188,14 +2188,14 @@ class Gerber(Geometry):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug('camlib.Gerber.rotate() Exception --> %s' % str(e))
|
log.debug('camlib.Gerber.rotate() Exception --> %s' % str(e))
|
||||||
return 'fail'
|
return 'fail'
|
||||||
self.app.inform.emit('[success] %s' %
|
self.app.inform.emit('[success] %s' % _("Gerber Rotate done."))
|
||||||
_("Gerber Rotate done."))
|
|
||||||
self.app.proc_container.new_text = ''
|
self.app.proc_container.new_text = ''
|
||||||
|
|
||||||
def buffer(self, distance, join):
|
def buffer(self, distance, join, factor=None):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
:param distance:
|
:param distance: if 'factor' is True then distance is the factor
|
||||||
|
:param factor: True or False (None)
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
log.debug("parseGerber.Gerber.buffer()")
|
log.debug("parseGerber.Gerber.buffer()")
|
||||||
|
@ -2206,14 +2206,14 @@ class Gerber(Geometry):
|
||||||
# variables to display the percentage of work done
|
# variables to display the percentage of work done
|
||||||
self.geo_len = 0
|
self.geo_len = 0
|
||||||
try:
|
try:
|
||||||
for __ in self.solid_geometry:
|
self.geo_len = len(self.solid_geometry)
|
||||||
self.geo_len += 1
|
except (TypeError, ValueError):
|
||||||
except TypeError:
|
|
||||||
self.geo_len = 1
|
self.geo_len = 1
|
||||||
|
|
||||||
self.old_disp_number = 0
|
self.old_disp_number = 0
|
||||||
self.el_count = 0
|
self.el_count = 0
|
||||||
|
|
||||||
|
if factor is None:
|
||||||
def buffer_geom(obj):
|
def buffer_geom(obj):
|
||||||
if type(obj) is list:
|
if type(obj) is list:
|
||||||
new_obj = []
|
new_obj = []
|
||||||
|
@ -2228,11 +2228,17 @@ class Gerber(Geometry):
|
||||||
self.app.proc_container.update_view_text(' %d%%' % disp_number)
|
self.app.proc_container.update_view_text(' %d%%' % disp_number)
|
||||||
self.old_disp_number = disp_number
|
self.old_disp_number = disp_number
|
||||||
|
|
||||||
return obj.buffer(distance, resolution=self.steps_per_circle, join_style=join)
|
return obj.buffer(distance, resolution=int(self.steps_per_circle), join_style=join)
|
||||||
|
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
self.solid_geometry = buffer_geom(self.solid_geometry)
|
res = buffer_geom(self.solid_geometry)
|
||||||
|
try:
|
||||||
|
__ = iter(res)
|
||||||
|
self.solid_geometry = res
|
||||||
|
except TypeError:
|
||||||
|
self.solid_geometry = [res]
|
||||||
|
|
||||||
# we need to buffer the geometry stored in the Gerber apertures, too
|
# we need to buffer the geometry stored in the Gerber apertures, too
|
||||||
try:
|
try:
|
||||||
|
@ -2244,7 +2250,7 @@ class Gerber(Geometry):
|
||||||
if 'solid' in geo_el:
|
if 'solid' in geo_el:
|
||||||
new_geo_el['solid'] = buffer_geom(geo_el['solid'])
|
new_geo_el['solid'] = buffer_geom(geo_el['solid'])
|
||||||
if 'follow' in geo_el:
|
if 'follow' in geo_el:
|
||||||
new_geo_el['follow'] = buffer_geom(geo_el['follow'])
|
new_geo_el['follow'] = geo_el['follow']
|
||||||
if 'clear' in geo_el:
|
if 'clear' in geo_el:
|
||||||
new_geo_el['clear'] = buffer_geom(geo_el['clear'])
|
new_geo_el['clear'] = buffer_geom(geo_el['clear'])
|
||||||
new_geometry.append(new_geo_el)
|
new_geometry.append(new_geo_el)
|
||||||
|
@ -2269,6 +2275,74 @@ class Gerber(Geometry):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug('camlib.Gerber.buffer() Exception --> %s' % str(e))
|
log.debug('camlib.Gerber.buffer() Exception --> %s' % str(e))
|
||||||
return 'fail'
|
return 'fail'
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
for apid in self.apertures:
|
||||||
|
try:
|
||||||
|
if str(self.apertures[apid]['type']) == 'R' or str(self.apertures[apid]['type']) == 'O':
|
||||||
|
self.apertures[apid]['width'] *= distance
|
||||||
|
self.apertures[apid]['height'] *= distance
|
||||||
|
elif str(self.apertures[apid]['type']) == 'P':
|
||||||
|
self.apertures[apid]['diam'] *= distance
|
||||||
|
self.apertures[apid]['nVertices'] *= distance
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
if self.apertures[apid]['size'] is not None:
|
||||||
|
self.apertures[apid]['size'] = float(self.apertures[apid]['size']) * distance
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
new_geometry = list()
|
||||||
|
if 'geometry' in self.apertures[apid]:
|
||||||
|
for geo_el in self.apertures[apid]['geometry']:
|
||||||
|
new_geo_el = dict()
|
||||||
|
if 'follow' in geo_el:
|
||||||
|
new_geo_el['follow'] = geo_el['follow']
|
||||||
|
size = float(self.apertures[apid]['size'])
|
||||||
|
if isinstance(new_geo_el['follow'], Point):
|
||||||
|
if str(self.apertures[apid]['type']) == 'C':
|
||||||
|
new_geo_el['solid'] = geo_el['follow'].buffer(
|
||||||
|
size / 1.9999,
|
||||||
|
resolution=int(self.steps_per_circle)
|
||||||
|
)
|
||||||
|
elif str(self.apertures[apid]['type']) == 'R':
|
||||||
|
width = self.apertures[apid]['width']
|
||||||
|
height = self.apertures[apid]['height']
|
||||||
|
minx = new_geo_el['follow'].x - width / 2
|
||||||
|
maxx = new_geo_el['follow'].x + width / 2
|
||||||
|
miny = new_geo_el['follow'].y - height / 2
|
||||||
|
maxy = new_geo_el['follow'].y + height / 2
|
||||||
|
|
||||||
|
geo_p = shply_box(minx, miny, maxx, maxy)
|
||||||
|
new_geo_el['solid'] = geo_p
|
||||||
|
else:
|
||||||
|
log.debug("flatcamParsers.ParseGerber.Gerber.buffer() --> "
|
||||||
|
"ap type not supported")
|
||||||
|
else:
|
||||||
|
new_geo_el['solid'] = geo_el['follow'].buffer(
|
||||||
|
size/1.9999,
|
||||||
|
resolution=int(self.steps_per_circle)
|
||||||
|
)
|
||||||
|
if 'clear' in geo_el:
|
||||||
|
new_geo_el['clear'] = geo_el['clear']
|
||||||
|
new_geometry.append(new_geo_el)
|
||||||
|
|
||||||
|
self.apertures[apid]['geometry'] = deepcopy(new_geometry)
|
||||||
|
except Exception as e:
|
||||||
|
log.debug('camlib.Gerber.buffer() Exception --> %s' % str(e))
|
||||||
|
return 'fail'
|
||||||
|
|
||||||
|
# make the new solid_geometry
|
||||||
|
new_solid_geo = list()
|
||||||
|
for apid in self.apertures:
|
||||||
|
if 'geometry' in self.apertures[apid]:
|
||||||
|
new_solid_geo += [geo_el['solid'] for geo_el in self.apertures[apid]['geometry']]
|
||||||
|
|
||||||
|
self.solid_geometry = MultiPolygon(new_solid_geo)
|
||||||
|
self.solid_geometry = self.solid_geometry.buffer(0.000001)
|
||||||
|
self.solid_geometry = self.solid_geometry.buffer(-0.000001)
|
||||||
|
|
||||||
self.app.inform.emit('[success] %s' % _("Gerber Buffer done."))
|
self.app.inform.emit('[success] %s' % _("Gerber Buffer done."))
|
||||||
self.app.proc_container.new_text = ''
|
self.app.proc_container.new_text = ''
|
||||||
|
|
|
@ -634,11 +634,6 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
def set_tool_ui(self):
|
def set_tool_ui(self):
|
||||||
self.units = self.app.defaults['units'].upper()
|
self.units = self.app.defaults['units'].upper()
|
||||||
|
|
||||||
if self.units == "IN":
|
|
||||||
self.decimals = 4
|
|
||||||
else:
|
|
||||||
self.decimals = 2
|
|
||||||
|
|
||||||
self.tools_frame.show()
|
self.tools_frame.show()
|
||||||
|
|
||||||
self.ncc_order_radio.set_value(self.app.defaults["tools_nccorder"])
|
self.ncc_order_radio.set_value(self.app.defaults["tools_nccorder"])
|
||||||
|
@ -701,10 +696,12 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
})
|
})
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
dias = [float(self.app.defaults["tools_ncctools"])]
|
||||||
|
except (ValueError, TypeError):
|
||||||
dias = [float(eval(dia)) for dia in self.app.defaults["tools_ncctools"].split(",") if dia != '']
|
dias = [float(eval(dia)) for dia in self.app.defaults["tools_ncctools"].split(",") if dia != '']
|
||||||
except Exception as e:
|
|
||||||
log.error("At least one tool diameter needed. "
|
if not dias:
|
||||||
"Verify in Edit -> Preferences -> TOOLS -> NCC Tools. %s" % str(e))
|
log.error("At least one tool diameter needed. Verify in Edit -> Preferences -> TOOLS -> NCC Tools.")
|
||||||
return
|
return
|
||||||
|
|
||||||
self.tooluid = 0
|
self.tooluid = 0
|
||||||
|
|
|
@ -601,13 +601,6 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
# updated units
|
# updated units
|
||||||
self.units = self.app.defaults['units'].upper()
|
self.units = self.app.defaults['units'].upper()
|
||||||
|
|
||||||
if self.units == "IN":
|
|
||||||
self.decimals = 4
|
|
||||||
self.addtool_entry.set_value(0.039)
|
|
||||||
else:
|
|
||||||
self.decimals = 2
|
|
||||||
self.addtool_entry.set_value(1)
|
|
||||||
|
|
||||||
# set the working variables to a known state
|
# set the working variables to a known state
|
||||||
self.paint_tools.clear()
|
self.paint_tools.clear()
|
||||||
self.tooluid = 0
|
self.tooluid = 0
|
||||||
|
@ -637,7 +630,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
"toolchangexy": self.app.defaults["geometry_toolchangexy"],
|
"toolchangexy": self.app.defaults["geometry_toolchangexy"],
|
||||||
"startz": self.app.defaults["geometry_startz"],
|
"startz": self.app.defaults["geometry_startz"],
|
||||||
|
|
||||||
"tooldia": float(self.app.defaults["tools_painttooldia"]),
|
"tooldia": self.app.defaults["tools_painttooldia"],
|
||||||
"paintmargin": float(self.app.defaults["tools_paintmargin"]),
|
"paintmargin": float(self.app.defaults["tools_paintmargin"]),
|
||||||
"paintmethod": self.app.defaults["tools_paintmethod"],
|
"paintmethod": self.app.defaults["tools_paintmethod"],
|
||||||
"selectmethod": self.app.defaults["tools_selectmethod"],
|
"selectmethod": self.app.defaults["tools_selectmethod"],
|
||||||
|
@ -646,9 +639,23 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
"paintoverlap": self.app.defaults["tools_paintoverlap"]
|
"paintoverlap": self.app.defaults["tools_paintoverlap"]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
try:
|
||||||
|
diameters = [float(self.app.defaults["tools_painttooldia"])]
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
diameters = [eval(x) for x in self.app.defaults["tools_painttooldia"].split(",") if x != '']
|
||||||
|
|
||||||
|
if not diameters:
|
||||||
|
log.error("At least one tool diameter needed. Verify in Edit -> Preferences -> TOOLS -> NCC Tools.")
|
||||||
|
self.build_ui()
|
||||||
|
# if the Paint Method is "Single" disable the tool table context menu
|
||||||
|
if self.default_data["selectmethod"] == "single":
|
||||||
|
self.tools_table.setContextMenuPolicy(Qt.NoContextMenu)
|
||||||
|
return
|
||||||
|
|
||||||
# call on self.on_tool_add() counts as an call to self.build_ui()
|
# call on self.on_tool_add() counts as an call to self.build_ui()
|
||||||
# through this, we add a initial row / tool in the tool_table
|
# through this, we add a initial row / tool in the tool_table
|
||||||
self.on_tool_add(float(self.app.defaults["tools_painttooldia"]), muted=True)
|
for dia in diameters:
|
||||||
|
self.on_tool_add(dia, muted=True)
|
||||||
|
|
||||||
# if the Paint Method is "Single" disable the tool table context menu
|
# if the Paint Method is "Single" disable the tool table context menu
|
||||||
if self.default_data["selectmethod"] == "single":
|
if self.default_data["selectmethod"] == "single":
|
||||||
|
|
|
@ -621,11 +621,6 @@ class SolderPaste(FlatCAMTool):
|
||||||
|
|
||||||
self.units = self.app.defaults['units'].upper()
|
self.units = self.app.defaults['units'].upper()
|
||||||
|
|
||||||
if self.units == "IN":
|
|
||||||
self.decimals = 4
|
|
||||||
else:
|
|
||||||
self.decimals = 2
|
|
||||||
|
|
||||||
for name in list(self.app.preprocessors.keys()):
|
for name in list(self.app.preprocessors.keys()):
|
||||||
# populate only with preprocessor files that start with 'Paste_'
|
# populate only with preprocessor files that start with 'Paste_'
|
||||||
if name.partition('_')[0] != 'Paste':
|
if name.partition('_')[0] != 'Paste':
|
||||||
|
|
|
@ -89,7 +89,10 @@ class ToolTransform(FlatCAMTool):
|
||||||
grid0.addWidget(self.rotate_entry, 1, 1)
|
grid0.addWidget(self.rotate_entry, 1, 1)
|
||||||
grid0.addWidget(self.rotate_button, 1, 2)
|
grid0.addWidget(self.rotate_button, 1, 2)
|
||||||
|
|
||||||
grid0.addWidget(QtWidgets.QLabel(''), 2, 0)
|
separator_line = QtWidgets.QFrame()
|
||||||
|
separator_line.setFrameShape(QtWidgets.QFrame.HLine)
|
||||||
|
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||||
|
grid0.addWidget(separator_line, 2, 0, 1, 3)
|
||||||
|
|
||||||
# ## Skew Title
|
# ## Skew Title
|
||||||
skew_title_label = QtWidgets.QLabel("<font size=3><b>%s</b></font>" % self.skewName)
|
skew_title_label = QtWidgets.QLabel("<font size=3><b>%s</b></font>" % self.skewName)
|
||||||
|
@ -139,7 +142,10 @@ class ToolTransform(FlatCAMTool):
|
||||||
grid0.addWidget(self.skewy_entry, 5, 1)
|
grid0.addWidget(self.skewy_entry, 5, 1)
|
||||||
grid0.addWidget(self.skewy_button, 5, 2)
|
grid0.addWidget(self.skewy_button, 5, 2)
|
||||||
|
|
||||||
grid0.addWidget(QtWidgets.QLabel(''), 6, 0)
|
separator_line = QtWidgets.QFrame()
|
||||||
|
separator_line.setFrameShape(QtWidgets.QFrame.HLine)
|
||||||
|
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||||
|
grid0.addWidget(separator_line, 6, 0, 1, 3)
|
||||||
|
|
||||||
# ## Scale Title
|
# ## Scale Title
|
||||||
scale_title_label = QtWidgets.QLabel("<font size=3><b>%s</b></font>" % self.scaleName)
|
scale_title_label = QtWidgets.QLabel("<font size=3><b>%s</b></font>" % self.scaleName)
|
||||||
|
@ -208,7 +214,11 @@ class ToolTransform(FlatCAMTool):
|
||||||
|
|
||||||
grid0.addWidget(self.scale_link_cb, 10, 0)
|
grid0.addWidget(self.scale_link_cb, 10, 0)
|
||||||
grid0.addWidget(self.scale_zero_ref_cb, 10, 1)
|
grid0.addWidget(self.scale_zero_ref_cb, 10, 1)
|
||||||
grid0.addWidget(QtWidgets.QLabel(''), 11, 0)
|
|
||||||
|
separator_line = QtWidgets.QFrame()
|
||||||
|
separator_line.setFrameShape(QtWidgets.QFrame.HLine)
|
||||||
|
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||||
|
grid0.addWidget(separator_line, 11, 0, 1, 3)
|
||||||
|
|
||||||
# ## Offset Title
|
# ## Offset Title
|
||||||
offset_title_label = QtWidgets.QLabel("<font size=3><b>%s</b></font>" % self.offsetName)
|
offset_title_label = QtWidgets.QLabel("<font size=3><b>%s</b></font>" % self.offsetName)
|
||||||
|
@ -256,7 +266,10 @@ class ToolTransform(FlatCAMTool):
|
||||||
grid0.addWidget(self.offy_entry, 14, 1)
|
grid0.addWidget(self.offy_entry, 14, 1)
|
||||||
grid0.addWidget(self.offy_button, 14, 2)
|
grid0.addWidget(self.offy_button, 14, 2)
|
||||||
|
|
||||||
grid0.addWidget(QtWidgets.QLabel(''), 15, 0, 1, 3)
|
separator_line = QtWidgets.QFrame()
|
||||||
|
separator_line.setFrameShape(QtWidgets.QFrame.HLine)
|
||||||
|
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||||
|
grid0.addWidget(separator_line, 15, 0, 1, 3)
|
||||||
|
|
||||||
# ## Flip Title
|
# ## Flip Title
|
||||||
flip_title_label = QtWidgets.QLabel("<font size=3><b>%s</b></font>" % self.flipName)
|
flip_title_label = QtWidgets.QLabel("<font size=3><b>%s</b></font>" % self.flipName)
|
||||||
|
@ -323,7 +336,10 @@ class ToolTransform(FlatCAMTool):
|
||||||
|
|
||||||
grid0.addWidget(self.flip_ref_button, 20, 0, 1, 3)
|
grid0.addWidget(self.flip_ref_button, 20, 0, 1, 3)
|
||||||
|
|
||||||
grid0.addWidget(QtWidgets.QLabel(''), 21, 0, 1, 3)
|
separator_line = QtWidgets.QFrame()
|
||||||
|
separator_line.setFrameShape(QtWidgets.QFrame.HLine)
|
||||||
|
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||||
|
grid0.addWidget(separator_line, 21, 0, 1, 3)
|
||||||
|
|
||||||
# ## Buffer Title
|
# ## Buffer Title
|
||||||
buffer_title_label = QtWidgets.QLabel("<font size=3><b>%s</b></font>" % self.bufferName)
|
buffer_title_label = QtWidgets.QLabel("<font size=3><b>%s</b></font>" % self.bufferName)
|
||||||
|
@ -343,13 +359,11 @@ class ToolTransform(FlatCAMTool):
|
||||||
self.buffer_entry.setWrapping(True)
|
self.buffer_entry.setWrapping(True)
|
||||||
self.buffer_entry.set_range(-9999.9999, 9999.9999)
|
self.buffer_entry.set_range(-9999.9999, 9999.9999)
|
||||||
|
|
||||||
# self.rotate_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
|
||||||
|
|
||||||
self.buffer_button = FCButton()
|
self.buffer_button = FCButton()
|
||||||
self.buffer_button.set_value(_("Buffer"))
|
self.buffer_button.set_value(_("Buffer D"))
|
||||||
self.buffer_button.setToolTip(
|
self.buffer_button.setToolTip(
|
||||||
_("Create the buffer effect on each geometry,\n"
|
_("Create the buffer effect on each geometry,\n"
|
||||||
"element from the selected object.")
|
"element from the selected object, using the distance.")
|
||||||
)
|
)
|
||||||
self.buffer_button.setMinimumWidth(90)
|
self.buffer_button.setMinimumWidth(90)
|
||||||
|
|
||||||
|
@ -357,8 +371,33 @@ class ToolTransform(FlatCAMTool):
|
||||||
grid0.addWidget(self.buffer_entry, 23, 1)
|
grid0.addWidget(self.buffer_entry, 23, 1)
|
||||||
grid0.addWidget(self.buffer_button, 23, 2)
|
grid0.addWidget(self.buffer_button, 23, 2)
|
||||||
|
|
||||||
self.buffer_rounded_cb = FCCheckBox()
|
self.buffer_factor_label = QtWidgets.QLabel('%s:' % _("Factor"))
|
||||||
self.buffer_rounded_cb.setText('%s' % _("Rounded"))
|
self.buffer_factor_label.setToolTip(
|
||||||
|
_("A positive value will create the effect of dilation,\n"
|
||||||
|
"while a negative value will create the effect of erosion.\n"
|
||||||
|
"Each geometry element of the object will be increased\n"
|
||||||
|
"or decreased by the 'factor'.")
|
||||||
|
)
|
||||||
|
|
||||||
|
self.buffer_factor_entry = FCDoubleSpinner(suffix='%')
|
||||||
|
self.buffer_factor_entry.set_range(-100.0000, 1000.0000)
|
||||||
|
self.buffer_factor_entry.set_precision(self.decimals)
|
||||||
|
self.buffer_factor_entry.setWrapping(True)
|
||||||
|
self.buffer_factor_entry.setSingleStep(1)
|
||||||
|
|
||||||
|
self.buffer_factor_button = FCButton()
|
||||||
|
self.buffer_factor_button.set_value(_("Buffer F"))
|
||||||
|
self.buffer_factor_button.setToolTip(
|
||||||
|
_("Create the buffer effect on each geometry,\n"
|
||||||
|
"element from the selected object, using the factor.")
|
||||||
|
)
|
||||||
|
self.buffer_factor_button.setMinimumWidth(90)
|
||||||
|
|
||||||
|
grid0.addWidget(self.buffer_factor_label, 24, 0)
|
||||||
|
grid0.addWidget(self.buffer_factor_entry, 24, 1)
|
||||||
|
grid0.addWidget(self.buffer_factor_button, 24, 2)
|
||||||
|
|
||||||
|
self.buffer_rounded_cb = FCCheckBox('%s' % _("Rounded"))
|
||||||
self.buffer_rounded_cb.setToolTip(
|
self.buffer_rounded_cb.setToolTip(
|
||||||
_("If checked then the buffer will surround the buffered shape,\n"
|
_("If checked then the buffer will surround the buffered shape,\n"
|
||||||
"every corner will be rounded.\n"
|
"every corner will be rounded.\n"
|
||||||
|
@ -366,9 +405,9 @@ class ToolTransform(FlatCAMTool):
|
||||||
"of the buffered shape.")
|
"of the buffered shape.")
|
||||||
)
|
)
|
||||||
|
|
||||||
grid0.addWidget(self.buffer_rounded_cb, 24, 0, 1, 3)
|
grid0.addWidget(self.buffer_rounded_cb, 25, 0, 1, 3)
|
||||||
|
|
||||||
grid0.addWidget(QtWidgets.QLabel(''), 25, 0, 1, 3)
|
grid0.addWidget(QtWidgets.QLabel(''), 26, 0, 1, 3)
|
||||||
|
|
||||||
self.transform_lay.addStretch()
|
self.transform_lay.addStretch()
|
||||||
|
|
||||||
|
@ -383,7 +422,8 @@ class ToolTransform(FlatCAMTool):
|
||||||
self.flipx_button.clicked.connect(self.on_flipx)
|
self.flipx_button.clicked.connect(self.on_flipx)
|
||||||
self.flipy_button.clicked.connect(self.on_flipy)
|
self.flipy_button.clicked.connect(self.on_flipy)
|
||||||
self.flip_ref_button.clicked.connect(self.on_flip_add_coords)
|
self.flip_ref_button.clicked.connect(self.on_flip_add_coords)
|
||||||
self.buffer_button.clicked.connect(self.on_buffer)
|
self.buffer_button.clicked.connect(self.on_buffer_by_distance)
|
||||||
|
self.buffer_factor_button.clicked.connect(self.on_buffer_by_factor)
|
||||||
|
|
||||||
# self.rotate_entry.returnPressed.connect(self.on_rotate)
|
# self.rotate_entry.returnPressed.connect(self.on_rotate)
|
||||||
# self.skewx_entry.returnPressed.connect(self.on_skewx)
|
# self.skewx_entry.returnPressed.connect(self.on_skewx)
|
||||||
|
@ -392,7 +432,7 @@ class ToolTransform(FlatCAMTool):
|
||||||
# self.scaley_entry.returnPressed.connect(self.on_scaley)
|
# self.scaley_entry.returnPressed.connect(self.on_scaley)
|
||||||
# self.offx_entry.returnPressed.connect(self.on_offx)
|
# self.offx_entry.returnPressed.connect(self.on_offx)
|
||||||
# self.offy_entry.returnPressed.connect(self.on_offy)
|
# self.offy_entry.returnPressed.connect(self.on_offy)
|
||||||
# self.buffer_entry.returnPressed.connect(self.on_buffer)
|
# self.buffer_entry.returnPressed.connect(self.on_buffer_by_distance)
|
||||||
|
|
||||||
def run(self, toggle=True):
|
def run(self, toggle=True):
|
||||||
self.app.report_usage("ToolTransform()")
|
self.app.report_usage("ToolTransform()")
|
||||||
|
@ -486,6 +526,11 @@ class ToolTransform(FlatCAMTool):
|
||||||
else:
|
else:
|
||||||
self.buffer_entry.set_value(0.0)
|
self.buffer_entry.set_value(0.0)
|
||||||
|
|
||||||
|
if self.app.defaults["tools_transform_buffer_factor"]:
|
||||||
|
self.buffer_factor_entry.set_value(self.app.defaults["tools_transform_buffer_factor"])
|
||||||
|
else:
|
||||||
|
self.buffer_factor_entry.set_value(100.0)
|
||||||
|
|
||||||
if self.app.defaults["tools_transform_buffer_corner"]:
|
if self.app.defaults["tools_transform_buffer_corner"]:
|
||||||
self.buffer_rounded_cb.set_value(self.app.defaults["tools_transform_buffer_corner"])
|
self.buffer_rounded_cb.set_value(self.app.defaults["tools_transform_buffer_corner"])
|
||||||
else:
|
else:
|
||||||
|
@ -589,13 +634,23 @@ class ToolTransform(FlatCAMTool):
|
||||||
self.app.worker_task.emit({'fcn': self.on_offset, 'params': [axis, value]})
|
self.app.worker_task.emit({'fcn': self.on_offset, 'params': [axis, value]})
|
||||||
return
|
return
|
||||||
|
|
||||||
def on_buffer(self):
|
def on_buffer_by_distance(self):
|
||||||
value = self.buffer_entry.get_value()
|
value = self.buffer_entry.get_value()
|
||||||
join = 1 if self.buffer_rounded_cb.get_value() else 2
|
join = 1 if self.buffer_rounded_cb.get_value() else 2
|
||||||
|
|
||||||
self.app.worker_task.emit({'fcn': self.on_buffer_action, 'params': [value, join]})
|
self.app.worker_task.emit({'fcn': self.on_buffer_action, 'params': [value, join]})
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def on_buffer_by_factor(self):
|
||||||
|
value = self.buffer_factor_entry.get_value() / 100.0
|
||||||
|
join = 1 if self.buffer_rounded_cb.get_value() else 2
|
||||||
|
|
||||||
|
# tell the buffer method to use the factor
|
||||||
|
factor = True
|
||||||
|
|
||||||
|
self.app.worker_task.emit({'fcn': self.on_buffer_action, 'params': [value, join, factor]})
|
||||||
|
return
|
||||||
|
|
||||||
def on_rotate_action(self, num):
|
def on_rotate_action(self, num):
|
||||||
obj_list = self.app.collection.get_selected()
|
obj_list = self.app.collection.get_selected()
|
||||||
xminlist = []
|
xminlist = []
|
||||||
|
@ -604,8 +659,7 @@ class ToolTransform(FlatCAMTool):
|
||||||
ymaxlist = []
|
ymaxlist = []
|
||||||
|
|
||||||
if not obj_list:
|
if not obj_list:
|
||||||
self.app.inform.emit('[WARNING_NOTCL] %s' %
|
self.app.inform.emit('[WARNING_NOTCL] %s' % _("No object selected. Please Select an object to rotate!"))
|
||||||
_("No object selected. Please Select an object to rotate!"))
|
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
with self.app.proc_container.new(_("Appying Rotate")):
|
with self.app.proc_container.new(_("Appying Rotate")):
|
||||||
|
@ -874,7 +928,7 @@ class ToolTransform(FlatCAMTool):
|
||||||
(_("Due of"), str(e), _("action was not executed.")))
|
(_("Due of"), str(e), _("action was not executed.")))
|
||||||
return
|
return
|
||||||
|
|
||||||
def on_buffer_action(self, value, join):
|
def on_buffer_action(self, value, join, factor=None):
|
||||||
obj_list = self.app.collection.get_selected()
|
obj_list = self.app.collection.get_selected()
|
||||||
|
|
||||||
if not obj_list:
|
if not obj_list:
|
||||||
|
@ -887,17 +941,17 @@ class ToolTransform(FlatCAMTool):
|
||||||
if isinstance(sel_obj, FlatCAMCNCjob):
|
if isinstance(sel_obj, FlatCAMCNCjob):
|
||||||
self.app.inform.emit(_("CNCJob objects can't be buffered."))
|
self.app.inform.emit(_("CNCJob objects can't be buffered."))
|
||||||
elif sel_obj.kind.lower() == 'gerber':
|
elif sel_obj.kind.lower() == 'gerber':
|
||||||
sel_obj.buffer(value, join)
|
sel_obj.buffer(value, join, factor)
|
||||||
sel_obj.source_file = self.app.export_gerber(obj_name=sel_obj.options['name'],
|
sel_obj.source_file = self.app.export_gerber(obj_name=sel_obj.options['name'],
|
||||||
filename=None, local_use=sel_obj,
|
filename=None, local_use=sel_obj,
|
||||||
use_thread=False)
|
use_thread=False)
|
||||||
elif sel_obj.kind.lower() == 'excellon':
|
elif sel_obj.kind.lower() == 'excellon':
|
||||||
sel_obj.buffer(value, join)
|
sel_obj.buffer(value, join, factor)
|
||||||
sel_obj.source_file = self.app.export_excellon(obj_name=sel_obj.options['name'],
|
sel_obj.source_file = self.app.export_excellon(obj_name=sel_obj.options['name'],
|
||||||
filename=None, local_use=sel_obj,
|
filename=None, local_use=sel_obj,
|
||||||
use_thread=False)
|
use_thread=False)
|
||||||
elif sel_obj.kind.lower() == 'geometry':
|
elif sel_obj.kind.lower() == 'geometry':
|
||||||
sel_obj.buffer(value, join)
|
sel_obj.buffer(value, join, factor)
|
||||||
|
|
||||||
self.app.object_changed.emit(sel_obj)
|
self.app.object_changed.emit(sel_obj)
|
||||||
sel_obj.plot()
|
sel_obj.plot()
|
||||||
|
|
Loading…
Reference in New Issue