import sys
import numpy as np
from vispy import app, scene
from vispy.visuals.transforms import STTransform
from vispy.scene.visuals import Ellipse, Line
class PaintCamera(scene.PanZoomCamera):
def __init__(self, rect=(0, 0, 1, 1), aspect=None, **kwargs):
super(PaintCamera, self).__init__(**kwargs)
self.transform = STTransform()
self.aspect = aspect
self._rect = None
self.rect = rect
def viewbox_mouse_event(self, event):
global old_mouse_coord
# Standard mouse wheel handling
if event.type == 'mouse_wheel':
center = self._scene_transform.imap(event.pos)
self.zoom((1 + self.zoom_factor) ** (-event.delta[1] * 30), center)
event.handled = True
elif event.type == 'mouse_press':
ttf = self.scene_node.node_transform(self)
mouse_coord = list(map(int, ttf.map(event.pos)))
# Draw an ellipse
ellipse = Ellipse(center=(0, 0), radius=(10, 10),
color="red", border_width=2, border_color="white",
num_segments=10, parent=view.scene)
# Move the ellipse at mouse coordinates
ellipse.transform = STTransform(translate=[mouse_coord[0], mouse_coord[1]])
# I can't understand why if I write:
# ellipse = Ellipse(center=(mouse_coord[0], mouse_coord[1])...
# the position of ellipse is different
self.update()
# Store the coordinates for successive use
old_mouse_coord = mouse_coord
event.handled = True
elif event.type == 'mouse_move':
ttf = self.scene_node.node_transform(self)
mouse_coord = list(map(int, ttf.map(event.pos)))
# Draw another ellipse and move
ellipse = Ellipse(center=(0, 0), radius=(10, 10),
color="green", border_width=2, border_color="white",
num_segments=10, parent=view.scene)
ellipse.transform = STTransform(translate=[mouse_coord[0], mouse_coord[1]])
# Draw a line between old_mouse_coord and mouse_coord
coord_linea = np.array([[old_mouse_coord[0], old_mouse_coord[1]], [mouse_coord[0], mouse_coord[1]]])
Line(coord_linea, width=20, color="white", parent=view.scene)
# You can use method ="agg" and width will be respected but it will be very slow
# Line(coord_linea, width=20, color="white", parent=view.scene, method ="agg")
# Store the coordinates for successive use
old_mouse_coord = mouse_coord
self.update()
event.handled = True
else:
event.handled = False
# Create the SceneCanvas and Viewbox
canvas = scene.SceneCanvas(keys='interactive', size=(800, 600))
canvas.size = 800, 600
canvas.show()
view = canvas.central_widget.add_view()
# Set the camera
view.camera = PaintCamera(aspect=1)
view.camera.flip = (0, 1, 0)
view.camera.set_range((0, 1000, 0, 1000))
if __name__ == '__main__' and sys.flags.interactive == 0:
app.run()
Try: simply click and drag.
import sys
import numpy as np
from vispy import app,
scene
canvas = scene.SceneCanvas(keys='interactive', show=True)
vista = canvas.central_widget.add_view()
# vista.camera=scene.PanZoomCamera(aspect=1)
pointer = scene.visuals.Markers(parent=vista.scene)
canvas.update()
@canvas.connect
def on_mouse_press(event):
global new_coord, line, ellipse, pointer
pp = event.pos
new_coord = np.array([pp, pp + 0.001])
line = scene.visuals.Line(pos=new_coord, color="red", parent=vista.scene, width=20, method="agg")
# line = scene.visuals.Line(pos=new_coord, color="red", parent=vista.scene, width=10, method="gl")
pointer.set_data(pos=np.array([pp]))
canvas.update()
@canvas.connect
def on_mouse_move(event):
global new_coord, pointer
pp = event.pos
pointer.set_data(pos=np.array([pp]))
if event.button == 1:
new_coord = np.append(new_coord, [pp], axis=0)
line.set_data(pos=new_coord)
canvas.update()
if __name__ == '__main__':
canvas.show()
if sys.flags.interactive == 0:
app.run()
import sys
import numpy as np
from vispy import app, scene
canvas = scene.SceneCanvas(keys='interactive', show=True)
vista = canvas.central_widget.add_view()
pointer = scene.visuals.Ellipse(center=(0., 0.), radius=(10., 10,), color=None, border_width=1, border_color="white",
num_segments=10, parent=vista.scene)
canvas.update()
lines_list = []
for i in range(1, 1000):
lines_list.append(
scene.visuals.Line(pos=np.array([[0, 0], [0, 0]]), color="red", parent=vista.scene, width=20, method="agg"))
line_index = -1
@canvas.connect
def on_mouse_press(event):
global coords, pointer, line_index
line_index = line_index + 1
pp = event.pos
coords = np.array([pp, pp])
lines_list[line_index].set_data(pos=coords, color="red", width=20)
canvas.update()
@canvas.connect
def on_mouse_move(event):
global coords, pointer
pp = event.pos
pointer.center = pp
if event.button == 1:
coords = np.append(coords, [pp], axis=0)
lines_list[line_index].set_data(pos=coords)
If this project is part of a larger piece of code and you need better performing draws, I would suggest combining all of your line visuals in to a single line visual.
connect : str or array
Determines which vertices are connected by lines.
- “strip” causes the line to be drawn with each vertex connected to the next.
- “segments” causes each pair of vertices to draw an independent line segment
- numpy arrays specify the exact set of segment pairs to connect.
Great!
"parent=vista.scene"