- Gerber Editor: made geometry transfer (which is slow) to Editor to be multithreaded

- Gerber Editor: plotting process is showed in the status bar
This commit is contained in:
Marius Stanciu
2019-04-05 15:28:32 +03:00
committed by Marius
parent 4ecdfba29c
commit cefb74d792
4 changed files with 88 additions and 48 deletions

View File

@@ -7949,9 +7949,15 @@ The normal flow when working in FlatCAM is the following:</span></p>
t = threading.Thread(target=lambda: self.check_project_file_size(1, filename=filename)) t = threading.Thread(target=lambda: self.check_project_file_size(1, filename=filename))
t.start() t.start()
# using Alfe's answer from here:
# https://stackoverflow.com/questions/474528/what-is-the-best-way-to-repeatedly-execute-a-function-every-x-seconds-in-python
def check_project_file_size(self, delay, filename): def check_project_file_size(self, delay, filename):
"""
Using Alfe's answer from here:
https://stackoverflow.com/questions/474528/what-is-the-best-way-to-repeatedly-execute-a-function-every-x-seconds-in-python
:param delay: period of checking if project file size is more than zero; in seconds
:param filename: the name of the project file to be checked for size more than zero
:return:
"""
next_time = time.time() + delay next_time = time.time() + delay
while True: while True:
time.sleep(max(0, next_time - time.time())) time.sleep(max(0, next_time - time.time()))

View File

@@ -240,6 +240,9 @@ class ObjectCollection(QtCore.QAbstractItemModel):
# tasks know that they have to wait until available. # tasks know that they have to wait until available.
self.promises = set() self.promises = set()
# same as above only for objects that are plotted
self.plot_promises = set()
self.app = app self.app = app
### View ### View
@@ -275,6 +278,16 @@ class ObjectCollection(QtCore.QAbstractItemModel):
def has_promises(self): def has_promises(self):
return len(self.promises) > 0 return len(self.promises) > 0
def plot_promise(self, plot_obj_name):
self.plot_promises.add(plot_obj_name)
def plot_remove_promise(self, plot_obj_name):
if plot_obj_name in self.plot_promises:
self.plot_promises.remove(plot_obj_name)
def has_plot_promises(self):
return len(self.plot_promises) > 0
def on_mouse_down(self, event): def on_mouse_down(self, event):
FlatCAMApp.App.log.debug("Mouse button pressed on list") FlatCAMApp.App.log.debug("Mouse button pressed on list")

View File

@@ -9,6 +9,11 @@ CAD program, and create G-Code for Isolation routing.
================================================= =================================================
5.04.2019
- Gerber Editor: made geometry transfer (which is slow) to Editor to be multithreaded
- Gerber Editor: plotting process is showed in the status bar
4.04.2019 4.04.2019
- added support for Gerber format specification D (no zero suppression) - PCBWizard Gerber files support - added support for Gerber format specification D (no zero suppression) - PCBWizard Gerber files support

View File

@@ -7,6 +7,7 @@ import shapely.affinity as affinity
from numpy import arctan2, Inf, array, sqrt, sign, dot from numpy import arctan2, Inf, array, sqrt, sign, dot
from rtree import index as rtindex from rtree import index as rtindex
import threading, time
from camlib import * from camlib import *
from flatcamGUI.GUIElements import FCEntry, FCComboBox, FCTable, FCDoubleSpinner, LengthEntry, RadioSet, SpinBoxDelegate from flatcamGUI.GUIElements import FCEntry, FCComboBox, FCTable, FCDoubleSpinner, LengthEntry, RadioSet, SpinBoxDelegate
@@ -1262,18 +1263,23 @@ class FlatCAMGrbEditor(QtCore.QObject):
# build the geometry for each tool-diameter, each drill will be represented by a '+' symbol # build the geometry for each tool-diameter, each drill will be represented by a '+' symbol
# and then add it to the storage elements (each storage elements is a member of a list # and then add it to the storage elements (each storage elements is a member of a list
def job_thread(apid):
with self.app.proc_container.new(_("Adding aperture: %s geo ...") % str(apid)):
storage_elem = FlatCAMGeoEditor.make_storage()
for geo in self.gerber_obj.apertures[apid]['solid_geometry']:
if geo is not None:
self.add_gerber_shape(DrawToolShape(geo), storage_elem)
self.storage_dict[apid] = storage_elem
# Check promises and clear if exists
self.app.collection.plot_remove_promise(apid)
for apid in self.gerber_obj.apertures: for apid in self.gerber_obj.apertures:
storage_elem = FlatCAMGeoEditor.make_storage() self.app.worker_task.emit({'fcn': job_thread, 'params': [apid]})
for geo in self.gerber_obj.apertures[apid]['solid_geometry']: self.app.collection.plot_promise(apid)
if geo is not None:
self.add_gerber_shape(DrawToolShape(geo), storage_elem)
self.storage_dict[apid] = storage_elem
self.replot() self.start_delayed_plot(check_period=0.5)
# add a first tool in the Tool Table but only if the Excellon Object is empty
# if not self.tool2tooldia:
# self.on_tool_add(tooldia=1.00)
def update_fcgerber(self, exc_obj): def update_fcgerber(self, exc_obj):
""" """
@@ -1845,25 +1851,56 @@ class FlatCAMGrbEditor(QtCore.QObject):
:return: None :return: None
:rtype: None :rtype: None
""" """
# self.app.log.debug("plot_all()") with self.app.proc_container.new("Plotting"):
self.shapes.clear(update=True) # self.app.log.debug("plot_all()")
self.shapes.clear(update=True)
for storage in self.storage_dict: for storage in self.storage_dict:
for shape_plus in self.storage_dict[storage].get_objects(): for shape in self.storage_dict[storage].get_objects():
if shape_plus.geo is None: if shape.geo is None:
continue continue
if shape_plus in self.selected: if shape in self.selected:
self.plot_shape(geometry=shape_plus.geo, color=self.app.defaults['global_sel_draw_color'], self.plot_shape(geometry=shape.geo, color=self.app.defaults['global_sel_draw_color'],
linewidth=2) linewidth=2)
continue continue
self.plot_shape(geometry=shape_plus.geo, color=self.app.defaults['global_draw_color']) self.plot_shape(geometry=shape.geo, color=self.app.defaults['global_draw_color'])
for shape in self.utility: for shape in self.utility:
self.plot_shape(geometry=shape.geo, linewidth=1) self.plot_shape(geometry=shape.geo, linewidth=1)
continue continue
self.shapes.redraw() self.shapes.redraw()
def start_delayed_plot(self, check_period):
self.plot_thread = threading.Thread(target=lambda: self.check_plot_finished(check_period))
self.plot_thread.start()
def stop_delayed_plot(self):
self.plot_thread.exit()
# self.plot_thread.join()
def check_plot_finished(self, delay):
"""
Using Alfe's answer from here:
https://stackoverflow.com/questions/474528/what-is-the-best-way-to-repeatedly-execute-a-function-every-x-seconds-in-python
:param delay: period of checking if project file size is more than zero; in seconds
:param filename: the name of the project file to be checked for size more than zero
:return:
"""
next_time = time.time() + delay
while True:
time.sleep(max(0, next_time - time.time()))
try:
if self.app.collection.has_plot_promises() is False:
self.plot_all()
break
except Exception:
traceback.print_exc()
# skip tasks if we are behind schedule:
next_time += (time.time() - next_time) // delay * delay + delay
def plot_shape(self, geometry=None, color='black', linewidth=1): def plot_shape(self, geometry=None, color='black', linewidth=1):
""" """
@@ -1887,27 +1924,6 @@ class FlatCAMGrbEditor(QtCore.QObject):
return return
self.shapes.add(shape=geometry, color=color, face_color=color+'AF', layer=0) self.shapes.add(shape=geometry, color=color, face_color=color+'AF', layer=0)
# try:
# for geo in geometry:
# plot_elements += self.plot_shape(geometry=geo.geo, color=color, linewidth=linewidth)
#
# ## Non-iterable
# except TypeError:
#
# # ## DrawToolShape
# # if isinstance(geometry, DrawToolShape):
# # plot_elements += self.plot_shape(geometry=geometry.geo, color=color, linewidth=linewidth)
# #
# # ## Polygon: Descend into exterior and each interior.
# # if type(geometry) == Polygon:
# # plot_elements += self.plot_shape(geometry=geometry.exterior, color=color, linewidth=linewidth)
# # plot_elements += self.plot_shape(geometry=geometry.interiors, color=color, linewidth=linewidth)
# if type(geometry) == Point:
# pass
# else:
# plot_elements.append(self.shapes.add(shape=geometry, color=color, face_color=color, layer=0))
# return plot_elements
def on_shape_complete(self): def on_shape_complete(self):
self.app.log.debug("on_shape_complete()") self.app.log.debug("on_shape_complete()")