- Gerber Editor: finished a new tool: Poligonize Tool (ALT+N in Editor). It will fuse a selection of tracks into a polygon. It will fill a selection of polygons if they are apart and it will make a single polygon if the selection is overlapped. All the newly created filled polygons will be stored in aperture '0' (if it does not exist it will be automatically created)

- fixed a bug in Move command in context menu who crashed the app when triggered
- Gerber Editor: when adding a new aperture it will be store as the last selected and it will be used for any tools that are triggered until a new aperture is selected.
This commit is contained in:
Marius Stanciu 2019-04-15 22:48:22 +03:00
parent 2b4beebba2
commit 2ba0b494ff
6 changed files with 64 additions and 35 deletions

View File

@ -5653,7 +5653,7 @@ class App(QtCore.QObject):
def obj_move(self):
self.report_usage("obj_move()")
self.move_tool.run()
self.move_tool.run(toggle=False)
def on_fileopengerber(self):
"""

View File

@ -17,7 +17,10 @@ CAD program, and create G-Code for Isolation routing.
- update the order of event handlers connection in Editors to first connect new handlers then disconnect old handlers. It seems that if nothing is connected some VispY functions like canvas panning no longer works if there is at least once nothing connected to the 'mouse_move' event
- Excellon Editor: update so always there is a tool selected even after the Execllon object was just edited; before it always required a click inside of the tool table, not you do it only if needed.
- fixed the menu File -> Edit -> Edit/Close Editor entry to reflect the status of the app (Editor active or not)
- added support in Excellon parser for autodetection of Excellon file format for the Excellon files generate by the following ECAD sw: DipTrace, Eagle, Altium, Sprint Layout
- added support in Excellon parser for autodetection of Excellon file format for the Excellon files generated by the following ECAD sw: DipTrace, Eagle, Altium, Sprint Layout
- Gerber Editor: finished a new tool: Poligonize Tool (ALT+N in Editor). It will fuse a selection of tracks into a polygon. It will fill a selection of polygons if they are apart and it will make a single polygon if the selection is overlapped. All the newly created filled polygons will be stored in aperture '0' (if it does not exist it will be automatically created)
- fixed a bug in Move command in context menu who crashed the app when triggered
- Gerber Editor: when adding a new aperture it will be store as the last selected and it will be used for any tools that are triggered until a new aperture is selected.
14.04.2019

View File

@ -3928,9 +3928,10 @@ class Excellon(Geometry):
log.warning("Found ALLEGRO start of the header: %s" % eline)
continue
# Header End #
# Since there might be comments in the header that include char % or M95
# we ignore the lines starting with ';' which show they are comments
# Search for Header End #
# Since there might be comments in the header that include header end char (% or M95)
# we ignore the lines starting with ';' that contains such header end chars because it is not a
# real header end.
if self.comm_re.search(eline):
match = self.tool_units_re.search(eline)
if match:
@ -3938,7 +3939,7 @@ class Excellon(Geometry):
line_units_found = True
line_units = match.group(3)
self.convert_units({"MILS": "IN", "MM": "MM"}[line_units])
log.warning("Type of Allegro UNITS found inline: %s" % line_units)
log.warning("Type of Allegro UNITS found inline in comments: %s" % line_units)
if match.group(2):
name_tool += 1
@ -3960,7 +3961,8 @@ class Excellon(Geometry):
self.excellon_format_upper_in = match.group(1)
self.excellon_format_lower_in = match.group(2)
log.warning("Altium Excellon format preset found: %s:%s" % (match.group(1), match.group(2)))
log.warning("Altium Excellon format preset found in comments: %s:%s" %
(match.group(1), match.group(2)))
continue
else:
log.warning("Line ignored, it's a comment: %s" % eline)

View File

@ -2,7 +2,7 @@ from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtCore import Qt, QSettings
from shapely.geometry import LineString, LinearRing, MultiLineString
from shapely.ops import cascaded_union
from shapely.ops import cascaded_union, unary_union
import shapely.affinity as affinity
from numpy import arctan2, Inf, array, sqrt, sign, dot
@ -497,39 +497,42 @@ class FCPoligonize(FCShapeTool):
self.make()
def click(self, point):
# self.draw_app.in_action = True
# if self.draw_app.selected:
# self.make()
# else:
# self.draw_app.app.inform.emit(_("[WARNING_NOTCL] No shapes are selected. Select shapes and try again ..."))
return ""
def make(self):
geo = []
for shape in self.draw_app.selected:
current_storage = self.draw_app.storage_dict[self.draw_app.last_aperture_selected]['solid_geometry']
print(self.draw_app.active_tool)
aha = []
if shape.geo:
shape_points = list(shape.geo.exterior.coords)
for pt in shape_points:
aha.append(Point(pt))
concave_hull, bla_bla = alpha_shape(points=aha, alpha=0.5)
geo.append(concave_hull)
print(geo)
self.geometry = DrawToolShape(geo)
self.draw_app.on_grb_shape_complete(current_storage)
if not self.draw_app.selected:
self.draw_app.in_action = False
self.complete = True
self.draw_app.app.inform.emit(_("[ERROR_NOTCL] Failed. Nothing selected."))
self.draw_app.select_tool("select")
return
try:
current_storage = self.draw_app.storage_dict['0']['solid_geometry']
except KeyError:
self.draw_app.on_aperture_add(apid='0')
current_storage = self.draw_app.storage_dict['0']['solid_geometry']
fused_geo = [Polygon(sh.geo.exterior) for sh in self.draw_app.selected]
fused_geo = MultiPolygon(fused_geo)
fused_geo = fused_geo.buffer(0.0000001)
if isinstance(fused_geo, MultiPolygon):
for geo in fused_geo:
self.draw_app.on_grb_shape_complete(current_storage, specific_shape=DrawToolShape(geo))
else:
self.draw_app.on_grb_shape_complete(current_storage, specific_shape=DrawToolShape(fused_geo))
self.draw_app.delete_selected()
self.draw_app.plot_all()
self.draw_app.in_action = False
self.complete = True
self.draw_app.app.inform.emit(_("[success] Done. Poligonize completed."))
self.draw_app.build_ui()
# MS: always return to the Select Tool if modifier key is not pressed
# else return to the current tool
key_modifier = QtWidgets.QApplication.keyboardModifiers()
if self.draw_app.app.defaults["global_mselect_key"] == 'Control':
modifier_to_use = Qt.ControlModifier
@ -1472,6 +1475,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.app.ui.grb_add_track_menuitem.triggered.connect(self.on_track_add)
self.app.ui.grb_add_region_menuitem.triggered.connect(self.on_region_add)
self.app.ui.grb_convert_poly_menuitem.triggered.connect(self.on_poligonize)
self.app.ui.grb_add_buffer_menuitem.triggered.connect(self.on_buffer)
self.app.ui.grb_add_scale_menuitem.triggered.connect(self.on_scale)
self.app.ui.grb_transform_menuitem.triggered.connect(self.transform_tool.run)
@ -1760,6 +1764,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.build_ui()
self.last_aperture_selected = ap_id
# make a quick sort through the tool2tooldia dict so we find which row to select
row_to_be_selected = None
for key in sorted(self.tool2tooldia):
@ -2346,15 +2352,22 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.options[key] = self.sender().isChecked()
return self.options[key]
def on_grb_shape_complete(self, storage=None):
def on_grb_shape_complete(self, storage=None, specific_shape=None):
self.app.log.debug("on_shape_complete()")
if specific_shape:
geo = specific_shape
else:
geo = self.active_tool.geometry
if geo is None:
return
if storage is not None:
# Add shape
self.add_gerber_shape(self.active_tool.geometry, storage)
self.add_gerber_shape(geo, storage)
else:
stora = self.storage_dict[self.last_aperture_selected]['solid_geometry']
self.add_gerber_shape(self.active_tool.geometry, storage=stora)
self.add_gerber_shape(geo, storage=stora)
# Remove any utility shapes
self.delete_utility_geometry()
@ -2372,6 +2385,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
:return: None
"""
# List of DrawToolShape?
if isinstance(shape, list):
for subshape in shape:
self.add_gerber_shape(subshape, storage)
@ -2859,6 +2873,9 @@ class FlatCAMGrbEditor(QtCore.QObject):
def on_region_add(self):
self.select_tool('region')
def on_poligonize(self):
self.select_tool('poligonize')
def on_buffer(self):
buff_value = 0.01
log.debug("FlatCAMGrbEditor.on_buffer()")

View File

@ -470,6 +470,8 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
_('Add Region\tN'))
self.grb_editor_menu.addSeparator()
self.grb_convert_poly_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/poligonize32.png'),
_("Poligonize\tALT+N"))
self.grb_add_buffer_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/buffer16-2.png'),
_('Buffer\tB'))
self.grb_add_scale_menuitem = self.grb_editor_menu.addAction(QtGui.QIcon('share/scale32.png'),
@ -690,7 +692,8 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
self.add_pad_ar_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/padarray32.png'), _('Add Pad Array'))
self.grb_add_track_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/track32.png'), _("Add Track"))
self.grb_add_region_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/polygon32.png'), _("Add Region"))
self.grb_convert_poly_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/polygon32.png'), _("Poligonize"))
self.grb_convert_poly_btn = self.grb_edit_toolbar.addAction(QtGui.QIcon('share/poligonize32.png'),
_("Poligonize"))
self.grb_edit_toolbar.addSeparator()
@ -2529,11 +2532,15 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
elif modifiers == QtCore.Qt.ShiftModifier:
pass
elif modifiers == QtCore.Qt.AltModifier:
# Poligonize Tool
if key == QtCore.Qt.Key_N or key == 'N':
self.app.grb_editor.on_poligonize()
return
# Transformation Tool
if key == QtCore.Qt.Key_R or key == 'R':
self.app.grb_editor.on_transform()
return
elif modifiers == QtCore.Qt.NoModifier:
# Abort the current action
if key == QtCore.Qt.Key_Escape or key == 'Escape':

BIN
share/poligonize32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 B