- in NCC and Isolation Tools, the Validity Checking of the tools is now multithreaded when the Check Validity UI control is checked

- translation strings updated
This commit is contained in:
Marius Stanciu 2020-11-03 17:07:19 +02:00 committed by Marius
parent 3083630e5f
commit 13e4d7bad7
22 changed files with 3415 additions and 3219 deletions

View File

@ -17,6 +17,8 @@ CHANGELOG for FlatCAM beta
- optimized some of the strings
- fixed the project context save functionality to work in the new program configuration
- updated Turkish translation (by Mehmet Kaya)
- in NCC and Isolation Tools, the Validity Checking of the tools is now multithreaded when the Check Validity UI control is checked
- translation strings updated
2.11.2020

View File

@ -908,9 +908,59 @@ class ToolIsolation(AppTool, Gerber):
})
def on_find_optimal_tooldia(self):
self.find_safe_tooldia_worker(is_displayed=True)
self.find_safe_tooldia_worker()
def find_safe_tooldia_worker(self, is_displayed):
@staticmethod
def find_optim_mp(aperture_storage, decimals):
msg = 'ok'
total_geo = []
for ap in list(aperture_storage.keys()):
if 'geometry' in aperture_storage[ap]:
for geo_el in aperture_storage[ap]['geometry']:
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)
except TypeError:
msg = ('[ERROR_NOTCL] %s' % _("The Gerber object has one Polygon as geometry.\n"
"There are no distances between geometry elements to be found."))
min_dict = {}
idx = 1
for geo in total_geo:
for s_geo in total_geo[idx:]:
# minimize the number of distances by not taking into considerations
# those that are too small
dist = geo.distance(s_geo)
dist = float('%.*f' % (decimals, dist))
loc_1, loc_2 = nearest_points(geo, s_geo)
proc_loc = (
(float('%.*f' % (decimals, loc_1.x)), float('%.*f' % (decimals, loc_1.y))),
(float('%.*f' % (decimals, loc_2.x)), float('%.*f' % (decimals, loc_2.y)))
)
if dist in min_dict:
min_dict[dist].append(proc_loc)
else:
min_dict[dist] = [proc_loc]
idx += 1
min_list = list(min_dict.keys())
min_dist = min(min_list)
return msg, min_dist
# multiprocessing variant
def find_safe_tooldia_multiprocessing(self):
self.app.inform.emit(_("Checking tools for validity."))
self.units = self.app.defaults['units'].upper()
obj_name = self.ui.object_combo.currentText()
@ -926,8 +976,73 @@ class ToolIsolation(AppTool, Gerber):
self.app.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Object not found"), str(obj_name)))
return
def job_thread(app_obj, is_display):
with self.app.proc_container.new(_("Working ...")):
def job_thread(app_obj):
with self.app.proc_container.new(_("Checking ...")):
ap_storage = fcobj.apertures
p = app_obj.pool.apply_async(self.find_optim_mp, args=(ap_storage, self.decimals))
res = p.get()
if res[0] != 'ok':
app_obj.inform.emit(res[0])
return 'fail'
else:
min_dist = res[1]
try:
min_dist_truncated = self.app.dec_format(float(min_dist), self.decimals)
self.safe_tooldia = min_dist_truncated
if self.safe_tooldia:
# 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
for tool in sorted_tools:
tool_dia = float(self.iso_tools[tool]['tooldia'])
if tool_dia > self.safe_tooldia:
msg = _("Incomplete isolation. "
"At least one tool could not do a complete isolation.")
self.app.inform.emit('[WARNING] %s' % msg)
break
# 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]})
def find_safe_tooldia_worker(self):
self.app.inform.emit(_("Checking tools for validity."))
self.units = self.app.defaults['units'].upper()
obj_name = self.ui.object_combo.currentText()
# Get source object.
try:
fcobj = self.app.collection.get_by_name(obj_name)
except Exception:
self.app.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Could not retrieve object"), str(obj_name)))
return
if fcobj is None:
self.app.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Object not found"), str(obj_name)))
return
def job_thread(app_obj):
with self.app.proc_container.new(_("Checking ...")):
try:
old_disp_number = 0
pol_nr = 0
@ -995,42 +1110,16 @@ class ToolIsolation(AppTool, Gerber):
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)
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:
if self.safe_tooldia:
# 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
for tool in sorted_tools:
tool_dia = float(self.iso_tools[tool]['tooldia'])
if tool_dia > self.safe_tooldia:
msg = _("Incomplete isolation. "
"At least one tool could not do a complete isolation.")
self.app.inform.emit('[WARNING] %s' % msg)
break
# reset the value to prepare for another isolation
self.safe_tooldia = None
app_obj.inform.emit('[success] %s: %s %s' %
(_("Optimal tool diameter found"), str(min_dist_truncated),
self.units.lower()))
except Exception as ee:
log.debug(str(ee))
return
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app, is_displayed]})
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
def on_tool_add(self, custom_dia=None):
self.blockSignals(True)
@ -1384,7 +1473,7 @@ class ToolIsolation(AppTool, Gerber):
return
if self.ui.valid_cb.get_value() is True:
self.find_safe_tooldia_worker(is_displayed=False)
self.find_safe_tooldia_multiprocessing()
def worker_task(iso_obj):
with self.app.proc_container.new(_("Isolating ...")):

View File

@ -845,10 +845,59 @@ class NonCopperClear(AppTool, Gerber):
})
def on_find_optimal_tooldia(self):
self.find_safe_tooldia_worker(is_displayed=True)
self.find_safe_tooldia_worker()
def find_safe_tooldia_worker(self, is_displayed):
self.app.inform.emit(_("NCC Tool. Checking tools for validity."))
@staticmethod
def find_optim_mp(aperture_storage, decimals):
msg = 'ok'
total_geo = []
for ap in list(aperture_storage.keys()):
if 'geometry' in aperture_storage[ap]:
for geo_el in aperture_storage[ap]['geometry']:
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)
except TypeError:
msg = ('[ERROR_NOTCL] %s' % _("The Gerber object has one Polygon as geometry.\n"
"There are no distances between geometry elements to be found."))
min_dict = {}
idx = 1
for geo in total_geo:
for s_geo in total_geo[idx:]:
# minimize the number of distances by not taking into considerations
# those that are too small
dist = geo.distance(s_geo)
dist = float('%.*f' % (decimals, dist))
loc_1, loc_2 = nearest_points(geo, s_geo)
proc_loc = (
(float('%.*f' % (decimals, loc_1.x)), float('%.*f' % (decimals, loc_1.y))),
(float('%.*f' % (decimals, loc_2.x)), float('%.*f' % (decimals, loc_2.y)))
)
if dist in min_dict:
min_dict[dist].append(proc_loc)
else:
min_dict[dist] = [proc_loc]
idx += 1
min_list = list(min_dict.keys())
min_dist = min(min_list)
return msg, min_dist
# multiprocessing variant
def find_safe_tooldia_multiprocessing(self):
self.app.inform.emit(_("Checking tools for validity."))
self.units = self.app.defaults['units'].upper()
obj_name = self.ui.object_combo.currentText()
@ -864,8 +913,77 @@ class NonCopperClear(AppTool, Gerber):
self.app.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Object not found"), str(obj_name)))
return
def job_thread(app_obj, is_display):
with self.app.proc_container.new(_("Working...")):
def job_thread(app_obj):
with self.app.proc_container.new(_("Checking ...")):
ap_storage = fcobj.apertures
p = app_obj.pool.apply_async(self.find_optim_mp, args=(ap_storage, self.decimals))
res = p.get()
if res[0] != 'ok':
app_obj.inform.emit(res[0])
return 'fail'
else:
min_dist = res[1]
try:
min_dist_truncated = self.app.dec_format(float(min_dist), self.decimals)
self.safe_tooldia = min_dist_truncated
# 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)
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]})
def find_safe_tooldia_worker(self):
self.app.inform.emit(_("Checking tools for validity."))
self.units = self.app.defaults['units'].upper()
obj_name = self.ui.object_combo.currentText()
# Get source object.
try:
fcobj = self.app.collection.get_by_name(obj_name)
except Exception:
self.app.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Could not retrieve object"), str(obj_name)))
return
if fcobj is None:
self.app.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Object not found"), str(obj_name)))
return
def job_thread(app_obj):
with self.app.proc_container.new(_("Checking ...")):
try:
old_disp_number = 0
pol_nr = 0
@ -933,46 +1051,16 @@ class NonCopperClear(AppTool, Gerber):
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)
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)
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
app_obj.inform.emit('[success] %s: %s %s' %
(_("Optimal tool diameter found"), str(min_dist_truncated),
self.units.lower()))
except Exception as ee:
log.debug(str(ee))
return
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app, is_displayed]})
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
def on_tool_add(self, custom_dia=None):
self.blockSignals(True)
@ -1327,7 +1415,8 @@ class NonCopperClear(AppTool, Gerber):
return
if self.ui.valid_cb.get_value() is True:
self.find_safe_tooldia_worker(is_displayed=False)
# this is done in another Process
self.find_safe_tooldia_multiprocessing()
# use the selected tools in the tool table; get diameters for isolation
self.iso_dia_list = []

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff