Просмотр исходного кода

- fixed the Buffer Tool in Geometry Editor; made the Buffer entry field a QDoubleSpinner and set the lower limit to zero.

Marius Stanciu 6 лет назад
Родитель
Сommit
10115dfd4c
2 измененных файлов с 74 добавлено и 72 удалено
  1. 1 1
      README.md
  2. 73 71
      flatcamEditors/FlatCAMGeoEditor.py

+ 1 - 1
README.md

@@ -15,7 +15,7 @@ CAD program, and create G-Code for Isolation routing.
 - added ability to turn ON/OFF the detachable capability of the tabs in Plot Tab Area through a context menu activated by right mouse button click on the Notebook header
 - added ability to turn ON/OFF the detachable capability of the tabs in Plot Tab Area through a context menu activated by right mouse button click on the Notebook header
 - added possibility to turn application portable from the Edit -> Preferences -> General -> App. Preferences -> Portable checkbox
 - added possibility to turn application portable from the Edit -> Preferences -> General -> App. Preferences -> Portable checkbox
 - moved the canvas setup into it's own function and called it in the init() function
 - moved the canvas setup into it's own function and called it in the init() function
-
+- fixed the Buffer Tool in Geometry Editor; made the Buffer entry field a QDoubleSpinner and set the lower limit to zero.
 
 
 21.08.2019
 21.08.2019
 
 

+ 73 - 71
flatcamEditors/FlatCAMGeoEditor.py

@@ -76,7 +76,9 @@ class BufferSelectionTool(FlatCAMTool):
         self.buffer_tools_box.addLayout(form_layout)
         self.buffer_tools_box.addLayout(form_layout)
 
 
         # Buffer distance
         # Buffer distance
-        self.buffer_distance_entry = FCEntry()
+        self.buffer_distance_entry = FCDoubleSpinner()
+        self.buffer_distance_entry.set_precision(4)
+        self.buffer_distance_entry.set_range(0.0000, 999999.9999)
         form_layout.addRow(_("Buffer distance:"), self.buffer_distance_entry)
         form_layout.addRow(_("Buffer distance:"), self.buffer_distance_entry)
         self.buffer_corner_lbl = QtWidgets.QLabel(_("Buffer corner:"))
         self.buffer_corner_lbl = QtWidgets.QLabel(_("Buffer corner:"))
         self.buffer_corner_lbl.setToolTip(
         self.buffer_corner_lbl.setToolTip(
@@ -2708,11 +2710,13 @@ class FCBuffer(FCShapeTool):
         # the cb index start from 0 but the join styles for the buffer start from 1 therefore the adjustment
         # the cb index start from 0 but the join styles for the buffer start from 1 therefore the adjustment
         # I populated the combobox such that the index coincide with the join styles value (whcih is really an INT)
         # I populated the combobox such that the index coincide with the join styles value (whcih is really an INT)
         join_style = self.buff_tool.buffer_corner_cb.currentIndex() + 1
         join_style = self.buff_tool.buffer_corner_cb.currentIndex() + 1
-        self.draw_app.buffer(buffer_distance, join_style)
+        ret_val = self.draw_app.buffer(buffer_distance, join_style)
         self.app.ui.notebook.setTabText(2, _("Tools"))
         self.app.ui.notebook.setTabText(2, _("Tools"))
         self.draw_app.app.ui.splitter.setSizes([0, 1])
         self.draw_app.app.ui.splitter.setSizes([0, 1])
 
 
         self.disactivate()
         self.disactivate()
+        if ret_val == 'fail':
+            return
         self.draw_app.app.inform.emit(_("[success] Done. Buffer Tool completed."))
         self.draw_app.app.inform.emit(_("[success] Done. Buffer Tool completed."))
 
 
     def on_buffer_int(self):
     def on_buffer_int(self):
@@ -2734,11 +2738,13 @@ class FCBuffer(FCShapeTool):
         # the cb index start from 0 but the join styles for the buffer start from 1 therefore the adjustment
         # the cb index start from 0 but the join styles for the buffer start from 1 therefore the adjustment
         # I populated the combobox such that the index coincide with the join styles value (whcih is really an INT)
         # I populated the combobox such that the index coincide with the join styles value (whcih is really an INT)
         join_style = self.buff_tool.buffer_corner_cb.currentIndex() + 1
         join_style = self.buff_tool.buffer_corner_cb.currentIndex() + 1
-        self.draw_app.buffer_int(buffer_distance, join_style)
+        ret_val = self.draw_app.buffer_int(buffer_distance, join_style)
         self.app.ui.notebook.setTabText(2, _("Tools"))
         self.app.ui.notebook.setTabText(2, _("Tools"))
         self.draw_app.app.ui.splitter.setSizes([0, 1])
         self.draw_app.app.ui.splitter.setSizes([0, 1])
 
 
         self.disactivate()
         self.disactivate()
+        if ret_val == 'fail':
+            return
         self.draw_app.app.inform.emit(_("[success] Done. Buffer Int Tool completed."))
         self.draw_app.app.inform.emit(_("[success] Done. Buffer Int Tool completed."))
 
 
     def on_buffer_ext(self):
     def on_buffer_ext(self):
@@ -2760,11 +2766,13 @@ class FCBuffer(FCShapeTool):
         # the cb index start from 0 but the join styles for the buffer start from 1 therefore the adjustment
         # the cb index start from 0 but the join styles for the buffer start from 1 therefore the adjustment
         # I populated the combobox such that the index coincide with the join styles value (whcih is really an INT)
         # I populated the combobox such that the index coincide with the join styles value (whcih is really an INT)
         join_style = self.buff_tool.buffer_corner_cb.currentIndex() + 1
         join_style = self.buff_tool.buffer_corner_cb.currentIndex() + 1
-        self.draw_app.buffer_ext(buffer_distance, join_style)
+        ret_val = self.draw_app.buffer_ext(buffer_distance, join_style)
         self.app.ui.notebook.setTabText(2, _("Tools"))
         self.app.ui.notebook.setTabText(2, _("Tools"))
         self.draw_app.app.ui.splitter.setSizes([0, 1])
         self.draw_app.app.ui.splitter.setSizes([0, 1])
 
 
         self.disactivate()
         self.disactivate()
+        if ret_val == 'fail':
+            return
         self.draw_app.app.inform.emit(_("[success] Done. Buffer Ext Tool completed."))
         self.draw_app.app.inform.emit(_("[success] Done. Buffer Ext Tool completed."))
 
 
     def activate(self):
     def activate(self):
@@ -2922,9 +2930,9 @@ class FCTransform(FCShapeTool):
         self.draw_app.transform_tool.run()
         self.draw_app.transform_tool.run()
 
 
 
 
-# ##################### ##
-# # ## Main Application # ##
-# ##################### ##
+# ###############################################
+# ################ Main Application #############
+# ###############################################
 class FlatCAMGeoEditor(QtCore.QObject):
 class FlatCAMGeoEditor(QtCore.QObject):
 
 
     transform_complete = QtCore.pyqtSignal()
     transform_complete = QtCore.pyqtSignal()
@@ -4230,11 +4238,11 @@ class FlatCAMGeoEditor(QtCore.QObject):
             # deselect everything
             # deselect everything
             self.selected = []
             self.selected = []
             self.replot()
             self.replot()
-            return
+            return 'fail'
 
 
         if len(selected) == 0:
         if len(selected) == 0:
             self.app.inform.emit(_("[WARNING_NOTCL] Nothing selected for buffering."))
             self.app.inform.emit(_("[WARNING_NOTCL] Nothing selected for buffering."))
-            return
+            return 'fail'
 
 
         if not isinstance(buf_distance, float):
         if not isinstance(buf_distance, float):
             self.app.inform.emit(_("[WARNING_NOTCL] Invalid distance for buffering."))
             self.app.inform.emit(_("[WARNING_NOTCL] Invalid distance for buffering."))
@@ -4242,17 +4250,32 @@ class FlatCAMGeoEditor(QtCore.QObject):
             # deselect everything
             # deselect everything
             self.selected = []
             self.selected = []
             self.replot()
             self.replot()
-            return
+            return 'fail'
 
 
-        pre_buffer = cascaded_union([t.geo for t in selected])
-        results = pre_buffer.buffer(buf_distance - 1e-10, resolution=32, join_style=join_style)
-        if results.is_empty:
+        results = []
+        for t in selected:
+            if isinstance(t.geo, Polygon) and not t.geo.is_empty:
+                results.append((t.geo.exterior).buffer(
+                    buf_distance - 1e-10,
+                    resolution=int(int(self.app.defaults["geometry_circle_steps"]) / 4),
+                    join_style=join_style)
+                )
+            else:
+                results.append(t.geo.buffer(
+                    buf_distance - 1e-10,
+                    resolution=int(int(self.app.defaults["geometry_circle_steps"]) / 4),
+                    join_style=join_style)
+                )
+
+        if not results:
             self.app.inform.emit(_("[ERROR_NOTCL] Failed, the result is empty. Choose a different buffer value."))
             self.app.inform.emit(_("[ERROR_NOTCL] Failed, the result is empty. Choose a different buffer value."))
             # deselect everything
             # deselect everything
             self.selected = []
             self.selected = []
             self.replot()
             self.replot()
-            return
-        self.add_shape(DrawToolShape(results))
+            return 'fail'
+
+        for sha in results:
+            self.add_shape(DrawToolShape(sha))
 
 
         self.replot()
         self.replot()
         self.app.inform.emit(_("[success] Full buffer geometry created."))
         self.app.inform.emit(_("[success] Full buffer geometry created."))
@@ -4262,77 +4285,48 @@ class FlatCAMGeoEditor(QtCore.QObject):
 
 
         if buf_distance < 0:
         if buf_distance < 0:
             self.app.inform.emit(
             self.app.inform.emit(
-                _("[ERROR_NOTCL] Negative buffer value is not accepted. "
-                  "Use Buffer interior to generate an 'inside' shape")
+                _("[ERROR_NOTCL] Negative buffer value is not accepted.")
             )
             )
             # deselect everything
             # deselect everything
             self.selected = []
             self.selected = []
             self.replot()
             self.replot()
-            return
+            return 'fail'
 
 
         if len(selected) == 0:
         if len(selected) == 0:
             self.app.inform.emit(_("[WARNING_NOTCL] Nothing selected for buffering."))
             self.app.inform.emit(_("[WARNING_NOTCL] Nothing selected for buffering."))
-            return
+            return 'fail'
 
 
         if not isinstance(buf_distance, float):
         if not isinstance(buf_distance, float):
             self.app.inform.emit(_("[WARNING_NOTCL] Invalid distance for buffering."))
             self.app.inform.emit(_("[WARNING_NOTCL] Invalid distance for buffering."))
             # deselect everything
             # deselect everything
             self.selected = []
             self.selected = []
             self.replot()
             self.replot()
-            return
+            return 'fail'
 
 
-        pre_buffer = cascaded_union([t.geo for t in selected])
-        results = pre_buffer.buffer(buf_distance + 1e-10, resolution=32, join_style=join_style)
+        results = []
+        for t in selected:
+            if isinstance(t.geo, LinearRing):
+                t.geo = Polygon(t.geo)
+
+            if isinstance(t.geo, Polygon) and not t.geo.is_empty:
+                results.append((t.geo).buffer(
+                    -buf_distance + 1e-10,
+                    resolution=int(int(self.app.defaults["geometry_circle_steps"]) / 4),
+                    join_style=join_style)
+                )
 
 
-        if results.is_empty:
+        if not results:
             self.app.inform.emit(_("[ERROR_NOTCL] Failed, the result is empty. Choose a smaller buffer value."))
             self.app.inform.emit(_("[ERROR_NOTCL] Failed, the result is empty. Choose a smaller buffer value."))
             # deselect everything
             # deselect everything
             self.selected = []
             self.selected = []
             self.replot()
             self.replot()
-            return
+            return 'fail'
 
 
-        if type(results) == MultiPolygon:
-            for poly in results:
-                for interior in poly.interiors:
-                    self.add_shape(DrawToolShape(interior))
-        else:
-            for interior in results:
-                self.add_shape(DrawToolShape(interior))
+        for sha in results:
+            self.add_shape(DrawToolShape(sha))
 
 
         self.replot()
         self.replot()
         self.app.inform.emit(_("[success] Interior buffer geometry created."))
         self.app.inform.emit(_("[success] Interior buffer geometry created."))
-        # selected = self.get_selected()
-        #
-        # if len(selected) == 0:
-        #     self.app.inform.emit("[WARNING] Nothing selected for buffering.")
-        #     return
-        #
-        # if not isinstance(buf_distance, float):
-        #     self.app.inform.emit("[WARNING] Invalid distance for buffering.")
-        #     return
-        #
-        # pre_buffer = cascaded_union([t.geo for t in selected])
-        # results = pre_buffer.buffer(buf_distance)
-        # if results.is_empty:
-        #     self.app.inform.emit("Failed. Choose a smaller buffer value.")
-        #     return
-        #
-        # int_geo = []
-        # if type(results) == MultiPolygon:
-        #     for poly in results:
-        #         for g in poly.interiors:
-        #             int_geo.append(g)
-        #         res = cascaded_union(int_geo)
-        #         self.add_shape(DrawToolShape(res))
-        # else:
-        #     print(results.interiors)
-        #     for g in results.interiors:
-        #         int_geo.append(g)
-        #     res = cascaded_union(int_geo)
-        #     self.add_shape(DrawToolShape(res))
-        #
-        # self.replot()
-        # self.app.inform.emit("Interior buffer geometry created.")
 
 
     def buffer_ext(self, buf_distance, join_style):
     def buffer_ext(self, buf_distance, join_style):
         selected = self.get_selected()
         selected = self.get_selected()
@@ -4356,19 +4350,27 @@ class FlatCAMGeoEditor(QtCore.QObject):
             self.replot()
             self.replot()
             return
             return
 
 
-        pre_buffer = cascaded_union([t.geo for t in selected])
-        results = pre_buffer.buffer(buf_distance - 1e-10, resolution=32, join_style=join_style)
-        if results.is_empty:
+        results = []
+        for t in selected:
+            if isinstance(t.geo, LinearRing):
+                t.geo = Polygon(t.geo)
+
+            if isinstance(t.geo, Polygon) and not t.geo.is_empty:
+                results.append((t.geo).buffer(
+                    buf_distance,
+                    resolution=int(int(self.app.defaults["geometry_circle_steps"]) / 4),
+                    join_style=join_style)
+                )
+
+        if not results:
             self.app.inform.emit(_("[ERROR_NOTCL] Failed, the result is empty. Choose a different buffer value."))
             self.app.inform.emit(_("[ERROR_NOTCL] Failed, the result is empty. Choose a different buffer value."))
             # deselect everything
             # deselect everything
             self.selected = []
             self.selected = []
             self.replot()
             self.replot()
             return
             return
-        if type(results) == MultiPolygon:
-            for poly in results:
-                self.add_shape(DrawToolShape(poly.exterior))
-        else:
-            self.add_shape(DrawToolShape(results.exterior))
+
+        for sha in results:
+            self.add_shape(DrawToolShape(sha))
 
 
         self.replot()
         self.replot()
         self.app.inform.emit(_("[success] Exterior buffer geometry created."))
         self.app.inform.emit(_("[success] Exterior buffer geometry created."))