- 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:
parent
c78404b737
commit
198e055328
@ -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)
|
||||
|
@ -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
|
||||
|
17
camlib.py
17
camlib.py
@ -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):
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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()))
|
||||
|
Loading…
Reference in New Issue
Block a user