Przeglądaj źródła

- in FlatCAMGeometry fixed the scale and offset methods to always process the self.solid_geometry
- Calibration Tool - finished the calibrated object creation method

Marius Stanciu 6 lat temu
rodzic
commit
1f1d200ab6

+ 35 - 44
FlatCAMObj.py

@@ -5370,9 +5370,8 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
 
         try:
             xfactor = float(xfactor)
-        except Exception as e:
-            self.app.inform.emit('[ERROR_NOTCL] %s' %
-                                 _("Scale factor has to be a number: integer or float."))
+        except Exception:
+            self.app.inform.emit('[ERROR_NOTCL] %s' %  _("Scale factor has to be a number: integer or float."))
             return
 
         if yfactor is None:
@@ -5380,29 +5379,19 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
         else:
             try:
                 yfactor = float(yfactor)
-            except Exception as e:
-                self.app.inform.emit('[ERROR_NOTCL] %s' %
-                                     _("Scale factor has to be a number: integer or float."))
+            except Exception:
+                self.app.inform.emit('[ERROR_NOTCL] %s' % _("Scale factor has to be a number: integer or float."))
                 return
 
+        if xfactor == 1 and yfactor == 1:
+            return
+
         if point is None:
             px = 0
             py = 0
         else:
             px, py = point
 
-        # if type(self.solid_geometry) == list:
-        #     geo_list =  self.flatten(self.solid_geometry)
-        #     self.solid_geometry = []
-        #     # for g in geo_list:
-        #     #     self.solid_geometry.append(affinity.scale(g, xfactor, yfactor, origin=(px, py)))
-        #     self.solid_geometry = [affinity.scale(g, xfactor, yfactor, origin=(px, py))
-        #                            for g in geo_list]
-        # else:
-        #     self.solid_geometry = affinity.scale(self.solid_geometry, xfactor, yfactor,
-        #                                          origin=(px, py))
-        # self.app.inform.emit("[success] Geometry Scale done.")
-
         self.geo_len = 0
         self.old_disp_number = 0
         self.el_count = 0
@@ -5438,25 +5427,24 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
                 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:
-                # variables to display the percentage of work done
-                self.geo_len = 0
-                try:
-                    self.geo_len = len(self.solid_geometry)
-                except TypeError:
-                    self.geo_len = 1
-                self.old_disp_number = 0
-                self.el_count = 0
+                self.geo_len = len(self.solid_geometry)
+            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 = []
-                return
+            self.solid_geometry = scale_recursion(self.solid_geometry)
+        except AttributeError:
+            self.solid_geometry = []
+            return
 
         self.app.proc_container.new_text = ''
-        if xfactor != 1 and yfactor != 1:
-            self.app.inform.emit('[success] %s' % _("Geometry Scale done."))
+        self.app.inform.emit('[success] %s' % _("Geometry Scale done."))
 
     def offset(self, vect):
         """
@@ -5478,6 +5466,9 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
                                  )
             return
 
+        if dx == 0 and dy == 0:
+            return
+
         self.geo_len = 0
         self.old_disp_number = 0
         self.el_count = 0
@@ -5513,18 +5504,18 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
                 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 = 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 = translate_recursion(self.solid_geometry)
+        # 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 = translate_recursion(self.solid_geometry)
 
         self.app.proc_container.new_text = ''
         self.app.inform.emit('[success] %s' % _("Geometry Offset done."))

+ 2 - 0
README.md

@@ -17,6 +17,8 @@ CAD program, and create G-Code for Isolation routing.
 - reverted this change: "selected object in Project used to ask twice for UI build" because it will not build the UI when a tab is closed for Document object and the object is selected
 - fixed issue after Geometry object edit; the GCode made from and edited object did not reflect the changes in the object
 - in Object UI, the Scale FCDoubleSpinner will no longer work for Return key press due of issues of unwanted scaling on focusOut event
+- in FlatCAMGeometry fixed the scale and offset methods to always process the self.solid_geometry
+- Calibration Tool - finished the calibrated object creation method
 
 8.12.2019
 

+ 2 - 1
flatcamGUI/GUIElements.py

@@ -531,6 +531,7 @@ class FCSpinner(QtWidgets.QSpinBox):
     def __init__(self, suffix=None, alignment=None, parent=None):
         super(FCSpinner, self).__init__(parent)
         self.readyToEdit = True
+
         self.editingFinished.connect(self.on_edit_finished)
         self.lineEdit().installEventFilter(self)
 
@@ -588,6 +589,7 @@ class FCSpinner(QtWidgets.QSpinBox):
             super(FCSpinner, self).focusOutEvent(e)  # required to remove cursor on focusOut
             self.lineEdit().deselect()
             self.readyToEdit = True
+            self.prev_readyToEdit = True
 
     def get_value(self):
         return int(self.value())
@@ -652,7 +654,6 @@ class FCDoubleSpinner(QtWidgets.QDoubleSpinBox):
                     self.readyToEdit = False
                 else:
                     self.lineEdit().deselect()
-
                 return True
         return False
 

+ 12 - 0
flatcamParsers/ParseExcellon.py

@@ -1112,6 +1112,9 @@ class Excellon(Geometry):
         else:
             px, py = point
 
+        if xfactor == 0 and yfactor == 0:
+            return
+
         def scale_geom(obj):
             if type(obj) is list:
                 new_obj = []
@@ -1168,6 +1171,9 @@ class Excellon(Geometry):
 
         dx, dy = vect
 
+        if dx == 0 and dy == 0:
+            return
+
         def offset_geom(obj):
             if type(obj) is list:
                 new_obj = []
@@ -1297,6 +1303,9 @@ class Excellon(Geometry):
         if angle_y is None:
             angle_y = 0.0
 
+        if angle_x == 0 and angle_y == 0:
+            return
+
         def skew_geom(obj):
             if type(obj) is list:
                 new_obj = []
@@ -1375,6 +1384,9 @@ class Excellon(Geometry):
         """
         log.debug("flatcamParsers.ParseExcellon.Excellon.rotate()")
 
+        if angle == 0:
+            return
+
         def rotate_geom(obj, origin=None):
             if type(obj) is list:
                 new_obj = []

+ 15 - 6
flatcamParsers/ParseGerber.py

@@ -1760,6 +1760,9 @@ class Gerber(Geometry):
                                      _("Scale factor has to be a number: integer or float."))
                 return
 
+        if xfactor == 0 and yfactor == 0:
+            return
+
         if point is None:
             px = 0
             py = 0
@@ -1769,8 +1772,7 @@ class Gerber(Geometry):
         # variables to display the percentage of work done
         self.geo_len = 0
         try:
-            for __ in self.solid_geometry:
-                self.geo_len += 1
+            self.geo_len = len(self.solid_geometry)
         except TypeError:
             self.geo_len = 1
 
@@ -1835,8 +1837,7 @@ class Gerber(Geometry):
             log.debug('camlib.Gerber.scale() Exception --> %s' % str(e))
             return 'fail'
 
-        self.app.inform.emit('[success] %s' %
-                             _("Gerber Scale done."))
+        self.app.inform.emit('[success] %s' % _("Gerber Scale done."))
         self.app.proc_container.new_text = ''
 
         # ## solid_geometry ???
@@ -1876,6 +1877,9 @@ class Gerber(Geometry):
                                    "Probable you entered only one value in the Offset field."))
             return
 
+        if dx == 0 and dy == 0:
+            return
+
         # variables to display the percentage of work done
         self.geo_len = 0
         try:
@@ -2028,11 +2032,13 @@ class Gerber(Geometry):
 
         px, py = point
 
+        if angle_x == 0 and angle_y == 0:
+            return
+
         # variables to display the percentage of work done
         self.geo_len = 0
         try:
-            for __ in self.solid_geometry:
-                self.geo_len += 1
+            self.geo_len = len(self.solid_geometry)
         except TypeError:
             self.geo_len = 1
 
@@ -2089,6 +2095,9 @@ class Gerber(Geometry):
 
         px, py = point
 
+        if angle == 0:
+            return
+
         # variables to display the percentage of work done
         self.geo_len = 0
         try:

+ 153 - 45
flatcamTools/ToolCalibration.py

@@ -18,6 +18,7 @@ from shapely.geometry.base import *
 import math
 from datetime import datetime
 import logging
+from copy import deepcopy
 
 import gettext
 import FlatCAMTranslation as fcTranslate
@@ -388,6 +389,21 @@ class ToolCalibration(FlatCAMTool):
                         """)
         grid_lay.addWidget(self.generate_factors_button, 20, 0, 1, 3)
 
+        separator_line1 = QtWidgets.QFrame()
+        separator_line1.setFrameShape(QtWidgets.QFrame.HLine)
+        separator_line1.setFrameShadow(QtWidgets.QFrame.Sunken)
+        grid_lay.addWidget(separator_line1, 21, 0, 1, 3)
+
+        grid_lay.addWidget(QtWidgets.QLabel(''), 22, 0, 1, 3)
+
+        # STEP 4 #
+        step_4 = QtWidgets.QLabel('<b>%s</b>' % _("STEP 4: Adjusted GCode"))
+        step_4.setToolTip(
+            _("Generate verification GCode file adjusted with\n"
+              "the factors above.")
+        )
+        grid_lay.addWidget(step_4, 23, 0, 1, 3)
+
         self.scalex_label = QtWidgets.QLabel(_("Scale Factor X:"))
         self.scalex_label.setToolTip(
             _("Factor for Scale action over X axis.")
@@ -397,8 +413,8 @@ class ToolCalibration(FlatCAMTool):
         self.scalex_entry.set_precision(self.decimals)
         self.scalex_entry.setSingleStep(0.1)
 
-        grid_lay.addWidget(self.scalex_label, 21, 0)
-        grid_lay.addWidget(self.scalex_entry, 21, 1, 1, 2)
+        grid_lay.addWidget(self.scalex_label, 24, 0)
+        grid_lay.addWidget(self.scalex_entry, 24, 1, 1, 2)
 
         self.scaley_label = QtWidgets.QLabel(_("Scale Factor Y:"))
         self.scaley_label.setToolTip(
@@ -409,20 +425,20 @@ class ToolCalibration(FlatCAMTool):
         self.scaley_entry.set_precision(self.decimals)
         self.scaley_entry.setSingleStep(0.1)
 
-        grid_lay.addWidget(self.scaley_label, 22, 0)
-        grid_lay.addWidget(self.scaley_entry, 22, 1, 1, 2)
+        grid_lay.addWidget(self.scaley_label, 25, 0)
+        grid_lay.addWidget(self.scaley_entry, 25, 1, 1, 2)
 
         self.scale_button = QtWidgets.QPushButton(_("Apply Scale Factors"))
         self.scale_button.setToolTip(
             _("Apply Scale factors on the calibration points.")
         )
         self.scale_button.setStyleSheet("""
-                        QPushButton
-                        {
-                            font-weight: bold;
-                        }
-                        """)
-        grid_lay.addWidget(self.scale_button, 23, 0, 1, 3)
+                               QPushButton
+                               {
+                                   font-weight: bold;
+                               }
+                               """)
+        grid_lay.addWidget(self.scale_button, 26, 0, 1, 3)
 
         self.skewx_label = QtWidgets.QLabel(_("Skew Angle X:"))
         self.skewx_label.setToolTip(
@@ -434,8 +450,8 @@ class ToolCalibration(FlatCAMTool):
         self.skewx_entry.set_precision(self.decimals)
         self.skewx_entry.setSingleStep(0.1)
 
-        grid_lay.addWidget(self.skewx_label, 24, 0)
-        grid_lay.addWidget(self.skewx_entry, 24, 1, 1, 2)
+        grid_lay.addWidget(self.skewx_label, 27, 0)
+        grid_lay.addWidget(self.skewx_entry, 27, 1, 1, 2)
 
         self.skewy_label = QtWidgets.QLabel(_("Skew Angle Y:"))
         self.skewy_label.setToolTip(
@@ -447,20 +463,20 @@ class ToolCalibration(FlatCAMTool):
         self.skewy_entry.set_precision(self.decimals)
         self.skewy_entry.setSingleStep(0.1)
 
-        grid_lay.addWidget(self.skewy_label, 25, 0)
-        grid_lay.addWidget(self.skewy_entry, 25, 1, 1, 2)
+        grid_lay.addWidget(self.skewy_label, 28, 0)
+        grid_lay.addWidget(self.skewy_entry, 28, 1, 1, 2)
 
         self.skew_button = QtWidgets.QPushButton(_("Apply Skew Factors"))
         self.skew_button.setToolTip(
             _("Apply Skew factors on the calibration points.")
         )
         self.skew_button.setStyleSheet("""
-                        QPushButton
-                        {
-                            font-weight: bold;
-                        }
-                        """)
-        grid_lay.addWidget(self.skew_button, 26, 0, 1, 3)
+                               QPushButton
+                               {
+                                   font-weight: bold;
+                               }
+                               """)
+        grid_lay.addWidget(self.skew_button, 29, 0, 1, 3)
 
         # final_factors_lbl = QtWidgets.QLabel('<b>%s</b>' % _("Final Factors"))
         # final_factors_lbl.setToolTip(
@@ -519,22 +535,8 @@ class ToolCalibration(FlatCAMTool):
         # grid_lay.addWidget(self.fin_skewy_label, 31, 0)
         # grid_lay.addWidget(self.fin_skewy_entry, 31, 1, 1, 2)
 
-        separator_line1 = QtWidgets.QFrame()
-        separator_line1.setFrameShape(QtWidgets.QFrame.HLine)
-        separator_line1.setFrameShadow(QtWidgets.QFrame.Sunken)
-        grid_lay.addWidget(separator_line1, 32, 0, 1, 3)
-
-        grid_lay.addWidget(QtWidgets.QLabel(''), 32, 0, 1, 3)
-
-        # STEP 4 #
-        step_4 = QtWidgets.QLabel('<b>%s</b>' % _("STEP 4: Adjusted GCode"))
-        step_4.setToolTip(
-            _("Generate verification GCode file adjusted with\n"
-              "the factors above.")
-        )
-        grid_lay.addWidget(step_4, 34, 0, 1, 3)
-
         # ## Adjusted GCode Button
+
         self.adj_gcode_button = QtWidgets.QPushButton(_("Generate Adjusted GCode"))
         self.adj_gcode_button.setToolTip(
             _("Generate verification GCode file adjusted with\n"
@@ -735,6 +737,16 @@ class ToolCalibration(FlatCAMTool):
             self.object_combo.setDisabled(True)
 
     def on_start_collect_points(self):
+
+        if self.cal_source_radio.get_value() == 'object':
+            selection_index = self.object_combo.currentIndex()
+            model_index = self.app.collection.index(selection_index, 0, self.object_combo.rootModelIndex())
+            try:
+                self.target_obj = model_index.internalPointer().obj
+            except Exception:
+                self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no source FlatCAM object selected..."))
+                return
+
         # disengage the grid snapping since it will be hard to find the drills on grid
         if self.app.ui.grid_snap_btn.isChecked():
             self.grid_status_memory = True
@@ -751,15 +763,6 @@ class ToolCalibration(FlatCAMTool):
 
         self.local_connected = True
 
-        if self.cal_source_radio.get_value() == 'object':
-            selection_index = self.object_combo.currentIndex()
-            model_index = self.app.collection.index(selection_index, 0, self.object_combo.rootModelIndex())
-            try:
-                self.target_obj = model_index.internalPointer().obj
-            except Exception:
-                self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no target object loaded ..."))
-                return
-
         self.reset_calibration_points()
 
         self.app.inform.emit(_("Get First calibration point. Bottom Left..."))
@@ -1038,8 +1041,113 @@ class ToolCalibration(FlatCAMTool):
             self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no FlatCAM object selected..."))
             return 'fail'
 
+        obj_name = self.cal_object.options["name"] + "_calibrated"
+
+        self.app.worker_task.emit({'fcn': self.new_calibrated_object, 'params': [obj_name]})
+
+    def new_calibrated_object(self, obj_name):
+
+        try:
+            origin_x = self.click_points[0][0]
+            origin_y = self.click_points[0][1]
+        except IndexError as e:
+            log.debug("ToolCalibration.new_calibrated_object() --> %s" % str(e))
+            return 'fail'
+
+        scalex = self.scalex_entry.get_value()
+        scaley = self.scaley_entry.get_value()
+
+        skewx = self.skewx_entry.get_value()
+        skewy = self.skewy_entry.get_value()
+
         # create a new object adjusted (calibrated)
-        # TODO
+        def initialize_geometry(obj_init, app):
+            obj_init.solid_geometry = deepcopy(obj.solid_geometry)
+            try:
+                obj_init.follow_geometry = deepcopy(obj.follow_geometry)
+            except AttributeError:
+                pass
+
+            try:
+                obj_init.apertures = deepcopy(obj.apertures)
+            except AttributeError:
+                pass
+
+            try:
+                if obj.tools:
+                    obj_init.tools = deepcopy(obj.tools)
+            except Exception as e:
+                log.debug("App.on_copy_object() --> %s" % str(e))
+
+            obj_init.scale(xfactor=scalex, yfactor=scaley, point=(origin_x, origin_y))
+            obj_init.skew(angle_x=skewx, angle_y=skewy, point=(origin_x, origin_y))
+
+            try:
+                obj_init.source_file = deepcopy(obj.source_file)
+            except (AttributeError, TypeError):
+                pass
+
+        def initialize_gerber(obj_init, app):
+            obj_init.solid_geometry = deepcopy(obj.solid_geometry)
+            try:
+                obj_init.follow_geometry = deepcopy(obj.follow_geometry)
+            except AttributeError:
+                pass
+
+            try:
+                obj_init.apertures = deepcopy(obj.apertures)
+            except AttributeError:
+                pass
+
+            try:
+                if obj.tools:
+                    obj_init.tools = deepcopy(obj.tools)
+            except Exception as e:
+                log.debug("App.on_copy_object() --> %s" % str(e))
+
+            obj_init.scale(xfactor=scalex, yfactor=scaley, point=(origin_x, origin_y))
+            obj_init.skew(angle_x=skewx, angle_y=skewy, point=(origin_x, origin_y))
+
+            try:
+                obj_init.source_file = self.export_gerber(obj_name=obj_name, filename=None, local_use=obj_init,
+                                                          use_thread=False)
+            except (AttributeError, TypeError):
+                pass
+
+        def initialize_excellon(obj_init, app):
+            obj_init.tools = deepcopy(obj.tools)
+
+            # drills are offset, so they need to be deep copied
+            obj_init.drills = deepcopy(obj.drills)
+            # slots are offset, so they need to be deep copied
+            obj_init.slots = deepcopy(obj.slots)
+
+            obj_init.scale(xfactor=scalex, yfactor=scaley, point=(origin_x, origin_y))
+            obj_init.skew(angle_x=skewx, angle_y=skewy, point=(origin_x, origin_y))
+
+            obj_init.create_geometry()
+
+            obj_init.source_file = self.app.export_excellon(obj_name=obj_name, local_use=obj, filename=None,
+                                                            use_thread=False)
+
+        obj = self.cal_object
+        obj_name = obj_name
+
+        if obj is None:
+            self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no FlatCAM object selected..."))
+            log.debug("ToolCalibration.new_calibrated_object() --> No object to calibrate")
+            return 'fail'
+
+        try:
+            if obj.kind.lower() == 'excellon':
+                self.app.new_object("excellon", str(obj_name), initialize_excellon)
+            elif obj.kind.lower() == 'gerber':
+                self.app.new_object("gerber", str(obj_name), initialize_gerber)
+            elif obj.kind.lower() == 'geometry':
+                self.app.new_object("geometry", str(obj_name), initialize_geometry)
+        except Exception as e:
+            log.debug("ToolCalibration.new_calibrated_object() --> %s" % str(e))
+            return "Operation failed: %s" % str(e)
 
     def disconnect_cal_events(self):
         # restore the Grid snapping if it was active before