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

- fixed the Edit -> Conversion -> Join ... functions (merge() functions)
- updated translations
- Russian translate by @camellan is not finished yet
- some PEP8 cleanup in camlib.py
- RELEASE 8.918

Marius Stanciu 6 лет назад
Родитель
Сommit
a106472900

+ 9 - 9
FlatCAMApp.py

@@ -95,7 +95,7 @@ class App(QtCore.QObject):
 
 
     # Version
     # Version
     version = 8.918
     version = 8.918
-    version_date = "2019/06/09"
+    version_date = "2019/06/11"
     beta = True
     beta = True
 
 
     # current date now
     # current date now
@@ -3457,14 +3457,14 @@ class App(QtCore.QObject):
         obj_name_multi = str(name) if name else "Combo_MultiGeo"
         obj_name_multi = str(name) if name else "Combo_MultiGeo"
 
 
         tooldias = []
         tooldias = []
-        geo_type_list = []
+        geo_type_list = set()
 
 
         objs = self.collection.get_selected()
         objs = self.collection.get_selected()
         for obj in objs:
         for obj in objs:
-            geo_type_list.append(obj.multigeo)
+            geo_type_list.add(obj.multigeo)
 
 
-        # if len(set(geo_type_list)) == 1 means that all list elements are the same
-        if len(set(geo_type_list)) != 1:
+        # if len(geo_type_list) == 1 means that all list elements are the same
+        if len(geo_type_list) != 1:
             self.inform.emit(_("[ERROR] Failed join. The Geometry objects are of different types.\n"
             self.inform.emit(_("[ERROR] Failed join. The Geometry objects are of different types.\n"
                                "At least one is MultiGeo type and the other is SingleGeo type. A possibility is to "
                                "At least one is MultiGeo type and the other is SingleGeo type. A possibility is to "
                                "convert from one to another and retry joining \n"
                                "convert from one to another and retry joining \n"
@@ -3476,7 +3476,7 @@ class App(QtCore.QObject):
         # if at least one True object is in the list then due of the previous check, all list elements are True objects
         # if at least one True object is in the list then due of the previous check, all list elements are True objects
         if True in geo_type_list:
         if True in geo_type_list:
             def initialize(obj, app):
             def initialize(obj, app):
-                FlatCAMGeometry.merge(objs, obj, multigeo=True)
+                FlatCAMGeometry.merge(self, geo_list=objs, geo_final=obj, multigeo=True)
 
 
                 # rename all the ['name] key in obj.tools[tooluid]['data'] to the obj_name_multi
                 # rename all the ['name] key in obj.tools[tooluid]['data'] to the obj_name_multi
                 for v in obj.tools.values():
                 for v in obj.tools.values():
@@ -3484,7 +3484,7 @@ class App(QtCore.QObject):
             self.new_object("geometry", obj_name_multi, initialize)
             self.new_object("geometry", obj_name_multi, initialize)
         else:
         else:
             def initialize(obj, app):
             def initialize(obj, app):
-                FlatCAMGeometry.merge(objs, obj, multigeo=False)
+                FlatCAMGeometry.merge(self, geo_list=objs, geo_final=obj, multigeo=False)
 
 
                 # rename all the ['name] key in obj.tools[tooluid]['data'] to the obj_name_multi
                 # rename all the ['name] key in obj.tools[tooluid]['data'] to the obj_name_multi
                 for v in obj.tools.values():
                 for v in obj.tools.values():
@@ -3510,7 +3510,7 @@ class App(QtCore.QObject):
                 return
                 return
 
 
         def initialize(obj, app):
         def initialize(obj, app):
-            FlatCAMExcellon.merge(objs, obj)
+            FlatCAMExcellon.merge(self, exc_list=objs, exc_final=obj)
 
 
         self.new_object("excellon", 'Combo_Excellon', initialize)
         self.new_object("excellon", 'Combo_Excellon', initialize)
         self.should_we_save = True
         self.should_we_save = True
@@ -3532,7 +3532,7 @@ class App(QtCore.QObject):
                 return
                 return
 
 
         def initialize(obj, app):
         def initialize(obj, app):
-            FlatCAMGerber.merge(objs, obj)
+            FlatCAMGerber.merge(self, grb_list=objs, grb_final=obj)
 
 
         self.new_object("gerber", 'Combo_Gerber', initialize)
         self.new_object("gerber", 'Combo_Gerber', initialize)
         self.should_we_save = True
         self.should_we_save = True

+ 35 - 71
FlatCAMObj.py

@@ -387,8 +387,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
 
 
     ui_type = GerberObjectUI
     ui_type = GerberObjectUI
 
 
-    @staticmethod
-    def merge(grb_list, grb_final):
+    def merge(self, grb_list, grb_final):
         """
         """
         Merges the geometry of objects in geo_list into
         Merges the geometry of objects in geo_list into
         the geometry of geo_final.
         the geometry of geo_final.
@@ -1590,15 +1589,14 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
         # store the source file here
         # store the source file here
         self.source_file = ""
         self.source_file = ""
 
 
-        self.multigeo = True
+        self.multigeo = False
 
 
         # Attributes to be included in serialization
         # Attributes to be included in serialization
         # Always append to it because it carries contents
         # Always append to it because it carries contents
         # from predecessors.
         # from predecessors.
         self.ser_attrs += ['options', 'kind']
         self.ser_attrs += ['options', 'kind']
 
 
-    @staticmethod
-    def merge(exc_list, exc_final):
+    def merge(self, exc_list, exc_final):
         """
         """
         Merge Excellon objects found in exc_list parameter into exc_final object.
         Merge Excellon objects found in exc_list parameter into exc_final object.
         Options are always copied from source .
         Options are always copied from source .
@@ -1659,10 +1657,13 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
             exc_final.zeros = exc.zeros
             exc_final.zeros = exc.zeros
             exc_final.units = exc.units
             exc_final.units = exc.units
 
 
+        # ##########################################
+        # Here we add data to the exc_final object #
+        # ##########################################
+
         # variable to make tool_name for the tools
         # variable to make tool_name for the tools
         current_tool = 0
         current_tool = 0
-        # Here we add data to the exc_final object
-        # the tools diameter are now the keys in the drill_dia dict and the values are the Shapely Points in case of
+        # The tools diameter are now the keys in the drill_dia dict and the values are the Shapely Points in case of
         # drills
         # drills
         for tool_dia in custom_dict_drills:
         for tool_dia in custom_dict_drills:
             # we create a tool name for each key in the drill_dia dict (the key is a unique drill diameter)
             # we create a tool name for each key in the drill_dia dict (the key is a unique drill diameter)
@@ -1681,8 +1682,7 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
                     }
                     }
                 )
                 )
 
 
-        # Here we add data to the exc_final object
-        # the tools diameter are now the keys in the drill_dia dict and the values are a list ([start, stop])
+        # The tools diameter are now the keys in the drill_dia dict and the values are a list ([start, stop])
         # of two Shapely Points in case of slots
         # of two Shapely Points in case of slots
         for tool_dia in custom_dict_slots:
         for tool_dia in custom_dict_slots:
             # we create a tool name for each key in the slot_dia dict (the key is a unique slot diameter)
             # we create a tool name for each key in the slot_dia dict (the key is a unique slot diameter)
@@ -2771,25 +2771,25 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
         if not FlatCAMObj.plot(self):
         if not FlatCAMObj.plot(self):
             return
             return
 
 
-        try:
-            # Plot excellon (All polygons?)
-            if self.options["solid"]:
-                for tool in self.tools:
-                    for geo in self.tools[tool]['solid_geometry']:
-                        self.add_shape(shape=geo, color='#750000BF', face_color='#C40000BF',
-                                       visible=self.options['plot'],
-                                       layer=2)
-            else:
-                for tool in self.tools:
-                    for geo in self.tools[tool]['solid_geometry']:
-                        self.add_shape(shape=geo.exterior, color='red', visible=self.options['plot'])
-                        for ints in geo.interiors:
-                            self.add_shape(shape=ints, color='green', visible=self.options['plot'])
-
-            self.shapes.redraw()
-            return
-        except (ObjectDeleted, AttributeError, KeyError):
-            self.shapes.clear(update=True)
+        # try:
+        #     # Plot Excellon (All polygons?)
+        #     if self.options["solid"]:
+        #         for tool in self.tools:
+        #             for geo in self.tools[tool]['solid_geometry']:
+        #                 self.add_shape(shape=geo, color='#750000BF', face_color='#C40000BF',
+        #                                visible=self.options['plot'],
+        #                                layer=2)
+        #     else:
+        #         for tool in self.tools:
+        #             for geo in self.tools[tool]['solid_geometry']:
+        #                 self.add_shape(shape=geo.exterior, color='red', visible=self.options['plot'])
+        #                 for ints in geo.interiors:
+        #                     self.add_shape(shape=ints, color='orange', visible=self.options['plot'])
+        #
+        #     self.shapes.redraw()
+        #     return
+        # except (ObjectDeleted, AttributeError, KeyError):
+        #     self.shapes.clear(update=True)
 
 
         # this stays for compatibility reasons, in case we try to open old projects
         # this stays for compatibility reasons, in case we try to open old projects
         try:
         try:
@@ -2798,55 +2798,22 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
             self.solid_geometry = [self.solid_geometry]
             self.solid_geometry = [self.solid_geometry]
 
 
         try:
         try:
-            # Plot excellon (All polygons?)
+            # Plot Excellon (All polygons?)
             if self.options["solid"]:
             if self.options["solid"]:
                 for geo in self.solid_geometry:
                 for geo in self.solid_geometry:
-                    self.add_shape(shape=geo, color='#750000BF', face_color='#C40000BF', visible=self.options['plot'],
+                    self.add_shape(shape=geo, color='#750000BF', face_color='#C40000BF',
+                                   visible=self.options['plot'],
                                    layer=2)
                                    layer=2)
             else:
             else:
                 for geo in self.solid_geometry:
                 for geo in self.solid_geometry:
                     self.add_shape(shape=geo.exterior, color='red', visible=self.options['plot'])
                     self.add_shape(shape=geo.exterior, color='red', visible=self.options['plot'])
                     for ints in geo.interiors:
                     for ints in geo.interiors:
-                        self.add_shape(shape=ints, color='green', visible=self.options['plot'])
+                        self.add_shape(shape=ints, color='orange', visible=self.options['plot'])
 
 
             self.shapes.redraw()
             self.shapes.redraw()
         except (ObjectDeleted, AttributeError):
         except (ObjectDeleted, AttributeError):
             self.shapes.clear(update=True)
             self.shapes.clear(update=True)
 
 
-        # try:
-        #     # Plot excellon (All polygons?)
-        #     if self.options["solid"]:
-        #         for geo_type in self.solid_geometry:
-        #             if geo_type is not None:
-        #                 if type(geo_type) is dict:
-        #                     for tooldia in geo_type:
-        #                         geo_list = geo_type[tooldia]
-        #                         for geo in geo_list:
-        #                             self.add_shape(shape=geo, color='#750000BF', face_color='#C40000BF',
-        #                                            visible=self.options['plot'],
-        #                                            layer=2)
-        #                 else:
-        #                     self.add_shape(shape=geo_type, color='#750000BF', face_color='#C40000BF',
-        #                                    visible=self.options['plot'],
-        #                                    layer=2)
-        #     else:
-        #         for geo_type in self.solid_geometry:
-        #             if geo_type is not None:
-        #                 if type(geo_type) is dict:
-        #                     for tooldia in geo_type:
-        #                         geo_list = geo_type[tooldia]
-        #                         for geo in geo_list:
-        #                             self.add_shape(shape=geo.exterior, color='red', visible=self.options['plot'])
-        #                             for ints in geo.interiors:
-        #                                 self.add_shape(shape=ints, color='green', visible=self.options['plot'])
-        #                 else:
-        #                     self.add_shape(shape=geo_type.exterior, color='red', visible=self.options['plot'])
-        #                     for ints in geo_type.interiors:
-        #                         self.add_shape(shape=ints, color='green', visible=self.options['plot'])
-        #     self.shapes.redraw()
-        # except (ObjectDeleted, AttributeError):
-        #     self.shapes.clear(update=True)
-
 
 
 class FlatCAMGeometry(FlatCAMObj, Geometry):
 class FlatCAMGeometry(FlatCAMObj, Geometry):
     """
     """
@@ -2856,8 +2823,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
     optionChanged = QtCore.pyqtSignal(str)
     optionChanged = QtCore.pyqtSignal(str)
     ui_type = GeometryObjectUI
     ui_type = GeometryObjectUI
 
 
-    @staticmethod
-    def merge(geo_list, geo_final, multigeo=None):
+    def merge(self, geo_list, geo_final, multigeo=None):
         """
         """
         Merges the geometry of objects in grb_list into
         Merges the geometry of objects in grb_list into
         the geometry of geo_final.
         the geometry of geo_final.
@@ -2873,8 +2839,6 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
         if type(geo_final.solid_geometry) is not list:
         if type(geo_final.solid_geometry) is not list:
             geo_final.solid_geometry = [geo_final.solid_geometry]
             geo_final.solid_geometry = [geo_final.solid_geometry]
 
 
-
-
         for geo in geo_list:
         for geo in geo_list:
             for option in geo.options:
             for option in geo.options:
                 if option is not 'name':
                 if option is not 'name':
@@ -2885,11 +2849,11 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
 
 
             # Expand lists
             # Expand lists
             if type(geo) is list:
             if type(geo) is list:
-                FlatCAMGeometry.merge(geo, geo_final)
+                FlatCAMGeometry.merge(self, geo_list=geo, geo_final=geo_final)
             # If not list, just append
             # If not list, just append
             else:
             else:
                 # merge solid_geometry, useful for singletool geometry, for multitool each is empty
                 # merge solid_geometry, useful for singletool geometry, for multitool each is empty
-                if multigeo is None or multigeo == False:
+                if multigeo is None or multigeo is False:
                     geo_final.multigeo = False
                     geo_final.multigeo = False
                     try:
                     try:
                         geo_final.solid_geometry.append(geo.solid_geometry)
                         geo_final.solid_geometry.append(geo.solid_geometry)

+ 8 - 0
README.md

@@ -9,6 +9,14 @@ CAD program, and create G-Code for Isolation routing.
 
 
 =================================================
 =================================================
 
 
+11.06.2019
+
+- fixed the Edit -> Conversion -> Join ... functions (merge() functions)
+- updated translations
+- Russian translate by @camellan is not finished yet
+- some PEP8 cleanup in camlib.py
+- RELEASE 8.918
+
 9.06.2019
 9.06.2019
 
 
 - updated translations
 - updated translations

+ 55 - 42
camlib.py

@@ -52,16 +52,15 @@ from flatcamParsers.ParseDXF import *
 
 
 import logging
 import logging
 import FlatCAMApp
 import FlatCAMApp
+import gettext
+import FlatCAMTranslation as fcTranslate
+import builtins
 
 
 if platform.architecture()[0] == '64bit':
 if platform.architecture()[0] == '64bit':
     from ortools.constraint_solver import pywrapcp
     from ortools.constraint_solver import pywrapcp
     from ortools.constraint_solver import routing_enums_pb2
     from ortools.constraint_solver import routing_enums_pb2
 
 
-import gettext
-import FlatCAMTranslation as fcTranslate
-
 fcTranslate.apply_language('strings')
 fcTranslate.apply_language('strings')
-import builtins
 
 
 log = logging.getLogger('base2')
 log = logging.getLogger('base2')
 log.setLevel(logging.DEBUG)
 log.setLevel(logging.DEBUG)
@@ -513,8 +512,8 @@ class Geometry(object):
         :param offset: Offset distance.
         :param offset: Offset distance.
         :type offset: float
         :type offset: float
         :param iso_type: type of isolation, can be 0 = exteriors or 1 = interiors or 2 = both (complete)
         :param iso_type: type of isolation, can be 0 = exteriors or 1 = interiors or 2 = both (complete)
-        :type integer
         :param corner: type of corner for the isolation: 0 = round; 1 = square; 2= beveled (line that connects the ends)
         :param corner: type of corner for the isolation: 0 = round; 1 = square; 2= beveled (line that connects the ends)
+        :param follow: whether the geometry to be isolated is a follow_geometry
         :return: The buffered geometry.
         :return: The buffered geometry.
         :rtype: Shapely.MultiPolygon or Shapely.Polygon
         :rtype: Shapely.MultiPolygon or Shapely.Polygon
         """
         """
@@ -533,7 +532,6 @@ class Geometry(object):
         #         geo_iso.append(self.solid_geometry.buffer(offset, int(int(self.geo_steps_per_circle) / 4)))
         #         geo_iso.append(self.solid_geometry.buffer(offset, int(int(self.geo_steps_per_circle) / 4)))
         # return geo_iso
         # return geo_iso
 
 
-
         # commented this because of the bug with multiple passes cutting out of the copper
         # commented this because of the bug with multiple passes cutting out of the copper
         # geo_iso = []
         # geo_iso = []
         # flattened_geo = self.flatten_list(self.solid_geometry)
         # flattened_geo = self.flatten_list(self.solid_geometry)
@@ -543,7 +541,6 @@ class Geometry(object):
         # except TypeError:
         # except TypeError:
         #     geo_iso.append(self.solid_geometry.buffer(offset, int(int(self.geo_steps_per_circle) / 4)))
         #     geo_iso.append(self.solid_geometry.buffer(offset, int(int(self.geo_steps_per_circle) / 4)))
 
 
-
         # the previously commented block is replaced with this block - regression - to solve the bug with multiple
         # the previously commented block is replaced with this block - regression - to solve the bug with multiple
         # isolation passes cutting from the copper features
         # isolation passes cutting from the copper features
         if offset == 0:
         if offset == 0:
@@ -587,8 +584,10 @@ class Geometry(object):
 
 
         :param filename: Path to the SVG file.
         :param filename: Path to the SVG file.
         :type filename: str
         :type filename: str
+        :param object_type: parameter passed further along
         :param flip: Flip the vertically.
         :param flip: Flip the vertically.
         :type flip: bool
         :type flip: bool
+        :param units: FlatCAM units
         :return: None
         :return: None
         """
         """
 
 
@@ -682,6 +681,10 @@ class Geometry(object):
         :type filename: str
         :type filename: str
         :param flip: Flip the object vertically.
         :param flip: Flip the object vertically.
         :type flip: bool
         :type flip: bool
+        :param units: FlatCAM units
+        :param dpi: dots per inch on the imported image
+        :param mode: how to import the image: as 'black' or 'color'
+        :param mask: level of detail for the import
         :return: None
         :return: None
         """
         """
         scale_factor = 0.264583333
         scale_factor = 0.264583333
@@ -780,8 +783,7 @@ class Geometry(object):
         return boundary.difference(self.solid_geometry)
         return boundary.difference(self.solid_geometry)
         
         
     @staticmethod
     @staticmethod
-    def clear_polygon(polygon, tooldia, steps_per_circle, overlap=0.15, connect=True,
-                        contour=True):
+    def clear_polygon(polygon, tooldia, steps_per_circle, overlap=0.15, connect=True, contour=True):
         """
         """
         Creates geometry inside a polygon for a tool to cover
         Creates geometry inside a polygon for a tool to cover
         the whole area.
         the whole area.
@@ -791,6 +793,7 @@ class Geometry(object):
 
 
         :param polygon: Polygon to clear.
         :param polygon: Polygon to clear.
         :param tooldia: Diameter of the tool.
         :param tooldia: Diameter of the tool.
+        :param steps_per_circle: number of linear segments to be used to approximate a circle
         :param overlap: Overlap of toolpasses.
         :param overlap: Overlap of toolpasses.
         :param connect: Draw lines between disjoint segments to
         :param connect: Draw lines between disjoint segments to
                         minimize tool lifts.
                         minimize tool lifts.
@@ -875,6 +878,7 @@ class Geometry(object):
         the polygon.
         the polygon.
 
 
         :param polygon_to_clear: Shapely.geometry.Polygon
         :param polygon_to_clear: Shapely.geometry.Polygon
+        :param steps_per_circle: how many linear segments to use to approximate a circle
         :param tooldia: Diameter of the tool
         :param tooldia: Diameter of the tool
         :param seedpoint: Shapely.geometry.Point or None
         :param seedpoint: Shapely.geometry.Point or None
         :param overlap: Tool fraction overlap bewteen passes
         :param overlap: Tool fraction overlap bewteen passes
@@ -916,8 +920,8 @@ class Geometry(object):
             if path.is_empty:
             if path.is_empty:
                 break
                 break
             else:
             else:
-                #geoms.append(path)
-                #geoms.insert(path)
+                # geoms.append(path)
+                # geoms.insert(path)
                 # path can be a collection of paths.
                 # path can be a collection of paths.
                 try:
                 try:
                     for p in path:
                     for p in path:
@@ -929,12 +933,14 @@ class Geometry(object):
 
 
         # Clean inside edges (contours) of the original polygon
         # Clean inside edges (contours) of the original polygon
         if contour:
         if contour:
-            outer_edges = [x.exterior for x in autolist(polygon_to_clear.buffer(-tooldia / 2, int(steps_per_circle / 4)))]
+            outer_edges = [x.exterior for x in autolist(
+                polygon_to_clear.buffer(-tooldia / 2, int(steps_per_circle / 4)))]
             inner_edges = []
             inner_edges = []
-            for x in autolist(polygon_to_clear.buffer(-tooldia / 2, int(steps_per_circle / 4))):  # Over resulting polygons
+            # Over resulting polygons
+            for x in autolist(polygon_to_clear.buffer(-tooldia / 2, int(steps_per_circle / 4))):
                 for y in x.interiors:  # Over interiors of each polygon
                 for y in x.interiors:  # Over interiors of each polygon
                     inner_edges.append(y)
                     inner_edges.append(y)
-            #geoms += outer_edges + inner_edges
+            # geoms += outer_edges + inner_edges
             for g in outer_edges + inner_edges:
             for g in outer_edges + inner_edges:
                 geoms.insert(g)
                 geoms.insert(g)
 
 
@@ -950,8 +956,7 @@ class Geometry(object):
         return geoms
         return geoms
 
 
     @staticmethod
     @staticmethod
-    def clear_polygon3(polygon, tooldia, steps_per_circle, overlap=0.15, connect=True,
-                       contour=True):
+    def clear_polygon3(polygon, tooldia, steps_per_circle, overlap=0.15, connect=True, contour=True):
         """
         """
         Creates geometry inside a polygon for a tool to cover
         Creates geometry inside a polygon for a tool to cover
         the whole area.
         the whole area.
@@ -961,6 +966,7 @@ class Geometry(object):
         :param polygon: The polygon being painted.
         :param polygon: The polygon being painted.
         :type polygon: shapely.geometry.Polygon
         :type polygon: shapely.geometry.Polygon
         :param tooldia: Tool diameter.
         :param tooldia: Tool diameter.
+        :param steps_per_circle: how many linear segments to use to approximate a circle
         :param overlap: Tool path overlap percentage.
         :param overlap: Tool path overlap percentage.
         :param connect: Connect lines to avoid tool lifts.
         :param connect: Connect lines to avoid tool lifts.
         :param contour: Paint around the edges.
         :param contour: Paint around the edges.
@@ -1026,8 +1032,11 @@ class Geometry(object):
         """
         """
         Scales all of the object's geometry by a given factor. Override
         Scales all of the object's geometry by a given factor. Override
         this method.
         this method.
-        :param factor: Number by which to scale.
-        :type factor: float
+        :param xfactor: Number by which to scale on X axis.
+        :type xfactor: float
+        :param yfactor: Number by which to scale on Y axis.
+        :type yfactor: float
+        :param point: point to be used as reference for scaling; a tuple
         :return: None
         :return: None
         :rtype: None
         :rtype: None
         """
         """
@@ -1055,6 +1064,7 @@ class Geometry(object):
         :type boundary: Polygon
         :type boundary: Polygon
         :param tooldia: Tool diameter.
         :param tooldia: Tool diameter.
         :rtype tooldia: float
         :rtype tooldia: float
+        :param steps_per_circle: how many linear segments to use to approximate a circle
         :param max_walk: Maximum allowable distance without lifting tool.
         :param max_walk: Maximum allowable distance without lifting tool.
         :type max_walk: float or None
         :type max_walk: float or None
         :return: Optimized geometry.
         :return: Optimized geometry.
@@ -1094,7 +1104,7 @@ class Geometry(object):
         try:
         try:
             while True:
             while True:
                 path_count += 1
                 path_count += 1
-                #log.debug("Path %d" % path_count)
+                # log.debug("Path %d" % path_count)
 
 
                 pt, candidate = storage.nearest(current_pt)
                 pt, candidate = storage.nearest(current_pt)
                 storage.remove(candidate)
                 storage.remove(candidate)
@@ -1112,7 +1122,7 @@ class Geometry(object):
                 walk_cut = walk_path.buffer(tooldia / 2, int(steps_per_circle / 4))
                 walk_cut = walk_path.buffer(tooldia / 2, int(steps_per_circle / 4))
 
 
                 if walk_cut.within(boundary) and walk_path.length < max_walk:
                 if walk_cut.within(boundary) and walk_path.length < max_walk:
-                    #log.debug("Walk to path #%d is inside. Joining." % path_count)
+                    # log.debug("Walk to path #%d is inside. Joining." % path_count)
 
 
                     # Completely inside. Append...
                     # Completely inside. Append...
                     geo.coords = list(geo.coords) + list(candidate.coords)
                     geo.coords = list(geo.coords) + list(candidate.coords)
@@ -1136,7 +1146,7 @@ class Geometry(object):
                 # pt, geo = storage.nearest(current_pt)
                 # pt, geo = storage.nearest(current_pt)
 
 
         except StopIteration:  # Nothing left in storage.
         except StopIteration:  # Nothing left in storage.
-            #pass
+            # pass
             optimized_paths.insert(geo)
             optimized_paths.insert(geo)
 
 
         return optimized_paths
         return optimized_paths
@@ -1273,7 +1283,7 @@ class Geometry(object):
             return 1.0
             return 1.0
 
 
         self.units = units
         self.units = units
-        self.scale(factor)
+        self.scale(factor, factor)
         self.file_units_factor = factor
         self.file_units_factor = factor
         return factor
         return factor
 
 
@@ -1370,7 +1380,7 @@ class Geometry(object):
                     new_obj.append(mirror_geom(g))
                     new_obj.append(mirror_geom(g))
                 return new_obj
                 return new_obj
             else:
             else:
-                return affinity.scale(obj, xscale, yscale, origin=(px,py))
+                return affinity.scale(obj, xscale, yscale, origin=(px, py))
 
 
         try:
         try:
             if self.multigeo is True:
             if self.multigeo is True:
@@ -1534,7 +1544,7 @@ class ApertureMacro:
         # Separate parts
         # Separate parts
         parts = self.raw.split('*')
         parts = self.raw.split('*')
 
 
-        #### Every part in the macro ## ##
+        # ### Every part in the macro ####
         for part in parts:
         for part in parts:
             # ## Comments. Ignored.
             # ## Comments. Ignored.
             match = ApertureMacro.amcomm_re.search(part)
             match = ApertureMacro.amcomm_re.search(part)
@@ -2404,7 +2414,7 @@ class Gerber (Geometry):
                         if match.group(2):  # Append
                         if match.group(2):  # Append
                             self.aperture_macros[current_macro].append(match.group(2))
                             self.aperture_macros[current_macro].append(match.group(2))
                         if match.group(3):  # Finish macro
                         if match.group(3):  # Finish macro
-                            #self.aperture_macros[current_macro].parse_content()
+                            # self.aperture_macros[current_macro].parse_content()
                             current_macro = None
                             current_macro = None
                             log.debug("Macro complete in 1 line.")
                             log.debug("Macro complete in 1 line.")
                         continue
                         continue
@@ -2414,7 +2424,7 @@ class Gerber (Geometry):
                     if match:  # Finish macro
                     if match:  # Finish macro
                         log.debug("End of macro. Line %d." % line_num)
                         log.debug("End of macro. Line %d." % line_num)
                         self.aperture_macros[current_macro].append(match.group(1))
                         self.aperture_macros[current_macro].append(match.group(1))
-                        #self.aperture_macros[current_macro].parse_content()
+                        # self.aperture_macros[current_macro].parse_content()
                         current_macro = None
                         current_macro = None
                     else:  # Append
                     else:  # Append
                         self.aperture_macros[current_macro].append(gline)
                         self.aperture_macros[current_macro].append(gline)
@@ -2592,7 +2602,7 @@ class Gerber (Geometry):
                     # is not and error.
                     # is not and error.
                     if len(path) < 3:
                     if len(path) < 3:
                         # print "ERROR: Path contains less than 3 points:"
                         # print "ERROR: Path contains less than 3 points:"
-                        #path = [[current_x, current_y]]
+                        # path = [[current_x, current_y]]
                         continue
                         continue
 
 
                     # For regions we may ignore an aperture that is None
                     # For regions we may ignore an aperture that is None
@@ -2765,8 +2775,8 @@ class Gerber (Geometry):
                                 except ValueError:
                                 except ValueError:
                                     log.warning("Problem %s %s" % (gline, line_num))
                                     log.warning("Problem %s %s" % (gline, line_num))
                                     self.app.inform.emit(_("[ERROR] Region does not have enough points. "
                                     self.app.inform.emit(_("[ERROR] Region does not have enough points. "
-                                                         "File will be processed but there are parser errors. "
-                                                         "Line number: %s") % str(line_num))
+                                                           "File will be processed but there are parser errors. "
+                                                           "Line number: %s") % str(line_num))
                             else:
                             else:
                                 if last_path_aperture is None:
                                 if last_path_aperture is None:
                                     log.warning("No aperture defined for curent path. (%d)" % line_num)
                                     log.warning("No aperture defined for curent path. (%d)" % line_num)
@@ -2860,7 +2870,7 @@ class Gerber (Geometry):
 
 
                         # this treats the case when we are storing geometry as solids
                         # this treats the case when we are storing geometry as solids
                         flash = self.create_flash_geometry(
                         flash = self.create_flash_geometry(
-                            Point( [linear_x, linear_y]),
+                            Point([linear_x, linear_y]),
                             self.apertures[current_aperture],
                             self.apertures[current_aperture],
                             self.steps_per_circle
                             self.steps_per_circle
                         )
                         )
@@ -3152,7 +3162,7 @@ class Gerber (Geometry):
         except Exception as err:
         except Exception as err:
             ex_type, ex, tb = sys.exc_info()
             ex_type, ex, tb = sys.exc_info()
             traceback.print_tb(tb)
             traceback.print_tb(tb)
-            #print traceback.format_exc()
+            # print traceback.format_exc()
 
 
             log.error("Gerber PARSING FAILED. Line %d: %s" % (line_num, gline))
             log.error("Gerber PARSING FAILED. Line %d: %s" % (line_num, gline))
             loc = 'Gerber Line #%d Gerber Line Content: %s\n' % (line_num, gline) + repr(err)
             loc = 'Gerber Line #%d Gerber Line Content: %s\n' % (line_num, gline) + repr(err)
@@ -3323,8 +3333,10 @@ class Gerber (Geometry):
         are recreated, the scaling will be lost. This behavior was modified
         are recreated, the scaling will be lost. This behavior was modified
         because of the complexity reached in this class.
         because of the complexity reached in this class.
 
 
-        :param factor: Number by which to scale.
-        :type factor: float
+        :param xfactor: Number by which to scale on X axis.
+        :type xfactor: float
+        :param yfactor: Number by which to scale on Y axis.
+        :type yfactor: float
         :rtype : None
         :rtype : None
         """
         """
         log.debug("camlib.Gerber.scale()")
         log.debug("camlib.Gerber.scale()")
@@ -3380,7 +3392,6 @@ class Gerber (Geometry):
 
 
         self.app.inform.emit(_("[success] Gerber Scale done."))
         self.app.inform.emit(_("[success] Gerber Scale done."))
 
 
-
         # ## solid_geometry ???
         # ## solid_geometry ???
         #  It's a cascaded union of objects.
         #  It's a cascaded union of objects.
         # self.solid_geometry = affinity.scale(self.solid_geometry, factor,
         # self.solid_geometry = affinity.scale(self.solid_geometry, factor,
@@ -3506,7 +3517,7 @@ class Gerber (Geometry):
 
 
         Parameters
         Parameters
         ----------
         ----------
-        xs, ys : float, float
+        angle_x, angle_y : float, float
             The shear angle(s) for the x and y axes respectively. These can be
             The shear angle(s) for the x and y axes respectively. These can be
             specified in either degrees (default) or radians by setting
             specified in either degrees (default) or radians by setting
             use_radians=True.
             use_radians=True.
@@ -3697,7 +3708,7 @@ class Excellon(Geometry):
                            'excellon_format_upper_in', 'excellon_format_lower_in', 'excellon_units', 'slots',
                            'excellon_format_upper_in', 'excellon_format_lower_in', 'excellon_units', 'slots',
                            'source_file']
                            'source_file']
 
 
-        #### Patterns ## ##
+        # ### Patterns ####
         # Regex basics:
         # Regex basics:
         # ^ - beginning
         # ^ - beginning
         # $ - end
         # $ - end
@@ -4509,24 +4520,26 @@ class Excellon(Geometry):
         :return: None
         :return: None
         """
         """
         self.solid_geometry = []
         self.solid_geometry = []
-
         try:
         try:
             # clear the solid_geometry in self.tools
             # clear the solid_geometry in self.tools
             for tool in self.tools:
             for tool in self.tools:
-                self.tools[tool]['solid_geometry'][:] = []
+                try:
+                    self.tools[tool]['solid_geometry'][:] = []
+                except KeyError:
+                    self.tools[tool]['solid_geometry'] = []
 
 
             for drill in self.drills:
             for drill in self.drills:
                 # poly = drill['point'].buffer(self.tools[drill['tool']]["C"]/2.0)
                 # poly = drill['point'].buffer(self.tools[drill['tool']]["C"]/2.0)
                 if drill['tool'] is '':
                 if drill['tool'] is '':
                     self.app.inform.emit(_("[WARNING] Excellon.create_geometry() -> a drill location was skipped "
                     self.app.inform.emit(_("[WARNING] Excellon.create_geometry() -> a drill location was skipped "
-                                         "due of not having a tool associated.\n"
-                                         "Check the resulting GCode."))
+                                           "due of not having a tool associated.\n"
+                                           "Check the resulting GCode."))
                     log.debug("Excellon.create_geometry() -> a drill location was skipped "
                     log.debug("Excellon.create_geometry() -> a drill location was skipped "
                               "due of not having a tool associated")
                               "due of not having a tool associated")
                     continue
                     continue
                 tooldia = self.tools[drill['tool']]['C']
                 tooldia = self.tools[drill['tool']]['C']
                 poly = drill['point'].buffer(tooldia / 2.0, int(int(self.geo_steps_per_circle) / 4))
                 poly = drill['point'].buffer(tooldia / 2.0, int(int(self.geo_steps_per_circle) / 4))
-                # self.solid_geometry.append(poly)
+                self.solid_geometry.append(poly)
                 self.tools[drill['tool']]['solid_geometry'].append(poly)
                 self.tools[drill['tool']]['solid_geometry'].append(poly)
 
 
             for slot in self.slots:
             for slot in self.slots:
@@ -4536,7 +4549,7 @@ class Excellon(Geometry):
 
 
                 lines_string = LineString([start, stop])
                 lines_string = LineString([start, stop])
                 poly = lines_string.buffer(slot_tooldia / 2.0, int(int(self.geo_steps_per_circle) / 4))
                 poly = lines_string.buffer(slot_tooldia / 2.0, int(int(self.geo_steps_per_circle) / 4))
-                # self.solid_geometry.append(poly)
+                self.solid_geometry.append(poly)
                 self.tools[slot['tool']]['solid_geometry'].append(poly)
                 self.tools[slot['tool']]['solid_geometry'].append(poly)
 
 
         except Exception as e:
         except Exception as e:

BIN
locale/de/LC_MESSAGES/strings.mo


Разница между файлами не показана из-за своего большого размера
+ 194 - 194
locale/de/LC_MESSAGES/strings.po


BIN
locale/en/LC_MESSAGES/strings.mo


Разница между файлами не показана из-за своего большого размера
+ 194 - 194
locale/en/LC_MESSAGES/strings.po


BIN
locale/ro/LC_MESSAGES/strings.mo


Разница между файлами не показана из-за своего большого размера
+ 194 - 194
locale/ro/LC_MESSAGES/strings.po


Разница между файлами не показана из-за своего большого размера
+ 198 - 198
locale_template/strings.pot


Некоторые файлы не были показаны из-за большого количества измененных файлов