diff --git a/FlatCAMApp.py b/FlatCAMApp.py
index 22e9bdac..0804b646 100644
--- a/FlatCAMApp.py
+++ b/FlatCAMApp.py
@@ -511,6 +511,9 @@ class App(QtCore.QObject):
"gerber_multicolored": False,
"gerber_circle_steps": 64,
"gerber_use_buffer_for_union": True,
+ "gerber_clean_apertures": True,
+ "gerber_extra_buffering": True,
+
"gerber_def_units": 'IN',
"gerber_def_zeros": 'L',
"gerber_save_filters": "Gerber File (*.gbr);;Gerber File (*.bot);;Gerber File (*.bsm);;"
@@ -1121,6 +1124,8 @@ class App(QtCore.QObject):
"gerber_circle_steps": self.ui.gerber_defaults_form.gerber_gen_group.circle_steps_entry,
"gerber_def_units": self.ui.gerber_defaults_form.gerber_gen_group.gerber_units_radio,
"gerber_def_zeros": self.ui.gerber_defaults_form.gerber_gen_group.gerber_zeros_radio,
+ "gerber_clean_apertures": self.ui.gerber_defaults_form.gerber_gen_group.gerber_clean_cb,
+ "gerber_extra_buffering": self.ui.gerber_defaults_form.gerber_gen_group.gerber_extra_buffering,
# Gerber Options
"gerber_isotooldia": self.ui.gerber_defaults_form.gerber_opt_group.iso_tool_dia_entry,
diff --git a/FlatCAMObj.py b/FlatCAMObj.py
index b658b63b..671678e4 100644
--- a/FlatCAMObj.py
+++ b/FlatCAMObj.py
@@ -5173,8 +5173,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
if self.tools[tooluid_key]['solid_geometry'] is None:
a += 1
if a == len(self.tools):
- self.app.inform.emit('[ERROR_NOTCL] %s...' %
- _('Cancelled. Empty file, it has no geometry'))
+ self.app.inform.emit('[ERROR_NOTCL] %s...' % _('Cancelled. Empty file, it has no geometry'))
return 'fail'
for tooluid_key in list(tools_dict.keys()):
diff --git a/README.md b/README.md
index 4521336d..1f8a04b3 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,11 @@ CAD program, and create G-Code for Isolation routing.
=================================================
+18.12.2019
+
+- added new parameters to improve Gerber parsing
+- small optimizations in the Preferences UI
+
17.12.2019
- more optimizations in NCC Tool
diff --git a/flatcamEditors/FlatCAMGrbEditor.py b/flatcamEditors/FlatCAMGrbEditor.py
index 5233314c..1779e8c5 100644
--- a/flatcamEditors/FlatCAMGrbEditor.py
+++ b/flatcamEditors/FlatCAMGrbEditor.py
@@ -4594,19 +4594,21 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.shapes.clear(update=True)
for storage in self.storage_dict:
- for elem in self.storage_dict[storage]['geometry']:
- if 'solid' in elem.geo:
- geometric_data = elem.geo['solid']
- if geometric_data is None:
- continue
+ # fix for apertures with now geometry inside
+ if 'geometry' in self.storage_dict[storage]:
+ for elem in self.storage_dict[storage]['geometry']:
+ if 'solid' in elem.geo:
+ geometric_data = elem.geo['solid']
+ if geometric_data is None:
+ continue
- if elem in self.selected:
- self.plot_shape(geometry=geometric_data,
- color=self.app.defaults['global_sel_draw_color'] + 'FF',
- linewidth=2)
- else:
- self.plot_shape(geometry=geometric_data,
- color=self.app.defaults['global_draw_color'] + 'FF')
+ if elem in self.selected:
+ self.plot_shape(geometry=geometric_data,
+ color=self.app.defaults['global_sel_draw_color'] + 'FF',
+ linewidth=2)
+ else:
+ self.plot_shape(geometry=geometric_data,
+ color=self.app.defaults['global_draw_color'] + 'FF')
if self.utility:
for elem in self.utility:
diff --git a/flatcamGUI/PreferencesUI.py b/flatcamGUI/PreferencesUI.py
index cb033589..6aaeabc3 100644
--- a/flatcamGUI/PreferencesUI.py
+++ b/flatcamGUI/PreferencesUI.py
@@ -1435,6 +1435,29 @@ class GerberGenPrefGroupUI(OptionsGroupUI):
grid0.addWidget(self.gerber_zeros_label, 5, 0)
grid0.addWidget(self.gerber_zeros_radio, 5, 1, 1, 2)
+ separator_line = QtWidgets.QFrame()
+ separator_line.setFrameShape(QtWidgets.QFrame.HLine)
+ separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
+ grid0.addWidget(separator_line, 6, 0, 1, 3)
+
+ # Apertures Cleaning
+ self.gerber_clean_cb = FCCheckBox(label='%s' % _('Clean Apertures'))
+ self.gerber_clean_cb.setToolTip(
+ _("Will remove apertures that do not have geometry\n"
+ "thus lowering the number of apertures in the Gerber object.")
+ )
+ grid0.addWidget(self.gerber_clean_cb, 7, 0, 1, 3)
+
+ # Apply Extra Buffering
+ self.gerber_extra_buffering = FCCheckBox(label='%s' % _('Polarity change buffer'))
+ self.gerber_extra_buffering.setToolTip(
+ _("Will apply extra buffering for the\n"
+ "solid geometry when we have polarity changes.\n"
+ "May help loading Gerber files that otherwise\n"
+ "do not load correctly.")
+ )
+ grid0.addWidget(self.gerber_extra_buffering, 8, 0, 1, 3)
+
self.layout.addStretch()
@@ -1528,6 +1551,11 @@ class GerberOptPrefGroupUI(OptionsGroupUI):
)
grid0.addWidget(self.combine_passes_cb, 5, 0, 1, 2)
+ separator_line = QtWidgets.QFrame()
+ separator_line.setFrameShape(QtWidgets.QFrame.HLine)
+ separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
+ grid0.addWidget(separator_line, 6, 0, 1, 2)
+
# ## Clear non-copper regions
self.clearcopper_label = QtWidgets.QLabel("%s:" % _("Non-copper regions"))
self.clearcopper_label.setToolTip(
@@ -1564,6 +1592,11 @@ class GerberOptPrefGroupUI(OptionsGroupUI):
)
grid1.addWidget(self.noncopper_rounded_cb, 1, 0, 1, 2)
+ separator_line = QtWidgets.QFrame()
+ separator_line.setFrameShape(QtWidgets.QFrame.HLine)
+ separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
+ grid1.addWidget(separator_line, 2, 0, 1, 2)
+
# ## Bounding box
self.boundingbox_label = QtWidgets.QLabel('%s:' % _('Bounding Box'))
self.layout.addWidget(self.boundingbox_label)
@@ -1634,6 +1667,11 @@ class GerberAdvOptPrefGroupUI(OptionsGroupUI):
)
grid0.addWidget(self.aperture_table_visibility_cb, 1, 0, 1, 2)
+ separator_line = QtWidgets.QFrame()
+ separator_line.setFrameShape(QtWidgets.QFrame.HLine)
+ separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
+ grid0.addWidget(separator_line, 2, 0, 1, 2)
+
# Tool Type
self.tool_type_label = QtWidgets.QLabel('%s' % _('Tool Type'))
self.tool_type_label.setToolTip(
@@ -1645,8 +1683,8 @@ class GerberAdvOptPrefGroupUI(OptionsGroupUI):
self.tool_type_radio = RadioSet([{'label': 'Circular', 'value': 'circular'},
{'label': 'V-Shape', 'value': 'v'}])
- grid0.addWidget(self.tool_type_label, 2, 0)
- grid0.addWidget(self.tool_type_radio, 2, 1, 1, 2)
+ grid0.addWidget(self.tool_type_label, 3, 0)
+ grid0.addWidget(self.tool_type_radio, 3, 1, 1, 2)
# Tip Dia
self.tipdialabel = QtWidgets.QLabel('%s:' % _('V-Tip Dia'))
@@ -1658,8 +1696,8 @@ class GerberAdvOptPrefGroupUI(OptionsGroupUI):
self.tipdia_spinner.set_range(-99.9999, 99.9999)
self.tipdia_spinner.setSingleStep(0.1)
self.tipdia_spinner.setWrapping(True)
- grid0.addWidget(self.tipdialabel, 3, 0)
- grid0.addWidget(self.tipdia_spinner, 3, 1, 1, 2)
+ grid0.addWidget(self.tipdialabel, 4, 0)
+ grid0.addWidget(self.tipdia_spinner, 4, 1, 1, 2)
# Tip Angle
self.tipanglelabel = QtWidgets.QLabel('%s:' % _('V-Tip Angle'))
@@ -1671,8 +1709,8 @@ class GerberAdvOptPrefGroupUI(OptionsGroupUI):
self.tipangle_spinner.set_range(0, 180)
self.tipangle_spinner.setSingleStep(5)
self.tipangle_spinner.setWrapping(True)
- grid0.addWidget(self.tipanglelabel, 4, 0)
- grid0.addWidget(self.tipangle_spinner, 4, 1, 1, 2)
+ grid0.addWidget(self.tipanglelabel, 5, 0)
+ grid0.addWidget(self.tipangle_spinner, 5, 1, 1, 2)
# Cut Z
self.cutzlabel = QtWidgets.QLabel('%s:' % _('Cut Z'))
@@ -1686,8 +1724,8 @@ class GerberAdvOptPrefGroupUI(OptionsGroupUI):
self.cutz_spinner.setSingleStep(0.1)
self.cutz_spinner.setWrapping(True)
- grid0.addWidget(self.cutzlabel, 5, 0)
- grid0.addWidget(self.cutz_spinner, 5, 1, 1, 2)
+ grid0.addWidget(self.cutzlabel, 6, 0)
+ grid0.addWidget(self.cutz_spinner, 6, 1, 1, 2)
# Isolation Type
self.iso_type_label = QtWidgets.QLabel('%s:' % _('Isolation Type'))
@@ -1705,8 +1743,13 @@ class GerberAdvOptPrefGroupUI(OptionsGroupUI):
{'label': _('Exterior'), 'value': 'ext'},
{'label': _('Interior'), 'value': 'int'}])
- grid0.addWidget(self.iso_type_label, 6, 0,)
- grid0.addWidget(self.iso_type_radio, 6, 1, 1, 2)
+ grid0.addWidget(self.iso_type_label, 7, 0,)
+ grid0.addWidget(self.iso_type_radio, 7, 1, 1, 2)
+
+ separator_line = QtWidgets.QFrame()
+ separator_line.setFrameShape(QtWidgets.QFrame.HLine)
+ separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
+ grid0.addWidget(separator_line, 8, 0, 1, 2)
# Buffering Type
buffering_label = QtWidgets.QLabel('%s:' % _('Buffering'))
@@ -1718,8 +1761,8 @@ class GerberAdvOptPrefGroupUI(OptionsGroupUI):
)
self.buffering_radio = RadioSet([{'label': _('None'), 'value': 'no'},
{'label': _('Full'), 'value': 'full'}])
- grid0.addWidget(buffering_label, 7, 0)
- grid0.addWidget(self.buffering_radio, 7, 1)
+ grid0.addWidget(buffering_label, 9, 0)
+ grid0.addWidget(self.buffering_radio, 9, 1)
# Simplification
self.simplify_cb = FCCheckBox(label=_('Simplify'))
@@ -1728,7 +1771,7 @@ class GerberAdvOptPrefGroupUI(OptionsGroupUI):
"loaded with simplification having a set tolerance.\n"
"<>: Don't change this unless you know what you are doing !!!")
)
- grid0.addWidget(self.simplify_cb, 8, 0, 1, 2)
+ grid0.addWidget(self.simplify_cb, 10, 0, 1, 2)
# Simplification tolerance
self.simplification_tol_label = QtWidgets.QLabel(_('Tolerance'))
@@ -1740,8 +1783,8 @@ class GerberAdvOptPrefGroupUI(OptionsGroupUI):
self.simplification_tol_spinner.setRange(0.00000, 0.01000)
self.simplification_tol_spinner.setSingleStep(0.0001)
- grid0.addWidget(self.simplification_tol_label, 9, 0)
- grid0.addWidget(self.simplification_tol_spinner, 9, 1)
+ grid0.addWidget(self.simplification_tol_label, 11, 0)
+ grid0.addWidget(self.simplification_tol_spinner, 11, 1)
self.ois_simplif = OptionalInputSection(
self.simplify_cb,
[
diff --git a/flatcamParsers/ParseGerber.py b/flatcamParsers/ParseGerber.py
index 1615f000..f8829c5c 100644
--- a/flatcamParsers/ParseGerber.py
+++ b/flatcamParsers/ParseGerber.py
@@ -72,6 +72,8 @@ class Gerber(Geometry):
# "use_buffer_for_union": True
# }
+ app = None
+
def __init__(self, steps_per_circle=None):
"""
The constructor takes no parameters. Use ``gerber.parse_files()``
@@ -1412,14 +1414,7 @@ class Gerber(Geometry):
if current_polarity == 'D':
self.app.inform.emit('%s' % _("Gerber processing. Applying Gerber polarity."))
if new_poly.is_valid:
- # self.solid_geometry = self.solid_geometry.union(new_poly)
- # FIX for issue #347 - Sprint Layout generate strange Gerber files when the copper pour is enabled
- # it use a filled bounding box polygon to which add clear polygons (negative) to isolate the copper
- # features
- candidate_geo = list()
- for p in self.solid_geometry.union(new_poly):
- candidate_geo.append(p.buffer(-0.0000001))
- self.solid_geometry = candidate_geo
+ self.solid_geometry = self.solid_geometry.union(new_poly)
else:
# I do this so whenever the parsed geometry of the file is not valid (intersections) it is still
# loaded. Instead of applying a union I add to a list of polygons.
@@ -1438,6 +1433,15 @@ class Gerber(Geometry):
self.solid_geometry = final_poly
+ # FIX for issue #347 - Sprint Layout generate strange Gerber files when the copper pour is enabled
+ # it use a filled bounding box polygon to which add clear polygons (negative) to isolate the copper
+ # features
+ if self.app.defaults['gerber_extra_buffering']:
+ candidate_geo = list()
+ for p in self.solid_geometry:
+ candidate_geo.append(p.buffer(0.0000001))
+ self.solid_geometry = candidate_geo
+
# try:
# self.solid_geometry = self.solid_geometry.union(new_poly)
# except Exception as e:
@@ -1450,6 +1454,12 @@ class Gerber(Geometry):
else:
self.solid_geometry = self.solid_geometry.difference(new_poly)
+ if self.app.defaults['gerber_clean_apertures']:
+ # clean the Gerber file of apertures with no geometry
+ for apid, apvalue in list(self.apertures.items()):
+ if 'geometry' not in apvalue:
+ self.apertures.pop(apid)
+
# init this for the following operations
self.conversion_done = False
except Exception as err: