def __init__(self, pos, charge, mass, radius, color, vel, fixed, negligible): """ Creates a new particle with specified properties (in SI units) pos: XYZ starting position of the particle, in meters charge: charge of the particle, in Coulombs mass: mass of the particle, in kg radius: radius of the particle, in meters. No effect on simulation color: color of the particle. If None, a default color will be chosen vel: initial velocity vector, in m/s fixed: if True, particle will remain fixed in place negligible: assume charge is small wrt other charges to speed up calculation """ self.pos = vector(pos) self.radius = radius self.charge = charge self.mass = mass self.vel = vector(vel) self.fixed = fixed self.negligible = negligible self.color = color if vp: self.vtk_actor = vp.add(Sphere( pos, r=radius, c=color)) # Sphere representing the particle # vp.addTrail(alpha=0.4, maxlength=1, n=50) # Add a trail behind the particle self.vtk_actor.addTrail(alpha=0.4, maxlength=1, n=50)
def myfnc(key): if not vp.clickedActor or key != "c": printc("click an actor and press c.", c="r") return printc("clicked actor :", vp.clickedActor.legend(), c=4) printc("clicked 3D point:", vp.picked3d, c=4) printc("clicked renderer:", [vp.renderer], c=2) vp.add(Sphere(pos=vp.picked3d, r=0.005, c="v")) vp.show()
def myfnc(key): if not vp.clickedActor or key != 'c': printc('click an actor and press c.', c='r') return printc('clicked actor :', vp.clickedActor.legend(), c=4) printc('clicked 3D point:', vp.picked3d, c=4) printc('clicked renderer:', vp.clickedRenderer, c=2) vp.add(Sphere(pos=vp.picked3d, r=.005, c='v')) vp.show()
vp += Torus(c="g", r=RingRadius, thickness=RingThickness, alpha=0.1).wireframe(1) ### <-- Atoms = [] poslist = [] plist, mlist, rlist = [], [], [] mass = Matom * Ratom**3 / Ratom**3 pavg = np.sqrt(2.0 * mass * 1.5 * k * T) # average kinetic energy p**2/(2mass) = (3/2)kT for i in range(Natoms): alpha = 2 * np.pi * random() x = RingRadius * np.cos(alpha) * 0.9 y = RingRadius * np.sin(alpha) * 0.9 z = 0 atm = Sphere(pos=(x, y, z), r=Ratom, c=i) vp += atm Atoms = Atoms + [atm] ### <-- theta = np.pi * random() phi = 2 * np.pi * random() px = pavg * np.sin(theta) * np.cos(phi) py = pavg * np.sin(theta) * np.sin(phi) pz = pavg * np.cos(theta) poslist.append((x, y, z)) plist.append((px, py, pz)) mlist.append(mass) rlist.append(Ratom) pos = np.array(poslist) poscircle = pos p = np.array(plist)
# Create the initial positions and velocitites (0,0) of the bobs bob_x = [0] bob_y = [0] x_dot = [0] * (N + 1) # velocities y_dot = [0] * (N + 1) for k in range(1, N + 1): alpha = np.pi / 5 * k / 10 bob_x.append(bob_x[k - 1] + np.cos(alpha) + np.random.normal(0, 0.1)) bob_y.append(bob_y[k - 1] + np.sin(alpha) + np.random.normal(0, 0.1)) # Create the bobs vp = Plotter(title="Multiple Pendulum", axes=0, interactive=0) vp += Box(pos=(0, -5, 0), length=12, width=12, height=0.7, c="k").wireframe(1) bob = [vp.add(Sphere(pos=(bob_x[0], bob_y[0], 0), r=R / 2, c="gray"))] for k in range(1, N + 1): bob.append( vp.add(Cylinder(pos=(bob_x[k], bob_y[k], 0), r=R, height=0.3, c=k))) # Create the springs out of N links link = [0] * N for k in range(N): p0 = bob[k].pos() p1 = bob[k + 1].pos() link[k] = vp.add(Spring(p0, p1, thickness=0.015, r=R / 3, c="gray")) # Create some auxiliary variables x_dot_m = [0] * (N + 1) y_dot_m = [0] * (N + 1) dij = [0] * (N + 1) # array with distances to previous bob
resy=n - 1).wire(False).lw(0.5).bc('lightblue') for i in range(n): for j in range(n): grd.setPoint(i * n + j, (x[i, j], y[i, j], z[i, j])) show(doc, pts, grd, axes=6, bg='w', azimuth=2, interactive=False) return [self.codebook[:, i].reshape(n, n) for i in range(3)] # ------------------------------------------------------------------------------- if __name__ == "__main__": n = 25 X, Y = np.meshgrid(np.linspace(0, 1, n), np.linspace(0, 1, n)) P = np.c_[X.ravel(), Y.ravel()] D = scipy.spatial.distance.cdist(P, P) s = Sphere(res=90).cutWithPlane(origin=(0, -.3, 0), normal='y').clean(0.01) som = SOM((len(P), 3), D) som.samples = s.coordinates() som.learn(n_epoch=7000, sigma=(1, 0.01), lrate=(1, 0.01)) show(interactive=True)
pts = [] for i, longs in enumerate(agrid_reco): ilat = grid_reco.lats()[i] for j, value in enumerate(longs): ilong = grid_reco.lons()[j] th = (90 - ilat) / 57.3 ph = ilong / 57.3 r = value + rbias p = np.array([sin(th) * cos(ph), sin(th) * sin(ph), cos(th)]) * r pts.append(p) return pts vp = Plotter(shape=[2, 2], verbose=0, axes=3, interactive=0) shape1 = Sphere(alpha=0.2) shape2 = vp.load('data/shapes/icosahedron.vtk').normalize().lineWidth(1) agrid1, actorpts1 = makeGrid(shape1, N) vp.show(at=0, actors=[shape1, actorpts1]) agrid2, actorpts2 = makeGrid(shape2, N) vp.show(at=1, actors=[shape2, actorpts2]) vp.camera.Zoom(1.2) vp.interactive = False clm1 = pyshtools.SHGrid.from_array(agrid1).expand() clm2 = pyshtools.SHGrid.from_array(agrid2).expand() # clm1.plot_spectrum2d() # plot the value of the sph harm. coefficients # clm2.plot_spectrum2d()
vp.add(Torus(c='g', r=RingRadius, thickness=RingThickness, alpha=.1).wire(1)) ### <-- Atoms = [] poslist = [] plist, mlist, rlist = [], [], [] mass = Matom * Ratom**3 / Ratom**3 pavg = np.sqrt(2. * mass * 1.5 * k * T) # average kinetic energy p**2/(2mass) = (3/2)kT for i in range(Natoms): alpha = 2 * np.pi * random() x = RingRadius * np.cos(alpha) * .9 y = RingRadius * np.sin(alpha) * .9 z = 0 Atoms = Atoms + [vp.add(Sphere(pos=(x, y, z), r=Ratom, c=i))] ### <-- theta = np.pi * random() phi = 2 * np.pi * random() px = pavg * np.sin(theta) * np.cos(phi) py = pavg * np.sin(theta) * np.sin(phi) pz = pavg * np.cos(theta) poslist.append((x, y, z)) plist.append((px, py, pz)) mlist.append(mass) rlist.append(Ratom) pos = np.array(poslist) poscircle = pos p = np.array(plist) m = np.array(mlist) m.shape = (Natoms, 1)
""" Example usage of addTrail(). Add a trailing line to a moving object. """ print(__doc__) from vtkplotter import Plotter, sin, Sphere, Point vp = Plotter(axes=6, bg='white', interactive=0) s = Sphere(c="green", res=24) s.cutWithPlane([-0.9, 0, 0], showcut=True) # cut left part of sphere p = Point([1, 1, 1], r=12, c="k") # add a trail to point p with maximum length 0.5 and 50 segments p.addTrail(c="k", lw=3, maxlength=0.5, n=50) vp += [s, p] for i in range(200): p.pos([-2 + i / 100.0, sin(i / 5.0) / 15, 0]) vp.show() vp.camera.Azimuth(-0.2) vp.show(interactive=1)
""" Example usage of addTrail(). Add a trailing line to a moving object. """ print(__doc__) from vtkplotter import Plotter, sin, Sphere, Point vp = Plotter(axes=6, bg='white', interactive=0) s = Sphere().c("green").bc("tomato") s.cutWithPlane([-0.9, 0, 0], showcut=True) # cut left part of sphere p = Point([1, 1, 1], r=12, c="k") # add a trail to point p with maximum length 0.5 and 50 segments p.addTrail(c="k", lw=3, maxlength=0.5, n=50) vp += [s, p] for i in range(200): p.pos([-2 + i / 100.0, sin(i / 5.0) / 15, 0]) vp.show() vp.camera.Azimuth(-0.2) vp.show(interactive=1)
ListPos.append(PossiblePos[n]) del PossiblePos[n] Pos = np.array(ListPos) # Create an array with all the radius and a list with all the masses Radius = np.concatenate((np.array([Rb]), np.array([Rs] * (Nsp - 1)))) Mass = [1.0] + [Ms] * (Nsp - 1) # Create the initial array of velocities at random with big sphere at rest ListVel = [(0.0, 0.0)] for s in range(1, Nsp): ListVel.append((Rb * random.uniform(-1, 1), Rb * random.uniform(-1, 1))) Vel = np.array(ListVel) # Create the spheres Spheres = [Sphere(pos=(Pos[0][0], Pos[0][1], 0), r=Radius[0], c="red")] for s in range(1, Nsp): a = Sphere(pos=(Pos[s][0], Pos[s][1], 0), r=Radius[s], c="blue") Spheres.append(a) # vp += a vp += Spheres vp += Grid(sx=screen_w, sy=screen_w) # Auxiliary variables Id = np.identity(Nsp) Dij = (Radius + Radius[:, np.newaxis])**2 # Matrix Dij=(Ri+Rj)**2 # The main loop pb = ProgressBar(0, 2000, c="r") for i in pb.range(): # Update all positions
"""Lock an object orientation to the scene camera. """ from vtkplotter import Sphere, Text, Plotter plt = Plotter(axes=1, interactive=0) sp = Sphere().wireframe() tx1 = Text("Fixed point", sp.getPoint(10), s=0.07, c="lb") tx2 = Text("Follow point", sp.getPoint(144), s=0.07, c="lg") # a camera must exist prior to calling followCamera() plt.show(sp) tx2.followCamera() # a vtkCamera can also be passed as argument plt.show(sp, tx1, tx2, Text(__doc__), interactive=1)
from vtkplotter import Cone, Sphere, merge, Volume, show import numpy as np import vtk print('---------------------------------') print('vtkVersion', vtk.vtkVersion().GetVTKVersion()) print('---------------------------------') ##################################### cone = Cone(res=48) sphere = Sphere(res=24) carr = cone.cellCenters()[:, 2] parr = cone.points()[:, 0] cone.addCellArray(carr, 'carr') cone.addPointArray(parr, 'parr') carr = sphere.cellCenters()[:, 2] parr = sphere.points()[:, 0] sphere.addCellArray(carr, 'carr') sphere.addPointArray(parr, 'parr') sphere.addPointArray(np.sin(sphere.points()), 'pvectors') sphere.addElevationScalars() cone.computeNormals() sphere.computeNormals() ###################################### test clone() c2 = cone.clone() assert cone.N() == c2.N()
""" Shrink the triangulation of a mesh to make the inside visible. """ from vtkplotter import load, Sphere, show, Text, datadir pot = load(datadir+"teapot.vtk").shrink(0.75) s = Sphere(r=0.2).pos(0, 0, -0.5) show(pot, s, Text(__doc__), viewup="z")
Generate a time sequence of 3D shapes (from a sphere to a tetrahedron) as noisy cloud Points, and smooth it with Moving Least Squares (smoothMLS3D). This make a simultaneus fit in 4D (space+time). smoothMLS3D method returns a vtkActor where points are color coded in bins of fitted time. Data itself can suggest a meaningful time separation based on the spatial distribution of points. The nr neighbours in the local 4D fitting must be specified. ''' from vtkplotter import Plotter, Sphere, smoothMLS3D, Points, Text vp = Plotter(N=2, axes=0, bg='w') # generate uniform points on sphere (tol separates points by 2% of actor size) cc = Sphere(res=200).clean(tol=0.02).coordinates() a, b, noise = .2, .4, .1 # some random warping paramenters, and noise factor sets = [] for i in range(5): # generate a time sequence of 5 shapes cs = cc + a * i * cc**2 + b * i * cc**3 # warp sphere in weird ways # set absolute time of points actor, and add 1% noise on positions ap = Points(cs, c=i, alpha=0.5).addGaussNoise(1.0).time(0.2 * i) sets.append(ap) vp.show(Text(__doc__, c='k'), at=0) vp.show(sets, at=0, zoom=1.4) # show input clouds as func(time) asse = smoothMLS3D(sets, neighbours=50) vp.addScalarBar3D(asse, at=1, pos=(-2, 0, -1)) # color indicates fitted time
""" Computes the (signed) distance from one mesh to another. """ from vtkplotter import Sphere, Cube, show, Text s1 = Sphere() s2 = Cube(pos=[1,0,0], c='white', alpha=0.4) s1.distanceToMesh(s2, signed=True, negate=False) s1.addScalarBar(title='Signed\nDistance') #print(s1.scalars("Distance")) show(s1, s2, Text(__doc__))
def add_actor_label(self, actors, labels, **kwargs): """ Adds a 2D text ancored to a point on the actor's mesh to label what the actor is :param kwargs: key word arguments can be passed to determine text appearance and location: - size: int, text size. Default 300 - color: str, text color. A list of colors can be passed if None the actor's color is used. Default None. - xoffset, yoffset, zoffset: integers that shift the label position - radius: radius of sphere used to denote label anchor. Set to 0 or None to hide. """ # Check args if not isinstance(actors, (tuple, list)): actors = [actors] if not isinstance(labels, (tuple, list)): labels = [labels] # Get text params size = kwargs.pop("size", 300) color = kwargs.pop("color", None) radius = kwargs.pop("radius", 100) xoffset = kwargs.pop("xoffset", 0) yoffset = kwargs.pop("yoffset", 0) zoffset = kwargs.pop("zoffset", 0) if self.atlas.atlas_name == 'ABA': offset = [-yoffset, -zoffset, xoffset] default_offset = np.array([0, -200, 100]) else: offset = [xoffset, yoffset, zoffset] default_offset = np.array([100, 0, -200]) new_actors = [] for n, (actor, label) in enumerate(zip(actors, labels)): if not isinstance(actor, Actor): raise ValueError(f'Actor must be an instance of Actor, not {type(actor)}') if not isinstance(label, str): raise ValueError(f'Label must be a string, not {type(label)}') # Get label color if color is None: color = actor.c() elif isinstance(color, (list, tuple)): color = color[n] # Get mesh's highest point points = actor.points().copy() point = points[np.argmin(points[:, 1]), :] point += np.array(offset) + default_offset if self.atlas.get_hemisphere_from_point(point) == 'left': point = self.atlas.mirror_point_across_hemispheres(point) # Create label txt = Text(label, point, s=size, c=color) new_actors.append(txt) # Mark a point on Actor that corresponds to the label location if radius is not None: pt = actor.closestPoint(point) new_actors.append(Sphere(pt, r=radius, c=color)) # Add to scene and return self.add_vtkactor(*new_actors, store=self.actors['labels']) if len(new_actors) == 0: return new_actors[0] elif not new_actors: return None else: return new_actors
""" Mark a specific point on a mesh with some text. """ from vtkplotter import Sphere, Point, show, Text sp = Sphere().wire(True) pcoords = sp.getPoint(144) pt = Point(pcoords, r=12, c="white") tx = Text("my fave\npoint", pcoords, s=0.1, c="lightblue", bc="green", followcam=False) show(sp, pt, tx, Text(__doc__), axes=1)
''' Work with vtkVolume objects and surface meshes in the same rendering window. ''' from vtkplotter import loadImageData, Plotter, Volume, Sphere, Text vp = Plotter(axes=0, verbose=0, bg='w') # Load a 3D voxel dataset (returns a vtkImageData object): img = loadImageData('data/embryo.slc', spacing=[1, 1, 1]) # Build a vtkVolume object. # A set of transparency values - of any length - can be passed # to define the opacity transfer function in the range of the scalar. # E.g.: setting alphas=[0, 0, 0, 1, 0, 0, 0] would make visible # only voxels with value close to 98.5 (see print output). vol = Volume(img, c='green', alphas=[0, 0.4, 0.9, 1]) # vtkVolume # can relocate volume in space: #vol.scale(0.3).pos([10,100,0]).rotate(90, axis=[0,1,1]) sph = Sphere(pos=[100, 100, 100], r=20) # add a dummy surface doc = Text(__doc__, c='k') # show both vtkVolume and vtkActor vp.show([vol, sph, doc], zoom=1.4)
""" Example of boolean operations with actors or polydata """ print(__doc__) from vtkplotter import Plotter, booleanOperation, Sphere # declare the instance of the class vp = Plotter(shape=(2, 2), interactive=0, axes=3) # build to sphere actors s1 = Sphere(pos=[-0.7, 0, 0], c="r", alpha=0.5) s2 = Sphere(pos=[0.7, 0, 0], c="g", alpha=0.5) # make 3 different possible operations: b1 = booleanOperation(s1, "intersect", s2).c('m').legend("intersect") b2 = booleanOperation(s1, "plus", s2).c("b").wireframe(True).legend("plus") b3 = booleanOperation(s1, "minus", s2).legend("minus").addScalarBar(c='w') # show the result in 4 different subwindows 0->3 vp.show(s1, s2, at=0) vp.show(b1, at=1) vp.show(b2, at=2) vp.show(b3, at=3) vp.show(interactive=1)
ListPos.append(PossiblePos[n]) del PossiblePos[n] Pos = np.array(ListPos) # Create an array with all the radius and a list with all the masses Radius = np.concatenate( (np.array([Rb]), np.array([Rs]*(Nsp-1))) ) Mass=[1.0]+[Ms]*(Nsp-1) # Create the initial array of velocities at random with big sphere at rest ListVel=[(0.,0.)] for s in range(1,Nsp): ListVel.append( (Rb*random.uniform(-1,1), Rb*random.uniform(-1,1)) ) Vel = np.array(ListVel) # Create the spheres Spheres = [vp.add(Sphere(pos=(Pos[0][0],Pos[0][1],0), r=Radius[0], c='red'))] for s in range(1,Nsp): a = vp.add(Sphere(pos=(Pos[s][0],Pos[s][1],0), r=Radius[s], c='blue')) Spheres.append(a) vp.add(Grid(sx=screen_w, sy=screen_w)) # Auxiliary variables Id = np.identity(Nsp) Dij = (Radius+Radius[:, np.newaxis])**2 # Matrix Dij=(Ri+Rj)**2 # The main loop pb = ProgressBar(0,2000, c='r') for i in pb.range(): # Update all positions np.add(Pos,Vel*Dt, Pos) # Fast version of Pos = Pos + Vel*Dt
''' Example of boolean operations with actors or polydata ''' print(__doc__) from vtkplotter import Plotter, booleanOperation, Sphere # declare the instance of the class vp = Plotter(shape=(2, 2), interactive=0, axes=3) # build to sphere actors s1 = Sphere(pos=[-.7, 0, 0], c='r', alpha=0.5) s2 = Sphere(pos=[0.7, 0, 0], c='g', alpha=0.5) # make 3 different possible operations: b1 = booleanOperation(s1, 'intersect', s2, c='m') b2 = booleanOperation(s1, 'plus', s2, c='b', wire=True) b3 = booleanOperation(s1, 'minus', s2, c=None) # show the result in 4 different subwindows 0->3 vp.show([s1, s2], at=0, legend='2 spheres') vp.show(b1, at=1, legend='intersect') vp.show(b2, at=2, legend='plus') vp.show(b3, at=3, legend='minus') vp.addScalarBar() # adds a scalarbar to the last actor vp.show(interactive=1)
from vtkplotter import makeLUT, Sphere mesh = Sphere().lineWidth(0.1) # create some data array to be associated to points data = mesh.getPoints()[:, 2] data[10:20] = float('nan') # Build a lookup table of colors: # scalar color alpha lut1 = makeLUT( [ (-0.80, 'pink'), (-0.33, 'green', 0.8), (0.67, 'red'), ], vmin=-1, vmax=1, aboveColor='grey', belowColor='white', interpolate=False, ) mesh.pointColors(data, cmap=lut1).addScalarBar() #Avoid interpolating cell colors before mapping: #mesh.mapper.InterpolateScalarsBeforeMappingOff() mesh.show(bg='white', axes=1, viewup='z')
from vtkplotter import Plotter, Sphere from vtkplotter.analysis import surfaceIntersection vp = Plotter() car = vp.load('data/shapes/porsche.ply', c='gold').alpha(0.1) s = Sphere(r=4, c='v', alpha=0.1).wire(True) # color is violet # Intersect car with Sphere, c=black, lw=line width contour = surfaceIntersection(car, s, lw=4) vp.show([car, contour, s], zoom=1.3)
ListPos.append(PossiblePos[n]) del PossiblePos[n] Pos = np.array(ListPos) # Create an array with all the radius and a list with all the masses Radius = np.concatenate((np.array([Rb]), np.array([Rs] * (Nsp - 1)))) Mass = [1.0] + [Ms] * (Nsp - 1) # Create the initial array of velocities at random with big sphere at rest ListVel = [(0.0, 0.0)] for s in range(1, Nsp): ListVel.append((Rb * random.uniform(-1, 1), Rb * random.uniform(-1, 1))) Vel = np.array(ListVel) # Create the spheres Spheres = [vp.add(Sphere(pos=(Pos[0][0], Pos[0][1], 0), r=Radius[0], c="red"))] for s in range(1, Nsp): a = vp.add(Sphere(pos=(Pos[s][0], Pos[s][1], 0), r=Radius[s], c="blue")) Spheres.append(a) vp.add(Grid(sx=screen_w, sy=screen_w)) # Auxiliary variables Id = np.identity(Nsp) Dij = (Radius + Radius[:, np.newaxis])**2 # Matrix Dij=(Ri+Rj)**2 # The main loop pb = ProgressBar(0, 2000, c="r") for i in pb.range(): # Update all positions np.add(Pos, Vel * Dt, Pos) # Fast version of Pos = Pos + Vel*Dt