- stored solid_geometry of Excellon object in the self.tools dictionary
- finished the solid_geometry restore after edit in Excellon Editor - finished plotting selection for each tool in the Excellon Tool Table - fixed the camlib.Excellon.bounds() function for the new type of Excellon geometry therefore fixed the canvas selection, too
This commit is contained in:
parent
02793f7ae2
commit
c94679919d
|
@ -4306,6 +4306,9 @@ class FlatCAMExcEditor(QtCore.QObject):
|
||||||
spec = {"C": float(tool_dia[0])}
|
spec = {"C": float(tool_dia[0])}
|
||||||
self.new_tools[name] = spec
|
self.new_tools[name] = spec
|
||||||
|
|
||||||
|
# add in self.tools the 'solid_geometry' key, the value (a list) is populated bellow
|
||||||
|
self.new_tools[name]['solid_geometry'] = []
|
||||||
|
|
||||||
# create the self.drills for the new Excellon object (the one with edited content)
|
# create the self.drills for the new Excellon object (the one with edited content)
|
||||||
for point in tool_dia[1]:
|
for point in tool_dia[1]:
|
||||||
self.new_drills.append(
|
self.new_drills.append(
|
||||||
|
@ -4314,6 +4317,9 @@ class FlatCAMExcEditor(QtCore.QObject):
|
||||||
'tool': str(current_tool)
|
'tool': str(current_tool)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
# repopulate the 'solid_geometry' for each tool
|
||||||
|
poly = Point(point).buffer(float(tool_dia[0]) / 2.0, int(int(exc_obj.geo_steps_per_circle) / 4))
|
||||||
|
self.new_tools[name]['solid_geometry'].append(poly)
|
||||||
|
|
||||||
if self.is_modified is True:
|
if self.is_modified is True:
|
||||||
if "_edit" in self.edited_obj_name:
|
if "_edit" in self.edited_obj_name:
|
||||||
|
|
267
FlatCAMObj.py
267
FlatCAMObj.py
|
@ -1134,10 +1134,16 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
|
||||||
t_offset = self.app.defaults['excellon_offset']
|
t_offset = self.app.defaults['excellon_offset']
|
||||||
tool_offset_item = QtWidgets.QTableWidgetItem('%s' % str(t_offset))
|
tool_offset_item = QtWidgets.QTableWidgetItem('%s' % str(t_offset))
|
||||||
|
|
||||||
|
plot_item = FCCheckBox()
|
||||||
|
plot_item.setLayoutDirection(QtCore.Qt.RightToLeft)
|
||||||
|
if self.ui.plot_cb.isChecked():
|
||||||
|
plot_item.setChecked(True)
|
||||||
|
|
||||||
self.ui.tools_table.setItem(self.tool_row, 1, dia) # Diameter
|
self.ui.tools_table.setItem(self.tool_row, 1, dia) # Diameter
|
||||||
self.ui.tools_table.setItem(self.tool_row, 2, drill_count) # Number of drills per tool
|
self.ui.tools_table.setItem(self.tool_row, 2, drill_count) # Number of drills per tool
|
||||||
self.ui.tools_table.setItem(self.tool_row, 3, slot_count) # Number of drills per tool
|
self.ui.tools_table.setItem(self.tool_row, 3, slot_count) # Number of drills per tool
|
||||||
self.ui.tools_table.setItem(self.tool_row, 4, tool_offset_item) # Tool offset
|
self.ui.tools_table.setItem(self.tool_row, 4, tool_offset_item) # Tool offset
|
||||||
|
self.ui.tools_table.setCellWidget(self.tool_row, 5, plot_item)
|
||||||
|
|
||||||
self.tool_row += 1
|
self.tool_row += 1
|
||||||
|
|
||||||
|
@ -1201,12 +1207,28 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
|
||||||
self.ui.tools_table.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
self.ui.tools_table.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
||||||
|
|
||||||
horizontal_header = self.ui.tools_table.horizontalHeader()
|
horizontal_header = self.ui.tools_table.horizontalHeader()
|
||||||
horizontal_header.setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeToContents)
|
horizontal_header.setMinimumSectionSize(10)
|
||||||
|
horizontal_header.setDefaultSectionSize(70)
|
||||||
|
horizontal_header.setSectionResizeMode(0, QtWidgets.QHeaderView.Fixed)
|
||||||
|
horizontal_header.resizeSection(0, 20)
|
||||||
horizontal_header.setSectionResizeMode(1, QtWidgets.QHeaderView.Stretch)
|
horizontal_header.setSectionResizeMode(1, QtWidgets.QHeaderView.Stretch)
|
||||||
horizontal_header.setSectionResizeMode(2, QtWidgets.QHeaderView.ResizeToContents)
|
horizontal_header.setSectionResizeMode(2, QtWidgets.QHeaderView.ResizeToContents)
|
||||||
horizontal_header.setSectionResizeMode(3, QtWidgets.QHeaderView.ResizeToContents)
|
horizontal_header.setSectionResizeMode(3, QtWidgets.QHeaderView.ResizeToContents)
|
||||||
|
horizontal_header.setSectionResizeMode(4, QtWidgets.QHeaderView.ResizeToContents)
|
||||||
|
horizontal_header.setSectionResizeMode(5, QtWidgets.QHeaderView.Fixed)
|
||||||
|
horizontal_header.resizeSection(5, 17)
|
||||||
|
self.ui.tools_table.setColumnWidth(5, 17)
|
||||||
|
|
||||||
# horizontal_header.setStretchLastSection(True)
|
# horizontal_header.setStretchLastSection(True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# horizontal_header.setColumnWidth(2, QtWidgets.QHeaderView.ResizeToContents)
|
||||||
|
|
||||||
|
# horizontal_header.setStretchLastSection(True)
|
||||||
|
self.ui.tools_table.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
||||||
|
|
||||||
self.ui.tools_table.setSortingEnabled(False)
|
self.ui.tools_table.setSortingEnabled(False)
|
||||||
|
|
||||||
self.ui.tools_table.setMinimumHeight(self.ui.tools_table.getHeight())
|
self.ui.tools_table.setMinimumHeight(self.ui.tools_table.getHeight())
|
||||||
|
@ -1233,6 +1255,8 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
|
||||||
# we reactivate the signals after the after the tool adding as we don't need to see the tool been populated
|
# we reactivate the signals after the after the tool adding as we don't need to see the tool been populated
|
||||||
self.ui.tools_table.itemChanged.connect(self.on_tool_offset_edit)
|
self.ui.tools_table.itemChanged.connect(self.on_tool_offset_edit)
|
||||||
|
|
||||||
|
self.ui_connect()
|
||||||
|
|
||||||
def set_ui(self, ui):
|
def set_ui(self, ui):
|
||||||
"""
|
"""
|
||||||
Configures the user interface for this object.
|
Configures the user interface for this object.
|
||||||
|
@ -1297,6 +1321,24 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
|
||||||
|
|
||||||
self.ui.pp_excellon_name_cb.activated.connect(self.on_pp_changed)
|
self.ui.pp_excellon_name_cb.activated.connect(self.on_pp_changed)
|
||||||
|
|
||||||
|
def ui_connect(self):
|
||||||
|
|
||||||
|
for row in range(self.ui.tools_table.rowCount() - 2):
|
||||||
|
self.ui.tools_table.cellWidget(row, 5).clicked.connect(self.on_plot_cb_click_table)
|
||||||
|
self.ui.plot_cb.stateChanged.connect(self.on_plot_cb_click)
|
||||||
|
|
||||||
|
def ui_disconnect(self):
|
||||||
|
for row in range(self.ui.tools_table.rowCount()):
|
||||||
|
try:
|
||||||
|
self.ui.tools_table.cellWidget(row, 5).clicked.disconnect()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.ui.plot_cb.stateChanged.disconnect()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
def on_tool_offset_edit(self):
|
def on_tool_offset_edit(self):
|
||||||
# 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.tools_table.itemChanged.disconnect()
|
self.ui.tools_table.itemChanged.disconnect()
|
||||||
|
@ -1351,8 +1393,10 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
|
||||||
"""
|
"""
|
||||||
table_tools_items = []
|
table_tools_items = []
|
||||||
for x in self.ui.tools_table.selectedItems():
|
for x in self.ui.tools_table.selectedItems():
|
||||||
|
# from the columnCount we subtract a value of 1 which represent the last column (plot column)
|
||||||
|
# which does not have text
|
||||||
table_tools_items.append([self.ui.tools_table.item(x.row(), column).text()
|
table_tools_items.append([self.ui.tools_table.item(x.row(), column).text()
|
||||||
for column in range(0, self.ui.tools_table.columnCount())])
|
for column in range(0, self.ui.tools_table.columnCount() - 1)])
|
||||||
for item in table_tools_items:
|
for item in table_tools_items:
|
||||||
item[0] = str(item[0])
|
item[0] = str(item[0])
|
||||||
return table_tools_items
|
return table_tools_items
|
||||||
|
@ -1839,17 +1883,6 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
|
||||||
# self.app.worker.add_task(job_thread, [self.app])
|
# self.app.worker.add_task(job_thread, [self.app])
|
||||||
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
|
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
|
||||||
|
|
||||||
def on_plot_cb_click(self, *args):
|
|
||||||
if self.muted_ui:
|
|
||||||
return
|
|
||||||
self.read_form_item('plot')
|
|
||||||
|
|
||||||
def on_solid_cb_click(self, *args):
|
|
||||||
if self.muted_ui:
|
|
||||||
return
|
|
||||||
self.read_form_item('solid')
|
|
||||||
self.plot()
|
|
||||||
|
|
||||||
def convert_units(self, units):
|
def convert_units(self, units):
|
||||||
factor = Excellon.convert_units(self, units)
|
factor = Excellon.convert_units(self, units)
|
||||||
|
|
||||||
|
@ -1875,6 +1908,89 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
|
||||||
self.options['startz'] = float(self.options['startz']) * factor
|
self.options['startz'] = float(self.options['startz']) * factor
|
||||||
self.options['endz'] = float(self.options['endz']) * factor
|
self.options['endz'] = float(self.options['endz']) * factor
|
||||||
|
|
||||||
|
def on_solid_cb_click(self, *args):
|
||||||
|
if self.muted_ui:
|
||||||
|
return
|
||||||
|
self.read_form_item('solid')
|
||||||
|
self.plot()
|
||||||
|
|
||||||
|
def on_plot_cb_click(self, *args):
|
||||||
|
if self.muted_ui:
|
||||||
|
return
|
||||||
|
self.plot()
|
||||||
|
self.read_form_item('plot')
|
||||||
|
|
||||||
|
self.ui_disconnect()
|
||||||
|
cb_flag = self.ui.plot_cb.isChecked()
|
||||||
|
for row in range(self.ui.tools_table.rowCount() - 2):
|
||||||
|
table_cb = self.ui.tools_table.cellWidget(row, 5)
|
||||||
|
if cb_flag:
|
||||||
|
table_cb.setChecked(True)
|
||||||
|
else:
|
||||||
|
table_cb.setChecked(False)
|
||||||
|
|
||||||
|
self.ui_connect()
|
||||||
|
|
||||||
|
def on_plot_cb_click_table(self):
|
||||||
|
# self.ui.cnc_tools_table.cellWidget(row, 2).widget().setCheckState(QtCore.Qt.Unchecked)
|
||||||
|
self.ui_disconnect()
|
||||||
|
# cw = self.sender()
|
||||||
|
# cw_index = self.ui.tools_table.indexAt(cw.pos())
|
||||||
|
# cw_row = cw_index.row()
|
||||||
|
check_row = 0
|
||||||
|
|
||||||
|
self.shapes.clear(update=True)
|
||||||
|
for tool_key in self.tools:
|
||||||
|
solid_geometry = self.tools[tool_key]['solid_geometry']
|
||||||
|
|
||||||
|
# find the geo_tool_table row associated with the tool_key
|
||||||
|
for row in range(self.ui.tools_table.rowCount()):
|
||||||
|
tool_item = int(self.ui.tools_table.item(row, 0).text())
|
||||||
|
if tool_item == int(tool_key):
|
||||||
|
check_row = row
|
||||||
|
break
|
||||||
|
if self.ui.tools_table.cellWidget(check_row, 5).isChecked():
|
||||||
|
self.options['plot'] = True
|
||||||
|
# self.plot_element(element=solid_geometry, visible=True)
|
||||||
|
# Plot excellon (All polygons?)
|
||||||
|
if self.options["solid"]:
|
||||||
|
for geo in solid_geometry:
|
||||||
|
self.add_shape(shape=geo, color='#750000BF', face_color='#C40000BF',
|
||||||
|
visible=self.options['plot'],
|
||||||
|
layer=2)
|
||||||
|
else:
|
||||||
|
for geo in solid_geometry:
|
||||||
|
self.add_shape(shape=geo.exterior, color='red', visible=self.options['plot'])
|
||||||
|
for ints in geo.interiors:
|
||||||
|
self.add_shape(shape=ints, color='green', visible=self.options['plot'])
|
||||||
|
self.shapes.redraw()
|
||||||
|
|
||||||
|
# make sure that the general plot is disabled if one of the row plot's are disabled and
|
||||||
|
# if all the row plot's are enabled also enable the general plot checkbox
|
||||||
|
cb_cnt = 0
|
||||||
|
total_row = self.ui.tools_table.rowCount()
|
||||||
|
for row in range(total_row - 2):
|
||||||
|
if self.ui.tools_table.cellWidget(row, 5).isChecked():
|
||||||
|
cb_cnt += 1
|
||||||
|
else:
|
||||||
|
cb_cnt -= 1
|
||||||
|
if cb_cnt < total_row - 2:
|
||||||
|
self.ui.plot_cb.setChecked(False)
|
||||||
|
else:
|
||||||
|
self.ui.plot_cb.setChecked(True)
|
||||||
|
self.ui_connect()
|
||||||
|
|
||||||
|
# def plot_element(self, element, color='red', visible=None, layer=None):
|
||||||
|
#
|
||||||
|
# visible = visible if visible else self.options['plot']
|
||||||
|
#
|
||||||
|
# try:
|
||||||
|
# for sub_el in element:
|
||||||
|
# self.plot_element(sub_el)
|
||||||
|
#
|
||||||
|
# except TypeError: # Element is not iterable...
|
||||||
|
# self.add_shape(shape=element, color=color, visible=visible, layer=0)
|
||||||
|
|
||||||
def plot(self):
|
def plot(self):
|
||||||
|
|
||||||
# Does all the required setup and returns False
|
# Does all the required setup and returns False
|
||||||
|
@ -3971,62 +4087,65 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
||||||
param_list = ['cutz', 'depthperpass', 'travelz', 'feedrate', 'feedrate_z', 'feedrate_rapid',
|
param_list = ['cutz', 'depthperpass', 'travelz', 'feedrate', 'feedrate_z', 'feedrate_rapid',
|
||||||
'endz', 'toolchangez']
|
'endz', 'toolchangez']
|
||||||
|
|
||||||
temp_tools_dict = {}
|
if isinstance(self, FlatCAMGeometry):
|
||||||
tool_dia_copy = {}
|
temp_tools_dict = {}
|
||||||
data_copy = {}
|
tool_dia_copy = {}
|
||||||
for tooluid_key, tooluid_value in self.tools.items():
|
data_copy = {}
|
||||||
for dia_key, dia_value in tooluid_value.items():
|
for tooluid_key, tooluid_value in self.tools.items():
|
||||||
if dia_key == 'tooldia':
|
for dia_key, dia_value in tooluid_value.items():
|
||||||
dia_value *= factor
|
if dia_key == 'tooldia':
|
||||||
dia_value = float('%.4f' % dia_value)
|
dia_value *= factor
|
||||||
tool_dia_copy[dia_key] = dia_value
|
dia_value = float('%.4f' % dia_value)
|
||||||
if dia_key == 'offset':
|
tool_dia_copy[dia_key] = dia_value
|
||||||
tool_dia_copy[dia_key] = dia_value
|
if dia_key == 'offset':
|
||||||
if dia_key == 'offset_value':
|
tool_dia_copy[dia_key] = dia_value
|
||||||
dia_value *= factor
|
if dia_key == 'offset_value':
|
||||||
tool_dia_copy[dia_key] = dia_value
|
dia_value *= factor
|
||||||
|
tool_dia_copy[dia_key] = dia_value
|
||||||
|
|
||||||
# convert the value in the Custom Tool Offset entry in UI
|
# convert the value in the Custom Tool Offset entry in UI
|
||||||
try:
|
custom_offset = None
|
||||||
custom_offset = float(self.ui.tool_offset_entry.get_value())
|
|
||||||
except ValueError:
|
|
||||||
# try to convert comma to decimal point. if it's still not working error message and return
|
|
||||||
try:
|
try:
|
||||||
custom_offset = float(self.ui.tool_offset_entry.get_value().replace(',', '.')
|
custom_offset = float(self.ui.tool_offset_entry.get_value())
|
||||||
)
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
# try to convert comma to decimal point. if it's still not working error message and return
|
||||||
"use a number.")
|
try:
|
||||||
return
|
custom_offset = float(self.ui.tool_offset_entry.get_value().replace(',', '.')
|
||||||
|
)
|
||||||
|
except ValueError:
|
||||||
|
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
|
"use a number.")
|
||||||
|
return
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
|
||||||
if custom_offset:
|
if custom_offset:
|
||||||
custom_offset *= factor
|
custom_offset *= factor
|
||||||
self.ui.tool_offset_entry.set_value(custom_offset)
|
self.ui.tool_offset_entry.set_value(custom_offset)
|
||||||
|
|
||||||
if dia_key == 'type':
|
if dia_key == 'type':
|
||||||
tool_dia_copy[dia_key] = dia_value
|
tool_dia_copy[dia_key] = dia_value
|
||||||
if dia_key == 'tool_type':
|
if dia_key == 'tool_type':
|
||||||
tool_dia_copy[dia_key] = dia_value
|
tool_dia_copy[dia_key] = dia_value
|
||||||
if dia_key == 'data':
|
if dia_key == 'data':
|
||||||
for data_key, data_value in dia_value.items():
|
for data_key, data_value in dia_value.items():
|
||||||
# convert the form fields that are convertible
|
# convert the form fields that are convertible
|
||||||
for param in param_list:
|
for param in param_list:
|
||||||
if data_key == param and data_value is not None:
|
if data_key == param and data_value is not None:
|
||||||
data_copy[data_key] = data_value * factor
|
data_copy[data_key] = data_value * factor
|
||||||
# copy the other dict entries that are not convertible
|
# copy the other dict entries that are not convertible
|
||||||
if data_key not in param_list:
|
if data_key not in param_list:
|
||||||
data_copy[data_key] = data_value
|
data_copy[data_key] = data_value
|
||||||
tool_dia_copy[dia_key] = copy.deepcopy(data_copy)
|
tool_dia_copy[dia_key] = copy.deepcopy(data_copy)
|
||||||
data_copy.clear()
|
data_copy.clear()
|
||||||
|
|
||||||
temp_tools_dict.update({
|
temp_tools_dict.update({
|
||||||
tooluid_key: copy.deepcopy(tool_dia_copy)
|
tooluid_key: copy.deepcopy(tool_dia_copy)
|
||||||
})
|
})
|
||||||
tool_dia_copy.clear()
|
tool_dia_copy.clear()
|
||||||
|
|
||||||
|
self.tools.clear()
|
||||||
self.tools.clear()
|
self.tools = copy.deepcopy(temp_tools_dict)
|
||||||
self.tools = copy.deepcopy(temp_tools_dict)
|
|
||||||
|
|
||||||
# if there is a value in the new tool field then convert that one too
|
# if there is a value in the new tool field then convert that one too
|
||||||
tooldia = self.ui.addtool_entry.get_value()
|
tooldia = self.ui.addtool_entry.get_value()
|
||||||
|
@ -4188,6 +4307,27 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
|
||||||
'''
|
'''
|
||||||
self.cnc_tools = {}
|
self.cnc_tools = {}
|
||||||
|
|
||||||
|
'''
|
||||||
|
This is a dict of dictionaries. Each dict is associated with a tool present in the file. The key is the
|
||||||
|
diameter of the tools and the value is another dict that will hold the data under the following form:
|
||||||
|
{tooldia: {
|
||||||
|
'tool': int,
|
||||||
|
'nr_drills': int,
|
||||||
|
'nr_slots': int,
|
||||||
|
'offset': float,
|
||||||
|
'data': {} # a dict to hold the parameters
|
||||||
|
'gcode': "" # a string with the actual GCODE
|
||||||
|
'gcode_parsed': {} # dictionary holding the CNCJob geometry and type of geometry (cut or move)
|
||||||
|
'solid_geometry': []
|
||||||
|
},
|
||||||
|
...
|
||||||
|
}
|
||||||
|
It is populated in the FlatCAMExcellon.on_create_cncjob_click() but actually
|
||||||
|
it's done in camlib.Excellon.generate_from_excellon_by_tool()
|
||||||
|
BEWARE: I rely on the ordered nature of the Python 3.7 dictionary. Things might change ...
|
||||||
|
'''
|
||||||
|
self.exc_cnc_tools = {}
|
||||||
|
|
||||||
# for now it show if the plot will be done for multi-tool CNCJob (True) or for single tool
|
# for now it show if the plot will be done for multi-tool CNCJob (True) or for single tool
|
||||||
# (like the one in the TCL Command), False
|
# (like the one in the TCL Command), False
|
||||||
self.multitool = False
|
self.multitool = False
|
||||||
|
@ -4223,10 +4363,9 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
|
||||||
# if the FlatCAM object is Excellon don't build the CNC Tools Table but hide it
|
# if the FlatCAM object is Excellon don't build the CNC Tools Table but hide it
|
||||||
if self.cnc_tools:
|
if self.cnc_tools:
|
||||||
self.ui.cnc_tools_table.show()
|
self.ui.cnc_tools_table.show()
|
||||||
self.ui.plot_options_label.show()
|
|
||||||
else:
|
else:
|
||||||
self.ui.cnc_tools_table.hide()
|
self.ui.cnc_tools_table.hide()
|
||||||
self.ui.plot_options_label.hide()
|
|
||||||
|
|
||||||
offset = 0
|
offset = 0
|
||||||
tool_idx = 0
|
tool_idx = 0
|
||||||
|
|
28
ObjectUI.py
28
ObjectUI.py
|
@ -388,16 +388,12 @@ class ExcellonObjectUI(ObjectUI):
|
||||||
|
|
||||||
grid0 = QtWidgets.QGridLayout()
|
grid0 = QtWidgets.QGridLayout()
|
||||||
self.custom_box.addLayout(grid0)
|
self.custom_box.addLayout(grid0)
|
||||||
self.plot_cb = FCCheckBox(label='Plot')
|
|
||||||
self.plot_cb.setToolTip(
|
|
||||||
"Plot (show) this object."
|
|
||||||
)
|
|
||||||
grid0.addWidget(self.plot_cb, 0, 0)
|
|
||||||
self.solid_cb = FCCheckBox(label='Solid')
|
self.solid_cb = FCCheckBox(label='Solid')
|
||||||
self.solid_cb.setToolTip(
|
self.solid_cb.setToolTip(
|
||||||
"Solid circles."
|
"Solid circles."
|
||||||
)
|
)
|
||||||
grid0.addWidget(self.solid_cb, 0, 1)
|
grid0.addWidget(self.solid_cb, 0, 0)
|
||||||
|
|
||||||
# add a frame and inside add a vertical box layout. Inside this vbox layout I add all the Drills widgets
|
# add a frame and inside add a vertical box layout. Inside this vbox layout I add all the Drills widgets
|
||||||
# this way I can hide/show the frame
|
# this way I can hide/show the frame
|
||||||
|
@ -408,19 +404,31 @@ class ExcellonObjectUI(ObjectUI):
|
||||||
self.tools_box.setContentsMargins(0, 0, 0, 0)
|
self.tools_box.setContentsMargins(0, 0, 0, 0)
|
||||||
self.drills_frame.setLayout(self.tools_box)
|
self.drills_frame.setLayout(self.tools_box)
|
||||||
|
|
||||||
|
hlay_plot = QtWidgets.QHBoxLayout()
|
||||||
|
self.tools_box.addLayout(hlay_plot)
|
||||||
|
|
||||||
#### Tools Drills ####
|
#### Tools Drills ####
|
||||||
self.tools_table_label = QtWidgets.QLabel('<b>Tools Table</b>')
|
self.tools_table_label = QtWidgets.QLabel('<b>Tools Table</b>')
|
||||||
self.tools_table_label.setToolTip(
|
self.tools_table_label.setToolTip(
|
||||||
"Tools in this Excellon object\n"
|
"Tools in this Excellon object\n"
|
||||||
"when are used for drilling."
|
"when are used for drilling."
|
||||||
)
|
)
|
||||||
self.tools_box.addWidget(self.tools_table_label)
|
hlay_plot.addWidget(self.tools_table_label)
|
||||||
|
|
||||||
|
# Plot CB
|
||||||
|
self.plot_cb = FCCheckBox('Plot Object')
|
||||||
|
self.plot_cb.setToolTip(
|
||||||
|
"Plot (show) this object."
|
||||||
|
)
|
||||||
|
self.plot_cb.setLayoutDirection(QtCore.Qt.RightToLeft)
|
||||||
|
hlay_plot.addStretch()
|
||||||
|
hlay_plot.addWidget(self.plot_cb)
|
||||||
|
|
||||||
self.tools_table = FCTable()
|
self.tools_table = FCTable()
|
||||||
self.tools_box.addWidget(self.tools_table)
|
self.tools_box.addWidget(self.tools_table)
|
||||||
|
|
||||||
self.tools_table.setColumnCount(5)
|
self.tools_table.setColumnCount(6)
|
||||||
self.tools_table.setHorizontalHeaderLabels(['#', 'Diameter', 'D', 'S', 'Offset'])
|
self.tools_table.setHorizontalHeaderLabels(['#', 'Diameter', 'D', 'S', 'Offset', 'P'])
|
||||||
self.tools_table.setSortingEnabled(False)
|
self.tools_table.setSortingEnabled(False)
|
||||||
|
|
||||||
self.tools_table.horizontalHeaderItem(0).setToolTip(
|
self.tools_table.horizontalHeaderItem(0).setToolTip(
|
||||||
|
@ -440,6 +448,8 @@ class ExcellonObjectUI(ObjectUI):
|
||||||
"Some drill bits (the larger ones) need to drill deeper\n"
|
"Some drill bits (the larger ones) need to drill deeper\n"
|
||||||
"to create the desired exit hole diameter due of the tip shape.\n"
|
"to create the desired exit hole diameter due of the tip shape.\n"
|
||||||
"The value here can compensate the Cut Z parameter.")
|
"The value here can compensate the Cut Z parameter.")
|
||||||
|
self.tools_table.horizontalHeaderItem(5).setToolTip(
|
||||||
|
"Toggle display of the drills for the current tool.")
|
||||||
|
|
||||||
self.empty_label = QtWidgets.QLabel('')
|
self.empty_label = QtWidgets.QLabel('')
|
||||||
self.tools_box.addWidget(self.empty_label)
|
self.tools_box.addWidget(self.empty_label)
|
||||||
|
|
|
@ -12,11 +12,16 @@ CAD program, and create G-Code for Isolation routing.
|
||||||
12.02.2019
|
12.02.2019
|
||||||
|
|
||||||
- whenever a FlatCAM tool is activated, if the notebook side is hidden it will be unhidden
|
- whenever a FlatCAM tool is activated, if the notebook side is hidden it will be unhidden
|
||||||
- reactivated the Voronoi classed
|
- reactivated the Voronoi classes
|
||||||
- added a new parameter named Offset in the Excellon tool table - work in progress
|
- added a new parameter named Offset in the Excellon tool table - work in progress
|
||||||
- finished work on Offset parameter in Excellon Object (Excellon Editor, camlib, FlatCAMObj updated to take this param in consideration)
|
- finished work on Offset parameter in Excellon Object (Excellon Editor, camlib, FlatCAMObj updated to take this param in consideration)
|
||||||
- fixed a bug where in Excellon editor when editing a file, a tool was automatically added. That is supposed to happen only for empty newly created Excellon Objects.
|
- fixed a bug where in Excellon editor when editing a file, a tool was automatically added. That is supposed to happen only for empty newly created Excellon Objects.
|
||||||
- starting to work on storing the solid_geometry for each tool in part in Excellon Object
|
- starting to work on storing the solid_geometry for each tool in part in Excellon Object
|
||||||
|
- stored solid_geometry of Excellon object in the self.tools dictionary
|
||||||
|
- finished the solid_geometry restore after edit in Excellon Editor
|
||||||
|
- finished plotting selection for each tool in the Excellon Tool Table
|
||||||
|
- fixed the camlib.Excellon.bounds() function for the new type of Excellon geometry therefore fixed the canvas selection, too
|
||||||
|
|
||||||
|
|
||||||
10.02.2019
|
10.02.2019
|
||||||
|
|
||||||
|
|
30
camlib.py
30
camlib.py
|
@ -4073,7 +4073,12 @@ class Excellon(Geometry):
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
self.solid_geometry = []
|
self.solid_geometry = []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# clear the solid_geometry in self.tools
|
||||||
|
for tool in self.tools:
|
||||||
|
self.tools[tool]['solid_geometry'][:] = []
|
||||||
|
|
||||||
for drill in self.drills:
|
for drill in self.drills:
|
||||||
# poly = drill['point'].buffer(self.tools[drill['tool']]["C"]/2.0)
|
# poly = drill['point'].buffer(self.tools[drill['tool']]["C"]/2.0)
|
||||||
if drill['tool'] is '':
|
if drill['tool'] is '':
|
||||||
|
@ -4096,7 +4101,7 @@ class Excellon(Geometry):
|
||||||
lines_string = LineString([start, stop])
|
lines_string = LineString([start, stop])
|
||||||
poly = lines_string.buffer(slot_tooldia / 2.0, int(int(self.geo_steps_per_circle) / 4))
|
poly = lines_string.buffer(slot_tooldia / 2.0, int(int(self.geo_steps_per_circle) / 4))
|
||||||
# self.solid_geometry.append(poly)
|
# self.solid_geometry.append(poly)
|
||||||
self.tools[drill['tool']]['solid_geometry'].append(poly)
|
self.tools[slot['tool']]['solid_geometry'].append(poly)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug("Excellon geometry creation failed due of ERROR: %s" % str(e))
|
log.debug("Excellon geometry creation failed due of ERROR: %s" % str(e))
|
||||||
|
@ -4139,9 +4144,9 @@ class Excellon(Geometry):
|
||||||
# now it can get bounds for nested lists of objects
|
# now it can get bounds for nested lists of objects
|
||||||
|
|
||||||
log.debug("Excellon() -> bounds()")
|
log.debug("Excellon() -> bounds()")
|
||||||
if self.solid_geometry is None:
|
# if self.solid_geometry is None:
|
||||||
log.debug("solid_geometry is None")
|
# log.debug("solid_geometry is None")
|
||||||
return 0, 0, 0, 0
|
# return 0, 0, 0, 0
|
||||||
|
|
||||||
def bounds_rec(obj):
|
def bounds_rec(obj):
|
||||||
if type(obj) is list:
|
if type(obj) is list:
|
||||||
|
@ -4169,8 +4174,19 @@ class Excellon(Geometry):
|
||||||
# it's a Shapely object, return it's bounds
|
# it's a Shapely object, return it's bounds
|
||||||
return obj.bounds
|
return obj.bounds
|
||||||
|
|
||||||
bounds_coords = bounds_rec(self.solid_geometry)
|
minx_list = []
|
||||||
return bounds_coords
|
miny_list = []
|
||||||
|
maxx_list = []
|
||||||
|
maxy_list = []
|
||||||
|
|
||||||
|
for tool in self.tools:
|
||||||
|
minx, miny, maxx, maxy = bounds_rec(self.tools[tool]['solid_geometry'])
|
||||||
|
minx_list.append(minx)
|
||||||
|
miny_list.append(miny)
|
||||||
|
maxx_list.append(maxx)
|
||||||
|
maxy_list.append(maxy)
|
||||||
|
|
||||||
|
return (min(minx_list), min(miny_list), max(maxx_list), max(maxy_list))
|
||||||
|
|
||||||
def convert_units(self, units):
|
def convert_units(self, units):
|
||||||
"""
|
"""
|
||||||
|
@ -5535,7 +5551,7 @@ class CNCjob(Geometry):
|
||||||
return "fail"
|
return "fail"
|
||||||
|
|
||||||
gobj = self.codes_split(line)
|
gobj = self.codes_split(line)
|
||||||
|
print(gobj)
|
||||||
## Units
|
## Units
|
||||||
if 'G' in gobj and (gobj['G'] == 20.0 or gobj['G'] == 21.0):
|
if 'G' in gobj and (gobj['G'] == 20.0 or gobj['G'] == 21.0):
|
||||||
self.units = {20.0: "IN", 21.0: "MM"}[gobj['G']]
|
self.units = {20.0: "IN", 21.0: "MM"}[gobj['G']]
|
||||||
|
|
Loading…
Reference in New Issue