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

This commit is contained in:
Marius Stanciu
2019-08-22 22:37:42 +03:00
committed by Marius
parent c2991b969b
commit 10115dfd4c
2 changed files with 74 additions and 72 deletions

View File

@@ -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

View File

@@ -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 = []
results = pre_buffer.buffer(buf_distance - 1e-10, resolution=32, join_style=join_style) for t in selected:
if results.is_empty: 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 return 'fail'
self.add_shape(DrawToolShape(results))
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. " _("[ERROR_NOTCL] Negative buffer value is not accepted.")
"Use Buffer interior to generate an 'inside' shape")
) )
# 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 = []
results = pre_buffer.buffer(buf_distance + 1e-10, resolution=32, join_style=join_style) for t in selected:
if isinstance(t.geo, LinearRing):
t.geo = Polygon(t.geo)
if results.is_empty: 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 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 sha in results:
for poly in results: self.add_shape(DrawToolShape(sha))
for interior in poly.interiors:
self.add_shape(DrawToolShape(interior))
else:
for interior in results:
self.add_shape(DrawToolShape(interior))
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 = []
results = pre_buffer.buffer(buf_distance - 1e-10, resolution=32, join_style=join_style) for t in selected:
if results.is_empty: 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: for sha in results:
self.add_shape(DrawToolShape(poly.exterior)) self.add_shape(DrawToolShape(sha))
else:
self.add_shape(DrawToolShape(results.exterior))
self.replot() self.replot()
self.app.inform.emit(_("[success] Exterior buffer geometry created.")) self.app.inform.emit(_("[success] Exterior buffer geometry created."))