From 4cbb5846e314bd7d4e3e7fe06a7b75dfb5220c0c Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Sat, 7 Sep 2019 17:08:25 +0300 Subject: [PATCH] - all transformation functions show now the progress (rotate, mirror, scale, offset, skew) - made threaded the Offset and Scale operations found in the Selected tab of the object --- FlatCAMObj.py | 83 ++++++++-- README.md | 2 + camlib.py | 342 ++++++++++++++++++++++++++++++++++++++- flatcamTools/ToolMove.py | 2 +- 4 files changed, 412 insertions(+), 17 deletions(-) diff --git a/FlatCAMObj.py b/FlatCAMObj.py index d926ea92..bf2408ae 100644 --- a/FlatCAMObj.py +++ b/FlatCAMObj.py @@ -212,26 +212,47 @@ class FlatCAMObj(QtCore.QObject): self.read_form() vector_val = self.ui.offsetvector_entry.get_value() - self.offset(vector_val) - self.plot() - self.app.object_changed.emit(self) + + def worker_task(): + with self.app.proc_container.new(_("Offsetting...")): + self.offset(vector_val) + self.app.proc_container.update_view_text('') + with self.app.proc_container.new(_("Plotting...")): + self.plot() + self.app.object_changed.emit(self) + + self.app.worker_task.emit({'fcn': worker_task, 'params': []}) def on_scale_button_click(self): self.app.report_usage("obj_on_scale_button") self.read_form() factor = self.ui.scale_entry.get_value() - self.scale(factor) - self.plot() - self.app.object_changed.emit(self) + + def worker_task(): + with self.app.proc_container.new(_("Scaling...")): + self.scale(factor) + self.app.proc_container.update_view_text('') + with self.app.proc_container.new(_("Plotting...")): + self.plot() + self.app.object_changed.emit(self) + + self.app.worker_task.emit({'fcn': worker_task, 'params': []}) def on_skew_button_click(self): self.app.report_usage("obj_on_skew_button") self.read_form() x_angle = self.ui.xangle_entry.get_value() y_angle = self.ui.yangle_entry.get_value() - self.skew(x_angle, y_angle) - self.plot() - self.app.object_changed.emit(self) + + def worker_task(): + with self.app.proc_container.new(_("Skewing...")): + self.skew(x_angle, y_angle) + self.app.proc_container.update_view_text('') + with self.app.proc_container.new(_("Plotting...")): + self.plot() + self.app.object_changed.emit(self) + + self.app.worker_task.emit({'fcn': worker_task, 'params': []}) def to_form(self): """ @@ -5123,6 +5144,10 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): # origin=(px, py)) # self.app.inform.emit("[success] Geometry Scale done.") + self.geo_len = 0 + self.old_disp_number = 0 + self.el_count = 0 + def scale_recursion(geom): if type(geom) is list: geoms = list() @@ -5131,15 +5156,41 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): return geoms else: try: + self.el_count += 1 + disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 99])) + if self.old_disp_number < disp_number <= 100: + self.app.proc_container.update_view_text(' %d%%' % disp_number) + self.old_disp_number = disp_number + return affinity.scale(geom, xfactor, yfactor, origin=(px, py)) except AttributeError: return geom if self.multigeo is True: for tool in self.tools: + # variables to display the percentage of work done + self.geo_len = 0 + try: + for g in self.tools[tool]['solid_geometry']: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 + self.old_disp_number = 0 + self.el_count = 0 + self.tools[tool]['solid_geometry'] = scale_recursion(self.tools[tool]['solid_geometry']) else: try: + # variables to display the percentage of work done + self.geo_len = 0 + try: + for g in self.solid_geometry: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 + self.old_disp_number = 0 + self.el_count = 0 + self.solid_geometry = scale_recursion(self.solid_geometry) except AttributeError: self.solid_geometry = [] @@ -5193,14 +5244,24 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): if self.multigeo is True: for tool in self.tools: # variables to display the percentage of work done - self.geo_len = len(self.tools[tool]['solid_geometry']) + self.geo_len = 0 + try: + for g in self.tools[tool]['solid_geometry']: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 self.old_disp_number = 0 self.el_count = 0 self.tools[tool]['solid_geometry'] = translate_recursion(self.tools[tool]['solid_geometry']) else: # variables to display the percentage of work done - self.geo_len = len(self.solid_geometry) + self.geo_len = 0 + try: + for g in self.solid_geometry: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 self.old_disp_number = 0 self.el_count = 0 diff --git a/README.md b/README.md index 14ef7d38..481169d5 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,8 @@ CAD program, and create G-Code for Isolation routing. - remade the handlers for the Enable/Disable Project Tree context menu so they are threaded and activity is shown in the lower right corner of the main window - added to GUI new options for the Gerber object related to area subtraction - added new feature in the Gerber object isolation allowing for the isolation to avoid an area defined by another object (Gerber or Geometry) +- all transformation functions show now the progress (rotate, mirror, scale, offset, skew) +- made threaded the Offset and Scale operations found in the Selected tab of the object 6.09.2019 diff --git a/camlib.py b/camlib.py index f247972a..1c0d664e 100644 --- a/camlib.py +++ b/camlib.py @@ -1413,6 +1413,12 @@ class Geometry(object): return new_obj else: try: + self.el_count += 1 + disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 99])) + if self.old_disp_number < disp_number <= 100: + self.app.proc_container.update_view_text(' %d%%' % disp_number) + self.old_disp_number = disp_number + return affinity.scale(obj, xscale, yscale, origin=(px, py)) except AttributeError: return obj @@ -1420,8 +1426,28 @@ class Geometry(object): try: if self.multigeo is True: for tool in self.tools: + # variables to display the percentage of work done + self.geo_len = 0 + try: + for g in self.tools[tool]['solid_geometry']: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 + self.old_disp_number = 0 + self.el_count = 0 + self.tools[tool]['solid_geometry'] = mirror_geom(self.tools[tool]['solid_geometry']) else: + # variables to display the percentage of work done + self.geo_len = 0 + try: + for g in self.solid_geometry: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 + self.old_disp_number = 0 + self.el_count = 0 + self.solid_geometry = mirror_geom(self.solid_geometry) self.app.inform.emit(_('[success] Object was mirrored ...')) except AttributeError: @@ -1455,6 +1481,12 @@ class Geometry(object): return new_obj else: try: + self.el_count += 1 + disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 99])) + if self.old_disp_number < disp_number <= 100: + self.app.proc_container.update_view_text(' %d%%' % disp_number) + self.old_disp_number = disp_number + return affinity.rotate(obj, angle, origin=(px, py)) except AttributeError: return obj @@ -1462,8 +1494,28 @@ class Geometry(object): try: if self.multigeo is True: for tool in self.tools: + # variables to display the percentage of work done + self.geo_len = 0 + try: + for g in self.tools[tool]['solid_geometry']: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 + self.old_disp_number = 0 + self.el_count = 0 + self.tools[tool]['solid_geometry'] = rotate_geom(self.tools[tool]['solid_geometry']) else: + # variables to display the percentage of work done + self.geo_len = 0 + try: + for g in self.solid_geometry: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 + self.old_disp_number = 0 + self.el_count = 0 + self.solid_geometry = rotate_geom(self.solid_geometry) self.app.inform.emit(_('[success] Object was rotated ...')) except AttributeError: @@ -1496,6 +1548,12 @@ class Geometry(object): return new_obj else: try: + self.el_count += 1 + disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 99])) + if self.old_disp_number < disp_number <= 100: + self.app.proc_container.update_view_text(' %d%%' % disp_number) + self.old_disp_number = disp_number + return affinity.skew(obj, angle_x, angle_y, origin=(px, py)) except AttributeError: return obj @@ -1503,8 +1561,28 @@ class Geometry(object): try: if self.multigeo is True: for tool in self.tools: + # variables to display the percentage of work done + self.geo_len = 0 + try: + for g in self.tools[tool]['solid_geometry']: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 + self.old_disp_number = 0 + self.el_count = 0 + self.tools[tool]['solid_geometry'] = skew_geom(self.tools[tool]['solid_geometry']) else: + # variables to display the percentage of work done + self.geo_len = 0 + try: + for g in self.solid_geometry: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 + self.old_disp_number = 0 + self.el_count = 0 + self.solid_geometry = skew_geom(self.solid_geometry) self.app.inform.emit(_('[success] Object was skewed ...')) except AttributeError: @@ -3409,6 +3487,17 @@ class Gerber (Geometry): else: px, py = point + # variables to display the percentage of work done + self.geo_len = 0 + try: + for g in self.solid_geometry: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 + + self.old_disp_number = 0 + self.el_count = 0 + def scale_geom(obj): if type(obj) is list: new_obj = [] @@ -3417,6 +3506,12 @@ class Gerber (Geometry): return new_obj else: try: + self.el_count += 1 + disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 99])) + if self.old_disp_number < disp_number <= 100: + self.app.proc_container.update_view_text(' %d%%' % disp_number) + self.old_disp_number = disp_number + return affinity.scale(obj, xfactor, yfactor, origin=(px, py)) except AttributeError: return obj @@ -3479,7 +3574,13 @@ class Gerber (Geometry): return # variables to display the percentage of work done - self.geo_len = len(self.solid_geometry) + self.geo_len = 0 + try: + for g in self.solid_geometry: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 + self.old_disp_number = 0 self.el_count = 0 @@ -3549,6 +3650,17 @@ class Gerber (Geometry): px, py = point xscale, yscale = {"X": (1.0, -1.0), "Y": (-1.0, 1.0)}[axis] + # variables to display the percentage of work done + self.geo_len = 0 + try: + for g in self.solid_geometry: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 + + self.old_disp_number = 0 + self.el_count = 0 + def mirror_geom(obj): if type(obj) is list: new_obj = [] @@ -3557,6 +3669,12 @@ class Gerber (Geometry): return new_obj else: try: + self.el_count += 1 + disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 99])) + if self.old_disp_number < disp_number <= 100: + self.app.proc_container.update_view_text(' %d%%' % disp_number) + self.old_disp_number = disp_number + return affinity.scale(obj, xscale, yscale, origin=(px, py)) except AttributeError: return obj @@ -3599,6 +3717,17 @@ class Gerber (Geometry): px, py = point + # variables to display the percentage of work done + self.geo_len = 0 + try: + for g in self.solid_geometry: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 + + self.old_disp_number = 0 + self.el_count = 0 + def skew_geom(obj): if type(obj) is list: new_obj = [] @@ -3607,6 +3736,12 @@ class Gerber (Geometry): return new_obj else: try: + self.el_count += 1 + disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 99])) + if self.old_disp_number < disp_number <= 100: + self.app.proc_container.update_view_text(' %d%%' % disp_number) + self.old_disp_number = disp_number + return affinity.skew(obj, angle_x, angle_y, origin=(px, py)) except AttributeError: return obj @@ -3642,6 +3777,17 @@ class Gerber (Geometry): px, py = point + # variables to display the percentage of work done + self.geo_len = 0 + try: + for g in self.solid_geometry: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 + + self.old_disp_number = 0 + self.el_count = 0 + def rotate_geom(obj): if type(obj) is list: new_obj = [] @@ -3650,6 +3796,12 @@ class Gerber (Geometry): return new_obj else: try: + self.el_count += 1 + disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 99])) + if self.old_disp_number < disp_number <= 100: + self.app.proc_container.update_view_text(' %d%%' % disp_number) + self.old_disp_number = disp_number + return affinity.rotate(obj, angle, origin=(px, py)) except AttributeError: return obj @@ -4766,10 +4918,26 @@ class Excellon(Geometry): except AttributeError: return obj + # variables to display the percentage of work done + self.geo_len = 0 + try: + for g in self.drills: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 + self.old_disp_number = 0 + self.el_count = 0 + # Drills for drill in self.drills: drill['point'] = affinity.scale(drill['point'], xfactor, yfactor, origin=(px, py)) + self.el_count += 1 + disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 99])) + if self.old_disp_number < disp_number <= 100: + self.app.proc_container.update_view_text(' %d%%' % disp_number) + self.old_disp_number = disp_number + # scale solid_geometry for tool in self.tools: self.tools[tool]['solid_geometry'] = scale_geom(self.tools[tool]['solid_geometry']) @@ -4806,7 +4974,12 @@ class Excellon(Geometry): return obj # variables to display the percentage of work done - self.geo_len = len(self.drills) + self.geo_len = 0 + try: + for g in self.drills: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 self.old_disp_number = 0 self.el_count = 0 @@ -4859,10 +5032,27 @@ class Excellon(Geometry): return obj # Modify data + + # variables to display the percentage of work done + self.geo_len = 0 + try: + for g in self.drills: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 + self.old_disp_number = 0 + self.el_count = 0 + # Drills for drill in self.drills: drill['point'] = affinity.scale(drill['point'], xscale, yscale, origin=(px, py)) + self.el_count += 1 + disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 99])) + if self.old_disp_number < disp_number <= 100: + self.app.proc_container.update_view_text(' %d%%' % disp_number) + self.old_disp_number = disp_number + # mirror solid_geometry for tool in self.tools: self.tools[tool]['solid_geometry'] = mirror_geom(self.tools[tool]['solid_geometry']) @@ -4910,6 +5100,16 @@ class Excellon(Geometry): except AttributeError: return obj + # variables to display the percentage of work done + self.geo_len = 0 + try: + for g in self.drills: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 + self.old_disp_number = 0 + self.el_count = 0 + if point is None: px, py = 0, 0 @@ -4917,6 +5117,13 @@ class Excellon(Geometry): for drill in self.drills: drill['point'] = affinity.skew(drill['point'], angle_x, angle_y, origin=(px, py)) + + self.el_count += 1 + disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 99])) + if self.old_disp_number < disp_number <= 100: + self.app.proc_container.update_view_text(' %d%%' % disp_number) + self.old_disp_number = disp_number + # skew solid_geometry for tool in self.tools: self.tools[tool]['solid_geometry'] = skew_geom(self.tools[tool]['solid_geometry']) @@ -4932,6 +5139,12 @@ class Excellon(Geometry): drill['point'] = affinity.skew(drill['point'], angle_x, angle_y, origin=(px, py)) + self.el_count += 1 + disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 99])) + if self.old_disp_number < disp_number <= 100: + self.app.proc_container.update_view_text(' %d%%' % disp_number) + self.old_disp_number = disp_number + # skew solid_geometry for tool in self.tools: self.tools[tool]['solid_geometry'] = skew_geom( self.tools[tool]['solid_geometry']) @@ -4970,6 +5183,16 @@ class Excellon(Geometry): except AttributeError: return obj + # variables to display the percentage of work done + self.geo_len = 0 + try: + for g in self.drills: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 + self.old_disp_number = 0 + self.el_count = 0 + if point is None: # Drills for drill in self.drills: @@ -4979,6 +5202,12 @@ class Excellon(Geometry): for tool in self.tools: self.tools[tool]['solid_geometry'] = rotate_geom(self.tools[tool]['solid_geometry'], origin='center') + self.el_count += 1 + disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 99])) + if self.old_disp_number < disp_number <= 100: + self.app.proc_container.update_view_text(' %d%%' % disp_number) + self.old_disp_number = disp_number + # Slots for slot in self.slots: slot['stop'] = affinity.rotate(slot['stop'], angle, origin='center') @@ -4989,6 +5218,12 @@ class Excellon(Geometry): for drill in self.drills: drill['point'] = affinity.rotate(drill['point'], angle, origin=(px, py)) + self.el_count += 1 + disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 99])) + if self.old_disp_number < disp_number <= 100: + self.app.proc_container.update_view_text(' %d%%' % disp_number) + self.old_disp_number = disp_number + # rotate solid_geometry for tool in self.tools: self.tools[tool]['solid_geometry'] = rotate_geom(self.tools[tool]['solid_geometry']) @@ -7621,23 +7856,59 @@ class CNCjob(Geometry): if self.multitool is False: # offset Gcode self.gcode = scale_g(self.gcode) - # offset geometry + + # variables to display the percentage of work done + self.geo_len = 0 + try: + for g in self.gcode_parsed: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 + self.old_disp_number = 0 + self.el_count = 0 + + # scale geometry for g in self.gcode_parsed: try: g['geom'] = affinity.scale(g['geom'], xfactor, yfactor, origin=(px, py)) except AttributeError: return g['geom'] + + self.el_count += 1 + disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 99])) + if self.old_disp_number < disp_number <= 100: + self.app.proc_container.update_view_text(' %d%%' % disp_number) + self.old_disp_number = disp_number + self.create_geometry() else: for k, v in self.cnc_tools.items(): # scale Gcode v['gcode'] = scale_g(v['gcode']) + + # variables to display the percentage of work done + self.geo_len = 0 + try: + for g in v['gcode_parsed']: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 + self.old_disp_number = 0 + self.el_count = 0 + # scale gcode_parsed for g in v['gcode_parsed']: try: g['geom'] = affinity.scale(g['geom'], xfactor, yfactor, origin=(px, py)) except AttributeError: return g['geom'] + + self.el_count += 1 + disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 99])) + if self.old_disp_number < disp_number <= 100: + self.app.proc_container.update_view_text(' %d%%' % disp_number) + self.old_disp_number = disp_number + v['solid_geometry'] = cascaded_union([geo['geom'] for geo in v['gcode_parsed']]) self.create_geometry() @@ -7696,7 +7967,12 @@ class CNCjob(Geometry): self.gcode = offset_g(self.gcode) # variables to display the percentage of work done - self.geo_len = len(self.gcode_parsed) + self.geo_len = 0 + try: + for g in self.gcode_parsed: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 self.old_disp_number = 0 self.el_count = 0 @@ -7720,7 +7996,12 @@ class CNCjob(Geometry): v['gcode'] = offset_g(v['gcode']) # variables to display the percentage of work done - self.geo_len = len(v['gcode_parsed']) + self.geo_len = 0 + try: + for g in v['gcode_parsed']: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 self.old_disp_number = 0 self.el_count = 0 @@ -7752,11 +8033,28 @@ class CNCjob(Geometry): px, py = point xscale, yscale = {"X": (1.0, -1.0), "Y": (-1.0, 1.0)}[axis] + # variables to display the percentage of work done + self.geo_len = 0 + try: + for g in self.gcode_parsed: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 + self.old_disp_number = 0 + self.el_count = 0 + for g in self.gcode_parsed: try: g['geom'] = affinity.scale(g['geom'], xscale, yscale, origin=(px, py)) except AttributeError: return g['geom'] + + self.el_count += 1 + disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 99])) + if self.old_disp_number < disp_number <= 100: + self.app.proc_container.update_view_text(' %d%%' % disp_number) + self.old_disp_number = disp_number + self.create_geometry() def skew(self, angle_x, angle_y, point): @@ -7778,11 +8076,28 @@ class CNCjob(Geometry): px, py = point + # variables to display the percentage of work done + self.geo_len = 0 + try: + for g in self.gcode_parsed: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 + self.old_disp_number = 0 + self.el_count = 0 + for g in self.gcode_parsed: try: g['geom'] = affinity.skew(g['geom'], angle_x, angle_y, origin=(px, py)) except AttributeError: return g['geom'] + + self.el_count += 1 + disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 99])) + if self.old_disp_number < disp_number <= 100: + self.app.proc_container.update_view_text(' %d%%' % disp_number) + self.old_disp_number = disp_number + self.create_geometry() def rotate(self, angle, point): @@ -7796,11 +8111,28 @@ class CNCjob(Geometry): px, py = point + # variables to display the percentage of work done + self.geo_len = 0 + try: + for g in self.gcode_parsed: + self.geo_len += 1 + except TypeError: + self.geo_len = 1 + self.old_disp_number = 0 + self.el_count = 0 + for g in self.gcode_parsed: try: g['geom'] = affinity.rotate(g['geom'], angle, origin=(px, py)) except AttributeError: return g['geom'] + + self.el_count += 1 + disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 99])) + if self.old_disp_number < disp_number <= 100: + self.app.proc_container.update_view_text(' %d%%' % disp_number) + self.old_disp_number = disp_number + self.create_geometry() diff --git a/flatcamTools/ToolMove.py b/flatcamTools/ToolMove.py index 33e86c90..ae8980ef 100644 --- a/flatcamTools/ToolMove.py +++ b/flatcamTools/ToolMove.py @@ -155,7 +155,7 @@ class ToolMove(FlatCAMTool): # self.app.collection.set_active(sel_obj.options['name']) except Exception as e: proc.done() - self.app.inform.emit('[ERROR_NOTCL] %s --> %s' % (_('ToolMove.on_left_click('), str(e))) + self.app.inform.emit('[ERROR_NOTCL] %s --> %s' % (_('ToolMove.on_left_click()'), str(e))) return "fail" proc.done() # delete the selection bounding box