- Cutout Tool - finished adding the Mouse Bites feature by adding mouse bites for manual cutouts
This commit is contained in:
parent
26ac02e484
commit
15a8f718c9
|
@ -19,6 +19,7 @@ CHANGELOG for FlatCAM beta
|
||||||
- Cutout Tool - fixed mouse bites feature in case of using a Geometry object and Freeform cutout
|
- Cutout Tool - fixed mouse bites feature in case of using a Geometry object and Freeform cutout
|
||||||
- Cutout Tool - can do cutouts on multigeo Geometry objects: it will automatically select the geometry of first tool
|
- Cutout Tool - can do cutouts on multigeo Geometry objects: it will automatically select the geometry of first tool
|
||||||
- Geometry Editor - fixed exception raised when trying to move and there is no shape to move
|
- Geometry Editor - fixed exception raised when trying to move and there is no shape to move
|
||||||
|
- Cutout Tool - finished adding the Mouse Bites feature by adding mouse bites for manual cutouts
|
||||||
|
|
||||||
28.08.2020
|
28.08.2020
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,12 @@ class CutOut(AppTool):
|
||||||
# store original geometry for manual cutout
|
# store original geometry for manual cutout
|
||||||
self.manual_solid_geo = None
|
self.manual_solid_geo = None
|
||||||
|
|
||||||
|
# here will store the original geometry for manual cutout with mouse bytes
|
||||||
|
self.mb_manual_solid_geo = None
|
||||||
|
|
||||||
|
# here will store the geo rests when doing manual cutouts with mouse bites
|
||||||
|
self.mb_manual_cuts = []
|
||||||
|
|
||||||
# here store the tool data for the Cutout Tool
|
# here store the tool data for the Cutout Tool
|
||||||
self.cut_tool_dict = {}
|
self.cut_tool_dict = {}
|
||||||
|
|
||||||
|
@ -1286,13 +1292,18 @@ class CutOut(AppTool):
|
||||||
|
|
||||||
self.manual_solid_geo = deepcopy(self.flatten(self.man_cutout_obj.solid_geometry))
|
self.manual_solid_geo = deepcopy(self.flatten(self.man_cutout_obj.solid_geometry))
|
||||||
|
|
||||||
self.cutting_dia = float(self.ui.dia.get_value())
|
self.cutting_dia = self.ui.dia.get_value()
|
||||||
if 0 in {self.cutting_dia}:
|
if 0 in {self.cutting_dia}:
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
||||||
_("Tool Diameter is zero value. Change it to a positive real number."))
|
_("Tool Diameter is zero value. Change it to a positive real number."))
|
||||||
return
|
return
|
||||||
|
|
||||||
self.cutting_gapsize = float(self.ui.gapsize.get_value())
|
if self.ui.gaptype_radio.get_value() == 'mb':
|
||||||
|
mb_dia = self.ui.mb_dia_entry.get_value()
|
||||||
|
b_dia = (self.cutting_dia / 2.0) - (mb_dia / 2.0)
|
||||||
|
self.mb_manual_solid_geo = self.flatten(unary_union(self.manual_solid_geo).buffer(b_dia).interiors)
|
||||||
|
|
||||||
|
self.cutting_gapsize = self.ui.gapsize.get_value()
|
||||||
|
|
||||||
name = self.ui.man_object_combo.currentText()
|
name = self.ui.man_object_combo.currentText()
|
||||||
# Get Geometry source object to be used as target for Manual adding Gaps
|
# Get Geometry source object to be used as target for Manual adding Gaps
|
||||||
|
@ -1328,8 +1339,8 @@ class CutOut(AppTool):
|
||||||
def on_manual_cutout(self, click_pos):
|
def on_manual_cutout(self, click_pos):
|
||||||
|
|
||||||
if self.man_cutout_obj is None:
|
if self.man_cutout_obj is None:
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
|
msg = '[ERROR_NOTCL] %s: %s' % (_("Geometry object for manual cutout not found"), self.man_cutout_obj)
|
||||||
(_("Geometry object for manual cutout not found"), self.man_cutout_obj))
|
self.app.inform.emit(msg)
|
||||||
return
|
return
|
||||||
|
|
||||||
# use the snapped position as reference
|
# use the snapped position as reference
|
||||||
|
@ -1337,10 +1348,18 @@ class CutOut(AppTool):
|
||||||
|
|
||||||
cut_poly = self.cutting_geo(pos=(snapped_pos[0], snapped_pos[1]))
|
cut_poly = self.cutting_geo(pos=(snapped_pos[0], snapped_pos[1]))
|
||||||
|
|
||||||
|
gap_type = self.ui.gaptype_radio.get_value()
|
||||||
gaps_solid_geo = None
|
gaps_solid_geo = None
|
||||||
if self.ui.gaptype_radio.get_value() == 'bt' and self.ui.thin_depth_entry.get_value() != 0:
|
if gap_type == 'bt' and self.ui.thin_depth_entry.get_value() != 0:
|
||||||
gaps_solid_geo = self.intersect_geo(self.manual_solid_geo, cut_poly)
|
gaps_solid_geo = self.intersect_geo(self.manual_solid_geo, cut_poly)
|
||||||
|
|
||||||
|
if gap_type == 'mb':
|
||||||
|
rests_geo = self.intersect_geo(self.mb_manual_solid_geo, cut_poly)
|
||||||
|
if isinstance(rests_geo, list):
|
||||||
|
self.mb_manual_cuts += rests_geo
|
||||||
|
else:
|
||||||
|
self.mb_manual_cuts.append(rests_geo)
|
||||||
|
|
||||||
# first subtract geometry for the total solid_geometry
|
# first subtract geometry for the total solid_geometry
|
||||||
new_solid_geometry = CutOut.subtract_geo(self.man_cutout_obj.solid_geometry, cut_poly)
|
new_solid_geometry = CutOut.subtract_geo(self.man_cutout_obj.solid_geometry, cut_poly)
|
||||||
new_solid_geometry = linemerge(new_solid_geometry)
|
new_solid_geometry = linemerge(new_solid_geometry)
|
||||||
|
@ -1359,7 +1378,7 @@ class CutOut(AppTool):
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("No tool in the Geometry object."))
|
self.app.inform.emit('[ERROR_NOTCL] %s' % _("No tool in the Geometry object."))
|
||||||
return
|
return
|
||||||
|
|
||||||
dia = float(self.ui.dia.get_value())
|
dia = self.ui.dia.get_value()
|
||||||
if gaps_solid_geo:
|
if gaps_solid_geo:
|
||||||
if 9999 not in self.man_cutout_obj.tools:
|
if 9999 not in self.man_cutout_obj.tools:
|
||||||
self.man_cutout_obj.tools.update({
|
self.man_cutout_obj.tools.update({
|
||||||
|
@ -1549,6 +1568,52 @@ class CutOut(AppTool):
|
||||||
# plot the final object
|
# plot the final object
|
||||||
self.man_cutout_obj.plot()
|
self.man_cutout_obj.plot()
|
||||||
|
|
||||||
|
# mouse bytes
|
||||||
|
if self.ui.gaptype_radio.get_value() == 'mb':
|
||||||
|
with self.app.proc_container.new("Generating Excellon ..."):
|
||||||
|
outname_exc = self.man_cutout_obj.options["name"] + "_mouse_bites"
|
||||||
|
self.app.collection.promise(outname_exc)
|
||||||
|
|
||||||
|
def job_thread(app_obj):
|
||||||
|
# list of Shapely Points to mark the drill points centers
|
||||||
|
holes = []
|
||||||
|
mb_dia = self.ui.mb_dia_entry.get_value()
|
||||||
|
mb_spacing = self.ui.mb_spacing_entry.get_value()
|
||||||
|
for line in self.mb_manual_cuts:
|
||||||
|
calc_len = 0
|
||||||
|
while calc_len < line.length:
|
||||||
|
holes.append(line.interpolate(calc_len))
|
||||||
|
calc_len += mb_dia + mb_spacing
|
||||||
|
self.mb_manual_cuts[:] = []
|
||||||
|
|
||||||
|
def excellon_init(exc_obj, app_o):
|
||||||
|
if not holes:
|
||||||
|
return 'fail'
|
||||||
|
|
||||||
|
tools = {}
|
||||||
|
tools[1] = {}
|
||||||
|
tools[1]["tooldia"] = mb_dia
|
||||||
|
tools[1]['drills'] = holes
|
||||||
|
tools[1]['solid_geometry'] = []
|
||||||
|
|
||||||
|
exc_obj.tools = tools
|
||||||
|
exc_obj.create_geometry()
|
||||||
|
exc_obj.source_file = app_o.export_excellon(obj_name=exc_obj.options['name'],
|
||||||
|
local_use=exc_obj,
|
||||||
|
filename=None, use_thread=False)
|
||||||
|
# calculate the bounds
|
||||||
|
xmin, ymin, xmax, ymax = CutOut.recursive_bounds(exc_obj.solid_geometry)
|
||||||
|
exc_obj.options['xmin'] = xmin
|
||||||
|
exc_obj.options['ymin'] = ymin
|
||||||
|
exc_obj.options['xmax'] = xmax
|
||||||
|
exc_obj.options['ymax'] = ymax
|
||||||
|
|
||||||
|
ret = app_obj.app_obj.new_object('excellon', outname_exc, excellon_init)
|
||||||
|
if ret == 'fail':
|
||||||
|
app_obj.inform.emit('[ERROR_NOTCL] %s' % _("Mouse bites failed."))
|
||||||
|
|
||||||
|
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
|
||||||
|
|
||||||
self.app.inform.emit('[success] %s' % _("Finished manual adding of gaps."))
|
self.app.inform.emit('[success] %s' % _("Finished manual adding of gaps."))
|
||||||
|
|
||||||
def on_mouse_move(self, event):
|
def on_mouse_move(self, event):
|
||||||
|
|
Loading…
Reference in New Issue