Преглед изворни кода

- 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.geo_form = None
         self.cnc_form = None
         self.cnc_form = None
         self.tools_form = None
         self.tools_form = None
+        self.tools2_form = None
         self.fa_form = None
         self.fa_form = None
 
 
         self.on_options_combo_change(0)  # Will show the initial form
         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.geo_form = self.ui.geometry_defaults_form
             self.cnc_form = self.ui.cncjob_defaults_form
             self.cnc_form = self.ui.cncjob_defaults_form
             self.tools_form = self.ui.tools_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
             self.fa_form = self.ui.util_defaults_form
         elif sel == 1:
         elif sel == 1:
             self.gen_form = self.ui.general_options_form
             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.geo_form = self.ui.geometry_options_form
             self.cnc_form = self.ui.cncjob_options_form
             self.cnc_form = self.ui.cncjob_options_form
             self.tools_form = self.ui.tools_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
             self.fa_form = self.ui.util_options_form
         else:
         else:
             return
             return
@@ -6054,6 +6057,13 @@ class App(QtCore.QObject):
         self.ui.tools_scroll_area.setWidget(self.tools_form)
         self.ui.tools_scroll_area.setWidget(self.tools_form)
         self.tools_form.show()
         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:
         try:
             self.ui.fa_scroll_area.takeWidget()
             self.ui.fa_scroll_area.takeWidget()
         except:
         except:
@@ -9697,13 +9707,13 @@ class App(QtCore.QObject):
         self.set_ui_title(name=self.project_filename)
         self.set_ui_title(name=self.project_filename)
         self.should_we_save = False
         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.
         Exports a Geometry Object to an SVG file.
 
 
         :param obj_name: the name of the FlatCAM object to be saved as SVG
         :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 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:
         :return:
         """
         """
         self.report_usage("export_svg()")
         self.report_usage("export_svg()")
@@ -9720,7 +9730,7 @@ class App(QtCore.QObject):
             return "Could not retrieve object: %s" % obj_name
             return "Could not retrieve object: %s" % obj_name
 
 
         with self.proc_container.new(_("Exporting SVG")) as proc:
         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
             # Determine bounding area for svg export
             bounds = obj.bounds()
             bounds = obj.bounds()
@@ -9763,7 +9773,12 @@ class App(QtCore.QObject):
             self.inform.emit('[success] %s: %s' %
             self.inform.emit('[success] %s: %s' %
                              (_("SVG file exported to"), filename))
                              (_("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.
         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 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 filename: Path to the SVG file to save to.
         :param boundary: thickness of a black border to surround all the features
         :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
         :param use_thread: if to be run in a separate thread; boolean
         :return:
         :return:
         """
         """
@@ -9800,7 +9822,11 @@ class App(QtCore.QObject):
             box = obj
             box = obj
 
 
         def make_negative_film():
         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
             # Determine bounding area for svg export
             bounds = box.bounds()
             bounds = box.bounds()
@@ -9889,14 +9915,27 @@ class App(QtCore.QObject):
         else:
         else:
             make_negative_film()
             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.
         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 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 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 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
         :param use_thread: if to be run in a separate thread; boolean
         :return:
         :return:
         """
         """
@@ -9925,7 +9964,11 @@ class App(QtCore.QObject):
             box = obj
             box = obj
 
 
         def make_positive_film():
         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)
             self.progress.emit(40)
 
 

+ 6 - 2
FlatCAMObj.py

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

+ 0 - 1
FlatCAMTranslation.py

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

+ 5 - 4
ObjectCollection.py

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

+ 49 - 17
camlib.py

@@ -1836,37 +1836,69 @@ class Geometry(object):
         """
         """
         self.solid_geometry = [cascaded_union(self.solid_geometry)]
         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
         Exports the Geometry Object as a SVG Element
 
 
         :return: 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'>":
         if str(type(self)) == "<class 'FlatCAMObj.FlatCAMGeometry'>":
             flat_geo = []
             flat_geo = []
             if self.multigeo:
             if self.multigeo:
                 for tool in self.tools:
                 for tool in self.tools:
                     flat_geo += self.flatten(self.tools[tool]['solid_geometry'])
                     flat_geo += self.flatten(self.tools[tool]['solid_geometry'])
-                geom = cascaded_union(flat_geo)
+                geom_svg = cascaded_union(flat_geo)
             else:
             else:
-                geom = cascaded_union(self.flatten())
+                geom_svg = cascaded_union(self.flatten())
         else:
         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
         # 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
         # This value appears to work for zooming, and getting the output svg line width
         # to match that viewed on screen with FlatCam
         # 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
         # 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
         # Convert to a SVG
-        svg_elem = geom.svg(scale_factor=scale_factor)
+        svg_elem = geom.svg(scale_factor=scale_stroke_factor)
         return svg_elem
         return svg_elem
 
 
     def mirror(self, axis, point):
     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
         gcode += self.doformat(p.lift_code, x=first_x, y=first_y)  # Stop cutting
         return gcode
         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
         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 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
         # 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
         # If still 0 then default to 0.05
         # This value appears to work for zooming, and getting the output svg line width
         # This value appears to work for zooming, and getting the output svg line width
         # to match that viewed on screen with FlatCam
         # 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
         # Separate the list of cuts and travels into 2 distinct lists
         # This way we can add different formatting / colors to both
         # 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
         # It's better to have the travels sitting underneath the cuts for visicut
         svg_elem = ""
         svg_elem = ""
         if travels:
         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:
         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
         return svg_elem
 
 

+ 0 - 1
flatcamEditors/FlatCAMExcEditor.py

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

+ 0 - 1
flatcamEditors/FlatCAMGrbEditor.py

@@ -1,6 +1,5 @@
 # ##########################################################
 # ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 8/17/2019                                          #
 # Date: 8/17/2019                                          #
 # MIT Licence                                              #
 # 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 flatcamGUI.GUIElements import *
 from PyQt5 import QtPrintSupport
 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_scroll_area = QtWidgets.QScrollArea()
         self.tools_tab_lay.addWidget(self.tools_scroll_area)
         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 = QtWidgets.QWidget()
         self.fa_tab.setObjectName("fa_tab")
         self.fa_tab.setObjectName("fa_tab")
         self.pref_tab_area.addTab(self.fa_tab, _("UTILITIES"))
         self.pref_tab_area.addTab(self.fa_tab, _("UTILITIES"))
@@ -1980,6 +1989,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         self.geometry_defaults_form = GeometryPreferencesUI()
         self.geometry_defaults_form = GeometryPreferencesUI()
         self.cncjob_defaults_form = CNCJobPreferencesUI()
         self.cncjob_defaults_form = CNCJobPreferencesUI()
         self.tools_defaults_form = ToolsPreferencesUI()
         self.tools_defaults_form = ToolsPreferencesUI()
+        self.tools2_defaults_form = Tools2PreferencesUI()
         self.util_defaults_form = UtilPreferencesUI()
         self.util_defaults_form = UtilPreferencesUI()
 
 
         self.general_options_form = GeneralPreferencesUI()
         self.general_options_form = GeneralPreferencesUI()
@@ -1988,6 +1998,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         self.geometry_options_form = GeometryPreferencesUI()
         self.geometry_options_form = GeometryPreferencesUI()
         self.cncjob_options_form = CNCJobPreferencesUI()
         self.cncjob_options_form = CNCJobPreferencesUI()
         self.tools_options_form = ToolsPreferencesUI()
         self.tools_options_form = ToolsPreferencesUI()
+        self.tools2_options_form = Tools2PreferencesUI()
         self.util_options_form = UtilPreferencesUI()
         self.util_options_form = UtilPreferencesUI()
 
 
         QtWidgets.qApp.installEventFilter(self)
         QtWidgets.qApp.installEventFilter(self)

+ 4 - 4
flatcamGUI/GUIElements.py

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

+ 4 - 5
flatcamGUI/PlotCanvas.py

@@ -1,10 +1,9 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # 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                                              #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 
 from PyQt5 import QtCore
 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 PyQt5.QtCore import QSettings
 from flatcamGUI.GUIElements import *
 from flatcamGUI.GUIElements import *
 import platform
 import platform
@@ -184,12 +191,46 @@ class ToolsPreferencesUI(QtWidgets.QWidget):
 
 
         self.vlay2 = QtWidgets.QVBoxLayout()
         self.vlay2 = QtWidgets.QVBoxLayout()
         self.vlay2.addWidget(self.tools_panelize_group)
         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 = QtWidgets.QVBoxLayout()
         self.vlay3.addWidget(self.tools_solderpaste_group)
         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.vlay)
         self.layout.addLayout(self.vlay1)
         self.layout.addLayout(self.vlay1)
@@ -4233,8 +4274,9 @@ class ToolsFilmPrefGroupUI(OptionsGroupUI):
         super(ToolsFilmPrefGroupUI, self).__init__(self)
         super(ToolsFilmPrefGroupUI, self).__init__(self)
 
 
         self.setTitle(str(_("Film Tool Options")))
         self.setTitle(str(_("Film Tool Options")))
+        self.decimals = 4
 
 
-        # ## Board cuttout
+        # ## Parameters
         self.film_label = QtWidgets.QLabel("<b>%s:</b>" % _("Parameters"))
         self.film_label = QtWidgets.QLabel("<b>%s:</b>" % _("Parameters"))
         self.film_label.setToolTip(
         self.film_label.setToolTip(
             _("Create a PCB film from a Gerber or Geometry\n"
             _("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_label, 3, 0)
         grid0.addWidget(self.film_scale_entry, 3, 1)
         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()
         self.layout.addStretch()
 
 
 
 
@@ -4539,7 +4689,7 @@ class ToolsTransformPrefGroupUI(OptionsGroupUI):
 
 
         # ## Skew/Shear Angle on X axis
         # ## Skew/Shear Angle on X axis
         self.skewx_entry = FCEntry()
         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(
         self.skewx_label.setToolTip(
             _("Angle for Skew action, in degrees.\n"
             _("Angle for Skew action, in degrees.\n"
               "Float number between -360 and 359.")
               "Float number between -360 and 359.")
@@ -4549,7 +4699,7 @@ class ToolsTransformPrefGroupUI(OptionsGroupUI):
 
 
         # ## Skew/Shear Angle on Y axis
         # ## Skew/Shear Angle on Y axis
         self.skewy_entry = FCEntry()
         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(
         self.skewy_label.setToolTip(
             _("Angle for Skew action, in degrees.\n"
             _("Angle for Skew action, in degrees.\n"
               "Float number between -360 and 359.")
               "Float number between -360 and 359.")
@@ -4559,7 +4709,7 @@ class ToolsTransformPrefGroupUI(OptionsGroupUI):
 
 
         # ## Scale factor on X axis
         # ## Scale factor on X axis
         self.scalex_entry = FCEntry()
         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(
         self.scalex_label.setToolTip(
             _("Factor for scaling on X axis.")
             _("Factor for scaling on X axis.")
         )
         )
@@ -4568,7 +4718,7 @@ class ToolsTransformPrefGroupUI(OptionsGroupUI):
 
 
         # ## Scale factor on X axis
         # ## Scale factor on X axis
         self.scaley_entry = FCEntry()
         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(
         self.scaley_label.setToolTip(
             _("Factor for scaling on Y axis.")
             _("Factor for scaling on Y axis.")
         )
         )
@@ -4595,7 +4745,7 @@ class ToolsTransformPrefGroupUI(OptionsGroupUI):
 
 
         # ## Offset distance on X axis
         # ## Offset distance on X axis
         self.offx_entry = FCEntry()
         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(
         self.offx_label.setToolTip(
            _("Distance to offset on X axis. In current units.")
            _("Distance to offset on X axis. In current units.")
         )
         )
@@ -4604,7 +4754,7 @@ class ToolsTransformPrefGroupUI(OptionsGroupUI):
 
 
         # ## Offset distance on Y axis
         # ## Offset distance on Y axis
         self.offy_entry = FCEntry()
         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(
         self.offy_label.setToolTip(
             _("Distance to offset on Y axis. In current units.")
             _("Distance to offset on Y axis. In current units.")
         )
         )
@@ -4834,6 +4984,50 @@ class ToolsSubPrefGroupUI(OptionsGroupUI):
         self.layout.addStretch()
         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):
 class FAExcPrefGroupUI(OptionsGroupUI):
     def __init__(self, parent=None):
     def __init__(self, parent=None):
         # OptionsGroupUI.__init__(self, "Excellon File associations Preferences", 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            #
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # http://flatcam.org                                       #
 # http://flatcam.org                                       #
 # File Author: Dennis Hayrullin                            #
 # File Author: Dennis Hayrullin                            #
 # Date: 2/5/2016                                           #
 # Date: 2/5/2016                                           #
 # MIT Licence                                              #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 
 import numpy as np
 import numpy as np
 from PyQt5.QtGui import QPalette
 from PyQt5.QtGui import QPalette

+ 2 - 2
flatcamGUI/VisPyPatches.py

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

+ 2 - 2
flatcamGUI/VisPyTesselators.py

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

+ 2 - 2
flatcamGUI/VisPyVisuals.py

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

+ 0 - 1
flatcamParsers/ParseDXF.py

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

+ 46 - 34
flatcamParsers/ParseDXF_Spline.py

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

+ 6 - 7
flatcamParsers/ParseFont.py

@@ -1,15 +1,14 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 3/10/2019                                          #
 # Date: 3/10/2019                                          #
 # MIT Licence                                              #
 # 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 re, os, sys, glob
 import itertools
 import itertools

+ 5 - 3
flatcamParsers/ParseSVG.py

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

+ 2 - 3
flatcamTools/ToolDistance.py

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

+ 0 - 1
flatcamTools/ToolDistanceMin.py

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

+ 206 - 21
flatcamTools/ToolFilm.py

@@ -1,10 +1,9 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 3/10/2019                                          #
 # Date: 3/10/2019                                          #
 # MIT Licence                                              #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 
 from FlatCAMTool import FlatCAMTool
 from FlatCAMTool import FlatCAMTool
 from FlatCAMObj import *
 from FlatCAMObj import *
@@ -31,6 +30,8 @@ class Film(FlatCAMTool):
     def __init__(self, app):
     def __init__(self, app):
         FlatCAMTool.__init__(self, app)
         FlatCAMTool.__init__(self, app)
 
 
+        self.decimals = 4
+
         # Title
         # Title
         title_label = QtWidgets.QLabel("%s" % self.toolName)
         title_label = QtWidgets.QLabel("%s" % self.toolName)
         title_label.setStyleSheet("""
         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_label, 3, 0)
         grid0.addWidget(self.tf_box_combo, 3, 1)
         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
         # 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"
             _("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"
               "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.")
               "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
         # Film Type
         self.film_type = RadioSet([{'label': _('Positive'), 'value': 'pos'},
         self.film_type = RadioSet([{'label': _('Positive'), 'value': 'pos'},
@@ -149,12 +271,15 @@ class Film(FlatCAMTool):
               "with white on a black canvas.\n"
               "with white on a black canvas.\n"
               "The Film format is SVG.")
               "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
         # Boundary for negative film generation
         self.boundary_entry = FCDoubleSpinner()
         self.boundary_entry = FCDoubleSpinner()
         self.boundary_entry.set_range(-999.9999, 999.9999)
         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 = QtWidgets.QLabel('%s:' % _("Border"))
         self.boundary_label.setToolTip(
         self.boundary_label.setToolTip(
             _("Specify a border around the object.\n"
             _("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"
               "white color like the rest and which may confound with the\n"
               "surroundings if not for this border.")
               "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_label.hide()
         self.boundary_entry.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"
         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"
                                    "the generated film is positive. This is done to help drilling,\n"
                                    "when done manually."))
                                    "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
         # this way I can hide/show the frame
         self.punch_frame = QtWidgets.QFrame()
         self.punch_frame = QtWidgets.QFrame()
@@ -199,8 +324,8 @@ class Film(FlatCAMTool):
               "- Pad Center -> will try to use the pads center as reference.")
               "- Pad Center -> will try to use the pads center as reference.")
         )
         )
         self.source_punch = RadioSet([{'label': _('Excellon'), 'value': 'exc'},
         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_label, 0, 0)
         punch_grid.addWidget(self.source_punch, 0, 1)
         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_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 = FCDoubleSpinner()
         self.punch_size_spinner.set_range(0, 999.9999)
         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_label, 2, 0)
         punch_grid.addWidget(self.punch_size_spinner, 2, 1)
         punch_grid.addWidget(self.punch_size_spinner, 2, 1)
@@ -304,7 +431,7 @@ class Film(FlatCAMTool):
         self.boundary_entry.set_value(float(b_entry))
         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
         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.punch_cb.set_value(False)
         self.source_punch.set_value('exc')
         self.source_punch.set_value('exc')
@@ -356,7 +483,7 @@ class Film(FlatCAMTool):
                                  _("No FlatCAM object selected. Load an object for Box and retry."))
                                  _("No FlatCAM object selected. Load an object for Box and retry."))
             return
             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()
         source = self.source_punch.get_value()
 
 
@@ -377,6 +504,29 @@ class Film(FlatCAMTool):
 
 
     def generate_positive_normal_film(self, name, boxname, factor):
     def generate_positive_normal_film(self, name, boxname, factor):
         log.debug("ToolFilm.Film.generate_positive_normal_film() started ...")
         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:
         try:
             filename, _f = QtWidgets.QFileDialog.getSaveFileName(
             filename, _f = QtWidgets.QFileDialog.getSaveFileName(
                 caption=_("Export SVG positive"),
                 caption=_("Export SVG positive"),
@@ -391,7 +541,13 @@ class Film(FlatCAMTool):
             self.app.inform.emit('[WARNING_NOTCL] %s' % _("Export SVG positive cancelled."))
             self.app.inform.emit('[WARNING_NOTCL] %s' % _("Export SVG positive cancelled."))
             return
             return
         else:
         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):
     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):
     def generate_negative_film(self, name, boxname, factor):
         log.debug("ToolFilm.Film.generate_negative_film() started ...")
         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())
         border = float(self.boundary_entry.get_value())
 
 
         if border is None:
         if border is None:
@@ -492,7 +671,13 @@ class Film(FlatCAMTool):
             self.app.inform.emit('[WARNING_NOTCL] %s' % _("Export SVG negative cancelled."))
             self.app.inform.emit('[WARNING_NOTCL] %s' % _("Export SVG negative cancelled."))
             return
             return
         else:
         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):
     def reset_fields(self):
         self.tf_object_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
         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            #
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # File Author: Marius Adrian Stanciu (c)                   #
 # Date: 3/10/2019                                          #
 # Date: 3/10/2019                                          #
 # MIT Licence                                              #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 
 from FlatCAMTool import FlatCAMTool
 from FlatCAMTool import FlatCAMTool
 
 

+ 0 - 1
flatcamTools/ToolMove.py

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

+ 2 - 3
flatcamTools/ToolNonCopperClear.py

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

+ 0 - 1
flatcamTools/ToolOptimal.py

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

+ 2 - 3
flatcamTools/ToolPDF.py

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

+ 0 - 1
flatcamTools/ToolPaint.py

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

+ 2 - 3
flatcamTools/ToolPanelize.py

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

+ 2 - 3
flatcamTools/ToolPcbWizard.py

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

+ 2 - 3
flatcamTools/ToolProperties.py

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

+ 20 - 18
flatcamTools/ToolRulesCheck.py

@@ -1,10 +1,9 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # FlatCAM: 2D Post-processing for Manufacturing            #
-# http://flatcam.org                                       #
 # File Author: Marius Adrian Stanciu (c)                   #
 # File Author: Marius Adrian Stanciu (c)                   #
-# Date: 09/27/2019                                          #
+# Date: 09/27/2019                                         #
 # MIT Licence                                              #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 
 from FlatCAMTool import FlatCAMTool
 from FlatCAMTool import FlatCAMTool
 from copy import copy, deepcopy
 from copy import copy, deepcopy
@@ -602,9 +601,7 @@ class RulesCheck(FlatCAMTool):
             total_geo = total_geo.buffer(0.000001)
             total_geo = total_geo.buffer(0.000001)
 
 
         if isinstance(total_geo, Polygon):
         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]
             return rule_title, [obj_violations]
         else:
         else:
             iterations = len(total_geo)
             iterations = len(total_geo)
@@ -846,21 +843,26 @@ class RulesCheck(FlatCAMTool):
             dia_list = []
             dia_list = []
             points_list = []
             points_list = []
             name = elem['name']
             name = elem['name']
+
             for apid in elem['apertures']:
             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['name'] = name
             obj_violations['size'] = dia_list
             obj_violations['size'] = dia_list
             obj_violations['points'] = points_list
             obj_violations['points'] = points_list
             violations.append(deepcopy(obj_violations))
             violations.append(deepcopy(obj_violations))
-
         return rule, violations
         return rule, violations
 
 
     @staticmethod
     @staticmethod
@@ -1025,7 +1027,7 @@ class RulesCheck(FlatCAMTool):
         log.debug("RuleCheck() executing")
         log.debug("RuleCheck() executing")
 
 
         def worker_job(app_obj):
         def worker_job(app_obj):
-            proc = self.app.proc_container.new(_("Working..."))
+            self.app.proc_container.new(_("Working..."))
 
 
             # RULE: Check Trace Size
             # RULE: Check Trace Size
             if self.trace_size_cb.get_value():
             if self.trace_size_cb.get_value():
@@ -1518,7 +1520,7 @@ class RulesCheck(FlatCAMTool):
             new_obj.source_file = txt
             new_obj.source_file = txt
             new_obj.read_only = True
             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):
     def reset_fields(self):
         # self.object_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
         # 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            #
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # http://flatcam.org                                       #
 # http://flatcam.org                                       #
 # Author: Juan Pablo Caram (c)                             #
 # Author: Juan Pablo Caram (c)                             #
 # Date: 2/5/2014                                           #
 # Date: 2/5/2014                                           #
 # MIT Licence                                              #
 # MIT Licence                                              #
-# ########################################################## ##
+# ##########################################################
 
 
 # from PyQt5.QtCore import pyqtSignal
 # from PyQt5.QtCore import pyqtSignal
 from PyQt5.QtCore import Qt
 from PyQt5.QtCore import Qt

+ 2 - 3
flatcamTools/ToolSolderPaste.py

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

+ 2 - 3
flatcamTools/ToolSub.py

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

+ 2 - 3
flatcamTools/ToolTransform.py

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

+ 5 - 5
make_win.py

@@ -1,4 +1,4 @@
-# ########################################################## ##
+# ##########################################################
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # FlatCAM: 2D Post-processing for Manufacturing            #
 # http://flatcam.org                                       #
 # http://flatcam.org                                       #
 # Author: Juan Pablo Caram (c)                             #
 # Author: Juan Pablo Caram (c)                             #
@@ -11,12 +11,12 @@
 # This is not an aid to install FlatCAM from source on     #
 # This is not an aid to install FlatCAM from source on     #
 # Windows platforms. It is only useful when FlatCAM is up  #
 # Windows platforms. It is only useful when FlatCAM is up  #
 # and running and ready to be packaged.                    #
 # and running and ready to be packaged.                    #
-# ########################################################## ##
+# ##########################################################
 
 
-# ########################################################## ##
-# File Modified (major mod): Marius Adrian Stanciu         #
+# ##########################################################
+# File Modified: Marius Adrian Stanciu                     #
 # Date: 3/10/2019                                          #
 # Date: 3/10/2019                                          #
-# ########################################################## ##
+# ##########################################################
 
 
 
 
 # Files not needed: Qt, tk.dll, tcl.dll, tk/, tcl/, vtk/,
 # 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 tclCommands.TclCommand import TclCommand
 from ObjectCollection import *
 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 ObjectCollection import *
 from tclCommands.TclCommand import TclCommand
 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 *
 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 ObjectCollection import *
 from tclCommands.TclCommand import TclCommandSignaled
 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 ObjectCollection import *
 from tclCommands.TclCommand import TclCommandSignaled
 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 ObjectCollection import *
 from tclCommands.TclCommand import TclCommandSignaled
 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 ObjectCollection import *
 from tclCommands.TclCommand import TclCommandSignaled
 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 ObjectCollection import *
 from tclCommands.TclCommand import TclCommand
 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 ObjectCollection import *
 from tclCommands.TclCommand import TclCommand
 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 *
 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 tclCommands.TclCommand import TclCommand
 from ObjectCollection import *
 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