- 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:
parent
3083630e5f
commit
13e4d7bad7
|
@ -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
|
||||
|
||||
|
|
|
@ -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 ...")):
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue