- added a new tool in the Geometry Editor named Explode which is the opposite of Union Tool: it will explode the polygons into lines
This commit is contained in:
@@ -17,6 +17,7 @@ CAD program, and create G-Code for Isolation routing.
|
|||||||
- fixed an issue with the tool table context menu in Paint Tool
|
- fixed an issue with the tool table context menu in Paint Tool
|
||||||
- made some changes in the GUI in Paint Tool, NCC Tool and SolderPaste Tool
|
- made some changes in the GUI in Paint Tool, NCC Tool and SolderPaste Tool
|
||||||
- changed some of the icons; added attributions for icons source in the About FlatCAM window
|
- changed some of the icons; added attributions for icons source in the About FlatCAM window
|
||||||
|
- added a new tool in the Geometry Editor named Explode which is the opposite of Union Tool: it will explode the polygons into lines
|
||||||
|
|
||||||
4.10.2019
|
4.10.2019
|
||||||
|
|
||||||
|
|||||||
@@ -1324,7 +1324,7 @@ class TransformEditorTool(FlatCAMTool):
|
|||||||
# get mirroring coords from the point entry
|
# get mirroring coords from the point entry
|
||||||
if self.flip_ref_cb.isChecked():
|
if self.flip_ref_cb.isChecked():
|
||||||
px, py = eval('{}'.format(self.flip_ref_entry.text()))
|
px, py = eval('{}'.format(self.flip_ref_entry.text()))
|
||||||
# get mirroing coords from the center of an all-enclosing bounding box
|
# get mirroring coords from the center of an all-enclosing bounding box
|
||||||
else:
|
else:
|
||||||
# first get a bounding box to fit all
|
# first get a bounding box to fit all
|
||||||
for sha in shape_list:
|
for sha in shape_list:
|
||||||
@@ -2455,6 +2455,61 @@ class FCSelect(DrawTool):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
class FCExplode(FCShapeTool):
|
||||||
|
def __init__(self, draw_app):
|
||||||
|
FCShapeTool.__init__(self, draw_app)
|
||||||
|
self.name = 'explode'
|
||||||
|
|
||||||
|
self.draw_app = draw_app
|
||||||
|
|
||||||
|
try:
|
||||||
|
QtGui.QGuiApplication.restoreOverrideCursor()
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.storage = self.draw_app.storage
|
||||||
|
self.origin = (0, 0)
|
||||||
|
self.destination = None
|
||||||
|
|
||||||
|
self.draw_app.active_tool = self
|
||||||
|
if len(self.draw_app.get_selected()) == 0:
|
||||||
|
self.draw_app.app.inform.emit('[WARNING_NOTCL] %s...' %
|
||||||
|
_("No shape selected. Select a shape to explode"))
|
||||||
|
else:
|
||||||
|
self.make()
|
||||||
|
|
||||||
|
def make(self):
|
||||||
|
to_be_deleted_list = list()
|
||||||
|
lines = list()
|
||||||
|
|
||||||
|
for shape in self.draw_app.get_selected():
|
||||||
|
to_be_deleted_list.append(shape)
|
||||||
|
geo = shape.geo
|
||||||
|
ext_coords = list(geo.exterior.coords)
|
||||||
|
|
||||||
|
for c in range(len(ext_coords)):
|
||||||
|
if c < len(ext_coords) - 1:
|
||||||
|
lines.append(LineString([ext_coords[c], ext_coords[c + 1]]))
|
||||||
|
|
||||||
|
for int_geo in geo.interiors:
|
||||||
|
int_coords = list(int_geo.coords)
|
||||||
|
for c in range(len(int_coords)):
|
||||||
|
if c < len(int_coords):
|
||||||
|
lines.append(LineString([int_coords[c], int_coords[c + 1]]))
|
||||||
|
|
||||||
|
for shape in to_be_deleted_list:
|
||||||
|
self.draw_app.storage.remove(shape)
|
||||||
|
if shape in self.draw_app.selected:
|
||||||
|
self.draw_app.selected.remove(shape)
|
||||||
|
|
||||||
|
geo_list = list()
|
||||||
|
for line in lines:
|
||||||
|
geo_list.append(DrawToolShape(line))
|
||||||
|
self.geometry = geo_list
|
||||||
|
self.draw_app.on_shape_complete()
|
||||||
|
self.draw_app.app.inform.emit('[success] %s...' % _("Done. Polygons exploded into lines."))
|
||||||
|
|
||||||
|
|
||||||
class FCMove(FCShapeTool):
|
class FCMove(FCShapeTool):
|
||||||
def __init__(self, draw_app):
|
def __init__(self, draw_app):
|
||||||
FCShapeTool.__init__(self, draw_app)
|
FCShapeTool.__init__(self, draw_app)
|
||||||
@@ -3015,7 +3070,9 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||||||
"transform": {"button": self.app.ui.geo_transform_btn,
|
"transform": {"button": self.app.ui.geo_transform_btn,
|
||||||
"constructor": FCTransform},
|
"constructor": FCTransform},
|
||||||
"copy": {"button": self.app.ui.geo_copy_btn,
|
"copy": {"button": self.app.ui.geo_copy_btn,
|
||||||
"constructor": FCCopy}
|
"constructor": FCCopy},
|
||||||
|
"explode": {"button": self.app.ui.geo_explode_btn,
|
||||||
|
"constructor": FCExplode}
|
||||||
}
|
}
|
||||||
|
|
||||||
# # ## Data
|
# # ## Data
|
||||||
@@ -4041,7 +4098,8 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||||||
|
|
||||||
if type(geometry) == LineString or type(geometry) == LinearRing:
|
if type(geometry) == LineString or type(geometry) == LinearRing:
|
||||||
plot_elements.append(self.shapes.add(shape=geometry, color=color, layer=0,
|
plot_elements.append(self.shapes.add(shape=geometry, color=color, layer=0,
|
||||||
tolerance=self.fcgeometry.drawing_tolerance))
|
tolerance=self.fcgeometry.drawing_tolerance,
|
||||||
|
linewidth=linewidth))
|
||||||
|
|
||||||
if type(geometry) == Point:
|
if type(geometry) == Point:
|
||||||
pass
|
pass
|
||||||
@@ -4098,9 +4156,14 @@ class FlatCAMGeoEditor(QtCore.QObject):
|
|||||||
pl.append(Polygon(p.exterior.coords[::-1], p.interiors))
|
pl.append(Polygon(p.exterior.coords[::-1], p.interiors))
|
||||||
elif isinstance(p, LinearRing):
|
elif isinstance(p, LinearRing):
|
||||||
pl.append(Polygon(p.coords[::-1]))
|
pl.append(Polygon(p.coords[::-1]))
|
||||||
# elif isinstance(p, LineString):
|
elif isinstance(p, LineString):
|
||||||
# pl.append(LineString(p.coords[::-1]))
|
pl.append(LineString(p.coords[::-1]))
|
||||||
geom = MultiPolygon(pl)
|
try:
|
||||||
|
geom = MultiPolygon(pl)
|
||||||
|
except TypeError:
|
||||||
|
# this may happen if the geom elements are made out of LineStrings because you can't create a
|
||||||
|
# MultiPolygon out of LineStrings
|
||||||
|
pass
|
||||||
except TypeError:
|
except TypeError:
|
||||||
if isinstance(geom, Polygon) and geom is not None:
|
if isinstance(geom, Polygon) and geom is not None:
|
||||||
geom = Polygon(geom.exterior.coords[::-1], geom.interiors)
|
geom = Polygon(geom.exterior.coords[::-1], geom.interiors)
|
||||||
|
|||||||
@@ -775,6 +775,8 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
|||||||
|
|
||||||
self.geo_edit_toolbar.addSeparator()
|
self.geo_edit_toolbar.addSeparator()
|
||||||
self.geo_union_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/union32.png'), _('Polygon Union'))
|
self.geo_union_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/union32.png'), _('Polygon Union'))
|
||||||
|
self.geo_explode_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/explode32.png'), _('Polygon Explode'))
|
||||||
|
|
||||||
self.geo_intersection_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/intersection32.png'),
|
self.geo_intersection_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/intersection32.png'),
|
||||||
_('Polygon Intersection'))
|
_('Polygon Intersection'))
|
||||||
self.geo_subtract_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/subtract32.png'),
|
self.geo_subtract_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/subtract32.png'),
|
||||||
@@ -2174,6 +2176,8 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
|||||||
|
|
||||||
self.geo_edit_toolbar.addSeparator()
|
self.geo_edit_toolbar.addSeparator()
|
||||||
self.geo_union_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/union32.png'), _('Polygon Union'))
|
self.geo_union_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/union32.png'), _('Polygon Union'))
|
||||||
|
self.geo_explode_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/explode32.png'), _('Polygon Explode'))
|
||||||
|
|
||||||
self.geo_intersection_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/intersection32.png'),
|
self.geo_intersection_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/intersection32.png'),
|
||||||
_('Polygon Intersection'))
|
_('Polygon Intersection'))
|
||||||
self.geo_subtract_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/subtract32.png'),
|
self.geo_subtract_btn = self.geo_edit_toolbar.addAction(QtGui.QIcon('share/subtract32.png'),
|
||||||
|
|||||||
@@ -810,7 +810,8 @@ class ShapeCollectionLegacy:
|
|||||||
self.axes = self.app.plotcanvas.new_axes(axes_name)
|
self.axes = self.app.plotcanvas.new_axes(axes_name)
|
||||||
|
|
||||||
def add(self, shape=None, color=None, face_color=None, alpha=None, visible=True,
|
def add(self, shape=None, color=None, face_color=None, alpha=None, visible=True,
|
||||||
update=False, layer=1, tolerance=0.01, obj=None, gcode_parsed=None, tool_tolerance=None, tooldia=None):
|
update=False, layer=1, tolerance=0.01, obj=None, gcode_parsed=None, tool_tolerance=None, tooldia=None,
|
||||||
|
linewidth=None):
|
||||||
"""
|
"""
|
||||||
This function will add shapes to the shape collection
|
This function will add shapes to the shape collection
|
||||||
|
|
||||||
@@ -826,6 +827,7 @@ class ShapeCollectionLegacy:
|
|||||||
:param gcode_parsed: not used; just for compatibility with VIsPy canvas
|
:param gcode_parsed: not used; just for compatibility with VIsPy canvas
|
||||||
:param tool_tolerance: just for compatibility with VIsPy canvas
|
:param tool_tolerance: just for compatibility with VIsPy canvas
|
||||||
:param tooldia:
|
:param tooldia:
|
||||||
|
:param linewidth: the width of the line
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
self._color = color[:-2] if color is not None else None
|
self._color = color[:-2] if color is not None else None
|
||||||
@@ -853,6 +855,7 @@ class ShapeCollectionLegacy:
|
|||||||
self.shape_dict.update({
|
self.shape_dict.update({
|
||||||
'color': self._color,
|
'color': self._color,
|
||||||
'face_color': self._face_color,
|
'face_color': self._face_color,
|
||||||
|
'linewidth': linewidth,
|
||||||
'alpha': self._alpha,
|
'alpha': self._alpha,
|
||||||
'shape': sh
|
'shape': sh
|
||||||
})
|
})
|
||||||
@@ -865,6 +868,7 @@ class ShapeCollectionLegacy:
|
|||||||
self.shape_dict.update({
|
self.shape_dict.update({
|
||||||
'color': self._color,
|
'color': self._color,
|
||||||
'face_color': self._face_color,
|
'face_color': self._face_color,
|
||||||
|
'linewidth': linewidth,
|
||||||
'alpha': self._alpha,
|
'alpha': self._alpha,
|
||||||
'shape': shape
|
'shape': shape
|
||||||
})
|
})
|
||||||
@@ -928,15 +932,21 @@ class ShapeCollectionLegacy:
|
|||||||
elif obj_type == 'geometry':
|
elif obj_type == 'geometry':
|
||||||
if type(local_shapes[element]['shape']) == Polygon:
|
if type(local_shapes[element]['shape']) == Polygon:
|
||||||
x, y = local_shapes[element]['shape'].exterior.coords.xy
|
x, y = local_shapes[element]['shape'].exterior.coords.xy
|
||||||
self.axes.plot(x, y, local_shapes[element]['color'], linestyle='-')
|
self.axes.plot(x, y, local_shapes[element]['color'],
|
||||||
|
linestyle='-',
|
||||||
|
linewidth=local_shapes[element]['linewidth'])
|
||||||
for ints in local_shapes[element]['shape'].interiors:
|
for ints in local_shapes[element]['shape'].interiors:
|
||||||
x, y = ints.coords.xy
|
x, y = ints.coords.xy
|
||||||
self.axes.plot(x, y, local_shapes[element]['color'], linestyle='-')
|
self.axes.plot(x, y, local_shapes[element]['color'],
|
||||||
|
linestyle='-',
|
||||||
|
linewidth=local_shapes[element]['linewidth'])
|
||||||
elif type(local_shapes[element]['shape']) == LineString or \
|
elif type(local_shapes[element]['shape']) == LineString or \
|
||||||
type(local_shapes[element]['shape']) == LinearRing:
|
type(local_shapes[element]['shape']) == LinearRing:
|
||||||
|
|
||||||
x, y = local_shapes[element]['shape'].coords.xy
|
x, y = local_shapes[element]['shape'].coords.xy
|
||||||
self.axes.plot(x, y, local_shapes[element]['color'], linestyle='-')
|
self.axes.plot(x, y, local_shapes[element]['color'],
|
||||||
|
linestyle='-',
|
||||||
|
linewidth=local_shapes[element]['linewidth'])
|
||||||
|
|
||||||
elif obj_type == 'gerber':
|
elif obj_type == 'gerber':
|
||||||
if self.obj.options["multicolored"]:
|
if self.obj.options["multicolored"]:
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ class ShapeCollectionVisual(CompoundVisual):
|
|||||||
self.freeze()
|
self.freeze()
|
||||||
|
|
||||||
def add(self, shape=None, color=None, face_color=None, alpha=None, visible=True,
|
def add(self, shape=None, color=None, face_color=None, alpha=None, visible=True,
|
||||||
update=False, layer=1, tolerance=0.01):
|
update=False, layer=1, tolerance=0.01, linewidth=None):
|
||||||
"""
|
"""
|
||||||
Adds shape to collection
|
Adds shape to collection
|
||||||
:return:
|
:return:
|
||||||
@@ -253,6 +253,8 @@ class ShapeCollectionVisual(CompoundVisual):
|
|||||||
Layer number. 0 - lowest.
|
Layer number. 0 - lowest.
|
||||||
:param tolerance: float
|
:param tolerance: float
|
||||||
Geometry simplifying tolerance
|
Geometry simplifying tolerance
|
||||||
|
:param linewidth: int
|
||||||
|
Not used, for compatibility
|
||||||
:return: int
|
:return: int
|
||||||
Index of shape
|
Index of shape
|
||||||
"""
|
"""
|
||||||
|
|||||||
BIN
share/explode32.png
Normal file
BIN
share/explode32.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 779 B |
Reference in New Issue
Block a user