- added new FlatCAM Tool: Corner Markers Tool which will add line markers in the selected corners of the bounding box of the targeted Gerber object

This commit is contained in:
Marius Stanciu 2020-05-17 03:27:26 +03:00 committed by Marius
parent fa33a5f487
commit 28f0c9c276
13 changed files with 615 additions and 69 deletions

View File

@ -7,6 +7,10 @@ CHANGELOG for FlatCAM beta
=================================================
17.05.2020
- added new FlatCAM Tool: Corner Markers Tool which will add line markers in the selected corners of the bounding box of the targeted Gerber object
16.05.2020
- worked on the NCC Tool; added a new clear method named 'Combo' which will go through all methods until the clear is done

View File

@ -1387,6 +1387,7 @@ class App(QtCore.QObject):
self.align_objects_tool = None
self.punch_tool = None
self.invert_tool = None
self.corners_tool = None
# always install tools only after the shell is initialized because the self.inform.emit() depends on shell
try:
@ -1975,6 +1976,9 @@ class App(QtCore.QObject):
self.invert_tool = ToolInvertGerber(self)
self.invert_tool.install(icon=QtGui.QIcon(self.resource_location + '/invert32.png'), pos=self.ui.menutool)
self.corners_tool = ToolCorners(self)
self.corners_tool.install(icon=QtGui.QIcon(self.resource_location + '/corners_32.png'), pos=self.ui.menutool)
self.transform_tool = ToolTransform(self)
self.transform_tool.install(icon=QtGui.QIcon(self.resource_location + '/transform.png'),
pos=self.ui.menuoptions, separator=True)
@ -2125,6 +2129,7 @@ class App(QtCore.QObject):
self.ui.fiducials_btn.triggered.connect(lambda: self.fiducial_tool.run(toggle=True))
self.ui.punch_btn.triggered.connect(lambda: self.punch_tool.run(toggle=True))
self.ui.invert_btn.triggered.connect(lambda: self.invert_tool.run(toggle=True))
self.ui.corners_tool_btn.triggered.connect(lambda: self.corners_tool.run(toggle=True))
def object2editor(self):
"""

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 B

View File

@ -525,6 +525,12 @@ class FlatCAMDefaults:
# Distance Tool
"tools_dist_snap_center": False,
# Corner Markers Tool
"tools_corners_thickness": 0.1,
"tools_corners_length": 3.0,
"tools_corners_margin": 0.0,
# ########################################################################################################
# ################################ TOOLS 2 ###############################################################
# ########################################################################################################

View File

@ -954,6 +954,8 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
QtGui.QIcon(self.app.resource_location + '/punch32.png'), _("Punch Gerber Tool"))
self.invert_btn = self.toolbartools.addAction(
QtGui.QIcon(self.app.resource_location + '/invert32.png'), _("Invert Gerber Tool"))
self.corners_tool_btn = self.toolbartools.addAction(
QtGui.QIcon(self.app.resource_location + '/corners_32.png'), _("Corner Markers Tool"))
# ########################################################################
# ########################## Excellon Editor Toolbar# ####################
@ -1612,6 +1614,10 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
<td height="20"><strong>Alt+L</strong></td>
<td>&nbsp;%s</td>
</tr>
<tr height="20">
<td height="20"><strong>Alt+M</strong></td>
<td>&nbsp;%s</td>
</tr>
<tr height="20">
<td height="20"><strong>Alt+N</strong></td>
<td>&nbsp;%s</td>
@ -1742,7 +1748,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
_("Align Objects Tool"), _("Calculators Tool"), _("2-Sided PCB Tool"), _("Transformations Tool"),
_("Punch Gerber Tool"), _("Extract Drills Tool"), _("Fiducials Tool"),
_("Solder Paste Dispensing Tool"),
_("Film PCB Tool"), _("Non-Copper Clearing Tool"), _("Optimal Tool"),
_("Film PCB Tool"), _("Corner Markers Tool"), _("Non-Copper Clearing Tool"), _("Optimal Tool"),
_("Paint Area Tool"), _("QRCode Tool"), _("Rules Check Tool"),
_("View File Source"),
_("Cutout PCB Tool"), _("Enable all Plots"), _("Disable all Plots"), _("Disable Non-selected Plots"),
@ -2633,6 +2639,8 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
QtGui.QIcon(self.app.resource_location + '/punch32.png'), _("Punch Gerber Tool"))
self.invert_btn = self.toolbartools.addAction(
QtGui.QIcon(self.app.resource_location + '/invert32.png'), _("Invert Gerber Tool"))
self.corners_tool_btn = self.toolbartools.addAction(
QtGui.QIcon(self.app.resource_location + '/corners_32.png'), _("Corner Markers Tool"))
# ########################################################################
# ## Excellon Editor Toolbar # ##
@ -3022,6 +3030,11 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
self.app.film_tool.run(toggle=True)
return
# Corner Markers Tool
if key == QtCore.Qt.Key_M:
self.app.corners_tool.run(toggle=True)
return
# Non-Copper Clear Tool
if key == QtCore.Qt.Key_N:
self.app.ncclear_tool.run(toggle=True)

View File

@ -467,6 +467,12 @@ class PreferencesUIManager:
"tools_solderpaste_pp": self.ui.tools_defaults_form.tools_solderpaste_group.pp_combo,
"tools_sub_close_paths": self.ui.tools_defaults_form.tools_sub_group.close_paths_cb,
# Corner Markers Tool
"tools_corners_thickness": self.ui.tools_defaults_form.tools_corners_group.thick_entry,
"tools_corners_length": self.ui.tools_defaults_form.tools_corners_group.l_entry,
"tools_corners_margin": self.ui.tools_defaults_form.tools_corners_group.margin_entry,
# #######################################################################################################
# ########################################## TOOLS 2 ####################################################
# #######################################################################################################

View File

@ -0,0 +1,81 @@
from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings
from flatcamGUI.GUIElements import FCDoubleSpinner
from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI
import gettext
import FlatCAMTranslation as fcTranslate
import builtins
fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
settings = QSettings("Open Source", "FlatCAM")
if settings.contains("machinist"):
machinist_setting = settings.value('machinist', type=int)
else:
machinist_setting = 0
class ToolsCornersPrefGroupUI(OptionsGroupUI):
def __init__(self, decimals=4, parent=None):
# OptionsGroupUI.__init__(self, "Calculators Tool Options", parent=parent)
super(ToolsCornersPrefGroupUI, self).__init__(self, parent=parent)
self.setTitle(str(_("Corner Markers Options")))
self.decimals = decimals
grid0 = QtWidgets.QGridLayout()
grid0.setColumnStretch(0, 0)
grid0.setColumnStretch(1, 1)
self.layout.addLayout(grid0)
self.param_label = QtWidgets.QLabel('<b>%s:</b>' % _('Parameters'))
self.param_label.setToolTip(
_("Parameters used for this tool.")
)
grid0.addWidget(self.param_label, 0, 0, 1, 2)
# Thickness #
self.thick_label = QtWidgets.QLabel('%s:' % _("Thickness"))
self.thick_label.setToolTip(
_("The thickness of the line that makes the corner marker.")
)
self.thick_entry = FCDoubleSpinner()
self.thick_entry.set_range(0.0000, 9.9999)
self.thick_entry.set_precision(self.decimals)
self.thick_entry.setWrapping(True)
self.thick_entry.setSingleStep(10 ** -self.decimals)
grid0.addWidget(self.thick_label, 1, 0)
grid0.addWidget(self.thick_entry, 1, 1)
# Length #
self.l_label = QtWidgets.QLabel('%s:' % _("Length"))
self.l_label.setToolTip(
_("The length of the line that makes the corner marker.")
)
self.l_entry = FCDoubleSpinner()
self.l_entry.set_range(-9999.9999, 9999.9999)
self.l_entry.set_precision(self.decimals)
self.l_entry.setSingleStep(10 ** -self.decimals)
# Margin #
self.margin_label = QtWidgets.QLabel('%s:' % _("Margin"))
self.margin_label.setToolTip(
_("Bounding box margin.")
)
self.margin_entry = FCDoubleSpinner()
self.margin_entry.set_range(-9999.9999, 9999.9999)
self.margin_entry.set_precision(self.decimals)
self.margin_entry.setSingleStep(0.1)
grid0.addWidget(self.margin_label, 2, 0)
grid0.addWidget(self.margin_entry, 2, 1)
grid0.addWidget(self.l_label, 4, 0)
grid0.addWidget(self.l_entry, 4, 1)
self.layout.addStretch()

View File

@ -3,6 +3,7 @@ from PyQt5.QtCore import QSettings
from flatcamGUI.preferences.tools.ToolsSubPrefGroupUI import ToolsSubPrefGroupUI
from flatcamGUI.preferences.tools.ToolsSolderpastePrefGroupUI import ToolsSolderpastePrefGroupUI
from flatcamGUI.preferences.tools.ToolsCornersPrefGroupUI import ToolsCornersPrefGroupUI
from flatcamGUI.preferences.tools.ToolsTransformPrefGroupUI import ToolsTransformPrefGroupUI
from flatcamGUI.preferences.tools.ToolsCalculatorsPrefGroupUI import ToolsCalculatorsPrefGroupUI
from flatcamGUI.preferences.tools.ToolsPanelizePrefGroupUI import ToolsPanelizePrefGroupUI
@ -62,6 +63,9 @@ class ToolsPreferencesUI(QtWidgets.QWidget):
self.tools_solderpaste_group = ToolsSolderpastePrefGroupUI(decimals=self.decimals)
self.tools_solderpaste_group.setMinimumWidth(200)
self.tools_corners_group = ToolsCornersPrefGroupUI(decimals=self.decimals)
self.tools_corners_group.setMinimumWidth(200)
self.tools_sub_group = ToolsSubPrefGroupUI(decimals=self.decimals)
self.tools_sub_group.setMinimumWidth(200)
@ -84,6 +88,7 @@ class ToolsPreferencesUI(QtWidgets.QWidget):
self.vlay4 = QtWidgets.QVBoxLayout()
self.vlay4.addWidget(self.tools_solderpaste_group)
self.vlay4.addWidget(self.tools_corners_group)
self.layout.addLayout(self.vlay)
self.layout.addLayout(self.vlay1)

423
flatcamTools/ToolCorners.py Normal file
View File

@ -0,0 +1,423 @@
# ##########################################################
# FlatCAM: 2D Post-processing for Manufacturing #
# File Author: Marius Adrian Stanciu (c) #
# Date: 5/17/2020 #
# MIT Licence #
# ##########################################################
from PyQt5 import QtWidgets, QtCore
from FlatCAMTool import FlatCAMTool
from flatcamGUI.GUIElements import FCDoubleSpinner, FCCheckBox, FCComboBox, FCButton
from shapely.geometry import MultiPolygon, LineString
from copy import deepcopy
import logging
import gettext
import FlatCAMTranslation as fcTranslate
import builtins
fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
log = logging.getLogger('base')
class ToolCorners(FlatCAMTool):
toolName = _("Corner Markers Tool")
def __init__(self, app):
FlatCAMTool.__init__(self, app)
self.app = app
self.canvas = self.app.plotcanvas
self.decimals = self.app.decimals
self.units = ''
# ## Title
title_label = QtWidgets.QLabel("%s" % self.toolName)
title_label.setStyleSheet("""
QLabel
{
font-size: 16px;
font-weight: bold;
}
""")
self.layout.addWidget(title_label)
self.layout.addWidget(QtWidgets.QLabel(''))
# Gerber object #
self.object_label = QtWidgets.QLabel('<b>%s:</b>' % _("Gerber Object"))
self.object_label.setToolTip(
_("The Gerber object that to which will be added corner markers.")
)
self.object_combo = FCComboBox()
self.object_combo.setModel(self.app.collection)
self.object_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
self.object_combo.is_last = True
self.object_combo.obj_type = "Gerber"
self.layout.addWidget(self.object_label)
self.layout.addWidget(self.object_combo)
separator_line = QtWidgets.QFrame()
separator_line.setFrameShape(QtWidgets.QFrame.HLine)
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
self.layout.addWidget(separator_line)
self.points_label = QtWidgets.QLabel('<b>%s:</b>' % _('Locations'))
self.points_label.setToolTip(
_("Locations where to place corner markers.")
)
self.layout.addWidget(self.points_label)
# BOTTOM LEFT
self.bl_cb = FCCheckBox(_("Bottom Left"))
self.layout.addWidget(self.bl_cb)
# BOTTOM RIGHT
self.br_cb = FCCheckBox(_("Bottom Right"))
self.layout.addWidget(self.br_cb)
# TOP LEFT
self.tl_cb = FCCheckBox(_("Top Left"))
self.layout.addWidget(self.tl_cb)
# TOP RIGHT
self.tr_cb = FCCheckBox(_("Top Right"))
self.layout.addWidget(self.tr_cb)
separator_line = QtWidgets.QFrame()
separator_line.setFrameShape(QtWidgets.QFrame.HLine)
separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
self.layout.addWidget(separator_line)
# ## Grid Layout
grid_lay = QtWidgets.QGridLayout()
self.layout.addLayout(grid_lay)
grid_lay.setColumnStretch(0, 0)
grid_lay.setColumnStretch(1, 1)
self.param_label = QtWidgets.QLabel('<b>%s:</b>' % _('Parameters'))
self.param_label.setToolTip(
_("Parameters used for this tool.")
)
grid_lay.addWidget(self.param_label, 0, 0, 1, 2)
# Thickness #
self.thick_label = QtWidgets.QLabel('%s:' % _("Thickness"))
self.thick_label.setToolTip(
_("The thickness of the line that makes the corner marker.")
)
self.thick_entry = FCDoubleSpinner(callback=self.confirmation_message)
self.thick_entry.set_range(0.0000, 9.9999)
self.thick_entry.set_precision(self.decimals)
self.thick_entry.setWrapping(True)
self.thick_entry.setSingleStep(10 ** -self.decimals)
grid_lay.addWidget(self.thick_label, 1, 0)
grid_lay.addWidget(self.thick_entry, 1, 1)
# Length #
self.l_label = QtWidgets.QLabel('%s:' % _("Length"))
self.l_label.setToolTip(
_("The length of the line that makes the corner marker.")
)
self.l_entry = FCDoubleSpinner(callback=self.confirmation_message)
self.l_entry.set_range(-9999.9999, 9999.9999)
self.l_entry.set_precision(self.decimals)
self.l_entry.setSingleStep(10 ** -self.decimals)
grid_lay.addWidget(self.l_label, 2, 0)
grid_lay.addWidget(self.l_entry, 2, 1)
# Margin #
self.margin_label = QtWidgets.QLabel('%s:' % _("Margin"))
self.margin_label.setToolTip(
_("Bounding box margin.")
)
self.margin_entry = FCDoubleSpinner(callback=self.confirmation_message)
self.margin_entry.set_range(-9999.9999, 9999.9999)
self.margin_entry.set_precision(self.decimals)
self.margin_entry.setSingleStep(0.1)
grid_lay.addWidget(self.margin_label, 3, 0)
grid_lay.addWidget(self.margin_entry, 3, 1)
separator_line_2 = QtWidgets.QFrame()
separator_line_2.setFrameShape(QtWidgets.QFrame.HLine)
separator_line_2.setFrameShadow(QtWidgets.QFrame.Sunken)
grid_lay.addWidget(separator_line_2, 4, 0, 1, 2)
# ## Insert Corner Marker
self.add_marker_button = FCButton(_("Add Marker"))
self.add_marker_button.setToolTip(
_("Will add corner markers to the selected Gerber file.")
)
self.add_marker_button.setStyleSheet("""
QPushButton
{
font-weight: bold;
}
""")
grid_lay.addWidget(self.add_marker_button, 11, 0, 1, 2)
self.layout.addStretch()
# ## Reset Tool
self.reset_button = QtWidgets.QPushButton(_("Reset Tool"))
self.reset_button.setToolTip(
_("Will reset the tool parameters.")
)
self.reset_button.setStyleSheet("""
QPushButton
{
font-weight: bold;
}
""")
self.layout.addWidget(self.reset_button)
# Objects involved in Copper thieving
self.grb_object = None
# store the flattened geometry here:
self.flat_geometry = []
# Tool properties
self.fid_dia = None
self.grb_steps_per_circle = self.app.defaults["gerber_circle_steps"]
# SIGNALS
self.add_marker_button.clicked.connect(self.add_markers)
def run(self, toggle=True):
self.app.defaults.report_usage("ToolCorners()")
if toggle:
# if the splitter is hidden, display it, else hide it but only if the current widget is the same
if self.app.ui.splitter.sizes()[0] == 0:
self.app.ui.splitter.setSizes([1, 1])
else:
try:
if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
# if tab is populated with the tool but it does not have the focus, focus on it
if not self.app.ui.notebook.currentWidget() is self.app.ui.tool_tab:
# focus on Tool Tab
self.app.ui.notebook.setCurrentWidget(self.app.ui.tool_tab)
else:
self.app.ui.splitter.setSizes([0, 1])
except AttributeError:
pass
else:
if self.app.ui.splitter.sizes()[0] == 0:
self.app.ui.splitter.setSizes([1, 1])
FlatCAMTool.run(self)
self.set_tool_ui()
self.app.ui.notebook.setTabText(2, _("Corners Tool"))
def install(self, icon=None, separator=None, **kwargs):
FlatCAMTool.install(self, icon, separator, shortcut='Alt+M', **kwargs)
def set_tool_ui(self):
self.units = self.app.defaults['units']
self.thick_entry.set_value(self.app.defaults["tools_corners_thickness"])
self.l_entry.set_value(float(self.app.defaults["tools_corners_length"]))
self.margin_entry.set_value(float(self.app.defaults["tools_corners_margin"]))
def add_markers(self):
self.app.call_source = "corners_tool"
tl_state = self.tl_cb.get_value()
tr_state = self.tr_cb.get_value()
bl_state = self.bl_cb.get_value()
br_state = self.br_cb.get_value()
# get the Gerber object on which the corner marker will be inserted
selection_index = self.object_combo.currentIndex()
model_index = self.app.collection.index(selection_index, 0, self.object_combo.rootModelIndex())
try:
self.grb_object = model_index.internalPointer().obj
except Exception as e:
log.debug("ToolCorners.add_markers() --> %s" % str(e))
self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no Gerber object loaded ..."))
return
xmin, ymin, xmax, ymax = self.grb_object.bounds()
points = {}
if tl_state:
points['tl'] = (xmin, ymax)
if tr_state:
points['tr'] = (xmax, ymax)
if bl_state:
points['bl'] = (xmin, ymin)
if br_state:
points['br'] = (xmax, ymin)
self.add_corners_geo(points, g_obj=self.grb_object)
self.grb_object.source_file = self.app.export_gerber(obj_name=self.grb_object.options['name'],
filename=None,
local_use=self.grb_object, use_thread=False)
self.on_exit()
def add_corners_geo(self, points_storage, g_obj):
"""
Add geometry to the solid_geometry of the copper Gerber object
:param points_storage: a dictionary holding the points where to add corners
:param g_obj: the Gerber object where to add the geometry
:return: None
"""
line_thickness = self.thick_entry.get_value()
line_length = self.l_entry.get_value()
margin = self.margin_entry.get_value()
geo_list = []
if not points_storage:
self.app.inform.emit("[ERROR_NOTCL] %s." % _("Please select at least a location"))
return
for key in points_storage:
if key == 'tl':
pt = points_storage[key]
x = pt[0] - margin - line_thickness / 2.0
y = pt[1] + margin + line_thickness / 2.0
line_geo_hor = LineString([
(x, y), (x + line_length, y)
])
line_geo_vert = LineString([
(x, y), (x, y - line_length)
])
geo_list.append(line_geo_hor)
geo_list.append(line_geo_vert)
if key == 'tr':
pt = points_storage[key]
x = pt[0] + margin + line_thickness / 2.0
y = pt[1] + margin + line_thickness / 2.0
line_geo_hor = LineString([
(x, y), (x - line_length, y)
])
line_geo_vert = LineString([
(x, y), (x, y - line_length)
])
geo_list.append(line_geo_hor)
geo_list.append(line_geo_vert)
if key == 'bl':
pt = points_storage[key]
x = pt[0] - margin - line_thickness / 2.0
y = pt[1] - margin - line_thickness / 2.0
line_geo_hor = LineString([
(x, y), (x + line_length, y)
])
line_geo_vert = LineString([
(x, y), (x, y + line_length)
])
geo_list.append(line_geo_hor)
geo_list.append(line_geo_vert)
if key == 'br':
pt = points_storage[key]
x = pt[0] + margin + line_thickness / 2.0
y = pt[1] - margin - line_thickness / 2.0
line_geo_hor = LineString([
(x, y), (x - line_length, y)
])
line_geo_vert = LineString([
(x, y), (x, y + line_length)
])
geo_list.append(line_geo_hor)
geo_list.append(line_geo_vert)
aperture_found = None
for ap_id, ap_val in g_obj.apertures.items():
if ap_val['type'] == 'C' and ap_val['size'] == line_thickness:
aperture_found = ap_id
break
geo_buff_list = []
if aperture_found:
for geo in geo_list:
geo_buff = geo.buffer(line_thickness / 2.0, resolution=self.grb_steps_per_circle, join_style=2)
geo_buff_list.append(geo_buff)
dict_el = {}
dict_el['follow'] = geo
dict_el['solid'] = geo_buff
g_obj.apertures[aperture_found]['geometry'].append(deepcopy(dict_el))
else:
ap_keys = list(g_obj.apertures.keys())
if ap_keys:
new_apid = str(int(max(ap_keys)) + 1)
else:
new_apid = '10'
g_obj.apertures[new_apid] = {}
g_obj.apertures[new_apid]['type'] = 'C'
g_obj.apertures[new_apid]['size'] = line_thickness
g_obj.apertures[new_apid]['geometry'] = []
for geo in geo_list:
geo_buff = geo.buffer(line_thickness / 2.0, resolution=self.grb_steps_per_circle, join_style=2)
geo_buff_list.append(geo_buff)
dict_el = {}
dict_el['follow'] = geo
dict_el['solid'] = geo_buff
g_obj.apertures[new_apid]['geometry'].append(deepcopy(dict_el))
s_list = []
if g_obj.solid_geometry:
try:
for poly in g_obj.solid_geometry:
s_list.append(poly)
except TypeError:
s_list.append(g_obj.solid_geometry)
geo_buff_list = MultiPolygon(geo_buff_list)
geo_buff_list = geo_buff_list.buffer(0)
for poly in geo_buff_list:
s_list.append(poly)
g_obj.solid_geometry = MultiPolygon(s_list)
def replot(self, obj, run_thread=True):
def worker_task():
with self.app.proc_container.new('%s...' % _("Plotting")):
obj.plot()
if run_thread:
self.app.worker_task.emit({'fcn': worker_task, 'params': []})
else:
worker_task()
def on_exit(self):
# plot the object
try:
self.replot(obj=self.grb_object)
except (AttributeError, TypeError):
return
# update the bounding box values
try:
a, b, c, d = self.grb_object.bounds()
self.grb_object.options['xmin'] = a
self.grb_object.options['ymin'] = b
self.grb_object.options['xmax'] = c
self.grb_object.options['ymax'] = d
except Exception as e:
log.debug("ToolCorners.on_exit() copper_obj bounds error --> %s" % str(e))
# reset the variables
self.grb_object = None
self.app.call_source = "app"
self.app.inform.emit('[success] %s' % _("Corners Tool exit."))

View File

@ -234,7 +234,7 @@ class ToolFiducials(FlatCAMTool):
# Line Thickness #
self.line_thickness_label = QtWidgets.QLabel('%s:' % _("Line thickness"))
self.line_thickness_label.setToolTip(
_("Bounding box margin.")
_("Thickness of the line that makes the fiducial.")
)
self.line_thickness_entry = FCDoubleSpinner(callback=self.confirmation_message)
self.line_thickness_entry.set_range(0.00001, 9999.9999)
@ -353,7 +353,8 @@ class ToolFiducials(FlatCAMTool):
self.margin_val = None
self.sec_position = None
self.geo_steps_per_circle = 128
self.grb_steps_per_circle = self.app.defaults["gerber_circle_steps"]
self.click_points = []
@ -471,7 +472,7 @@ class ToolFiducials(FlatCAMTool):
if self.mode_method == 'auto':
xmin, ymin, xmax, ymax = self.grb_object.bounds()
bbox = box(xmin, ymin, xmax, ymax)
buf_bbox = bbox.buffer(self.margin_val, join_style=2)
buf_bbox = bbox.buffer(self.margin_val, self.grb_steps_per_circle, join_style=2)
x0, y0, x1, y1 = buf_bbox.bounds
self.click_points.append(
@ -539,7 +540,7 @@ class ToolFiducials(FlatCAMTool):
radius = fid_size / 2.0
if fid_type == 'circular':
geo_list = [Point(pt).buffer(radius) for pt in points_list]
geo_list = [Point(pt).buffer(radius, self.grb_steps_per_circle) for pt in points_list]
aperture_found = None
for ap_id, ap_val in g_obj.apertures.items():
@ -604,8 +605,8 @@ class ToolFiducials(FlatCAMTool):
geo_buff_list = []
if aperture_found:
for geo in geo_list:
geo_buff_h = geo[0].buffer(line_thickness / 2.0)
geo_buff_v = geo[1].buffer(line_thickness / 2.0)
geo_buff_h = geo[0].buffer(line_thickness / 2.0, self.grb_steps_per_circle)
geo_buff_v = geo[1].buffer(line_thickness / 2.0, self.grb_steps_per_circle)
geo_buff_list.append(geo_buff_h)
geo_buff_list.append(geo_buff_v)
@ -629,8 +630,8 @@ class ToolFiducials(FlatCAMTool):
g_obj.apertures[new_apid]['geometry'] = []
for geo in geo_list:
geo_buff_h = geo[0].buffer(line_thickness / 2.0)
geo_buff_v = geo[1].buffer(line_thickness / 2.0)
geo_buff_h = geo[0].buffer(line_thickness / 2.0, self.grb_steps_per_circle)
geo_buff_v = geo[1].buffer(line_thickness / 2.0, self.grb_steps_per_circle)
geo_buff_list.append(geo_buff_h)
geo_buff_list.append(geo_buff_v)

View File

@ -2093,75 +2093,77 @@ class NonCopperClear(FlatCAMTool, Gerber):
isolated_geo = self.generate_envelope(tool_iso / 2, 0)
if isolated_geo == 'fail':
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Isolation geometry could not be generated."))
else:
if ncc_margin < tool_iso:
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Isolation geometry is broken. Margin is less "
"than isolation tool diameter."))
try:
for geo_elem in isolated_geo:
# provide the app with a way to process the GUI events when in a blocking loop
QtWidgets.QApplication.processEvents()
self.app.inform.emit('[ERROR_NOTCL] %s %s' %
(_("Isolation geometry could not be generated."), str(tool_iso)))
continue
if self.app.abort_flag:
# graceful abort requested by the user
raise grace
if ncc_margin < tool_iso:
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Isolation geometry is broken. Margin is less "
"than isolation tool diameter."))
try:
for geo_elem in isolated_geo:
# provide the app with a way to process the GUI events when in a blocking loop
QtWidgets.QApplication.processEvents()
if isinstance(geo_elem, Polygon):
for ring in self.poly2rings(geo_elem):
if self.app.abort_flag:
# graceful abort requested by the user
raise grace
if isinstance(geo_elem, Polygon):
for ring in self.poly2rings(geo_elem):
new_geo = ring.intersection(bounding_box)
if new_geo and not new_geo.is_empty:
new_geometry.append(new_geo)
elif isinstance(geo_elem, MultiPolygon):
for poly in geo_elem:
for ring in self.poly2rings(poly):
new_geo = ring.intersection(bounding_box)
if new_geo and not new_geo.is_empty:
new_geometry.append(new_geo)
elif isinstance(geo_elem, MultiPolygon):
for poly in geo_elem:
for ring in self.poly2rings(poly):
new_geo = ring.intersection(bounding_box)
if new_geo and not new_geo.is_empty:
new_geometry.append(new_geo)
elif isinstance(geo_elem, LineString):
new_geo = geo_elem.intersection(bounding_box)
if new_geo:
if not new_geo.is_empty:
new_geometry.append(new_geo)
elif isinstance(geo_elem, MultiLineString):
for line_elem in geo_elem:
new_geo = line_elem.intersection(bounding_box)
if new_geo and not new_geo.is_empty:
new_geometry.append(new_geo)
except TypeError:
if isinstance(isolated_geo, Polygon):
for ring in self.poly2rings(isolated_geo):
new_geo = ring.intersection(bounding_box)
if new_geo:
if not new_geo.is_empty:
new_geometry.append(new_geo)
elif isinstance(isolated_geo, LineString):
new_geo = isolated_geo.intersection(bounding_box)
if new_geo and not new_geo.is_empty:
new_geometry.append(new_geo)
elif isinstance(isolated_geo, MultiLineString):
for line_elem in isolated_geo:
elif isinstance(geo_elem, LineString):
new_geo = geo_elem.intersection(bounding_box)
if new_geo:
if not new_geo.is_empty:
new_geometry.append(new_geo)
elif isinstance(geo_elem, MultiLineString):
for line_elem in geo_elem:
new_geo = line_elem.intersection(bounding_box)
if new_geo and not new_geo.is_empty:
new_geometry.append(new_geo)
except TypeError:
if isinstance(isolated_geo, Polygon):
for ring in self.poly2rings(isolated_geo):
new_geo = ring.intersection(bounding_box)
if new_geo:
if not new_geo.is_empty:
new_geometry.append(new_geo)
elif isinstance(isolated_geo, LineString):
new_geo = isolated_geo.intersection(bounding_box)
if new_geo and not new_geo.is_empty:
new_geometry.append(new_geo)
elif isinstance(isolated_geo, MultiLineString):
for line_elem in isolated_geo:
new_geo = line_elem.intersection(bounding_box)
if new_geo and not new_geo.is_empty:
new_geometry.append(new_geo)
# a MultiLineString geometry element will show that the isolation is broken for this tool
for geo_e in new_geometry:
if type(geo_e) == MultiLineString:
warning_flag += 1
break
# a MultiLineString geometry element will show that the isolation is broken for this tool
for geo_e in new_geometry:
if type(geo_e) == MultiLineString:
warning_flag += 1
break
current_uid = 0
for k, v in tools_storage.items():
if float('%.*f' % (self.decimals, v['tooldia'])) == float('%.*f' % (self.decimals,
tool_iso)):
current_uid = int(k)
# add the solid_geometry to the current too in self.paint_tools dictionary
# and then reset the temporary list that stored that solid_geometry
v['solid_geometry'] = deepcopy(new_geometry)
v['data']['name'] = name
break
geo_obj.tools[current_uid] = dict(tools_storage[current_uid])
current_uid = 0
for k, v in tools_storage.items():
if float('%.*f' % (self.decimals, v['tooldia'])) == float('%.*f' % (self.decimals,
tool_iso)):
current_uid = int(k)
# add the solid_geometry to the current too in self.paint_tools dictionary
# and then reset the temporary list that stored that solid_geometry
v['solid_geometry'] = deepcopy(new_geometry)
v['data']['name'] = name
break
geo_obj.tools[current_uid] = dict(tools_storage[current_uid])
sol_geo = cascaded_union(isolated_geo)
if has_offset is True:

View File

@ -1,4 +1,3 @@
import sys
from flatcamTools.ToolCalculators import ToolCalculator
from flatcamTools.ToolCalibration import ToolCalibration
@ -41,3 +40,4 @@ from flatcamTools.ToolTransform import ToolTransform
from flatcamTools.ToolPunchGerber import ToolPunchGerber
from flatcamTools.ToolInvertGerber import ToolInvertGerber
from flatcamTools.ToolCorners import ToolCorners