From 057ab93ef8a5f2662bbc36b87cc5a5ced14fbfb3 Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Mon, 18 Nov 2019 17:44:52 +0200 Subject: [PATCH] - finished the Dots and Squares options in the Copper Thieving Tool - working on the Lines option in Copper Thieving Tool --- README.md | 5 ++ flatcamTools/ToolCopperThieving.py | 128 ++++++++++++++++++++++++++--- flatcamTools/ToolDblSided.py | 14 +--- 3 files changed, 124 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 0c3ea63a..407096db 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,11 @@ CAD program, and create G-Code for Isolation routing. ================================================= +18.11.2019 + +- finished the Dots and Squares options in the Copper Thieving Tool +- working on the Lines option in Copper Thieving Tool + 17.11.2019 - optimized the storage of the Gerber mark shapes by making them one layer only diff --git a/flatcamTools/ToolCopperThieving.py b/flatcamTools/ToolCopperThieving.py index 351ea096..02a41c2a 100644 --- a/flatcamTools/ToolCopperThieving.py +++ b/flatcamTools/ToolCopperThieving.py @@ -16,6 +16,7 @@ import shapely.geometry.base as base from shapely.ops import cascaded_union, unary_union from shapely.geometry import Polygon, MultiPolygon, Point from shapely.geometry import box as box +import shapely.affinity as affinity import logging from copy import deepcopy @@ -760,9 +761,10 @@ class ToolCopperThieving(FlatCAMTool): env_obj = cascaded_union(geo_n) env_obj = env_obj.convex_hull else: - if isinstance(geo_n, Polygon) or \ - (isinstance(geo_n, list) and len(geo_n) == 1) or \ - (isinstance(geo_n, MultiPolygon) and len(geo_n) == 1): + 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 @@ -797,7 +799,7 @@ class ToolCopperThieving(FlatCAMTool): bounding_box = cascaded_union(geo_buff_list) - elif ref_selected == 'box': + else: # ref_selected == 'box' geo_n = working_obj.solid_geometry if isinstance(working_obj, FlatCAMGeometry): @@ -831,15 +833,119 @@ class ToolCopperThieving(FlatCAMTool): # ########## Generate filling geometry. ################################################### # ######################################################################################### - if fill_type == 'solid': - new_solid_geometry = bounding_box.difference(clearance_geometry) - elif fill_type == 'dots': - dot_geo = Point((0, 0)).buffer(dot_dia / 2.0) + 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: - for bb in bounding_box: - pass + _it = iter(new_solid_geometry) except TypeError: - pass + 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 + + outline_geometry = [] + try: + for pol in self.grb_object.solid_geometry: + if self.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)).exterior + ) + + 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) + outline_geometry.append( + self.grb_object.solid_geometry.buffer( + c_val+half_thick_line, + int(int(self.geo_steps_per_circle) / 4).exterior + ) + ) + + self.app.proc_container.update_view_text(' %s' % _("Buffering")) + t = list() + for l in outline_geometry: + t.append(l.buffer(half_thick_line, resolution=int(int(self.geo_steps_per_circle) / 4))) + outline_geometry = unary_union(t) + + try: + _it = iter(new_solid_geometry) + except TypeError: + new_solid_geometry = [new_solid_geometry] + + # thieving_outlines = list() + # for geo_t in new_solid_geometry: + # for interior in geo_t.interiors: + # thieving_geo = interior.buffer(distance=half_thick_line) + # + # if thieving_geo.is_valid: + # thieving_outlines.append(thieving_geo) + new_solid_geometry = outline_geometry geo_list = self.grb_object.solid_geometry if isinstance(self.grb_object.solid_geometry, MultiPolygon): diff --git a/flatcamTools/ToolDblSided.py b/flatcamTools/ToolDblSided.py index cbb683cd..2ec3a1c8 100644 --- a/flatcamTools/ToolDblSided.py +++ b/flatcamTools/ToolDblSided.py @@ -368,22 +368,12 @@ class DblSidedTool(FlatCAMTool): xscale, yscale = {"X": (1.0, -1.0), "Y": (-1.0, 1.0)}[axis] - try: - dia = float(self.drill_dia.get_value()) - except ValueError: - # try to convert comma to decimal point. if it's still not working error message and return - try: - dia = float(self.drill_dia.get_value().replace(',', '.')) - self.drill_dia.set_value(dia) - except ValueError: - self.app.inform.emit('[WARNING_NOTCL] %s' % _("Tool diameter value is missing or wrong format. " - "Add it and retry.")) - return - + dia = float(self.drill_dia.get_value()) if dia is '': self.app.inform.emit('[WARNING_NOTCL] %s' % _("No value or wrong format in Drill Dia entry. Add it and retry.")) return + tools = {"1": {"C": dia}} # holes = self.alignment_holes.get_value()