Bläddra i källkod

- in Gerber Editor made the selection multithreaded in a bid to get more performance but until Shapely will start working on vectorized geometry this don't yield too much improvement

Marius Stanciu 5 år sedan
förälder
incheckning
f1107fbd3b
3 ändrade filer med 199 tillägg och 52 borttagningar
  1. 4 0
      CHANGELOG.md
  2. 75 52
      appEditors/AppGerberEditor.py
  3. 120 0
      make_freezed.py

+ 4 - 0
CHANGELOG.md

@@ -7,6 +7,10 @@ CHANGELOG for FlatCAM beta
 
 =================================================
 
+6.11.2020
+
+- in Gerber Editor made the selection multithreaded in a bid to get more performance but until Shapely will start working on vectorized geometry this don't yield too much improvement
+
 5.11.2020
 
 - fixed the annotation plotting in the CNCJob object

+ 75 - 52
appEditors/AppGerberEditor.py

@@ -2397,9 +2397,12 @@ class EraserEditorGrb(ShapeToolEditorGrb):
         return DrawToolUtilityShape(geo_list)
 
 
-class SelectEditorGrb(DrawTool):
+class SelectEditorGrb(QtCore.QObject, DrawTool):
+    selection_triggered = QtCore.pyqtSignal(object)
+
     def __init__(self, draw_app):
-        DrawTool.__init__(self, draw_app)
+        super().__init__(draw_app=draw_app)
+        # DrawTool.__init__(self, draw_app)
         self.name = 'select'
         self.origin = None
 
@@ -2417,6 +2420,9 @@ class SelectEditorGrb(DrawTool):
         # here store the selected apertures
         self.sel_aperture = []
 
+        # multiprocessing results
+        self.results = []
+
         try:
             self.draw_app.ui.apertures_table.clearSelection()
         except Exception as e:
@@ -2432,16 +2438,16 @@ class SelectEditorGrb(DrawTool):
             log.debug("AppGerberEditor.SelectEditorGrb --> %s" % str(e))
 
         try:
-            self.draw_app.selection_triggered.disconnect()
+            self.selection_triggered.disconnect()
         except (TypeError, AttributeError):
             pass
-        self.draw_app.selection_triggered.connect(self.selection_worker)
+        self.selection_triggered.connect(self.selection_worker)
 
         try:
             self.draw_app.plot_object.disconnect()
         except (TypeError, AttributeError):
             pass
-        self.draw_app.plot_object.connect(self.clean_up)
+        self.draw_app.plot_object.connect(self.after_selection)
 
     def set_origin(self, origin):
         self.origin = origin
@@ -2476,64 +2482,82 @@ class SelectEditorGrb(DrawTool):
             self.draw_app.selected.clear()
             self.sel_aperture.clear()
 
-        self.draw_app.selection_triggered.emit(point)
+        self.selection_triggered.emit(point)
 
     def selection_worker(self, point):
         def job_thread(editor_obj):
+            self.results = []
             with editor_obj.app.proc_container.new('%s' % _("Working ...")):
-                brake_flag = False
-                for storage_key, storage_val in editor_obj.storage_dict.items():
-                    for shape_stored in storage_val['geometry']:
-                        if 'solid' in shape_stored.geo:
-                            geometric_data = shape_stored.geo['solid']
-                            if Point(point).intersects(geometric_data):
-                                if shape_stored in editor_obj.selected:
-                                    editor_obj.selected.remove(shape_stored)
-                                else:
-                                    # add the object to the selected shapes
-                                    editor_obj.selected.append(shape_stored)
-                                brake_flag = True
-                                break
-                    if brake_flag is True:
-                        break
+                for ap_key, storage_val in editor_obj.storage_dict.items():
+                    self.results.append(
+                        editor_obj.pool.apply_async(self.check_intersection, args=(ap_key, storage_val, point))
+                    )
 
-                # ######################################################################################################
-                # select the aperture in the Apertures Table that is associated with the selected shape
-                # ######################################################################################################
-                self.sel_aperture.clear()
-                editor_obj.ui.apertures_table.clearSelection()
+                output = []
+                for p in self.results:
+                    output.append(p.get())
 
-                # disconnect signal when clicking in the table
-                try:
-                    editor_obj.ui.apertures_table.cellPressed.disconnect()
-                except Exception as e:
-                    log.debug("AppGerberEditor.SelectEditorGrb.click_release() --> %s" % str(e))
-
-                brake_flag = False
-                for shape_s in editor_obj.selected:
-                    for storage in editor_obj.storage_dict:
-                        if shape_s in editor_obj.storage_dict[storage]['geometry']:
-                            self.sel_aperture.append(storage)
-                            brake_flag = True
-                            break
-                    if brake_flag is True:
-                        break
+                for ret_val in output:
+                    if ret_val:
+                        k = ret_val[0]
+                        idx = ret_val[1]
+                        shape_stored = editor_obj.storage_dict[k]['geometry'][idx]
 
-                # actual row selection is done here
-                for aper in self.sel_aperture:
-                    for row in range(editor_obj.ui.apertures_table.rowCount()):
-                        if str(aper) == editor_obj.ui.apertures_table.item(row, 1).text():
-                            if not editor_obj.ui.apertures_table.item(row, 0).isSelected():
-                                editor_obj.ui.apertures_table.selectRow(row)
-                                editor_obj.last_aperture_selected = aper
-
-                # reconnect signal when clicking in the table
-                editor_obj.ui.apertures_table.cellPressed.connect(editor_obj.on_row_selected)
+                        if shape_stored in editor_obj.selected:
+                            editor_obj.selected.remove(shape_stored)
+                        else:
+                            # add the object to the selected shapes
+                            editor_obj.selected.append(shape_stored)
 
                 editor_obj.plot_object.emit(None)
 
         self.draw_app.app.worker_task.emit({'fcn': job_thread, 'params': [self.draw_app]})
 
+    @staticmethod
+    def check_intersection(ap_key, ap_storage, point):
+        for idx, shape_stored in enumerate(ap_storage['geometry']):
+            if 'solid' in shape_stored.geo:
+                geometric_data = shape_stored.geo['solid']
+                if Point(point).intersects(geometric_data):
+                    return ap_key, idx
+
+    def after_selection(self):
+        # ######################################################################################################
+        # select the aperture in the Apertures Table that is associated with the selected shape
+        # ######################################################################################################
+        self.sel_aperture.clear()
+        self.draw_app.ui.apertures_table.clearSelection()
+
+        # disconnect signal when clicking in the table
+        try:
+            self.draw_app.ui.apertures_table.cellPressed.disconnect()
+        except Exception as e:
+            log.debug("AppGerberEditor.SelectEditorGrb.click_release() --> %s" % str(e))
+
+        brake_flag = False
+        for shape_s in self.draw_app.selected:
+            for storage in self.draw_app.storage_dict:
+                if shape_s in self.draw_app.storage_dict[storage]['geometry']:
+                    self.sel_aperture.append(storage)
+                    brake_flag = True
+                    break
+            if brake_flag is True:
+                break
+
+        # actual row selection is done here
+        for aper in self.sel_aperture:
+            for row in range(self.draw_app.ui.apertures_table.rowCount()):
+                if str(aper) == self.draw_app.ui.apertures_table.item(row, 1).text():
+                    if not self.draw_app.ui.apertures_table.item(row, 0).isSelected():
+                        self.draw_app.ui.apertures_table.selectRow(row)
+                        self.draw_app.last_aperture_selected = aper
+
+        # reconnect signal when clicking in the table
+        self.draw_app.ui.apertures_table.cellPressed.connect(self.draw_app.on_row_selected)
+
+        # and plot all
+        self.draw_app.plot_all()
+
     def clean_up(self):
         self.draw_app.plot_all()
 
@@ -2563,7 +2587,6 @@ class AppGerberEditor(QtCore.QObject):
     # plot_finished = QtCore.pyqtSignal()
     mp_finished = QtCore.pyqtSignal(list)
 
-    selection_triggered = QtCore.pyqtSignal(object)
     plot_object = QtCore.pyqtSignal(object)
 
     def __init__(self, app):

+ 120 - 0
make_freezed.py

@@ -0,0 +1,120 @@
+# ##########################################################
+# FlatCAM: 2D Post-processing for Manufacturing            #
+# http://flatcam.org                                       #
+# Author: Juan Pablo Caram (c)                             #
+# Date: 12/20/2018                                         #
+# MIT Licence                                              #
+#                                                          #
+# Creates a portable copy of FlatCAM, including Python     #
+# itself and all dependencies.                             #
+#                                                          #
+# This is not an aid to install FlatCAM from source on     #
+# Windows platforms. It is only useful when FlatCAM is up  #
+# and running and ready to be packaged.                    #
+# ##########################################################
+
+# ##########################################################
+# File Modified: Marius Adrian Stanciu                     #
+# Date: 3/10/2019                                          #
+# ##########################################################
+
+
+# Files not needed: Qt, tk.dll, tcl.dll, tk/, tcl/, vtk/,
+#   scipy.lib.lapack.flapack.pyd, scipy.lib.blas.fblas.pyd,
+#   numpy.core._dotblas.pyd, scipy.sparse.sparsetools._bsr.pyd,
+#   scipy.sparse.sparsetools._csr.pyd, scipy.sparse.sparsetools._csc.pyd,
+#   scipy.sparse.sparsetools._coo.pyd
+
+import os
+import site
+import sys
+import platform
+from cx_Freeze import setup, Executable
+
+# this is done to solve the tkinter not being found
+PYTHON_INSTALL_DIR = os.path.dirname(os.path.dirname(os.__file__))
+os.environ['TCL_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tcl8.6')
+os.environ['TK_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tk8.6')
+
+# Get the site-package folder, not everybody will install
+# Python into C:\PythonXX
+site_dir = site.getsitepackages()[1]
+
+include_files = []
+
+include_files.append((os.path.join(site_dir, "shapely"), "shapely"))
+include_files.append((os.path.join(site_dir, "svg"), "svg"))
+include_files.append((os.path.join(site_dir, "svg/path"), "svg"))
+include_files.append((os.path.join(site_dir, "vispy"), "vispy"))
+include_files.append((os.path.join(site_dir, "vispy/app"), "vispy/app"))
+include_files.append((os.path.join(site_dir, "vispy/app/backends"), "vispy/app/backends"))
+# include_files.append((os.path.join(site_dir, "matplotlib"), "matplotlib"))
+include_files.append((os.path.join(site_dir, "rtree"), "rtree"))
+
+if platform.architecture()[0] == '64bit':
+    include_files.append((os.path.join(site_dir, "google"), "google"))
+    include_files.append((os.path.join(site_dir, "google/protobuf"), "google/protobuf"))
+    include_files.append((os.path.join(site_dir, "ortools"), "ortools"))
+
+include_files.append(("locale", "lib/locale"))
+include_files.append(("preprocessors", "lib/preprocessors"))
+# include_files.append(("assets", "lib/assets"))
+include_files.append(("assets/examples", "lib/assets/examples"))
+include_files.append(("assets/linux", "lib/assets/linux"))
+include_files.append(("assets/resources", "lib/assets/resources"))
+# include_files.append(("share", "lib/share"))
+include_files.append(("appGUI/VisPyData", "lib/vispy"))
+include_files.append(("config", "lib/config"))
+
+include_files.append(("README.md", "README.md"))
+include_files.append(("LICENSE", "LICENSE"))
+include_files.append(("CHANGELOG.md", "CHANGELOG.md"))
+base = None
+
+# Lets not open the console while running the app
+if sys.platform == "win32":
+    base = "Win32GUI"
+
+if platform.architecture()[0] == '64bit':
+    buildOptions = dict(
+        include_files=include_files,
+        excludes=['scipy', 'pytz', "matplotlib.tests", "numpy.random._examples"],
+        # packages=['OpenGL','numpy','vispy','ortools','google']
+        # packages=['numpy','google', 'rasterio'] # works for Python 3.7
+        packages=['opengl', 'numpy', 'google', 'rasterio'],   # works for Python 3.6.5 and Python 3.7.1
+    )
+else:
+    buildOptions = dict(
+        include_files=include_files,
+        excludes=['scipy', 'pytz'],
+        # packages=['OpenGL','numpy','vispy','ortools','google']
+        # packages=['numpy', 'rasterio']  # works for Python 3.7
+        packages=['opengl', 'numpy', 'rasterio'],   # works for Python 3.6.5 and Python 3.7.1
+    )
+
+if sys.platform == "win32":
+    buildOptions["include_msvcr"] = True
+
+print("INCLUDE_FILES", include_files)
+
+
+def getTargetName():
+    my_OS = platform.system()
+    if my_OS == 'Linux':
+        return "FlatCAM"
+    elif my_OS == 'Windows':
+        return "FlatCAM.exe"
+    else:
+        return "FlatCAM.dmg"
+
+
+exe = Executable("FlatCAM.py", icon='assets/resources/flatcam_icon48.ico', base=base, targetName=getTargetName())
+
+setup(
+    name="FlatCAM",
+    author="Community effort",
+    version="8.9",
+    description="FlatCAM Evo: 2D Computer Aided PCB Manufacturing",
+    options=dict(build_exe=buildOptions),
+    executables=[exe]
+)