- finished Copper Thieving Tool improvements

This commit is contained in:
Marius Stanciu 2019-11-18 23:03:04 +02:00 committed by Marius
parent 8888869d3b
commit 92b1ad6f05
3 changed files with 349 additions and 297 deletions

View File

@ -14,6 +14,7 @@ CAD program, and create G-Code for Isolation routing.
- finished the Dots and Squares options in the Copper Thieving Tool
- working on the Lines option in Copper Thieving Tool
- finished the Lines option in the Copper Thieving Tool; still have to add threading to maximize performance
- finished Copper Thieving Tool improvements
17.11.2019

View File

@ -336,6 +336,9 @@ class ToolCopperThieving(FlatCAMTool):
self.ref_obj = None
self.sel_rect = list()
# store the flattened geometry here:
self.flat_geometry = list()
# Events ID
self.mr = None
self.mm = None
@ -405,6 +408,7 @@ class ToolCopperThieving(FlatCAMTool):
self.line_size_entry.set_value(self.app.defaults["tools_copper_thieving_lines_size"])
self.lines_spacing_entry.set_value(self.app.defaults["tools_copper_thieving_lines_spacing"])
# INIT SECTION
self.area_method = False
def on_combo_box_type(self):
@ -428,6 +432,11 @@ class ToolCopperThieving(FlatCAMTool):
self.bbox_type_label.show()
self.bbox_type_radio.show()
else:
if self.fill_type_radio.get_value() == 'line':
self.reference_radio.set_value('itself')
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Lines Grid works only for 'itself' reference ..."))
return
self.bbox_type_label.hide()
self.bbox_type_radio.hide()
@ -436,15 +445,21 @@ class ToolCopperThieving(FlatCAMTool):
self.dots_frame.hide()
self.squares_frame.hide()
self.lines_frame.hide()
self.app.inform.emit(_("Solid fill selected."))
elif choice == 'dot':
self.dots_frame.show()
self.squares_frame.hide()
self.lines_frame.hide()
self.app.inform.emit(_("Dots grid fill selected."))
elif choice == 'square':
self.dots_frame.hide()
self.squares_frame.show()
self.lines_frame.hide()
self.app.inform.emit(_("Squares grid fill selected."))
else:
if self.reference_radio.get_value() != 'itself':
self.reference_radio.set_value('itself')
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Lines Grid works only for 'itself' reference ..."))
self.dots_frame.hide()
self.squares_frame.hide()
self.lines_frame.show()
@ -656,11 +671,12 @@ class ToolCopperThieving(FlatCAMTool):
"""
if run_threaded:
proc = self.app.proc_container.new('%s ...' % _("Copper thieving"))
proc = self.app.proc_container.new('%s ...' % _("Thieving"))
else:
self.app.proc_container.view.set_busy('%s ...' % _("Copper thieving"))
QtWidgets.QApplication.processEvents()
self.app.proc_container.view.set_busy('%s ...' % _("Thieving"))
# #####################################################################
# ####### Read the parameters #########################################
# #####################################################################
@ -686,340 +702,353 @@ class ToolCopperThieving(FlatCAMTool):
if not isinstance(self.grb_object.solid_geometry, Iterable):
self.grb_object.solid_geometry = [self.grb_object.solid_geometry]
# #########################################################################################
# Prepare isolation polygon. This will create the clearance over the Gerber features ######
# #########################################################################################
log.debug("Copper Thieving Tool. Preparing isolation polygons.")
self.app.inform.emit(_("Copper Thieving Tool. Preparing isolation polygons."))
# variables to display the percentage of work done
geo_len = 0
try:
for pol in self.grb_object.solid_geometry:
geo_len += 1
except TypeError:
geo_len = 1
old_disp_number = 0
pol_nr = 0
clearance_geometry = []
try:
for pol in self.grb_object.solid_geometry:
if self.app.abort_flag:
# graceful abort requested by the user
raise FlatCAMApp.GracefulException
clearance_geometry.append(
pol.buffer(c_val, int(int(self.geo_steps_per_circle) / 4))
)
pol_nr += 1
disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 100]))
if old_disp_number < disp_number <= 100:
self.app.proc_container.update_view_text(' %s ... %d%%' %
(_("Buffering"), int(disp_number)))
old_disp_number = disp_number
except TypeError:
# taking care of the case when the self.solid_geometry is just a single Polygon, not a list or a
# MultiPolygon (not an iterable)
clearance_geometry.append(
self.grb_object.solid_geometry.buffer(c_val, int(int(self.geo_steps_per_circle) / 4))
)
self.app.proc_container.update_view_text(' %s' % _("Buffering"))
clearance_geometry = unary_union(clearance_geometry)
# #########################################################################################
# Prepare the area to fill with copper. ###################################################
# #########################################################################################
log.debug("Copper Thieving Tool. Preparing areas to fill with copper.")
self.app.inform.emit(_("Copper Thieving Tool. Preparing areas to fill with copper."))
try:
if ref_obj is None or ref_obj == 'itself':
working_obj = thieving_obj
else:
working_obj = ref_obj
except Exception as e:
log.debug("ToolCopperThieving.on_copper_thieving() --> %s" % str(e))
return 'fail'
bounding_box = None
if ref_selected == 'itself':
geo_n = working_obj.solid_geometry
def job_thread_thieving(app_obj):
# #########################################################################################
# Prepare isolation polygon. This will create the clearance over the Gerber features ######
# #########################################################################################
log.debug("Copper Thieving Tool. Preparing isolation polygons.")
app_obj.app.inform.emit(_("Copper Thieving Tool. Preparing isolation polygons."))
# variables to display the percentage of work done
geo_len = 0
try:
if self.bbox_type_radio.get_value() == 'min':
if isinstance(geo_n, MultiPolygon):
env_obj = geo_n.convex_hull
elif (isinstance(geo_n, MultiPolygon) and len(geo_n) == 1) or \
(isinstance(geo_n, list) and len(geo_n) == 1) and isinstance(geo_n[0], Polygon):
env_obj = cascaded_union(geo_n)
else:
env_obj = cascaded_union(geo_n)
env_obj = env_obj.convex_hull
else:
if isinstance(geo_n, Polygon):
env_obj = geo_n.buffer(0, join_style=base.JOIN_STYLE.mitre).exterior
elif isinstance(geo_n, list):
geo_n = unary_union(geo_n)
env_obj = geo_n.buffer(0, join_style=base.JOIN_STYLE.mitre).exterior
elif isinstance(geo_n, MultiPolygon):
x0, y0, x1, y1 = geo_n.bounds
geo = box(x0, y0, x1, y1)
env_obj = geo.buffer(0, join_style=base.JOIN_STYLE.mitre)
else:
self.app.inform.emit(
'[ERROR_NOTCL] %s: %s' % (_("Geometry not supported for bounding box"), type(geo_n))
)
return 'fail'
bounding_box = env_obj.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre)
except Exception as e:
log.debug("ToolCopperFIll.on_copper_thieving() 'itself' --> %s" % str(e))
self.app.inform.emit('[ERROR_NOTCL] %s' % _("No object available."))
return 'fail'
elif ref_selected == 'area':
geo_n = cascaded_union(working_obj)
try:
__ = iter(geo_n)
except Exception as e:
log.debug("ToolCopperFIll.on_copper_thieving() 'area' --> %s" % str(e))
geo_n = [geo_n]
geo_buff_list = []
for poly in geo_n:
if self.app.abort_flag:
# graceful abort requested by the user
raise FlatCAMApp.GracefulException
geo_buff_list.append(poly.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre))
bounding_box = cascaded_union(geo_buff_list)
else: # ref_selected == 'box'
geo_n = working_obj.solid_geometry
if isinstance(working_obj, FlatCAMGeometry):
try:
__ = iter(geo_n)
except Exception as e:
log.debug("ToolCopperFIll.on_copper_thieving() 'box' --> %s" % str(e))
geo_n = [geo_n]
geo_buff_list = []
for poly in geo_n:
if self.app.abort_flag:
# graceful abort requested by the user
raise FlatCAMApp.GracefulException
geo_buff_list.append(poly.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre))
bounding_box = cascaded_union(geo_buff_list)
elif isinstance(working_obj, FlatCAMGerber):
geo_n = cascaded_union(geo_n).convex_hull
bounding_box = cascaded_union(thieving_obj.solid_geometry).convex_hull.intersection(geo_n)
bounding_box = bounding_box.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre)
else:
self.app.inform.emit('[ERROR_NOTCL] %s' % _("The reference object type is not supported."))
return 'fail'
log.debug("Copper Thieving Tool. Finished creating areas to fill with copper.")
self.app.inform.emit(_("Copper Thieving Tool. Appending new geometry and buffering."))
# #########################################################################################
# ########## Generate filling geometry. ###################################################
# #########################################################################################
new_solid_geometry = bounding_box.difference(clearance_geometry)
# determine the bounding box polygon for the entire Gerber object to which we add copper thieving
if isinstance(geo_n, list):
env_obj = unary_union(geo_n).buffer(distance=margin, join_style=base.JOIN_STYLE.mitre)
else:
env_obj = geo_n.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre)
x0, y0, x1, y1 = env_obj.bounds
bounding_box = box(x0, y0, x1, y1)
if fill_type == 'dot' or fill_type == 'square':
# build the MultiPolygon of dots/squares that will fill the entire bounding box
thieving_list = list()
if fill_type == 'dot':
radius = dot_dia / 2.0
new_x = x0 + radius
new_y = y0 + radius
while new_x <= x1 - radius:
while new_y <= y1 - radius:
dot_geo = Point((new_x, new_y)).buffer(radius, resolution=64)
thieving_list.append(dot_geo)
new_y += dot_dia + dot_spacing
new_x += dot_dia + dot_spacing
new_y = y0 + radius
else:
h_size = square_size / 2.0
new_x = x0 + h_size
new_y = y0 + h_size
while new_x <= x1 - h_size:
while new_y <= y1 - h_size:
a, b, c, d = (Point((new_x, new_y)).buffer(h_size)).bounds
square_geo = box(a, b, c, d)
thieving_list.append(square_geo)
new_y += square_size + square_spacing
new_x += square_size + square_spacing
new_y = y0 + h_size
thieving_box_geo = MultiPolygon(thieving_list)
dx = bounding_box.centroid.x - thieving_box_geo.centroid.x
dy = bounding_box.centroid.y - thieving_box_geo.centroid.y
thieving_box_geo = affinity.translate(thieving_box_geo, xoff=dx, yoff=dy)
try:
_it = iter(new_solid_geometry)
for pol in app_obj.grb_object.solid_geometry:
geo_len += 1
except TypeError:
new_solid_geometry = [new_solid_geometry]
geo_len = 1
old_disp_number = 0
pol_nr = 0
clearance_geometry = []
try:
_it = iter(thieving_box_geo)
except TypeError:
thieving_box_geo = [thieving_box_geo]
thieving_geo = list()
for dot_geo in thieving_box_geo:
for geo_t in new_solid_geometry:
if dot_geo.within(geo_t):
thieving_geo.append(dot_geo)
new_solid_geometry = thieving_geo
if fill_type == 'line':
half_thick_line = line_size / 2.0
# create a thick polygon-line that surrounds the copper features
outline_geometry = []
try:
for pol in self.grb_object.solid_geometry:
if self.app.abort_flag:
for pol in app_obj.grb_object.solid_geometry:
if app_obj.app.abort_flag:
# graceful abort requested by the user
raise FlatCAMApp.GracefulException
outline_geometry.append(
pol.buffer(c_val+half_thick_line, int(int(self.geo_steps_per_circle) / 4))
clearance_geometry.append(
pol.buffer(c_val, int(int(app_obj.geo_steps_per_circle) / 4))
)
pol_nr += 1
disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 100]))
if old_disp_number < disp_number <= 100:
self.app.proc_container.update_view_text(' %s ... %d%%' %
(_("Buffering"), int(disp_number)))
app_obj.app.proc_container.update_view_text(' %s ... %d%%' %
(_("Thieving"), int(disp_number)))
old_disp_number = disp_number
except TypeError:
# taking care of the case when the self.solid_geometry is just a single Polygon, not a list or a
# MultiPolygon (not an iterable)
outline_geometry.append(
self.grb_object.solid_geometry.buffer(
c_val+half_thick_line,
int(int(self.geo_steps_per_circle) / 4)
)
clearance_geometry.append(
app_obj.grb_object.solid_geometry.buffer(c_val, int(int(app_obj.geo_steps_per_circle) / 4))
)
self.app.proc_container.update_view_text(' %s' % _("Buffering"))
outline_geometry = unary_union(outline_geometry)
app_obj.app.proc_container.update_view_text(' %s ...' % _("Buffering"))
clearance_geometry = unary_union(clearance_geometry)
# #########################################################################################
# Prepare the area 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."))
outline_line = list()
try:
for geo_o in outline_geometry:
outline_line.append(
geo_o.exterior.buffer(
half_thick_line, resolution=int(int(self.geo_steps_per_circle) / 4)
if ref_obj is None or ref_obj == 'itself':
working_obj = thieving_obj
else:
working_obj = ref_obj
except Exception as e:
log.debug("ToolCopperThieving.on_copper_thieving() --> %s" % str(e))
return 'fail'
app_obj.app.proc_container.update_view_text(' %s' % _("Working..."))
if ref_selected == 'itself':
geo_n = working_obj.solid_geometry
try:
if app_obj.bbox_type_radio.get_value() == 'min':
if isinstance(geo_n, MultiPolygon):
env_obj = geo_n.convex_hull
elif (isinstance(geo_n, MultiPolygon) and len(geo_n) == 1) or \
(isinstance(geo_n, list) and len(geo_n) == 1) and isinstance(geo_n[0], Polygon):
env_obj = cascaded_union(geo_n)
else:
env_obj = cascaded_union(geo_n)
env_obj = env_obj.convex_hull
bounding_box = env_obj.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre)
else:
if isinstance(geo_n, Polygon):
bounding_box = geo_n.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre).exterior
elif isinstance(geo_n, list):
geo_n = unary_union(geo_n)
bounding_box = geo_n.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre).exterior
elif isinstance(geo_n, MultiPolygon):
x0, y0, x1, y1 = geo_n.bounds
geo = box(x0, y0, x1, y1)
bounding_box = geo.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre)
else:
app_obj.app.inform.emit(
'[ERROR_NOTCL] %s: %s' % (_("Geometry not supported for bounding box"), type(geo_n))
)
return 'fail'
except Exception as e:
log.debug("ToolCopperFIll.on_copper_thieving() 'itself' --> %s" % str(e))
app_obj.app.inform.emit('[ERROR_NOTCL] %s' % _("No object available."))
return 'fail'
elif ref_selected == 'area':
geo_buff_list = []
try:
for poly in working_obj:
if app_obj.app.abort_flag:
# graceful abort requested by the user
raise FlatCAMApp.GracefulException
geo_buff_list.append(poly.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre))
except TypeError:
geo_buff_list.append(working_obj.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre))
bounding_box = MultiPolygon(geo_buff_list)
else: # ref_selected == 'box'
geo_n = working_obj.solid_geometry
if isinstance(working_obj, FlatCAMGeometry):
try:
__ = iter(geo_n)
except Exception as e:
log.debug("ToolCopperFIll.on_copper_thieving() 'box' --> %s" % str(e))
geo_n = [geo_n]
geo_buff_list = []
for poly in geo_n:
if app_obj.app.abort_flag:
# graceful abort requested by the user
raise FlatCAMApp.GracefulException
geo_buff_list.append(poly.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre))
bounding_box = cascaded_union(geo_buff_list)
elif isinstance(working_obj, FlatCAMGerber):
geo_n = cascaded_union(geo_n).convex_hull
bounding_box = cascaded_union(thieving_obj.solid_geometry).convex_hull.intersection(geo_n)
bounding_box = bounding_box.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre)
else:
app_obj.app.inform.emit('[ERROR_NOTCL] %s' % _("The reference object type is not supported."))
return 'fail'
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."))
# #########################################################################################
# ########## Generate filling geometry. ###################################################
# #########################################################################################
new_solid_geometry = bounding_box.difference(clearance_geometry)
# determine the bounding box polygon for the entire Gerber object to which we add copper thieving
# if isinstance(geo_n, list):
# env_obj = unary_union(geo_n).buffer(distance=margin, join_style=base.JOIN_STYLE.mitre)
# else:
# env_obj = geo_n.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre)
#
# x0, y0, x1, y1 = env_obj.bounds
# bounding_box = box(x0, y0, x1, y1)
app_obj.app.proc_container.update_view_text(' %s' % _("Create geometry"))
bounding_box = thieving_obj.solid_geometry.envelope.buffer(
distance=margin,
join_style=base.JOIN_STYLE.mitre
)
x0, y0, x1, y1 = bounding_box.bounds
if fill_type == 'dot' or fill_type == 'square':
# build the MultiPolygon of dots/squares that will fill the entire bounding box
thieving_list = list()
if fill_type == 'dot':
radius = dot_dia / 2.0
new_x = x0 + radius
new_y = y0 + radius
while new_x <= x1 - radius:
while new_y <= y1 - radius:
dot_geo = Point((new_x, new_y)).buffer(radius, resolution=64)
thieving_list.append(dot_geo)
new_y += dot_dia + dot_spacing
new_x += dot_dia + dot_spacing
new_y = y0 + radius
else:
h_size = square_size / 2.0
new_x = x0 + h_size
new_y = y0 + h_size
while new_x <= x1 - h_size:
while new_y <= y1 - h_size:
a, b, c, d = (Point((new_x, new_y)).buffer(h_size)).bounds
square_geo = box(a, b, c, d)
thieving_list.append(square_geo)
new_y += square_size + square_spacing
new_x += square_size + square_spacing
new_y = y0 + h_size
thieving_box_geo = MultiPolygon(thieving_list)
dx = bounding_box.centroid.x - thieving_box_geo.centroid.x
dy = bounding_box.centroid.y - thieving_box_geo.centroid.y
thieving_box_geo = affinity.translate(thieving_box_geo, xoff=dx, yoff=dy)
try:
_it = iter(new_solid_geometry)
except TypeError:
new_solid_geometry = [new_solid_geometry]
try:
_it = iter(thieving_box_geo)
except TypeError:
thieving_box_geo = [thieving_box_geo]
thieving_geo = list()
for dot_geo in thieving_box_geo:
for geo_t in new_solid_geometry:
if dot_geo.within(geo_t):
thieving_geo.append(dot_geo)
new_solid_geometry = thieving_geo
if fill_type == 'line':
half_thick_line = line_size / 2.0
# create a thick polygon-line that surrounds the copper features
outline_geometry = []
try:
for pol in app_obj.grb_object.solid_geometry:
if app_obj.app.abort_flag:
# graceful abort requested by the user
raise FlatCAMApp.GracefulException
outline_geometry.append(
pol.buffer(c_val+half_thick_line, int(int(app_obj.geo_steps_per_circle) / 4))
)
pol_nr += 1
disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 100]))
if old_disp_number < disp_number <= 100:
app_obj.app.proc_container.update_view_text(' %s ... %d%%' %
(_("Buffering"), int(disp_number)))
old_disp_number = disp_number
except TypeError:
# taking care of the case when the self.solid_geometry is just a single Polygon, not a list or a
# MultiPolygon (not an iterable)
outline_geometry.append(
app_obj.grb_object.solid_geometry.buffer(
c_val+half_thick_line,
int(int(app_obj.geo_steps_per_circle) / 4)
)
)
except TypeError:
outline_line.append(
outline_geometry.exterior.buffer(
half_thick_line, resolution=int(int(self.geo_steps_per_circle) / 4)
app_obj.app.proc_container.update_view_text(' %s' % _("Buffering"))
outline_geometry = unary_union(outline_geometry)
outline_line = list()
try:
for geo_o in outline_geometry:
outline_line.append(
geo_o.exterior.buffer(
half_thick_line, resolution=int(int(app_obj.geo_steps_per_circle) / 4)
)
)
except TypeError:
outline_line.append(
outline_geometry.exterior.buffer(
half_thick_line, resolution=int(int(app_obj.geo_steps_per_circle) / 4)
)
)
)
outline_geometry = unary_union(outline_line)
outline_geometry = unary_union(outline_line)
# create a polygon-line that surrounds in the inside the bounding box polygon of the target Gerber
box_outline_geo = box(x0, y0, x1, y1).buffer(-half_thick_line)
box_outline_geo_exterior = box_outline_geo.exterior
box_outline_geometry = box_outline_geo_exterior.buffer(
half_thick_line,
resolution=int(int(self.geo_steps_per_circle) / 4)
)
bx0, by0, bx1, by1 = box_outline_geo.bounds
thieving_lines_geo = list()
new_x = bx0
new_y = by0
while new_x <= x1 - half_thick_line:
line_geo = LineString([(new_x, by0), (new_x, by1)]).buffer(
# create a polygon-line that surrounds in the inside the bounding box polygon of the target Gerber
box_outline_geo = box(x0, y0, x1, y1).buffer(-half_thick_line)
box_outline_geo_exterior = box_outline_geo.exterior
box_outline_geometry = box_outline_geo_exterior.buffer(
half_thick_line,
resolution=int(int(self.geo_steps_per_circle) / 4)
resolution=int(int(app_obj.geo_steps_per_circle) / 4)
)
thieving_lines_geo.append(line_geo)
new_x += line_size + line_spacing
while new_y <= y1 - half_thick_line:
line_geo = LineString([(bx0, new_y), (bx1, new_y)]).buffer(
half_thick_line,
resolution=int(int(self.geo_steps_per_circle) / 4)
)
thieving_lines_geo.append(line_geo)
new_y += line_size + line_spacing
bx0, by0, bx1, by1 = box_outline_geo.bounds
thieving_lines_geo = list()
new_x = bx0
new_y = by0
while new_x <= x1 - half_thick_line:
line_geo = LineString([(new_x, by0), (new_x, by1)]).buffer(
half_thick_line,
resolution=int(int(app_obj.geo_steps_per_circle) / 4)
)
thieving_lines_geo.append(line_geo)
new_x += line_size + line_spacing
thieving_box_geo = cascaded_union(thieving_lines_geo)
while new_y <= y1 - half_thick_line:
line_geo = LineString([(bx0, new_y), (bx1, new_y)]).buffer(
half_thick_line,
resolution=int(int(app_obj.geo_steps_per_circle) / 4)
)
thieving_lines_geo.append(line_geo)
new_y += line_size + line_spacing
# merge everything together
diff_lines_geo = thieving_box_geo.difference(clearance_geometry)
new_solid_geometry = unary_union([outline_geometry, box_outline_geometry, diff_lines_geo])
# merge everything together
diff_lines_geo = list()
for line_poly in thieving_lines_geo:
rest_line = line_poly.difference(clearance_geometry)
diff_lines_geo.append(rest_line)
app_obj.flatten([outline_geometry, box_outline_geometry, diff_lines_geo])
new_solid_geometry = app_obj.flat_geometry
geo_list = self.grb_object.solid_geometry
if isinstance(self.grb_object.solid_geometry, MultiPolygon):
geo_list = list(self.grb_object.solid_geometry.geoms)
app_obj.app.proc_container.update_view_text(' %s' % _("Append geometry"))
geo_list = app_obj.grb_object.solid_geometry
if isinstance(app_obj.grb_object.solid_geometry, MultiPolygon):
geo_list = list(app_obj.grb_object.solid_geometry.geoms)
if '0' not in self.grb_object.apertures:
self.grb_object.apertures['0'] = dict()
self.grb_object.apertures['0']['geometry'] = list()
self.grb_object.apertures['0']['type'] = 'REG'
self.grb_object.apertures['0']['size'] = 0.0
if '0' not in app_obj.grb_object.apertures:
app_obj.grb_object.apertures['0'] = dict()
app_obj.grb_object.apertures['0']['geometry'] = list()
app_obj.grb_object.apertures['0']['type'] = 'REG'
app_obj.grb_object.apertures['0']['size'] = 0.0
try:
for poly in new_solid_geometry:
try:
for poly in new_solid_geometry:
# append to the new solid geometry
geo_list.append(poly)
# append into the '0' aperture
geo_elem = dict()
geo_elem['solid'] = poly
geo_elem['follow'] = poly.exterior
app_obj.grb_object.apertures['0']['geometry'].append(deepcopy(geo_elem))
except TypeError:
# append to the new solid geometry
geo_list.append(poly)
geo_list.append(new_solid_geometry)
# append into the '0' aperture
geo_elem = dict()
geo_elem['solid'] = poly
geo_elem['follow'] = poly.exterior
self.grb_object.apertures['0']['geometry'].append(deepcopy(geo_elem))
except TypeError:
# append to the new solid geometry
geo_list.append(new_solid_geometry)
geo_elem['solid'] = new_solid_geometry
geo_elem['follow'] = new_solid_geometry.exterior
app_obj.grb_object.apertures['0']['geometry'].append(deepcopy(geo_elem))
# append into the '0' aperture
geo_elem = dict()
geo_elem['solid'] = new_solid_geometry
geo_elem['follow'] = new_solid_geometry.exterior
self.grb_object.apertures['0']['geometry'].append(deepcopy(geo_elem))
app_obj.grb_object.solid_geometry = MultiPolygon(geo_list).buffer(0.0000001).buffer(-0.0000001)
self.grb_object.solid_geometry = MultiPolygon(geo_list).buffer(0.0000001).buffer(-0.0000001)
app_obj.app.proc_container.update_view_text(' %s' % _("Append source file"))
# update the source file with the new geometry:
app_obj.grb_object.source_file = app_obj.app.export_gerber(obj_name=app_obj.grb_object.options['name'],
filename=None,
local_use=app_obj.grb_object,
use_thread=False)
app_obj.app.proc_container.update_view_text(' %s' % '')
app_obj.on_exit()
app_obj.app.inform.emit('[success] %s' % _("Copper Thieving Tool done."))
# update the source file with the new geometry:
self.grb_object.source_file = self.app.export_gerber(obj_name=self.grb_object.options['name'], filename=None,
local_use=self.grb_object, use_thread=False)
self.on_exit()
self.app.inform.emit('[success] %s' % _("Copper Thieving Tool done."))
if run_threaded:
self.app.worker_task.emit({'fcn': job_thread_thieving, 'params': [self]})
else:
job_thread_thieving(self)
def replot(self, obj):
def worker_task():
@ -1077,3 +1106,23 @@ class ToolCopperThieving(FlatCAMTool):
self.app.call_source = "app"
self.app.inform.emit('[success] %s' % _("Copper Thieving Tool exit."))
def flatten(self, geometry):
"""
Creates a list of non-iterable linear geometry objects.
:param geometry: Shapely type or list or list of list of such.
Results are placed in self.flat_geometry
"""
# ## If iterable, expand recursively.
try:
for geo in geometry:
if geo is not None:
self.flatten(geometry=geo)
# ## Not iterable, do the actual indexing and add.
except TypeError:
self.flat_geometry.append(geometry)
return self.flat_geometry

View File

@ -25,7 +25,10 @@
# scipy.sparse.sparsetools._csr.pyd, scipy.sparse.sparsetools._csc.pyd,
# scipy.sparse.sparsetools._coo.pyd
import os, site, sys, platform
import os
import site
import sys
import platform
from cx_Freeze import setup, Executable
# this is done to solve the tkinter not being found
@ -71,7 +74,7 @@ if sys.platform == "win32":
if platform.architecture()[0] == '64bit':
buildOptions = dict(
include_files=include_files,
excludes=['scipy','pytz'],
excludes=['scipy', 'pytz'],
# packages=['OpenGL','numpy','vispy','ortools','google']
# packages=['numpy','google', 'rasterio'] # works for Python 3.7
packages=['opengl', 'numpy', 'google', 'rasterio'], # works for Python 3.6.5 and Python 3.7.1
@ -101,7 +104,6 @@ def getTargetName():
return "FlatCAM.dmg"
# execfile('clean.py')
exe = Executable("FlatCAM.py", icon='share/flatcam_icon48.ico', base=base, targetName=getTargetName())
setup(