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 addObstacle(self, x, y, radius): self.obstacles.append( vplt.Cylinder(pos=(x, y, 0.5), height=1, axis=vplt.vector(0, 0, 1), r=0.8, c="dg"))
def avesize(pts): # helper fnc s, amean = 0, vector(0, 0, 0) for p in pts: amean = amean + p amean /= len(pts) for p in pts: s += mag(p - amean) return amean, s / len(pts)
def transform(self, p): a1,a2,a3,a4,a5,a6, b1,b2,b3,b4,b5,b6, c1,c2,c3,c4,c5,c6, s = self.params pos, sz = self.s_size[0], self.s_size[1] x, y, z = (p - pos)/sz*s #bring to origin, norm and scale xx, yy, zz, xy, yz, xz = x*x, y*y, z*z, x*y, y*z, x*z xp = x +2*a1*xy +a4*xx +2*a2*yz +a5*yy +2*a3*xz +a6*zz yp = +2*b1*xy +b4*xx +y +2*b2*yz +b5*yy +2*b3*xz +b6*zz zp = +2*c1*xy +c4*xx +2*c2*yz +c5*yy +z +2*c3*xz +c6*zz p2 = vector(xp,yp,zp) p2 = (p2 * sz) + pos #take back to original size and position return p2
def simulate(self): """ Runs the particle simulation. Simulates one time step, dt, of the particle motion. Calculates the force between each pair of particles and updates particles' motion accordingly """ # Main simulation loop for i in range(self.iterations): for a in self.particles: if a.fixed: continue ftot = vector(0,0,0) # total force acting on particle a for b in self.particles: if a.negligible and b.negligible or a==b: continue ab = a.pos - b.pos ftot += ((K_COULOMB * a.charge * b.charge) / mag2(ab)) * norm(ab) a.vel += ftot / a.mass * self.dt # update velocity and position of a a.pos += a.vel * self.dt a.vtk_actor.pos(a.pos) if vp: vp.render(zoom=1.2) vp.camera.Azimuth(0.1) # rotate camera
from __future__ import division, print_function from vtkplotter import Plotter, ProgressBar, vector vp = Plotter(title='Spring in viscous medium', verbose=0, axes=3) l_rest = 0.1 # spring x position at rest x0 = 0.85 # initial x-coordinate of the block k = 25 # spring constant m = 20 # block mass b = 0.5 # viscosity friction (proportional to velocity) dt = 0.1 # time step #initial conditions v = vector(0, 0, 0.2) x = vector(x0, 0, 0) xr = vector(l_rest, 0, 0) sx0 = vector(-0.8, 0, 0) offx = vector(0, 0.3, 0) vp.box(pos=(0, -0.1, 0), length=2.0, width=0.02, height=0.5) #surface vp.box(pos=(-.82, .15, 0), length=.04, width=0.50, height=0.3) #wall block = vp.cube(pos=x, length=0.2, c='t') spring = vp.helix(sx0, x, r=.06, thickness=.01, texture='metal1') pb = ProgressBar(0, 500, c='r') for i in pb.range(): F = -k * (x - xr) - b * v # Force and friction a = F / m # acceleration v = v + a * dt # velocity x = x + v * dt + 1 / 2 * a * dt**2 # position
# ############################################################ parameters dt = 5e-05 # time step Lshaft = 1 # length of gyroscope shaft M = 1 # mass of gyroscope (massless shaft) R = 0.4 # radius of gyroscope rotor theta = 1.3 # initial polar angle of shaft (from vertical) psidot = -40 # spinning angular velocity (rad/s) phidot = 0 # (try -1 and +1 to get first and second pattern) # ############################################################ g, r = 9.81, Lshaft/2 I3 = 1/2*M*R**2 # moment of inertia, I, of gyroscope about its own axis I1 = M*r**2 + 1/2*I3 # I about a line through the support, perpendicular to axis phi = psi = thetadot = 0 x = vector(theta, phi, psi) # Lagrangian coordinates v = vector(thetadot, phidot, psidot) # ############################################################ the scene vp = Plotter(verbose=0, axes=3, interactive=0) shaft = vp.cylinder([[0,0,0], [Lshaft,0,0]], r=.03, c='dg') rotor = vp.cylinder([[Lshaft/2.2,0,0],[Lshaft/1.8,0,0]], r=R, texture='marble') base = vp.sphere([ 0, 0, 0], c='dg', r=.03) tip = vp.sphere([Lshaft, 0, 0], c='dg', r=.03) gyro = vp.makeAssembly([shaft, rotor, base, tip]) # group relevant actors pedestal = vp.box([0,-0.63,0], height=.1, length=.1, width=1, texture='wood5') pedbase = vp.box([0,-1.13,0], height=.5, length=.5, width=.05, texture='wood5') pedpin = vp.pyramid([0,-.08,0], axis=[0,1,0], s=.05, height=.12, texture='wood5') formulas = vp.load('data/images/gyro_formulas.png', alpha=.9).scale(.003).pos([-1,-1,-1.1])
for k in range(1, N): factor = fctr(dij_m[k + 1]) x_dot[k] -= Dt * Ks * (bob_x_m[k] - bob_x_m[k + 1]) * factor y_dot[k] -= Dt * Ks * (bob_y_m[k] - bob_y_m[k + 1]) * factor # Check to see if they are colliding for i in range(1, N): for j in range(i + 1, N + 1): dist2 = (bob_x[i] - bob_x[j])**2 + (bob_y[i] - bob_y[j])**2 if dist2 < DiaSq: # are colliding Ddist = np.sqrt(dist2) - 2 * R tau = versor([bob_x[j] - bob_x[i], bob_y[j] - bob_y[i], 0]) DR = Ddist / 2 * tau bob_x[i] += DR[0] # DR.x bob_y[i] += DR[1] # DR.y bob_x[j] -= DR[0] # DR.x bob_y[j] -= DR[1] # DR.y Vji = vector(x_dot[j] - x_dot[i], y_dot[j] - y_dot[i]) DV = np.dot(Vji, tau) * tau x_dot[i] += DV[0] # DV.x y_dot[i] += DV[1] # DV.y x_dot[j] -= DV[0] # DV.x y_dot[j] -= DV[1] # DV.y # Update the loations of the bobs and the stretching of the springs for k in range(1, N + 1): bob[k].pos([bob_x[k], bob_y[k], 0]) link[k - 1].stretch(bob[k - 1].pos(), bob[k].pos()) vp.show()
coords = np.random.rand(npts, 3) # range is [0, 1] scals = np.abs(coords[:, 2]) # let the scalar be the z of point itself fact = 1. / (bins - 1) # conversion factor btw the 2 ranges vp = Plotter(verbose=0) vp.ztitle = 'z == scalar value' cloud = vp.points(coords) # fill the vtkImageData object pb = ProgressBar(0, bins, c=4) for iz in pb.range(): pb.print() for iy in range(bins): for ix in range(bins): pt = vector(ix, iy, iz) * fact closestPointsIDs = cloud.closestPoint(pt, N=5, returnIds=True) num, den = 0, 0 for i in closestPointsIDs: # work out RBF manually on N points invdist = 1 / (mag2(coords[i] - pt) + 1e-06) num += scals[i] * invdist den += invdist img.SetScalarComponentFromFloat(ix, iy, iz, 0, num / den) #vp.write(img, 'imgcube.tif') # or .vti # set colors and transparencies along the scalar range vol = Volume(img, c=['r', 'g', 'b'], alphas=[0.4, 0.8]) #vtkVolume act = vp.points(coords / fact) vp.show([vol, act], viewup='z')
# Gyroscope hanging from a spring # (adapted by M. Musy from Bruce Sherwood, 2009) from __future__ import division, print_function from vtkplotter import Plotter, ProgressBar, vector, mag, norm, cross # ############################################################ parameters dt = 0.005 # time step ks = 15 # spring stiffness Lrest = 1 # unstretched length of spring Ls = 1 # length of gyroscope shaft M = 1 # mass of gyroscope (massless shaft) R = 0.4 # radius of gyroscope rotor omega = 50 # angular velocity of rotor (rad/s, not shown) gpos = vector(0, 0, 0) # initial position of spring free end # ############################################################ inits top = vector(0, 2, 0) # where top of spring is held precess = vector(0, 0, 0) # initial momentum of center of mass Fgrav = vector(0, -M*9.81, 0) gaxis = vector(0, 0, 1) # initial orientation of gyroscope gaxis = norm(gaxis) I = 1/2*M*R**2 # moment of inertia of gyroscope Lrot = I*omega*gaxis # angular momentum cm = gpos + 0.5*Ls*gaxis # center of mass of shaft # ############################################################ the scene vp = Plotter(verbose=0, axes=0, interactive=0) shaft = vp.cylinder([[0,0,0], Ls*gaxis], r=0.03, c='dg') rotor = vp.cylinder([(Ls-0.55)*gaxis, (Ls-0.45)*gaxis], r=R, c='t') bar = vp.cylinder([Ls*gaxis/2-R*vector(0,1,0), Ls*gaxis/2+R*vector(0,1,0)], r=R/6, c='r')
# (values can be copied in the code by pressing C in the rendering window) vp = Plotter(verbose=0, axes=0, interactive=0) vp.camera.SetPosition(962, -239, 1034) vp.camera.SetFocalPoint(0.0, 0.0, 10.0) vp.camera.SetViewUp(-0.693, -0.479, 0.539) pb = ProgressBar(0,nc, c='g') # a green progress bar for t1 in pb.range(): # for each time point t2=t1+1 if t1==nc-1: t2=t1 # avoid index overflow with last time point vp.actors=[] # clean up the list of actors at each iteration vp.cylinder([0,0,-15], r=260, height=10, texture='marble', res=60) vp.cylinder([0,0, 10], r=260, height=50, wire=1, c='gray', res=60) pts, cols = [],[] for i,p in enumerate(mesh): # for each vertex in the mesh c1, c2 = conc[t1,i], conc[t2,i] cgrad = abs(c2-c1)*cgradfac # intensity of variation gx, gy, gz = np.random.randn(3) # make points wiggle a bit pts.append(p + vector(gx/4, gy/4, gz + c1*20)) cols.append([0, c1, cgrad]) # RGB color vp.points(pts, c=cols, alpha=1.0, r=6) # points actor vp.points(pts, c=cols, alpha=0.1, r=30) # halos actor vp.camera.Azimuth(60/nc) # rotate camera by a fraction vp.show() # show the four new actors at each iteration pb.print() vp.show(interactive=1)
# Intersect a vtkImageData (voxel dataset) with planes # from vtkplotter import Plotter, vtkio, analysis, vector vp = Plotter(axes=4) img = vtkio.loadImageData('data/embryo.slc') planes=[] for i in range(6): print('probing slice plane #',i) pos = img.GetCenter() + vector(0,0,(i-3)*25.) a = analysis.probePlane(img, origin=pos, normal=(0,0,1)).alpha(0.2) planes.append(a) #print(max(a.scalars(0))) # access scalars this way, 0 means first vp.show(planes)
# Intersect a vtkImageData (voxel dataset) with planes # from vtkplotter import Plotter, vtkio, analysis, vector vp = Plotter(axes=4) img = vtkio.loadImageData('data/embryo.slc') pos = img.GetCenter() lines = [] for i in range(60): # probe scalars on 60 parallel lines step = (i - 30) * 2 p1, p2 = pos + vector(-100, step, step), pos + vector(100, step, step) a = analysis.probeLine(img, p1, p2, res=200) a.alpha(0.5).lineWidth(9) lines.append(a) #print(a.scalars(0)) # numpy scalars can be access here #print(a.scalars('vtkValidPointMask')) # the mask of valid points vp.show(lines)
def loop(*event ): ################################################################## global bob_x, x_dot, bob_y, y_dot # Compute the midpoint variables bob_x_m = list(map((lambda x, dx: x + Dt2 * dx), bob_x, x_dot)) # midpoint variables bob_y_m = list(map((lambda y, dy: y + Dt2 * dy), bob_y, y_dot)) for k in range(1, N + 1): factor = fctr(dij[k]) x_dot_m[k] = x_dot[k] - Dt2 * (Ks * (bob_x[k] - bob_x[k - 1]) * factor + gamma * x_dot[k]) y_dot_m[k] = y_dot[k] - Dt2 * (Ks * (bob_y[k] - bob_y[k - 1]) * factor + gamma * y_dot[k] + g) for k in range(1, N): factor = fctr(dij[k + 1]) x_dot_m[k] -= Dt2 * Ks * (bob_x[k] - bob_x[k + 1]) * factor y_dot_m[k] -= Dt2 * Ks * (bob_y[k] - bob_y[k + 1]) * factor # Compute the full step variables bob_x = list(map((lambda x, dx: x + Dt * dx), bob_x, x_dot_m)) bob_y = list(map((lambda y, dy: y + Dt * dy), bob_y, y_dot_m)) for k in range(1, N + 1): dij[k] = mag([bob_x[k] - bob_x[k - 1], bob_y[k] - bob_y[k - 1]]) dij_m[k] = mag( [bob_x_m[k] - bob_x_m[k - 1], bob_y_m[k] - bob_y_m[k - 1]]) factor = fctr(dij_m[k]) x_dot[k] -= Dt * (Ks * (bob_x_m[k] - bob_x_m[k - 1]) * factor + gamma * x_dot_m[k]) y_dot[k] -= Dt * (Ks * (bob_y_m[k] - bob_y_m[k - 1]) * factor + gamma * y_dot_m[k] + g) for k in range(1, N): factor = fctr(dij_m[k + 1]) x_dot[k] -= Dt * Ks * (bob_x_m[k] - bob_x_m[k + 1]) * factor y_dot[k] -= Dt * Ks * (bob_y_m[k] - bob_y_m[k + 1]) * factor # Check to see if they are colliding for i in range(1, N): for j in range(i + 1, N + 1): dist2 = (bob_x[i] - bob_x[j])**2 + (bob_y[i] - bob_y[j])**2 if dist2 < DiaSq: # are colliding Ddist = np.sqrt(dist2) - 2 * R tau = norm(vector(bob_x[j] - bob_x[i], bob_y[j] - bob_y[i])) DR = Ddist / 2 * tau bob_x[i] += DR[0] # DR.x bob_y[i] += DR[1] # DR.y bob_x[j] -= DR[0] # DR.x bob_y[j] -= DR[1] # DR.y Vji = vector(x_dot[j] - x_dot[i], y_dot[j] - y_dot[i]) DV = np.dot(Vji, tau) * tau x_dot[i] += DV[0] # DV.x y_dot[i] += DV[1] # DV.y x_dot[j] -= DV[0] # DV.x y_dot[j] -= DV[1] # DV.y # Update the loations of the bobs and the stretching of the springs for k in range(1, N + 1): bob[k].pos([bob_x[k], bob_y[k], 0]) link[k - 1].stretch(bob[k - 1].pos(), bob[k].pos()) vp.render(resetcam=True) # show() would cause exiting the loop vp.camera.Azimuth(0.1) # move camera a bit
""" Intersect a Volume (voxel dataset) with planes """ from vtkplotter import show, load, probePlane, vector, Text, datadir vol = load(datadir+"embryo.slc") planes = [] for i in range(6): print("probing slice plane #", i) pos = vol.imagedata().GetCenter() + vector(0, 0, (i - 3) * 25.0) a = probePlane(vol, origin=pos, normal=(0, 0, 1)).alpha(0.2) planes.append(a) # print(max(a.scalars(0))) # access scalars this way, 0 means first show(planes, Text(__doc__), axes=4, bg="w")
gamma * x_dot_m[k]) y_dot[k] -= Dt * (Ks * (bob_y_m[k] - bob_y_m[k - 1]) * factor + gamma * y_dot_m[k] + g) for k in range(1, N): factor = fctr(dij_m[k + 1]) x_dot[k] -= Dt * Ks * (bob_x_m[k] - bob_x_m[k + 1]) * factor y_dot[k] -= Dt * Ks * (bob_y_m[k] - bob_y_m[k + 1]) * factor # Check to see if they are colliding for i in range(1, N): for j in range(i + 1, N + 1): dist2 = (bob_x[i] - bob_x[j])**2 + (bob_y[i] - bob_y[j])**2 if dist2 < DiaSq: # are colliding Ddist = np.sqrt(dist2) - 2 * R tau = norm(vector(bob_x[j] - bob_x[i], bob_y[j] - bob_y[i])) DR = Ddist / 2 * tau bob_x[i] += DR[0] # DR.x bob_y[i] += DR[1] # DR.y bob_x[j] -= DR[0] # DR.x bob_y[j] -= DR[1] # DR.y Vji = vector(x_dot[j] - x_dot[i], y_dot[j] - y_dot[i]) DV = np.dot(Vji, tau) * tau x_dot[i] += DV[0] # DV.x y_dot[i] += DV[1] # DV.y x_dot[j] -= DV[0] # DV.x y_dot[j] -= DV[1] # DV.y # Update the loations of the bobs and the stretching of the springs for k in range(1, N + 1): bob[k].pos([bob_x[k], bob_y[k], 0])