Kaynağa Gözat

- fixed the Gerber object UI layout
- added ability to mark individual apertures in Gerber file using the Gerber Aperture Table

Marius Stanciu 7 yıl önce
ebeveyn
işleme
d43de2ea77
6 değiştirilmiş dosya ile 273 ekleme ve 104 silme
  1. 8 0
      FlatCAMApp.py
  2. 120 75
      FlatCAMObj.py
  3. 60 24
      ObjectUI.py
  4. 3 1
      PlotCanvas.py
  5. 5 0
      README.md
  6. 77 4
      camlib.py

+ 8 - 0
FlatCAMApp.py

@@ -4936,6 +4936,14 @@ class App(QtCore.QObject):
         # Clear pool
         self.clear_pool()
 
+        #delete shapes left drawn from mark shape_collections, if any
+        for obj in self.collection.get_list():
+            try:
+                obj.mark_shapes.enabled = False
+                obj.mark_shapes.clear(update=True)
+            except:
+                pass
+
         # tcl needs to be reinitialized, otherwise  old shell variables etc  remains
         self.init_tcl()
 

+ 120 - 75
FlatCAMObj.py

@@ -70,6 +70,8 @@ class FlatCAMObj(QtCore.QObject):
         # self.shapes = ShapeCollection(parent=self.app.plotcanvas.vispy_canvas.view.scene)
         self.shapes = self.app.plotcanvas.new_shape_group()
 
+        self.mark_shapes = self.app.plotcanvas.new_shape_collection(layers=2)
+
         self.item = None  # Link with project view item
 
         self.muted_ui = False
@@ -311,6 +313,13 @@ class FlatCAMObj(QtCore.QObject):
             key = self.shapes.add(tolerance=self.drawing_tolerance, **kwargs)
         return key
 
+    def add_mark_shape(self, **kwargs):
+        if self.deleted:
+            raise ObjectDeleted()
+        else:
+            key = self.mark_shapes.add(tolerance=self.drawing_tolerance, **kwargs)
+        return key
+
     @property
     def visible(self):
         return self.shapes.visible
@@ -570,17 +579,17 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
                 ap_size_item = QtWidgets.QTableWidgetItem('')
             ap_size_item.setFlags(QtCore.Qt.ItemIsEnabled)
 
-            plot_item = FCCheckBox()
-            plot_item.setLayoutDirection(QtCore.Qt.RightToLeft)
-            if self.ui.plot_cb.isChecked():
-                plot_item.setChecked(True)
+            mark_item = FCCheckBox()
+            mark_item.setLayoutDirection(QtCore.Qt.RightToLeft)
+            # if self.ui.aperture_table_visibility_cb.isChecked():
+            #     mark_item.setChecked(True)
 
             self.ui.apertures_table.setItem(self.apertures_row, 1, ap_code_item)  # Aperture Code
             self.ui.apertures_table.setItem(self.apertures_row, 2, ap_type_item)  # Aperture Type
             self.ui.apertures_table.setItem(self.apertures_row, 3, ap_size_item)   # Aperture Dimensions
             self.ui.apertures_table.setItem(self.apertures_row, 4, ap_dim_item)   # Aperture Dimensions
 
-            self.ui.apertures_table.setCellWidget(self.apertures_row, 5, plot_item)
+            self.ui.apertures_table.setCellWidget(self.apertures_row, 5, mark_item)
 
             self.apertures_row += 1
 
@@ -596,14 +605,14 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
             ap_type_item = QtWidgets.QTableWidgetItem('AM')
             ap_type_item.setFlags(QtCore.Qt.ItemIsEnabled)
 
-            plot_item = FCCheckBox()
-            plot_item.setLayoutDirection(QtCore.Qt.RightToLeft)
-            if self.ui.plot_cb.isChecked():
-                plot_item.setChecked(True)
+            mark_item = FCCheckBox()
+            mark_item.setLayoutDirection(QtCore.Qt.RightToLeft)
+            # if self.ui.aperture_table_visibility_cb.isChecked():
+            #     mark_item.setChecked(True)
 
             self.ui.apertures_table.setItem(self.apertures_row, 1, ap_code_item)  # Aperture Code
             self.ui.apertures_table.setItem(self.apertures_row, 2, ap_type_item)  # Aperture Type
-            self.ui.apertures_table.setCellWidget(self.apertures_row, 5, plot_item)
+            self.ui.apertures_table.setCellWidget(self.apertures_row, 5, mark_item)
 
             self.apertures_row += 1
 
@@ -634,7 +643,40 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
         self.ui.apertures_table.setSortingEnabled(False)
         self.ui.apertures_table.setMinimumHeight(self.ui.apertures_table.getHeight())
 
-        # self.ui_connect()
+        self.ui_connect()
+
+    def ui_connect(self):
+        for row in range(self.ui.apertures_table.rowCount()):
+            self.ui.apertures_table.cellWidget(row, 5).clicked.connect(self.on_mark_cb_click_table)
+
+    def ui_disconnect(self):
+        for row in range(self.ui.apertures_table.rowCount()):
+            try:
+                self.ui.apertures_table.cellWidget(row, 5).clicked.disconnect()
+            except:
+                pass
+
+    def on_mark_cb_click_table(self):
+        self.ui_disconnect()
+        cw = self.sender()
+        cw_index = self.ui.apertures_table.indexAt(cw.pos())
+        cw_row = cw_index.row()
+        check_row = 0
+
+        self.mark_shapes.clear(update=True)
+        for aperture in self.apertures:
+            # find the apertures_table row associated with the aperture
+            for row in range(self.ui.apertures_table.rowCount()):
+                if int(self.ui.apertures_table.item(row, 1).text()) == int(aperture):
+                    check_row = row
+                    break
+
+            if self.ui.apertures_table.cellWidget(check_row, 5).isChecked():
+                self.plot_apertures(color = '#2d4606bf', marked_aperture=aperture, visible=True)
+
+        self.mark_shapes.redraw()
+
+        self.ui_connect()
 
     def on_generatenoncopper_button_click(self, *args):
         self.app.report_usage("gerber_on_generatenoncopper_button")
@@ -895,6 +937,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
         if self.muted_ui:
             return
         self.read_form_item('plot')
+        self.plot()
 
     def on_solid_cb_click(self, *args):
         if self.muted_ui:
@@ -916,8 +959,19 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
     def on_aperture_table_visibility_change(self):
         if self.ui.aperture_table_visibility_cb.isChecked():
             self.ui.apertures_table.setVisible(True)
+            self.ui.scale_aperture_label.setVisible(True)
+            self.ui.scale_aperture_entry.setVisible(True)
+            self.ui.scale_aperture_button.setVisible(True)
         else:
             self.ui.apertures_table.setVisible(False)
+            self.ui.scale_aperture_label.setVisible(False)
+            self.ui.scale_aperture_entry.setVisible(False)
+            self.ui.scale_aperture_button.setVisible(False)
+
+            # on hide disable all mark plots
+            for row in range(self.ui.apertures_table.rowCount()):
+                self.ui.apertures_table.cellWidget(row, 5).set_value(False)
+            self.mark_shapes.clear(update=True)
 
     def convert_units(self, units):
         """
@@ -1005,70 +1059,60 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
             self.shapes.clear(update=True)
 
     # experimental plot() when the solid_geometry is stored in the self.apertures
-    # def plot_apertures(self, **kwargs):
-    #     """
-    #
-    #     :param kwargs: color and face_color
-    #     :return:
-    #     """
-    #
-    #     FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + " --> FlatCAMGerber.plot()")
-    #
-    #     # Does all the required setup and returns False
-    #     # if the 'ptint' option is set to False.
-    #     if not FlatCAMObj.plot(self):
-    #         return
-    #
-    #     if 'color' in kwargs:
-    #         color = kwargs['color']
-    #     else:
-    #         color = self.app.defaults['global_plot_line']
-    #     if 'face_color' in kwargs:
-    #         face_color = kwargs['face_color']
-    #     else:
-    #         face_color = self.app.defaults['global_plot_fill']
-    #
-    #     geometry = {}
-    #     for ap in self.apertures:
-    #         geometry[ap] = self.apertures[ap]['solid_geometry']
-    #         try:
-    #             _ = iter(geometry[ap])
-    #         except TypeError:
-    #             geometry[ap] = [geometry[ap]]
-    #
-    #     def random_color():
-    #         color = np.random.rand(4)
-    #         color[3] = 1
-    #         return color
-    #
-    #     try:
-    #         if self.options["solid"]:
-    #             for geo in geometry:
-    #                 for g in geometry[geo]:
-    #                     if type(g) == Polygon or type(g) == LineString:
-    #                         self.add_shape(shape=g, color=color,
-    #                                        face_color=random_color() if self.options['multicolored']
-    #                                        else face_color, visible=self.options['plot'])
-    #                     else:
-    #                         for el in g:
-    #                             self.add_shape(shape=el, color=color,
-    #                                            face_color=random_color() if self.options['multicolored']
-    #                                            else face_color, visible=self.options['plot'])
-    #         else:
-    #             for geo in geometry:
-    #                 for g in geometry[geo]:
-    #                     if type(g) == Polygon or type(g) == LineString:
-    #                         self.add_shape(shape=g,
-    #                                        color=random_color() if self.options['multicolored'] else 'black',
-    #                                        visible=self.options['plot'])
-    #                     else:
-    #                         for el in g:
-    #                             self.add_shape(shape=el,
-    #                                            color=random_color() if self.options['multicolored'] else 'black',
-    #                                            visible=self.options['plot'])
-    #         self.shapes.redraw()
-    #     except (ObjectDeleted, AttributeError):
-    #         self.shapes.clear(update=True)
+    def plot_apertures(self, **kwargs):
+        """
+
+        :param kwargs: color and face_color
+        :return:
+        """
+
+        FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + " --> FlatCAMGerber.plot_apertures()")
+
+        # Does all the required setup and returns False
+        # if the 'ptint' option is set to False.
+        if not FlatCAMObj.plot(self):
+            return
+
+        # for marking apertures, line color and fill color are the same
+        if 'color' in kwargs:
+            color = kwargs['color']
+        else:
+            color = self.app.defaults['global_plot_fill']
+
+        if 'marked_aperture' not in kwargs:
+            return
+        else:
+            aperture_to_plot_mark = kwargs['marked_aperture']
+            if aperture_to_plot_mark is None:
+                return
+
+        if 'visible' not in kwargs:
+            visibility = True
+        else:
+            visibility = kwargs['visible']
+
+        geometry = {}
+        for ap in self.apertures:
+            geometry[int(ap)] = self.apertures[ap]['solid_geometry']
+            try:
+                _ = iter(geometry[int(ap)])
+            except TypeError:
+                geometry[int(ap)] = [geometry[int(ap)]]
+
+        try:
+            if aperture_to_plot_mark in self.apertures:
+                for geo in geometry[int(aperture_to_plot_mark)]:
+                    if type(geo) == Polygon or type(geo) == LineString:
+                        self.add_mark_shape(shape=geo, color=color,
+                                       face_color=color, visible=visibility)
+                    else:
+                        for el in geo:
+                            self.add_mark_shape(shape=el, color=color,
+                                           face_color=color, visible=visibility)
+
+            self.mark_shapes.redraw()
+        except (ObjectDeleted, AttributeError):
+            self.mark_shapes.clear(update=True)
 
     def serialize(self):
         return {
@@ -4383,6 +4427,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
                 self.tools[tool]['solid_geometry'] = scale_recursion(self.tools[tool]['solid_geometry'])
         else:
             self.solid_geometry=scale_recursion(self.solid_geometry)
+
         self.app.inform.emit("[success]Geometry Scale done.")
 
     def offset(self, vect):

+ 60 - 24
ObjectUI.py

@@ -127,6 +127,8 @@ class GerberObjectUI(ObjectUI):
         self.custom_box.addLayout(grid0)
 
         self.plot_options_label = QtWidgets.QLabel("<b>Plot Options:</b>")
+        self.plot_options_label.setFixedWidth(90)
+
         grid0.addWidget(self.plot_options_label, 0, 0)
 
         # Solid CB
@@ -158,10 +160,12 @@ class GerberObjectUI(ObjectUI):
         self.custom_box.addLayout(hlay_plot)
 
         #### Gerber Apertures ####
-        self.apertures_table_label = QtWidgets.QLabel('<b>Apertures Table</b>')
+        self.apertures_table_label = QtWidgets.QLabel('<b>Apertures</b>')
         self.apertures_table_label.setToolTip(
-            "Apertures in this Gerber object."
+            "Apertures Table containining this Gerber object apertures."
         )
+        self.apertures_table_label.setFixedWidth(90)
+
         hlay_plot.addWidget(self.apertures_table_label)
 
         # Aperture Table Visibility CB
@@ -181,7 +185,7 @@ class GerberObjectUI(ObjectUI):
         self.custom_box.addWidget(self.apertures_table)
 
         self.apertures_table.setColumnCount(6)
-        self.apertures_table.setHorizontalHeaderLabels(['#', 'Code', 'Type', 'Size', 'Dim', 'P'])
+        self.apertures_table.setHorizontalHeaderLabels(['#', 'Code', 'Type', 'Size', 'Dim', 'M'])
         self.apertures_table.setSortingEnabled(False)
 
         self.apertures_table.horizontalHeaderItem(0).setToolTip(
@@ -197,16 +201,40 @@ class GerberObjectUI(ObjectUI):
             " - (width, height) for R, O type.\n"
             " - (dia, nVertices) for P type")
         self.apertures_table.horizontalHeaderItem(5).setToolTip(
-            "Toggle display of the aperture instances.")
+            "Mark the aperture instances on canvas.")
+        # self.apertures_table.setColumnHidden(5, True)
+
+        #### Aperture Scale ####
+        self.scale_aperture_grid = QtWidgets.QGridLayout()
+        self.custom_box.addLayout(self.scale_aperture_grid)
+
+        # Factor
+        self.scale_aperture_label = QtWidgets.QLabel('<b>Factor:</b>')
+        self.scale_aperture_label.setToolTip(
+            "Change the size of the selected apertures.\n"
+            "Factor by which to multiply\n"
+            "geometric features of this object."
+        )
+        self.scale_aperture_label.setFixedWidth(90)
+        self.scale_aperture_grid.addWidget(self.scale_aperture_label, 0, 0)
+
+        self.scale_aperture_entry = FloatEntry2()
+        self.scale_aperture_entry.set_value(1.0)
+        self.scale_aperture_grid.addWidget(self.scale_aperture_entry, 0, 1)
+
+        # Scale Button
+        self.scale_aperture_button = QtWidgets.QPushButton('Scale')
+        self.scale_aperture_button.setToolTip(
+            "Perform scaling operation."
+        )
+        self.scale_aperture_button.setFixedWidth(40)
+        self.scale_aperture_grid.addWidget(self.scale_aperture_button, 0, 2)
 
         # start with apertures table hidden
         self.apertures_table.setVisible(False)
-
-        # hide the plot column. for now I can't plot individually the apertures without making the plot really ugly
-        self.apertures_table.setColumnHidden(5, True)
-        #
-        # self.empty_label = QtWidgets.QLabel('')
-        # self.custom_box.addWidget(self.empty_label)
+        self.scale_aperture_label.setVisible(False)
+        self.scale_aperture_entry.setVisible(False)
+        self.scale_aperture_button.setVisible(False)
 
         # Isolation Routing
         self.isolation_routing_label = QtWidgets.QLabel("<b>Isolation Routing:</b>")
@@ -226,6 +254,7 @@ class GerberObjectUI(ObjectUI):
             "feature, use a negative value for\n"
             "this parameter."
         )
+        tdlabel.setFixedWidth(90)
         grid1.addWidget(tdlabel, 0, 0)
         self.iso_tool_dia_entry = LengthEntry()
         grid1.addWidget(self.iso_tool_dia_entry, 0, 1)
@@ -235,6 +264,7 @@ class GerberObjectUI(ObjectUI):
             "Width of the isolation gap in\n"
             "number (integer) of tool widths."
         )
+        passlabel.setFixedWidth(90)
         grid1.addWidget(passlabel, 1, 0)
         self.iso_width_entry = IntEntry()
         grid1.addWidget(self.iso_width_entry, 1, 1)
@@ -245,6 +275,7 @@ class GerberObjectUI(ObjectUI):
             "Example:\n"
             "A value here of 0.25 means an overlap of 25% from the tool diameter found above."
         )
+        overlabel.setFixedWidth(90)
         grid1.addWidget(overlabel, 2, 0)
         self.iso_overlap_entry = FloatEntry()
         grid1.addWidget(self.iso_overlap_entry, 2, 1)
@@ -295,6 +326,15 @@ class GerberObjectUI(ObjectUI):
         hlay_1 = QtWidgets.QHBoxLayout()
         self.custom_box.addLayout(hlay_1)
 
+        self.generate_iso_button = QtWidgets.QPushButton('FULL Geo')
+        self.generate_iso_button.setToolTip(
+            "Create the Geometry Object\n"
+            "for isolation routing. It contains both\n"
+            "the interiors and exteriors geometry."
+        )
+        self.generate_iso_button.setFixedWidth(90)
+        hlay_1.addWidget(self.generate_iso_button)
+
         hlay_1.addStretch()
 
         self.generate_ext_iso_button = QtWidgets.QPushButton('Ext Geo')
@@ -303,7 +343,7 @@ class GerberObjectUI(ObjectUI):
             "for isolation routing containing\n"
             "only the exteriors geometry."
         )
-        self.generate_ext_iso_button.setFixedWidth(60)
+        # self.generate_ext_iso_button.setFixedWidth(60)
         hlay_1.addWidget(self.generate_ext_iso_button)
 
         self.generate_int_iso_button = QtWidgets.QPushButton('Int Geo')
@@ -312,18 +352,9 @@ class GerberObjectUI(ObjectUI):
             "for isolation routing containing\n"
             "only the interiors geometry."
         )
-        self.generate_int_iso_button.setFixedWidth(60)
+        # self.generate_int_iso_button.setFixedWidth(60)
         hlay_1.addWidget(self.generate_int_iso_button)
 
-        self.generate_iso_button = QtWidgets.QPushButton('FULL Geo')
-        self.generate_iso_button.setToolTip(
-            "Create the Geometry Object\n"
-            "for isolation routing. It contains both\n"
-            "the interiors and exteriors geometry."
-        )
-        self.generate_iso_button.setFixedWidth(80)
-        hlay_1.addWidget(self.generate_iso_button)
-
         # when the follow checkbox is checked then the exteriors and interiors isolation generation buttons
         # are disabled as is doesn't make sense to have them enabled due of the nature of "follow"
         self.ois_iso = OptionalInputSection(self.follow_cb,
@@ -333,11 +364,12 @@ class GerberObjectUI(ObjectUI):
         self.custom_box.addLayout(grid2)
 
         ## Clear non-copper regions
-        self.clearcopper_label = QtWidgets.QLabel("<b>Clear non-copper:</b>")
+        self.clearcopper_label = QtWidgets.QLabel("<b>Clear N-copper:</b>")
         self.clearcopper_label.setToolTip(
             "Create a Geometry object with\n"
             "toolpaths to cut all non-copper regions."
         )
+        self.clearcopper_label.setFixedWidth(90)
         grid2.addWidget(self.clearcopper_label, 0, 0)
 
         self.generate_ncc_button = QtWidgets.QPushButton('NCC Tool')
@@ -385,15 +417,17 @@ class GerberObjectUI(ObjectUI):
             "objects with this minimum\n"
             "distance."
         )
+        bmlabel.setFixedWidth(90)
         grid4.addWidget(bmlabel, 0, 0)
         self.noncopper_margin_entry = LengthEntry()
         grid4.addWidget(self.noncopper_margin_entry, 0, 1)
 
         # Rounded corners
-        self.noncopper_rounded_cb = FCCheckBox(label="Rounded corners")
+        self.noncopper_rounded_cb = FCCheckBox(label="Rounded Geo")
         self.noncopper_rounded_cb.setToolTip(
             "Resulting geometry will have rounded corners."
         )
+        self.noncopper_rounded_cb.setFixedWidth(90)
         grid4.addWidget(self.noncopper_rounded_cb, 1, 0)
 
         self.generate_noncopper_button = QtWidgets.QPushButton('Generate Geo')
@@ -415,17 +449,19 @@ class GerberObjectUI(ObjectUI):
             "Distance of the edges of the box\n"
             "to the nearest polygon."
         )
+        bbmargin.setFixedWidth(90)
         grid5.addWidget(bbmargin, 0, 0)
         self.bbmargin_entry = LengthEntry()
         grid5.addWidget(self.bbmargin_entry, 0, 1)
 
-        self.bbrounded_cb = FCCheckBox(label="Rounded corners")
+        self.bbrounded_cb = FCCheckBox(label="Rounded Geo")
         self.bbrounded_cb.setToolTip(
             "If the bounding box is \n"
             "to have rounded corners\n"
             "their radius is equal to\n"
             "the margin."
         )
+        self.bbrounded_cb.setFixedWidth(90)
         grid5.addWidget(self.bbrounded_cb, 1, 0)
 
         self.generate_bb_button = QtWidgets.QPushButton('Generate Geo')

+ 3 - 1
PlotCanvas.py

@@ -165,7 +165,9 @@ class PlotCanvas(QtCore.QObject):
         """
         self.vispy_canvas.view.camera.zoom(factor, center)
 
-    def new_shape_group(self):
+    def new_shape_group(self, shape_collection=None):
+        if shape_collection:
+            return ShapeGroup(shape_collection)
         return ShapeGroup(self.shape_collection)
 
     def new_shape_collection(self, **kwargs):

+ 5 - 0
README.md

@@ -9,6 +9,11 @@ CAD program, and create G-Code for Isolation routing.
 
 =================================================
 
+25.02.2019
+
+- fixed the Gerber object UI layout
+- added ability to mark individual apertures in Gerber file using the Gerber Aperture Table
+
 24.02.2019
 
 - fixed a small bug in the Tool Solder Paste: the App don't take into consideration pads already filled with solder paste.

+ 77 - 4
camlib.py

@@ -1858,7 +1858,8 @@ class Gerber (Geometry):
     +-----------+-----------------------------------+
     | others    | Depend on ``type``                |
     +-----------+-----------------------------------+
-
+    | solid_geometry      | (list)                  |
+    +-----------+-----------------------------------+
     * ``aperture_macros`` (dictionary): Are predefined geometrical structures
       that can be instantiated with different parameters in an aperture
       definition. See ``apertures`` above. The key is the name of the macro,
@@ -1921,9 +1922,7 @@ class Gerber (Geometry):
                 'size':float, 
                 'width':float,
                 'height':float,
-                'light_solid_geometry': [],
-                'dark_solid_geometry': [],
-                'buff_solid_geometry': [],
+                'solid_geometry': [],
                 'follow_geometry': [],
             }
         }
@@ -2247,6 +2246,11 @@ class Gerber (Geometry):
                         geo = LineString(path).buffer(width / 1.999, int(self.steps_per_circle / 4))
                         if not geo.is_empty:
                             poly_buffer.append(geo)
+                            try:
+                                self.apertures[current_aperture]['solid_geometry'].append(geo)
+                            except KeyError:
+                                self.apertures[current_aperture]['solid_geometry'] = []
+                                self.apertures[current_aperture]['solid_geometry'].append(geo)
 
                         path = [path[-1]]
 
@@ -2411,6 +2415,11 @@ class Gerber (Geometry):
                                 int(self.steps_per_circle))
                             if not flash.is_empty:
                                 poly_buffer.append(flash)
+                                try:
+                                    self.apertures[current_aperture]['solid_geometry'].append(flash)
+                                except KeyError:
+                                    self.apertures[current_aperture]['solid_geometry'] = []
+                                    self.apertures[current_aperture]['solid_geometry'].append(flash)
                         except IndexError:
                             log.warning("Line %d: %s -> Nothing there to flash!" % (line_num, gline))
 
@@ -2448,6 +2457,11 @@ class Gerber (Geometry):
                             geo = LineString(path).buffer(width / 1.999, int(self.steps_per_circle / 4))
                             if not geo.is_empty:
                                 poly_buffer.append(geo)
+                                try:
+                                    self.apertures[last_path_aperture]['solid_geometry'].append(geo)
+                                except KeyError:
+                                    self.apertures[last_path_aperture]['solid_geometry'] = []
+                                    self.apertures[last_path_aperture]['solid_geometry'].append(geo)
 
                             path = [path[-1]]
 
@@ -2468,6 +2482,11 @@ class Gerber (Geometry):
                         geo = LineString(path).buffer(width/1.999, int(self.steps_per_circle / 4))
                         if not geo.is_empty:
                             poly_buffer.append(geo)
+                            try:
+                                self.apertures[current_aperture]['solid_geometry'].append(geo)
+                            except KeyError:
+                                self.apertures[current_aperture]['solid_geometry'] = []
+                                self.apertures[current_aperture]['solid_geometry'].append(geo)
 
                         path = [path[-1]]
 
@@ -2485,6 +2504,11 @@ class Gerber (Geometry):
                             if not geo.is_empty:
                                 follow_buffer.append(geo)
                                 poly_buffer.append(geo)
+                                try:
+                                    self.apertures[current_aperture]['solid_geometry'].append(geo)
+                                except KeyError:
+                                    self.apertures[current_aperture]['solid_geometry'] = []
+                                    self.apertures[current_aperture]['solid_geometry'].append(geo)
                             continue
 
                     # Only one path defines region?
@@ -2514,6 +2538,11 @@ class Gerber (Geometry):
 
                     if not region.is_empty:
                         poly_buffer.append(region)
+                        try:
+                            self.apertures[current_aperture]['solid_geometry'].append(region)
+                        except KeyError:
+                            self.apertures[current_aperture]['solid_geometry'] = []
+                            self.apertures[current_aperture]['solid_geometry'].append(region)
 
                     path = [[current_x, current_y]]  # Start new path
                     continue
@@ -2584,6 +2613,11 @@ class Gerber (Geometry):
 
                                         geo = shply_box(minx, miny, maxx, maxy)
                                         poly_buffer.append(geo)
+                                        try:
+                                            self.apertures[current_aperture]['solid_geometry'].append(geo)
+                                        except KeyError:
+                                            self.apertures[current_aperture]['solid_geometry'] = []
+                                            self.apertures[current_aperture]['solid_geometry'].append(geo)
                                 except:
                                     pass
                             last_path_aperture = current_aperture
@@ -2633,6 +2667,11 @@ class Gerber (Geometry):
                                         poly_buffer.append(geo)
                             except:
                                 poly_buffer.append(geo)
+                                try:
+                                    self.apertures[current_aperture]['solid_geometry'].append(geo)
+                                except KeyError:
+                                    self.apertures[current_aperture]['solid_geometry'] = []
+                                    self.apertures[current_aperture]['solid_geometry'].append(geo)
 
                         # if linear_x or linear_y are None, ignore those
                         if linear_x is not None and linear_y is not None:
@@ -2665,8 +2704,18 @@ class Gerber (Geometry):
                                 try:
                                     if self.apertures[current_aperture]["type"] != 'R':
                                         poly_buffer.append(geo)
+                                        try:
+                                            self.apertures[current_aperture]['solid_geometry'].append(geo)
+                                        except KeyError:
+                                            self.apertures[current_aperture]['solid_geometry'] = []
+                                            self.apertures[current_aperture]['solid_geometry'].append(geo)
                                 except:
                                     poly_buffer.append(geo)
+                                    try:
+                                        self.apertures[current_aperture]['solid_geometry'].append(geo)
+                                    except KeyError:
+                                        self.apertures[current_aperture]['solid_geometry'] = []
+                                        self.apertures[current_aperture]['solid_geometry'].append(geo)
 
                         # Reset path starting point
                         path = [[linear_x, linear_y]]
@@ -2684,6 +2733,11 @@ class Gerber (Geometry):
                         )
                         if not flash.is_empty:
                             poly_buffer.append(flash)
+                            try:
+                                self.apertures[current_aperture]['solid_geometry'].append(flash)
+                            except KeyError:
+                                self.apertures[current_aperture]['solid_geometry'] = []
+                                self.apertures[current_aperture]['solid_geometry'].append(flash)
 
                     # maybe those lines are not exactly needed but it is easier to read the program as those coordinates
                     # are used in case that circular interpolation is encountered within the Gerber file
@@ -2773,6 +2827,11 @@ class Gerber (Geometry):
                             buffered = LineString(path).buffer(width / 1.999, int(self.steps_per_circle))
                             if not buffered.is_empty:
                                 poly_buffer.append(buffered)
+                                try:
+                                    self.apertures[current_aperture]['solid_geometry'].append(buffered)
+                                except KeyError:
+                                    self.apertures[current_aperture]['solid_geometry'] = []
+                                    self.apertures[current_aperture]['solid_geometry'].append(buffered)
 
                         current_x = circular_x
                         current_y = circular_y
@@ -2900,6 +2959,11 @@ class Gerber (Geometry):
                     geo = LineString(path).buffer(width / 1.999, int(self.steps_per_circle / 4))
                     if not geo.is_empty:
                         poly_buffer.append(geo)
+                        try:
+                            self.apertures[last_path_aperture]['solid_geometry'].append(geo)
+                        except KeyError:
+                            self.apertures[last_path_aperture]['solid_geometry'] = []
+                            self.apertures[last_path_aperture]['solid_geometry'].append(geo)
 
             # --- Apply buffer ---
 
@@ -3110,6 +3174,7 @@ class Gerber (Geometry):
         :type factor: float
         :rtype : None
         """
+        log.debug("camlib.Gerber.scale()")
 
         try:
             xfactor = float(xfactor)
@@ -3143,6 +3208,14 @@ class Gerber (Geometry):
                                              yfactor, origin=(px, py))
 
         self.solid_geometry = scale_geom(self.solid_geometry)
+
+        # we need to scale the geometry stored in the Gerber apertures, too
+        try:
+            for apid in self.apertures:
+                self.apertures[apid]['solid_geometry'] = scale_geom(self.apertures[apid]['solid_geometry'])
+        except Exception as e:
+            log.debug('FlatCAMGeometry.scale() --> %s' % str(e))
+
         self.app.inform.emit("[success]Gerber Scale done.")
 
         ## solid_geometry ???