- fixed NCC Tool not working with the new changes; the check for not having complete isolation is just a Warning

This commit is contained in:
Marius Stanciu
2020-10-29 15:03:17 +02:00
parent 443f9a51e8
commit fcfc819fff
4 changed files with 204 additions and 195 deletions

View File

@@ -8,7 +8,7 @@
from PyQt5 import QtWidgets, QtCore, QtGui
from appTool import AppTool
from appGUI.GUIElements import FCCheckBox, FCDoubleSpinner, RadioSet, FCTable, FCInputDialog, FCButton,\
from appGUI.GUIElements import FCCheckBox, FCDoubleSpinner, RadioSet, FCTable, FCButton,\
FCComboBox, OptionalInputSection, FCLabel, FCInputDialogSpinnerButton, FCComboBox2
from appParsers.ParseGerber import Gerber
@@ -463,8 +463,8 @@ class NonCopperClear(AppTool, Gerber):
callback=self.on_find_optimal_tooldia)
tool_add_popup.setWindowIcon(QtGui.QIcon(self.app.resource_location + '/letter_t_32.png'))
def find_optimal(val):
tool_add_popup.set_value(float(val))
def find_optimal(valor):
tool_add_popup.set_value(float(valor))
self.optimal_found_sig.connect(find_optimal)
@@ -629,7 +629,7 @@ class NonCopperClear(AppTool, Gerber):
# read the table tools uid
current_uid_list = []
for row in range(self.ui.tools_table.rowCount()):
uid = int(self.ui.tools_table.item(row,3).text())
uid = int(self.ui.tools_table.item(row, 3).text())
current_uid_list.append(uid)
new_tools = {}
@@ -675,7 +675,8 @@ class NonCopperClear(AppTool, Gerber):
tool_id += 1
id_ = QtWidgets.QTableWidgetItem('%d' % int(tool_id))
id_.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
flags = QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled
id_.setFlags(flags)
row_no = tool_id - 1
self.ui.tools_table.setItem(row_no, 0, id_) # Tool name/id
@@ -696,8 +697,8 @@ class NonCopperClear(AppTool, Gerber):
# make the diameter column editable
for row in range(tool_id):
self.ui.tools_table.item(row, 1).setFlags(
QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
flags = QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled
self.ui.tools_table.item(row, 1).setFlags(flags)
self.ui.tools_table.resizeColumnsToContents()
self.ui.tools_table.resizeRowsToContents()
@@ -862,113 +863,113 @@ class NonCopperClear(AppTool, Gerber):
self.app.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Object not found"), str(obj_name)))
return
proc = self.app.proc_container.new(_("Working..."))
def job_thread(app_obj, is_display):
try:
old_disp_number = 0
pol_nr = 0
app_obj.proc_container.update_view_text(' %d%%' % 0)
total_geo = []
with self.app.proc_container.new(_("Working...")):
try:
old_disp_number = 0
pol_nr = 0
app_obj.proc_container.update_view_text(' %d%%' % 0)
total_geo = []
for ap in list(fcobj.apertures.keys()):
if 'geometry' in fcobj.apertures[ap]:
for geo_el in fcobj.apertures[ap]['geometry']:
for ap in list(fcobj.apertures.keys()):
if 'geometry' in fcobj.apertures[ap]:
for geo_el in fcobj.apertures[ap]['geometry']:
if self.app.abort_flag:
# graceful abort requested by the user
raise grace
if 'solid' in geo_el and geo_el['solid'] is not None and geo_el['solid'].is_valid:
total_geo.append(geo_el['solid'])
total_geo = MultiPolygon(total_geo)
total_geo = total_geo.buffer(0)
try:
__ = iter(total_geo)
geo_len = len(total_geo)
geo_len = (geo_len * (geo_len - 1)) / 2
except TypeError:
app_obj.inform.emit('[ERROR_NOTCL] %s' %
_("The Gerber object has one Polygon as geometry.\n"
"There are no distances between geometry elements to be found."))
return 'fail'
min_dict = {}
idx = 1
for geo in total_geo:
for s_geo in total_geo[idx:]:
if self.app.abort_flag:
# graceful abort requested by the user
raise grace
if 'solid' in geo_el and geo_el['solid'] is not None and geo_el['solid'].is_valid:
total_geo.append(geo_el['solid'])
# minimize the number of distances by not taking into considerations
# those that are too small
dist = geo.distance(s_geo)
dist = float('%.*f' % (self.decimals, dist))
loc_1, loc_2 = nearest_points(geo, s_geo)
total_geo = MultiPolygon(total_geo)
total_geo = total_geo.buffer(0)
proc_loc = (
(float('%.*f' % (self.decimals, loc_1.x)), float('%.*f' % (self.decimals, loc_1.y))),
(float('%.*f' % (self.decimals, loc_2.x)), float('%.*f' % (self.decimals, loc_2.y)))
)
try:
__ = iter(total_geo)
geo_len = len(total_geo)
geo_len = (geo_len * (geo_len - 1)) / 2
except TypeError:
app_obj.inform.emit('[ERROR_NOTCL] %s' %
_("The Gerber object has one Polygon as geometry.\n"
"There are no distances between geometry elements to be found."))
return 'fail'
if dist in min_dict:
min_dict[dist].append(proc_loc)
else:
min_dict[dist] = [proc_loc]
min_dict = {}
idx = 1
for geo in total_geo:
for s_geo in total_geo[idx:]:
if self.app.abort_flag:
# graceful abort requested by the user
raise grace
pol_nr += 1
disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 100]))
# minimize the number of distances by not taking into considerations those that are too small
dist = geo.distance(s_geo)
dist = float('%.*f' % (self.decimals, dist))
loc_1, loc_2 = nearest_points(geo, s_geo)
if old_disp_number < disp_number <= 100:
app_obj.proc_container.update_view_text(' %d%%' % disp_number)
old_disp_number = disp_number
idx += 1
proc_loc = (
(float('%.*f' % (self.decimals, loc_1.x)), float('%.*f' % (self.decimals, loc_1.y))),
(float('%.*f' % (self.decimals, loc_2.x)), float('%.*f' % (self.decimals, loc_2.y)))
)
min_list = list(min_dict.keys())
min_dist = min(min_list)
if dist in min_dict:
min_dict[dist].append(proc_loc)
else:
min_dict[dist] = [proc_loc]
min_dist_truncated = self.app.dec_format(float(min_dist), self.decimals)
self.safe_tooldia = min_dist_truncated
pol_nr += 1
disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 100]))
if is_display:
self.optimal_found_sig.emit(min_dist_truncated)
if old_disp_number < disp_number <= 100:
app_obj.proc_container.update_view_text(' %d%%' % disp_number)
old_disp_number = disp_number
idx += 1
min_list = list(min_dict.keys())
min_dist = min(min_list)
min_dist_truncated = self.app.dec_format(float(min_dist), self.decimals)
self.safe_tooldia = min_dist_truncated
if is_display:
self.optimal_found_sig.emit(min_dist_truncated)
app_obj.inform.emit('[success] %s: %s %s' %
(_("Optimal tool diameter found"), str(min_dist_truncated),
self.units.lower()))
else:
# find the selected tool ID's
sorted_tools = []
table_items = self.ui.tools_table.selectedItems()
sel_rows = {t.row() for t in table_items}
for row in sel_rows:
tid = int(self.ui.tools_table.item(row, 3).text())
sorted_tools.append(tid)
if not sorted_tools:
msg = _("There are no tools selected in the Tool Table.")
self.app.inform.emit('[ERROR_NOTCL] %s' % msg)
return 'fail'
# check if the tools diameters are less then the safe tool diameter
suitable_tools = []
for tool in sorted_tools:
tool_dia = float(self.ncc_tools[tool]['tooldia'])
if tool_dia <= self.safe_tooldia:
suitable_tools.append(tool_dia)
if not suitable_tools:
msg = _("Incomplete isolation. None of the selected tools could do a complete isolation.")
self.app.inform.emit('[WARNING] %s' % msg)
app_obj.inform.emit('[success] %s: %s %s' %
(_("Optimal tool diameter found"), str(min_dist_truncated),
self.units.lower()))
else:
msg = _("At least one of the selected tools can do a complete isolation.")
self.app.inform.emit('[success] %s' % msg)
# find the selected tool ID's
sorted_tools = []
table_items = self.ui.tools_table.selectedItems()
sel_rows = {t.row() for t in table_items}
for row in sel_rows:
tid = int(self.ui.tools_table.item(row, 3).text())
sorted_tools.append(tid)
if not sorted_tools:
msg = _("There are no tools selected in the Tool Table.")
self.app.inform.emit('[ERROR_NOTCL] %s' % msg)
return 'fail'
# reset the value to prepare for another isolation
self.safe_tooldia = None
except Exception as ee:
log.debug(str(ee))
return
# check if the tools diameters are less then the safe tool diameter
suitable_tools = []
for tool in sorted_tools:
tool_dia = float(self.ncc_tools[tool]['tooldia'])
if tool_dia <= self.safe_tooldia:
suitable_tools.append(tool_dia)
if not suitable_tools:
msg = _("Incomplete isolation. None of the selected tools could do a complete isolation.")
self.app.inform.emit('[WARNING] %s' % msg)
else:
msg = _("At least one of the selected tools can do a complete isolation.")
self.app.inform.emit('[success] %s' % msg)
# reset the value to prepare for another isolation
self.safe_tooldia = None
except Exception as ee:
log.debug(str(ee))
return
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app, is_displayed]})
@@ -1374,7 +1375,7 @@ class NonCopperClear(AppTool, Gerber):
isotooldia=self.iso_dia_list,
outname=self.o_name,
tools_storage=self.ncc_tools)
elif self.select_method == 1: # Area Selection
elif self.select_method == 1: # Area Selection
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Click the start point of the area."))
if self.app.is_legacy is False:
@@ -1676,7 +1677,7 @@ class NonCopperClear(AppTool, Gerber):
box_kind = box_obj.kind if box_obj is not None else None
env_obj = None
if ncc_select == _('Itself'):
if ncc_select == 0: # _('Itself')
geo_n = ncc_obj.solid_geometry
try:
@@ -1692,13 +1693,13 @@ class NonCopperClear(AppTool, Gerber):
log.debug("NonCopperClear.calculate_bounding_box() 'itself' --> %s" % str(e))
self.app.inform.emit('[ERROR_NOTCL] %s' % _("No object available."))
return None
elif ncc_select == _("Area Selection"):
elif ncc_select == 1: # _("Area Selection")
env_obj = unary_union(self.sel_rect)
try:
__ = iter(env_obj)
except Exception:
env_obj = [env_obj]
elif ncc_select == _("Reference Object"):
elif ncc_select == 2: # _("Reference Object")
if box_obj is None:
return None, None
@@ -1740,14 +1741,14 @@ class NonCopperClear(AppTool, Gerber):
return 'fail'
new_bounding_box = None
if ncc_select == _('Itself'):
if ncc_select == 0: # _('Itself')
try:
new_bounding_box = bbox.buffer(distance=ncc_margin, join_style=base.JOIN_STYLE.mitre)
except Exception as e:
log.debug("NonCopperClear.apply_margin_to_bounding_box() 'itself' --> %s" % str(e))
self.app.inform.emit('[ERROR_NOTCL] %s' % _("No object available."))
return 'fail'
elif ncc_select == _("Area Selection"):
elif ncc_select == 1: # _("Area Selection")
geo_buff_list = []
for poly in bbox:
if self.app.abort_flag:
@@ -1755,7 +1756,7 @@ class NonCopperClear(AppTool, Gerber):
raise grace
geo_buff_list.append(poly.buffer(distance=ncc_margin, join_style=base.JOIN_STYLE.mitre))
new_bounding_box = unary_union(geo_buff_list)
elif ncc_select == _("Reference Object"):
elif ncc_select == 2: # _("Reference Object")
if box_kind == 'geometry':
geo_buff_list = []
for poly in bbox:
@@ -1974,7 +1975,7 @@ class NonCopperClear(AppTool, Gerber):
cp = None
if ncc_method == 0: # standard
if ncc_method == 0: # standard
try:
cp = self.clear_polygon(pol, tooldia,
steps_per_circle=self.circle_steps,
@@ -2133,7 +2134,7 @@ class NonCopperClear(AppTool, Gerber):
app_obj.poly_not_cleared = False # flag for polygons not cleared
if ncc_select == 2: # Reference Object
if ncc_select == 2: # Reference Object
bbox_geo, bbox_kind = self.calculate_bounding_box(
ncc_obj=ncc_obj, box_obj=sel_obj, ncc_select=ncc_select)
else:
@@ -2360,14 +2361,10 @@ class NonCopperClear(AppTool, Gerber):
sorted_clear_tools.sort(reverse=True)
cleared_by_last_tool = []
rest_geo = []
current_uid = 1
# repurposed flag for final object, geo_obj. True if it has any solid_geometry, False if not.
# re purposed flag for final object, geo_obj. True if it has any solid_geometry, False if not.
app_obj.poly_not_cleared = True
if ncc_select == 2: # Reference Object
if ncc_select == 2: # Reference Object
env_obj, box_obj_kind = self.calculate_bounding_box(
ncc_obj=ncc_obj, box_obj=sel_obj, ncc_select=ncc_select)
else:
@@ -2718,7 +2715,7 @@ class NonCopperClear(AppTool, Gerber):
self.app.inform.emit(_("NCC Tool. Preparing non-copper polygons."))
try:
if sel_obj is None or sel_obj == 0: # sel_obj == 'itself'
if sel_obj is None or sel_obj == 0: # sel_obj == 'itself'
ncc_sel_obj = ncc_obj
else:
ncc_sel_obj = sel_obj
@@ -2727,7 +2724,7 @@ class NonCopperClear(AppTool, Gerber):
return 'fail'
bounding_box = None
if ncc_select == 0: # itself
if ncc_select == 0: # itself
geo_n = ncc_sel_obj.solid_geometry
try:
@@ -2998,6 +2995,7 @@ class NonCopperClear(AppTool, Gerber):
log.debug("NCC Tool. Finished calculation of 'empty' area.")
self.app.inform.emit(_("NCC Tool. Finished calculation of 'empty' area."))
tool = 1
# COPPER CLEARING #
for tool in sorted_tools:
log.debug("Starting geometry processing for tool: %s" % str(tool))
@@ -3450,7 +3448,7 @@ class NonCopperClear(AppTool, Gerber):
if isinstance(p, Polygon):
try:
if ncc_method == 0: # standard
if ncc_method == 0: # standard
cp = self.clear_polygon(p, tool_used,
self.circle_steps,
overlap=overlap, contour=contour, connect=connect,
@@ -3479,7 +3477,7 @@ class NonCopperClear(AppTool, Gerber):
QtWidgets.QApplication.processEvents()
try:
if ncc_method == 0: # 'standard'
if ncc_method == 0: # 'standard'
cp = self.clear_polygon(poly_p, tool_used,
self.circle_steps,
overlap=overlap, contour=contour,
@@ -3636,6 +3634,10 @@ class NonCopperClear(AppTool, Gerber):
geo_len = 1
else:
geo_len = len(target)
if isinstance(target, list):
target = MultiPolygon(target)
pol_nr = 0
old_disp_number = 0