- in Geometry Editor - improvements and some issues are solved

This commit is contained in:
Marius Stanciu
2020-11-29 03:35:40 +02:00
committed by Marius
parent 6a3631a401
commit 89039a9606
2 changed files with 216 additions and 201 deletions

View File

@@ -7,6 +7,10 @@ CHANGELOG for FlatCAM beta
================================================= =================================================
29.11.2020
- in Geometry Editor - improvements and some issues are solved
28.11.2020 28.11.2020
- updated the Italian translation (by Massimiliano Golfetto) - updated the Italian translation (by Massimiliano Golfetto)

View File

@@ -481,7 +481,7 @@ class PaintOptionsTool(AppTool):
# Tool dia # Tool dia
ptdlabel = FCLabel('%s:' % _('Tool Dia')) ptdlabel = FCLabel('%s:' % _('Tool Dia'))
ptdlabel.setToolTip( ptdlabel.setToolTip(
_("Diameter of the tool to be used in the operation.") _("Diameter of the tool to be used in the operation.")
) )
grid.addWidget(ptdlabel, 0, 0) grid.addWidget(ptdlabel, 0, 0)
@@ -513,9 +513,9 @@ class PaintOptionsTool(AppTool):
# Margin # Margin
marginlabel = FCLabel('%s:' % _('Margin')) marginlabel = FCLabel('%s:' % _('Margin'))
marginlabel.setToolTip( marginlabel.setToolTip(
_("Distance by which to avoid\n" _("Distance by which to avoid\n"
"the edges of the polygon to\n" "the edges of the polygon to\n"
"be painted.") "be painted.")
) )
self.paintmargin_entry = FCDoubleSpinner() self.paintmargin_entry = FCDoubleSpinner()
self.paintmargin_entry.set_range(-10000.0000, 10000.0000) self.paintmargin_entry.set_range(-10000.0000, 10000.0000)
@@ -548,8 +548,8 @@ class PaintOptionsTool(AppTool):
# Connect lines # Connect lines
pathconnectlabel = FCLabel('%s:' % _("Connect")) pathconnectlabel = FCLabel('%s:' % _("Connect"))
pathconnectlabel.setToolTip( pathconnectlabel.setToolTip(
_("Draw lines between resulting\n" _("Draw lines between resulting\n"
"segments to minimize tool lifts.") "segments to minimize tool lifts.")
) )
self.pathconnect_cb = FCCheckBox() self.pathconnect_cb = FCCheckBox()
@@ -1163,7 +1163,7 @@ class TransformEditorTool(AppTool):
self.point_entry.hide() self.point_entry.hide()
self.point_button.hide() self.point_button.hide()
elif index == 2: # "Point" reference elif index == 2: # "Point" reference
self.point_label.show() self.point_label.show()
self.point_entry.show() self.point_entry.show()
self.point_button.show() self.point_button.show()
@@ -1174,7 +1174,7 @@ class TransformEditorTool(AppTool):
else: else:
ref_val = self.ref_combo.currentIndex() ref_val = self.ref_combo.currentIndex()
if ref_val == 0: # "Origin" reference if ref_val == 0: # "Origin" reference
return 0, 0 return 0, 0
elif ref_val == 1: # "Selection" reference elif ref_val == 1: # "Selection" reference
sel_list = self.draw_app.selected sel_list = self.draw_app.selected
@@ -1199,13 +1199,13 @@ class TransformEditorTool(AppTool):
if sel_list: if sel_list:
xmin, ymin, xmax, ymax = self.alt_bounds(sel_list) xmin, ymin, xmax, ymax = self.alt_bounds(sel_list)
if ref_val == 3: if ref_val == 3:
return xmin, ymin # lower left corner return xmin, ymin # lower left corner
elif ref_val == 4: elif ref_val == 4:
return xmax, ymin # lower right corner return xmax, ymin # lower right corner
elif ref_val == 5: elif ref_val == 5:
return xmax, ymax # upper right corner return xmax, ymax # upper right corner
else: else:
return xmin, ymax # upper left corner return xmin, ymax # upper left corner
else: else:
self.app.inform.emit('[ERROR_NOTCL] %s' % _("No shape selected.")) self.app.inform.emit('[ERROR_NOTCL] %s' % _("No shape selected."))
return "fail" return "fail"
@@ -1646,9 +1646,9 @@ class DrawToolShape(object):
the object can be a Polygon, Not a polygon, or a list the object can be a Polygon, Not a polygon, or a list
of such. Search is done recursively. of such. Search is done recursively.
:param: geometric object :param o: geometric object
:return: List of points :return: List of points
:rtype: list :rtype: list
""" """
pts = [] pts = []
@@ -1656,7 +1656,6 @@ class DrawToolShape(object):
try: try:
for subo in o: for subo in o:
pts += DrawToolShape.get_pts(subo) pts += DrawToolShape.get_pts(subo)
# Non-iterable # Non-iterable
except TypeError: except TypeError:
if o is not None: if o is not None:
@@ -1664,7 +1663,7 @@ class DrawToolShape(object):
if isinstance(o, DrawToolShape): if isinstance(o, DrawToolShape):
pts += DrawToolShape.get_pts(o.geo) pts += DrawToolShape.get_pts(o.geo)
# Descend into .exerior and .interiors # Descend into .exterior and .interiors
elif type(o) == Polygon: elif type(o) == Polygon:
pts += DrawToolShape.get_pts(o.exterior) pts += DrawToolShape.get_pts(o.exterior)
for i in o.interiors: for i in o.interiors:
@@ -1696,6 +1695,7 @@ class DrawToolShape(object):
Returns coordinates of rectangular bounds Returns coordinates of rectangular bounds
of geometry: (xmin, ymin, xmax, ymax). of geometry: (xmin, ymin, xmax, ymax).
""" """
# fixed issue of getting bounds only for one level lists of objects # fixed issue of getting bounds only for one level lists of objects
# now it can get bounds for nested lists of objects # now it can get bounds for nested lists of objects
def bounds_rec(shape_el): def bounds_rec(shape_el):
@@ -2503,6 +2503,7 @@ class FCPath(FCPolygon):
""" """
Resulting type: LineString Resulting type: LineString
""" """
def __init__(self, draw_app): def __init__(self, draw_app):
FCPolygon.__init__(self, draw_app) FCPolygon.__init__(self, draw_app)
self.draw_app = draw_app self.draw_app = draw_app
@@ -3326,8 +3327,8 @@ class FCTransform(FCShapeTool):
# ################ Main Application ############# # ################ Main Application #############
# ############################################### # ###############################################
class AppGeoEditor(QtCore.QObject): class AppGeoEditor(QtCore.QObject):
# will emit the name of the object that was just selected # will emit the name of the object that was just selected
item_selected = QtCore.pyqtSignal(str) item_selected = QtCore.pyqtSignal(str)
transform_complete = QtCore.pyqtSignal() transform_complete = QtCore.pyqtSignal()
@@ -4413,9 +4414,9 @@ class AppGeoEditor(QtCore.QObject):
try: try:
self.storage.insert(shape) self.storage.insert(shape)
except Exception as err: except Exception as err:
self.app.inform_shell.emit('%s\n%s' % ( _("Error on inserting shapes into storage."), str(err))) self.app.inform_shell.emit('%s\n%s' % (_("Error on inserting shapes into storage."), str(err)))
if build_ui is True: if build_ui is True:
self.build_ui_sig.emit() # Build UI self.build_ui_sig.emit() # Build UI
def delete_utility_geometry(self): def delete_utility_geometry(self):
""" """
@@ -4549,7 +4550,7 @@ class AppGeoEditor(QtCore.QObject):
return return
# Selection with left mouse button # Selection with left mouse button
if self.active_tool is not None and event.button == 1: if self.active_tool is not None:
# Dispatch event to active_tool # Dispatch event to active_tool
self.active_tool.click(self.snap(self.pos[0], self.pos[1])) self.active_tool.click(self.snap(self.pos[0], self.pos[1]))
@@ -4558,7 +4559,7 @@ class AppGeoEditor(QtCore.QObject):
if isinstance(self.active_tool, FCShapeTool) and self.active_tool.complete: if isinstance(self.active_tool, FCShapeTool) and self.active_tool.complete:
self.on_shape_complete() self.on_shape_complete()
if isinstance(self.active_tool, FCText): if isinstance(self.active_tool, (FCText, FCMove)):
self.select_tool("select") self.select_tool("select")
else: else:
self.select_tool(self.active_tool.name) self.select_tool(self.active_tool.name)
@@ -4922,7 +4923,7 @@ class AppGeoEditor(QtCore.QObject):
# plot_elements += self.plot_shape(geometry=geometry.interiors, color=color, linewidth=linewidth) # plot_elements += self.plot_shape(geometry=geometry.interiors, color=color, linewidth=linewidth)
if isinstance(geometry, Polygon): if isinstance(geometry, Polygon):
plot_elements.append(self.shapes.add(shape=geometry, color=color, face_color=color[:-2]+'50', layer=0, plot_elements.append(self.shapes.add(shape=geometry, color=color, face_color=color[:-2] + '50', layer=0,
tolerance=self.fcgeometry.drawing_tolerance, tolerance=self.fcgeometry.drawing_tolerance,
linewidth=linewidth)) linewidth=linewidth))
if isinstance(geometry, (LineString, LinearRing)): if isinstance(geometry, (LineString, LinearRing)):
@@ -4946,8 +4947,7 @@ class AppGeoEditor(QtCore.QObject):
self.shapes.clear(update=True) self.shapes.clear(update=True)
for shape in self.storage.get_objects(): for shape in self.storage.get_objects():
if shape.geo is None or shape.geo.is_empty or not shape.geo.is_valid:
if shape.geo is None: # TODO: This shouldn't have happened
continue continue
if shape in self.selected: if shape in self.selected:
@@ -4977,7 +4977,7 @@ class AppGeoEditor(QtCore.QObject):
for shape in self.active_tool.geometry: for shape in self.active_tool.geometry:
geom.append(shape.geo) geom.append(shape.geo)
except TypeError: except TypeError:
geom = self.active_tool.geometry.geo geom = [self.active_tool.geometry.geo]
if self.app.defaults['geometry_editor_milling_type'] == 'cl': if self.app.defaults['geometry_editor_milling_type'] == 'cl':
# reverse the geometry coordinates direction to allow creation of Gcode for climb milling # reverse the geometry coordinates direction to allow creation of Gcode for climb milling
@@ -4991,9 +4991,15 @@ class AppGeoEditor(QtCore.QObject):
pl.append(LinearRing(p.coords[::-1])) pl.append(LinearRing(p.coords[::-1]))
elif isinstance(p, LineString): elif isinstance(p, LineString):
pl.append(LineString(p.coords[::-1])) pl.append(LineString(p.coords[::-1]))
elif isinstance(p, MultiLineString):
for line in p.geoms:
pl.append(LineString(line.coords[::-1]))
elif isinstance(p, MultiPolygon): elif isinstance(p, MultiPolygon):
for poly in p.geoms: for poly in p.geoms:
pl.append(Polygon(poly.exterior.coords[::-1], poly.interiors)) pl.append(Polygon(poly.exterior.coords[::-1], poly.interiors))
else:
self.app.log.debug("AppGeoEditor.on_shape_complete() Error --> Unexpected Geometry %s" %
type(p))
try: try:
geom = MultiPolygon(pl) geom = MultiPolygon(pl)
@@ -5003,14 +5009,18 @@ class AppGeoEditor(QtCore.QObject):
pass 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)]
elif isinstance(geom, LinearRing) and geom is not None: elif isinstance(geom, LinearRing) and geom is not None:
geom = LinearRing(geom.coords[::-1]) geom = [LinearRing(geom.coords[::-1])]
elif isinstance(geom, LineString) and geom is not None: elif isinstance(geom, LineString) and geom is not None:
geom = LineString(geom.coords[::-1]) geom = [LineString(geom.coords[::-1])]
elif isinstance(geom, MultiLineString):
geom = [LineString(line.coords[::-1]) for line in geom.geoms]
elif isinstance(geom, MultiPolygon):
geom = [Polygon(poly.exterior.coords[::-1], poly.interiors) for poly in geom.geoms]
else: else:
self.app.log.debug("AppGeoEditor.on_shape_complete() Error --> Unexpected Geometry %s" % self.app.log.debug("AppGeoEditor.on_shape_complete() Error --> Unexpected Geometry %s" %
type(geom)) type(geom))
except Exception as e: except Exception as e:
self.app.log.debug("AppGeoEditor.on_shape_complete() Error --> %s" % str(e)) self.app.log.debug("AppGeoEditor.on_shape_complete() Error --> %s" % str(e))
return 'fail' return 'fail'
@@ -5029,7 +5039,7 @@ class AppGeoEditor(QtCore.QObject):
self.delete_utility_geometry() self.delete_utility_geometry()
self.tool_shape.clear(update=True) self.tool_shape.clear(update=True)
# Replot and reset tool. # Re-plot and reset tool.
self.replot() self.replot()
# self.active_tool = type(self.active_tool)(self) # self.active_tool = type(self.active_tool)(self)
@@ -5151,14 +5161,14 @@ class AppGeoEditor(QtCore.QObject):
if self.app.defaults['geometry_spindledir'] == 'CW': if self.app.defaults['geometry_spindledir'] == 'CW':
if self.app.defaults['geometry_editor_milling_type'] == 'cl': if self.app.defaults['geometry_editor_milling_type'] == 'cl':
milling_type = 1 # CCW motion = climb milling (spindle is rotating CW) milling_type = 1 # CCW motion = climb milling (spindle is rotating CW)
else: else:
milling_type = -1 # CW motion = conventional milling (spindle is rotating CW) milling_type = -1 # CW motion = conventional milling (spindle is rotating CW)
else: else:
if self.app.defaults['geometry_editor_milling_type'] == 'cl': if self.app.defaults['geometry_editor_milling_type'] == 'cl':
milling_type = -1 # CCW motion = climb milling (spindle is rotating CCW) milling_type = -1 # CCW motion = climb milling (spindle is rotating CCW)
else: else:
milling_type = 1 # CW motion = conventional milling (spindle is rotating CCW) milling_type = 1 # CW motion = conventional milling (spindle is rotating CCW)
def task_job(editor_obj): def task_job(editor_obj):
# Link shapes into editor. # Link shapes into editor.
@@ -5280,24 +5290,24 @@ class AppGeoEditor(QtCore.QObject):
:return: None. :return: None.
""" """
def work_task(self): def work_task(editor_self):
with self.app.proc_container.new(_("Working...")): with editor_self.app.proc_container.new(_("Working...")):
results = unary_union([t.geo for t in self.get_selected()]) results = unary_union([t.geo for t in editor_self.get_selected()])
if results.geom_type == 'MultiLineString': if results.geom_type == 'MultiLineString':
results = linemerge(results) results = linemerge(results)
# Delete originals. # Delete originals.
for_deletion = [s for s in self.get_selected()] for_deletion = [s for s in editor_self.get_selected()]
for shape in for_deletion: for shape in for_deletion:
self.delete_shape(shape) editor_self.delete_shape(shape)
# Selected geometry is now gone! # Selected geometry is now gone!
self.selected = [] editor_self.selected = []
self.add_shape(DrawToolShape(results)) editor_self.add_shape(DrawToolShape(results))
self.replot() editor_self.replot()
self.build_ui_sig.emit() editor_self.build_ui_sig.emit()
self.app.inform.emit('[success] %s' % _("Done.")) editor_self.app.inform.emit('[success] %s' % _("Done."))
self.app.worker_task.emit({'fcn': work_task, 'params': [self]}) self.app.worker_task.emit({'fcn': work_task, 'params': [self]})
@@ -5307,16 +5317,17 @@ class AppGeoEditor(QtCore.QObject):
:return: None :return: None
""" """
def work_task(self):
self.app.log.debug("AppGeoEditor.intersection_2()")
with self.app.proc_container.new(_("Working...")): def work_task(editor_self):
selected = self.get_selected() editor_self.app.log.debug("AppGeoEditor.intersection_2()")
with editor_self.app.proc_container.new(_("Working...")):
selected = editor_self.get_selected()
if len(selected) < 2: if len(selected) < 2:
self.app.inform.emit('[WARNING_NOTCL] %s' % editor_self.app.inform.emit('[WARNING_NOTCL] %s' %
_("A selection of minimum two items is required to do Intersection.")) _("A selection of minimum two items is required to do Intersection."))
self.select_tool('select') editor_self.select_tool('select')
return return
target = deepcopy(selected[0].geo) target = deepcopy(selected[0].geo)
@@ -5337,19 +5348,19 @@ class AppGeoEditor(QtCore.QObject):
target = target.exterior target = target.exterior
result = DrawToolShape(target) result = DrawToolShape(target)
self.add_shape(deepcopy(result)) editor_self.add_shape(deepcopy(result))
# Delete originals. # Delete originals.
for_deletion = [s for s in self.get_selected()] for_deletion = [s for s in editor_self.get_selected()]
for shape_el in for_deletion: for shape_el in for_deletion:
self.delete_shape(shape_el) editor_self.delete_shape(shape_el)
# Selected geometry is now gone! # Selected geometry is now gone!
self.selected = [] editor_self.selected = []
self.replot() editor_self.replot()
self.build_ui_sig.emit() editor_self.build_ui_sig.emit()
self.app.inform.emit('[success] %s' % _("Done.")) editor_self.app.inform.emit('[success] %s' % _("Done."))
self.app.worker_task.emit({'fcn': work_task, 'params': [self]}) self.app.worker_task.emit({'fcn': work_task, 'params': [self]})
@@ -5360,18 +5371,18 @@ class AppGeoEditor(QtCore.QObject):
:return: None :return: None
""" """
def work_task(self): def work_task(editor_self):
self.app.log.debug("AppGeoEditor.intersection()") editor_self.app.log.debug("AppGeoEditor.intersection()")
with self.app.proc_container.new(_("Working...")): with editor_self.app.proc_container.new(_("Working...")):
selected = self.get_selected() selected = editor_self.get_selected()
results = [] results = []
intact = [] intact = []
if len(selected) < 2: if len(selected) < 2:
self.app.inform.emit('[WARNING_NOTCL] %s' % editor_self.app.inform.emit('[WARNING_NOTCL] %s' %
_("A selection of minimum two items is required to do Intersection.")) _("A selection of minimum two items is required to do Intersection."))
self.select_tool('select') editor_self.select_tool('select')
return return
intersector = selected[0].geo intersector = selected[0].geo
@@ -5390,36 +5401,36 @@ class AppGeoEditor(QtCore.QObject):
if results: if results:
# Delete originals. # Delete originals.
for_deletion = [s for s in self.get_selected()] for_deletion = [s for s in editor_self.get_selected()]
for shape_el in for_deletion: for shape_el in for_deletion:
if shape_el not in intact: if shape_el not in intact:
self.delete_shape(shape_el) editor_self.delete_shape(shape_el)
for geo in results: for geo in results:
if geo.geom_type == 'MultiPolygon': if geo.geom_type == 'MultiPolygon':
for poly in geo.geoms: for poly in geo.geoms:
p_geo = [poly.exterior] + [ints for ints in poly.interiors] p_geo = [poly.exterior] + [ints for ints in poly.interiors]
for g in p_geo: for g in p_geo:
self.add_shape(DrawToolShape(g)) editor_self.add_shape(DrawToolShape(g))
elif geo.geom_type == 'Polygon': elif geo.geom_type == 'Polygon':
p_geo = [geo.exterior] + [ints for ints in geo.interiors] p_geo = [geo.exterior] + [ints for ints in geo.interiors]
for g in p_geo: for g in p_geo:
self.add_shape(DrawToolShape(g)) editor_self.add_shape(DrawToolShape(g))
else: else:
self.add_shape(DrawToolShape(geo)) editor_self.add_shape(DrawToolShape(geo))
# Selected geometry is now gone! # Selected geometry is now gone!
self.selected = [] editor_self.selected = []
self.replot() editor_self.replot()
self.build_ui_sig.emit() editor_self.build_ui_sig.emit()
self.app.inform.emit('[success] %s' % _("Done.")) editor_self.app.inform.emit('[success] %s' % _("Done."))
self.app.worker_task.emit({'fcn': work_task, 'params': [self]}) self.app.worker_task.emit({'fcn': work_task, 'params': [self]})
def subtract(self): def subtract(self):
def work_task(self): def work_task(editor_self):
with self.app.proc_container.new(_("Working...")): with editor_self.app.proc_container.new(_("Working...")):
selected = self.get_selected() selected = editor_self.get_selected()
try: try:
target = deepcopy(selected[0].geo) target = deepcopy(selected[0].geo)
tools = selected[1:] tools = selected[1:]
@@ -5430,24 +5441,24 @@ class AppGeoEditor(QtCore.QObject):
sub_geo = Polygon(tool.geo) sub_geo = Polygon(tool.geo)
target = target.difference(sub_geo) target = target.difference(sub_geo)
result = DrawToolShape(target) result = DrawToolShape(target)
self.add_shape(deepcopy(result)) editor_self.add_shape(deepcopy(result))
for_deletion = [s for s in self.get_selected()] for_deletion = [s for s in editor_self.get_selected()]
for shape in for_deletion: for shape in for_deletion:
self.delete_shape(shape) self.delete_shape(shape)
self.replot() editor_self.replot()
self.build_ui_sig.emit() editor_self.build_ui_sig.emit()
self.app.inform.emit('[success] %s' % _("Done.")) editor_self.app.inform.emit('[success] %s' % _("Done."))
except Exception as e: except Exception as e:
self.app.log.debug(str(e)) editor_self.app.log.debug(str(e))
self.app.worker_task.emit({'fcn': work_task, 'params': [self]}) self.app.worker_task.emit({'fcn': work_task, 'params': [self]})
def subtract_2(self): def subtract_2(self):
def work_task(self): def work_task(editor_self):
with self.app.proc_container.new(_("Working...")): with editor_self.app.proc_container.new(_("Working...")):
selected = self.get_selected() selected = editor_self.get_selected()
try: try:
target = deepcopy(selected[0].geo) target = deepcopy(selected[0].geo)
tools = selected[1:] tools = selected[1:]
@@ -5457,73 +5468,73 @@ class AppGeoEditor(QtCore.QObject):
sub_geo = Polygon(tool.geo) sub_geo = Polygon(tool.geo)
target = target.difference(sub_geo) target = target.difference(sub_geo)
result = DrawToolShape(target) result = DrawToolShape(target)
self.add_shape(deepcopy(result)) editor_self.add_shape(deepcopy(result))
self.delete_shape(selected[0]) editor_self.delete_shape(selected[0])
self.replot() editor_self.replot()
self.build_ui_sig.emit() editor_self.build_ui_sig.emit()
self.app.inform.emit('[success] %s' % _("Done.")) editor_self.app.inform.emit('[success] %s' % _("Done."))
except Exception as e: except Exception as e:
self.app.log.debug(str(e)) editor_self.app.log.debug(str(e))
self.app.worker_task.emit({'fcn': work_task, 'params': [self]}) self.app.worker_task.emit({'fcn': work_task, 'params': [self]})
def cutpath(self): def cutpath(self):
def work_task(self): def work_task(editor_self):
with self.app.proc_container.new(_("Working...")): with editor_self.app.proc_container.new(_("Working...")):
selected = self.get_selected() selected = editor_self.get_selected()
tools = selected[1:] tools = selected[1:]
toolgeo = unary_union([shp.geo for shp in tools]) toolgeo = unary_union([shp.geo for shp in tools])
target = selected[0] target = selected[0]
if type(target.geo) == Polygon: if type(target.geo) == Polygon:
for ring in poly2rings(target.geo): for ring in poly2rings(target.geo):
self.add_shape(DrawToolShape(ring.difference(toolgeo))) editor_self.add_shape(DrawToolShape(ring.difference(toolgeo)))
elif type(target.geo) == LineString or type(target.geo) == LinearRing: elif type(target.geo) == LineString or type(target.geo) == LinearRing:
self.add_shape(DrawToolShape(target.geo.difference(toolgeo))) editor_self.add_shape(DrawToolShape(target.geo.difference(toolgeo)))
elif type(target.geo) == MultiLineString: elif type(target.geo) == MultiLineString:
try: try:
for linestring in target.geo: for linestring in target.geo:
self.add_shape(DrawToolShape(linestring.difference(toolgeo))) editor_self.add_shape(DrawToolShape(linestring.difference(toolgeo)))
except Exception as e: except Exception as e:
self.app.log.warning("Current LinearString does not intersect the target. %s" % str(e)) editor_self.app.log.warning("Current LinearString does not intersect the target. %s" % str(e))
else: else:
self.app.log.warning("Not implemented. Object type: %s" % str(type(target.geo))) editor_self.app.log.warning("Not implemented. Object type: %s" % str(type(target.geo)))
return return
self.delete_shape(target) editor_self.delete_shape(target)
self.replot() editor_self.replot()
self.build_ui_sig.emit() editor_self.build_ui_sig.emit()
self.app.inform.emit('[success] %s' % _("Done.")) editor_self.app.inform.emit('[success] %s' % _("Done."))
self.app.worker_task.emit({'fcn': work_task, 'params': [self]}) self.app.worker_task.emit({'fcn': work_task, 'params': [self]})
def buffer(self, buf_distance, join_style): def buffer(self, buf_distance, join_style):
def work_task(self): def work_task(editor_self):
with self.app.proc_container.new(_("Working...")): with editor_self.app.proc_container.new(_("Working...")):
selected = self.get_selected() selected = editor_self.get_selected()
if buf_distance < 0: if buf_distance < 0:
self.app.inform.emit('[ERROR_NOTCL] %s' % msg = '[ERROR_NOTCL] %s' % _("Negative buffer value is not accepted. "
_("Negative buffer value is not accepted. Use Buffer interior to generate an " "Use Buffer interior to generate an 'inside' shape")
"'inside' shape")) editor_self.app.inform.emit(msg)
# deselect everything # deselect everything
self.selected = [] editor_self.selected = []
self.replot() editor_self.replot()
return 'fail' return 'fail'
if len(selected) == 0: if len(selected) == 0:
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Nothing selected.")) editor_self.app.inform.emit('[WARNING_NOTCL] %s' % _("Nothing selected."))
return 'fail' return 'fail'
if not isinstance(buf_distance, float): if not isinstance(buf_distance, float):
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Invalid distance.")) editor_self.app.inform.emit('[WARNING_NOTCL] %s' % _("Invalid distance."))
# deselect everything # deselect everything
self.selected = [] editor_self.selected = []
self.replot() editor_self.replot()
return 'fail' return 'fail'
results = [] results = []
@@ -5532,7 +5543,7 @@ class AppGeoEditor(QtCore.QObject):
if t.geo.geom_type == 'Polygon': if t.geo.geom_type == 'Polygon':
results.append(t.geo.exterior.buffer( results.append(t.geo.exterior.buffer(
buf_distance - 1e-10, buf_distance - 1e-10,
resolution=int(int(self.app.defaults["geometry_circle_steps"]) / 4), resolution=int(int(editor_self.app.defaults["geometry_circle_steps"]) / 4),
join_style=join_style) join_style=join_style)
) )
elif t.geo.geom_type == 'MultiLineString': elif t.geo.geom_type == 'MultiLineString':
@@ -5541,65 +5552,65 @@ class AppGeoEditor(QtCore.QObject):
b_geo = Polygon(line) b_geo = Polygon(line)
results.append(b_geo.buffer( results.append(b_geo.buffer(
buf_distance - 1e-10, buf_distance - 1e-10,
resolution=int(int(self.app.defaults["geometry_circle_steps"]) / 4), resolution=int(int(editor_self.app.defaults["geometry_circle_steps"]) / 4),
join_style=join_style).exterior join_style=join_style).exterior
) )
results.append(b_geo.buffer( results.append(b_geo.buffer(
-buf_distance + 1e-10, -buf_distance + 1e-10,
resolution=int(int(self.app.defaults["geometry_circle_steps"]) / 4), resolution=int(int(editor_self.app.defaults["geometry_circle_steps"]) / 4),
join_style=join_style).exterior join_style=join_style).exterior
) )
elif t.geo.geom_type in ['LineString', 'LinearRing']: elif t.geo.geom_type in ['LineString', 'LinearRing']:
if t.geo.is_ring: if t.geo.is_ring:
b_geo = Polygon(t.geo) b_geo = Polygon(t.geo)
results.append(b_geo.buffer( results.append(b_geo.buffer(
buf_distance - 1e-10, buf_distance - 1e-10,
resolution=int(int(self.app.defaults["geometry_circle_steps"]) / 4), resolution=int(int(editor_self.app.defaults["geometry_circle_steps"]) / 4),
join_style=join_style).exterior join_style=join_style).exterior
) )
results.append(b_geo.buffer( results.append(b_geo.buffer(
-buf_distance + 1e-10, -buf_distance + 1e-10,
resolution=int(int(self.app.defaults["geometry_circle_steps"]) / 4), resolution=int(int(editor_self.app.defaults["geometry_circle_steps"]) / 4),
join_style=join_style).exterior join_style=join_style).exterior
) )
if not results: if not results:
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed, the result is empty.")) editor_self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed, the result is empty."))
# deselect everything # deselect everything
self.selected = [] editor_self.selected = []
self.replot() editor_self.replot()
return 'fail' return 'fail'
for sha in results: for sha in results:
self.add_shape(DrawToolShape(sha)) editor_self.add_shape(DrawToolShape(sha))
self.replot() editor_self.replot()
self.build_ui_sig.emit() editor_self.build_ui_sig.emit()
self.app.inform.emit('[success] %s' % _("Done.")) editor_self.app.inform.emit('[success] %s' % _("Done."))
self.app.worker_task.emit({'fcn': work_task, 'params': [self]}) self.app.worker_task.emit({'fcn': work_task, 'params': [self]})
def buffer_int(self, buf_distance, join_style): def buffer_int(self, buf_distance, join_style):
def work_task(self): def work_task(editor_self):
with self.app.proc_container.new(_("Working...")): with editor_self.app.proc_container.new(_("Working...")):
selected = self.get_selected() selected = editor_self.get_selected()
if buf_distance < 0: if buf_distance < 0:
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Negative buffer value is not accepted.")) editor_self.app.inform.emit('[ERROR_NOTCL] %s' % _("Negative buffer value is not accepted."))
# deselect everything # deselect everything
self.selected = [] editor_self.selected = []
self.replot() editor_self.replot()
return 'fail' return 'fail'
if len(selected) == 0: if len(selected) == 0:
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Nothing selected.")) editor_self.app.inform.emit('[WARNING_NOTCL] %s' % _("Nothing selected."))
return 'fail' return 'fail'
if not isinstance(buf_distance, float): if not isinstance(buf_distance, float):
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Invalid distance.")) editor_self.app.inform.emit('[WARNING_NOTCL] %s' % _("Invalid distance."))
# deselect everything # deselect everything
self.selected = [] editor_self.selected = []
self.replot() editor_self.replot()
return 'fail' return 'fail'
results = [] results = []
@@ -5608,66 +5619,66 @@ class AppGeoEditor(QtCore.QObject):
if t.geo.geom_type == 'Polygon': if t.geo.geom_type == 'Polygon':
results.append(t.geo.exterior.buffer( results.append(t.geo.exterior.buffer(
-buf_distance + 1e-10, -buf_distance + 1e-10,
resolution=int(int(self.app.defaults["geometry_circle_steps"]) / 4), resolution=int(int(editor_self.app.defaults["geometry_circle_steps"]) / 4),
join_style=join_style).exterior join_style=join_style).exterior
) )
elif t.geo.geom_type == 'MultiLineString': elif t.geo.geom_type == 'MultiLineString':
for line in t.geo: for line in t.geo:
if line.is_ring: if line.is_ring:
b_geo = Polygon(line) b_geo = Polygon(line)
results.append(b_geo.buffer( results.append(b_geo.buffer(
-buf_distance + 1e-10, -buf_distance + 1e-10,
resolution=int(int(self.app.defaults["geometry_circle_steps"]) / 4), resolution=int(int(editor_self.app.defaults["geometry_circle_steps"]) / 4),
join_style=join_style).exterior join_style=join_style).exterior
) )
elif t.geo.geom_type in ['LineString', 'LinearRing']: elif t.geo.geom_type in ['LineString', 'LinearRing']:
if t.geo.is_ring: if t.geo.is_ring:
b_geo = Polygon(t.geo) b_geo = Polygon(t.geo)
results.append(b_geo.buffer( results.append(b_geo.buffer(
-buf_distance + 1e-10, -buf_distance + 1e-10,
resolution=int(int(self.app.defaults["geometry_circle_steps"]) / 4), resolution=int(int(editor_self.app.defaults["geometry_circle_steps"]) / 4),
join_style=join_style).exterior join_style=join_style).exterior
) )
if not results: if not results:
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed, the result is empty.")) editor_self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed, the result is empty."))
# deselect everything # deselect everything
self.selected = [] editor_self.selected = []
self.replot() editor_self.replot()
return 'fail' return 'fail'
for sha in results: for sha in results:
self.add_shape(DrawToolShape(sha)) editor_self.add_shape(DrawToolShape(sha))
self.replot() editor_self.replot()
self.build_ui_sig.emit() editor_self.build_ui_sig.emit()
self.app.inform.emit('[success] %s' % _("Done.")) editor_self.app.inform.emit('[success] %s' % _("Done."))
self.app.worker_task.emit({'fcn': work_task, 'params': [self]}) self.app.worker_task.emit({'fcn': work_task, 'params': [self]})
def buffer_ext(self, buf_distance, join_style): def buffer_ext(self, buf_distance, join_style):
def work_task(self): def work_task(editor_self):
with self.app.proc_container.new(_("Working...")): with editor_self.app.proc_container.new(_("Working...")):
selected = self.get_selected() selected = editor_self.get_selected()
if buf_distance < 0: if buf_distance < 0:
self.app.inform.emit('[ERROR_NOTCL] %s' % msg = '[ERROR_NOTCL] %s' % _("Negative buffer value is not accepted. "
_("Negative buffer value is not accepted. Use Buffer interior to generate an " "Use Buffer interior to generate an 'inside' shape")
"'inside' shape")) editor_self.app.inform.emit(msg)
# deselect everything # deselect everything
self.selected = [] editor_self.selected = []
self.replot() editor_self.replot()
return return
if len(selected) == 0: if len(selected) == 0:
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Nothing selected.")) editor_self.app.inform.emit('[WARNING_NOTCL] %s' % _("Nothing selected."))
return return
if not isinstance(buf_distance, float): if not isinstance(buf_distance, float):
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Invalid distance.")) editor_self.app.inform.emit('[WARNING_NOTCL] %s' % _("Invalid distance."))
# deselect everything # deselect everything
self.selected = [] editor_self.selected = []
self.replot() editor_self.replot()
return return
results = [] results = []
@@ -5676,62 +5687,62 @@ class AppGeoEditor(QtCore.QObject):
if t.geo.geom_type == 'Polygon': if t.geo.geom_type == 'Polygon':
results.append(t.geo.exterior.buffer( results.append(t.geo.exterior.buffer(
buf_distance - 1e-10, buf_distance - 1e-10,
resolution=int(int(self.app.defaults["geometry_circle_steps"]) / 4), resolution=int(int(editor_self.app.defaults["geometry_circle_steps"]) / 4),
join_style=join_style).exterior join_style=join_style).exterior
) )
elif t.geo.geom_type == 'MultiLineString': elif t.geo.geom_type == 'MultiLineString':
for line in t.geo: for line in t.geo:
if line.is_ring: if line.is_ring:
b_geo = Polygon(line) b_geo = Polygon(line)
results.append(b_geo.buffer( results.append(b_geo.buffer(
buf_distance - 1e-10, buf_distance - 1e-10,
resolution=int(int(self.app.defaults["geometry_circle_steps"]) / 4), resolution=int(int(editor_self.app.defaults["geometry_circle_steps"]) / 4),
join_style=join_style).exterior join_style=join_style).exterior
) )
elif t.geo.geom_type in ['LineString', 'LinearRing']: elif t.geo.geom_type in ['LineString', 'LinearRing']:
if t.geo.is_ring: if t.geo.is_ring:
b_geo = Polygon(t.geo) b_geo = Polygon(t.geo)
results.append(b_geo.buffer( results.append(b_geo.buffer(
buf_distance - 1e-10, buf_distance - 1e-10,
resolution=int(int(self.app.defaults["geometry_circle_steps"]) / 4), resolution=int(int(editor_self.app.defaults["geometry_circle_steps"]) / 4),
join_style=join_style).exterior join_style=join_style).exterior
) )
if not results: if not results:
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed, the result is empty.")) editor_self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed, the result is empty."))
# deselect everything # deselect everything
self.selected = [] editor_self.selected = []
self.replot() editor_self.replot()
return 'fail' return 'fail'
for sha in results: for sha in results:
self.add_shape(DrawToolShape(sha)) editor_self.add_shape(DrawToolShape(sha))
self.replot() editor_self.replot()
self.build_ui_sig.emit() editor_self.build_ui_sig.emit()
self.app.inform.emit('[success] %s' % _("Done.")) editor_self.app.inform.emit('[success] %s' % _("Done."))
self.app.worker_task.emit({'fcn': work_task, 'params': [self]}) self.app.worker_task.emit({'fcn': work_task, 'params': [self]})
def paint(self, tooldia, overlap, margin, connect, contour, method): def paint(self, tooldia, overlap, margin, connect, contour, method):
def work_task(self): def work_task(editor_self):
with self.app.proc_container.new(_("Working...")): with editor_self.app.proc_container.new(_("Working...")):
if overlap >= 100: if overlap >= 100:
self.app.inform.emit('[ERROR_NOTCL] %s' % editor_self.app.inform.emit('[ERROR_NOTCL] %s' %
_("Could not do Paint. Overlap value has to be less than 100%%.")) _("Could not do Paint. Overlap value has to be less than 100%%."))
return return
self.paint_tooldia = tooldia editor_self.paint_tooldia = tooldia
selected = self.get_selected() selected = editor_self.get_selected()
if len(selected) == 0: if len(selected) == 0:
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Nothing selected.")) editor_self.app.inform.emit('[WARNING_NOTCL] %s' % _("Nothing selected."))
return return
for param in [tooldia, overlap, margin]: for param in [tooldia, overlap, margin]:
if not isinstance(param, float): if not isinstance(param, float):
param_name = [k for k, v in locals().items() if v is param][0] param_name = [k for k, v in locals().items() if v is param][0]
self.app.inform.emit('[WARNING] %s: %s' % (_("Invalid value for"), str(param))) editor_self.app.inform.emit('[WARNING] %s: %s' % (_("Invalid value for"), str(param)))
results = [] results = []
@@ -5774,25 +5785,25 @@ class AppGeoEditor(QtCore.QObject):
if method == _("Seed"): if method == _("Seed"):
cp = Geometry.clear_polygon2( cp = Geometry.clear_polygon2(
self, polygon_to_clear=poly_buf, tooldia=tooldia, editor_self, polygon_to_clear=poly_buf, tooldia=tooldia,
steps_per_circle=self.app.defaults["geometry_circle_steps"], steps_per_circle=editor_self.app.defaults["geometry_circle_steps"],
overlap=overlap, contour=contour, connect=connect) overlap=overlap, contour=contour, connect=connect)
elif method == _("Lines"): elif method == _("Lines"):
cp = Geometry.clear_polygon3( cp = Geometry.clear_polygon3(
self, polygon=poly_buf, tooldia=tooldia, editor_self, polygon=poly_buf, tooldia=tooldia,
steps_per_circle=self.app.defaults["geometry_circle_steps"], steps_per_circle=editor_self.app.defaults["geometry_circle_steps"],
overlap=overlap, contour=contour, connect=connect) overlap=overlap, contour=contour, connect=connect)
else: else:
cp = Geometry.clear_polygon( cp = Geometry.clear_polygon(
self, polygon=poly_buf, tooldia=tooldia, editor_self, polygon=poly_buf, tooldia=tooldia,
steps_per_circle=self.app.defaults["geometry_circle_steps"], steps_per_circle=editor_self.app.defaults["geometry_circle_steps"],
overlap=overlap, contour=contour, connect=connect) overlap=overlap, contour=contour, connect=connect)
if cp is not None: if cp is not None:
local_results += list(cp.get_objects()) local_results += list(cp.get_objects())
except Exception as e: except Exception as e:
self.app.log.debug("Could not Paint the polygons. %s" % str(e)) editor_self.app.log.debug("Could not Paint the polygons. %s" % str(e))
self.app.inform.emit( editor_self.app.inform.emit(
'[ERROR] %s\n%s' % (_("Could not do Paint. Try a different combination of parameters. " '[ERROR] %s\n%s' % (_("Could not do Paint. Try a different combination of parameters. "
"Or a different method of Paint"), str(e)) "Or a different method of Paint"), str(e))
) )
@@ -5803,10 +5814,10 @@ class AppGeoEditor(QtCore.QObject):
# This is a dirty patch: # This is a dirty patch:
for r in results: for r in results:
self.add_shape(DrawToolShape(r)) editor_self.add_shape(DrawToolShape(r))
self.replot() editor_self.replot()
self.build_ui_sig.emit() editor_self.build_ui_sig.emit()
self.app.inform.emit('[success] %s' % _("Done.")) editor_self.app.inform.emit('[success] %s' % _("Done."))
self.app.worker_task.emit({'fcn': work_task, 'params': [self]}) self.app.worker_task.emit({'fcn': work_task, 'params': [self]})