-clean-up before merge
This commit is contained in:
228
PlotCanvas.py
Normal file
228
PlotCanvas.py
Normal file
@@ -0,0 +1,228 @@
|
||||
############################################################
|
||||
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||
# http://caram.cl/software/flatcam #
|
||||
# Author: Juan Pablo Caram (c) #
|
||||
# Date: 2/5/2014 #
|
||||
# MIT Licence #
|
||||
############################################################
|
||||
|
||||
from PyQt5 import QtCore
|
||||
|
||||
import logging
|
||||
from VisPyCanvas import VisPyCanvas
|
||||
from VisPyVisuals import ShapeGroup, ShapeCollection, TextCollection, TextGroup, Cursor
|
||||
from vispy.scene.visuals import InfiniteLine, Line
|
||||
import numpy as np
|
||||
from vispy.geometry import Rect
|
||||
import time
|
||||
|
||||
log = logging.getLogger('base')
|
||||
|
||||
|
||||
class PlotCanvas(QtCore.QObject):
|
||||
"""
|
||||
Class handling the plotting area in the application.
|
||||
"""
|
||||
|
||||
def __init__(self, container, app):
|
||||
"""
|
||||
The constructor configures the VisPy figure that
|
||||
will contain all plots, creates the base axes and connects
|
||||
events to the plotting area.
|
||||
|
||||
:param container: The parent container in which to draw plots.
|
||||
:rtype: PlotCanvas
|
||||
"""
|
||||
|
||||
super(PlotCanvas, self).__init__()
|
||||
|
||||
self.app = app
|
||||
|
||||
# Parent container
|
||||
self.container = container
|
||||
|
||||
# workspace lines; I didn't use the rectangle because I didn't want to add another VisPy Node,
|
||||
# which might decrease performance
|
||||
self.b_line, self.r_line, self.t_line, self.l_line = None, None, None, None
|
||||
|
||||
# Attach to parent
|
||||
self.vispy_canvas = VisPyCanvas()
|
||||
|
||||
self.vispy_canvas.create_native()
|
||||
self.vispy_canvas.native.setParent(self.app.ui)
|
||||
self.container.addWidget(self.vispy_canvas.native)
|
||||
|
||||
### AXIS ###
|
||||
self.v_line = InfiniteLine(pos=0, color=(0.70, 0.3, 0.3, 1.0), vertical=True,
|
||||
parent=self.vispy_canvas.view.scene)
|
||||
|
||||
self.h_line = InfiniteLine(pos=0, color=(0.70, 0.3, 0.3, 1.0), vertical=False,
|
||||
parent=self.vispy_canvas.view.scene)
|
||||
|
||||
# draw a rectangle made out of 4 lines on the canvas to serve as a hint for the work area
|
||||
# all CNC have a limited workspace
|
||||
|
||||
self.draw_workspace()
|
||||
|
||||
# if self.app.defaults['global_workspace'] is True:
|
||||
# if self.app.general_options_form.general_group.units_radio.get_value().upper() == 'MM':
|
||||
# self.wkspace_t = Line(pos=)
|
||||
|
||||
self.shape_collections = []
|
||||
|
||||
self.shape_collection = self.new_shape_collection()
|
||||
self.app.pool_recreated.connect(self.on_pool_recreated)
|
||||
self.text_collection = self.new_text_collection()
|
||||
|
||||
# TODO: Should be setting to show/hide CNC job annotations (global or per object)
|
||||
self.text_collection.enabled = False
|
||||
|
||||
# draw a rectangle made out of 4 lines on the canvas to serve as a hint for the work area
|
||||
# all CNC have a limited workspace
|
||||
def draw_workspace(self):
|
||||
a = np.empty((0, 0))
|
||||
|
||||
a4p_in = np.array([(0, 0), (8.3, 0), (8.3, 11.7), (0, 11.7)])
|
||||
a4l_in = np.array([(0, 0), (11.7, 0), (11.7, 8.3), (0, 8.3)])
|
||||
a3p_in = np.array([(0, 0), (11.7, 0), (11.7, 16.5), (0, 16.5)])
|
||||
a3l_in = np.array([(0, 0), (16.5, 0), (16.5, 11.7), (0, 11.7)])
|
||||
|
||||
a4p_mm = np.array([(0, 0), (210, 0), (210, 297), (0, 297)])
|
||||
a4l_mm = np.array([(0, 0), (297, 0), (297,210), (0, 210)])
|
||||
a3p_mm = np.array([(0, 0), (297, 0), (297, 420), (0, 420)])
|
||||
a3l_mm = np.array([(0, 0), (420, 0), (420, 297), (0, 297)])
|
||||
|
||||
if self.app.general_options_form.general_group.units_radio.get_value().upper() == 'MM':
|
||||
if self.app.defaults['global_workspaceT'] == 'A4P':
|
||||
a = a4p_mm
|
||||
elif self.app.defaults['global_workspaceT'] == 'A4L':
|
||||
a = a4l_mm
|
||||
elif self.app.defaults['global_workspaceT'] == 'A3P':
|
||||
a = a3p_mm
|
||||
elif self.app.defaults['global_workspaceT'] == 'A3L':
|
||||
a = a3l_mm
|
||||
else:
|
||||
if self.app.defaults['global_workspaceT'] == 'A4P':
|
||||
a = a4p_in
|
||||
elif self.app.defaults['global_workspaceT'] == 'A4L':
|
||||
a = a4l_in
|
||||
elif self.app.defaults['global_workspaceT'] == 'A3P':
|
||||
a = a3p_in
|
||||
elif self.app.defaults['global_workspaceT'] == 'A3L':
|
||||
a = a3l_in
|
||||
|
||||
self.delete_workspace()
|
||||
|
||||
self.b_line = Line(pos=a[0:2], color=(0.70, 0.3, 0.3, 1.0),
|
||||
antialias= True, method='agg', parent=self.vispy_canvas.view.scene)
|
||||
self.r_line = Line(pos=a[1:3], color=(0.70, 0.3, 0.3, 1.0),
|
||||
antialias= True, method='agg', parent=self.vispy_canvas.view.scene)
|
||||
|
||||
self.t_line = Line(pos=a[2:4], color=(0.70, 0.3, 0.3, 1.0),
|
||||
antialias= True, method='agg', parent=self.vispy_canvas.view.scene)
|
||||
self.l_line = Line(pos=np.array((a[0], a[3])), color=(0.70, 0.3, 0.3, 1.0),
|
||||
antialias= True, method='agg', parent=self.vispy_canvas.view.scene)
|
||||
|
||||
if self.app.defaults['global_workspace'] is False:
|
||||
self.delete_workspace()
|
||||
|
||||
# delete the workspace lines from the plot by removing the parent
|
||||
def delete_workspace(self):
|
||||
try:
|
||||
self.b_line.parent = None
|
||||
self.r_line.parent = None
|
||||
self.t_line.parent = None
|
||||
self.l_line.parent = None
|
||||
except:
|
||||
pass
|
||||
|
||||
# redraw the workspace lines on the plot by readding them to the parent view.scene
|
||||
def restore_workspace(self):
|
||||
try:
|
||||
self.b_line.parent = self.vispy_canvas.view.scene
|
||||
self.r_line.parent = self.vispy_canvas.view.scene
|
||||
self.t_line.parent = self.vispy_canvas.view.scene
|
||||
self.l_line.parent = self.vispy_canvas.view.scene
|
||||
except:
|
||||
pass
|
||||
|
||||
def vis_connect(self, event_name, callback):
|
||||
return getattr(self.vispy_canvas.events, event_name).connect(callback)
|
||||
|
||||
def vis_disconnect(self, event_name, callback):
|
||||
getattr(self.vispy_canvas.events, event_name).disconnect(callback)
|
||||
|
||||
def zoom(self, factor, center=None):
|
||||
"""
|
||||
Zooms the plot by factor around a given
|
||||
center point. Takes care of re-drawing.
|
||||
|
||||
:param factor: Number by which to scale the plot.
|
||||
:type factor: float
|
||||
:param center: Coordinates [x, y] of the point around which to scale the plot.
|
||||
:type center: list
|
||||
:return: None
|
||||
"""
|
||||
self.vispy_canvas.view.camera.zoom(factor, center)
|
||||
|
||||
def new_shape_group(self):
|
||||
return ShapeGroup(self.shape_collection)
|
||||
|
||||
def new_shape_collection(self, **kwargs):
|
||||
# sc = ShapeCollection(parent=self.vispy_canvas.view.scene, pool=self.app.pool, **kwargs)
|
||||
# self.shape_collections.append(sc)
|
||||
# return sc
|
||||
return ShapeCollection(parent=self.vispy_canvas.view.scene, pool=self.app.pool, **kwargs)
|
||||
|
||||
def new_cursor(self):
|
||||
c = Cursor(pos=np.empty((0, 2)), parent=self.vispy_canvas.view.scene)
|
||||
c.antialias = 0
|
||||
return c
|
||||
|
||||
def new_text_group(self):
|
||||
return TextGroup(self.text_collection)
|
||||
|
||||
def new_text_collection(self, **kwargs):
|
||||
return TextCollection(parent=self.vispy_canvas.view.scene, **kwargs)
|
||||
|
||||
def fit_view(self, rect=None):
|
||||
|
||||
# Lock updates in other threads
|
||||
self.shape_collection.lock_updates()
|
||||
|
||||
if not rect:
|
||||
rect = Rect(-1, -1, 20, 20)
|
||||
try:
|
||||
rect.left, rect.right = self.shape_collection.bounds(axis=0)
|
||||
rect.bottom, rect.top = self.shape_collection.bounds(axis=1)
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
self.vispy_canvas.view.camera.rect = rect
|
||||
|
||||
self.shape_collection.unlock_updates()
|
||||
|
||||
def fit_center(self, loc, rect=None):
|
||||
|
||||
# Lock updates in other threads
|
||||
self.shape_collection.lock_updates()
|
||||
|
||||
if not rect:
|
||||
try:
|
||||
rect = Rect(loc[0]-20, loc[1]-20, 40, 40)
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
self.vispy_canvas.view.camera.rect = rect
|
||||
|
||||
self.shape_collection.unlock_updates()
|
||||
|
||||
def clear(self):
|
||||
pass
|
||||
|
||||
def redraw(self):
|
||||
self.shape_collection.redraw([])
|
||||
self.text_collection.redraw()
|
||||
|
||||
def on_pool_recreated(self, pool):
|
||||
self.shape_collection.pool = pool
|
||||
Reference in New Issue
Block a user