Parcourir la source

- added progress for the generation of Isolation geometry

Marius Stanciu il y a 6 ans
Parent
commit
5838bd0554
3 fichiers modifiés avec 58 ajouts et 38 suppressions
  1. 12 6
      FlatCAMObj.py
  2. 1 0
      README.md
  3. 45 32
      camlib.py

+ 12 - 6
FlatCAMObj.py

@@ -952,7 +952,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
         base_name = self.options["name"] + "_iso"
         base_name = outname or base_name
 
-        def generate_envelope(offset, invert, envelope_iso_type=2, follow=None):
+        def generate_envelope(offset, invert, envelope_iso_type=2, follow=None, passes=0):
             # isolation_geometry produces an envelope that is going on the left of the geometry
             # (the copper features). To leave the least amount of burrs on the features
             # the tool needs to travel on the right side of the features (this is called conventional milling)
@@ -960,7 +960,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
             # the other passes overlap preceding ones and cut the left over copper. It is better for them
             # to cut on the right side of the left over copper i.e on the left side of the features.
             try:
-                geom = self.isolation_geometry(offset, iso_type=envelope_iso_type, follow=follow)
+                geom = self.isolation_geometry(offset, iso_type=envelope_iso_type, follow=follow, passes=passes)
             except Exception as e:
                 log.debug('FlatCAMGerber.isolate().generate_envelope() --> %s' % str(e))
                 return 'fail'
@@ -1076,9 +1076,11 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
                     # if milling type is climb then the move is counter-clockwise around features
                     if milling_type == 'cl':
                         # geom = generate_envelope (offset, i == 0)
-                        geom = generate_envelope(iso_offset, 1, envelope_iso_type=self.iso_type, follow=follow)
+                        geom = generate_envelope(iso_offset, 1, envelope_iso_type=self.iso_type, follow=follow,
+                                                 passes=i)
                     else:
-                        geom = generate_envelope(iso_offset, 0, envelope_iso_type=self.iso_type, follow=follow)
+                        geom = generate_envelope(iso_offset, 0, envelope_iso_type=self.iso_type, follow=follow,
+                                                 passes=i)
                     if geom == 'fail':
                         app_obj.inform.emit('[ERROR_NOTCL] %s' %
                                             _("Isolation geometry could not be generated."))
@@ -1152,6 +1154,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
                 # ########## AREA SUBTRACTION ################################
                 # ############################################################
                 if self.ui.except_cb.get_value():
+                    self.app.proc_container.update_view_text(' %s' % _("Subtracting Geo"))
                     geo_obj.solid_geometry = area_subtraction(geo_obj.solid_geometry)
 
             # TODO: Do something if this is None. Offer changing name?
@@ -1183,9 +1186,11 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
                     # if milling type is climb then the move is counter-clockwise around features
                     if milling_type == 'cl':
                         # geo_obj.solid_geometry = generate_envelope(offset, i == 0)
-                        geom = generate_envelope(offset, 1, envelope_iso_type=self.iso_type, follow=follow)
+                        geom = generate_envelope(offset, 1, envelope_iso_type=self.iso_type, follow=follow,
+                                                 passes=i)
                     else:
-                        geom = generate_envelope(offset, 0, envelope_iso_type=self.iso_type, follow=follow)
+                        geom = generate_envelope(offset, 0, envelope_iso_type=self.iso_type, follow=follow,
+                                                 passes=i)
                     if geom == 'fail':
                         app_obj.inform.emit('[ERROR_NOTCL] %s' %
                                             _("Isolation geometry could not be generated."))
@@ -1218,6 +1223,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
                     # ########## AREA SUBTRACTION ################################
                     # ############################################################
                     if self.ui.except_cb.get_value():
+                        self.app.proc_container.update_view_text(' %s' % _("Subtracting Geo"))
                         geo_obj.solid_geometry = area_subtraction(geo_obj.solid_geometry)
 
                 # TODO: Do something if this is None. Offer changing name?

+ 1 - 0
README.md

@@ -15,6 +15,7 @@ CAD program, and create G-Code for Isolation routing.
 - fixed a small typo in TclCommandCopperCLear
 - made changing the Plot kind in CNCJob selected tab, threaded
 - fixed an object used before declaring it in NCC Tool - Area option
+- added progress for the generation of Isolation geometry
 
 9.09.2019
 

+ 45 - 32
camlib.py

@@ -523,7 +523,7 @@ class Geometry(object):
     #
     #     return self.flat_geometry, self.flat_geometry_rtree
 
-    def isolation_geometry(self, offset, iso_type=2, corner=None, follow=None):
+    def isolation_geometry(self, offset, iso_type=2, corner=None, follow=None, passes=0):
         """
         Creates contours around geometry at a given
         offset distance.
@@ -533,36 +533,11 @@ class Geometry(object):
         :param iso_type: type of isolation, can be 0 = exteriors or 1 = interiors or 2 = both (complete)
         :param corner: type of corner for the isolation: 0 = round; 1 = square; 2= beveled (line that connects the ends)
         :param follow: whether the geometry to be isolated is a follow_geometry
+        :param passes: current pass out of possible multiple passes for which the isolation is done
         :return: The buffered geometry.
         :rtype: Shapely.MultiPolygon or Shapely.Polygon
         """
 
-        # geo_iso = []
-        # In case that the offset value is zero we don't use the buffer as the resulting geometry is actually the
-        # original solid_geometry
-        # if offset == 0:
-        #     geo_iso = self.solid_geometry
-        # else:
-        #     flattened_geo = self.flatten_list(self.solid_geometry)
-        #     try:
-        #         for mp_geo in flattened_geo:
-        #             geo_iso.append(mp_geo.buffer(offset, int(int(self.geo_steps_per_circle) / 4)))
-        #     except TypeError:
-        #         geo_iso.append(self.solid_geometry.buffer(offset, int(int(self.geo_steps_per_circle) / 4)))
-        # return geo_iso
-
-        # commented this because of the bug with multiple passes cutting out of the copper
-        # geo_iso = []
-        # flattened_geo = self.flatten_list(self.solid_geometry)
-        # try:
-        #     for mp_geo in flattened_geo:
-        #         geo_iso.append(mp_geo.buffer(offset, int(int(self.geo_steps_per_circle) / 4)))
-        # except TypeError:
-        #     geo_iso.append(self.solid_geometry.buffer(offset, int(int(self.geo_steps_per_circle) / 4)))
-
-        # the previously commented block is replaced with this block - regression - to solve the bug with multiple
-        # isolation passes cutting from the copper features
-
         if self.app.abort_flag:
             # graceful abort requested by the user
             raise FlatCAMApp.GracefulException
@@ -584,11 +559,47 @@ class Geometry(object):
 
                 # Remember: do not make a buffer for each element in the solid_geometry because it will cut into
                 # other copper features
-                if corner is None:
-                    geo_iso = temp_geo.buffer(offset, int(int(self.geo_steps_per_circle) / 4))
-                else:
-                    geo_iso = temp_geo.buffer(offset, int(int(self.geo_steps_per_circle) / 4),
-                                              join_style=corner)
+                # if corner is None:
+                #     geo_iso = temp_geo.buffer(offset, int(int(self.geo_steps_per_circle) / 4))
+                # else:
+                #     geo_iso = temp_geo.buffer(offset, int(int(self.geo_steps_per_circle) / 4),
+                #                               join_style=corner)
+
+                # variables to display the percentage of work done
+                geo_len = 0
+                try:
+                    for pol in self.solid_geometry:
+                        geo_len += 1
+                except TypeError:
+                    geo_len = 1
+                disp_number = 0
+                old_disp_number = 0
+                pol_nr = 0
+                # yet, it can be done by issuing an unary_union in the end, thus getting rid of the overlapping geo
+                try:
+                    for pol in self.solid_geometry:
+                        if corner is None:
+                            geo_iso.append(pol.buffer(offset, int(int(self.geo_steps_per_circle) / 4)))
+                        else:
+                            geo_iso.append(pol.buffer(offset, int(int(self.geo_steps_per_circle) / 4)),
+                                           join_style=corner)
+                        pol_nr += 1
+                        disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 99]))
+
+                        if disp_number > old_disp_number and disp_number <= 100:
+                            self.app.proc_container.update_view_text(' %s %d: %d%%' %
+                                                                     (_("Pass"), int(passes + 1), 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)
+                    if corner is None:
+                        geo_iso.append(self.solid_geometry.buffer(offset, int(int(self.geo_steps_per_circle) / 4)))
+                    else:
+                        geo_iso.append(self.solid_geometry.buffer(offset, int(int(self.geo_steps_per_circle) / 4)),
+                                       join_style=corner)
+                self.app.proc_container.update_view_text(' %s' % _("Buffering"))
+                geo_iso = unary_union(geo_iso)
 
         # end of replaced block
         if follow:
@@ -596,8 +607,10 @@ class Geometry(object):
         elif iso_type == 2:
             return geo_iso
         elif iso_type == 0:
+            self.app.proc_container.update_view_text(' %s' % _("Get Exteriors"))
             return self.get_exteriors(geo_iso)
         elif iso_type == 1:
+            self.app.proc_container.update_view_text(' %s' % _("Get Interiors"))
             return self.get_interiors(geo_iso)
         else:
             log.debug("Geometry.isolation_geometry() --> Type of isolation not supported")