class MainWindow(Qt.QMainWindow): def __init__(self, parent=None): Qt.QMainWindow.__init__(self, parent) self.frame = Qt.QFrame() self.layout = Qt.QVBoxLayout() self.vtkWidget = QVTKRenderWindowInteractor(self.frame) # Create renderer and add the vedo objects and callbacks self.vp = Plotter(qtWidget=self.vtkWidget) self.id1 = self.vp.addCallback("mouse click", self.onMouseClick) self.id2 = self.vp.addCallback("key press", self.onKeypress) self.vp += Cone().rotateX(20) self.vp.show() # <--- show the vedo rendering # Set-up the rest of the Qt window button = Qt.QPushButton("My Button makes the cone red") button.setToolTip('This is an example button') button.clicked.connect(self.onClick) self.layout.addWidget(self.vtkWidget) self.layout.addWidget(button) self.frame.setLayout(self.layout) self.setCentralWidget(self.frame) self.show() # <--- show the Qt Window def onMouseClick(self, evt): printc("You have clicked your mouse button. Event info:\n", evt, c='y') def onKeypress(self, evt): printc("You have pressed key:", evt.keyPressed, c='b') @Qt.pyqtSlot() def onClick(self): printc("..calling onClick") self.vp.actors[0].color('red').rotateZ(40) self.vp.interactor.Render() def onClose(self): #Disable the interactor before closing to prevent it #from trying to act on already deleted items printc("..calling onClose") self.vtkWidget.close()
class MainWindow(Qt.QMainWindow): def __init__(self, parent=None): Qt.QMainWindow.__init__(self, parent) self.frame = Qt.QFrame() self.layout = Qt.QVBoxLayout() self.vtkWidget = QVTKRenderWindowInteractor(self.frame) # Create vedo renderer and add objects and callbacks self.vp = Plotter(qtWidget=self.vtkWidget) self.cbid = self.vp.addCallback("key press", self.onKeypress) self.imgActor = Picture( "https://icatcare.org/app/uploads/2018/07/Helping-your-new-cat-or-kitten-settle-in-1.png" ) self.text2d = Text2D("Use slider to change contrast") self.slider = Qt.QSlider(1) self.slider.valueChanged.connect(self.onSlider) self.layout.addWidget(self.vtkWidget) self.layout.addWidget(self.slider) self.frame.setLayout(self.layout) self.setCentralWidget(self.frame) self.vp.show(self.imgActor, self.text2d, mode='image') # build the vedo rendering self.show() # show the Qt Window def onSlider(self, value): self.imgActor.window(value * 10) # change image contrast self.text2d.text(f"window level is now: {value*10}") self.vp.render() def onKeypress(self, evt): printc("You have pressed key:", evt.keyPressed, c='b') if evt.keyPressed == 'q': self.vp.close() self.vtkWidget.close() exit() def onClose(self): self.vtkWidget.close()
"""Mouse click and other type of events will trigger a call to a custom function""" from vedo import printc, Plotter, Mesh, datadir printc("Click object to trigger a function call", invert=1) # callback functions def onLeftClick(event): if not event.actor: return printc("Left button pressed on", [event.actor], c=event.actor.color()) # printc('full dump of event:', event) def onEvent(event): printc(event.name, 'happened at mouse position', event.picked2d) ###################### tea = Mesh(datadir + "teapot.vtk").c("gold") mug = Mesh(datadir + "mug.ply").rotateX(90).scale(8).pos(2, 0, -.7).c("silver") plt = Plotter(axes=11) plt.addCallback('LeftButtonPress', onLeftClick) plt.addCallback('Interaction', onEvent) # mouse dragging triggers this plt.show(tea, mug, __doc__)
"""Click a sphere to highlight it""" from vedo import Text2D, Sphere, Plotter import numpy as np spheres = [] for i in range(25): p = np.random.rand(2) s = Sphere(r=0.05).pos(p).color('k5') s.name = f"sphere nr.{i} at {p}" spheres.append(s) def func(evt): if not evt.actor: return sil = evt.actor.silhouette().lineWidth(6).c('red5') msg.text("You clicked: " + evt.actor.name) plt.remove(silcont.pop()).add(sil) silcont.append(sil) silcont = [None] msg = Text2D("", pos="bottom-center", c='k', bg='r9', alpha=0.8) plt = Plotter(axes=1, bg='black') plt.addCallback('mouse click', func) plt.show(spheres, msg, __doc__, zoom=1.2).close()
def update(evt): global t t += 0.005 P_ = np.zeros((n, 3)) cos_t = 1.5 * np.cos(2 * np.pi * t) sin_t = 1.5 * np.sin(2 * np.pi * t) for i in range(n): x, y = P[i] f = intensity[i] * 50 dx = noise4(scale * x, scale * y, cos_t, sin_t, 2) * f dy = noise4(100 + scale * x, 200 + scale * y, cos_t, sin_t, 2) * f P_[i] = [x + dx, y + dy, np.sqrt(dx * dx + dy * dy) / 2] pts.points(P_) plt.render() pts = Points([X, Y], r=3).alpha(0.8) cir = Circle(pos=(width / 2, height / 2, -5), r=radius * 1.05) txt1 = Text2D("\Lambda L I E N L I F E", s=2.8, pos="top-center") txt2 = Text2D("Original idea by Necessary Disorder", s=0.9, pos="bottom-center") plt = Plotter() plt.show(pts, cir, txt1, txt2, elevation=-35, zoom=1.2, interactive=False) plt.addCallback("timer", update) plt.timerCallback("create") interactive()
class Morpher: def __init__(self, mesh1, mesh2, n): ############################### init self.n = n # desired nr. of intermediate shapes self.mode = '2d' self.mesh1 = mesh1 self.mesh2 = mesh2 self.merged_meshes = merge(mesh1, mesh2) self.mesh1.lw(4).c('grey2').pickable(False) self.mesh2.lw(4).c('grey1').pickable(False) self.arrow_starts = [] self.arrow_stops = [] self.dottedln = None self.toggle = False self.instructions = ( "Click to add arrows interactively on the left panel\n" "right-click to remove last arrow. Then press:\n" "- m to morph the plane\n" "- c to clear\n" "- g to generate interpolation") self.msg1 = Text2D(self.instructions, pos='top-left', font="VictorMono", bg='g2', alpha=0.6) self.msg2 = Text2D('[output will show here]', pos='top-left', font="VictorMono") sz = self.merged_meshes.diagonalSize() self.plane1 = Grid(sx=sz, sy=sz, resx=50, resy=50).pos(self.merged_meshes.centerOfMass()) self.plane1.wireframe(False).alpha(1).lineWidth(0.1).c('white').lc( 'grey5') self.plane2 = self.plane1.clone().pickable(False) self.plotter = Plotter(N=2, bg='light blue', size=(2000, 1000)) self.plotter.addCallback('left click', self.onleftclick) self.plotter.addCallback('right click', self.onrightclick) self.plotter.addCallback('key press', self.onkeypress) def start( self): ################################################ show stuff paxes = Axes(self.plane1, xyGrid=0, textScale=0.6) self.plotter.show(self.plane1, paxes, self.msg1, self.mesh1, self.mesh2, at=0) self.plotter.show(self.plane2, self.msg2, at=1, mode='image') if len(self.arrow_starts): self.draw(True) self.draw(False) self.msg1.text(self.instructions) self.plotter.show(interactive=True, zoom=1.3).close() def draw(self, toggle=None): #################################### update scene if toggle is None: toggle = self.toggle if toggle: self.msg1.text( "Choose start point or press:\nm to morph the shapes\ng to interpolate" ) self.plotter.remove("displacementArrows", at=0) if not len(self.arrow_starts): return arrows = Arrows2D(self.arrow_starts, self.arrow_stops, c='red4') arrows.name = "displacementArrows" self.plotter.add(arrows, at=0) else: self.msg1.text("Click to choose an end point") self.plotter.remove("displacementPoints", at=0) points = Points(self.arrow_starts, r=15, c='green3', alpha=0.5) points.name = "displacementPoints" self.plotter.add(points, at=0) def onleftclick( self, evt): ############################################ add points msh = evt.actor if not msh or msh.name != "Grid": return pt = self.merged_meshes.closestPoint( evt.picked3d) # get the closest pt on the line self.arrow_stops.append( pt) if self.toggle else self.arrow_starts.append(pt) self.draw() self.toggle = not self.toggle def onrightclick( self, evt): ######################################## remove points if not self.arrow_starts: return self.arrow_starts.pop() if not self.toggle: self.arrow_stops.pop() self.plotter.clear(at=0).addRendererFrame() self.plotter.add([self.plane1, self.msg1, self.mesh1, self.mesh2], at=0, render=False) self.draw(False) self.draw(True) def onkeypress( self, evt): ###################################### MORPH & GENERATE if evt.keyPressed == 'm': ##--------- morph mesh1 based on the existing arrows if len(self.arrow_starts) != len(self.arrow_stops): printc("You must select your end point first!", c='y') return output = [self.mesh1.clone().c('grey4'), self.mesh2, self.msg2] warped_plane = self.plane1.clone().pickable(False) warped_plane.warp(self.arrow_starts, self.arrow_stops, mode=self.mode) output.append(warped_plane + Axes(warped_plane, xyGrid=0, textScale=0.6)) mw = self.mesh1.clone().applyTransform( warped_plane.transform).c('red4') output.append(mw) T_inv = warped_plane.transform.GetInverse() a = Points(self.arrow_starts, r=10).applyTransform(warped_plane.transform) b = Points(self.arrow_stops, r=10).applyTransform(warped_plane.transform) self.dottedln = Lines( a, b, res=self.n).applyTransform(T_inv).pointSize(5) output.append(self.dottedln) self.msg1.text(self.instructions) self.msg2.text("Morphed output:") self.plotter.clear(at=1).addRendererFrame().add(output, at=1) elif evt.keyPressed == 'g': ##------- generate intermediate shapes if not self.dottedln: return intermediates = [] allpts = self.dottedln.points() allpts = allpts.reshape(len(self.arrow_starts), self.n + 1, 3) for i in range(self.n + 1): pi = allpts[:, i, :] m_nterp = self.mesh1.clone().warp(self.arrow_starts, pi, mode=self.mode).c('b3').lw(1) intermediates.append(m_nterp) self.msg2.text("Morphed output + Interpolation:") self.plotter.add(intermediates, at=1) self.dottedln = None elif evt.keyPressed == 'c': ##------- clear all self.arrow_starts = [] self.arrow_stops = [] self.toggle = False self.dottedln = None self.msg1.text(self.instructions) self.msg2.text("[output will show here]") self.plotter.clear(at=0).clear(at=1).addRendererFrame() self.plotter.add([self.plane1, self.msg1, self.mesh1, self.mesh2], at=0) self.plotter.add([self.plane2, self.msg2], at=1)
"""Forward kinematics: hover the mouse to drag the chain""" from vedo import Plotter, versor, Plane, Line n = 15 # number of points l = 3 # length of one segment def move(evt): if not evt.actor: return coords = line.points() coords[0] = evt.picked3d for i in range(1, n): v = versor(coords[i] - coords[i - 1]) coords[i] = coords[i - 1] + v * l line.points(coords) # update positions nodes.points(coords) plt.render() plt = Plotter() plt.addCallback("mouse move", move) surf = Plane(sx=60, sy=60) line = Line([l * n / 2, 0], [-l * n / 2, 0], res=n, lw=12) nodes = line.clone().c('red3').pointSize(15) plt.show(surf, line, nodes, __doc__, zoom=1.3).close()