diff --git a/FlatCAMApp.py b/FlatCAMApp.py
index 2bfdcf2d..08d39abb 100644
--- a/FlatCAMApp.py
+++ b/FlatCAMApp.py
@@ -843,6 +843,7 @@ class App(QtCore.QObject):
"tools_transform_mirror_reference": False,
"tools_transform_mirror_point": (0, 0),
"tools_transform_buffer_dis": 0.0,
+ "tools_transform_buffer_factor": 100.0,
"tools_transform_buffer_corner": True,
# SolderPaste Tool
@@ -1465,6 +1466,7 @@ class App(QtCore.QObject):
"tools_transform_mirror_reference": self.ui.tools_defaults_form.tools_transform_group.mirror_reference_cb,
"tools_transform_mirror_point": self.ui.tools_defaults_form.tools_transform_group.flip_ref_entry,
"tools_transform_buffer_dis": self.ui.tools_defaults_form.tools_transform_group.buffer_entry,
+ "tools_transform_buffer_factor": self.ui.tools_defaults_form.tools_transform_group.buffer_factor_entry,
"tools_transform_buffer_corner": self.ui.tools_defaults_form.tools_transform_group.buffer_rounded_cb,
# SolderPaste Dispensing Tool
diff --git a/FlatCAMObj.py b/FlatCAMObj.py
index 7d22fe6a..d28e40ab 100644
--- a/FlatCAMObj.py
+++ b/FlatCAMObj.py
@@ -2215,8 +2215,8 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
Gerber.skew(self, angle_x=angle_x, angle_y=angle_y, point=point)
self.replotApertures.emit()
- def buffer(self, distance, join):
- Gerber.buffer(self, distance=distance, join=join)
+ def buffer(self, distance, join, factor=None):
+ Gerber.buffer(self, distance=distance, join=join, factor=factor)
self.replotApertures.emit()
def serialize(self):
diff --git a/README.md b/README.md
index fb38722a..d3419233 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,11 @@ CAD program, and create G-Code for Isolation routing.
=================================================
+30.12.2019
+
+- Buffer sub-tool in Transform Tool: added the possibility to apply a factor effectively scaling the aperture size thus the copper features sizes
+- in Transform Tool adjusted the GUI
+
29.12.2019
- the Apply button text in Preferences is now made red when changes were made and require to be applied
diff --git a/camlib.py b/camlib.py
index 75a440db..7f87351a 100644
--- a/camlib.py
+++ b/camlib.py
@@ -2118,11 +2118,11 @@ class Geometry(object):
# self.solid_geometry = affinity.skew(self.solid_geometry, angle_x, angle_y,
# origin=(px, py))
- def buffer(self, distance, join):
+ def buffer(self, distance, join, factor):
"""
- :param distance:
- :param join:
+ :param distance: if 'factor' is True then distance is the factor
+ :param factor: True or False (None)
:return:
"""
@@ -2145,7 +2145,10 @@ class Geometry(object):
self.app.proc_container.update_view_text(' %d%%' % disp_number)
self.old_disp_number = disp_number
- return obj.buffer(distance, resolution=self.geo_steps_per_circle, join_style=join)
+ if factor is None:
+ return obj.buffer(distance, resolution=self.geo_steps_per_circle, join_style=join)
+ else:
+ return affinity.scale(obj, xfact=distance, yfact=distance, origin='center')
except AttributeError:
return obj
@@ -2155,20 +2158,23 @@ class Geometry(object):
# variables to display the percentage of work done
self.geo_len = 0
try:
- for __ in self.tools[tool]['solid_geometry']:
- self.geo_len += 1
+ self.geo_len += len(self.tools[tool]['solid_geometry'])
except TypeError:
- self.geo_len = 1
+ self.geo_len += 1
self.old_disp_number = 0
self.el_count = 0
- self.tools[tool]['solid_geometry'] = buffer_geom(self.tools[tool]['solid_geometry'])
+ res = buffer_geom(self.tools[tool]['solid_geometry'])
+ try:
+ __ = iter(res)
+ self.tools[tool]['solid_geometry'] = res
+ except TypeError:
+ self.tools[tool]['solid_geometry'] = [res]
# 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
self.old_disp_number = 0
@@ -2182,6 +2188,7 @@ class Geometry(object):
self.app.proc_container.new_text = ''
+
class AttrDict(dict):
def __init__(self, *args, **kwargs):
super(AttrDict, self).__init__(*args, **kwargs)
diff --git a/flatcamGUI/PreferencesUI.py b/flatcamGUI/PreferencesUI.py
index d322232b..2ec568bd 100644
--- a/flatcamGUI/PreferencesUI.py
+++ b/flatcamGUI/PreferencesUI.py
@@ -6416,6 +6416,23 @@ class ToolsTransformPrefGroupUI(OptionsGroupUI):
grid0.addWidget(self.buffer_label, 17, 0)
grid0.addWidget(self.buffer_entry, 17, 1)
+ self.buffer_factor_label = QtWidgets.QLabel('%s:' % _("Factor"))
+ self.buffer_factor_label.setToolTip(
+ _("A positive value will create the effect of dilation,\n"
+ "while a negative value will create the effect of erosion.\n"
+ "Each geometry element of the object will be increased\n"
+ "or decreased by the 'factor'.")
+ )
+
+ self.buffer_factor_entry = FCDoubleSpinner(suffix='%')
+ self.buffer_factor_entry.set_range(-100.0000, 1000.0000)
+ self.buffer_factor_entry.set_precision(self.decimals)
+ self.buffer_factor_entry.setWrapping(True)
+ self.buffer_factor_entry.setSingleStep(1)
+
+ grid0.addWidget(self.buffer_factor_label, 18, 0)
+ grid0.addWidget(self.buffer_factor_entry, 18, 1)
+
self.buffer_rounded_cb = FCCheckBox()
self.buffer_rounded_cb.setText('%s' % _("Rounded"))
self.buffer_rounded_cb.setToolTip(
@@ -6425,9 +6442,8 @@ class ToolsTransformPrefGroupUI(OptionsGroupUI):
"of the buffered shape.")
)
- grid0.addWidget(self.buffer_rounded_cb, 18, 0, 1, 2)
+ grid0.addWidget(self.buffer_rounded_cb, 19, 0, 1, 2)
- grid0.addWidget(QtWidgets.QLabel(''), 19, 0, 1, 2)
self.layout.addStretch()
diff --git a/flatcamParsers/ParseExcellon.py b/flatcamParsers/ParseExcellon.py
index 894851c6..adba5941 100644
--- a/flatcamParsers/ParseExcellon.py
+++ b/flatcamParsers/ParseExcellon.py
@@ -1459,11 +1459,11 @@ class Excellon(Geometry):
self.create_geometry()
self.app.proc_container.new_text = ''
- def buffer(self, distance, join):
+ def buffer(self, distance, join, factor):
"""
- :param distance:
- :param join:
+ :param distance: if 'factor' is True then distance is the factor
+ :param factor: True or False (None)
:return:
"""
log.debug("flatcamParsers.ParseExcellon.Excellon.buffer()")
@@ -1479,13 +1479,24 @@ class Excellon(Geometry):
return new_obj
else:
try:
- return obj.buffer(distance, resolution=self.geo_steps_per_circle)
+ if factor is None:
+ return obj.buffer(distance, resolution=self.geo_steps_per_circle)
+ else:
+ return affinity.scale(obj, xfact=distance, yfact=distance, origin='center')
except AttributeError:
return obj
# buffer solid_geometry
for tool, tool_dict in list(self.tools.items()):
- self.tools[tool]['solid_geometry'] = buffer_geom(tool_dict['solid_geometry'])
- self.tools[tool]['C'] += distance
+ res = buffer_geom(tool_dict['solid_geometry'])
+ try:
+ __ = iter(res)
+ self.tools[tool]['solid_geometry'] = res
+ except TypeError:
+ self.tools[tool]['solid_geometry'] = [res]
+ if factor is None:
+ self.tools[tool]['C'] += distance
+ else:
+ self.tools[tool]['C'] *= distance
self.create_geometry()
diff --git a/flatcamParsers/ParseGerber.py b/flatcamParsers/ParseGerber.py
index 876947a0..6f79c31a 100644
--- a/flatcamParsers/ParseGerber.py
+++ b/flatcamParsers/ParseGerber.py
@@ -2188,14 +2188,14 @@ class Gerber(Geometry):
except Exception as e:
log.debug('camlib.Gerber.rotate() Exception --> %s' % str(e))
return 'fail'
- self.app.inform.emit('[success] %s' %
- _("Gerber Rotate done."))
+ self.app.inform.emit('[success] %s' % _("Gerber Rotate done."))
self.app.proc_container.new_text = ''
- def buffer(self, distance, join):
+ def buffer(self, distance, join, factor=None):
"""
- :param distance:
+ :param distance: if 'factor' is True then distance is the factor
+ :param factor: True or False (None)
:return:
"""
log.debug("parseGerber.Gerber.buffer()")
@@ -2206,69 +2206,143 @@ 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
- except TypeError:
+ self.geo_len = len(self.solid_geometry)
+ except (TypeError, ValueError):
self.geo_len = 1
self.old_disp_number = 0
self.el_count = 0
- def buffer_geom(obj):
- if type(obj) is list:
- new_obj = []
- for g in obj:
- new_obj.append(buffer_geom(g))
- return new_obj
- else:
- try:
- self.el_count += 1
- disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 100]))
- if self.old_disp_number < disp_number <= 100:
- self.app.proc_container.update_view_text(' %d%%' % disp_number)
- self.old_disp_number = disp_number
+ if factor is None:
+ def buffer_geom(obj):
+ if type(obj) is list:
+ new_obj = []
+ for g in obj:
+ new_obj.append(buffer_geom(g))
+ return new_obj
+ else:
+ try:
+ self.el_count += 1
+ disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 100]))
+ 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 obj.buffer(distance, resolution=self.steps_per_circle, join_style=join)
- except AttributeError:
- return obj
+ return obj.buffer(distance, resolution=int(self.steps_per_circle), join_style=join)
- self.solid_geometry = buffer_geom(self.solid_geometry)
+ except AttributeError:
+ return obj
- # we need to buffer the geometry stored in the Gerber apertures, too
- try:
+ res = buffer_geom(self.solid_geometry)
+ try:
+ __ = iter(res)
+ self.solid_geometry = res
+ except TypeError:
+ self.solid_geometry = [res]
+
+ # we need to buffer the geometry stored in the Gerber apertures, too
+ try:
+ for apid in self.apertures:
+ new_geometry = list()
+ if 'geometry' in self.apertures[apid]:
+ for geo_el in self.apertures[apid]['geometry']:
+ new_geo_el = dict()
+ if 'solid' in geo_el:
+ new_geo_el['solid'] = buffer_geom(geo_el['solid'])
+ if 'follow' in geo_el:
+ new_geo_el['follow'] = geo_el['follow']
+ if 'clear' in geo_el:
+ new_geo_el['clear'] = buffer_geom(geo_el['clear'])
+ new_geometry.append(new_geo_el)
+
+ self.apertures[apid]['geometry'] = deepcopy(new_geometry)
+
+ try:
+ if str(self.apertures[apid]['type']) == 'R' or str(self.apertures[apid]['type']) == 'O':
+ self.apertures[apid]['width'] += (distance * 2)
+ self.apertures[apid]['height'] += (distance * 2)
+ elif str(self.apertures[apid]['type']) == 'P':
+ self.apertures[apid]['diam'] += (distance * 2)
+ self.apertures[apid]['nVertices'] += (distance * 2)
+ except KeyError:
+ pass
+
+ try:
+ if self.apertures[apid]['size'] is not None:
+ self.apertures[apid]['size'] = float(self.apertures[apid]['size'] + (distance * 2))
+ except KeyError:
+ pass
+ except Exception as e:
+ log.debug('camlib.Gerber.buffer() Exception --> %s' % str(e))
+ return 'fail'
+ else:
+ try:
+ for apid in self.apertures:
+ try:
+ if str(self.apertures[apid]['type']) == 'R' or str(self.apertures[apid]['type']) == 'O':
+ self.apertures[apid]['width'] *= distance
+ self.apertures[apid]['height'] *= distance
+ elif str(self.apertures[apid]['type']) == 'P':
+ self.apertures[apid]['diam'] *= distance
+ self.apertures[apid]['nVertices'] *= distance
+ except KeyError:
+ pass
+
+ try:
+ if self.apertures[apid]['size'] is not None:
+ self.apertures[apid]['size'] = float(self.apertures[apid]['size']) * distance
+ except KeyError:
+ pass
+
+ new_geometry = list()
+ if 'geometry' in self.apertures[apid]:
+ for geo_el in self.apertures[apid]['geometry']:
+ new_geo_el = dict()
+ if 'follow' in geo_el:
+ new_geo_el['follow'] = geo_el['follow']
+ size = float(self.apertures[apid]['size'])
+ if isinstance(new_geo_el['follow'], Point):
+ if str(self.apertures[apid]['type']) == 'C':
+ new_geo_el['solid'] = geo_el['follow'].buffer(
+ size / 1.9999,
+ resolution=int(self.steps_per_circle)
+ )
+ elif str(self.apertures[apid]['type']) == 'R':
+ width = self.apertures[apid]['width']
+ height = self.apertures[apid]['height']
+ minx = new_geo_el['follow'].x - width / 2
+ maxx = new_geo_el['follow'].x + width / 2
+ miny = new_geo_el['follow'].y - height / 2
+ maxy = new_geo_el['follow'].y + height / 2
+
+ geo_p = shply_box(minx, miny, maxx, maxy)
+ new_geo_el['solid'] = geo_p
+ else:
+ log.debug("flatcamParsers.ParseGerber.Gerber.buffer() --> "
+ "ap type not supported")
+ else:
+ new_geo_el['solid'] = geo_el['follow'].buffer(
+ size/1.9999,
+ resolution=int(self.steps_per_circle)
+ )
+ if 'clear' in geo_el:
+ new_geo_el['clear'] = geo_el['clear']
+ new_geometry.append(new_geo_el)
+
+ self.apertures[apid]['geometry'] = deepcopy(new_geometry)
+ except Exception as e:
+ log.debug('camlib.Gerber.buffer() Exception --> %s' % str(e))
+ return 'fail'
+
+ # make the new solid_geometry
+ new_solid_geo = list()
for apid in self.apertures:
- new_geometry = list()
if 'geometry' in self.apertures[apid]:
- for geo_el in self.apertures[apid]['geometry']:
- new_geo_el = dict()
- if 'solid' in geo_el:
- new_geo_el['solid'] = buffer_geom(geo_el['solid'])
- if 'follow' in geo_el:
- new_geo_el['follow'] = buffer_geom(geo_el['follow'])
- if 'clear' in geo_el:
- new_geo_el['clear'] = buffer_geom(geo_el['clear'])
- new_geometry.append(new_geo_el)
+ new_solid_geo += [geo_el['solid'] for geo_el in self.apertures[apid]['geometry']]
- self.apertures[apid]['geometry'] = deepcopy(new_geometry)
-
- try:
- if str(self.apertures[apid]['type']) == 'R' or str(self.apertures[apid]['type']) == 'O':
- self.apertures[apid]['width'] += (distance * 2)
- self.apertures[apid]['height'] += (distance * 2)
- elif str(self.apertures[apid]['type']) == 'P':
- self.apertures[apid]['diam'] += (distance * 2)
- self.apertures[apid]['nVertices'] += (distance * 2)
- except KeyError:
- pass
-
- try:
- if self.apertures[apid]['size'] is not None:
- self.apertures[apid]['size'] = float(self.apertures[apid]['size'] + (distance * 2))
- except KeyError:
- pass
- except Exception as e:
- log.debug('camlib.Gerber.buffer() Exception --> %s' % str(e))
- return 'fail'
+ self.solid_geometry = MultiPolygon(new_solid_geo)
+ self.solid_geometry = self.solid_geometry.buffer(0.000001)
+ self.solid_geometry = self.solid_geometry.buffer(-0.000001)
self.app.inform.emit('[success] %s' % _("Gerber Buffer done."))
self.app.proc_container.new_text = ''
diff --git a/flatcamTools/ToolTransform.py b/flatcamTools/ToolTransform.py
index 566372c2..cbfe6f34 100644
--- a/flatcamTools/ToolTransform.py
+++ b/flatcamTools/ToolTransform.py
@@ -89,7 +89,10 @@ class ToolTransform(FlatCAMTool):
grid0.addWidget(self.rotate_entry, 1, 1)
grid0.addWidget(self.rotate_button, 1, 2)
- grid0.addWidget(QtWidgets.QLabel(''), 2, 0)
+ separator_line = QtWidgets.QFrame()
+ separator_line.setFrameShape(QtWidgets.QFrame.HLine)
+ separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
+ grid0.addWidget(separator_line, 2, 0, 1, 3)
# ## Skew Title
skew_title_label = QtWidgets.QLabel("%s" % self.skewName)
@@ -139,7 +142,10 @@ class ToolTransform(FlatCAMTool):
grid0.addWidget(self.skewy_entry, 5, 1)
grid0.addWidget(self.skewy_button, 5, 2)
- grid0.addWidget(QtWidgets.QLabel(''), 6, 0)
+ separator_line = QtWidgets.QFrame()
+ separator_line.setFrameShape(QtWidgets.QFrame.HLine)
+ separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
+ grid0.addWidget(separator_line, 6, 0, 1, 3)
# ## Scale Title
scale_title_label = QtWidgets.QLabel("%s" % self.scaleName)
@@ -208,7 +214,11 @@ class ToolTransform(FlatCAMTool):
grid0.addWidget(self.scale_link_cb, 10, 0)
grid0.addWidget(self.scale_zero_ref_cb, 10, 1)
- grid0.addWidget(QtWidgets.QLabel(''), 11, 0)
+
+ separator_line = QtWidgets.QFrame()
+ separator_line.setFrameShape(QtWidgets.QFrame.HLine)
+ separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
+ grid0.addWidget(separator_line, 11, 0, 1, 3)
# ## Offset Title
offset_title_label = QtWidgets.QLabel("%s" % self.offsetName)
@@ -256,7 +266,10 @@ class ToolTransform(FlatCAMTool):
grid0.addWidget(self.offy_entry, 14, 1)
grid0.addWidget(self.offy_button, 14, 2)
- grid0.addWidget(QtWidgets.QLabel(''), 15, 0, 1, 3)
+ separator_line = QtWidgets.QFrame()
+ separator_line.setFrameShape(QtWidgets.QFrame.HLine)
+ separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
+ grid0.addWidget(separator_line, 15, 0, 1, 3)
# ## Flip Title
flip_title_label = QtWidgets.QLabel("%s" % self.flipName)
@@ -323,7 +336,10 @@ class ToolTransform(FlatCAMTool):
grid0.addWidget(self.flip_ref_button, 20, 0, 1, 3)
- grid0.addWidget(QtWidgets.QLabel(''), 21, 0, 1, 3)
+ separator_line = QtWidgets.QFrame()
+ separator_line.setFrameShape(QtWidgets.QFrame.HLine)
+ separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
+ grid0.addWidget(separator_line, 21, 0, 1, 3)
# ## Buffer Title
buffer_title_label = QtWidgets.QLabel("%s" % self.bufferName)
@@ -343,13 +359,11 @@ class ToolTransform(FlatCAMTool):
self.buffer_entry.setWrapping(True)
self.buffer_entry.set_range(-9999.9999, 9999.9999)
- # self.rotate_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
-
self.buffer_button = FCButton()
- self.buffer_button.set_value(_("Buffer"))
+ self.buffer_button.set_value(_("Buffer D"))
self.buffer_button.setToolTip(
_("Create the buffer effect on each geometry,\n"
- "element from the selected object.")
+ "element from the selected object, using the distance.")
)
self.buffer_button.setMinimumWidth(90)
@@ -357,8 +371,33 @@ class ToolTransform(FlatCAMTool):
grid0.addWidget(self.buffer_entry, 23, 1)
grid0.addWidget(self.buffer_button, 23, 2)
- self.buffer_rounded_cb = FCCheckBox()
- self.buffer_rounded_cb.setText('%s' % _("Rounded"))
+ self.buffer_factor_label = QtWidgets.QLabel('%s:' % _("Factor"))
+ self.buffer_factor_label.setToolTip(
+ _("A positive value will create the effect of dilation,\n"
+ "while a negative value will create the effect of erosion.\n"
+ "Each geometry element of the object will be increased\n"
+ "or decreased by the 'factor'.")
+ )
+
+ self.buffer_factor_entry = FCDoubleSpinner(suffix='%')
+ self.buffer_factor_entry.set_range(-100.0000, 1000.0000)
+ self.buffer_factor_entry.set_precision(self.decimals)
+ self.buffer_factor_entry.setWrapping(True)
+ self.buffer_factor_entry.setSingleStep(1)
+
+ self.buffer_factor_button = FCButton()
+ self.buffer_factor_button.set_value(_("Buffer F"))
+ self.buffer_factor_button.setToolTip(
+ _("Create the buffer effect on each geometry,\n"
+ "element from the selected object, using the factor.")
+ )
+ self.buffer_factor_button.setMinimumWidth(90)
+
+ grid0.addWidget(self.buffer_factor_label, 24, 0)
+ grid0.addWidget(self.buffer_factor_entry, 24, 1)
+ grid0.addWidget(self.buffer_factor_button, 24, 2)
+
+ self.buffer_rounded_cb = FCCheckBox('%s' % _("Rounded"))
self.buffer_rounded_cb.setToolTip(
_("If checked then the buffer will surround the buffered shape,\n"
"every corner will be rounded.\n"
@@ -366,9 +405,9 @@ class ToolTransform(FlatCAMTool):
"of the buffered shape.")
)
- grid0.addWidget(self.buffer_rounded_cb, 24, 0, 1, 3)
+ grid0.addWidget(self.buffer_rounded_cb, 25, 0, 1, 3)
- grid0.addWidget(QtWidgets.QLabel(''), 25, 0, 1, 3)
+ grid0.addWidget(QtWidgets.QLabel(''), 26, 0, 1, 3)
self.transform_lay.addStretch()
@@ -383,7 +422,8 @@ class ToolTransform(FlatCAMTool):
self.flipx_button.clicked.connect(self.on_flipx)
self.flipy_button.clicked.connect(self.on_flipy)
self.flip_ref_button.clicked.connect(self.on_flip_add_coords)
- self.buffer_button.clicked.connect(self.on_buffer)
+ self.buffer_button.clicked.connect(self.on_buffer_by_distance)
+ self.buffer_factor_button.clicked.connect(self.on_buffer_by_factor)
# self.rotate_entry.returnPressed.connect(self.on_rotate)
# self.skewx_entry.returnPressed.connect(self.on_skewx)
@@ -392,7 +432,7 @@ class ToolTransform(FlatCAMTool):
# self.scaley_entry.returnPressed.connect(self.on_scaley)
# self.offx_entry.returnPressed.connect(self.on_offx)
# self.offy_entry.returnPressed.connect(self.on_offy)
- # self.buffer_entry.returnPressed.connect(self.on_buffer)
+ # self.buffer_entry.returnPressed.connect(self.on_buffer_by_distance)
def run(self, toggle=True):
self.app.report_usage("ToolTransform()")
@@ -486,6 +526,11 @@ class ToolTransform(FlatCAMTool):
else:
self.buffer_entry.set_value(0.0)
+ if self.app.defaults["tools_transform_buffer_factor"]:
+ self.buffer_factor_entry.set_value(self.app.defaults["tools_transform_buffer_factor"])
+ else:
+ self.buffer_factor_entry.set_value(100.0)
+
if self.app.defaults["tools_transform_buffer_corner"]:
self.buffer_rounded_cb.set_value(self.app.defaults["tools_transform_buffer_corner"])
else:
@@ -589,13 +634,23 @@ class ToolTransform(FlatCAMTool):
self.app.worker_task.emit({'fcn': self.on_offset, 'params': [axis, value]})
return
- def on_buffer(self):
+ def on_buffer_by_distance(self):
value = self.buffer_entry.get_value()
join = 1 if self.buffer_rounded_cb.get_value() else 2
self.app.worker_task.emit({'fcn': self.on_buffer_action, 'params': [value, join]})
return
+ def on_buffer_by_factor(self):
+ value = self.buffer_factor_entry.get_value() / 100.0
+ join = 1 if self.buffer_rounded_cb.get_value() else 2
+
+ # tell the buffer method to use the factor
+ factor = True
+
+ self.app.worker_task.emit({'fcn': self.on_buffer_action, 'params': [value, join, factor]})
+ return
+
def on_rotate_action(self, num):
obj_list = self.app.collection.get_selected()
xminlist = []
@@ -604,8 +659,7 @@ class ToolTransform(FlatCAMTool):
ymaxlist = []
if not obj_list:
- self.app.inform.emit('[WARNING_NOTCL] %s' %
- _("No object selected. Please Select an object to rotate!"))
+ self.app.inform.emit('[WARNING_NOTCL] %s' % _("No object selected. Please Select an object to rotate!"))
return
else:
with self.app.proc_container.new(_("Appying Rotate")):
@@ -874,7 +928,7 @@ class ToolTransform(FlatCAMTool):
(_("Due of"), str(e), _("action was not executed.")))
return
- def on_buffer_action(self, value, join):
+ def on_buffer_action(self, value, join, factor=None):
obj_list = self.app.collection.get_selected()
if not obj_list:
@@ -887,17 +941,17 @@ class ToolTransform(FlatCAMTool):
if isinstance(sel_obj, FlatCAMCNCjob):
self.app.inform.emit(_("CNCJob objects can't be buffered."))
elif sel_obj.kind.lower() == 'gerber':
- sel_obj.buffer(value, join)
+ sel_obj.buffer(value, join, factor)
sel_obj.source_file = self.app.export_gerber(obj_name=sel_obj.options['name'],
filename=None, local_use=sel_obj,
use_thread=False)
elif sel_obj.kind.lower() == 'excellon':
- sel_obj.buffer(value, join)
+ sel_obj.buffer(value, join, factor)
sel_obj.source_file = self.app.export_excellon(obj_name=sel_obj.options['name'],
filename=None, local_use=sel_obj,
use_thread=False)
elif sel_obj.kind.lower() == 'geometry':
- sel_obj.buffer(value, join)
+ sel_obj.buffer(value, join, factor)
self.app.object_changed.emit(sel_obj)
sel_obj.plot()