Просмотр исходного кода

- Gerber Editor: made geometry transfer (which is slow) to Editor to be multithreaded
- Gerber Editor: plotting process is showed in the status bar

Marius Stanciu 6 лет назад
Родитель
Сommit
cefb74d792
4 измененных файлов с 88 добавлено и 48 удалено
  1. 8 2
      FlatCAMApp.py
  2. 13 0
      ObjectCollection.py
  3. 5 0
      README.md
  4. 62 46
      flatcamEditors/FlatCAMGrbEditor.py

+ 8 - 2
FlatCAMApp.py

@@ -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.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):
+        """
+        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()))

+ 13 - 0
ObjectCollection.py

@@ -240,6 +240,9 @@ class ObjectCollection(QtCore.QAbstractItemModel):
         # tasks know that they have to wait until available.
         self.promises = set()
 
+        # same as above only for objects that are plotted
+        self.plot_promises = set()
+
         self.app = app
 
         ### View
@@ -275,6 +278,16 @@ class ObjectCollection(QtCore.QAbstractItemModel):
     def has_promises(self):
         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):
         FlatCAMApp.App.log.debug("Mouse button pressed on list")
 

+ 5 - 0
README.md

@@ -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
 
 - added support for Gerber format specification D (no zero suppression) - PCBWizard Gerber files support

+ 62 - 46
flatcamEditors/FlatCAMGrbEditor.py

@@ -7,6 +7,7 @@ import shapely.affinity as affinity
 
 from numpy import arctan2, Inf, array, sqrt, sign, dot
 from rtree import index as rtindex
+import threading, time
 
 from camlib import *
 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
         # and then add it to the storage elements (each storage elements is a member of a list
-        for apid in self.gerber_obj.apertures:
-            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
 
-        self.replot()
+        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:
+            self.app.worker_task.emit({'fcn': job_thread, 'params': [apid]})
+            self.app.collection.plot_promise(apid)
 
-        # 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)
+        self.start_delayed_plot(check_period=0.5)
 
     def update_fcgerber(self, exc_obj):
         """
@@ -1845,25 +1851,56 @@ class FlatCAMGrbEditor(QtCore.QObject):
         :return: None
         :rtype: None
         """
-        # self.app.log.debug("plot_all()")
-        self.shapes.clear(update=True)
+        with self.app.proc_container.new("Plotting"):
+            # self.app.log.debug("plot_all()")
+            self.shapes.clear(update=True)
 
-        for storage in self.storage_dict:
-            for shape_plus in self.storage_dict[storage].get_objects():
-                if shape_plus.geo is None:
-                    continue
+            for storage in self.storage_dict:
+                for shape in self.storage_dict[storage].get_objects():
+                    if shape.geo is None:
+                        continue
+
+                    if shape in self.selected:
+                        self.plot_shape(geometry=shape.geo, color=self.app.defaults['global_sel_draw_color'],
+                                        linewidth=2)
+                        continue
+                    self.plot_shape(geometry=shape.geo, color=self.app.defaults['global_draw_color'])
+
+            for shape in self.utility:
+                self.plot_shape(geometry=shape.geo, linewidth=1)
+                continue
 
-                if shape_plus in self.selected:
-                    self.plot_shape(geometry=shape_plus.geo, color=self.app.defaults['global_sel_draw_color'],
-                                    linewidth=2)
-                    continue
-                self.plot_shape(geometry=shape_plus.geo, color=self.app.defaults['global_draw_color'])
+            self.shapes.redraw()
 
-        for shape in self.utility:
-            self.plot_shape(geometry=shape.geo, linewidth=1)
-            continue
+    def start_delayed_plot(self, check_period):
+        self.plot_thread = threading.Thread(target=lambda: self.check_plot_finished(check_period))
+        self.plot_thread.start()
 
-        self.shapes.redraw()
+    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):
         """
@@ -1887,27 +1924,6 @@ class FlatCAMGrbEditor(QtCore.QObject):
                 return
             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):
         self.app.log.debug("on_shape_complete()")