- added a setting in Preferences -> Gerber -> Gerber General named Buffering. If set to 'no' the Gerber objects load a lot more faster (perhaps 10 times faster than when set to 'full') but the visual look is not so great as all the aperture polygons can be seen

This commit is contained in:
Marius Stanciu 2019-09-09 02:41:14 +03:00 committed by Marius
parent c78404b737
commit 198e055328
6 changed files with 108 additions and 19 deletions

View File

@ -423,6 +423,7 @@ class App(QtCore.QObject):
"gerber_solid": self.ui.gerber_defaults_form.gerber_gen_group.solid_cb,
"gerber_multicolored": self.ui.gerber_defaults_form.gerber_gen_group.multicolored_cb,
"gerber_circle_steps": self.ui.gerber_defaults_form.gerber_gen_group.circle_steps_entry,
"gerber_buffering": self.ui.gerber_defaults_form.gerber_gen_group.buffering_radio,
# Gerber Options
"gerber_isotooldia": self.ui.gerber_defaults_form.gerber_opt_group.iso_tool_dia_entry,
@ -824,19 +825,20 @@ class App(QtCore.QObject):
"gerber_plot": True,
"gerber_solid": True,
"gerber_multicolored": False,
"gerber_circle_steps": 128,
"gerber_use_buffer_for_union": True,
"gerber_buffering": "full",
# Gerber Options
"gerber_isotooldia": 0.00787402,
"gerber_isopasses": 1,
"gerber_isooverlap": 0.00393701,
# Gerber Options
"gerber_combine_passes": False,
"gerber_milling_type": "cl",
"gerber_combine_passes": False,
"gerber_noncoppermargin": 0.00393701,
"gerber_noncopperrounded": False,
"gerber_bboxmargin": 0.00393701,
"gerber_bboxrounded": False,
"gerber_circle_steps": 128,
"gerber_use_buffer_for_union": True,
# Gerber Advanced Options
"gerber_aperture_display": False,
@ -3724,6 +3726,17 @@ class App(QtCore.QObject):
# Icon and title
self.setWindowIcon(parent.app_icon)
self.setWindowTitle("FlatCAM")
# self.setStyleSheet("background-image: url(share/flatcam_icon256.png); background-attachment: fixed")
# self.setStyleSheet(
# "border-image: url(share/flatcam_icon256.png) 0 0 0 0 stretch stretch; "
# "background-attachment: fixed"
# )
# bgimage = QtGui.QImage('share/flatcam_icon256.png')
# s_bgimage = bgimage.scaled(QtCore.QSize(self.frameGeometry().width(), self.frameGeometry().height()))
# palette = QtGui.QPalette()
# palette.setBrush(10, QtGui.QBrush(bgimage)) # 10 = Windowrole
# self.setPalette(palette)
layout1 = QtWidgets.QVBoxLayout()
self.setLayout(layout1)

View File

@ -9,6 +9,11 @@ CAD program, and create G-Code for Isolation routing.
=================================================
9.09.2019
- changed the triangulation type in VisPyVisuals for ShapeCollectionVisual class
- added a setting in Preferences -> Gerber -> Gerber General named Buffering. If set to 'no' the Gerber objects load a lot more faster (perhaps 10 times faster than when set to 'full') but the visual look is not so great as all the aperture polygons can be seen
8.09.2019
- added some documentation strings for methods in FlatCAMApp.App class

View File

@ -2368,6 +2368,8 @@ class Gerber (Geometry):
# ### Parsing starts here ## ##
line_num = 0
gline = ""
self.app.inform.emit('%s %d %s.' % (_("Gerber processing. Parsing"), len(glines), _("lines")))
try:
for gline in glines:
if self.app.abort_flag:
@ -3277,18 +3279,21 @@ class Gerber (Geometry):
self.follow_geometry = follow_buffer
# this treats the case when we are storing geometry as solids
log.warning("Joining %d polygons." % len(poly_buffer))
if len(poly_buffer) == 0:
log.error("Object is not Gerber file or empty. Aborting Object creation.")
return 'fail'
log.warning("Joining %d polygons." % len(poly_buffer))
self.app.inform.emit('%s %d %s.' % (_("Gerber processing. Joining"), len(poly_buffer), _("polygons")))
if self.use_buffer_for_union:
log.debug("Union by buffer...")
new_poly = MultiPolygon(poly_buffer)
new_poly = new_poly.buffer(0.00000001)
new_poly = new_poly.buffer(-0.00000001)
if self.app.defaults["gerber_buffering"] == 'full':
new_poly = new_poly.buffer(0.00000001)
new_poly = new_poly.buffer(-0.00000001)
log.warning("Union(buffer) done.")
else:
log.debug("Union by union()...")
@ -3299,15 +3304,15 @@ class Gerber (Geometry):
self.solid_geometry = self.solid_geometry.union(new_poly)
else:
self.solid_geometry = self.solid_geometry.difference(new_poly)
except Exception as err:
ex_type, ex, tb = sys.exc_info()
traceback.print_tb(tb)
# print traceback.format_exc()
log.error("Gerber PARSING FAILED. Line %d: %s" % (line_num, gline))
loc = 'Gerber Line #%d Gerber Line Content: %s\n' % (line_num, gline) + repr(err)
self.app.inform.emit(_("[ERROR]Gerber Parser ERROR.\n%s:") % loc)
loc = '%s #%d %s: %s\n' % (_("Gerber Line"), line_num, _("Gerber Line Content"), gline) + repr(err)
self.app.inform.emit('[ERROR] %s\n%s:' % (_("Gerber Parser ERROR"), loc))
@staticmethod
def create_flash_geometry(location, aperture, steps_per_circle=None):

View File

@ -4314,10 +4314,23 @@ class GerberGenPrefGroupUI(OptionsGroupUI):
_("The number of circle steps for Gerber \n"
"circular aperture linear approximation.")
)
grid0.addWidget(self.circle_steps_label, 1, 0)
self.circle_steps_entry = IntEntry()
grid0.addWidget(self.circle_steps_label, 1, 0)
grid0.addWidget(self.circle_steps_entry, 1, 1)
# Milling Type
buffering_label = QtWidgets.QLabel('%s:' % _('Buffering'))
buffering_label.setToolTip(
_("Buffering type:\n"
"- None --> best performance, fast file loading but no so good display\n"
"- Full --> slow file loading but good visuals. This is the default.\n"
"<<WARNING>>: Don't change this unless you know what you are doing !!!")
)
self.buffering_radio = RadioSet([{'label': _('None'), 'value': 'no'},
{'label': _('Full'), 'value': 'full'}])
grid0.addWidget(buffering_label, 2, 0)
grid0.addWidget(self.buffering_radio, 2, 1)
self.layout.addStretch()
@ -4370,6 +4383,7 @@ class GerberOptPrefGroupUI(OptionsGroupUI):
self.iso_overlap_entry = FloatEntry()
grid0.addWidget(self.iso_overlap_entry, 2, 1)
# Milling Type
milling_type_label = QtWidgets.QLabel('%s:' % _('Milling Type'))
milling_type_label.setToolTip(
_("Milling type:\n"

View File

@ -187,7 +187,7 @@ class ShapeGroup(object):
class ShapeCollectionVisual(CompoundVisual):
def __init__(self, line_width=1, triangulation='gpc', layers=3, pool=None, **kwargs):
def __init__(self, line_width=1, triangulation='vispy', layers=3, pool=None, **kwargs):
"""
Represents collection of shapes to draw on VisPy scene
:param line_width: float

View File

@ -1515,7 +1515,13 @@ class NonCopperClear(FlatCAMTool, Gerber):
self.app.inform.emit(_("NCC Tool. Calculate 'empty' area."))
if isinstance(ncc_obj, FlatCAMGerber) and not isotooldia:
sol_geo = ncc_obj.solid_geometry
# unfortunately for this function to work time efficient,
# if the Gerber was loaded without buffering then it require the buffering now.
if self.app.defaults['gerber_buffering'] == 'no':
sol_geo = ncc_obj.solid_geometry.buffer(0)
else:
sol_geo = ncc_obj.solid_geometry
if has_offset is True:
app_obj.inform.emit('[WARNING_NOTCL] %s ...' %
_("Buffering"))
@ -1523,9 +1529,17 @@ class NonCopperClear(FlatCAMTool, Gerber):
app_obj.inform.emit('[success] %s ...' %
_("Buffering finished"))
empty = self.get_ncc_empty_area(target=sol_geo, boundary=bounding_box)
if empty == 'fail':
return 'fail'
elif isinstance(ncc_obj, FlatCAMGerber) and isotooldia:
isolated_geo = []
self.solid_geometry = ncc_obj.solid_geometry
# unfortunately for this function to work time efficient,
# if the Gerber was loaded without buffering then it require the buffering now.
if self.app.defaults['gerber_buffering'] == 'no':
self.solid_geometry = ncc_obj.solid_geometry.buffer(0)
else:
self.solid_geometry = ncc_obj.solid_geometry
# if milling type is climb then the move is counter-clockwise around features
milling_type = self.milling_type_radio.get_value()
@ -1609,6 +1623,9 @@ class NonCopperClear(FlatCAMTool, Gerber):
app_obj.inform.emit('[success] %s ...' %
_("Buffering finished"))
empty = self.get_ncc_empty_area(target=sol_geo, boundary=bounding_box)
if empty == 'fail':
return 'fail'
elif isinstance(ncc_obj, FlatCAMGeometry):
sol_geo = cascaded_union(ncc_obj.solid_geometry)
if has_offset is True:
@ -1618,6 +1635,9 @@ class NonCopperClear(FlatCAMTool, Gerber):
app_obj.inform.emit('[success] %s ...' %
_("Buffering finished"))
empty = self.get_ncc_empty_area(target=sol_geo, boundary=bounding_box)
if empty == 'fail':
return 'fail'
else:
app_obj.inform.emit('[ERROR_NOTCL] %s' %
_('The selected object is not suitable for copper clearing.'))
@ -1832,6 +1852,8 @@ class NonCopperClear(FlatCAMTool, Gerber):
app_obj.inform.emit('[success] %s ...' %
_("Buffering finished"))
empty = self.get_ncc_empty_area(target=sol_geo, boundary=bounding_box)
if empty == 'fail':
return 'fail'
elif isinstance(ncc_obj, FlatCAMGerber) and isotooldia:
isolated_geo = []
@ -1922,6 +1944,8 @@ class NonCopperClear(FlatCAMTool, Gerber):
app_obj.inform.emit('[success] %s ...' %
_("Buffering finished"))
empty = self.get_ncc_empty_area(target=sol_geo, boundary=bounding_box)
if empty == 'fail':
return 'fail'
elif isinstance(ncc_obj, FlatCAMGeometry):
sol_geo = cascaded_union(ncc_obj.solid_geometry)
@ -1932,7 +1956,8 @@ class NonCopperClear(FlatCAMTool, Gerber):
app_obj.inform.emit('[success] %s ...' %
_("Buffering finished"))
empty = self.get_ncc_empty_area(target=sol_geo, boundary=bounding_box)
if empty == 'fail':
return 'fail'
else:
app_obj.inform.emit('[ERROR_NOTCL] %s' %
_('The selected object is not suitable for copper clearing.'))
@ -2509,16 +2534,43 @@ class NonCopperClear(FlatCAMTool, Gerber):
# # Background
# self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
@staticmethod
def get_ncc_empty_area(target, boundary=None):
def get_ncc_empty_area(self, target, boundary=None):
"""
Returns the complement of target geometry within
the given boundary polygon. If not specified, it defaults to
the rectangular bounding box of target geometry.
"""
geo_len = len(target)
pol_nr = 0
old_disp_number = 0
if boundary is None:
boundary = target.envelope
return boundary.difference(target)
else:
boundary = boundary
try:
ret_val = boundary.difference(target)
except Exception as e:
try:
for el in target:
if self.app.abort_flag:
# graceful abort requested by the user
raise FlatCAMApp.GracefulException
boundary = boundary.difference(el)
pol_nr += 1
disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 99]))
if disp_number > old_disp_number and disp_number <= 100:
self.app.proc_container.update_view_text(' %d%%' % disp_number)
old_disp_number = disp_number
return boundary
except Exception as e:
self.app.inform.emit('[ERROR_NOTCL] %s' %
_("Try to use the Buffering Type = Full in Preferences -> Gerber General. "
"Reload the Gerber file after this change."))
return 'fail'
return ret_val
def reset_fields(self):
self.object_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))