Merged in legacy_2D (pull request #2)

Legacy 2D
This commit is contained in:
Marius Stanciu 2019-09-22 11:04:30 +00:00
commit c8a121d9e1
10 changed files with 195 additions and 60 deletions

View File

@ -124,7 +124,7 @@ class App(QtCore.QObject):
# ################## Version and VERSION DATE ##############################
# ##########################################################################
version = 8.97
version_date = "2019/09/20"
version_date = "2019/09/22"
beta = True
engine = '3D'
@ -2760,7 +2760,7 @@ class App(QtCore.QObject):
:param name: String that store the project path and project name
:return: None
"""
self.ui.setWindowTitle('FlatCAM %s %s - %s - (%s) %s' %
self.ui.setWindowTitle('FlatCAM %s %s - %s - [%s] %s' %
(self.version,
('BETA' if self.beta else ''),
platform.architecture()[0],
@ -7719,10 +7719,9 @@ class App(QtCore.QObject):
if self.grid_status() == True:
pos = self.geo_editor.snap(pos_canvas[0], pos_canvas[1])
if self.is_legacy is False:
# Update cursor
self.app_cursor.set_data(np.asarray([(pos[0], pos[1])]),
symbol='++', edge_color='black', size=20)
# Update cursor
self.app_cursor.set_data(np.asarray([(pos[0], pos[1])]),
symbol='++', edge_color='black', size=20)
else:
pos = (pos_canvas[0], pos_canvas[1])
@ -7766,7 +7765,7 @@ class App(QtCore.QObject):
obj.isHovering = True
obj.notHovering = True
# create the selection box around the selected object
self.draw_hover_shape(obj, color='#d1e0e0')
self.draw_hover_shape(obj, color='#d1e0e0FF')
else:
if obj.notHovering is True:
obj.notHovering = False

View File

@ -1356,11 +1356,26 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
except TypeError:
geometry = [geometry]
# if self.app.is_legacy is False:
def random_color():
color = np.random.rand(4)
color[3] = 1
return color
if self.app.is_legacy is False:
def random_color():
color = np.random.rand(4)
color[3] = 1
return color
else:
def random_color():
while True:
color = np.random.rand(4)
color[3] = 1
new_color = '#'
for idx in range(len(color)):
new_color += '%x' % int(color[idx] * 255)
# do it until a valid color is generated
# a valid color has the # symbol, another 6 chars for the color and the last 2 chars for alpha
# for a total of 9 chars
if len(new_color) == 9:
break
return new_color
try:
if self.options["solid"]:
@ -1395,11 +1410,14 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
self.shapes.redraw()
except (ObjectDeleted, AttributeError):
self.shapes.clear(update=True)
except Exception as e:
log.debug("FlatCAMGerber.plot() --> %s" % str(e))
# experimental plot() when the solid_geometry is stored in the self.apertures
def plot_aperture(self, **kwargs):
def plot_aperture(self, run_thread=True, **kwargs):
"""
:param run_thread: if True run the aperture plot as a thread in a worker
:param kwargs: color and face_color
:return:
"""
@ -1429,31 +1447,34 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
else:
visibility = kwargs['visible']
with self.app.proc_container.new(_("Plotting Apertures")) as proc:
with self.app.proc_container.new(_("Plotting Apertures")):
self.app.progress.emit(30)
def job_thread(app_obj):
self.app.progress.emit(30)
try:
if aperture_to_plot_mark in self.apertures:
for elem in self.apertures[aperture_to_plot_mark]['geometry']:
if 'solid' in elem:
geo = elem['solid']
if type(geo) == Polygon or type(geo) == LineString:
self.add_mark_shape(apid=aperture_to_plot_mark, shape=geo, color=color,
face_color=color, visible=visibility)
else:
for el in geo:
self.add_mark_shape(apid=aperture_to_plot_mark, shape=el, color=color,
geo = elem['solid']
if type(geo) == Polygon or type(geo) == LineString:
self.add_mark_shape(apid=aperture_to_plot_mark, shape=geo, color=color,
face_color=color, visible=visibility)
else:
for el in geo:
self.add_mark_shape(apid=aperture_to_plot_mark, shape=el, color=color,
face_color=color, visible=visibility)
self.mark_shapes[aperture_to_plot_mark].redraw()
self.app.progress.emit(100)
except (ObjectDeleted, AttributeError):
self.clear_plot_apertures()
except Exception as e:
print(str(e))
self.app.worker_task.emit({'fcn': job_thread, 'params': [self]})
if run_thread:
self.app.worker_task.emit({'fcn': job_thread, 'params': [self]})
else:
job_thread(self)
def clear_plot_apertures(self, aperture='all'):
"""
@ -1497,8 +1518,9 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
if self.ui.apertures_table.cellWidget(cw_row, 5).isChecked():
self.marked_rows.append(True)
# self.plot_aperture(color='#2d4606bf', marked_aperture=aperture, visible=True)
self.plot_aperture(color=self.app.defaults['global_sel_draw_color'], marked_aperture=aperture, visible=True)
self.mark_shapes[aperture].redraw()
self.plot_aperture(color=self.app.defaults['global_sel_draw_color'] + 'FF',
marked_aperture=aperture, visible=True, run_thread=True)
# self.mark_shapes[aperture].redraw()
else:
self.marked_rows.append(False)
self.clear_plot_apertures(aperture=aperture)
@ -1534,7 +1556,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
if mark_all:
for aperture in self.apertures:
# self.plot_aperture(color='#2d4606bf', marked_aperture=aperture, visible=True)
self.plot_aperture(color=self.app.defaults['global_sel_draw_color'],
self.plot_aperture(color=self.app.defaults['global_sel_draw_color'] + 'FF',
marked_aperture=aperture, visible=True)
# HACK: enable/disable the grid for a better look
self.app.ui.grid_snap_btn.trigger()

View File

@ -18,6 +18,11 @@ CAD program, and create G-Code for Isolation routing.
- fixed display of distance labels and code optimizations in ToolPaint and NCC Tool
- adjusted axis at startup for legacy graphic engine plotcanvas
- when the graphic engine is changed in Edit -> Preferences -> General -> App Preferences, the application will restart
- made hover shapes work in legacy graphic engine
- fixed bug in display of the apertures marked in the Aperture table found in the Gerber Selected tab and through this made it to also work with the legacy graphic engine
- fixed annotation in Mark Area Tool in Gerber Editor to work in legacy graphic engine
- fixed the MultiColor plot option Gerber selected tab to work in legacy graphic engine
- documented some methods in the ShapeCollectionLegacy class
21.09.2019

View File

@ -3655,9 +3655,9 @@ class FlatCAMExcEditor(QtCore.QObject):
# ## Snap coordinates
if self.app.grid_status() == True:
x, y = self.app.geo_editor.snap(x, y)
if self.app.is_legacy is False:
# Update cursor
self.app.app_cursor.set_data(np.asarray([(x, y)]), symbol='++', edge_color='black', size=20)
# Update cursor
self.app.app_cursor.set_data(np.asarray([(x, y)]), symbol='++', edge_color='black', size=20)
self.snap_x = x
self.snap_y = y
@ -3704,9 +3704,8 @@ class FlatCAMExcEditor(QtCore.QObject):
else:
self.app.selection_type = None
if self.app.is_legacy is False:
# Update cursor
self.app.app_cursor.set_data(np.asarray([(x, y)]), symbol='++', edge_color='black', size=20)
# Update cursor
self.app.app_cursor.set_data(np.asarray([(x, y)]), symbol='++', edge_color='black', size=20)
def on_canvas_key_release(self, event):
self.key = None

View File

@ -3739,9 +3739,9 @@ class FlatCAMGeoEditor(QtCore.QObject):
# ### Snap coordinates ###
if self.app.grid_status() == True:
x, y = self.snap(x, y)
if self.app.is_legacy is False:
# Update cursor
self.app.app_cursor.set_data(np.asarray([(x, y)]), symbol='++', edge_color='black', size=20)
# Update cursor
self.app.app_cursor.set_data(np.asarray([(x, y)]), symbol='++', edge_color='black', size=20)
self.snap_x = x
self.snap_y = y

View File

@ -2607,8 +2607,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.ma_lower_threshold_entry = FCEntry()
self.ma_lower_threshold_entry.setValidator(QtGui.QDoubleValidator(0.0000, 9999.9999, 4))
ma_form_layout.addRow(self.ma_upper_threshold_lbl, self.ma_upper_threshold_entry)
ma_form_layout.addRow(self.ma_lower_threshold_lbl, self.ma_lower_threshold_entry)
ma_form_layout.addRow(self.ma_upper_threshold_lbl, self.ma_upper_threshold_entry)
# Buttons
hlay_ma = QtWidgets.QHBoxLayout()
@ -2829,7 +2829,11 @@ class FlatCAMGrbEditor(QtCore.QObject):
from flatcamGUI.PlotCanvasLegacy import ShapeCollectionLegacy
self.shapes = ShapeCollectionLegacy(obj=self, app=self.app, name='shapes_grb_editor')
self.tool_shape = ShapeCollectionLegacy(obj=self, app=self.app, name='tool_shapes_grb_editor')
self.ma_annotation = ShapeCollectionLegacy(obj=self, app=self.app, name='ma_anno_grb_editor')
self.ma_annotation = ShapeCollectionLegacy(
obj=self,
app=self.app,
name='ma_anno_grb_editor',
annotation_job=True)
self.app.pool_recreated.connect(self.pool_recreated)
@ -2983,8 +2987,8 @@ class FlatCAMGrbEditor(QtCore.QObject):
self.buffer_distance_entry.set_value(self.app.defaults["gerber_editor_buff_f"])
self.scale_factor_entry.set_value(self.app.defaults["gerber_editor_scale_f"])
self.ma_upper_threshold_entry.set_value(self.app.defaults["gerber_editor_ma_low"])
self.ma_lower_threshold_entry.set_value(self.app.defaults["gerber_editor_ma_high"])
self.ma_upper_threshold_entry.set_value(self.app.defaults["gerber_editor_ma_high"])
self.ma_lower_threshold_entry.set_value(self.app.defaults["gerber_editor_ma_low"])
self.apsize_entry.set_value(self.app.defaults["gerber_editor_newsize"])
self.aptype_cb.set_value(self.app.defaults["gerber_editor_newtype"])
@ -4392,9 +4396,9 @@ class FlatCAMGrbEditor(QtCore.QObject):
# # ## Snap coordinates
if self.app.grid_status() == True:
x, y = self.app.geo_editor.snap(x, y)
if self.app.is_legacy is False:
# Update cursor
self.app.app_cursor.set_data(np.asarray([(x, y)]), symbol='++', edge_color='black', size=20)
# Update cursor
self.app.app_cursor.set_data(np.asarray([(x, y)]), symbol='++', edge_color='black', size=20)
self.snap_x = x
self.snap_y = y
@ -4835,7 +4839,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
except Exception as e:
lower_threshold_val = 0.0
if area < float(upper_threshold_val) and area > float(lower_threshold_val):
if float(upper_threshold_val) > area > float(lower_threshold_val):
current_pos = geo_el['solid'].exterior.coords[-1]
text_elem = '%.4f' % area
text.append(text_elem)
@ -4844,7 +4848,7 @@ class FlatCAMGrbEditor(QtCore.QObject):
if text:
self.ma_annotation.set(text=text, pos=position, visible=True,
font_size=self.app.defaults["cncjob_annotation_fontsize"],
color=self.app.defaults["global_sel_draw_color"])
color='#000000FF')
self.app.inform.emit('[success] %s' %
_("Polygon areas marked."))
else:

View File

@ -4,6 +4,7 @@
# Author: Juan Pablo Caram (c) #
# Date: 2/5/2014 #
# MIT Licence #
# Modified by Marius Stanciu 09/21/2019 #
############################################################
from PyQt5 import QtGui, QtCore, QtWidgets
@ -26,6 +27,14 @@ import FlatCAMApp
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
mpl_use("Qt5Agg")
log = logging.getLogger('base')
@ -617,7 +626,12 @@ class PlotCanvasLegacy(QtCore.QObject):
return width / xpx, height / ypx
class FakeCursor():
class FakeCursor:
"""
This is a fake cursor to ensure compatibility with the OpenGL engine (VisPy).
This way I don't have to chane (disable) things related to the cursor all over when
using the low performance Matplotlib 2D graphic engine.
"""
def __init__(self):
self._enabled = True
@ -629,9 +643,17 @@ class FakeCursor():
def enabled(self, value):
self._enabled = value
def set_data(self, pos, **kwargs):
"""Internal event handler to draw the cursor when the mouse moves."""
pass
class MplCursor(Cursor):
"""
Unfortunately this gets attached to the current axes and if a new axes is added
it will not be showed until that axes is deleted.
Not the kind of behavior needed here so I don't use it anymore.
"""
def __init__(self, axes, color='red', linewidth=1):
super().__init__(ax=axes, useblit=True, color=color, linewidth=linewidth)
@ -687,11 +709,23 @@ class MplCursor(Cursor):
class ShapeCollectionLegacy:
"""
This will create the axes for each collection of shapes and will also
hold the collection of shapes into a dict self._shapes.
This handles the shapes redraw on canvas.
"""
def __init__(self, obj, app, name=None, annotation_job=None):
"""
def __init__(self, obj, app, name=None):
:param obj: this is the object to which the shapes collection is attached and for
which it will have to draw shapes
:param app: this is the FLatCAM.App usually, needed because we have to access attributes there
:param name: this is the name given to the Matplotlib axes; it needs to be unique due of Matplotlib requurements
:param annotation_job: make this True if the job needed is just for annotation
"""
self.obj = obj
self.app = app
self.annotation_job = annotation_job
self._shapes = dict()
self.shape_dict = dict()
@ -719,7 +753,23 @@ class ShapeCollectionLegacy:
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):
"""
This function will add shapes to the shape collection
:param shape: the Shapely shape to be added to the shape collection
:param color: edge color of the shape, hex value
:param face_color: the body color of the shape, hex value
:param alpha: level of transparency of the shape [0.0 ... 1.0]; Float
:param visible: if True will allow the shapes to be added
:param update: not used; just for compatibility with VIsPy canvas
:param layer: just for compatibility with VIsPy canvas
:param tolerance: just for compatibility with VIsPy canvas
:param obj: not used
:param gcode_parsed: not used; just for compatibility with VIsPy canvas
:param tool_tolerance: just for compatibility with VIsPy canvas
:param tooldia:
:return:
"""
self._color = color[:-2] if color is not None else None
self._face_color = face_color[:-2] if face_color is not None else None
self._alpha = int(face_color[-2:], 16) / 255 if face_color is not None else 0.75
@ -730,7 +780,7 @@ class ShapeCollectionLegacy:
self._visible = visible
self._update = update
# CNCJob oject related arguments
# CNCJob object related arguments
self._obj = obj
self._gcode_parsed = gcode_parsed
self._tool_tolerance = tool_tolerance
@ -768,6 +818,12 @@ class ShapeCollectionLegacy:
return self.shape_id
def clear(self, update=None):
"""
Clear the canvas of the shapes.
:param update:
:return: None
"""
self._shapes.clear()
self.shape_id = 0
@ -778,6 +834,11 @@ class ShapeCollectionLegacy:
self.redraw()
def redraw(self):
"""
This draw the shapes in the shapes collection, on canvas
:return: None
"""
path_num = 0
local_shapes = deepcopy(self._shapes)
@ -887,6 +948,37 @@ class ShapeCollectionLegacy:
self.app.plotcanvas.auto_adjust_axes()
def set(self, text, pos, visible=True, font_size=16, color=None):
"""
This will set annotations on the canvas.
:param text: a list of text elements to be used as annotations
:param pos: a list of positions for showing the text elements above
:param visible: if True will display annotations, if False will clear them on canvas
:param font_size: the font size or the annotations
:param color: color of the annotations
:return: None
"""
if color is None:
color = "#000000FF"
if visible is not True:
self.clear()
return
if len(text) != len(pos):
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Could not annotate due of a difference between the number "
"of text elements and the number of text positions."))
return
for idx in range(len(text)):
try:
self.axes.annotate(text[idx], xy=pos[idx], xycoords='data', fontsize=font_size, color=color)
except Exception as e:
log.debug("ShapeCollectionLegacy.set() --> %s" % str(e))
self.app.plotcanvas.auto_adjust_axes()
@property
def visible(self):
return self._visible
@ -900,3 +992,17 @@ class ShapeCollectionLegacy:
if self._visible is False:
self.redraw()
self._visible = value
@property
def enabled(self):
return self._visible
@enabled.setter
def enabled(self, value):
if value is False:
self.axes.cla()
self.app.plotcanvas.auto_adjust_axes()
else:
if self._visible is False:
self.redraw()
self._visible = value

View File

@ -343,10 +343,10 @@ class Measurement(FlatCAMTool):
if self.app.grid_status() == True:
pos = self.app.geo_editor.snap(pos_canvas[0], pos_canvas[1])
if self.app.is_legacy is False:
# Update cursor
self.app.app_cursor.set_data(np.asarray([(pos[0], pos[1])]),
symbol='++', edge_color='black', size=20)
# Update cursor
self.app.app_cursor.set_data(np.asarray([(pos[0], pos[1])]),
symbol='++', edge_color='black', size=20)
else:
pos = (pos_canvas[0], pos_canvas[1])

View File

@ -1280,9 +1280,9 @@ class NonCopperClear(FlatCAMTool, Gerber):
if self.app.grid_status() == True:
# Update cursor
curr_pos = self.app.geo_editor.snap(curr_pos[0], curr_pos[1])
if self.app.is_legacy is False:
self.app.app_cursor.set_data(np.asarray([(curr_pos[0], curr_pos[1])]),
symbol='++', edge_color='black', size=20)
self.app.app_cursor.set_data(np.asarray([(curr_pos[0], curr_pos[1])]),
symbol='++', edge_color='black', size=20)
# update the positions on status bar
self.app.ui.position_label.setText("&nbsp;&nbsp;&nbsp;&nbsp;<b>X</b>: %.4f&nbsp;&nbsp; "

View File

@ -1183,9 +1183,9 @@ class ToolPaint(FlatCAMTool, Gerber):
if self.app.grid_status() == True:
# Update cursor
curr_pos = self.app.geo_editor.snap(curr_pos[0], curr_pos[1])
if self.app.is_legacy is False:
self.app.app_cursor.set_data(np.asarray([(curr_pos[0], curr_pos[1])]),
symbol='++', edge_color='black', size=20)
self.app.app_cursor.set_data(np.asarray([(curr_pos[0], curr_pos[1])]),
symbol='++', edge_color='black', size=20)
# update the positions on status bar
self.app.ui.position_label.setText("&nbsp;&nbsp;&nbsp;&nbsp;<b>X</b>: %.4f&nbsp;&nbsp; "