Przeglądaj źródła

- started a new way to clear the Gerber polygons based on the 'follow' lines

Marius Stanciu 6 lat temu
rodzic
commit
82ab0d83d6
2 zmienionych plików z 141 dodań i 1 usunięć
  1. 1 0
      README.md
  2. 140 1
      camlib.py

+ 1 - 0
README.md

@@ -14,6 +14,7 @@ CAD program, and create G-Code for Isolation routing.
 - optimized the Paint and NCC Tools. When the Lines type of painting/clearing is used, the lines will try to arrange themselves on the direction that the lines length clearing the polygon are bigger
 - solved bug that made drilling with Marlin preprocessor very slow
 - applied the fix for above bug to the TclCommand Drillcncjob too
+- started a new way to clear the Gerber polygons based on the 'follow' lines
 
 8.02.2020
 

+ 140 - 1
camlib.py

@@ -1446,7 +1446,7 @@ class Geometry(object):
             return None
 
         # decide the direction of the lines
-        if abs(left - right) >= abs(top  -bot):
+        if abs(left - right) >= abs(top - bot):
             # First line
             try:
                 y = top - tooldia / 1.99999999
@@ -1562,6 +1562,145 @@ class Geometry(object):
 
         return geoms
 
+    def fill_with_lines(self, line, aperture_size, tooldia, steps_per_circle, overlap=0.15, connect=True, contour=True,
+                        prog_plot=False):
+        """
+        Creates geometry of lines inside a polygon for a tool to cover
+        the whole area.
+
+        This algorithm draws parallel lines inside the polygon.
+
+        :param line: The target line that create painted polygon.
+        :type line: shapely.geometry.LineString or shapely.geometry.MultiLineString
+        :param tooldia: Tool diameter.
+        :param steps_per_circle: how many linear segments to use to approximate a circle
+        :param overlap: Tool path overlap percentage.
+        :param connect: Connect lines to avoid tool lifts.
+        :param contour: Paint around the edges.
+        :param prog_plot: boolean; if to use the progressive plotting
+        :return:
+        """
+
+        # log.debug("camlib.fill_with_lines()")
+        if not isinstance(line, LineString) or not isinstance(line, MultiLineString):
+            log.debug("camlib.Geometry.fill_with_lines() --> Not a LineString/MultiLineString but %s" % str(type(line)))
+            return None
+
+        # ## The toolpaths
+        # Index first and last points in paths
+        def get_pts(o):
+            return [o.coords[0], o.coords[-1]]
+
+        geoms = FlatCAMRTreeStorage()
+        geoms.get_points = get_pts
+
+        lines_trimmed = []
+
+        polygon = line.buffer(aperture_size / 1.99999999999999999, int(steps_per_circle))
+
+        try:
+            margin_poly = polygon.buffer(-tooldia / 1.99999999, int(steps_per_circle))
+        except Exception:
+            log.debug("camlib.Geometry.fill_with_lines() --> Could not buffer the Polygon, tool diameter too high")
+            return None
+
+        # First line
+        try:
+            delta = 0
+            while delta < aperture_size / 2:
+                if self.app.abort_flag:
+                    # graceful abort requested by the user
+                    raise FlatCAMApp.GracefulException
+
+                # provide the app with a way to process the GUI events when in a blocking loop
+                QtWidgets.QApplication.processEvents()
+
+                line = line.parallel_offset(distance=delta, side='left', resolution=int(steps_per_circle))
+                line = line.intersection(margin_poly)
+                lines_trimmed.append(line)
+
+                line = line.parallel_offset(distance=delta, side='right', resolution=int(steps_per_circle))
+                line = line.intersection(margin_poly)
+                lines_trimmed.append(line)
+
+                delta += tooldia * (1 - overlap)
+                if prog_plot:
+                    self.plot_temp_shapes(line)
+                    self.temp_shapes.redraw()
+
+            # Last line
+            delta = aperture_size / 2
+
+            line = line.parallel_offset(distance=delta, side='left', resolution=int(steps_per_circle))
+            line = line.intersection(margin_poly)
+
+            for ll in line:
+                lines_trimmed.append(ll)
+                if prog_plot:
+                    self.plot_temp_shapes(line)
+
+            line = line.parallel_offset(distance=delta, side='left', resolution=int(steps_per_circle))
+            line = line.intersection(margin_poly)
+
+            for ll in line:
+                lines_trimmed.append(ll)
+                if prog_plot:
+                    self.plot_temp_shapes(line)
+        except Exception as e:
+            log.debug('camlib.Geometry.fill_with_lines() Processing poly --> %s' % str(e))
+            return None
+
+        if prog_plot:
+            self.temp_shapes.redraw()
+
+        lines_trimmed = unary_union(lines_trimmed)
+
+        # Add lines to storage
+        try:
+            for line in lines_trimmed:
+                if isinstance(line, LineString) or isinstance(line, LinearRing):
+                    geoms.insert(line)
+                else:
+                    log.debug("camlib.Geometry.fill_with_lines(). Not a line: %s" % str(type(line)))
+        except TypeError:
+            # in case lines_trimmed are not iterable (Linestring, LinearRing)
+            geoms.insert(lines_trimmed)
+
+        # Add margin (contour) to storage
+        if contour:
+            try:
+                for poly in margin_poly:
+                    if isinstance(poly, Polygon) and not poly.is_empty:
+                        geoms.insert(poly.exterior)
+                        if prog_plot:
+                            self.plot_temp_shapes(poly.exterior)
+                        for ints in poly.interiors:
+                            geoms.insert(ints)
+                            if prog_plot:
+                                self.plot_temp_shapes(ints)
+            except TypeError:
+                if isinstance(margin_poly, Polygon) and not margin_poly.is_empty:
+                    marg_ext = margin_poly.exterior
+                    geoms.insert(marg_ext)
+                    if prog_plot:
+                        self.plot_temp_shapes(margin_poly.exterior)
+                    for ints in margin_poly.interiors:
+                        geoms.insert(ints)
+                        if prog_plot:
+                            self.plot_temp_shapes(ints)
+
+        if prog_plot:
+            self.temp_shapes.redraw()
+
+        # Optimization: Reduce lifts
+        if connect:
+            # log.debug("Reducing tool lifts...")
+            geoms_conn = Geometry.paint_connect(geoms, polygon, tooldia, steps_per_circle)
+            if geoms_conn:
+                return geoms_conn
+
+        return geoms
+
     def scale(self, xfactor, yfactor, point=None):
         """
         Scales all of the object's geometry by a given factor. Override