- upgraded the Fiducials Tool to create new objects instead of updating in place the source objects

- upgraded the Copper Thieving Tool to create new objects instead of updating in place the source objects
- updated translation strings
This commit is contained in:
Marius Stanciu 2020-11-02 13:50:00 +02:00 committed by Marius
parent 540eb27673
commit 84ef0f8a03
25 changed files with 16742 additions and 16560 deletions

View File

@ -17,6 +17,9 @@ CHANGELOG for FlatCAM beta
- made sure that the object selection will not work while in Editors or in the App Tools - made sure that the object selection will not work while in Editors or in the App Tools
- some minor changes to strings and icons - some minor changes to strings and icons
- in Corner Markers Tool - the new Gerber object will have also follow_geometry - in Corner Markers Tool - the new Gerber object will have also follow_geometry
- upgraded the Fiducials Tool to create new objects instead of updating in place the source objects
- upgraded the Copper Thieving Tool to create new objects instead of updating in place the source objects
- updated translation strings
1.11.2020 1.11.2020

View File

@ -93,7 +93,7 @@ class ToolsCornersPrefGroupUI(OptionsGroupUI):
grid0.addWidget(self.l_entry, 8, 1) grid0.addWidget(self.l_entry, 8, 1)
# Drill Tool Diameter # Drill Tool Diameter
self.drill_dia_label = FCLabel('%s:' % _("Tool Dia")) self.drill_dia_label = FCLabel('%s:' % _("Drill Dia"))
self.drill_dia_label.setToolTip( self.drill_dia_label.setToolTip(
'%s.' % _("Drill Diameter") '%s.' % _("Drill Diameter")
) )

View File

@ -69,7 +69,7 @@ class ToolCopperThieving(AppTool):
self.cursor_pos = (0, 0) self.cursor_pos = (0, 0)
self.first_click = False self.first_click = False
self.area_method = False self.handlers_connected = False
# Tool properties # Tool properties
self.clearance_val = None self.clearance_val = None
@ -90,9 +90,9 @@ class ToolCopperThieving(AppTool):
self.ui.reference_radio.group_toggle_fn = self.on_toggle_reference self.ui.reference_radio.group_toggle_fn = self.on_toggle_reference
self.ui.fill_type_radio.activated_custom.connect(self.on_thieving_type) self.ui.fill_type_radio.activated_custom.connect(self.on_thieving_type)
self.ui.fill_button.clicked.connect(self.execute) self.ui.fill_button.clicked.connect(self.on_add_copper_thieving_click)
self.ui.rb_button.clicked.connect(self.add_robber_bar) self.ui.rb_button.clicked.connect(self.on_add_robber_bar_click)
self.ui.ppm_button.clicked.connect(self.on_add_ppm) self.ui.ppm_button.clicked.connect(self.on_add_ppm_click)
self.ui.reset_button.clicked.connect(self.set_tool_ui) self.ui.reset_button.clicked.connect(self.set_tool_ui)
self.work_finished.connect(self.on_new_pattern_plating_object) self.work_finished.connect(self.on_new_pattern_plating_object)
@ -150,7 +150,7 @@ class ToolCopperThieving(AppTool):
self.ui.clearance_ppm_entry.set_value(self.app.defaults["tools_copper_thieving_mask_clearance"]) self.ui.clearance_ppm_entry.set_value(self.app.defaults["tools_copper_thieving_mask_clearance"])
# INIT SECTION # INIT SECTION
self.area_method = False self.handlers_connected = False
self.robber_geo = None self.robber_geo = None
self.robber_line = None self.robber_line = None
self.new_solid_geometry = None self.new_solid_geometry = None
@ -211,7 +211,7 @@ class ToolCopperThieving(AppTool):
self.ui.squares_frame.hide() self.ui.squares_frame.hide()
self.ui.lines_frame.show() self.ui.lines_frame.show()
def add_robber_bar(self): def on_add_robber_bar_click(self):
rb_margin = self.ui.rb_margin_entry.get_value() rb_margin = self.ui.rb_margin_entry.get_value()
self.rb_thickness = self.ui.rb_thickness_entry.get_value() self.rb_thickness = self.ui.rb_thickness_entry.get_value()
@ -222,13 +222,13 @@ class ToolCopperThieving(AppTool):
try: try:
self.grb_object = model_index.internalPointer().obj self.grb_object = model_index.internalPointer().obj
except Exception as e: except Exception as e:
log.debug("ToolCopperThieving.add_robber_bar() --> %s" % str(e)) log.debug("ToolCopperThieving.on_add_robber_bar_click() --> %s" % str(e))
self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no Gerber object loaded ...")) self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no Gerber object loaded ..."))
return return
try: try:
outline_pol = self.grb_object.solid_geometry.envelope outline_pol = self.grb_object.solid_geometry.envelope
except TypeError: except (TypeError, AttributeError):
outline_pol = MultiPolygon(self.grb_object.solid_geometry).envelope outline_pol = MultiPolygon(self.grb_object.solid_geometry).envelope
rb_distance = rb_margin + (self.rb_thickness / 2.0) rb_distance = rb_margin + (self.rb_thickness / 2.0)
@ -238,6 +238,7 @@ class ToolCopperThieving(AppTool):
self.app.proc_container.update_view_text(' %s' % _("Append geometry")) self.app.proc_container.update_view_text(' %s' % _("Append geometry"))
new_apertures = deepcopy(self.grb_object.apertures)
aperture_found = None aperture_found = None
for ap_id, ap_val in self.grb_object.apertures.items(): for ap_id, ap_val in self.grb_object.apertures.items():
if ap_val['type'] == 'C' and ap_val['size'] == self.rb_thickness: if ap_val['type'] == 'C' and ap_val['size'] == self.rb_thickness:
@ -246,46 +247,66 @@ class ToolCopperThieving(AppTool):
if aperture_found: if aperture_found:
geo_elem = {'solid': self.robber_geo, 'follow': self.robber_line} geo_elem = {'solid': self.robber_geo, 'follow': self.robber_line}
self.grb_object.apertures[aperture_found]['geometry'].append(deepcopy(geo_elem)) new_apertures[aperture_found]['geometry'].append(deepcopy(geo_elem))
else: else:
ap_keys = list(self.grb_object.apertures.keys()) ap_keys = list(new_apertures.keys())
if ap_keys: if ap_keys:
new_apid = str(int(max(ap_keys)) + 1) new_apid = str(int(max(ap_keys)) + 1)
else: else:
new_apid = '10' new_apid = '10'
self.grb_object.apertures[new_apid] = {} new_apertures[new_apid] = {
self.grb_object.apertures[new_apid]['type'] = 'C' 'type': 'C',
self.grb_object.apertures[new_apid]['size'] = self.rb_thickness 'size': deepcopy(self.rb_thickness),
self.grb_object.apertures[new_apid]['geometry'] = [] 'geometry': []
}
geo_elem = {'solid': self.robber_geo, 'follow': self.robber_line} geo_elem = {'solid': self.robber_geo, 'follow': self.robber_line}
self.grb_object.apertures[new_apid]['geometry'].append(deepcopy(geo_elem)) new_apertures[new_apid]['geometry'].append(deepcopy(geo_elem))
geo_obj = self.grb_object.solid_geometry geo_obj = deepcopy(self.grb_object.solid_geometry)
if isinstance(geo_obj, MultiPolygon): if isinstance(geo_obj, MultiPolygon):
s_list = [] s_list = []
for pol in geo_obj.geoms: for pol in geo_obj.geoms:
s_list.append(pol) s_list.append(pol)
s_list.append(self.robber_geo) s_list.append(deepcopy(self.robber_geo))
geo_obj = MultiPolygon(s_list) geo_obj = MultiPolygon(s_list)
elif isinstance(geo_obj, list): elif isinstance(geo_obj, list):
geo_obj.append(self.robber_geo) geo_obj.append(deepcopy(self.robber_geo))
elif isinstance(geo_obj, Polygon): elif isinstance(geo_obj, Polygon):
geo_obj = MultiPolygon([geo_obj, self.robber_geo]) geo_obj = MultiPolygon([geo_obj, deepcopy(self.robber_geo)])
self.grb_object.solid_geometry = geo_obj outname = '%s_%s' % (str(self.grb_object.options['name']), 'robber')
self.app.proc_container.update_view_text(' %s' % _("Append source file")) def initialize(grb_obj, app_obj):
# update the source file with the new geometry: grb_obj.options = {}
self.grb_object.source_file = self.app.f_handlers.export_gerber(obj_name=self.grb_object.options['name'], for opt in self.grb_object.options:
filename=None, local_use=self.grb_object, if opt != 'name':
use_thread=False) grb_obj.options[opt] = deepcopy(self.grb_object.options[opt])
grb_obj.options['name'] = outname
grb_obj.multitool = False
grb_obj.multigeo = False
grb_obj.follow = deepcopy(self.grb_object.follow)
grb_obj.apertures = new_apertures
grb_obj.solid_geometry = unary_union(geo_obj)
grb_obj.follow_geometry = deepcopy(self.grb_object.follow_geometry) + [deepcopy(self.robber_line)]
app_obj.proc_container.update_view_text(' %s' % _("Append source file"))
# update the source file with the new geometry:
grb_obj.source_file = app_obj.f_handlers.export_gerber(obj_name=outname, filename=None, local_use=grb_obj,
use_thread=False)
ret_val = self.app.app_obj.new_object('gerber', outname, initialize, plot=True)
self.app.proc_container.update_view_text(' %s' % '') self.app.proc_container.update_view_text(' %s' % '')
if ret_val == 'fail':
self.app.call_source = "app"
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed."))
return
self.on_exit() self.on_exit()
self.app.inform.emit('[success] %s' % _("Copper Thieving Tool done.")) self.app.inform.emit('[success] %s' % _("Copper Thieving Tool done."))
def execute(self): def on_add_copper_thieving_click(self):
self.app.call_source = "copper_thieving_tool" self.app.call_source = "copper_thieving_tool"
self.clearance_val = self.ui.clearance_entry.get_value() self.clearance_val = self.ui.clearance_entry.get_value()
@ -299,7 +320,7 @@ class ToolCopperThieving(AppTool):
try: try:
self.grb_object = model_index.internalPointer().obj self.grb_object = model_index.internalPointer().obj
except Exception as e: except Exception as e:
log.debug("ToolCopperThieving.execute() --> %s" % str(e)) log.debug("ToolCopperThieving.on_add_copper_thieving_click() --> %s" % str(e))
self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no Gerber object loaded ...")) self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no Gerber object loaded ..."))
return return
@ -321,20 +342,7 @@ class ToolCopperThieving(AppTool):
elif reference_method == 'area': elif reference_method == 'area':
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Click the start point of the area.")) self.app.inform.emit('[WARNING_NOTCL] %s' % _("Click the start point of the area."))
self.connect_event_handlers()
self.area_method = True
if self.app.is_legacy is False:
self.app.plotcanvas.graph_event_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.plotcanvas.graph_event_disconnect('mouse_move', self.app.on_mouse_move_over_plot)
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
else:
self.app.plotcanvas.graph_event_disconnect(self.app.mp)
self.app.plotcanvas.graph_event_disconnect(self.app.mm)
self.app.plotcanvas.graph_event_disconnect(self.app.mr)
self.mr = self.app.plotcanvas.graph_event_connect('mouse_release', self.on_mouse_release)
self.mm = self.app.plotcanvas.graph_event_connect('mouse_move', self.on_mouse_move)
elif reference_method == 'box': elif reference_method == 'box':
bound_obj_name = self.ui.ref_combo.currentText() bound_obj_name = self.ui.ref_combo.currentText()
@ -401,24 +409,10 @@ class ToolCopperThieving(AppTool):
return return
elif event.button == right_button and self.mouse_is_dragging is False: elif event.button == right_button and self.mouse_is_dragging is False:
self.area_method = False
self.first_click = False self.first_click = False
self.delete_tool_selection_shape() self.delete_tool_selection_shape()
self.disconnect_event_handlers()
if self.app.is_legacy is False:
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.on_mouse_release)
self.app.plotcanvas.graph_event_disconnect('mouse_move', self.on_mouse_move)
else:
self.app.plotcanvas.graph_event_disconnect(self.mr)
self.app.plotcanvas.graph_event_disconnect(self.mm)
self.app.mp = self.app.plotcanvas.graph_event_connect('mouse_press',
self.app.on_mouse_click_over_plot)
self.app.mm = self.app.plotcanvas.graph_event_connect('mouse_move',
self.app.on_mouse_move_over_plot)
self.app.mr = self.app.plotcanvas.graph_event_connect('mouse_release',
self.app.on_mouse_click_release_over_plot)
if len(self.sel_rect) == 0: if len(self.sel_rect) == 0:
return return
@ -530,16 +524,16 @@ class ToolCopperThieving(AppTool):
if not isinstance(self.grb_object.solid_geometry, Iterable): if not isinstance(self.grb_object.solid_geometry, Iterable):
self.grb_object.solid_geometry = [self.grb_object.solid_geometry] self.grb_object.solid_geometry = [self.grb_object.solid_geometry]
def job_thread_thieving(app_obj): def job_thread_thieving(tool_obj):
# ######################################################################################### # #########################################################################################################
# Prepare isolation polygon. This will create the clearance over the Gerber features ###### # Prepare isolation polygon. This will create the clearance over the Gerber features
# ######################################################################################### # #########################################################################################################
log.debug("Copper Thieving Tool. Preparing isolation polygons.") log.debug("Copper Thieving Tool. Preparing isolation polygons.")
app_obj.app.inform.emit(_("Copper Thieving Tool. Preparing isolation polygons.")) tool_obj.app.inform.emit(_("Copper Thieving Tool. Preparing isolation polygons."))
# variables to display the percentage of work done # variables to display the percentage of work done
try: try:
geo_len = len(app_obj.grb_object.solid_geometry) geo_len = len(tool_obj.grb_object.solid_geometry)
except TypeError: except TypeError:
geo_len = 1 geo_len = 1
@ -548,37 +542,37 @@ class ToolCopperThieving(AppTool):
clearance_geometry = [] clearance_geometry = []
try: try:
for pol in app_obj.grb_object.solid_geometry: for pol in tool_obj.grb_object.solid_geometry:
if app_obj.app.abort_flag: if tool_obj.app.abort_flag:
# graceful abort requested by the user # graceful abort requested by the user
raise grace raise grace
clearance_geometry.append( clearance_geometry.append(
pol.buffer(c_val, int(int(app_obj.geo_steps_per_circle) / 4)) pol.buffer(c_val, int(int(tool_obj.geo_steps_per_circle) / 4))
) )
pol_nr += 1 pol_nr += 1
disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 100])) disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 100]))
if old_disp_number < disp_number <= 100: if old_disp_number < disp_number <= 100:
app_obj.app.proc_container.update_view_text(' %s ... %d%%' % msg = ' %s ... %d%%' % (_("Thieving"), int(disp_number))
(_("Thieving"), int(disp_number))) tool_obj.app.proc_container.update_view_text(msg)
old_disp_number = disp_number old_disp_number = disp_number
except TypeError: except TypeError:
# taking care of the case when the self.solid_geometry is just a single Polygon, not a list or a # taking care of the case when the self.solid_geometry is just a single Polygon, not a list or a
# MultiPolygon (not an iterable) # MultiPolygon (not an iterable)
clearance_geometry.append( clearance_geometry.append(
app_obj.grb_object.solid_geometry.buffer(c_val, int(int(app_obj.geo_steps_per_circle) / 4)) tool_obj.grb_object.solid_geometry.buffer(c_val, int(int(tool_obj.geo_steps_per_circle) / 4))
) )
app_obj.app.proc_container.update_view_text(' %s ...' % _("Buffering")) tool_obj.app.proc_container.update_view_text(' %s ...' % _("Buffering"))
clearance_geometry = unary_union(clearance_geometry) clearance_geometry = unary_union(clearance_geometry)
# ######################################################################################### # #########################################################################################################
# Prepare the area to fill with copper. ################################################### # Prepare the area to fill with copper.
# ######################################################################################### # #########################################################################################################
log.debug("Copper Thieving Tool. Preparing areas to fill with copper.") log.debug("Copper Thieving Tool. Preparing areas to fill with copper.")
app_obj.app.inform.emit(_("Copper Thieving Tool. Preparing areas to fill with copper.")) tool_obj.app.inform.emit(_("Copper Thieving Tool. Preparing areas to fill with copper."))
try: try:
if ref_obj is None or ref_obj == 'itself': if ref_obj is None or ref_obj == 'itself':
@ -589,12 +583,16 @@ class ToolCopperThieving(AppTool):
log.debug("ToolCopperThieving.on_copper_thieving() --> %s" % str(e)) log.debug("ToolCopperThieving.on_copper_thieving() --> %s" % str(e))
return 'fail' return 'fail'
app_obj.app.proc_container.update_view_text(' %s' % _("Working...")) tool_obj.app.proc_container.update_view_text(' %s' % _("Working..."))
# #########################################################################################################
# generate the bounding box geometry
# #########################################################################################################
if ref_selected == 'itself': if ref_selected == 'itself':
geo_n = working_obj.solid_geometry geo_n = deepcopy(working_obj.solid_geometry)
try: try:
if app_obj.ui.bbox_type_radio.get_value() == 'min': if tool_obj.ui.bbox_type_radio.get_value() == 'min':
if isinstance(geo_n, MultiPolygon): if isinstance(geo_n, MultiPolygon):
env_obj = geo_n.convex_hull env_obj = geo_n.convex_hull
elif (isinstance(geo_n, MultiPolygon) and len(geo_n) == 1) or \ elif (isinstance(geo_n, MultiPolygon) and len(geo_n) == 1) or \
@ -617,20 +615,20 @@ class ToolCopperThieving(AppTool):
geo = box(x0, y0, x1, y1) geo = box(x0, y0, x1, y1)
bounding_box = geo.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre) bounding_box = geo.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre)
else: else:
app_obj.app.inform.emit( tool_obj.app.inform.emit(
'[ERROR_NOTCL] %s: %s' % (_("Geometry not supported for bounding box"), type(geo_n)) '[ERROR_NOTCL] %s: %s' % (_("Geometry not supported for bounding box"), type(geo_n))
) )
return 'fail' return 'fail'
except Exception as e: except Exception as e:
log.debug("ToolCopperFIll.on_copper_thieving() 'itself' --> %s" % str(e)) log.debug("ToolCopperFIll.on_copper_thieving() 'itself' --> %s" % str(e))
app_obj.app.inform.emit('[ERROR_NOTCL] %s' % _("No object available.")) tool_obj.app.inform.emit('[ERROR_NOTCL] %s' % _("No object available."))
return 'fail' return 'fail'
elif ref_selected == 'area': elif ref_selected == 'area':
geo_buff_list = [] geo_buff_list = []
try: try:
for poly in working_obj: for poly in working_obj:
if app_obj.app.abort_flag: if tool_obj.app.abort_flag:
# graceful abort requested by the user # graceful abort requested by the user
raise grace raise grace
geo_buff_list.append(poly.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre)) geo_buff_list.append(poly.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre))
@ -650,7 +648,7 @@ class ToolCopperThieving(AppTool):
geo_buff_list = [] geo_buff_list = []
for poly in geo_n: for poly in geo_n:
if app_obj.app.abort_flag: if tool_obj.app.abort_flag:
# graceful abort requested by the user # graceful abort requested by the user
raise grace raise grace
geo_buff_list.append(poly.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre)) geo_buff_list.append(poly.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre))
@ -661,18 +659,18 @@ class ToolCopperThieving(AppTool):
bounding_box = unary_union(thieving_obj.solid_geometry).convex_hull.intersection(geo_n) bounding_box = unary_union(thieving_obj.solid_geometry).convex_hull.intersection(geo_n)
bounding_box = bounding_box.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre) bounding_box = bounding_box.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre)
else: else:
app_obj.app.inform.emit('[ERROR_NOTCL] %s' % _("The reference object type is not supported.")) tool_obj.app.inform.emit('[ERROR_NOTCL] %s' % _("The reference object type is not supported."))
return 'fail' return 'fail'
log.debug("Copper Thieving Tool. Finished creating areas to fill with copper.") log.debug("Copper Thieving Tool. Finished creating areas to fill with copper.")
app_obj.app.inform.emit(_("Copper Thieving Tool. Appending new geometry and buffering.")) tool_obj.app.inform.emit(_("Copper Thieving Tool. Appending new geometry and buffering."))
# ######################################################################################### # #########################################################################################################
# ########## Generate filling geometry. ################################################### # ########## Generate filling geometry.
# ######################################################################################### # #########################################################################################################
app_obj.new_solid_geometry = bounding_box.difference(clearance_geometry) tool_obj.new_solid_geometry = bounding_box.difference(clearance_geometry)
# determine the bounding box polygon for the entire Gerber object to which we add copper thieving # determine the bounding box polygon for the entire Gerber object to which we add copper thieving
# if isinstance(geo_n, list): # if isinstance(geo_n, list):
@ -682,8 +680,11 @@ class ToolCopperThieving(AppTool):
# #
# x0, y0, x1, y1 = env_obj.bounds # x0, y0, x1, y1 = env_obj.bounds
# bounding_box = box(x0, y0, x1, y1) # bounding_box = box(x0, y0, x1, y1)
app_obj.app.proc_container.update_view_text(' %s' % _("Create geometry")) tool_obj.app.proc_container.update_view_text(' %s' % _("Create geometry"))
# #########################################################################################################
# apply the 'margin' to the bounding box geometry
# #########################################################################################################
try: try:
bounding_box = thieving_obj.solid_geometry.envelope.buffer( bounding_box = thieving_obj.solid_geometry.envelope.buffer(
distance=margin, distance=margin,
@ -696,6 +697,9 @@ class ToolCopperThieving(AppTool):
) )
x0, y0, x1, y1 = bounding_box.bounds x0, y0, x1, y1 = bounding_box.bounds
# #########################################################################################################
# add Thieving geometry
# #########################################################################################################
if fill_type == 'dot' or fill_type == 'square': if fill_type == 'dot' or fill_type == 'square':
# build the MultiPolygon of dots/squares that will fill the entire bounding box # build the MultiPolygon of dots/squares that will fill the entire bounding box
thieving_list = [] thieving_list = []
@ -731,9 +735,9 @@ class ToolCopperThieving(AppTool):
thieving_box_geo = affinity.translate(thieving_box_geo, xoff=dx, yoff=dy) thieving_box_geo = affinity.translate(thieving_box_geo, xoff=dx, yoff=dy)
try: try:
_it = iter(app_obj.new_solid_geometry) _it = iter(tool_obj.new_solid_geometry)
except TypeError: except TypeError:
app_obj.new_solid_geometry = [app_obj.new_solid_geometry] tool_obj.new_solid_geometry = [tool_obj.new_solid_geometry]
try: try:
_it = iter(thieving_box_geo) _it = iter(thieving_box_geo)
@ -742,11 +746,11 @@ class ToolCopperThieving(AppTool):
thieving_geo = [] thieving_geo = []
for dot_geo in thieving_box_geo: for dot_geo in thieving_box_geo:
for geo_t in app_obj.new_solid_geometry: for geo_t in tool_obj.new_solid_geometry:
if dot_geo.within(geo_t): if dot_geo.within(geo_t):
thieving_geo.append(dot_geo) thieving_geo.append(dot_geo)
app_obj.new_solid_geometry = thieving_geo tool_obj.new_solid_geometry = thieving_geo
if fill_type == 'line': if fill_type == 'line':
half_thick_line = line_size / 2.0 half_thick_line = line_size / 2.0
@ -754,33 +758,33 @@ class ToolCopperThieving(AppTool):
# create a thick polygon-line that surrounds the copper features # create a thick polygon-line that surrounds the copper features
outline_geometry = [] outline_geometry = []
try: try:
for pol in app_obj.grb_object.solid_geometry: for pol in tool_obj.grb_object.solid_geometry:
if app_obj.app.abort_flag: if tool_obj.app.abort_flag:
# graceful abort requested by the user # graceful abort requested by the user
raise grace raise grace
outline_geometry.append( outline_geometry.append(
pol.buffer(c_val+half_thick_line, int(int(app_obj.geo_steps_per_circle) / 4)) pol.buffer(c_val+half_thick_line, int(int(tool_obj.geo_steps_per_circle) / 4))
) )
pol_nr += 1 pol_nr += 1
disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 100])) disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 100]))
if old_disp_number < disp_number <= 100: if old_disp_number < disp_number <= 100:
app_obj.app.proc_container.update_view_text(' %s ... %d%%' % msg = ' %s ... %d%%' % (_("Buffering"), int(disp_number))
(_("Buffering"), int(disp_number))) tool_obj.app.proc_container.update_view_text(msg)
old_disp_number = disp_number old_disp_number = disp_number
except TypeError: except TypeError:
# taking care of the case when the self.solid_geometry is just a single Polygon, not a list or a # taking care of the case when the self.solid_geometry is just a single Polygon, not a list or a
# MultiPolygon (not an iterable) # MultiPolygon (not an iterable)
outline_geometry.append( outline_geometry.append(
app_obj.grb_object.solid_geometry.buffer( tool_obj.grb_object.solid_geometry.buffer(
c_val+half_thick_line, c_val+half_thick_line,
int(int(app_obj.geo_steps_per_circle) / 4) int(int(tool_obj.geo_steps_per_circle) / 4)
) )
) )
app_obj.app.proc_container.update_view_text(' %s' % _("Buffering")) tool_obj.app.proc_container.update_view_text(' %s' % _("Buffering"))
outline_geometry = unary_union(outline_geometry) outline_geometry = unary_union(outline_geometry)
outline_line = [] outline_line = []
@ -788,13 +792,13 @@ class ToolCopperThieving(AppTool):
for geo_o in outline_geometry: for geo_o in outline_geometry:
outline_line.append( outline_line.append(
geo_o.exterior.buffer( geo_o.exterior.buffer(
half_thick_line, resolution=int(int(app_obj.geo_steps_per_circle) / 4) half_thick_line, resolution=int(int(tool_obj.geo_steps_per_circle) / 4)
) )
) )
except TypeError: except TypeError:
outline_line.append( outline_line.append(
outline_geometry.exterior.buffer( outline_geometry.exterior.buffer(
half_thick_line, resolution=int(int(app_obj.geo_steps_per_circle) / 4) half_thick_line, resolution=int(int(tool_obj.geo_steps_per_circle) / 4)
) )
) )
@ -805,7 +809,7 @@ class ToolCopperThieving(AppTool):
box_outline_geo_exterior = box_outline_geo.exterior box_outline_geo_exterior = box_outline_geo.exterior
box_outline_geometry = box_outline_geo_exterior.buffer( box_outline_geometry = box_outline_geo_exterior.buffer(
half_thick_line, half_thick_line,
resolution=int(int(app_obj.geo_steps_per_circle) / 4) resolution=int(int(tool_obj.geo_steps_per_circle) / 4)
) )
bx0, by0, bx1, by1 = box_outline_geo.bounds bx0, by0, bx1, by1 = box_outline_geo.bounds
@ -815,7 +819,7 @@ class ToolCopperThieving(AppTool):
while new_x <= x1 - half_thick_line: while new_x <= x1 - half_thick_line:
line_geo = LineString([(new_x, by0), (new_x, by1)]).buffer( line_geo = LineString([(new_x, by0), (new_x, by1)]).buffer(
half_thick_line, half_thick_line,
resolution=int(int(app_obj.geo_steps_per_circle) / 4) resolution=int(int(tool_obj.geo_steps_per_circle) / 4)
) )
thieving_lines_geo.append(line_geo) thieving_lines_geo.append(line_geo)
new_x += line_size + line_spacing new_x += line_size + line_spacing
@ -823,7 +827,7 @@ class ToolCopperThieving(AppTool):
while new_y <= y1 - half_thick_line: while new_y <= y1 - half_thick_line:
line_geo = LineString([(bx0, new_y), (bx1, new_y)]).buffer( line_geo = LineString([(bx0, new_y), (bx1, new_y)]).buffer(
half_thick_line, half_thick_line,
resolution=int(int(app_obj.geo_steps_per_circle) / 4) resolution=int(int(tool_obj.geo_steps_per_circle) / 4)
) )
thieving_lines_geo.append(line_geo) thieving_lines_geo.append(line_geo)
new_y += line_size + line_spacing new_y += line_size + line_spacing
@ -833,53 +837,76 @@ class ToolCopperThieving(AppTool):
for line_poly in thieving_lines_geo: for line_poly in thieving_lines_geo:
rest_line = line_poly.difference(clearance_geometry) rest_line = line_poly.difference(clearance_geometry)
diff_lines_geo.append(rest_line) diff_lines_geo.append(rest_line)
app_obj.flatten([outline_geometry, box_outline_geometry, diff_lines_geo]) tool_obj.flatten([outline_geometry, box_outline_geometry, diff_lines_geo])
app_obj.new_solid_geometry = app_obj.flat_geometry tool_obj.new_solid_geometry = tool_obj.flat_geometry
app_obj.app.proc_container.update_view_text(' %s' % _("Append geometry")) tool_obj.app.proc_container.update_view_text(' %s' % _("Append geometry"))
geo_list = app_obj.grb_object.solid_geometry geo_list = deepcopy(tool_obj.grb_object.solid_geometry)
if isinstance(app_obj.grb_object.solid_geometry, MultiPolygon): if isinstance(tool_obj.grb_object.solid_geometry, MultiPolygon):
geo_list = list(app_obj.grb_object.solid_geometry.geoms) geo_list = list(geo_list.geoms)
if '0' not in app_obj.grb_object.apertures: new_apertures = deepcopy(tool_obj.grb_object.apertures)
app_obj.grb_object.apertures['0'] = {} if '0' not in new_apertures:
app_obj.grb_object.apertures['0']['geometry'] = [] new_apertures['0'] = {
app_obj.grb_object.apertures['0']['type'] = 'REG' 'type': 'REG',
app_obj.grb_object.apertures['0']['size'] = 0.0 'size': 0.0,
'geometry': []
}
try: try:
for poly in app_obj.new_solid_geometry: for poly in tool_obj.new_solid_geometry:
# append to the new solid geometry # append to the new solid geometry
geo_list.append(poly) geo_list.append(poly)
# append into the '0' aperture # append into the '0' aperture
geo_elem = {'solid': poly, 'follow': poly.exterior} geo_elem = {'solid': poly, 'follow': poly.exterior}
app_obj.grb_object.apertures['0']['geometry'].append(deepcopy(geo_elem)) new_apertures['0']['geometry'].append(deepcopy(geo_elem))
except TypeError: except TypeError:
# append to the new solid geometry # append to the new solid geometry
geo_list.append(app_obj.new_solid_geometry) geo_list.append(tool_obj.new_solid_geometry)
# append into the '0' aperture # append into the '0' aperture
geo_elem = {'solid': app_obj.new_solid_geometry, 'follow': app_obj.new_solid_geometry.exterior} geo_elem = {'solid': tool_obj.new_solid_geometry, 'follow': tool_obj.new_solid_geometry.exterior}
app_obj.grb_object.apertures['0']['geometry'].append(deepcopy(geo_elem)) new_apertures['0']['geometry'].append(deepcopy(geo_elem))
app_obj.grb_object.solid_geometry = MultiPolygon(geo_list).buffer(0.0000001).buffer(-0.0000001) new_solid_geo = MultiPolygon(geo_list).buffer(0.0000001).buffer(-0.0000001)
app_obj.app.proc_container.update_view_text(' %s' % _("Append source file")) outname = '%s_%s' % (str(self.grb_object.options['name']), 'thief')
# update the source file with the new geometry:
app_obj.grb_object.source_file = app_obj.app.f_handlers.export_gerber( def initialize(grb_obj, app_obj):
obj_name=app_obj.grb_object.options['name'], filename=None, local_use=app_obj.grb_object, grb_obj.options = {}
use_thread=False) for opt in self.grb_object.options:
app_obj.app.proc_container.update_view_text(' %s' % '') if opt != 'name':
app_obj.on_exit() grb_obj.options[opt] = deepcopy(self.grb_object.options[opt])
app_obj.app.inform.emit('[success] %s' % _("Copper Thieving Tool done.")) grb_obj.options['name'] = outname
grb_obj.multitool = False
grb_obj.multigeo = False
grb_obj.follow = deepcopy(self.grb_object.follow)
grb_obj.apertures = new_apertures
grb_obj.solid_geometry = deepcopy(new_solid_geo)
grb_obj.follow_geometry = deepcopy(self.grb_object.follow_geometry)
app_obj.proc_container.update_view_text(' %s' % _("Append source file"))
grb_obj.source_file = app_obj.f_handlers.export_gerber(obj_name=outname, filename=None,
local_use=grb_obj,
use_thread=False)
ret_val = self.app.app_obj.new_object('gerber', outname, initialize, plot=True)
tool_obj.app.proc_container.update_view_text(' %s' % '')
if ret_val == 'fail':
self.app.call_source = "app"
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed."))
return
tool_obj.on_exit()
tool_obj.app.inform.emit('[success] %s' % _("Copper Thieving Tool done."))
if run_threaded: if run_threaded:
self.app.worker_task.emit({'fcn': job_thread_thieving, 'params': [self]}) self.app.worker_task.emit({'fcn': job_thread_thieving, 'params': [self]})
else: else:
job_thread_thieving(self) job_thread_thieving(self)
def on_add_ppm(self): def on_add_ppm_click(self):
run_threaded = True run_threaded = True
if run_threaded: if run_threaded:
@ -895,6 +922,9 @@ class ToolCopperThieving(AppTool):
self.on_new_pattern_plating_object() self.on_new_pattern_plating_object()
def on_new_pattern_plating_object(self): def on_new_pattern_plating_object(self):
ppm_clearance = self.ui.clearance_ppm_entry.get_value()
rb_thickness = self.rb_thickness
# get the Gerber object on which the Copper thieving will be inserted # get the Gerber object on which the Copper thieving will be inserted
selection_index = self.ui.sm_object_combo.currentIndex() selection_index = self.ui.sm_object_combo.currentIndex()
model_index = self.app.collection.index(selection_index, 0, self.ui.sm_object_combo.rootModelIndex()) model_index = self.app.collection.index(selection_index, 0, self.ui.sm_object_combo.rootModelIndex())
@ -902,13 +932,10 @@ class ToolCopperThieving(AppTool):
try: try:
self.sm_object = model_index.internalPointer().obj self.sm_object = model_index.internalPointer().obj
except Exception as e: except Exception as e:
log.debug("ToolCopperThieving.on_add_ppm() --> %s" % str(e)) log.debug("ToolCopperThieving.on_add_ppm_click() --> %s" % str(e))
self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no Gerber object loaded ...")) self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no Gerber object loaded ..."))
return return
ppm_clearance = self.ui.clearance_ppm_entry.get_value()
rb_thickness = self.rb_thickness
self.app.proc_container.update_view_text(' %s' % _("Append PP-M geometry")) self.app.proc_container.update_view_text(' %s' % _("Append PP-M geometry"))
geo_list = self.sm_object.solid_geometry geo_list = self.sm_object.solid_geometry
if isinstance(self.sm_object.solid_geometry, MultiPolygon): if isinstance(self.sm_object.solid_geometry, MultiPolygon):
@ -932,11 +959,16 @@ class ToolCopperThieving(AppTool):
plated_area += self.robber_geo.area plated_area += self.robber_geo.area
self.ui.plated_area_entry.set_value(plated_area) self.ui.plated_area_entry.set_value(plated_area)
thieving_solid_geo = self.new_solid_geometry thieving_solid_geo = deepcopy(self.new_solid_geometry)
robber_solid_geo = self.robber_geo robber_solid_geo = deepcopy(self.robber_geo)
robber_line = self.robber_line robber_line = deepcopy(self.robber_line)
def obj_init(grb_obj, app_obj): def obj_init(grb_obj, app_obj):
grb_obj.options = {}
for opt in self.sm_object.options:
if opt != 'name':
grb_obj.options[opt] = deepcopy(self.sm_object.options[opt])
grb_obj.options['name'] = outname
grb_obj.multitool = False grb_obj.multitool = False
grb_obj.source_file = [] grb_obj.source_file = []
grb_obj.multigeo = False grb_obj.multigeo = False
@ -947,10 +979,11 @@ class ToolCopperThieving(AppTool):
# if we have copper thieving geometry, add it # if we have copper thieving geometry, add it
if thieving_solid_geo: if thieving_solid_geo:
if '0' not in grb_obj.apertures: if '0' not in grb_obj.apertures:
grb_obj.apertures['0'] = {} grb_obj.apertures['0'] = {
grb_obj.apertures['0']['geometry'] = [] 'type': 'REG',
grb_obj.apertures['0']['type'] = 'REG' 'size': 0.0,
grb_obj.apertures['0']['size'] = 0.0 'geometry': []
}
try: try:
for poly in thieving_solid_geo: for poly in thieving_solid_geo:
@ -967,6 +1000,7 @@ class ToolCopperThieving(AppTool):
grb_obj.apertures['0']['geometry'].append(deepcopy(geo_elem)) grb_obj.apertures['0']['geometry'].append(deepcopy(geo_elem))
except TypeError: except TypeError:
# append to the new solid geometry # append to the new solid geometry
assert isinstance(thieving_solid_geo, Polygon)
geo_list.append(thieving_solid_geo.buffer(ppm_clearance)) geo_list.append(thieving_solid_geo.buffer(ppm_clearance))
# append into the '0' aperture # append into the '0' aperture
@ -995,10 +1029,11 @@ class ToolCopperThieving(AppTool):
else: else:
new_apid = '10' new_apid = '10'
grb_obj.apertures[new_apid] = {} grb_obj.apertures[new_apid] = {
grb_obj.apertures[new_apid]['type'] = 'C' 'type': 'C',
grb_obj.apertures[new_apid]['size'] = rb_thickness + ppm_clearance 'size': rb_thickness + ppm_clearance,
grb_obj.apertures[new_apid]['geometry'] = [] 'geometry': []
}
geo_elem = { geo_elem = {
'solid': robber_solid_geo.buffer(ppm_clearance), 'solid': robber_solid_geo.buffer(ppm_clearance),
@ -1012,61 +1047,49 @@ class ToolCopperThieving(AppTool):
app_obj.proc_container.update_view_text(' %s' % _("Append source file")) app_obj.proc_container.update_view_text(' %s' % _("Append source file"))
# update the source file with the new geometry: # update the source file with the new geometry:
grb_obj.source_file = app_obj.f_handlers.export_gerber(obj_name=name, filename=None, local_use=grb_obj, grb_obj.source_file = app_obj.f_handlers.export_gerber(obj_name=outname, filename=None, local_use=grb_obj,
use_thread=False) use_thread=False)
app_obj.proc_container.update_view_text(' %s' % '') app_obj.proc_container.update_view_text(' %s' % '')
# Object name # Object name
obj_name, separatpr, obj_extension = self.sm_object.options['name'].rpartition('.') obj_name, separatpr, obj_extension = self.sm_object.options['name'].rpartition('.')
name = '%s_%s.%s' % (obj_name, 'plating_mask', obj_extension) outname = '%s_%s.%s' % (obj_name, 'plating_mask', obj_extension)
self.app.app_obj.new_object('gerber', name, obj_init, autoselected=False) ret_val = self.app.app_obj.new_object('gerber', outname, obj_init, autoselected=False)
if ret_val == 'fail':
self.app.call_source = "app"
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed."))
return
# Register recent file # Register recent file
self.app.file_opened.emit("gerber", name) self.app.file_opened.emit("gerber", outname)
self.on_exit() self.on_exit()
self.app.inform.emit('[success] %s' % _("Generating Pattern Plating Mask done.")) self.app.inform.emit('[success] %s' % _("Generating Pattern Plating Mask done."))
def replot(self, obj): def replot(self, obj, run_thread=True):
def worker_task(): def worker_task():
with self.app.proc_container.new('%s...' % _("Plotting")): with self.app.proc_container.new('%s...' % _("Plotting")):
obj.plot() obj.plot()
self.app.app_obj.object_plotted.emit(obj)
self.app.worker_task.emit({'fcn': worker_task, 'params': []}) if run_thread:
self.app.worker_task.emit({'fcn': worker_task, 'params': []})
else:
worker_task()
def on_exit(self): def on_exit(self, obj=None):
# plot the objects # plot the objects
if self.grb_object: if obj:
self.replot(obj=self.grb_object) try:
for ob in obj:
if self.sm_object: self.replot(obj=ob)
self.replot(obj=self.sm_object) except (AttributeError, TypeError):
self.replot(obj=obj)
# update the bounding box values except Exception:
try: return
a, b, c, d = self.grb_object.bounds()
self.grb_object.options['xmin'] = a
self.grb_object.options['ymin'] = b
self.grb_object.options['xmax'] = c
self.grb_object.options['ymax'] = d
except Exception as e:
log.debug("ToolCopperThieving.on_exit() bounds -> copper thieving Gerber error --> %s" % str(e))
# update the bounding box values
try:
a, b, c, d = self.sm_object.bounds()
self.sm_object.options['xmin'] = a
self.sm_object.options['ymin'] = b
self.sm_object.options['xmax'] = c
self.sm_object.options['ymax'] = d
except Exception as e:
log.debug("ToolCopperThieving.on_exit() bounds -> pattern plating mask error --> %s" % str(e))
# reset the variables # reset the variables
self.grb_object = None
self.sm_object = None
self.ref_obj = None
self.sel_rect = [] self.sel_rect = []
# Events ID # Events ID
@ -1079,10 +1102,31 @@ class ToolCopperThieving(AppTool):
self.first_click = False self.first_click = False
# if True it means we exited from tool in the middle of area adding therefore disconnect the events # if True it means we exited from tool in the middle of area adding therefore disconnect the events
if self.area_method is True: if self.handlers_connected is True:
self.app.delete_selection_shape() self.app.delete_selection_shape()
self.area_method = False
self.disconnect_event_handlers()
self.app.call_source = "app"
self.app.inform.emit('[success] %s' % _("Copper Thieving Tool exit."))
def connect_event_handlers(self):
if self.handlers_connected is False:
if self.app.is_legacy is False:
self.app.plotcanvas.graph_event_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.plotcanvas.graph_event_disconnect('mouse_move', self.app.on_mouse_move_over_plot)
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
else:
self.app.plotcanvas.graph_event_disconnect(self.app.mp)
self.app.plotcanvas.graph_event_disconnect(self.app.mm)
self.app.plotcanvas.graph_event_disconnect(self.app.mr)
self.mr = self.app.plotcanvas.graph_event_connect('mouse_release', self.on_mouse_release)
self.mm = self.app.plotcanvas.graph_event_connect('mouse_move', self.on_mouse_move)
self.handlers_connected = True
def disconnect_event_handlers(self):
if self.handlers_connected is True:
if self.app.is_legacy is False: if self.app.is_legacy is False:
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.on_mouse_release) self.app.plotcanvas.graph_event_disconnect('mouse_release', self.on_mouse_release)
self.app.plotcanvas.graph_event_disconnect('mouse_move', self.on_mouse_move) self.app.plotcanvas.graph_event_disconnect('mouse_move', self.on_mouse_move)
@ -1096,9 +1140,7 @@ class ToolCopperThieving(AppTool):
self.app.on_mouse_move_over_plot) self.app.on_mouse_move_over_plot)
self.app.mr = self.app.plotcanvas.graph_event_connect('mouse_release', self.app.mr = self.app.plotcanvas.graph_event_connect('mouse_release',
self.app.on_mouse_click_release_over_plot) self.app.on_mouse_click_release_over_plot)
self.handlers_connected = False
self.app.call_source = "app"
self.app.inform.emit('[success] %s' % _("Copper Thieving Tool exit."))
def flatten(self, geometry): def flatten(self, geometry):
""" """

View File

@ -304,6 +304,11 @@ class ToolCorners(AppTool):
outname = '%s_%s' % (str(self.grb_object.options['name']), 'corners') outname = '%s_%s' % (str(self.grb_object.options['name']), 'corners')
def initialize(grb_obj, app_obj): def initialize(grb_obj, app_obj):
grb_obj.options = {}
for opt in g_obj.options:
if opt != 'name':
grb_obj.options[opt] = deepcopy(g_obj.options[opt])
grb_obj.options['name'] = outname
grb_obj.multitool = False grb_obj.multitool = False
grb_obj.multigeo = False grb_obj.multigeo = False
grb_obj.follow = deepcopy(g_obj.follow) grb_obj.follow = deepcopy(g_obj.follow)
@ -417,12 +422,16 @@ class ToolCorners(AppTool):
else: else:
worker_task() worker_task()
def on_exit(self, corner_gerber_obj): def on_exit(self, corner_gerber_obj=None):
# plot the object # plot the object
try: if corner_gerber_obj:
self.replot(obj=corner_gerber_obj) try:
except (AttributeError, TypeError): for ob in corner_gerber_obj:
return self.replot(obj=ob)
except (AttributeError, TypeError):
self.replot(obj=corner_gerber_obj)
except Exception:
return
# update the bounding box values # update the bounding box values
try: try:
@ -613,7 +622,7 @@ class CornersUI:
grid_lay.addWidget(self.drills_label, 16, 0, 1, 2) grid_lay.addWidget(self.drills_label, 16, 0, 1, 2)
# Drill Tooldia # # Drill Tooldia #
self.drill_dia_label = FCLabel('%s:' % _("Tool Dia")) self.drill_dia_label = FCLabel('%s:' % _("Drill Dia"))
self.drill_dia_label.setToolTip( self.drill_dia_label.setToolTip(
'%s.' % _("Drill Diameter") '%s.' % _("Drill Diameter")
) )

View File

@ -824,7 +824,7 @@ class DsidedUI:
grid4.addWidget(self.alignment_label, 0, 0, 1, 2) grid4.addWidget(self.alignment_label, 0, 0, 1, 2)
# ## Drill diameter for alignment holes # ## Drill diameter for alignment holes
self.dt_label = FCLabel("%s:" % _('Drill Diameter')) self.dt_label = FCLabel("%s:" % _('Drill Dia'))
self.dt_label.setToolTip( self.dt_label.setToolTip(
_("Diameter of the drill for the alignment holes.") _("Diameter of the drill for the alignment holes.")
) )

View File

@ -12,6 +12,7 @@ from appGUI.GUIElements import FCDoubleSpinner, RadioSet, EvalEntry, FCTable, FC
from shapely.geometry import Point, Polygon, MultiPolygon, LineString from shapely.geometry import Point, Polygon, MultiPolygon, LineString
from shapely.geometry import box as box from shapely.geometry import box as box
from shapely.ops import unary_union
import math import math
import logging import logging
@ -76,6 +77,8 @@ class ToolFiducials(AppTool):
self.click_points = [] self.click_points = []
self.handlers_connected = False
# SIGNALS # SIGNALS
self.ui.add_cfid_button.clicked.connect(self.add_fiducials) self.ui.add_cfid_button.clicked.connect(self.add_fiducials)
self.ui.add_sm_opening_button.clicked.connect(self.add_soldermask_opening) self.ui.add_sm_opening_button.clicked.connect(self.add_soldermask_opening)
@ -147,12 +150,13 @@ class ToolFiducials(AppTool):
def on_method_change(self, val): def on_method_change(self, val):
""" """
Make sure that on method change we disconnect the event handlers and reset the points storage Make sure that on method change we disconnect the event handlers and reset the points storage
:param val: value of the Radio button which trigger this method
:return: None
"""
if val == 'auto':
self.click_points = []
:param val: value of the Radio button which trigger this method
:return: None
"""
self.click_points = []
if val == 'auto':
try: try:
self.disconnect_event_handlers() self.disconnect_event_handlers()
except TypeError: except TypeError:
@ -228,10 +232,14 @@ class ToolFiducials(AppTool):
) )
self.ui.sec_points_coords_entry.set_value('(%.*f, %.*f)' % (self.decimals, x1, self.decimals, y0)) self.ui.sec_points_coords_entry.set_value('(%.*f, %.*f)' % (self.decimals, x1, self.decimals, y0))
self.add_fiducials_geo(self.click_points, g_obj=self.grb_object, fid_type=fid_type) ret_val = self.add_fiducials_geo(self.click_points, g_obj=self.grb_object, fid_type=fid_type)
self.grb_object.source_file = self.app.f_handlers.export_gerber(obj_name=self.grb_object.options['name'], self.app.call_source = "app"
filename=None, if ret_val == 'fail':
local_use=self.grb_object, use_thread=False) self.app.call_source = "app"
self.disconnect_event_handlers()
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed."))
return
self.on_exit() self.on_exit()
else: else:
self.app.inform.emit(_("Click to add first Fiducial. Bottom Left...")) self.app.inform.emit(_("Click to add first Fiducial. Bottom Left..."))
@ -259,6 +267,8 @@ class ToolFiducials(AppTool):
radius = fid_size / 2.0 radius = fid_size / 2.0
new_apertures = deepcopy(g_obj.apertures)
if fid_type == 'circular': if fid_type == 'circular':
geo_list = [Point(pt).buffer(radius, self.grb_steps_per_circle) for pt in points_list] geo_list = [Point(pt).buffer(radius, self.grb_steps_per_circle) for pt in points_list]
@ -271,7 +281,7 @@ class ToolFiducials(AppTool):
if aperture_found: if aperture_found:
for geo in geo_list: for geo in geo_list:
dict_el = {'follow': geo.centroid, 'solid': geo} dict_el = {'follow': geo.centroid, 'solid': geo}
g_obj.apertures[aperture_found]['geometry'].append(deepcopy(dict_el)) new_apertures[aperture_found]['geometry'].append(deepcopy(dict_el))
else: else:
ap_keys = list(g_obj.apertures.keys()) ap_keys = list(g_obj.apertures.keys())
if ap_keys: if ap_keys:
@ -279,14 +289,15 @@ class ToolFiducials(AppTool):
else: else:
new_apid = '10' new_apid = '10'
g_obj.apertures[new_apid] = {} new_apertures[new_apid] = {
g_obj.apertures[new_apid]['type'] = 'C' 'type': 'C',
g_obj.apertures[new_apid]['size'] = fid_size 'size': fid_size,
g_obj.apertures[new_apid]['geometry'] = [] 'geometry': []
}
for geo in geo_list: for geo in geo_list:
dict_el = {'follow': geo.centroid, 'solid': geo} dict_el = {'follow': geo.centroid, 'solid': geo}
g_obj.apertures[new_apid]['geometry'].append(deepcopy(dict_el)) new_apertures[new_apid]['geometry'].append(deepcopy(dict_el))
s_list = [] s_list = []
if g_obj.solid_geometry: if g_obj.solid_geometry:
@ -297,7 +308,6 @@ class ToolFiducials(AppTool):
s_list.append(g_obj.solid_geometry) s_list.append(g_obj.solid_geometry)
s_list += geo_list s_list += geo_list
g_obj.solid_geometry = MultiPolygon(s_list)
elif fid_type == 'cross': elif fid_type == 'cross':
geo_list = [] geo_list = []
@ -327,10 +337,9 @@ class ToolFiducials(AppTool):
geo_buff_list.append(geo_buff_v) geo_buff_list.append(geo_buff_v)
dict_el = {'follow': geo_buff_h.centroid, 'solid': geo_buff_h} dict_el = {'follow': geo_buff_h.centroid, 'solid': geo_buff_h}
g_obj.apertures[aperture_found]['geometry'].append(deepcopy(dict_el)) new_apertures[aperture_found]['geometry'].append(deepcopy(dict_el))
dict_el['follow'] = geo_buff_v.centroid dict_el = {'follow': geo_buff_v.centroid, 'solid': geo_buff_v}
dict_el['solid'] = geo_buff_v new_apertures[aperture_found]['geometry'].append(deepcopy(dict_el))
g_obj.apertures[aperture_found]['geometry'].append(deepcopy(dict_el))
else: else:
ap_keys = list(g_obj.apertures.keys()) ap_keys = list(g_obj.apertures.keys())
if ap_keys: if ap_keys:
@ -338,7 +347,7 @@ class ToolFiducials(AppTool):
else: else:
new_apid = '10' new_apid = '10'
g_obj.apertures[new_apid] = { new_apertures[new_apid] = {
'type': 'C', 'type': 'C',
'size': line_thickness, 'size': line_thickness,
'geometry': [] 'geometry': []
@ -351,10 +360,9 @@ class ToolFiducials(AppTool):
geo_buff_list.append(geo_buff_v) geo_buff_list.append(geo_buff_v)
dict_el = {'follow': geo_buff_h.centroid, 'solid': geo_buff_h} dict_el = {'follow': geo_buff_h.centroid, 'solid': geo_buff_h}
g_obj.apertures[new_apid]['geometry'].append(deepcopy(dict_el)) new_apertures[new_apid]['geometry'].append(deepcopy(dict_el))
dict_el['follow'] = geo_buff_v.centroid dict_el = {'follow': geo_buff_v.centroid, 'solid': geo_buff_v}
dict_el['solid'] = geo_buff_v new_apertures[new_apid]['geometry'].append(deepcopy(dict_el))
g_obj.apertures[new_apid]['geometry'].append(deepcopy(dict_el))
s_list = [] s_list = []
if g_obj.solid_geometry: if g_obj.solid_geometry:
@ -368,7 +376,6 @@ class ToolFiducials(AppTool):
geo_buff_list = geo_buff_list.buffer(0) geo_buff_list = geo_buff_list.buffer(0)
for poly in geo_buff_list: for poly in geo_buff_list:
s_list.append(poly) s_list.append(poly)
g_obj.solid_geometry = MultiPolygon(s_list)
else: else:
# chess pattern fiducial type # chess pattern fiducial type
geo_list = [] geo_list = []
@ -406,7 +413,7 @@ class ToolFiducials(AppTool):
geo_buff_list.append(geo) geo_buff_list.append(geo)
dict_el = {'follow': geo.centroid, 'solid': geo} dict_el = {'follow': geo.centroid, 'solid': geo}
g_obj.apertures[aperture_found]['geometry'].append(deepcopy(dict_el)) new_apertures[aperture_found]['geometry'].append(deepcopy(dict_el))
else: else:
ap_keys = list(g_obj.apertures.keys()) ap_keys = list(g_obj.apertures.keys())
if ap_keys: if ap_keys:
@ -414,7 +421,7 @@ class ToolFiducials(AppTool):
else: else:
new_apid = '10' new_apid = '10'
g_obj.apertures[new_apid] = { new_apertures[new_apid] = {
'type': 'R', 'type': 'R',
'size': new_ap_size, 'size': new_ap_size,
'width': fid_size, 'width': fid_size,
@ -426,7 +433,7 @@ class ToolFiducials(AppTool):
geo_buff_list.append(geo) geo_buff_list.append(geo)
dict_el = {'follow': geo.centroid, 'solid': geo} dict_el = {'follow': geo.centroid, 'solid': geo}
g_obj.apertures[new_apid]['geometry'].append(deepcopy(dict_el)) new_apertures[new_apid]['geometry'].append(deepcopy(dict_el))
s_list = [] s_list = []
if g_obj.solid_geometry: if g_obj.solid_geometry:
@ -438,7 +445,28 @@ class ToolFiducials(AppTool):
for poly in geo_buff_list: for poly in geo_buff_list:
s_list.append(poly) s_list.append(poly)
g_obj.solid_geometry = MultiPolygon(s_list)
outname = '%s_%s' % (str(g_obj.options['name']), 'fid')
def initialize(grb_obj, app_obj):
grb_obj.options = {}
for opt in g_obj.options:
if opt != 'name':
grb_obj.options[opt] = deepcopy(g_obj.options[opt])
grb_obj.options['name'] = outname
grb_obj.multitool = False
grb_obj.multigeo = False
grb_obj.follow = deepcopy(g_obj.follow)
grb_obj.apertures = new_apertures
grb_obj.solid_geometry = unary_union(s_list)
grb_obj.follow_geometry = deepcopy(g_obj.follow_geometry) + geo_list
grb_obj.source_file = app_obj.f_handlers.export_gerber(obj_name=outname, filename=None, local_use=grb_obj,
use_thread=False)
ret = self.app.app_obj.new_object('gerber', outname, initialize, plot=True)
return ret
def add_soldermask_opening(self): def add_soldermask_opening(self):
sm_opening_dia = self.ui.fid_size_entry.get_value() * 2.0 sm_opening_dia = self.ui.fid_size_entry.get_value() * 2.0
@ -455,12 +483,15 @@ class ToolFiducials(AppTool):
return return
self.sm_obj_set.add(self.sm_object.options['name']) self.sm_obj_set.add(self.sm_object.options['name'])
self.add_fiducials_geo(self.click_points, g_obj=self.sm_object, fid_size=sm_opening_dia, fid_type='circular') ret_val = self.add_fiducials_geo(
self.click_points, g_obj=self.sm_object, fid_size=sm_opening_dia, fid_type='circular')
self.app.call_source = "app"
if ret_val == 'fail':
self.app.call_source = "app"
self.disconnect_event_handlers()
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed."))
return
self.sm_object.source_file = self.app.f_handlers.export_gerber(obj_name=self.sm_object.options['name'],
filename=None,
local_use=self.sm_object,
use_thread=False)
self.on_exit() self.on_exit()
def on_mouse_release(self, event): def on_mouse_release(self, event):
@ -486,7 +517,7 @@ class ToolFiducials(AppTool):
self.check_points() self.check_points()
def check_points(self): def check_points(self):
fid_type = self.fid_type_radio.get_value() fid_type = self.ui.fid_type_radio.get_value()
if len(self.click_points) == 1: if len(self.click_points) == 1:
self.ui.bottom_left_coords_entry.set_value(self.click_points[0]) self.ui.bottom_left_coords_entry.set_value(self.click_points[0])
@ -499,19 +530,29 @@ class ToolFiducials(AppTool):
elif len(self.click_points) == 3: elif len(self.click_points) == 3:
self.ui.sec_points_coords_entry.set_value(self.click_points[2]) self.ui.sec_points_coords_entry.set_value(self.click_points[2])
self.app.inform.emit('[success] %s' % _("Done. All fiducials have been added.")) self.app.inform.emit('[success] %s' % _("Done. All fiducials have been added."))
self.add_fiducials_geo(self.click_points, g_obj=self.grb_object, fid_type=fid_type)
self.grb_object.source_file = self.app.f_handlers.export_gerber( ret_val = self.add_fiducials_geo(self.click_points, g_obj=self.grb_object, fid_type=fid_type)
obj_name=self.grb_object.options['name'], filename=None, local_use=self.grb_object, self.app.call_source = "app"
use_thread=False)
if ret_val == 'fail':
self.app.call_source = "app"
self.disconnect_event_handlers()
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed."))
return
self.on_exit() self.on_exit()
else: else:
if len(self.click_points) == 2: if len(self.click_points) == 2:
self.ui.top_right_coords_entry.set_value(self.click_points[1]) self.ui.top_right_coords_entry.set_value(self.click_points[1])
self.app.inform.emit('[success] %s' % _("Done. All fiducials have been added.")) self.app.inform.emit('[success] %s' % _("Done. All fiducials have been added."))
self.add_fiducials_geo(self.click_points, g_obj=self.grb_object, fid_type=fid_type)
self.grb_object.source_file = self.app.f_handlers.export_gerber( ret_val = self.add_fiducials_geo(self.click_points, g_obj=self.grb_object, fid_type=fid_type)
obj_name=self.grb_object.options['name'], filename=None, self.app.call_source = "app"
local_use=self.grb_object, use_thread=False)
if ret_val == 'fail':
self.app.call_source = "app"
self.disconnect_event_handlers()
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed."))
return
self.on_exit() self.on_exit()
def on_mouse_move(self, event): def on_mouse_move(self, event):
@ -521,6 +562,7 @@ class ToolFiducials(AppTool):
def worker_task(): def worker_task():
with self.app.proc_container.new('%s...' % _("Plotting")): with self.app.proc_container.new('%s...' % _("Plotting")):
obj.plot() obj.plot()
self.app.app_obj.object_plotted.emit(obj)
if run_thread: if run_thread:
self.app.worker_task.emit({'fcn': worker_task, 'params': []}) self.app.worker_task.emit({'fcn': worker_task, 'params': []})
@ -569,10 +611,6 @@ class ToolFiducials(AppTool):
except Exception as e: except Exception as e:
log.debug("ToolFiducials.on_exit() sm_obj bounds error --> %s" % str(e)) log.debug("ToolFiducials.on_exit() sm_obj bounds error --> %s" % str(e))
# reset the variables
self.grb_object = None
self.sm_object = None
# Events ID # Events ID
self.mr = None self.mr = None
# self.mm = None # self.mm = None
@ -587,32 +625,31 @@ class ToolFiducials(AppTool):
self.app.inform.emit('[success] %s' % _("Fiducials Tool exit.")) self.app.inform.emit('[success] %s' % _("Fiducials Tool exit."))
def connect_event_handlers(self): def connect_event_handlers(self):
if self.app.is_legacy is False: if self.handlers_connected is False:
self.app.plotcanvas.graph_event_disconnect('mouse_press', self.app.on_mouse_click_over_plot) if self.app.is_legacy is False:
# self.app.plotcanvas.graph_event_disconnect('mouse_move', self.app.on_mouse_move_over_plot) self.app.plotcanvas.graph_event_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot) self.app.plotcanvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
else: else:
self.app.plotcanvas.graph_event_disconnect(self.app.mp) self.app.plotcanvas.graph_event_disconnect(self.app.mp)
# self.app.plotcanvas.graph_event_disconnect(self.app.mm) self.app.plotcanvas.graph_event_disconnect(self.app.mr)
self.app.plotcanvas.graph_event_disconnect(self.app.mr)
self.mr = self.app.plotcanvas.graph_event_connect('mouse_release', self.on_mouse_release) self.mr = self.app.plotcanvas.graph_event_connect('mouse_release', self.on_mouse_release)
# self.mm = self.app.plotcanvas.graph_event_connect('mouse_move', self.on_mouse_move)
self.handlers_connected = True
def disconnect_event_handlers(self): def disconnect_event_handlers(self):
if self.app.is_legacy is False: if self.handlers_connected is True:
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.on_mouse_release) if self.app.is_legacy is False:
# self.app.plotcanvas.graph_event_disconnect('mouse_move', self.on_mouse_move) self.app.plotcanvas.graph_event_disconnect('mouse_release', self.on_mouse_release)
else: else:
self.app.plotcanvas.graph_event_disconnect(self.mr) self.app.plotcanvas.graph_event_disconnect(self.mr)
# self.app.plotcanvas.graph_event_disconnect(self.mm)
self.app.mp = self.app.plotcanvas.graph_event_connect('mouse_press', self.app.mp = self.app.plotcanvas.graph_event_connect('mouse_press',
self.app.on_mouse_click_over_plot) self.app.on_mouse_click_over_plot)
# self.app.mm = self.app.plotcanvas.graph_event_connect('mouse_move',
# self.app.on_mouse_move_over_plot) self.app.mr = self.app.plotcanvas.graph_event_connect('mouse_release',
self.app.mr = self.app.plotcanvas.graph_event_connect('mouse_release', self.app.on_mouse_click_release_over_plot)
self.app.on_mouse_click_release_over_plot) self.handlers_connected = False
def flatten(self, geometry): def flatten(self, geometry):
""" """

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff