浏览代码

- enhanced the Tool Film adding the Film adjustments and added the GUI in Preferences
- set the GUI layout in Preferences for a new category named Tools 2

Marius Stanciu 6 年之前
父节点
当前提交
b00c1018e4
共有 53 个文件被更改,包括 748 次插入197 次删除
  1. 52 9
      FlatCAMApp.py
  2. 6 2
      FlatCAMObj.py
  3. 0 1
      FlatCAMTranslation.py
  4. 5 4
      ObjectCollection.py
  5. 2 0
      README.md
  6. 49 17
      camlib.py
  7. 0 1
      flatcamEditors/FlatCAMExcEditor.py
  8. 0 1
      flatcamEditors/FlatCAMGrbEditor.py
  9. 7 0
      flatcamEditors/FlatCAMTextEditor.py
  10. 11 0
      flatcamGUI/FlatCAMGUI.py
  11. 4 4
      flatcamGUI/GUIElements.py
  12. 4 5
      flatcamGUI/PlotCanvas.py
  13. 204 10
      flatcamGUI/PreferencesUI.py
  14. 2 2
      flatcamGUI/VisPyCanvas.py
  15. 2 2
      flatcamGUI/VisPyPatches.py
  16. 2 2
      flatcamGUI/VisPyTesselators.py
  17. 2 2
      flatcamGUI/VisPyVisuals.py
  18. 0 1
      flatcamParsers/ParseDXF.py
  19. 46 34
      flatcamParsers/ParseDXF_Spline.py
  20. 6 7
      flatcamParsers/ParseFont.py
  21. 5 3
      flatcamParsers/ParseSVG.py
  22. 2 3
      flatcamTools/ToolCalculators.py
  23. 7 0
      flatcamTools/ToolCutOut.py
  24. 2 3
      flatcamTools/ToolDistance.py
  25. 0 1
      flatcamTools/ToolDistanceMin.py
  26. 206 21
      flatcamTools/ToolFilm.py
  27. 2 3
      flatcamTools/ToolImage.py
  28. 0 1
      flatcamTools/ToolMove.py
  29. 2 3
      flatcamTools/ToolNonCopperClear.py
  30. 0 1
      flatcamTools/ToolOptimal.py
  31. 2 3
      flatcamTools/ToolPDF.py
  32. 0 1
      flatcamTools/ToolPaint.py
  33. 2 3
      flatcamTools/ToolPanelize.py
  34. 2 3
      flatcamTools/ToolPcbWizard.py
  35. 2 3
      flatcamTools/ToolProperties.py
  36. 20 18
      flatcamTools/ToolRulesCheck.py
  37. 2 2
      flatcamTools/ToolShell.py
  38. 2 3
      flatcamTools/ToolSolderPaste.py
  39. 2 3
      flatcamTools/ToolSub.py
  40. 2 3
      flatcamTools/ToolTransform.py
  41. 5 5
      make_win.py
  42. 7 0
      tclCommands/TclCommandClearShell.py
  43. 7 0
      tclCommands/TclCommandGetSys.py
  44. 7 0
      tclCommands/TclCommandListSys.py
  45. 7 0
      tclCommands/TclCommandMillDrills.py
  46. 7 0
      tclCommands/TclCommandMillSlots.py
  47. 7 0
      tclCommands/TclCommandNewExcellon.py
  48. 7 0
      tclCommands/TclCommandNewGerber.py
  49. 7 0
      tclCommands/TclCommandPlotObjects.py
  50. 7 0
      tclCommands/TclCommandQuit.py
  51. 7 0
      tclCommands/TclCommandSaveSys.py
  52. 7 0
      tclCommands/TclCommandSetOrigin.py
  53. 0 7
      upgrade_geos.sh

+ 52 - 9
FlatCAMApp.py

@@ -1566,6 +1566,7 @@ class App(QtCore.QObject):
         self.geo_form = None
         self.cnc_form = None
         self.tools_form = None
+        self.tools2_form = None
         self.fa_form = None
 
         self.on_options_combo_change(0)  # Will show the initial form
@@ -6000,6 +6001,7 @@ class App(QtCore.QObject):
             self.geo_form = self.ui.geometry_defaults_form
             self.cnc_form = self.ui.cncjob_defaults_form
             self.tools_form = self.ui.tools_defaults_form
+            self.tools2_form = self.ui.tools2_defaults_form
             self.fa_form = self.ui.util_defaults_form
         elif sel == 1:
             self.gen_form = self.ui.general_options_form
@@ -6008,6 +6010,7 @@ class App(QtCore.QObject):
             self.geo_form = self.ui.geometry_options_form
             self.cnc_form = self.ui.cncjob_options_form
             self.tools_form = self.ui.tools_options_form
+            self.tools2_form = self.ui.tools2_options_form
             self.fa_form = self.ui.util_options_form
         else:
             return
@@ -6054,6 +6057,13 @@ class App(QtCore.QObject):
         self.ui.tools_scroll_area.setWidget(self.tools_form)
         self.tools_form.show()
 
+        try:
+            self.ui.tools2_scroll_area.takeWidget()
+        except:
+            self.log.debug("Nothing to remove")
+        self.ui.tools2_scroll_area.setWidget(self.tools2_form)
+        self.tools2_form.show()
+
         try:
             self.ui.fa_scroll_area.takeWidget()
         except:
@@ -9697,13 +9707,13 @@ class App(QtCore.QObject):
         self.set_ui_title(name=self.project_filename)
         self.should_we_save = False
 
-    def export_svg(self, obj_name, filename, scale_factor=0.00):
+    def export_svg(self, obj_name, filename, scale_stroke_factor=0.00):
         """
         Exports a Geometry Object to an SVG file.
 
         :param obj_name: the name of the FlatCAM object to be saved as SVG
         :param filename: Path to the SVG file to save to.
-        :param scale_factor: factor by which to change/scale the thickness of the features
+        :param scale_stroke_factor: factor by which to change/scale the thickness of the features
         :return:
         """
         self.report_usage("export_svg()")
@@ -9720,7 +9730,7 @@ class App(QtCore.QObject):
             return "Could not retrieve object: %s" % obj_name
 
         with self.proc_container.new(_("Exporting SVG")) as proc:
-            exported_svg = obj.export_svg(scale_factor=scale_factor)
+            exported_svg = obj.export_svg(scale_stroke_factor=scale_stroke_factor)
 
             # Determine bounding area for svg export
             bounds = obj.bounds()
@@ -9763,7 +9773,12 @@ class App(QtCore.QObject):
             self.inform.emit('[success] %s: %s' %
                              (_("SVG file exported to"), filename))
 
-    def export_svg_negative(self, obj_name, box_name, filename, boundary, scale_factor=0.00, use_thread=True):
+    def export_svg_negative(self, obj_name, box_name, filename, boundary,
+                            scale_stroke_factor=0.00,
+                            scale_factor_x=None, scale_factor_y=None,
+                            skew_factor_x=None, skew_factor_y=None, skew_reference='center',
+                            mirror=None,
+                            use_thread=True):
         """
         Exports a Geometry Object to an SVG file in negative.
 
@@ -9771,7 +9786,14 @@ class App(QtCore.QObject):
         :param box_name: the name of the FlatCAM object to be used as delimitation of the content to be saved
         :param filename: Path to the SVG file to save to.
         :param boundary: thickness of a black border to surround all the features
-        :param scale_factor: factor by which to change/scale the thickness of the features
+        :param scale_stroke_factor: factor by which to change/scale the thickness of the features
+        :param scale_factor_x: factor to scale the svg geometry on the X axis
+        :param scale_factor_y: factor to scale the svg geometry on the Y axis
+        :param skew_factor_x: factor to skew the svg geometry on the X axis
+        :param skew_factor_y: factor to skew the svg geometry on the Y axis
+        :param skew_reference: reference to use for skew. Can be 'bottomleft', 'bottomright', 'topleft', 'topright' and
+        those are the 4 points of the bounding box of the geometry to be skewed.
+        :param mirror: can be 'x' or 'y' or 'both'. Axis on which to mirror the svg geometry
         :param use_thread: if to be run in a separate thread; boolean
         :return:
         """
@@ -9800,7 +9822,11 @@ class App(QtCore.QObject):
             box = obj
 
         def make_negative_film():
-            exported_svg = obj.export_svg(scale_factor=scale_factor)
+            exported_svg = obj.export_svg(scale_stroke_factor=scale_stroke_factor,
+                                          scale_factor_x=scale_factor_x, scale_factor_y=scale_factor_y,
+                                          skew_factor_x=skew_factor_x, skew_factor_y=skew_factor_y,
+                                          mirror=mirror
+                                          )
 
             # Determine bounding area for svg export
             bounds = box.bounds()
@@ -9889,14 +9915,27 @@ class App(QtCore.QObject):
         else:
             make_negative_film()
 
-    def export_svg_positive(self, obj_name, box_name, filename, scale_factor=0.00, use_thread=True):
+    def export_svg_positive(self, obj_name, box_name, filename,
+                            scale_stroke_factor=0.00,
+                            scale_factor_x=None, scale_factor_y=None,
+                            skew_factor_x=None, skew_factor_y=None, skew_reference='center',
+                            mirror=None,
+                            use_thread=True):
         """
         Exports a Geometry Object to an SVG file in positive black.
 
         :param obj_name: the name of the FlatCAM object to be saved as SVG
         :param box_name: the name of the FlatCAM object to be used as delimitation of the content to be saved
         :param filename: Path to the SVG file to save to.
-        :param scale_factor: factor by which to change/scale the thickness of the features
+        :param scale_stroke_factor: factor by which to change/scale the thickness of the features
+        :param scale_factor_x: factor to scale the svg geometry on the X axis
+        :param scale_factor_y: factor to scale the svg geometry on the Y axis
+        :param skew_factor_x: factor to skew the svg geometry on the X axis
+        :param skew_factor_y: factor to skew the svg geometry on the Y axis
+        :param skew_reference: reference to use for skew. Can be 'bottomleft', 'bottomright', 'topleft', 'topright' and
+        those are the 4 points of the bounding box of the geometry to be skewed.
+        :param mirror: can be 'x' or 'y' or 'both'. Axis on which to mirror the svg geometry
+
         :param use_thread: if to be run in a separate thread; boolean
         :return:
         """
@@ -9925,7 +9964,11 @@ class App(QtCore.QObject):
             box = obj
 
         def make_positive_film():
-            exported_svg = obj.export_svg(scale_factor=scale_factor)
+            exported_svg = obj.export_svg(scale_stroke_factor=scale_stroke_factor,
+                                          scale_factor_x=scale_factor_x, scale_factor_y=scale_factor_y,
+                                          skew_factor_x=skew_factor_x, skew_factor_y=skew_factor_y,
+                                          mirror=mirror
+                                          )
 
             self.progress.emit(40)
 

+ 6 - 2
FlatCAMObj.py

@@ -1,10 +1,14 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # http://flatcam.org                                       #
 # Author: Juan Pablo Caram (c)                             #
 # Date: 2/5/2014                                           #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
+
+# ##########################################################
+# File modified by: Marius Stanciu                         #
+# ##########################################################
 
 from PyQt5.QtCore import Qt
 from PyQt5.QtGui import QTextDocument

+ 0 - 1
FlatCAMTranslation.py

@@ -1,6 +1,5 @@
 # ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 3/10/2019                                          #
 # MIT Licence                                              #

+ 5 - 4
ObjectCollection.py

@@ -1,14 +1,15 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # http://flatcam.org                                       #
 # Author: Juan Pablo Caram (c)                             #
 # Date: 2/5/2014                                           #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
-# ########################################################## ##
+# ##########################################################
 # File modified by: Dennis Hayrullin                       #
-# ########################################################## ##
+# File modified by: Marius Stanciu                         #
+# ##########################################################
 
 # from PyQt5.QtCore import QModelIndex
 from FlatCAMObj import *

+ 2 - 0
README.md

@@ -15,6 +15,8 @@ CAD program, and create G-Code for Isolation routing.
 - fixed the Export PNG function when using the 2D legacy graphic engine
 - added a new capability to toggle the grid lines for both graphic engines: menu link in View and key shortcut combo ALT+G
 - changed the grid colors for 3D graphic engine when in Dark mode
+- enhanced the Tool Film adding the Film adjustments and added the GUI in Preferences
+- set the GUI layout in Preferences for a new category named Tools 2
 
 12.10.2019
 

+ 49 - 17
camlib.py

@@ -1836,37 +1836,69 @@ class Geometry(object):
         """
         self.solid_geometry = [cascaded_union(self.solid_geometry)]
 
-    def export_svg(self, scale_factor=0.00):
+    def export_svg(self, scale_stroke_factor=0.00,
+                   scale_factor_x=None, scale_factor_y=None,
+                   skew_factor_x=None, skew_factor_y=None,
+                   skew_reference='center',
+                   mirror=None):
         """
         Exports the Geometry Object as a SVG Element
 
         :return: SVG Element
         """
 
-        # Make sure we see a Shapely Geometry class and not a list
+        geom = None
 
+        # Make sure we see a Shapely Geometry class and not a list
         if str(type(self)) == "<class 'FlatCAMObj.FlatCAMGeometry'>":
             flat_geo = []
             if self.multigeo:
                 for tool in self.tools:
                     flat_geo += self.flatten(self.tools[tool]['solid_geometry'])
-                geom = cascaded_union(flat_geo)
+                geom_svg = cascaded_union(flat_geo)
             else:
-                geom = cascaded_union(self.flatten())
+                geom_svg = cascaded_union(self.flatten())
         else:
-            geom = cascaded_union(self.flatten())
+            geom_svg = cascaded_union(self.flatten())
+
+        skew_ref = 'center'
+        if skew_reference != 'center':
+            xmin, ymin, xmax, ymax = geom_svg.bounds
+            if skew_reference == 'topleft':
+                skew_ref = (xmin, ymax)
+            elif skew_reference == 'bottomleft':
+                skew_ref = (xmin, ymin)
+            elif skew_reference == 'topright':
+                skew_ref = (xmax, ymax)
+            elif skew_reference == 'bottomright':
+                skew_ref = (xmax, ymin)
+
+        if scale_factor_x:
+            geom = affinity.scale(geom_svg, scale_factor_x, 1.0)
+        if scale_factor_y:
+            geom = affinity.scale(geom_svg, 1.0, scale_factor_y)
+        if skew_factor_x:
+            geom = affinity.skew(geom_svg, skew_factor_x, 0.0, origin=skew_ref)
+        if skew_factor_y:
+            geom = affinity.skew(geom_svg, 0.0, skew_factor_y, origin=skew_ref)
+        if mirror:
+            if mirror == 'x':
+                geom = affinity.scale(geom_svg, 1.0, -1.0)
+            if mirror == 'y':
+                geom = affinity.scale(geom_svg, -1.0, 1.0)
+            if mirror == 'both':
+                geom = affinity.scale(geom_svg, -1.0, -1.0)
 
         # scale_factor is a multiplication factor for the SVG stroke-width used within shapely's svg export
-
-        # If 0 or less which is invalid then default to 0.05
+        # If 0 or less which is invalid then default to 0.01
         # This value appears to work for zooming, and getting the output svg line width
         # to match that viewed on screen with FlatCam
         # MS: I choose a factor of 0.01 so the scale is right for PCB UV film
-        if scale_factor <= 0:
-            scale_factor = 0.01
+        if scale_stroke_factor <= 0:
+            scale_stroke_factor = 0.01
 
         # Convert to a SVG
-        svg_elem = geom.svg(scale_factor=scale_factor)
+        svg_elem = geom.svg(scale_factor=scale_stroke_factor)
         return svg_elem
 
     def mirror(self, axis, point):
@@ -4599,7 +4631,7 @@ class CNCjob(Geometry):
         gcode += self.doformat(p.lift_code, x=first_x, y=first_y)  # Stop cutting
         return gcode
 
-    def export_svg(self, scale_factor=0.00):
+    def export_svg(self, scale_stroke_factor=0.00):
         """
         Exports the CNC Job as a SVG Element
 
@@ -4611,14 +4643,14 @@ class CNCjob(Geometry):
         # This way what is on screen will match what is outputed for the svg
         # This is quite a useful feature for svg's used with visicut
 
-        if scale_factor <= 0:
-            scale_factor = self.options['tooldia'] / 2
+        if scale_stroke_factor <= 0:
+            scale_stroke_factor = self.options['tooldia'] / 2
 
         # If still 0 then default to 0.05
         # This value appears to work for zooming, and getting the output svg line width
         # to match that viewed on screen with FlatCam
-        if scale_factor == 0:
-            scale_factor = 0.01
+        if scale_stroke_factor == 0:
+            scale_stroke_factor = 0.01
 
         # Separate the list of cuts and travels into 2 distinct lists
         # This way we can add different formatting / colors to both
@@ -4651,9 +4683,9 @@ class CNCjob(Geometry):
         # It's better to have the travels sitting underneath the cuts for visicut
         svg_elem = ""
         if travels:
-            svg_elem = travelsgeom.svg(scale_factor=scale_factor, stroke_color="#F0E24D")
+            svg_elem = travelsgeom.svg(scale_factor=scale_stroke_factor, stroke_color="#F0E24D")
         if cuts:
-            svg_elem += cutsgeom.svg(scale_factor=scale_factor, stroke_color="#5E6CFF")
+            svg_elem += cutsgeom.svg(scale_factor=scale_stroke_factor, stroke_color="#5E6CFF")
 
         return svg_elem
 

+ 0 - 1
flatcamEditors/FlatCAMExcEditor.py

@@ -1,6 +1,5 @@
 # ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 8/17/2019                                          #
 # MIT Licence                                              #

+ 0 - 1
flatcamEditors/FlatCAMGrbEditor.py

@@ -1,6 +1,5 @@
 # ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 8/17/2019                                          #
 # MIT Licence                                              #

+ 7 - 0
flatcamEditors/FlatCAMTextEditor.py

@@ -1,3 +1,10 @@
+# ##########################################################
+# FlatCAM: 2D Post-processing for Manufacturing            #
+# File Author: Marius Adrian Stanciu (c)                   #
+# Date: 10/10/2019                                         #
+# MIT Licence                                              #
+# ##########################################################
+
 from flatcamGUI.GUIElements import *
 from PyQt5 import QtPrintSupport
 

+ 11 - 0
flatcamGUI/FlatCAMGUI.py

@@ -1027,6 +1027,15 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         self.tools_scroll_area = QtWidgets.QScrollArea()
         self.tools_tab_lay.addWidget(self.tools_scroll_area)
 
+        self.tools2_tab = QtWidgets.QWidget()
+        self.pref_tab_area.addTab(self.tools2_tab, _("TOOLS 2"))
+        self.tools2_tab_lay = QtWidgets.QVBoxLayout()
+        self.tools2_tab_lay.setContentsMargins(2, 2, 2, 2)
+        self.tools2_tab.setLayout(self.tools2_tab_lay)
+
+        self.tools2_scroll_area = QtWidgets.QScrollArea()
+        self.tools2_tab_lay.addWidget(self.tools2_scroll_area)
+
         self.fa_tab = QtWidgets.QWidget()
         self.fa_tab.setObjectName("fa_tab")
         self.pref_tab_area.addTab(self.fa_tab, _("UTILITIES"))
@@ -1980,6 +1989,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         self.geometry_defaults_form = GeometryPreferencesUI()
         self.cncjob_defaults_form = CNCJobPreferencesUI()
         self.tools_defaults_form = ToolsPreferencesUI()
+        self.tools2_defaults_form = Tools2PreferencesUI()
         self.util_defaults_form = UtilPreferencesUI()
 
         self.general_options_form = GeneralPreferencesUI()
@@ -1988,6 +1998,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         self.geometry_options_form = GeometryPreferencesUI()
         self.cncjob_options_form = CNCJobPreferencesUI()
         self.tools_options_form = ToolsPreferencesUI()
+        self.tools2_options_form = Tools2PreferencesUI()
         self.util_options_form = UtilPreferencesUI()
 
         QtWidgets.qApp.installEventFilter(self)

+ 4 - 4
flatcamGUI/GUIElements.py

@@ -1,15 +1,15 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # http://flatcam.org                                       #
 # Author: Juan Pablo Caram (c)                             #
 # Date: 2/5/2014                                           #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
-# ########################################################## ##
+# ##########################################################
 # File Modified (major mod): Marius Adrian Stanciu         #
 # Date: 3/10/2019                                          #
-# ########################################################## ##
+# ##########################################################
 
 from PyQt5 import QtGui, QtCore, QtWidgets
 from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot

+ 4 - 5
flatcamGUI/PlotCanvas.py

@@ -1,10 +1,9 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://caram.cl/software/flatcam                         #
-# Author: Juan Pablo Caram (c)                             #
-# Date: 2/5/2014                                           #
+# Author: Dennis Hayrullin (c)                             #
+# Date: 2016                                               #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 from PyQt5 import QtCore
 

+ 204 - 10
flatcamGUI/PreferencesUI.py

@@ -1,3 +1,10 @@
+# ##########################################################
+# FlatCAM: 2D Post-processing for Manufacturing            #
+# File Author: Marius Adrian Stanciu (c)                   #
+# Date: 10/10/2019                                         #
+# MIT Licence                                              #
+# ##########################################################
+
 from PyQt5.QtCore import QSettings
 from flatcamGUI.GUIElements import *
 import platform
@@ -184,12 +191,46 @@ class ToolsPreferencesUI(QtWidgets.QWidget):
 
         self.vlay2 = QtWidgets.QVBoxLayout()
         self.vlay2.addWidget(self.tools_panelize_group)
-        self.vlay2.addWidget(self.tools_calculators_group)
+        self.vlay2.addWidget(self.tools_sub_group)
+        self.vlay2.addWidget(self.tools_film_group)
 
         self.vlay3 = QtWidgets.QVBoxLayout()
         self.vlay3.addWidget(self.tools_solderpaste_group)
-        self.vlay3.addWidget(self.tools_sub_group)
-        self.vlay3.addWidget(self.tools_film_group)
+        self.vlay3.addWidget(self.tools_calculators_group)
+
+        self.layout.addLayout(self.vlay)
+        self.layout.addLayout(self.vlay1)
+        self.layout.addLayout(self.vlay2)
+        self.layout.addLayout(self.vlay3)
+
+        self.layout.addStretch()
+
+
+class Tools2PreferencesUI(QtWidgets.QWidget):
+
+    def __init__(self, parent=None):
+        QtWidgets.QWidget.__init__(self, parent=parent)
+        self.layout = QtWidgets.QHBoxLayout()
+        self.setLayout(self.layout)
+
+        self.tools2_checkrules = Tools2RulesCheckPrefGroupUI()
+        self.tools2_checkrules.setMinimumWidth(220)
+
+        self.tools2_optimal = Tools2OptimalPrefGroupUI()
+        self.tools2_optimal.setMinimumWidth(220)
+
+        self.vlay = QtWidgets.QVBoxLayout()
+        self.vlay.addWidget(self.tools2_checkrules)
+        self.vlay.addWidget(self.tools2_optimal)
+
+        self.vlay1 = QtWidgets.QVBoxLayout()
+
+
+        self.vlay2 = QtWidgets.QVBoxLayout()
+
+
+        self.vlay3 = QtWidgets.QVBoxLayout()
+
 
         self.layout.addLayout(self.vlay)
         self.layout.addLayout(self.vlay1)
@@ -4233,8 +4274,9 @@ class ToolsFilmPrefGroupUI(OptionsGroupUI):
         super(ToolsFilmPrefGroupUI, self).__init__(self)
 
         self.setTitle(str(_("Film Tool Options")))
+        self.decimals = 4
 
-        # ## Board cuttout
+        # ## Parameters
         self.film_label = QtWidgets.QLabel("<b>%s:</b>" % _("Parameters"))
         self.film_label.setToolTip(
             _("Create a PCB film from a Gerber or Geometry\n"
@@ -4305,6 +4347,114 @@ class ToolsFilmPrefGroupUI(OptionsGroupUI):
         grid0.addWidget(self.film_scale_label, 3, 0)
         grid0.addWidget(self.film_scale_entry, 3, 1)
 
+        self.film_adj_label = QtWidgets.QLabel('<b>%s</b>' % _("Film Adjustments"))
+        self.film_adj_label.setToolTip(
+            _("Sometime the printers will distort the print shape, especially the Laser types.\n"
+              "This section provide the tools to compensate for the print distortions.")
+        )
+
+        grid0.addWidget(self.film_adj_label, 4, 0, 1, 2)
+
+        # Scale Geometry
+        self.film_scale_cb = FCCheckBox('%s' % _("Scale Film geometry"))
+        self.film_scale_cb.setToolTip(
+            _("A value greater than 1 will stretch the film\n"
+              "while a value less than 1 will jolt it.")
+        )
+        self.film_scale_cb.setStyleSheet(
+            """
+            QCheckBox {font-weight: bold; color: black}
+            """
+        )
+        grid0.addWidget(self.film_scale_cb, 5, 0, 1, 2)
+
+        self.film_scalex_label = QtWidgets.QLabel('%s:' % _("X factor"))
+        self.film_scalex_entry = FCDoubleSpinner()
+        self.film_scalex_entry.set_range(-999.9999, 999.9999)
+        self.film_scalex_entry.set_precision(self.decimals)
+        self.film_scalex_entry.setSingleStep(0.01)
+
+        grid0.addWidget(self.film_scalex_label, 6, 0)
+        grid0.addWidget(self.film_scalex_entry, 6, 1)
+
+        self.film_scaley_label = QtWidgets.QLabel('%s:' % _("Y factor"))
+        self.film_scaley_entry = FCDoubleSpinner()
+        self.film_scaley_entry.set_range(-999.9999, 999.9999)
+        self.film_scaley_entry.set_precision(self.decimals)
+        self.film_scaley_entry.setSingleStep(0.01)
+
+        grid0.addWidget(self.film_scaley_label, 7, 0)
+        grid0.addWidget(self.film_scaley_entry, 7, 1)
+
+        # Skew Geometry
+        self.film_skew_cb = FCCheckBox('%s' % _("Skew Film geometry"))
+        self.film_skew_cb.setToolTip(
+            _("Positive values will skew to the right\n"
+              "while negative values will skew to the left.")
+        )
+        self.film_skew_cb.setStyleSheet(
+            """
+            QCheckBox {font-weight: bold; color: black}
+            """
+        )
+        grid0.addWidget(self.film_skew_cb, 8, 0, 1, 2)
+
+        self.film_skewx_label = QtWidgets.QLabel('%s:' % _("X angle"))
+        self.film_skewx_entry = FCDoubleSpinner()
+        self.film_skewx_entry.set_range(-999.9999, 999.9999)
+        self.film_skewx_entry.set_precision(self.decimals)
+        self.film_skewx_entry.setSingleStep(0.01)
+
+        grid0.addWidget(self.film_skewx_label, 9, 0)
+        grid0.addWidget(self.film_skewx_entry, 9, 1)
+
+        self.film_skewy_label = QtWidgets.QLabel('%s:' % _("Y angle"))
+        self.film_skewy_entry = FCDoubleSpinner()
+        self.film_skewy_entry.set_range(-999.9999, 999.9999)
+        self.film_skewy_entry.set_precision(self.decimals)
+        self.film_skewy_entry.setSingleStep(0.01)
+
+        grid0.addWidget(self.film_skewy_label, 10, 0)
+        grid0.addWidget(self.film_skewy_entry, 10, 1)
+
+        self.film_skew_ref_label = QtWidgets.QLabel('%s:' % _("Reference"))
+        self.film_skew_ref_label.setToolTip(
+            _("The reference point to be used as origin for the skew.\n"
+              "It can be one of the four points of the geometry bounding box.")
+        )
+        self.film_skew_reference = RadioSet([{'label': _('Bottom Left'), 'value': 'bottomleft'},
+                                             {'label': _('Top Left'), 'value': 'topleft'},
+                                             {'label': _('Bottom Right'), 'value': 'bottomright'},
+                                             {'label': _('Top right'), 'value': 'topright'}],
+                                            orientation='vertical',
+                                            stretch=False)
+
+        grid0.addWidget(self.film_skew_ref_label, 11, 0)
+        grid0.addWidget(self.film_skew_reference, 11, 1)
+
+        # Mirror Geometry
+        self.film_mirror_cb = FCCheckBox('%s' % _("Mirror Film geometry"))
+        self.film_mirror_cb.setToolTip(
+            _("Mirror the film geometry on the selected axis or on both.")
+        )
+        self.film_mirror_cb.setStyleSheet(
+            """
+            QCheckBox {font-weight: bold; color: black}
+            """
+        )
+        grid0.addWidget(self.film_mirror_cb, 12, 0, 1, 2)
+
+        self.film_mirror_axis = RadioSet([{'label': _('None'), 'value': 'none'},
+                                          {'label': _('X'), 'value': 'x'},
+                                          {'label': _('Y'), 'value': 'y'},
+                                          {'label': _('Both'), 'value': 'both'}],
+                                         stretch=False)
+        self.film_mirror_axis_label = QtWidgets.QLabel('%s:' % _("Mirror axis"))
+
+        grid0.addWidget(self.film_mirror_axis_label, 13, 0)
+        grid0.addWidget(self.film_mirror_axis, 13, 1)
+
+
         self.layout.addStretch()
 
 
@@ -4539,7 +4689,7 @@ class ToolsTransformPrefGroupUI(OptionsGroupUI):
 
         # ## Skew/Shear Angle on X axis
         self.skewx_entry = FCEntry()
-        self.skewx_label = QtWidgets.QLabel('%s:' % _("Skew_X angle"))
+        self.skewx_label = QtWidgets.QLabel('%s:' % _("X angle"))
         self.skewx_label.setToolTip(
             _("Angle for Skew action, in degrees.\n"
               "Float number between -360 and 359.")
@@ -4549,7 +4699,7 @@ class ToolsTransformPrefGroupUI(OptionsGroupUI):
 
         # ## Skew/Shear Angle on Y axis
         self.skewy_entry = FCEntry()
-        self.skewy_label = QtWidgets.QLabel('%s:' % _("Skew_Y angle"))
+        self.skewy_label = QtWidgets.QLabel('%s:' % _("Y angle"))
         self.skewy_label.setToolTip(
             _("Angle for Skew action, in degrees.\n"
               "Float number between -360 and 359.")
@@ -4559,7 +4709,7 @@ class ToolsTransformPrefGroupUI(OptionsGroupUI):
 
         # ## Scale factor on X axis
         self.scalex_entry = FCEntry()
-        self.scalex_label = QtWidgets.QLabel('%s:' % _("Scale_X factor"))
+        self.scalex_label = QtWidgets.QLabel('%s:' % _("X factor"))
         self.scalex_label.setToolTip(
             _("Factor for scaling on X axis.")
         )
@@ -4568,7 +4718,7 @@ class ToolsTransformPrefGroupUI(OptionsGroupUI):
 
         # ## Scale factor on X axis
         self.scaley_entry = FCEntry()
-        self.scaley_label = QtWidgets.QLabel('%s:' % _("Scale_Y factor"))
+        self.scaley_label = QtWidgets.QLabel('%s:' % _("Y factor"))
         self.scaley_label.setToolTip(
             _("Factor for scaling on Y axis.")
         )
@@ -4595,7 +4745,7 @@ class ToolsTransformPrefGroupUI(OptionsGroupUI):
 
         # ## Offset distance on X axis
         self.offx_entry = FCEntry()
-        self.offx_label = QtWidgets.QLabel('%s:' % _("Offset_X val"))
+        self.offx_label = QtWidgets.QLabel('%s:' % _("X val"))
         self.offx_label.setToolTip(
            _("Distance to offset on X axis. In current units.")
         )
@@ -4604,7 +4754,7 @@ class ToolsTransformPrefGroupUI(OptionsGroupUI):
 
         # ## Offset distance on Y axis
         self.offy_entry = FCEntry()
-        self.offy_label = QtWidgets.QLabel('%s:' % _("Offset_Y val"))
+        self.offy_label = QtWidgets.QLabel('%s:' % _("Y val"))
         self.offy_label.setToolTip(
             _("Distance to offset on Y axis. In current units.")
         )
@@ -4834,6 +4984,50 @@ class ToolsSubPrefGroupUI(OptionsGroupUI):
         self.layout.addStretch()
 
 
+class Tools2RulesCheckPrefGroupUI(OptionsGroupUI):
+    def __init__(self, parent=None):
+
+        super(Tools2RulesCheckPrefGroupUI, self).__init__(self)
+
+        self.setTitle(str(_("Substractor Tool Options")))
+
+        # ## Solder Paste Dispensing
+        self.sublabel = QtWidgets.QLabel("<b>%s:</b>" % _("Parameters"))
+        self.sublabel.setToolTip(
+            _("A tool to substract one Gerber or Geometry object\n"
+              "from another of the same type.")
+        )
+        self.layout.addWidget(self.sublabel)
+
+        self.close_paths_cb = FCCheckBox(_("Close paths"))
+        self.close_paths_cb.setToolTip(_("Checking this will close the paths cut by the Geometry substractor object."))
+        self.layout.addWidget(self.close_paths_cb)
+
+        self.layout.addStretch()
+
+
+class Tools2OptimalPrefGroupUI(OptionsGroupUI):
+    def __init__(self, parent=None):
+
+        super(Tools2OptimalPrefGroupUI, self).__init__(self)
+
+        self.setTitle(str(_("Substractor Tool Options")))
+
+        # ## Solder Paste Dispensing
+        self.sublabel = QtWidgets.QLabel("<b>%s:</b>" % _("Parameters"))
+        self.sublabel.setToolTip(
+            _("A tool to substract one Gerber or Geometry object\n"
+              "from another of the same type.")
+        )
+        self.layout.addWidget(self.sublabel)
+
+        self.close_paths_cb = FCCheckBox(_("Close paths"))
+        self.close_paths_cb.setToolTip(_("Checking this will close the paths cut by the Geometry substractor object."))
+        self.layout.addWidget(self.close_paths_cb)
+
+        self.layout.addStretch()
+
+
 class FAExcPrefGroupUI(OptionsGroupUI):
     def __init__(self, parent=None):
         # OptionsGroupUI.__init__(self, "Excellon File associations Preferences", parent=None)

+ 2 - 2
flatcamGUI/VisPyCanvas.py

@@ -1,10 +1,10 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # http://flatcam.org                                       #
 # File Author: Dennis Hayrullin                            #
 # Date: 2/5/2016                                           #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 import numpy as np
 from PyQt5.QtGui import QPalette

+ 2 - 2
flatcamGUI/VisPyPatches.py

@@ -1,10 +1,10 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # http://flatcam.org                                       #
 # File Author: Dennis Hayrullin                            #
 # Date: 2/5/2016                                           #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 from vispy.visuals import markers, LineVisual, InfiniteLineVisual
 from vispy.visuals.axis import Ticker, _get_ticks_talbot

+ 2 - 2
flatcamGUI/VisPyTesselators.py

@@ -1,10 +1,10 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # http://flatcam.org                                       #
 # File Author: Dennis Hayrullin                            #
 # Date: 2/5/2016                                           #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 from OpenGL import GLU
 

+ 2 - 2
flatcamGUI/VisPyVisuals.py

@@ -1,10 +1,10 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # http://flatcam.org                                       #
 # File Author: Dennis Hayrullin                            #
 # Date: 2/5/2016                                           #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 from vispy.visuals import CompoundVisual, LineVisual, MeshVisual, TextVisual, MarkersVisual
 from vispy.scene.visuals import VisualNode, generate_docstring, visuals

+ 0 - 1
flatcamParsers/ParseDXF.py

@@ -1,6 +1,5 @@
 # ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 3/10/2019                                          #
 # MIT Licence                                              #

+ 46 - 34
flatcamParsers/ParseDXF_Spline.py

@@ -2,30 +2,32 @@
 # Vasilis Vlachoudis
 # Date: 20-Oct-2015
 
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File modified: Marius Adrian Stanciu                     #
 # Date: 3/10/2019                                          #
-# ########################################################## ##
+# ##########################################################
 
 import math
 import sys
 
+
 def norm(v):
     return math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2])
 
+
 def normalize_2(v):
     m = norm(v)
     return [v[0]/m, v[1]/m, v[2]/m]
 
+
 # ------------------------------------------------------------------------------
 # Convert a B-spline to polyline with a fixed number of segments
 #
 # FIXME to become adaptive
 # ------------------------------------------------------------------------------
 def spline2Polyline(xyz, degree, closed, segments, knots):
-    '''
+    """
     :param xyz: DXF spline control points
     :param degree: degree of the Spline curve
     :param closed: closed Spline
@@ -33,7 +35,7 @@ def spline2Polyline(xyz, degree, closed, segments, knots):
     :param segments: how many lines to use for Spline approximation
     :param knots: DXF spline knots
     :return: x,y,z coordinates (each is a list)
-    '''
+    """
 
     # Check if last point coincide with the first one
     if (Vector(xyz[0]) - Vector(xyz[-1])).length2() < 1e-10:
@@ -51,16 +53,16 @@ def spline2Polyline(xyz, degree, closed, segments, knots):
 
     npts = len(xyz)
 
-    if degree<1 or degree>3:
-        #print "invalid degree"
-        return None,None,None
+    if degree < 1 or degree > 3:
+        # print "invalid degree"
+        return None, None, None
 
     # order:
     k = degree+1
 
     if npts < k:
-        #print "not enough control points"
-        return None,None,None
+        # print "not enough control points"
+        return None, None, None
 
     # resolution:
     nseg = segments * npts
@@ -72,12 +74,12 @@ def spline2Polyline(xyz, degree, closed, segments, knots):
 
     i = 1
     for pt in xyz:
-        b[i]   = pt[0]
+        b[i] = pt[0]
         b[i+1] = pt[1]
         b[i+2] = pt[2]
-        i +=3
+        i += 3
 
-    #if periodic:
+    # if periodic:
     if closed:
         _rbsplinu(npts, k, nseg, b, h, p, knots)
     else:
@@ -86,7 +88,7 @@ def spline2Polyline(xyz, degree, closed, segments, knots):
     x = []
     y = []
     z = []
-    for i in range(1,3*nseg+1,3):
+    for i in range(1, 3*nseg+1, 3):
         x.append(p[i])
         y.append(p[i+1])
         z.append(p[i+2])
@@ -94,7 +96,8 @@ def spline2Polyline(xyz, degree, closed, segments, knots):
 #    for i,xyz in enumerate(zip(x,y,z)):
 #        print i,xyz
 
-    return x,y,z
+    return x, y, z
+
 
 # ------------------------------------------------------------------------------
 # Subroutine to generate a B-spline open knot vector with multiplicity
@@ -108,12 +111,13 @@ def spline2Polyline(xyz, degree, closed, segments, knots):
 def _knot(n, order):
     x = [0.0]*(n+order+1)
     for i in range(2, n+order+1):
-        if i>order and i<n+2:
+        if order < i < n+2:
             x[i] = x[i-1] + 1.0
         else:
             x[i] = x[i-1]
     return x
 
+
 # ------------------------------------------------------------------------------
 # Subroutine to generate a B-spline uniform (periodic) knot vector.
 #
@@ -128,6 +132,7 @@ def _knotu(n, order):
         x[i] = float(i-1)
     return x
 
+
 # ------------------------------------------------------------------------------
 # Subroutine to generate rational B-spline basis functions--open knot vector
 
@@ -163,8 +168,8 @@ def _rbasis(c, t, npts, x, h, r):
             temp[i] = 0.0
 
     # calculate the higher order non-rational basis functions
-    for k in range(2,c+1):
-        for i in range(1,nplusc-k+1):
+    for k in range(2, c+1):
+        for i in range(1, nplusc-k+1):
             # if the lower order basis function is zero skip the calculation
             if temp[i] != 0.0:
                 d = ((t-x[i])*temp[i])/(x[i+k-1]-x[i])
@@ -184,7 +189,7 @@ def _rbasis(c, t, npts, x, h, r):
 
     # calculate sum for denominator of rational basis functions
     s = 0.0
-    for i in range(1,npts+1):
+    for i in range(1, npts+1):
         s += temp[i]*h[i]
 
     # form rational basis functions and put in r vector
@@ -194,6 +199,7 @@ def _rbasis(c, t, npts, x, h, r):
         else:
             r[i] = 0
 
+
 # ------------------------------------------------------------------------------
 # Generates a rational B-spline curve using a uniform open knot vector.
 #
@@ -245,11 +251,12 @@ def _rbspline(npts, k, p1, b, h, p, x):
             p[icount+j] = 0.0
             # Do local matrix multiplication
             for i in range(1, npts+1):
-                p[icount+j] +=  nbasis[i]*b[jcount]
+                p[icount+j] += nbasis[i]*b[jcount]
                 jcount += 3
         icount += 3
         t += step
 
+
 # ------------------------------------------------------------------------------
 # Subroutine to generate a rational B-spline curve using an uniform periodic knot vector
 #
@@ -296,23 +303,24 @@ def _rbsplinu(npts, k, p1, b, h, p, x=None):
         nbasis = [0.0]*(npts+1)
         _rbasis(k, t, npts, x, h, nbasis)
         # generate a point on the curve
-        for j in range(1,4):
+        for j in range(1, 4):
             jcount = j
             p[icount+j] = 0.0
             #  Do local matrix multiplication
-            for i in range(1,npts+1):
+            for i in range(1, npts+1):
                 p[icount+j] += nbasis[i]*b[jcount]
                 jcount += 3
         icount += 3
         t += step
 
+
 # Accuracy for comparison operators
 _accuracy = 1E-15
 
 
 def Cmp0(x):
     """Compare against zero within _accuracy"""
-    return abs(x)<_accuracy
+    return abs(x) < _accuracy
 
 
 def gauss(A, B):
@@ -337,7 +345,8 @@ def gauss(A, B):
                 j = i
                 ap = api
 
-        if j != k: p[k], p[j] = p[j], p[k]  # Swap values
+        if j != k:
+            p[k], p[j] = p[j], p[k]  # Swap values
 
         for i in range(k + 1, n):
             z = A[p[i]][k] / A[p[k]][k]
@@ -384,20 +393,22 @@ class Vector(list):
         """Set vector"""
         self[0] = x
         self[1] = y
-        if z: self[2] = z
+        if z:
+            self[2] = z
 
     # ----------------------------------------------------------------------
     def __repr__(self):
-        return "[%s]" % (", ".join([repr(x) for x in self]))
+        return "[%s]" % ", ".join([repr(x) for x in self])
 
     # ----------------------------------------------------------------------
     def __str__(self):
-        return "[%s]" % (", ".join([("%15g" % (x)).strip() for x in self]))
+        return "[%s]" % ", ".join([("%15g" % (x)).strip() for x in self])
 
     # ----------------------------------------------------------------------
     def eq(self, v, acc=_accuracy):
         """Test for equality with vector v within accuracy"""
-        if len(self) != len(v): return False
+        if len(self) != len(v):
+            return False
         s2 = 0.0
         for a, b in zip(self, v):
             s2 += (a - b) ** 2
@@ -523,12 +534,12 @@ class Vector(list):
     # ----------------------------------------------------------------------
     def norm(self):
         """Normalize vector and return length"""
-        l = self.length()
-        if l > 0.0:
-            invlen = 1.0 / l
+        length = self.length()
+        if length > 0.0:
+            invlen = 1.0 / length
             for i in range(len(self)):
                 self[i] *= invlen
-        return l
+        return length
 
     normalize = norm
 
@@ -580,8 +591,9 @@ class Vector(list):
         """return containing the direction if normalized with any of the axis"""
 
         v = self.clone()
-        l = v.norm()
-        if abs(l) <= zero: return "O"
+        length = v.norm()
+        if abs(length) <= zero:
+            return "O"
 
         if abs(v[0] - 1.0) < zero:
             return "X"

+ 6 - 7
flatcamParsers/ParseFont.py

@@ -1,15 +1,14 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 3/10/2019                                          #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
-# ####################################################################### ##
-# ## Borrowed code from 'https://github.com/gddc/ttfquery/blob/master/ # ##
-# ## and made it work with Python 3                          ########### ##
-# ####################################################################### ##
+# ######################################################################
+# ## Borrowed code from 'https://github.com/gddc/ttfquery/blob/master/ #
+# ## and made it work with Python 3                                    #
+# ######################################################################
 
 import re, os, sys, glob
 import itertools

+ 5 - 3
flatcamParsers/ParseSVG.py

@@ -1,4 +1,4 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # http://flatcam.org                                       #
 # Author: Juan Pablo Caram (c)                             #
@@ -17,7 +17,7 @@
 #  * All transformations                                   #
 #                                                          #
 #  Reference: www.w3.org/TR/SVG/Overview.html              #
-# ########################################################## ##
+# ##########################################################
 
 # import xml.etree.ElementTree as ET
 from svg.path import Line, Arc, CubicBezier, QuadraticBezier, parse_path
@@ -136,6 +136,7 @@ def path2shapely(path, object_type, res=1.0):
 
     return geometry
 
+
 def svgrect2shapely(rect, n_points=32):
     """
     Converts an SVG rect into Shapely geometry.
@@ -284,7 +285,7 @@ def svgpolygon2shapely(polygon):
     # return LinearRing(points)
 
 
-def getsvggeo(node, object_type, root = None):
+def getsvggeo(node, object_type, root=None):
     """
     Extracts and flattens all geometry from an SVG node
     into a list of Shapely geometry.
@@ -482,6 +483,7 @@ def getsvgtext(node, object_type, units='MM'):
 
     return geo
 
+
 def parse_svg_point_list(ptliststr):
     """
     Returns a list of coordinate pairs extracted from the "points"

+ 2 - 3
flatcamTools/ToolCalculators.py

@@ -1,10 +1,9 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 3/10/2019                                          #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 from FlatCAMTool import FlatCAMTool
 from FlatCAMObj import *

+ 7 - 0
flatcamTools/ToolCutOut.py

@@ -1,3 +1,10 @@
+# ##########################################################
+# FlatCAM: 2D Post-processing for Manufacturing            #
+# File Author: Marius Adrian Stanciu (c)                   #
+# Date: 3/10/2019                                          #
+# MIT Licence                                              #
+# ##########################################################
+
 from FlatCAMTool import FlatCAMTool
 from ObjectCollection import *
 from FlatCAMApp import *

+ 2 - 3
flatcamTools/ToolDistance.py

@@ -1,10 +1,9 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 3/10/2019                                          #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 from FlatCAMTool import FlatCAMTool
 from FlatCAMObj import *

+ 0 - 1
flatcamTools/ToolDistanceMin.py

@@ -1,6 +1,5 @@
 # ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 09/29/2019                                         #
 # MIT Licence                                              #

+ 206 - 21
flatcamTools/ToolFilm.py

@@ -1,10 +1,9 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 3/10/2019                                          #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 from FlatCAMTool import FlatCAMTool
 from FlatCAMObj import *
@@ -31,6 +30,8 @@ class Film(FlatCAMTool):
     def __init__(self, app):
         FlatCAMTool.__init__(self, app)
 
+        self.decimals = 4
+
         # Title
         title_label = QtWidgets.QLabel("%s" % self.toolName)
         title_label.setStyleSheet("""
@@ -121,20 +122,141 @@ class Film(FlatCAMTool):
         grid0.addWidget(self.tf_box_combo_label, 3, 0)
         grid0.addWidget(self.tf_box_combo, 3, 1)
 
+        grid0.addWidget(QtWidgets.QLabel(''), 4, 0)
+
+        self.film_adj_label = QtWidgets.QLabel('<b>%s</b>' % _("Film Adjustments"))
+        self.film_adj_label.setToolTip(
+            _("Sometime the printers will distort the print shape, especially the Laser types.\n"
+              "This section provide the tools to compensate for the print distortions.")
+        )
+
+        grid0.addWidget(self.film_adj_label, 5, 0, 1, 2)
+
+        # Scale Geometry
+        self.film_scale_cb = FCCheckBox('%s' % _("Scale Film geometry"))
+        self.film_scale_cb.setToolTip(
+            _("A value greater than 1 will stretch the film\n"
+              "while a value less than 1 will jolt it.")
+        )
+        self.film_scale_cb.setStyleSheet(
+            """
+            QCheckBox {font-weight: bold; color: black}
+            """
+        )
+        grid0.addWidget(self.film_scale_cb, 6, 0, 1, 2)
+
+        self.film_scalex_label = QtWidgets.QLabel('%s:' % _("X factor"))
+        self.film_scalex_entry = FCDoubleSpinner()
+        self.film_scalex_entry.set_range(-999.9999, 999.9999)
+        self.film_scalex_entry.set_precision(self.decimals)
+        self.film_scalex_entry.setSingleStep(0.01)
+
+        grid0.addWidget(self.film_scalex_label, 7, 0)
+        grid0.addWidget(self.film_scalex_entry, 7, 1)
+
+        self.film_scaley_label = QtWidgets.QLabel('%s:' % _("Y factor"))
+        self.film_scaley_entry = FCDoubleSpinner()
+        self.film_scaley_entry.set_range(-999.9999, 999.9999)
+        self.film_scaley_entry.set_precision(self.decimals)
+        self.film_scaley_entry.setSingleStep(0.01)
+
+        grid0.addWidget(self.film_scaley_label, 8, 0)
+        grid0.addWidget(self.film_scaley_entry, 8, 1)
+
+        self.ois_scale = OptionalInputSection(self.film_scale_cb, [self.film_scalex_label, self.film_scalex_entry,
+                                                                   self.film_scaley_label,  self.film_scaley_entry])
+        # Skew Geometry
+        self.film_skew_cb =FCCheckBox('%s' % _("Skew Film geometry"))
+        self.film_skew_cb.setToolTip(
+            _("Positive values will skew to the right\n"
+              "while negative values will skew to the left.")
+        )
+        self.film_skew_cb.setStyleSheet(
+            """
+            QCheckBox {font-weight: bold; color: black}
+            """
+        )
+        grid0.addWidget(self.film_skew_cb, 9, 0, 1, 2)
+
+        self.film_skewx_label = QtWidgets.QLabel('%s:' % _("X angle"))
+        self.film_skewx_entry = FCDoubleSpinner()
+        self.film_skewx_entry.set_range(-999.9999, 999.9999)
+        self.film_skewx_entry.set_precision(self.decimals)
+        self.film_skewx_entry.setSingleStep(0.01)
+
+        grid0.addWidget(self.film_skewx_label, 10, 0)
+        grid0.addWidget(self.film_skewx_entry, 10, 1)
+
+        self.film_skewy_label = QtWidgets.QLabel('%s:' % _("Y angle"))
+        self.film_skewy_entry = FCDoubleSpinner()
+        self.film_skewy_entry.set_range(-999.9999, 999.9999)
+        self.film_skewy_entry.set_precision(self.decimals)
+        self.film_skewy_entry.setSingleStep(0.01)
+
+        grid0.addWidget(self.film_skewy_label, 11, 0)
+        grid0.addWidget(self.film_skewy_entry, 11, 1)
+
+        self.film_skew_ref_label = QtWidgets.QLabel('%s:' % _("Reference"))
+        self.film_skew_ref_label.setToolTip(
+            _("The reference point to be used as origin for the skew.\n"
+              "It can be one of the four points of the geometry bounding box.")
+        )
+        self.film_skew_reference = RadioSet([{'label': _('Bottom Left'), 'value': 'bottomleft'},
+                                          {'label': _('Top Left'), 'value': 'topleft'},
+                                          {'label': _('Bottom Right'), 'value': 'bottomright'},
+                                          {'label': _('Top right'), 'value': 'topright'}],
+                                            orientation='vertical',
+                                            stretch=False)
+
+        grid0.addWidget(self.film_skew_ref_label, 12, 0)
+        grid0.addWidget(self.film_skew_reference, 12, 1)
+
+        self.ois_skew = OptionalInputSection(self.film_skew_cb, [self.film_skewx_label, self.film_skewx_entry,
+                                                                 self.film_skewy_label,  self.film_skewy_entry,
+                                                                 self.film_skew_reference])
+        # Mirror Geometry
+        self.film_mirror_cb = FCCheckBox('%s' % _("Mirror Film geometry"))
+        self.film_mirror_cb.setToolTip(
+            _("Mirror the film geometry on the selected axis or on both.")
+        )
+        self.film_mirror_cb.setStyleSheet(
+            """
+            QCheckBox {font-weight: bold; color: black}
+            """
+        )
+        grid0.addWidget(self.film_mirror_cb, 13, 0, 1, 2)
+
+        self.film_mirror_axis = RadioSet([{'label': _('None'), 'value': 'none'},
+                                          {'label': _('X'), 'value': 'x'},
+                                          {'label': _('Y'), 'value': 'y'},
+                                          {'label': _('Both'), 'value': 'both'}],
+                                         stretch=False)
+        self.film_mirror_axis_label = QtWidgets.QLabel('%s:' % _("Mirror axis"))
+
+        grid0.addWidget(self.film_mirror_axis_label, 14, 0)
+        grid0.addWidget(self.film_mirror_axis, 14, 1)
+
+        self.ois_mirror = OptionalInputSection(self.film_mirror_cb,
+                                               [self.film_mirror_axis_label, self.film_mirror_axis])
+
+        grid0.addWidget(QtWidgets.QLabel(''), 15, 0)
+
         # Scale Stroke size
-        self.film_scale_entry = FCDoubleSpinner()
-        self.film_scale_entry.set_range(-999.9999, 999.9999)
+        self.film_scale_stroke_entry = FCDoubleSpinner()
+        self.film_scale_stroke_entry.set_range(-999.9999, 999.9999)
+        self.film_scale_stroke_entry.setSingleStep(0.01)
+        self.film_scale_stroke_entry.set_precision(self.decimals)
 
-        self.film_scale_label = QtWidgets.QLabel('%s:' % _("Scale Stroke"))
-        self.film_scale_label.setToolTip(
+        self.film_scale_stroke_label = QtWidgets.QLabel('%s:' % _("Scale Stroke"))
+        self.film_scale_stroke_label.setToolTip(
             _("Scale the line stroke thickness of each feature in the SVG file.\n"
               "It means that the line that envelope each SVG feature will be thicker or thinner,\n"
               "therefore the fine features may be more affected by this parameter.")
         )
-        grid0.addWidget(self.film_scale_label, 4, 0)
-        grid0.addWidget(self.film_scale_entry, 4, 1)
+        grid0.addWidget(self.film_scale_stroke_label, 16, 0)
+        grid0.addWidget(self.film_scale_stroke_entry, 16, 1)
 
-        grid0.addWidget(QtWidgets.QLabel(''), 5, 0)
+        grid0.addWidget(QtWidgets.QLabel(''), 17, 0)
 
         # Film Type
         self.film_type = RadioSet([{'label': _('Positive'), 'value': 'pos'},
@@ -149,12 +271,15 @@ class Film(FlatCAMTool):
               "with white on a black canvas.\n"
               "The Film format is SVG.")
         )
-        grid0.addWidget(self.film_type_label, 6, 0)
-        grid0.addWidget(self.film_type, 6, 1)
+        grid0.addWidget(self.film_type_label, 18, 0)
+        grid0.addWidget(self.film_type, 18, 1)
 
         # Boundary for negative film generation
         self.boundary_entry = FCDoubleSpinner()
         self.boundary_entry.set_range(-999.9999, 999.9999)
+        self.boundary_entry.setSingleStep(0.01)
+        self.boundary_entry.set_precision(self.decimals)
+
         self.boundary_label = QtWidgets.QLabel('%s:' % _("Border"))
         self.boundary_label.setToolTip(
             _("Specify a border around the object.\n"
@@ -166,8 +291,8 @@ class Film(FlatCAMTool):
               "white color like the rest and which may confound with the\n"
               "surroundings if not for this border.")
         )
-        grid0.addWidget(self.boundary_label, 7, 0)
-        grid0.addWidget(self.boundary_entry, 7, 1)
+        grid0.addWidget(self.boundary_label, 19, 0)
+        grid0.addWidget(self.boundary_entry, 19, 1)
 
         self.boundary_label.hide()
         self.boundary_entry.hide()
@@ -177,7 +302,7 @@ class Film(FlatCAMTool):
         self.punch_cb.setToolTip(_("When checked the generated film will have holes in pads when\n"
                                    "the generated film is positive. This is done to help drilling,\n"
                                    "when done manually."))
-        grid0.addWidget(self.punch_cb, 8, 0, 1, 2)
+        grid0.addWidget(self.punch_cb, 20, 0, 1, 2)
 
         # this way I can hide/show the frame
         self.punch_frame = QtWidgets.QFrame()
@@ -199,8 +324,8 @@ class Film(FlatCAMTool):
               "- Pad Center -> will try to use the pads center as reference.")
         )
         self.source_punch = RadioSet([{'label': _('Excellon'), 'value': 'exc'},
-                                   {'label': _('Pad center'), 'value': 'pad'}],
-                                   stretch=False)
+                                      {'label': _('Pad center'), 'value': 'pad'}],
+                                     stretch=False)
         punch_grid.addWidget(self.source_label, 0, 0)
         punch_grid.addWidget(self.source_punch, 0, 1)
 
@@ -222,6 +347,8 @@ class Film(FlatCAMTool):
         self.punch_size_label.setToolTip(_("The value here will control how big is the punch hole in the pads."))
         self.punch_size_spinner = FCDoubleSpinner()
         self.punch_size_spinner.set_range(0, 999.9999)
+        self.punch_size_spinner.setSingleStep(0.1)
+        self.punch_size_spinner.set_precision(self.decimals)
 
         punch_grid.addWidget(self.punch_size_label, 2, 0)
         punch_grid.addWidget(self.punch_size_spinner, 2, 1)
@@ -304,7 +431,7 @@ class Film(FlatCAMTool):
         self.boundary_entry.set_value(float(b_entry))
 
         scale_stroke_width = self.app.defaults["tools_film_scale"] if self.app.defaults["tools_film_scale"] else 0.0
-        self.film_scale_entry.set_value(int(scale_stroke_width))
+        self.film_scale_stroke_entry.set_value(int(scale_stroke_width))
 
         self.punch_cb.set_value(False)
         self.source_punch.set_value('exc')
@@ -356,7 +483,7 @@ class Film(FlatCAMTool):
                                  _("No FlatCAM object selected. Load an object for Box and retry."))
             return
 
-        scale_stroke_width = float(self.film_scale_entry.get_value())
+        scale_stroke_width = float(self.film_scale_stroke_entry.get_value())
 
         source = self.source_punch.get_value()
 
@@ -377,6 +504,29 @@ class Film(FlatCAMTool):
 
     def generate_positive_normal_film(self, name, boxname, factor):
         log.debug("ToolFilm.Film.generate_positive_normal_film() started ...")
+
+        scale_factor_x = None
+        scale_factor_y = None
+        skew_factor_x = None
+        skew_factor_y = None
+        mirror = None
+        skew_reference = 'center'
+
+        if self.film_scale_cb.get_value():
+            if self.film_scalex_entry.get_value() != 1.0:
+                scale_factor_x = self.film_scalex_entry.get_value()
+            if self.film_scaley_entry.get_value() != 1.0:
+                scale_factor_y = self.film_scaley_entry.get_value()
+        if self.film_skew_cb.get_value():
+            if self.film_skewx_entry.get_value() != 0.0:
+                skew_factor_x = self.film_skewx_entry.get_value()
+            if self.film_skewy_entry.get_value() != 0.0:
+                skew_factor_y = self.film_skewy_entry.get_value()
+
+            skew_reference = self.film_skew_reference.get_value()
+        if self.film_mirror_cb.get_value():
+            if self.film_mirror_axis.get_value() != 'none':
+                mirror = self.film_mirror_axis.get_value()
         try:
             filename, _f = QtWidgets.QFileDialog.getSaveFileName(
                 caption=_("Export SVG positive"),
@@ -391,7 +541,13 @@ class Film(FlatCAMTool):
             self.app.inform.emit('[WARNING_NOTCL] %s' % _("Export SVG positive cancelled."))
             return
         else:
-            self.app.export_svg_positive(name, boxname, filename, scale_factor=factor)
+            self.app.export_svg_positive(name, boxname, filename,
+                                         scale_stroke_factor=factor,
+                                         scale_factor_x=scale_factor_x, scale_factor_y=scale_factor_y,
+                                         skew_factor_x=skew_factor_x, skew_factor_y=skew_factor_y,
+                                         skew_reference=skew_reference,
+                                         mirror=mirror
+                                         )
 
     def generate_positive_punched_film(self, name, boxname, source, factor):
 
@@ -473,6 +629,29 @@ class Film(FlatCAMTool):
     def generate_negative_film(self, name, boxname, factor):
         log.debug("ToolFilm.Film.generate_negative_film() started ...")
 
+        scale_factor_x = None
+        scale_factor_y = None
+        skew_factor_x = None
+        skew_factor_y = None
+        mirror = None
+        skew_reference = 'center'
+
+        if self.film_scale_cb.get_value():
+            if self.film_scalex_entry.get_value() != 1.0:
+                scale_factor_x = self.film_scalex_entry.get_value()
+            if self.film_scaley_entry.get_value() != 1.0:
+                scale_factor_y = self.film_scaley_entry.get_value()
+        if self.film_skew_cb.get_value():
+            if self.film_skewx_entry.get_value() != 0.0:
+                skew_factor_x = self.film_skewx_entry.get_value()
+            if self.film_skewy_entry.get_value() != 0.0:
+                skew_factor_y = self.film_skewy_entry.get_value()
+
+            skew_reference = self.film_skew_reference.get_value()
+        if self.film_mirror_cb.get_value():
+            if self.film_mirror_axis.get_value() != 'none':
+                mirror = self.film_mirror_axis.get_value()
+
         border = float(self.boundary_entry.get_value())
 
         if border is None:
@@ -492,7 +671,13 @@ class Film(FlatCAMTool):
             self.app.inform.emit('[WARNING_NOTCL] %s' % _("Export SVG negative cancelled."))
             return
         else:
-            self.app.export_svg_negative(name, boxname, filename, border, scale_factor=factor)
+            self.app.export_svg_negative(name, boxname, filename, border,
+                                         scale_stroke_factor=factor,
+                                         scale_factor_x=scale_factor_x, scale_factor_y=scale_factor_y,
+                                         skew_factor_x=skew_factor_x, skew_factor_y=skew_factor_y,
+                                         skew_reference=skew_reference,
+                                         mirror=mirror
+                                         )
 
     def reset_fields(self):
         self.tf_object_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))

+ 2 - 3
flatcamTools/ToolImage.py

@@ -1,10 +1,9 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 3/10/2019                                          #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 from FlatCAMTool import FlatCAMTool
 

+ 0 - 1
flatcamTools/ToolMove.py

@@ -1,6 +1,5 @@
 # ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 3/10/2019                                          #
 # MIT Licence                                              #

+ 2 - 3
flatcamTools/ToolNonCopperClear.py

@@ -1,10 +1,9 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Modified by: Marius Adrian Stanciu (c)              #
 # Date: 3/10/2019                                          #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 from FlatCAMTool import FlatCAMTool
 from copy import copy, deepcopy

+ 0 - 1
flatcamTools/ToolOptimal.py

@@ -1,6 +1,5 @@
 # ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 09/27/2019                                         #
 # MIT Licence                                              #

+ 2 - 3
flatcamTools/ToolPDF.py

@@ -1,10 +1,9 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 4/23/2019                                          #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 from FlatCAMTool import FlatCAMTool
 from shapely.geometry import Point, Polygon, LineString

+ 0 - 1
flatcamTools/ToolPaint.py

@@ -1,6 +1,5 @@
 # ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Modified: Marius Adrian Stanciu (c)                 #
 # Date: 3/10/2019                                          #
 # MIT Licence                                              #

+ 2 - 3
flatcamTools/ToolPanelize.py

@@ -1,10 +1,9 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 3/10/2019                                          #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 from FlatCAMTool import FlatCAMTool
 from copy import copy, deepcopy

+ 2 - 3
flatcamTools/ToolPcbWizard.py

@@ -1,10 +1,9 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 4/15/2019                                          #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 from FlatCAMTool import FlatCAMTool
 

+ 2 - 3
flatcamTools/ToolProperties.py

@@ -1,10 +1,9 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 3/10/2019                                          #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 from PyQt5 import QtGui, QtCore, QtWidgets
 from PyQt5.QtCore import Qt

+ 20 - 18
flatcamTools/ToolRulesCheck.py

@@ -1,10 +1,9 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
-# Date: 09/27/2019                                          #
+# Date: 09/27/2019                                         #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 from FlatCAMTool import FlatCAMTool
 from copy import copy, deepcopy
@@ -602,9 +601,7 @@ class RulesCheck(FlatCAMTool):
             total_geo = total_geo.buffer(0.000001)
 
         if isinstance(total_geo, Polygon):
-            iterations = 1
-            obj_violations['points'] =['Failed. Only one polygon.']
-
+            obj_violations['points'] = ['Failed. Only one polygon.']
             return rule_title, [obj_violations]
         else:
             iterations = len(total_geo)
@@ -846,21 +843,26 @@ class RulesCheck(FlatCAMTool):
             dia_list = []
             points_list = []
             name = elem['name']
+
             for apid in elem['apertures']:
-                tool_dia = float(elem['apertures'][apid]['size'])
-                if tool_dia < float(size) and tool_dia != 0.0:
-                    dia_list.append(tool_dia)
-                    for geo_el in elem['apertures'][apid]['geometry']:
-                        if 'solid' in geo_el.keys():
-                            geo = geo_el['solid']
-                            pt = geo.representative_point()
-                            points_list.append((pt.x, pt.y))
+                try:
+                    tool_dia = float(elem['apertures'][apid]['size'])
+                    if tool_dia < float(size) and tool_dia != 0.0:
+                        dia_list.append(tool_dia)
+                        for geo_el in elem['apertures'][apid]['geometry']:
+                            if 'solid' in geo_el.keys():
+                                geo = geo_el['solid']
+                                pt = geo.representative_point()
+                                points_list.append((pt.x, pt.y))
+                except Exception as e:
+                    # An exception  will be raised for the 'size' key in case of apertures of type AM (macro) which does
+                    # not have the size key
+                    pass
 
             obj_violations['name'] = name
             obj_violations['size'] = dia_list
             obj_violations['points'] = points_list
             violations.append(deepcopy(obj_violations))
-
         return rule, violations
 
     @staticmethod
@@ -1025,7 +1027,7 @@ class RulesCheck(FlatCAMTool):
         log.debug("RuleCheck() executing")
 
         def worker_job(app_obj):
-            proc = self.app.proc_container.new(_("Working..."))
+            self.app.proc_container.new(_("Working..."))
 
             # RULE: Check Trace Size
             if self.trace_size_cb.get_value():
@@ -1518,7 +1520,7 @@ class RulesCheck(FlatCAMTool):
             new_obj.source_file = txt
             new_obj.read_only = True
 
-        self.app.new_object('document', name='Rules Check results', initialize=init, plot=False )
+        self.app.new_object('document', name='Rules Check results', initialize=init, plot=False)
 
     def reset_fields(self):
         # self.object_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))

+ 2 - 2
flatcamTools/ToolShell.py

@@ -1,10 +1,10 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # http://flatcam.org                                       #
 # Author: Juan Pablo Caram (c)                             #
 # Date: 2/5/2014                                           #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 # from PyQt5.QtCore import pyqtSignal
 from PyQt5.QtCore import Qt

+ 2 - 3
flatcamTools/ToolSolderPaste.py

@@ -1,10 +1,9 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 3/10/2019                                          #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 from FlatCAMTool import FlatCAMTool
 from FlatCAMCommon import LoudDict

+ 2 - 3
flatcamTools/ToolSub.py

@@ -1,10 +1,9 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 4/24/2019                                          #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 
 from FlatCAMTool import FlatCAMTool

+ 2 - 3
flatcamTools/ToolTransform.py

@@ -1,10 +1,9 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 3/10/2019                                          #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 from FlatCAMTool import FlatCAMTool
 from FlatCAMObj import *

+ 5 - 5
make_win.py

@@ -1,4 +1,4 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # http://flatcam.org                                       #
 # Author: Juan Pablo Caram (c)                             #
@@ -11,12 +11,12 @@
 # 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 (major mod): Marius Adrian Stanciu         #
+# ##########################################################
+# File Modified: Marius Adrian Stanciu                     #
 # Date: 3/10/2019                                          #
-# ########################################################## ##
+# ##########################################################
 
 
 # Files not needed: Qt, tk.dll, tcl.dll, tk/, tcl/, vtk/,

+ 7 - 0
tclCommands/TclCommandClearShell.py

@@ -1,3 +1,10 @@
+# ##########################################################
+# FlatCAM: 2D Post-processing for Manufacturing            #
+# File Author: Marius Adrian Stanciu (c)                   #
+# Date: 8/17/2019                                          #
+# MIT Licence                                              #
+# ##########################################################
+
 from tclCommands.TclCommand import TclCommand
 from ObjectCollection import *
 

+ 7 - 0
tclCommands/TclCommandGetSys.py

@@ -1,3 +1,10 @@
+# ##########################################################
+# FlatCAM: 2D Post-processing for Manufacturing            #
+# File Author: Marius Adrian Stanciu (c)                   #
+# Date: 8/17/2019                                          #
+# MIT Licence                                              #
+# ##########################################################
+
 from ObjectCollection import *
 from tclCommands.TclCommand import TclCommand
 

+ 7 - 0
tclCommands/TclCommandListSys.py

@@ -1,3 +1,10 @@
+# ##########################################################
+# FlatCAM: 2D Post-processing for Manufacturing            #
+# File Author: Marius Adrian Stanciu (c)                   #
+# Date: 8/17/2019                                          #
+# MIT Licence                                              #
+# ##########################################################
+
 from tclCommands.TclCommand import *
 
 

+ 7 - 0
tclCommands/TclCommandMillDrills.py

@@ -1,3 +1,10 @@
+# ##########################################################
+# FlatCAM: 2D Post-processing for Manufacturing            #
+# File Author: Marius Adrian Stanciu (c)                   #
+# Date: 8/17/2019                                          #
+# MIT Licence                                              #
+# ##########################################################
+
 from ObjectCollection import *
 from tclCommands.TclCommand import TclCommandSignaled
 

+ 7 - 0
tclCommands/TclCommandMillSlots.py

@@ -1,3 +1,10 @@
+# ##########################################################
+# FlatCAM: 2D Post-processing for Manufacturing            #
+# File Author: Marius Adrian Stanciu (c)                   #
+# Date: 8/17/2019                                          #
+# MIT Licence                                              #
+# ##########################################################
+
 from ObjectCollection import *
 from tclCommands.TclCommand import TclCommandSignaled
 

+ 7 - 0
tclCommands/TclCommandNewExcellon.py

@@ -1,3 +1,10 @@
+# ##########################################################
+# FlatCAM: 2D Post-processing for Manufacturing            #
+# File Author: Marius Adrian Stanciu (c)                   #
+# Date: 8/17/2019                                          #
+# MIT Licence                                              #
+# ##########################################################
+
 from ObjectCollection import *
 from tclCommands.TclCommand import TclCommandSignaled
 

+ 7 - 0
tclCommands/TclCommandNewGerber.py

@@ -1,3 +1,10 @@
+# ##########################################################
+# FlatCAM: 2D Post-processing for Manufacturing            #
+# File Author: Marius Adrian Stanciu (c)                   #
+# Date: 8/17/2019                                          #
+# MIT Licence                                              #
+# ##########################################################
+
 from ObjectCollection import *
 from tclCommands.TclCommand import TclCommandSignaled
 

+ 7 - 0
tclCommands/TclCommandPlotObjects.py

@@ -1,3 +1,10 @@
+# ##########################################################
+# FlatCAM: 2D Post-processing for Manufacturing            #
+# File Author: Marius Adrian Stanciu (c)                   #
+# Date: 8/17/2019                                          #
+# MIT Licence                                              #
+# ##########################################################
+
 from ObjectCollection import *
 from tclCommands.TclCommand import TclCommand
 

+ 7 - 0
tclCommands/TclCommandQuit.py

@@ -1,3 +1,10 @@
+# ##########################################################
+# FlatCAM: 2D Post-processing for Manufacturing            #
+# File Author: Marius Adrian Stanciu (c)                   #
+# Date: 8/17/2019                                          #
+# MIT Licence                                              #
+# ##########################################################
+
 from ObjectCollection import *
 from tclCommands.TclCommand import TclCommand
 

+ 7 - 0
tclCommands/TclCommandSaveSys.py

@@ -1,3 +1,10 @@
+# ##########################################################
+# FlatCAM: 2D Post-processing for Manufacturing            #
+# File Author: Marius Adrian Stanciu (c)                   #
+# Date: 8/17/2019                                          #
+# MIT Licence                                              #
+# ##########################################################
+
 from tclCommands.TclCommand import *
 
 

+ 7 - 0
tclCommands/TclCommandSetOrigin.py

@@ -1,3 +1,10 @@
+# ##########################################################
+# FlatCAM: 2D Post-processing for Manufacturing            #
+# File Author: Marius Adrian Stanciu (c)                   #
+# Date: 8/17/2019                                          #
+# MIT Licence                                              #
+# ##########################################################
+
 from tclCommands.TclCommand import TclCommand
 from ObjectCollection import *
 

+ 0 - 7
upgrade_geos.sh

@@ -1,7 +0,0 @@
-#!/bin/sh
-wget http://download.osgeo.org/geos/geos-3.4.2.tar.bz2
-tar xjvf geos-3.4.2.tar.bz2
-cd geos-3.4.2
-./configure --prefix=/usr
-make
-make install