|
@@ -511,6 +511,8 @@ class NonCopperClear(AppTool, Gerber):
|
|
|
self.ui.ncc_offset_spinner.set_value(self.app.defaults["tools_ncc_offset_value"])
|
|
self.ui.ncc_offset_spinner.set_value(self.app.defaults["tools_ncc_offset_value"])
|
|
|
|
|
|
|
|
self.ui.ncc_rest_cb.set_value(self.app.defaults["tools_ncc_rest"])
|
|
self.ui.ncc_rest_cb.set_value(self.app.defaults["tools_ncc_rest"])
|
|
|
|
|
+ self.ui.on_rest_machining_check(state=self.app.defaults["tools_ncc_rest"])
|
|
|
|
|
+
|
|
|
self.ui.rest_ncc_margin_entry.set_value(self.app.defaults["tools_ncc_margin"])
|
|
self.ui.rest_ncc_margin_entry.set_value(self.app.defaults["tools_ncc_margin"])
|
|
|
self.ui.rest_ncc_connect_cb.set_value(self.app.defaults["tools_ncc_connect"])
|
|
self.ui.rest_ncc_connect_cb.set_value(self.app.defaults["tools_ncc_connect"])
|
|
|
self.ui.rest_ncc_contour_cb.set_value(self.app.defaults["tools_ncc_contour"])
|
|
self.ui.rest_ncc_contour_cb.set_value(self.app.defaults["tools_ncc_contour"])
|
|
@@ -777,11 +779,11 @@ class NonCopperClear(AppTool, Gerber):
|
|
|
pass
|
|
pass
|
|
|
|
|
|
|
|
try:
|
|
try:
|
|
|
- self.ui.ncc_rest_cb.stateChanged.disconnect()
|
|
|
|
|
|
|
+ self.ui.ncc_rest_cb.stateChanged.disconnect(self.ui.on_rest_machining_check)
|
|
|
except (TypeError, ValueError):
|
|
except (TypeError, ValueError):
|
|
|
pass
|
|
pass
|
|
|
try:
|
|
try:
|
|
|
- self.ui.ncc_order_radio.activated_custom[str].disconnect()
|
|
|
|
|
|
|
+ self.ui.ncc_order_radio.activated_custom[str].disconnect(self.on_order_changed)
|
|
|
except (TypeError, ValueError):
|
|
except (TypeError, ValueError):
|
|
|
pass
|
|
pass
|
|
|
|
|
|
|
@@ -2383,6 +2385,13 @@ class NonCopperClear(AppTool, Gerber):
|
|
|
ncc_margin=ncc_margin, tools_storage=tools_storage,
|
|
ncc_margin=ncc_margin, tools_storage=tools_storage,
|
|
|
bounding_box=bbox)
|
|
bounding_box=bbox)
|
|
|
|
|
|
|
|
|
|
+ # for testing purposes ----------------------------------
|
|
|
|
|
+ # for po in area.geoms:
|
|
|
|
|
+ # self.app.tool_shapes.add(po, color=self.app.defaults['global_sel_line'],
|
|
|
|
|
+ # face_color=self.app.defaults['global_sel_line'],
|
|
|
|
|
+ # update=True, layer=0, tolerance=None)
|
|
|
|
|
+ # -------------------------------------------------------
|
|
|
|
|
+
|
|
|
# Generate area for each tool
|
|
# Generate area for each tool
|
|
|
while sorted_clear_tools:
|
|
while sorted_clear_tools:
|
|
|
tool = sorted_clear_tools.pop(0)
|
|
tool = sorted_clear_tools.pop(0)
|
|
@@ -2402,84 +2411,135 @@ class NonCopperClear(AppTool, Gerber):
|
|
|
|
|
|
|
|
tool_uid = 0 # find the current tool_uid
|
|
tool_uid = 0 # find the current tool_uid
|
|
|
for k, v in self.ncc_tools.items():
|
|
for k, v in self.ncc_tools.items():
|
|
|
- if float('%.*f' % (self.decimals, v['tooldia'])) == float('%.*f' % (self.decimals, tool)):
|
|
|
|
|
|
|
+ if self.app.dec_format(v['tooldia'], self.decimals) == self.app.dec_format(tool, self.decimals):
|
|
|
tool_uid = int(k)
|
|
tool_uid = int(k)
|
|
|
break
|
|
break
|
|
|
|
|
|
|
|
|
|
+ tool_data_dict = self.ncc_tools[tool_uid]["data"]
|
|
|
|
|
+
|
|
|
# parameters that are particular to the current tool
|
|
# parameters that are particular to the current tool
|
|
|
- ncc_overlap = float(self.ncc_tools[tool_uid]["data"]["tools_ncc_overlap"]) / 100.0
|
|
|
|
|
- ncc_method = self.ncc_tools[tool_uid]["data"]["tools_ncc_method"]
|
|
|
|
|
|
|
+ ncc_overlap = float(tool_data_dict["tools_ncc_overlap"]) / 100.0
|
|
|
|
|
+ ncc_method = tool_data_dict["tools_ncc_method"]
|
|
|
|
|
|
|
|
# variables to display the percentage of work done
|
|
# variables to display the percentage of work done
|
|
|
geo_len = len(area.geoms)
|
|
geo_len = len(area.geoms)
|
|
|
old_disp_number = 0
|
|
old_disp_number = 0
|
|
|
- log.warning("Total number of polygons to be cleared. %s" % str(geo_len))
|
|
|
|
|
|
|
+ log.warning("Total number of polygons to be cleared: %s" % str(geo_len))
|
|
|
|
|
+
|
|
|
|
|
+ # def random_color():
|
|
|
|
|
+ # r_color = np.random.rand(4)
|
|
|
|
|
+ # r_color[3] = 0.5
|
|
|
|
|
+ # return r_color
|
|
|
|
|
|
|
|
# store here the geometry generated by clear operation
|
|
# store here the geometry generated by clear operation
|
|
|
cleared_geo = []
|
|
cleared_geo = []
|
|
|
|
|
|
|
|
- if area.geoms:
|
|
|
|
|
- if len(area.geoms) > 0:
|
|
|
|
|
- pol_nr = 0
|
|
|
|
|
- for p in area.geoms:
|
|
|
|
|
- if self.app.abort_flag:
|
|
|
|
|
- # graceful abort requested by the user
|
|
|
|
|
- raise grace
|
|
|
|
|
-
|
|
|
|
|
- if p is not None and p.is_valid:
|
|
|
|
|
- # provide the app with a way to process the GUI events when in a blocking loop
|
|
|
|
|
- QtWidgets.QApplication.processEvents()
|
|
|
|
|
-
|
|
|
|
|
- poly_failed = 0
|
|
|
|
|
|
|
+ poly_failed = 0
|
|
|
|
|
+ if area.geoms and len(area.geoms) > 0:
|
|
|
|
|
+ pol_nr = 0
|
|
|
|
|
+ for p in area.geoms:
|
|
|
|
|
+ if self.app.abort_flag:
|
|
|
|
|
+ # graceful abort requested by the user
|
|
|
|
|
+ raise grace
|
|
|
|
|
|
|
|
- # speedup the clearing by not trying to clear polygons that is clear they can't be
|
|
|
|
|
- # cleared with the current tool. this tremendously reduce the clearing time
|
|
|
|
|
- check_dist = -tool / 2.0
|
|
|
|
|
- check_buff = p.buffer(check_dist)
|
|
|
|
|
- if not check_buff or check_buff.is_empty:
|
|
|
|
|
- continue
|
|
|
|
|
|
|
+ if p is not None and p.is_valid and not p.is_empty:
|
|
|
|
|
+ # provide the app with a way to process the GUI events when in a blocking loop
|
|
|
|
|
+ QtWidgets.QApplication.processEvents()
|
|
|
|
|
|
|
|
- # actual copper claring is done here
|
|
|
|
|
- if isinstance(p, Polygon):
|
|
|
|
|
- res = self.clear_polygon_worker(pol=p, tooldia=tool,
|
|
|
|
|
- ncc_method=ncc_method,
|
|
|
|
|
- ncc_overlap=ncc_overlap,
|
|
|
|
|
- ncc_connect=ncc_connect,
|
|
|
|
|
- ncc_contour=ncc_contour,
|
|
|
|
|
- prog_plot=prog_plot)
|
|
|
|
|
- if res is not None:
|
|
|
|
|
- cleared_geo += res
|
|
|
|
|
- else:
|
|
|
|
|
- poly_failed += 1
|
|
|
|
|
|
|
+ # speedup the clearing by not trying to clear polygons that is clear they can't be
|
|
|
|
|
+ # cleared with the current tool. this tremendously reduce the clearing time
|
|
|
|
|
+ check_dist = -tool / 2
|
|
|
|
|
+ check_buff = p.buffer(check_dist, self.circle_steps)
|
|
|
|
|
+ if not check_buff or check_buff.is_empty:
|
|
|
|
|
+ continue
|
|
|
|
|
+
|
|
|
|
|
+ # if self.app.dec_format(float(tool), self.decimals) == 0.15:
|
|
|
|
|
+ # # for testing purposes ----------------------------------
|
|
|
|
|
+ # self.app.tool_shapes.add(p, color=self.app.defaults['global_sel_line'],
|
|
|
|
|
+ # face_color=random_color(),
|
|
|
|
|
+ # update=True, layer=0, tolerance=None)
|
|
|
|
|
+ # self.app.tool_shapes.add(check_buff, color=self.app.defaults['global_sel_line'],
|
|
|
|
|
+ # face_color='#FFFFFFFF',
|
|
|
|
|
+ # update=True, layer=0, tolerance=None)
|
|
|
|
|
+ # # -------------------------------------------------------
|
|
|
|
|
+
|
|
|
|
|
+ # actual copper clearing is done here
|
|
|
|
|
+ if isinstance(p, Polygon):
|
|
|
|
|
+ res = self.clear_polygon_worker(pol=p, tooldia=tool,
|
|
|
|
|
+ ncc_method=ncc_method,
|
|
|
|
|
+ ncc_overlap=ncc_overlap,
|
|
|
|
|
+ ncc_connect=ncc_connect,
|
|
|
|
|
+ ncc_contour=ncc_contour,
|
|
|
|
|
+ prog_plot=prog_plot)
|
|
|
|
|
+
|
|
|
|
|
+ if res is not None:
|
|
|
|
|
+ cleared_geo += res
|
|
|
else:
|
|
else:
|
|
|
- log.warning("Expected geo is a Polygon. Instead got a %s" % str(type(p)))
|
|
|
|
|
|
|
+ poly_failed += 1
|
|
|
|
|
+ else:
|
|
|
|
|
+ log.warning("Expected geo is a Polygon. Instead got a %s" % str(type(p)))
|
|
|
|
|
|
|
|
- if poly_failed > 0:
|
|
|
|
|
- app_obj.poly_not_cleared = True
|
|
|
|
|
|
|
+ if poly_failed > 0:
|
|
|
|
|
+ app_obj.poly_not_cleared = True
|
|
|
|
|
|
|
|
- pol_nr += 1
|
|
|
|
|
- disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 100]))
|
|
|
|
|
- # log.debug("Polygons cleared: %d" % pol_nr)
|
|
|
|
|
|
|
+ pol_nr += 1
|
|
|
|
|
+ disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 100]))
|
|
|
|
|
+ # log.debug("Polygons cleared: %d" % pol_nr)
|
|
|
|
|
|
|
|
- if old_disp_number < disp_number <= 100:
|
|
|
|
|
- self.app.proc_container.update_view_text(' %d%%' % disp_number)
|
|
|
|
|
- old_disp_number = disp_number
|
|
|
|
|
- # log.debug("Polygons cleared: %d. Percentage done: %d%%" % (pol_nr, disp_number))
|
|
|
|
|
|
|
+ if old_disp_number < disp_number <= 100:
|
|
|
|
|
+ self.app.proc_container.update_view_text(' %d%%' % disp_number)
|
|
|
|
|
+ old_disp_number = disp_number
|
|
|
|
|
+ # log.debug("Polygons cleared: %d. Percentage done: %d%%" % (pol_nr, disp_number))
|
|
|
|
|
|
|
|
- if self.app.abort_flag:
|
|
|
|
|
- raise grace # graceful abort requested by the user
|
|
|
|
|
|
|
+ if self.app.abort_flag:
|
|
|
|
|
+ raise grace # graceful abort requested by the user
|
|
|
|
|
|
|
|
- # check if there is a geometry at all in the cleared geometry
|
|
|
|
|
- if cleared_geo:
|
|
|
|
|
- tools_storage[tool_uid]["solid_geometry"] = deepcopy(cleared_geo)
|
|
|
|
|
- tools_storage[tool_uid]["data"]["name"] = name + '_' + str(tool)
|
|
|
|
|
- geo_obj.tools[current_uid] = dict(tools_storage[current_uid])
|
|
|
|
|
- else:
|
|
|
|
|
- log.debug("There are no geometries in the cleared polygon.")
|
|
|
|
|
|
|
+ # check if there is a geometry at all in the cleared geometry
|
|
|
|
|
+ if cleared_geo:
|
|
|
|
|
+ tools_storage[tool_uid]["solid_geometry"] = deepcopy(cleared_geo)
|
|
|
|
|
+ tools_storage[tool_uid]["data"]["name"] = name + '_' + str(tool)
|
|
|
|
|
+ geo_obj.tools[tool_uid] = dict(tools_storage[tool_uid])
|
|
|
|
|
+ else:
|
|
|
|
|
+ log.debug("There are no geometries in the cleared polygon.")
|
|
|
|
|
|
|
|
- # Area to clear next
|
|
|
|
|
- buffered_cleared = unary_union(cleared_geo).buffer(tool / 2.0)
|
|
|
|
|
- area = area.difference(buffered_cleared)
|
|
|
|
|
|
|
+ log.warning("Total number of polygons failed to be cleared: %s" % str(poly_failed))
|
|
|
|
|
+ else:
|
|
|
|
|
+ log.warning("The area to be cleared has no polygons.")
|
|
|
|
|
+
|
|
|
|
|
+ # # Area to clear next
|
|
|
|
|
+ # try:
|
|
|
|
|
+ # # buffered_cleared = unary_union(cleared_geo).buffer(tool / 2.0)
|
|
|
|
|
+ # # area = area.difference(buffered_cleared)
|
|
|
|
|
+ # area = area.difference(unary_union(cleared_geo))
|
|
|
|
|
+ # except Exception as e:
|
|
|
|
|
+ # log.debug("Creating new area failed due of: %s" % str(e))
|
|
|
|
|
+
|
|
|
|
|
+ new_area = MultiPolygon([line.buffer(tool / 1.9999999) for line in cleared_geo])
|
|
|
|
|
+ new_area = new_area.buffer(0.0000001)
|
|
|
|
|
+
|
|
|
|
|
+ area = area.difference(new_area)
|
|
|
|
|
+
|
|
|
|
|
+ new_area = [pol for pol in area if pol.is_valid and not pol.is_empty]
|
|
|
|
|
+ area = MultiPolygon(new_area)
|
|
|
|
|
+
|
|
|
|
|
+ # speedup the clearing by not trying to clear polygons that is clear they can't be
|
|
|
|
|
+ # cleared with any tool. this tremendously reduce the clearing time
|
|
|
|
|
+ # found_poly_to_clear = False
|
|
|
|
|
+ # for t in sorted_clear_tools:
|
|
|
|
|
+ # check_dist = -t / 2.000000001
|
|
|
|
|
+ # for pl in area:
|
|
|
|
|
+ # check_buff = pl.buffer(check_dist)
|
|
|
|
|
+ # if not check_buff or check_buff.is_empty or not check_buff.is_valid:
|
|
|
|
|
+ # continue
|
|
|
|
|
+ # else:
|
|
|
|
|
+ # found_poly_to_clear = True
|
|
|
|
|
+ # break
|
|
|
|
|
+ # if found_poly_to_clear is True:
|
|
|
|
|
+ # break
|
|
|
|
|
+ #
|
|
|
|
|
+ # if found_poly_to_clear is False:
|
|
|
|
|
+ # log.warning("The area to be cleared no longer has polygons. Finishing.")
|
|
|
|
|
+ # break
|
|
|
|
|
|
|
|
if not area or area.is_empty:
|
|
if not area or area.is_empty:
|
|
|
break
|
|
break
|