- 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:
parent
a25fc1e88c
commit
d43de2ea77
|
@ -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()
|
||||
|
||||
|
|
195
FlatCAMObj.py
195
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):
|
||||
|
|
84
ObjectUI.py
84
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')
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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.
|
||||
|
|
81
camlib.py
81
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 ???
|
||||
|
|
Loading…
Reference in New Issue