- fixed the Gerber object UI layout

- added ability to mark individual apertures in Gerber file using the Gerber Aperture Table
This commit is contained in:
Marius Stanciu 2019-02-25 16:28:32 +02:00 committed by Marius
parent a25fc1e88c
commit d43de2ea77
6 changed files with 273 additions and 104 deletions

View File

@ -4936,6 +4936,14 @@ class App(QtCore.QObject):
# Clear pool # Clear pool
self.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 # tcl needs to be reinitialized, otherwise old shell variables etc remains
self.init_tcl() self.init_tcl()

View File

@ -70,6 +70,8 @@ class FlatCAMObj(QtCore.QObject):
# self.shapes = ShapeCollection(parent=self.app.plotcanvas.vispy_canvas.view.scene) # self.shapes = ShapeCollection(parent=self.app.plotcanvas.vispy_canvas.view.scene)
self.shapes = self.app.plotcanvas.new_shape_group() 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.item = None # Link with project view item
self.muted_ui = False self.muted_ui = False
@ -311,6 +313,13 @@ class FlatCAMObj(QtCore.QObject):
key = self.shapes.add(tolerance=self.drawing_tolerance, **kwargs) key = self.shapes.add(tolerance=self.drawing_tolerance, **kwargs)
return key 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 @property
def visible(self): def visible(self):
return self.shapes.visible return self.shapes.visible
@ -570,17 +579,17 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
ap_size_item = QtWidgets.QTableWidgetItem('') ap_size_item = QtWidgets.QTableWidgetItem('')
ap_size_item.setFlags(QtCore.Qt.ItemIsEnabled) ap_size_item.setFlags(QtCore.Qt.ItemIsEnabled)
plot_item = FCCheckBox() mark_item = FCCheckBox()
plot_item.setLayoutDirection(QtCore.Qt.RightToLeft) mark_item.setLayoutDirection(QtCore.Qt.RightToLeft)
if self.ui.plot_cb.isChecked(): # if self.ui.aperture_table_visibility_cb.isChecked():
plot_item.setChecked(True) # 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, 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, 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, 3, ap_size_item) # Aperture Dimensions
self.ui.apertures_table.setItem(self.apertures_row, 4, ap_dim_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 self.apertures_row += 1
@ -596,14 +605,14 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
ap_type_item = QtWidgets.QTableWidgetItem('AM') ap_type_item = QtWidgets.QTableWidgetItem('AM')
ap_type_item.setFlags(QtCore.Qt.ItemIsEnabled) ap_type_item.setFlags(QtCore.Qt.ItemIsEnabled)
plot_item = FCCheckBox() mark_item = FCCheckBox()
plot_item.setLayoutDirection(QtCore.Qt.RightToLeft) mark_item.setLayoutDirection(QtCore.Qt.RightToLeft)
if self.ui.plot_cb.isChecked(): # if self.ui.aperture_table_visibility_cb.isChecked():
plot_item.setChecked(True) # 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, 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, 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 self.apertures_row += 1
@ -634,7 +643,40 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
self.ui.apertures_table.setSortingEnabled(False) self.ui.apertures_table.setSortingEnabled(False)
self.ui.apertures_table.setMinimumHeight(self.ui.apertures_table.getHeight()) 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): def on_generatenoncopper_button_click(self, *args):
self.app.report_usage("gerber_on_generatenoncopper_button") self.app.report_usage("gerber_on_generatenoncopper_button")
@ -895,6 +937,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
if self.muted_ui: if self.muted_ui:
return return
self.read_form_item('plot') self.read_form_item('plot')
self.plot()
def on_solid_cb_click(self, *args): def on_solid_cb_click(self, *args):
if self.muted_ui: if self.muted_ui:
@ -916,8 +959,19 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
def on_aperture_table_visibility_change(self): def on_aperture_table_visibility_change(self):
if self.ui.aperture_table_visibility_cb.isChecked(): if self.ui.aperture_table_visibility_cb.isChecked():
self.ui.apertures_table.setVisible(True) 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: else:
self.ui.apertures_table.setVisible(False) 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): def convert_units(self, units):
""" """
@ -1005,70 +1059,60 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
self.shapes.clear(update=True) self.shapes.clear(update=True)
# experimental plot() when the solid_geometry is stored in the self.apertures # experimental plot() when the solid_geometry is stored in the self.apertures
# def plot_apertures(self, **kwargs): def plot_apertures(self, **kwargs):
# """ """
#
# :param kwargs: color and face_color :param kwargs: color and face_color
# :return: :return:
# """ """
#
# FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + " --> FlatCAMGerber.plot()") FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + " --> FlatCAMGerber.plot_apertures()")
#
# # Does all the required setup and returns False # Does all the required setup and returns False
# # if the 'ptint' option is set to False. # if the 'ptint' option is set to False.
# if not FlatCAMObj.plot(self): if not FlatCAMObj.plot(self):
# return return
#
# if 'color' in kwargs: # for marking apertures, line color and fill color are the same
# color = kwargs['color'] if 'color' in kwargs:
# else: color = kwargs['color']
# color = self.app.defaults['global_plot_line'] else:
# if 'face_color' in kwargs: color = self.app.defaults['global_plot_fill']
# face_color = kwargs['face_color']
# else: if 'marked_aperture' not in kwargs:
# face_color = self.app.defaults['global_plot_fill'] return
# else:
# geometry = {} aperture_to_plot_mark = kwargs['marked_aperture']
# for ap in self.apertures: if aperture_to_plot_mark is None:
# geometry[ap] = self.apertures[ap]['solid_geometry'] return
# try:
# _ = iter(geometry[ap]) if 'visible' not in kwargs:
# except TypeError: visibility = True
# geometry[ap] = [geometry[ap]] else:
# visibility = kwargs['visible']
# def random_color():
# color = np.random.rand(4) geometry = {}
# color[3] = 1 for ap in self.apertures:
# return color geometry[int(ap)] = self.apertures[ap]['solid_geometry']
# try:
# try: _ = iter(geometry[int(ap)])
# if self.options["solid"]: except TypeError:
# for geo in geometry: geometry[int(ap)] = [geometry[int(ap)]]
# for g in geometry[geo]:
# if type(g) == Polygon or type(g) == LineString: try:
# self.add_shape(shape=g, color=color, if aperture_to_plot_mark in self.apertures:
# face_color=random_color() if self.options['multicolored'] for geo in geometry[int(aperture_to_plot_mark)]:
# else face_color, visible=self.options['plot']) if type(geo) == Polygon or type(geo) == LineString:
# else: self.add_mark_shape(shape=geo, color=color,
# for el in g: face_color=color, visible=visibility)
# self.add_shape(shape=el, color=color, else:
# face_color=random_color() if self.options['multicolored'] for el in geo:
# else face_color, visible=self.options['plot']) self.add_mark_shape(shape=el, color=color,
# else: face_color=color, visible=visibility)
# for geo in geometry:
# for g in geometry[geo]: self.mark_shapes.redraw()
# if type(g) == Polygon or type(g) == LineString: except (ObjectDeleted, AttributeError):
# self.add_shape(shape=g, self.mark_shapes.clear(update=True)
# 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 serialize(self): def serialize(self):
return { return {
@ -4383,6 +4427,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
self.tools[tool]['solid_geometry'] = scale_recursion(self.tools[tool]['solid_geometry']) self.tools[tool]['solid_geometry'] = scale_recursion(self.tools[tool]['solid_geometry'])
else: else:
self.solid_geometry=scale_recursion(self.solid_geometry) self.solid_geometry=scale_recursion(self.solid_geometry)
self.app.inform.emit("[success]Geometry Scale done.") self.app.inform.emit("[success]Geometry Scale done.")
def offset(self, vect): def offset(self, vect):

View File

@ -127,6 +127,8 @@ class GerberObjectUI(ObjectUI):
self.custom_box.addLayout(grid0) self.custom_box.addLayout(grid0)
self.plot_options_label = QtWidgets.QLabel("<b>Plot Options:</b>") self.plot_options_label = QtWidgets.QLabel("<b>Plot Options:</b>")
self.plot_options_label.setFixedWidth(90)
grid0.addWidget(self.plot_options_label, 0, 0) grid0.addWidget(self.plot_options_label, 0, 0)
# Solid CB # Solid CB
@ -158,10 +160,12 @@ class GerberObjectUI(ObjectUI):
self.custom_box.addLayout(hlay_plot) self.custom_box.addLayout(hlay_plot)
#### Gerber Apertures #### #### 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( 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) hlay_plot.addWidget(self.apertures_table_label)
# Aperture Table Visibility CB # Aperture Table Visibility CB
@ -181,7 +185,7 @@ class GerberObjectUI(ObjectUI):
self.custom_box.addWidget(self.apertures_table) self.custom_box.addWidget(self.apertures_table)
self.apertures_table.setColumnCount(6) 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.setSortingEnabled(False)
self.apertures_table.horizontalHeaderItem(0).setToolTip( self.apertures_table.horizontalHeaderItem(0).setToolTip(
@ -197,16 +201,40 @@ class GerberObjectUI(ObjectUI):
" - (width, height) for R, O type.\n" " - (width, height) for R, O type.\n"
" - (dia, nVertices) for P type") " - (dia, nVertices) for P type")
self.apertures_table.horizontalHeaderItem(5).setToolTip( 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 # start with apertures table hidden
self.apertures_table.setVisible(False) self.apertures_table.setVisible(False)
self.scale_aperture_label.setVisible(False)
# hide the plot column. for now I can't plot individually the apertures without making the plot really ugly self.scale_aperture_entry.setVisible(False)
self.apertures_table.setColumnHidden(5, True) self.scale_aperture_button.setVisible(False)
#
# self.empty_label = QtWidgets.QLabel('')
# self.custom_box.addWidget(self.empty_label)
# Isolation Routing # Isolation Routing
self.isolation_routing_label = QtWidgets.QLabel("<b>Isolation Routing:</b>") self.isolation_routing_label = QtWidgets.QLabel("<b>Isolation Routing:</b>")
@ -226,6 +254,7 @@ class GerberObjectUI(ObjectUI):
"feature, use a negative value for\n" "feature, use a negative value for\n"
"this parameter." "this parameter."
) )
tdlabel.setFixedWidth(90)
grid1.addWidget(tdlabel, 0, 0) grid1.addWidget(tdlabel, 0, 0)
self.iso_tool_dia_entry = LengthEntry() self.iso_tool_dia_entry = LengthEntry()
grid1.addWidget(self.iso_tool_dia_entry, 0, 1) grid1.addWidget(self.iso_tool_dia_entry, 0, 1)
@ -235,6 +264,7 @@ class GerberObjectUI(ObjectUI):
"Width of the isolation gap in\n" "Width of the isolation gap in\n"
"number (integer) of tool widths." "number (integer) of tool widths."
) )
passlabel.setFixedWidth(90)
grid1.addWidget(passlabel, 1, 0) grid1.addWidget(passlabel, 1, 0)
self.iso_width_entry = IntEntry() self.iso_width_entry = IntEntry()
grid1.addWidget(self.iso_width_entry, 1, 1) grid1.addWidget(self.iso_width_entry, 1, 1)
@ -245,6 +275,7 @@ class GerberObjectUI(ObjectUI):
"Example:\n" "Example:\n"
"A value here of 0.25 means an overlap of 25% from the tool diameter found above." "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) grid1.addWidget(overlabel, 2, 0)
self.iso_overlap_entry = FloatEntry() self.iso_overlap_entry = FloatEntry()
grid1.addWidget(self.iso_overlap_entry, 2, 1) grid1.addWidget(self.iso_overlap_entry, 2, 1)
@ -295,6 +326,15 @@ class GerberObjectUI(ObjectUI):
hlay_1 = QtWidgets.QHBoxLayout() hlay_1 = QtWidgets.QHBoxLayout()
self.custom_box.addLayout(hlay_1) 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() hlay_1.addStretch()
self.generate_ext_iso_button = QtWidgets.QPushButton('Ext Geo') self.generate_ext_iso_button = QtWidgets.QPushButton('Ext Geo')
@ -303,7 +343,7 @@ class GerberObjectUI(ObjectUI):
"for isolation routing containing\n" "for isolation routing containing\n"
"only the exteriors geometry." "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) hlay_1.addWidget(self.generate_ext_iso_button)
self.generate_int_iso_button = QtWidgets.QPushButton('Int Geo') self.generate_int_iso_button = QtWidgets.QPushButton('Int Geo')
@ -312,18 +352,9 @@ class GerberObjectUI(ObjectUI):
"for isolation routing containing\n" "for isolation routing containing\n"
"only the interiors geometry." "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) 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 # 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" # 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, self.ois_iso = OptionalInputSection(self.follow_cb,
@ -333,11 +364,12 @@ class GerberObjectUI(ObjectUI):
self.custom_box.addLayout(grid2) self.custom_box.addLayout(grid2)
## Clear non-copper regions ## 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( self.clearcopper_label.setToolTip(
"Create a Geometry object with\n" "Create a Geometry object with\n"
"toolpaths to cut all non-copper regions." "toolpaths to cut all non-copper regions."
) )
self.clearcopper_label.setFixedWidth(90)
grid2.addWidget(self.clearcopper_label, 0, 0) grid2.addWidget(self.clearcopper_label, 0, 0)
self.generate_ncc_button = QtWidgets.QPushButton('NCC Tool') self.generate_ncc_button = QtWidgets.QPushButton('NCC Tool')
@ -385,15 +417,17 @@ class GerberObjectUI(ObjectUI):
"objects with this minimum\n" "objects with this minimum\n"
"distance." "distance."
) )
bmlabel.setFixedWidth(90)
grid4.addWidget(bmlabel, 0, 0) grid4.addWidget(bmlabel, 0, 0)
self.noncopper_margin_entry = LengthEntry() self.noncopper_margin_entry = LengthEntry()
grid4.addWidget(self.noncopper_margin_entry, 0, 1) grid4.addWidget(self.noncopper_margin_entry, 0, 1)
# Rounded corners # Rounded corners
self.noncopper_rounded_cb = FCCheckBox(label="Rounded corners") self.noncopper_rounded_cb = FCCheckBox(label="Rounded Geo")
self.noncopper_rounded_cb.setToolTip( self.noncopper_rounded_cb.setToolTip(
"Resulting geometry will have rounded corners." "Resulting geometry will have rounded corners."
) )
self.noncopper_rounded_cb.setFixedWidth(90)
grid4.addWidget(self.noncopper_rounded_cb, 1, 0) grid4.addWidget(self.noncopper_rounded_cb, 1, 0)
self.generate_noncopper_button = QtWidgets.QPushButton('Generate Geo') self.generate_noncopper_button = QtWidgets.QPushButton('Generate Geo')
@ -415,17 +449,19 @@ class GerberObjectUI(ObjectUI):
"Distance of the edges of the box\n" "Distance of the edges of the box\n"
"to the nearest polygon." "to the nearest polygon."
) )
bbmargin.setFixedWidth(90)
grid5.addWidget(bbmargin, 0, 0) grid5.addWidget(bbmargin, 0, 0)
self.bbmargin_entry = LengthEntry() self.bbmargin_entry = LengthEntry()
grid5.addWidget(self.bbmargin_entry, 0, 1) 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( self.bbrounded_cb.setToolTip(
"If the bounding box is \n" "If the bounding box is \n"
"to have rounded corners\n" "to have rounded corners\n"
"their radius is equal to\n" "their radius is equal to\n"
"the margin." "the margin."
) )
self.bbrounded_cb.setFixedWidth(90)
grid5.addWidget(self.bbrounded_cb, 1, 0) grid5.addWidget(self.bbrounded_cb, 1, 0)
self.generate_bb_button = QtWidgets.QPushButton('Generate Geo') self.generate_bb_button = QtWidgets.QPushButton('Generate Geo')

View File

@ -165,7 +165,9 @@ class PlotCanvas(QtCore.QObject):
""" """
self.vispy_canvas.view.camera.zoom(factor, center) 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) return ShapeGroup(self.shape_collection)
def new_shape_collection(self, **kwargs): def new_shape_collection(self, **kwargs):

View File

@ -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 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. - fixed a small bug in the Tool Solder Paste: the App don't take into consideration pads already filled with solder paste.

View File

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