- In Gerber isolation changed the UI
- in Gerber isolation added the option to selectively isolate only certain polygons
This commit is contained in:
parent
aac4fd75ca
commit
d5a9e0bb5a
|
@ -523,6 +523,7 @@ class App(QtCore.QObject):
|
|||
"gerber_isooverlap": 0.00393701,
|
||||
"gerber_milling_type": "cl",
|
||||
"gerber_combine_passes": False,
|
||||
"gerber_iso_scope": 'all',
|
||||
"gerber_noncoppermargin": 0.00393701,
|
||||
"gerber_noncopperrounded": False,
|
||||
"gerber_bboxmargin": 0.00393701,
|
||||
|
@ -537,6 +538,7 @@ class App(QtCore.QObject):
|
|||
"gerber_vtipdia": 0.1,
|
||||
"gerber_vtipangle": 30,
|
||||
"gerber_vcutz": -0.05,
|
||||
"gerber_iso_type": "full",
|
||||
"gerber_buffering": "full",
|
||||
"gerber_simplification": False,
|
||||
"gerber_simp_tolerance": 0.0005,
|
||||
|
@ -1077,6 +1079,7 @@ class App(QtCore.QObject):
|
|||
"gerber_isopasses": self.ui.gerber_defaults_form.gerber_opt_group.iso_width_entry,
|
||||
"gerber_isooverlap": self.ui.gerber_defaults_form.gerber_opt_group.iso_overlap_entry,
|
||||
"gerber_combine_passes": self.ui.gerber_defaults_form.gerber_opt_group.combine_passes_cb,
|
||||
"gerber_iso_scope": self.ui.gerber_defaults_form.gerber_opt_group.iso_scope_radio,
|
||||
"gerber_milling_type": self.ui.gerber_defaults_form.gerber_opt_group.milling_type_radio,
|
||||
"gerber_noncoppermargin": self.ui.gerber_defaults_form.gerber_opt_group.noncopper_margin_entry,
|
||||
"gerber_noncopperrounded": self.ui.gerber_defaults_form.gerber_opt_group.noncopper_rounded_cb,
|
||||
|
@ -1092,6 +1095,7 @@ class App(QtCore.QObject):
|
|||
"gerber_vtipdia": self.ui.gerber_defaults_form.gerber_adv_opt_group.tipdia_spinner,
|
||||
"gerber_vtipangle": self.ui.gerber_defaults_form.gerber_adv_opt_group.tipangle_spinner,
|
||||
"gerber_vcutz": self.ui.gerber_defaults_form.gerber_adv_opt_group.cutz_spinner,
|
||||
"gerber_iso_type": self.ui.gerber_defaults_form.gerber_adv_opt_group.iso_type_radio,
|
||||
|
||||
"gerber_buffering": self.ui.gerber_defaults_form.gerber_adv_opt_group.buffering_radio,
|
||||
"gerber_simplification": self.ui.gerber_defaults_form.gerber_adv_opt_group.simplify_cb,
|
||||
|
@ -2424,6 +2428,9 @@ class App(QtCore.QObject):
|
|||
# decide if we have a double click or single click
|
||||
self.doubleclick = False
|
||||
|
||||
# store here the is_dragging value
|
||||
self.event_is_dragging = False
|
||||
|
||||
# variable to store if a command is active (then the var is not None) and which one it is
|
||||
self.command_active = None
|
||||
# variable to store the status of moving selection action
|
||||
|
@ -8337,7 +8344,7 @@ class App(QtCore.QObject):
|
|||
pan_button = 2
|
||||
else:
|
||||
pan_button = 3
|
||||
event_is_dragging = event.is_dragging
|
||||
self.event_is_dragging = event.is_dragging
|
||||
else:
|
||||
event_pos = (event.xdata, event.ydata)
|
||||
# Matplotlib has the middle and right buttons mapped in reverse compared with VisPy
|
||||
|
@ -8345,7 +8352,7 @@ class App(QtCore.QObject):
|
|||
pan_button = 3
|
||||
else:
|
||||
pan_button = 2
|
||||
event_is_dragging = self.plotcanvas.is_dragging
|
||||
self.event_is_dragging = self.plotcanvas.is_dragging
|
||||
|
||||
# So it can receive key presses
|
||||
self.plotcanvas.native.setFocus()
|
||||
|
@ -8355,7 +8362,7 @@ class App(QtCore.QObject):
|
|||
|
||||
if not origin_click:
|
||||
# if the RMB is clicked and mouse is moving over plot then 'panning_action' is True
|
||||
if event.button == pan_button and event_is_dragging == 1:
|
||||
if event.button == pan_button and self.event_is_dragging == 1:
|
||||
self.ui.popMenu.mouse_is_panning = True
|
||||
return
|
||||
|
||||
|
@ -8383,7 +8390,7 @@ class App(QtCore.QObject):
|
|||
self.mouse = [pos[0], pos[1]]
|
||||
|
||||
# if the mouse is moved and the LMB is clicked then the action is a selection
|
||||
if event_is_dragging == 1 and event.button == 1:
|
||||
if self.event_is_dragging == 1 and event.button == 1:
|
||||
self.delete_selection_shape()
|
||||
if dx < 0:
|
||||
self.draw_moving_selection_shape(self.pos, pos, color=self.defaults['global_alt_sel_line'],
|
||||
|
|
222
FlatCAMObj.py
222
FlatCAMObj.py
|
@ -597,7 +597,9 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
|||
"bboxmargin": 0.0,
|
||||
"bboxrounded": False,
|
||||
"aperture_display": False,
|
||||
"follow": False
|
||||
"follow": False,
|
||||
"iso_scope": 'all',
|
||||
"iso_type": 'full'
|
||||
})
|
||||
|
||||
# type of isolation: 0 = exteriors, 1 = interiors, 2 = complete isolation (both interiors and exteriors)
|
||||
|
@ -618,6 +620,12 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
|||
# Number of decimals to be used by tools in this class
|
||||
self.decimals = 4
|
||||
|
||||
# Mouse events
|
||||
self.mr = self.app.mr
|
||||
|
||||
# list to store the polygons selected for isolation
|
||||
self.poly_list = list()
|
||||
|
||||
# Attributes to be included in serialization
|
||||
# Always append to it because it carries contents
|
||||
# from predecessors.
|
||||
|
@ -662,7 +670,9 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
|||
"bboxmargin": self.ui.bbmargin_entry,
|
||||
"bboxrounded": self.ui.bbrounded_cb,
|
||||
"aperture_display": self.ui.aperture_table_visibility_cb,
|
||||
"follow": self.ui.follow_cb
|
||||
"follow": self.ui.follow_cb,
|
||||
"iso_scope": self.ui.iso_scope_radio,
|
||||
"iso_type": self.ui.iso_type_radio
|
||||
})
|
||||
|
||||
# Fill form fields only on object create
|
||||
|
@ -672,8 +682,6 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
|||
self.ui.plot_cb.stateChanged.connect(self.on_plot_cb_click)
|
||||
self.ui.solid_cb.stateChanged.connect(self.on_solid_cb_click)
|
||||
self.ui.multicolored_cb.stateChanged.connect(self.on_multicolored_cb_click)
|
||||
self.ui.generate_ext_iso_button.clicked.connect(self.on_ext_iso_button_click)
|
||||
self.ui.generate_int_iso_button.clicked.connect(self.on_int_iso_button_click)
|
||||
self.ui.generate_iso_button.clicked.connect(self.on_iso_button_click)
|
||||
self.ui.generate_ncc_button.clicked.connect(self.app.ncclear_tool.run)
|
||||
self.ui.generate_cutout_button.clicked.connect(self.app.cutout_tool.run)
|
||||
|
@ -710,8 +718,8 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
|||
self.ui.aperture_table_visibility_cb.hide()
|
||||
self.ui.milling_type_label.hide()
|
||||
self.ui.milling_type_radio.hide()
|
||||
self.ui.generate_ext_iso_button.hide()
|
||||
self.ui.generate_int_iso_button.hide()
|
||||
self.ui.iso_type_radio.hide()
|
||||
|
||||
self.ui.follow_cb.hide()
|
||||
self.ui.except_cb.setChecked(False)
|
||||
self.ui.except_cb.hide()
|
||||
|
@ -978,42 +986,16 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
|||
|
||||
self.app.new_object("geometry", name, geo_init)
|
||||
|
||||
def on_ext_iso_button_click(self, *args):
|
||||
obj = self.app.collection.get_active()
|
||||
|
||||
def worker_task(obj, app_obj):
|
||||
with self.app.proc_container.new(_("Isolating...")):
|
||||
if self.ui.follow_cb.get_value() is True:
|
||||
obj.follow_geo()
|
||||
# in the end toggle the visibility of the origin object so we can see the generated Geometry
|
||||
obj.ui.plot_cb.toggle()
|
||||
else:
|
||||
app_obj.report_usage("gerber_on_iso_button")
|
||||
self.read_form()
|
||||
self.isolate(iso_type=0)
|
||||
|
||||
self.app.worker_task.emit({'fcn': worker_task, 'params': [obj, self.app]})
|
||||
|
||||
def on_int_iso_button_click(self, *args):
|
||||
obj = self.app.collection.get_active()
|
||||
|
||||
def worker_task(obj, app_obj):
|
||||
with self.app.proc_container.new(_("Isolating...")):
|
||||
if self.ui.follow_cb.get_value() is True:
|
||||
obj.follow_geo()
|
||||
# in the end toggle the visibility of the origin object so we can see the generated Geometry
|
||||
obj.ui.plot_cb.toggle()
|
||||
else:
|
||||
app_obj.report_usage("gerber_on_iso_button")
|
||||
self.read_form()
|
||||
self.isolate(iso_type=1)
|
||||
|
||||
self.app.worker_task.emit({'fcn': worker_task, 'params': [obj, self.app]})
|
||||
|
||||
def on_iso_button_click(self, *args):
|
||||
|
||||
obj = self.app.collection.get_active()
|
||||
|
||||
self.iso_type = 2
|
||||
if self.ui.iso_type_radio.get_value() == 'ext':
|
||||
self.iso_type = 0
|
||||
if self.ui.iso_type_radio.get_value() == 'int':
|
||||
self.iso_type = 1
|
||||
|
||||
def worker_task(obj, app_obj):
|
||||
with self.app.proc_container.new(_("Isolating...")):
|
||||
if self.ui.follow_cb.get_value() is True:
|
||||
|
@ -1023,7 +1005,9 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
|||
else:
|
||||
app_obj.report_usage("gerber_on_iso_button")
|
||||
self.read_form()
|
||||
self.isolate()
|
||||
|
||||
iso_scope = 'all' if self.ui.iso_scope_radio == 'all' else 'single'
|
||||
self.isolate_handler(iso_type=self.iso_type, iso_scope=iso_scope)
|
||||
|
||||
self.app.worker_task.emit({'fcn': worker_task, 'params': [obj, self.app]})
|
||||
|
||||
|
@ -1053,18 +1037,96 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
|||
except Exception as e:
|
||||
return "Operation failed: %s" % str(e)
|
||||
|
||||
def isolate(self, iso_type=None, dia=None, passes=None, overlap=None, outname=None, combine=None,
|
||||
def isolate_handler(self, iso_type, iso_scope):
|
||||
|
||||
if iso_scope == 'all':
|
||||
self.isolate(iso_type=iso_type)
|
||||
else:
|
||||
# disengage the grid snapping since it will be hard to find the drills on grid
|
||||
if self.app.ui.grid_snap_btn.isChecked():
|
||||
self.grid_status_memory = True
|
||||
self.app.ui.grid_snap_btn.trigger()
|
||||
else:
|
||||
self.grid_status_memory = False
|
||||
|
||||
self.mr = self.app.plotcanvas.graph_event_connect('mouse_release', self.on_mouse_click_release)
|
||||
|
||||
if self.app.is_legacy is False:
|
||||
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
|
||||
else:
|
||||
self.app.plotcanvas.graph_event_disconnect(self.app.mr)
|
||||
|
||||
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Click on polygon to isolate it."))
|
||||
|
||||
def on_mouse_click_release(self, event):
|
||||
if self.app.is_legacy is False:
|
||||
event_pos = event.pos
|
||||
event_is_dragging = event.is_dragging
|
||||
right_button = 2
|
||||
else:
|
||||
event_pos = (event.xdata, event.ydata)
|
||||
event_is_dragging = self.app.plotcanvas.is_dragging
|
||||
right_button = 3
|
||||
|
||||
try:
|
||||
x = float(event_pos[0])
|
||||
y = float(event_pos[1])
|
||||
except TypeError:
|
||||
return
|
||||
|
||||
event_pos = (x, y)
|
||||
curr_pos = self.app.plotcanvas.translate_coords(event_pos)
|
||||
|
||||
if event.button == 1:
|
||||
clicked_poly = self.find_polygon(point=(curr_pos[0], curr_pos[1]))
|
||||
|
||||
if clicked_poly:
|
||||
self.poly_list.append(clicked_poly)
|
||||
self.app.inform.emit(
|
||||
'%s: %d. %s' % (_("Added polygon"),
|
||||
int(len(self.poly_list)),
|
||||
_("Click to start adding next polygon or right click to start isolation."))
|
||||
)
|
||||
else:
|
||||
self.app.inform.emit(_("No polygon detected under click position. Try again."))
|
||||
|
||||
elif event.button == right_button and self.app.event_is_dragging is False:
|
||||
# restore the Grid snapping if it was active before
|
||||
if self.grid_status_memory is True:
|
||||
self.app.ui.grid_snap_btn.trigger()
|
||||
|
||||
if self.app.is_legacy is False:
|
||||
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.on_mouse_click_release)
|
||||
else:
|
||||
self.app.plotcanvas.graph_event_disconnect(self.mr)
|
||||
|
||||
self.app.mr = self.app.plotcanvas.graph_event_connect('mouse_release',
|
||||
self.app.on_mouse_click_release_over_plot)
|
||||
|
||||
self.isolate(iso_type=self.iso_type, geometry=self.poly_list)
|
||||
|
||||
def isolate(self, iso_type=None, geometry=None, dia=None, passes=None, overlap=None, outname=None, combine=None,
|
||||
milling_type=None, follow=None, plot=True):
|
||||
"""
|
||||
Creates an isolation routing geometry object in the project.
|
||||
|
||||
:param iso_type: type of isolation to be done: 0 = exteriors, 1 = interiors and 2 = both
|
||||
:param iso_scope: whether to isolate all polygons or single polygpns: 'all' = all, 'single' = one by one, single
|
||||
:param dia: Tool diameter
|
||||
:param passes: Number of tool widths to cut
|
||||
:param overlap: Overlap between passes in fraction of tool diameter
|
||||
:param outname: Base name of the output object
|
||||
:return: None
|
||||
"""
|
||||
|
||||
if geometry is None:
|
||||
if follow:
|
||||
work_geo = self.follow_geometry
|
||||
else:
|
||||
work_geo = self.solid_geometry
|
||||
else:
|
||||
work_geo = geometry
|
||||
|
||||
if dia is None:
|
||||
dia = float(self.options["isotooldia"])
|
||||
if passes is None:
|
||||
|
@ -1075,28 +1137,33 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
|||
combine = self.options["combine_passes"]
|
||||
else:
|
||||
combine = bool(combine)
|
||||
|
||||
if milling_type is None:
|
||||
milling_type = self.options["milling_type"]
|
||||
|
||||
if iso_type is None:
|
||||
self.iso_type = 2
|
||||
iso_t = 2
|
||||
else:
|
||||
self.iso_type = iso_type
|
||||
iso_t = iso_type
|
||||
|
||||
base_name = self.options["name"]
|
||||
|
||||
def generate_envelope(offset, invert, envelope_iso_type=2, follow=None, passes=0):
|
||||
def generate_envelope(offset, invert, geometry=None, env_iso_type=2, follow=None, nr_passes=0):
|
||||
# isolation_geometry produces an envelope that is going on the left of the geometry
|
||||
# (the copper features). To leave the least amount of burrs on the features
|
||||
# the tool needs to travel on the right side of the features (this is called conventional milling)
|
||||
# the first pass is the one cutting all of the features, so it needs to be reversed
|
||||
# the other passes overlap preceding ones and cut the left over copper. It is better for them
|
||||
# to cut on the right side of the left over copper i.e on the left side of the features.
|
||||
try:
|
||||
geom = self.isolation_geometry(offset, iso_type=envelope_iso_type, follow=follow, passes=passes)
|
||||
except Exception as e:
|
||||
log.debug('FlatCAMGerber.isolate().generate_envelope() --> %s' % str(e))
|
||||
return 'fail'
|
||||
|
||||
if follow:
|
||||
geom = self.isolation_geometry(offset, geometry=geometry, follow=follow)
|
||||
else:
|
||||
try:
|
||||
geom = self.isolation_geometry(offset, geometry=geometry, iso_type=env_iso_type, passes=nr_passes)
|
||||
except Exception as e:
|
||||
log.debug('FlatCAMGerber.isolate().generate_envelope() --> %s' % str(e))
|
||||
return 'fail'
|
||||
|
||||
if invert:
|
||||
try:
|
||||
|
@ -1121,24 +1188,6 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
|||
return 'fail'
|
||||
return geom
|
||||
|
||||
# if invert:
|
||||
# try:
|
||||
# if type(geom) is MultiPolygon:
|
||||
# pl = []
|
||||
# for p in geom:
|
||||
# if p is not None:
|
||||
# pl.append(Polygon(p.exterior.coords[::-1], p.interiors))
|
||||
# geom = MultiPolygon(pl)
|
||||
# elif type(geom) is Polygon and geom is not None:
|
||||
# geom = Polygon(geom.exterior.coords[::-1], geom.interiors)
|
||||
# else:
|
||||
# log.debug("FlatCAMGerber.isolate().generate_envelope() Error --> Unexpected Geometry %s" %
|
||||
# type(geom))
|
||||
# except Exception as e:
|
||||
# log.debug("FlatCAMGerber.isolate().generate_envelope() Error --> %s" % str(e))
|
||||
# return 'fail'
|
||||
# return geom
|
||||
|
||||
# if float(self.options["isotooldia"]) < 0:
|
||||
# self.options["isotooldia"] = -self.options["isotooldia"]
|
||||
|
||||
|
@ -1210,30 +1259,26 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
|||
iso_offset = dia * ((2 * i + 1) / 2.0) - (i * overlap * dia)
|
||||
|
||||
# if milling type is climb then the move is counter-clockwise around features
|
||||
if milling_type == 'cl':
|
||||
# geom = generate_envelope (offset, i == 0)
|
||||
geom = generate_envelope(iso_offset, 1, envelope_iso_type=self.iso_type, follow=follow,
|
||||
passes=i)
|
||||
else:
|
||||
geom = generate_envelope(iso_offset, 0, envelope_iso_type=self.iso_type, follow=follow,
|
||||
passes=i)
|
||||
mill_t = 1 if milling_type == 'cl' else 0
|
||||
geom = generate_envelope(iso_offset, mill_t, geometry=work_geo, env_iso_type=iso_t, follow=follow,
|
||||
nr_passes=i)
|
||||
|
||||
if geom == 'fail':
|
||||
app_obj.inform.emit('[ERROR_NOTCL] %s' %
|
||||
_("Isolation geometry could not be generated."))
|
||||
app_obj.inform.emit('[ERROR_NOTCL] %s' % _("Isolation geometry could not be generated."))
|
||||
return 'fail'
|
||||
geo_obj.solid_geometry.append(geom)
|
||||
|
||||
# transfer the Cut Z and Vtip and VAngle values in case that we use the V-Shape tool in Gerber UI
|
||||
if self.ui.tool_type_radio.get_value() == 'circular':
|
||||
new_cutz = self.app.defaults['geometry_cutz']
|
||||
new_vtipdia = self.app.defaults['geometry_vtipdia']
|
||||
new_vtipangle = self.app.defaults['geometry_vtipangle']
|
||||
tool_type = 'C1'
|
||||
else:
|
||||
if self.ui.tool_type_radio.get_value() == 'v':
|
||||
new_cutz = self.ui.cutz_spinner.get_value()
|
||||
new_vtipdia = self.ui.tipdia_spinner.get_value()
|
||||
new_vtipangle = self.ui.tipangle_spinner.get_value()
|
||||
tool_type = 'V'
|
||||
else:
|
||||
new_cutz = self.app.defaults['geometry_cutz']
|
||||
new_vtipdia = self.app.defaults['geometry_vtipdia']
|
||||
new_vtipangle = self.app.defaults['geometry_vtipangle']
|
||||
tool_type = 'C1'
|
||||
|
||||
# store here the default data for Geometry Data
|
||||
default_data = {}
|
||||
|
@ -1280,7 +1325,8 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
|||
# proceed with object creation, if there are empty and the number of them is the length
|
||||
# of the list then we have an empty solid_geometry which should raise a Custom Exception
|
||||
empty_cnt = 0
|
||||
if not isinstance(geo_obj.solid_geometry, list):
|
||||
if not isinstance(geo_obj.solid_geometry, list) and \
|
||||
not isinstance(geo_obj.solid_geometry, MultiPolygon):
|
||||
geo_obj.solid_geometry = [geo_obj.solid_geometry]
|
||||
|
||||
for g in geo_obj.solid_geometry:
|
||||
|
@ -1338,13 +1384,11 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
|||
geo_obj.options["cnctooldia"] = str(self.options["isotooldia"])
|
||||
|
||||
# if milling type is climb then the move is counter-clockwise around features
|
||||
if milling_type == 'cl':
|
||||
# geo_obj.solid_geometry = generate_envelope(offset, i == 0)
|
||||
geom = generate_envelope(offset, 1, envelope_iso_type=self.iso_type, follow=follow,
|
||||
passes=i)
|
||||
else:
|
||||
geom = generate_envelope(offset, 0, envelope_iso_type=self.iso_type, follow=follow,
|
||||
passes=i)
|
||||
mill_t = 1 if milling_type == 'cl' else 0
|
||||
mill_t = 1 if milling_type == 'cl' else 0
|
||||
geom = generate_envelope(offset, mill_t, geometry=work_geo, env_iso_type=iso_t, follow=follow,
|
||||
nr_passes=i)
|
||||
|
||||
if geom == 'fail':
|
||||
app_obj.inform.emit('[ERROR_NOTCL] %s' %
|
||||
_("Isolation geometry could not be generated."))
|
||||
|
|
|
@ -9,6 +9,11 @@ CAD program, and create G-Code for Isolation routing.
|
|||
|
||||
=================================================
|
||||
|
||||
25.11.2019
|
||||
|
||||
- In Gerber isolation changed the UI
|
||||
- in Gerber isolation added the option to selectively isolate only certain polygons
|
||||
|
||||
23.11.2019
|
||||
|
||||
- in Tool Fiducials added a new fiducial type: chess pattern
|
||||
|
|
109
camlib.py
109
camlib.py
|
@ -897,7 +897,7 @@ class Geometry(object):
|
|||
#
|
||||
# return self.flat_geometry, self.flat_geometry_rtree
|
||||
|
||||
def isolation_geometry(self, offset, iso_type=2, corner=None, follow=None, passes=0):
|
||||
def isolation_geometry(self, offset, geometry=None, iso_type=2, corner=None, follow=None, passes=0):
|
||||
"""
|
||||
Creates contours around geometry at a given
|
||||
offset distance.
|
||||
|
@ -916,73 +916,58 @@ class Geometry(object):
|
|||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
|
||||
geo_iso = []
|
||||
if offset == 0:
|
||||
if follow:
|
||||
geo_iso = self.follow_geometry
|
||||
else:
|
||||
geo_iso = self.solid_geometry
|
||||
geo_iso = list()
|
||||
|
||||
if follow:
|
||||
return geometry
|
||||
|
||||
if geometry:
|
||||
working_geo = geometry
|
||||
else:
|
||||
if follow:
|
||||
geo_iso = self.follow_geometry
|
||||
working_geo = self.solid_geometry
|
||||
|
||||
try:
|
||||
geo_len = len(working_geo)
|
||||
except TypeError:
|
||||
geo_len = 1
|
||||
|
||||
old_disp_number = 0
|
||||
pol_nr = 0
|
||||
# yet, it can be done by issuing an unary_union in the end, thus getting rid of the overlapping geo
|
||||
try:
|
||||
for pol in working_geo:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
if offset == 0:
|
||||
geo_iso.append(pol)
|
||||
else:
|
||||
corner_type = 1 if corner is None else corner
|
||||
geo_iso.append(pol.buffer(offset, int(int(self.geo_steps_per_circle) / 4), join_style=corner_type))
|
||||
pol_nr += 1
|
||||
disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 100]))
|
||||
|
||||
if old_disp_number < disp_number <= 100:
|
||||
self.app.proc_container.update_view_text(' %s %d: %d%%' %
|
||||
(_("Pass"), int(passes + 1), int(disp_number)))
|
||||
old_disp_number = disp_number
|
||||
except TypeError:
|
||||
# taking care of the case when the self.solid_geometry is just a single Polygon, not a list or a
|
||||
# MultiPolygon (not an iterable)
|
||||
if offset == 0:
|
||||
geo_iso.append(working_geo)
|
||||
else:
|
||||
# if isinstance(self.solid_geometry, list):
|
||||
# temp_geo = cascaded_union(self.solid_geometry)
|
||||
# else:
|
||||
# temp_geo = self.solid_geometry
|
||||
corner_type = 1 if corner is None else corner
|
||||
geo_iso.append(working_geo.buffer(offset, int(int(self.geo_steps_per_circle) / 4),
|
||||
join_style=corner_type))
|
||||
|
||||
# Remember: do not make a buffer for each element in the solid_geometry because it will cut into
|
||||
# other copper features
|
||||
# if corner is None:
|
||||
# geo_iso = temp_geo.buffer(offset, int(int(self.geo_steps_per_circle) / 4))
|
||||
# else:
|
||||
# geo_iso = temp_geo.buffer(offset, int(int(self.geo_steps_per_circle) / 4),
|
||||
# join_style=corner)
|
||||
|
||||
# variables to display the percentage of work done
|
||||
geo_len = 0
|
||||
try:
|
||||
for pol in self.solid_geometry:
|
||||
geo_len += 1
|
||||
except TypeError:
|
||||
geo_len = 1
|
||||
disp_number = 0
|
||||
old_disp_number = 0
|
||||
pol_nr = 0
|
||||
# yet, it can be done by issuing an unary_union in the end, thus getting rid of the overlapping geo
|
||||
try:
|
||||
for pol in self.solid_geometry:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise FlatCAMApp.GracefulException
|
||||
if corner is None:
|
||||
geo_iso.append(pol.buffer(offset, int(int(self.geo_steps_per_circle) / 4)))
|
||||
else:
|
||||
geo_iso.append(pol.buffer(offset, int(int(self.geo_steps_per_circle) / 4)),
|
||||
join_style=corner)
|
||||
pol_nr += 1
|
||||
disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 100]))
|
||||
|
||||
if old_disp_number < disp_number <= 100:
|
||||
self.app.proc_container.update_view_text(' %s %d: %d%%' %
|
||||
(_("Pass"), int(passes + 1), int(disp_number)))
|
||||
old_disp_number = disp_number
|
||||
except TypeError:
|
||||
# taking care of the case when the self.solid_geometry is just a single Polygon, not a list or a
|
||||
# MultiPolygon (not an iterable)
|
||||
if corner is None:
|
||||
geo_iso.append(self.solid_geometry.buffer(offset, int(int(self.geo_steps_per_circle) / 4)))
|
||||
else:
|
||||
geo_iso.append(self.solid_geometry.buffer(offset, int(int(self.geo_steps_per_circle) / 4)),
|
||||
join_style=corner)
|
||||
self.app.proc_container.update_view_text(' %s' % _("Buffering"))
|
||||
geo_iso = unary_union(geo_iso)
|
||||
self.app.proc_container.update_view_text(' %s' % _("Buffering"))
|
||||
geo_iso = unary_union(geo_iso)
|
||||
|
||||
self.app.proc_container.update_view_text('')
|
||||
# end of replaced block
|
||||
if follow:
|
||||
return geo_iso
|
||||
elif iso_type == 2:
|
||||
|
||||
if iso_type == 2:
|
||||
return geo_iso
|
||||
elif iso_type == 0:
|
||||
self.app.proc_container.update_view_text(' %s' % _("Get Exteriors"))
|
||||
|
|
|
@ -281,6 +281,7 @@ class GerberObjectUI(ObjectUI):
|
|||
self.custom_box.addLayout(grid1)
|
||||
grid1.setColumnStretch(0, 0)
|
||||
grid1.setColumnStretch(1, 1)
|
||||
grid1.setColumnStretch(2, 1)
|
||||
|
||||
# Tool Type
|
||||
self.tool_type_label = QtWidgets.QLabel('%s:' % _('Tool Type'))
|
||||
|
@ -290,8 +291,8 @@ class GerberObjectUI(ObjectUI):
|
|||
"When the 'V-shape' is selected then the tool\n"
|
||||
"diameter will depend on the chosen cut depth.")
|
||||
)
|
||||
self.tool_type_radio = RadioSet([{'label': 'Circular', 'value': 'circular'},
|
||||
{'label': 'V-Shape', 'value': 'v'}])
|
||||
self.tool_type_radio = RadioSet([{'label': _('Circular'), 'value': 'circular'},
|
||||
{'label': _('V-Shape'), 'value': 'v'}])
|
||||
|
||||
grid1.addWidget(self.tool_type_label, 0, 0)
|
||||
grid1.addWidget(self.tool_type_radio, 0, 1, 1, 2)
|
||||
|
@ -396,7 +397,7 @@ class GerberObjectUI(ObjectUI):
|
|||
grid1.addWidget(self.milling_type_radio, 7, 1, 1, 2)
|
||||
|
||||
# combine all passes CB
|
||||
self.combine_passes_cb = FCCheckBox(label=_('Combine Passes'))
|
||||
self.combine_passes_cb = FCCheckBox(label=_('Combine'))
|
||||
self.combine_passes_cb.setToolTip(
|
||||
_("Combine all passes into one object")
|
||||
)
|
||||
|
@ -406,15 +407,15 @@ class GerberObjectUI(ObjectUI):
|
|||
self.follow_cb.setToolTip(_("Generate a 'Follow' geometry.\n"
|
||||
"This means that it will cut through\n"
|
||||
"the middle of the trace."))
|
||||
grid1.addWidget(self.combine_passes_cb, 8, 0)
|
||||
|
||||
# avoid an area from isolation
|
||||
self.except_cb = FCCheckBox(label=_('Except'))
|
||||
grid1.addWidget(self.follow_cb, 8, 1)
|
||||
|
||||
self.except_cb.setToolTip(_("When the isolation geometry is generated,\n"
|
||||
"by checking this, the area of the object bellow\n"
|
||||
"will be subtracted from the isolation geometry."))
|
||||
|
||||
grid1.addWidget(self.combine_passes_cb, 8, 0)
|
||||
grid1.addWidget(self.follow_cb, 8, 1)
|
||||
grid1.addWidget(self.except_cb, 8, 2)
|
||||
|
||||
# ## Form Layout
|
||||
|
@ -454,8 +455,50 @@ class GerberObjectUI(ObjectUI):
|
|||
|
||||
form_layout.addRow(self.obj_label, self.obj_combo)
|
||||
|
||||
self.gen_iso_label = QtWidgets.QLabel("<b>%s</b>" % _("Generate Isolation Geometry"))
|
||||
self.gen_iso_label.setToolTip(
|
||||
# ---------------------------------------------- #
|
||||
# --------- Isolation scope -------------------- #
|
||||
# ---------------------------------------------- #
|
||||
self.iso_scope_label = QtWidgets.QLabel('%s:' % _('Scope'))
|
||||
self.iso_scope_label.setToolTip(
|
||||
_("Isolation scope. Choose what to isolate:\n"
|
||||
"- 'All' -> Isolate all the polygons in the object\n"
|
||||
"- 'Single' -> Isolate a single polygon.")
|
||||
)
|
||||
self.iso_scope_radio = RadioSet([{'label': _('All'), 'value': 'all'},
|
||||
{'label': _('Single'), 'value': 'single'}])
|
||||
|
||||
grid1.addWidget(self.iso_scope_label, 10, 0)
|
||||
grid1.addWidget(self.iso_scope_radio, 10, 1, 1, 2)
|
||||
|
||||
# ---------------------------------------------- #
|
||||
# --------- Isolation type -------------------- #
|
||||
# ---------------------------------------------- #
|
||||
self.iso_type_label = QtWidgets.QLabel('%s:' % _('Isolation Type'))
|
||||
self.iso_type_label.setToolTip(
|
||||
_("Choose how the isolation will be executed:\n"
|
||||
"- 'Full' -> complete isolation of polygons\n"
|
||||
"- 'Ext' -> will isolate only on the outside\n"
|
||||
"- 'Int' -> will isolate only on the inside\n"
|
||||
"'Exterior' isolation is almost always possible\n"
|
||||
"(with the right tool) but 'Interior'\n"
|
||||
"isolation can be done only when there is an opening\n"
|
||||
"inside of the polygon (e.g polygon is a 'doughnut' shape).")
|
||||
)
|
||||
self.iso_type_radio = RadioSet([{'label': _('Full'), 'value': 'full'},
|
||||
{'label': _('Ext'), 'value': 'ext'},
|
||||
{'label': _('Int'), 'value': 'int'}])
|
||||
|
||||
grid1.addWidget(self.iso_type_label, 11, 0)
|
||||
grid1.addWidget(self.iso_type_radio, 11, 1, 1, 2)
|
||||
|
||||
self.generate_iso_button = QtWidgets.QPushButton("%s" % _("Generate Isolation Geometry"))
|
||||
self.generate_iso_button.setStyleSheet("""
|
||||
QPushButton
|
||||
{
|
||||
font-weight: bold;
|
||||
}
|
||||
""")
|
||||
self.generate_iso_button.setToolTip(
|
||||
_("Create a Geometry object with toolpaths to cut \n"
|
||||
"isolation outside, inside or on both sides of the\n"
|
||||
"object. For a Gerber object outside means outside\n"
|
||||
|
@ -466,7 +509,7 @@ class GerberObjectUI(ObjectUI):
|
|||
"inside the actual Gerber feature, use a negative tool\n"
|
||||
"diameter above.")
|
||||
)
|
||||
grid1.addWidget(self.gen_iso_label, 10, 0, 1, 3)
|
||||
grid1.addWidget(self.generate_iso_button, 12, 0, 1, 3)
|
||||
|
||||
self.create_buffer_button = QtWidgets.QPushButton(_('Buffer Solid Geometry'))
|
||||
self.create_buffer_button.setToolTip(
|
||||
|
@ -475,48 +518,15 @@ class GerberObjectUI(ObjectUI):
|
|||
"Clicking this will create the buffered geometry\n"
|
||||
"required for isolation.")
|
||||
)
|
||||
grid1.addWidget(self.create_buffer_button, 11, 0, 1, 3)
|
||||
|
||||
self.generate_iso_button = QtWidgets.QPushButton(_('FULL Geo'))
|
||||
self.generate_iso_button.setToolTip(
|
||||
_("Create the Geometry Object\n"
|
||||
"for isolation routing. It contains both\n"
|
||||
"the interiors and exteriors geometry.")
|
||||
)
|
||||
grid1.addWidget(self.generate_iso_button, 12, 0)
|
||||
|
||||
hlay_1 = QtWidgets.QHBoxLayout()
|
||||
grid1.addLayout(hlay_1, 12, 1, 1, 2)
|
||||
|
||||
self.generate_ext_iso_button = QtWidgets.QPushButton(_('Ext Geo'))
|
||||
self.generate_ext_iso_button.setToolTip(
|
||||
_("Create the Geometry Object\n"
|
||||
"for isolation routing containing\n"
|
||||
"only the exteriors geometry.")
|
||||
)
|
||||
# self.generate_ext_iso_button.setMinimumWidth(100)
|
||||
hlay_1.addWidget(self.generate_ext_iso_button)
|
||||
|
||||
self.generate_int_iso_button = QtWidgets.QPushButton(_('Int Geo'))
|
||||
self.generate_int_iso_button.setToolTip(
|
||||
_("Create the Geometry Object\n"
|
||||
"for isolation routing containing\n"
|
||||
"only the interiors geometry.")
|
||||
)
|
||||
# self.generate_ext_iso_button.setMinimumWidth(90)
|
||||
hlay_1.addWidget(self.generate_int_iso_button)
|
||||
grid1.addWidget(self.create_buffer_button, 13, 0, 1, 2)
|
||||
|
||||
self.ohis_iso = OptionalHideInputSection(
|
||||
self.except_cb,
|
||||
[self.type_obj_combo, self.type_obj_combo_label, self.obj_combo, self.obj_label],
|
||||
logic=True
|
||||
)
|
||||
# when the follow checkbox is checked then the exteriors and interiors isolation generation buttons
|
||||
# are disabled as is doesn't make sense to have them enabled due of the nature of "follow"
|
||||
self.ois_iso = OptionalInputSection(self.follow_cb,
|
||||
[self.generate_int_iso_button, self.generate_ext_iso_button], logic=False)
|
||||
|
||||
grid1.addWidget(QtWidgets.QLabel(''), 13, 0)
|
||||
grid1.addWidget(QtWidgets.QLabel(''), 14, 0)
|
||||
|
||||
# ###########################################
|
||||
# ########## NEW GRID #######################
|
||||
|
@ -562,6 +572,11 @@ class GerberObjectUI(ObjectUI):
|
|||
grid2.addWidget(self.board_cutout_label, 2, 0)
|
||||
grid2.addWidget(self.generate_cutout_button, 2, 1)
|
||||
|
||||
separator_line = QtWidgets.QFrame()
|
||||
separator_line.setFrameShape(QtWidgets.QFrame.HLine)
|
||||
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||
grid2.addWidget(separator_line, 3, 0, 1, 2)
|
||||
|
||||
# ## Non-copper regions
|
||||
self.noncopper_label = QtWidgets.QLabel("<b>%s</b>" % _("Non-copper regions"))
|
||||
self.noncopper_label.setToolTip(
|
||||
|
@ -572,7 +587,7 @@ class GerberObjectUI(ObjectUI):
|
|||
"copper from a specified region.")
|
||||
)
|
||||
|
||||
grid2.addWidget(self.noncopper_label, 3, 0, 1, 2)
|
||||
grid2.addWidget(self.noncopper_label, 4, 0, 1, 2)
|
||||
|
||||
# Margin
|
||||
bmlabel = QtWidgets.QLabel('%s:' % _('Boundary Margin'))
|
||||
|
@ -588,8 +603,8 @@ class GerberObjectUI(ObjectUI):
|
|||
self.noncopper_margin_entry.set_precision(self.decimals)
|
||||
self.noncopper_margin_entry.setSingleStep(0.1)
|
||||
|
||||
grid2.addWidget(bmlabel, 4, 0)
|
||||
grid2.addWidget(self.noncopper_margin_entry, 4, 1)
|
||||
grid2.addWidget(bmlabel, 5, 0)
|
||||
grid2.addWidget(self.noncopper_margin_entry, 5, 1)
|
||||
|
||||
# Rounded corners
|
||||
self.noncopper_rounded_cb = FCCheckBox(label=_("Rounded Geo"))
|
||||
|
@ -599,8 +614,13 @@ class GerberObjectUI(ObjectUI):
|
|||
self.noncopper_rounded_cb.setMinimumWidth(90)
|
||||
|
||||
self.generate_noncopper_button = QtWidgets.QPushButton(_('Generate Geo'))
|
||||
grid2.addWidget(self.noncopper_rounded_cb, 5, 0)
|
||||
grid2.addWidget(self.generate_noncopper_button, 5, 1)
|
||||
grid2.addWidget(self.noncopper_rounded_cb, 6, 0)
|
||||
grid2.addWidget(self.generate_noncopper_button, 6, 1)
|
||||
|
||||
separator_line1 = QtWidgets.QFrame()
|
||||
separator_line1.setFrameShape(QtWidgets.QFrame.HLine)
|
||||
separator_line1.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||
grid2.addWidget(separator_line1, 7, 0, 1, 2)
|
||||
|
||||
# ## Bounding box
|
||||
self.boundingbox_label = QtWidgets.QLabel('<b>%s</b>' % _('Bounding Box'))
|
||||
|
@ -609,7 +629,7 @@ class GerberObjectUI(ObjectUI):
|
|||
"Square shape.")
|
||||
)
|
||||
|
||||
grid2.addWidget(self.boundingbox_label, 6, 0, 1, 2)
|
||||
grid2.addWidget(self.boundingbox_label, 8, 0, 1, 2)
|
||||
|
||||
bbmargin = QtWidgets.QLabel('%s:' % _('Boundary Margin'))
|
||||
bbmargin.setToolTip(
|
||||
|
@ -622,8 +642,8 @@ class GerberObjectUI(ObjectUI):
|
|||
self.bbmargin_entry.set_precision(self.decimals)
|
||||
self.bbmargin_entry.setSingleStep(0.1)
|
||||
|
||||
grid2.addWidget(bbmargin, 7, 0)
|
||||
grid2.addWidget(self.bbmargin_entry, 7, 1)
|
||||
grid2.addWidget(bbmargin, 9, 0)
|
||||
grid2.addWidget(self.bbmargin_entry, 9, 1)
|
||||
|
||||
self.bbrounded_cb = FCCheckBox(label=_("Rounded Geo"))
|
||||
self.bbrounded_cb.setToolTip(
|
||||
|
@ -638,9 +658,13 @@ class GerberObjectUI(ObjectUI):
|
|||
self.generate_bb_button.setToolTip(
|
||||
_("Generate the Geometry object.")
|
||||
)
|
||||
grid2.addWidget(self.bbrounded_cb, 8, 0)
|
||||
grid2.addWidget(self.generate_bb_button, 8, 1)
|
||||
grid2.addWidget(self.bbrounded_cb, 10, 0)
|
||||
grid2.addWidget(self.generate_bb_button, 10, 1)
|
||||
|
||||
separator_line2 = QtWidgets.QFrame()
|
||||
separator_line2.setFrameShape(QtWidgets.QFrame.HLine)
|
||||
separator_line2.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||
grid2.addWidget(separator_line2, 11, 0, 1, 2)
|
||||
|
||||
class ExcellonObjectUI(ObjectUI):
|
||||
"""
|
||||
|
|
|
@ -1344,9 +1344,10 @@ class GerberOptPrefGroupUI(OptionsGroupUI):
|
|||
_("Width of the isolation gap in\n"
|
||||
"number (integer) of tool widths.")
|
||||
)
|
||||
grid0.addWidget(passlabel, 1, 0)
|
||||
self.iso_width_entry = FCSpinner()
|
||||
self.iso_width_entry.setRange(1, 999)
|
||||
|
||||
grid0.addWidget(passlabel, 1, 0)
|
||||
grid0.addWidget(self.iso_width_entry, 1, 1)
|
||||
|
||||
# Pass overlap
|
||||
|
@ -1356,14 +1357,28 @@ class GerberOptPrefGroupUI(OptionsGroupUI):
|
|||
"Example:\n"
|
||||
"A value here of 0.25 means an overlap of 25%% from the tool diameter found above.")
|
||||
)
|
||||
grid0.addWidget(overlabel, 2, 0)
|
||||
self.iso_overlap_entry = FCDoubleSpinner()
|
||||
self.iso_overlap_entry.set_precision(3)
|
||||
self.iso_overlap_entry.setWrapping(True)
|
||||
self.iso_overlap_entry.setRange(0.000, 0.999)
|
||||
self.iso_overlap_entry.setSingleStep(0.1)
|
||||
|
||||
grid0.addWidget(overlabel, 2, 0)
|
||||
grid0.addWidget(self.iso_overlap_entry, 2, 1)
|
||||
|
||||
# Isolation Scope
|
||||
self.iso_scope_label = QtWidgets.QLabel('%s:' % _('Scope'))
|
||||
self.iso_scope_label.setToolTip(
|
||||
_("Isolation scope. Choose what to isolate:\n"
|
||||
"- 'All' -> Isolate all the polygons in the object\n"
|
||||
"- 'Single' -> Isolate a single polygon.")
|
||||
)
|
||||
self.iso_scope_radio = RadioSet([{'label': _('All'), 'value': 'all'},
|
||||
{'label': _('Single'), 'value': 'single'}])
|
||||
|
||||
grid0.addWidget(self.iso_scope_label, 3, 0)
|
||||
grid0.addWidget(self.iso_scope_radio, 3, 1, 1, 2)
|
||||
|
||||
# Milling Type
|
||||
milling_type_label = QtWidgets.QLabel('%s:' % _('Milling Type'))
|
||||
milling_type_label.setToolTip(
|
||||
|
@ -1371,17 +1386,17 @@ class GerberOptPrefGroupUI(OptionsGroupUI):
|
|||
"- climb / best for precision milling and to reduce tool usage\n"
|
||||
"- conventional / useful when there is no backlash compensation")
|
||||
)
|
||||
grid0.addWidget(milling_type_label, 3, 0)
|
||||
grid0.addWidget(milling_type_label, 4, 0)
|
||||
self.milling_type_radio = RadioSet([{'label': _('Climb'), 'value': 'cl'},
|
||||
{'label': _('Conv.'), 'value': 'cv'}])
|
||||
grid0.addWidget(self.milling_type_radio, 3, 1)
|
||||
grid0.addWidget(self.milling_type_radio, 4, 1)
|
||||
|
||||
# Combine passes
|
||||
self.combine_passes_cb = FCCheckBox(label=_('Combine Passes'))
|
||||
self.combine_passes_cb.setToolTip(
|
||||
_("Combine all passes into one object")
|
||||
)
|
||||
grid0.addWidget(self.combine_passes_cb, 4, 0, 1, 2)
|
||||
grid0.addWidget(self.combine_passes_cb, 5, 0, 1, 2)
|
||||
|
||||
# ## Clear non-copper regions
|
||||
self.clearcopper_label = QtWidgets.QLabel("<b>%s:</b>" % _("Non-copper regions"))
|
||||
|
@ -1537,9 +1552,29 @@ class GerberAdvOptPrefGroupUI(OptionsGroupUI):
|
|||
self.cutz_spinner.set_range(-99.9999, -0.0001)
|
||||
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)
|
||||
|
||||
# Isolation Type
|
||||
self.iso_type_label = QtWidgets.QLabel('%s:' % _('Isolation Type'))
|
||||
self.iso_type_label.setToolTip(
|
||||
_("Choose how the isolation will be executed:\n"
|
||||
"- 'Full' -> complete isolation of polygons\n"
|
||||
"- 'Ext' -> will isolate only on the outside\n"
|
||||
"- 'Int' -> will isolate only on the inside\n"
|
||||
"'Exterior' isolation is almost always possible\n"
|
||||
"(with the right tool) but 'Interior'\n"
|
||||
"isolation can be done only when there is an opening\n"
|
||||
"inside of the polygon (e.g polygon is a 'doughnut' shape).")
|
||||
)
|
||||
self.iso_type_radio = RadioSet([{'label': _('Full'), 'value': 'full'},
|
||||
{'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)
|
||||
|
||||
# Buffering Type
|
||||
buffering_label = QtWidgets.QLabel('%s:' % _('Buffering'))
|
||||
buffering_label.setToolTip(
|
||||
|
@ -1550,8 +1585,8 @@ class GerberAdvOptPrefGroupUI(OptionsGroupUI):
|
|||
)
|
||||
self.buffering_radio = RadioSet([{'label': _('None'), 'value': 'no'},
|
||||
{'label': _('Full'), 'value': 'full'}])
|
||||
grid0.addWidget(buffering_label, 6, 0)
|
||||
grid0.addWidget(self.buffering_radio, 6, 1)
|
||||
grid0.addWidget(buffering_label, 7, 0)
|
||||
grid0.addWidget(self.buffering_radio, 7, 1)
|
||||
|
||||
# Simplification
|
||||
self.simplify_cb = FCCheckBox(label=_('Simplify'))
|
||||
|
@ -1560,7 +1595,7 @@ class GerberAdvOptPrefGroupUI(OptionsGroupUI):
|
|||
"loaded with simplification having a set tolerance.\n"
|
||||
"<<WARNING>>: Don't change this unless you know what you are doing !!!")
|
||||
)
|
||||
grid0.addWidget(self.simplify_cb, 7, 0, 1, 2)
|
||||
grid0.addWidget(self.simplify_cb, 8, 0, 1, 2)
|
||||
|
||||
# Simplification tolerance
|
||||
self.simplification_tol_label = QtWidgets.QLabel(_('Tolerance'))
|
||||
|
@ -1572,11 +1607,14 @@ 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, 8, 0)
|
||||
grid0.addWidget(self.simplification_tol_spinner, 8, 1)
|
||||
self.ois_simplif = OptionalInputSection(self.simplify_cb,
|
||||
[self.simplification_tol_label, self.simplification_tol_spinner],
|
||||
logic=True)
|
||||
grid0.addWidget(self.simplification_tol_label, 9, 0)
|
||||
grid0.addWidget(self.simplification_tol_spinner, 9, 1)
|
||||
self.ois_simplif = OptionalInputSection(
|
||||
self.simplify_cb,
|
||||
[
|
||||
self.simplification_tol_label, self.simplification_tol_spinner
|
||||
],
|
||||
logic=True)
|
||||
|
||||
self.layout.addStretch()
|
||||
|
||||
|
|
Loading…
Reference in New Issue