def init_vpython(self): scene = canvas(title="Fans", width=self.win, height=self.win, x=0, y=0, center=vec(0, 0, 0), forward=vec(1,0,-1), up=self.up) scene.autoscale = False scene.range = 25 h = 0.1 mybox = box(pos=vec(0, 0, -h/2), length=self.L, height=h, width=L, up=self.up, color=color.white) # create dust particles for pos in self.positions: p = sphere(pos=vec(*pos), radius=self.radius, color=color.red) p.update = True # to determine if needs position update self.particles.append(p)
def loop(self): while self.something_in_the_air: self.update() if self.particles: rate(200) for p,pos in zip(sim.particles, sim.positions): if p.update: p.pos = vec(*pos) if p.pos.z < start.z: p.update = False
from vpython import vec from color import Color from enum import Enum cores = { "red": vec(1, 0, 0), "yellow": vec(1, 1, 0), "black": vec(0, 0, 0), "green": vec(0, 1, 0), "orange": vec(1, 0.6, 0), "white": vec(1, 1, 1), "blue": vec(0, 0, 1), "cyan": vec(0, 1, 1), "purple": vec(0.4, 0.2, 0.6), "magenta": vec(1, 0, 1) } color = Color("#ffffff") print(color) color.change_color_from_hex("#ff00ff") print(color) # for key in cores: # print(key, end=" ") # color.change_color_from_vec(cores[key]) # print(color)
def vector_to_vec(self, inVec): return vec(inVec.to_points()[0], inVec.to_points()[1], inVec.to_points()[2])
def import_object_from_numpy_stl(filename, scene): # pragma nocover """ Import either an ASCII or BINARY file format of an STL file. The triangles will be combined into a single compound entity. :param filename: Path of the stl file to import. :type filename: `str` :param scene: The scene in which to draw the object :type scene: class:`vpython.canvas` :return: Compound object of a collection of triangles formed from an stl file. :rtype: class:`vpython.compound` """ # filename = meshdata[0] # scale = meshdata[1] # origin = meshdata[2] # origin_pos = get_pose_pos(origin) # origin_x = get_pose_x_vec(origin) # origin_y = get_pose_y_vec(origin) # origin_z = get_pose_z_vec(origin) # Load the mesh using NumPy-STL the_mesh = mesh.Mesh.from_file(filename) num_faces = len(the_mesh.vectors) triangles = [] # For every face in the model for face in range(0, num_faces): # Get the (3) 3D points point0 = the_mesh.vectors[face][0] point1 = the_mesh.vectors[face][1] point2 = the_mesh.vectors[face][2] # Get the normal direction for the face normal0 = the_mesh.normals[face][0] normal1 = the_mesh.normals[face][1] normal2 = the_mesh.normals[face][2] normal = vec(normal0, normal1, normal2) # Create the VPython 3D points vertex0 = vertex(pos=vec(point0[0], point0[1], point0[2]), normal=normal, color=color.white) vertex1 = vertex(pos=vec(point1[0], point1[1], point1[2]), normal=normal, color=color.white) vertex2 = vertex(pos=vec(point2[0], point2[1], point2[2]), normal=normal, color=color.white) # Combine them in a list vertices = [vertex0, vertex1, vertex2] # Create a triangle using the points, and add it to the list triangles.append(triangle(canvas=scene, vs=vertices)) # Return a compound of the triangles visual_mesh = compound(triangles, origin=vec(0, 0, 0), canvas=scene) # visual_mesh.length *= scale[0] # visual_mesh.height *= scale[1] # visual_mesh.width *= scale[2] return visual_mesh
def _create_hab(self, entity: Entity, texture: str) -> \ vpython.compound: def vertex(x: float, y: float, z: float) -> vpython.vertex: return vpython.vertex(pos=vpython.vector(x, y, z)) # See the docstring of ThreeDeeObj._create_obj for why the dimensions # that define the shape of the habitat will not actually directly # translate to world-space. body = vpython.cylinder(pos=vpython.vec(0, 0, 0), axis=vpython.vec(-5, 0, 0), radius=10) head = vpython.cone(pos=vpython.vec(0, 0, 0), axis=vpython.vec(2, 0, 0), radius=10) wing = vpython.triangle(v0=vertex(0, 0, 0), v1=vertex(-5, 30, 0), v2=vertex(-5, -30, 0)) wing2 = vpython.triangle(v0=vertex(0, 0, 0), v1=vertex(-5, 0, 30), v2=vertex(-5, 0, -30)) hab = vpython.compound([body, head, wing, wing2], make_trail=True, texture=texture) hab.axis = calc.angle_to_vpy(entity.heading) hab.radius = entity.r / 2 hab.shininess = 0.1 hab.length = entity.r * 2 boosters: List[vpython.cylinder] = [] body_radius = entity.r / 8 for quadrant in range(0, 4): # Generate four SRB bodies. normal = vpython.rotate(vpython.vector(0, 1, 1).hat, angle=quadrant * vpython.radians(90), axis=vpython.vector(1, 0, 0)) boosters.append( vpython.cylinder(radius=self.BOOSTER_RADIUS, pos=(self.BOOSTER_RADIUS + body_radius) * normal)) boosters.append( vpython.cone( radius=self.BOOSTER_RADIUS, length=0.2, pos=((self.BOOSTER_RADIUS + body_radius) * normal + vpython.vec(1, 0, 0)))) # Append an invisible point to shift the boosters down the fuselage. # For an explanation of why that matters, read the # ThreeDeeObj._create_obj docstring (and if that doesn't make sense, # get in touch with Patrick M please hello hi I'm always free!) boosters.append(vpython.sphere(opacity=0, pos=vpython.vec(1.2, 0, 0))) booster_texture = texture.replace(f'{entity.name}.jpg', 'SRB.jpg') hab.boosters = vpython.compound(boosters, texture=booster_texture) hab.boosters.length = entity.r * 2 hab.boosters.axis = hab.axis parachute: List[vpython.standardAttributes] = [] string_length = entity.r * 0.5 parachute_texture = texture.replace(f'{entity.name}.jpg', 'Parachute.jpg') # Build the parachute fabric. parachute.append( vpython.extrusion( path=vpython.paths.circle(radius=0.5, up=vpython.vec(-1, 0, 0)), shape=vpython.shapes.arc(angle1=vpython.radians(5), angle2=vpython.radians(95), radius=1), pos=vpython.vec(string_length + self.PARACHUTE_RADIUS / 2, 0, 0))) parachute[0].height = self.PARACHUTE_RADIUS * 2 parachute[0].width = self.PARACHUTE_RADIUS * 2 parachute[0].length = self.PARACHUTE_RADIUS for quadrant in range(0, 4): # Generate parachute attachment lines. string = vpython.cylinder(axis=vpython.vec(string_length, self.PARACHUTE_RADIUS, 0), radius=0.2) string.rotate(angle=(quadrant * vpython.radians(90) - vpython.radians(45)), axis=vpython.vector(1, 0, 0)) parachute.append(string) parachute.append( vpython.sphere(opacity=0, pos=vpython.vec( -(string_length + self.PARACHUTE_RADIUS), 0, 0))) hab.parachute = vpython.compound(parachute, texture=parachute_texture) hab.parachute.visible = False return hab
X_LIMIT = x_bound * AU Y_LIMIT = y_bound * AU Z_LIMIT = z_bound * AU # Scale the axis length based on the size of the system AXIS_LENGTH = X_LIMIT / 10 if __name__ == "__main__": # Create the scene scene = vp.canvas(title="Planet Formation", background=vp.color.black, width=1300, height=650) scene.autoscale = 1 # Draw coordinate axes for reference x_axis = vp.curve(pos=[vp.vec(0, 0, 0), vp.vec(AXIS_LENGTH, 0, 0)], color=vp.vec(1, 0, 0)) y_axis = vp.curve(pos=[vp.vec(0, 0, 0), vp.vec(0, AXIS_LENGTH, 0)], color=vp.vec(0, 1, 0)) z_axis = vp.curve(pos=[vp.vec(0, 0, 0), vp.vec(0, 0, AXIS_LENGTH)], color=vp.vec(0, 0, 1)) # Start populating the scene create_system(x_bound=10, y_bound=10, z_bound=10) bounds = (X_LIMIT, Y_LIMIT, Z_LIMIT) # Make some planetesimals for i in range(50): p = celest.create_random_planetesimal(bounds=bounds) PLANETESIMALS.append(p)
from vpython import sphere, box, cylinder, cone, color, curve, rate from vpython import sqrt, atan, cos, sin from vpython import vector as vec dirt = vec(1, 0.6, 0.4) ground = box(color=dirt) ground.axis = vec(1, 0, 1) ground.size = vec(0.305 * 120 / sqrt(2), 0.305 * 1, 0.305 * 120 / sqrt(2)) ground.pos = 0.305 * vec(0, -0.5, 0) mound = cone(color=dirt) mound.axis = 0.305 * vec(0, 10 / 12, 0) mound.radius = 0.305 * 9 pitcher = cylinder(color=color.red) pitcher.pos = 0.305 * vec(0, 10 / 12, 0) pitcher.axis = 0.305 * vec(0, 6, 0) plate = box(color=color.yellow) plate.size = vec(1, 0.1, 1) plate.pos = 0.305 * vec(60.5, 0, 0) strikezone = box(color=color.red) strikezone.size = vec(0.305 / 12, 0.305 * 2, 0.305 * 2) strikezone.pos = 0.305 * vec(60.5, 2.5, 0) def in_boundary(x, bound, pos): return x - bound / 2 < pos < x + bound / 2
def __init_scene__(self): scene.width = 1320 scene.height = 830 scene.range = self.ctx.L scene.forward = vec(-1, -1, -1)
def getColor(n, total): RGB = colorsys.hsv_to_rgb(n / total, 0.9, 0.9) return vpython.vec(*RGB)
radius=.15, color=vp.vector(0, 0, 0)) head = vp.compound([head_main, left_eye, right_eye]) for i in range(5): print(ser.readline()) old_theta = 0 old_phi = 0 while 1: read = ser.readline().decode("utf-8").split() x = float(read[1]) y = float(read[3]) z = float(read[5]) theta = float(read[7]) phi = float(read[9]) print(f'x: {x} y: {y} z: {z} theta: {theta}, phi: {phi}') #mag = sqrt(x**2 + y**2 + z**2) #head.axis = vp.vector(x/mag, y/mag, z/mag) head.rotate(angle=-old_theta, axis=vp.vec(-1, 0, 0), origin=vp.vector(0, 0, 0)) head.rotate(angle=theta, axis=vp.vec(-1, 0, 0), origin=vp.vector(0, 0, 0)) head.rotate(angle=-old_phi, axis=vp.vec(0, 0, 1), origin=vp.vector(0, 0, 0)) head.rotate(angle=phi, axis=vp.vec(0, 0, 1), origin=vp.vector(0, 0, 0)) old_theta = theta old_phi = phi
inputs: ------- vector - (vpy.vector) - a vpython vector returns: -------- (float) - maximum absolute value of the coordinates of the vector """ return max(abs(vector.x), abs(vector.y), abs(vector.z)) if __name__ == "__main__": canvas = vpy.canvas(background=vpy.vector(0.8, 0.8, 0.8), up=vpy.vector(0, 0, 1), forward=vpy.vector(-1, 0, 0)) canvas.lights = [] canvas.ambient = vpy.vec(1, 1, 1) * 0.4 vpy.distant_light(direction=vpy.vector(1, 1, 1), color=vpy.vector(0.7, 0.7, 0.7)) vpy.distant_light(direction=vpy.vector(-1, -1, -1), color=vpy.vector(0.7, 0.7, 0.7)) # points = ggb_vpy.get_point_dicts("ggb_files/mixup cube points.ggb") # points = ggb_vpy.get_point_dicts("ggb_files/rubiks cube points.ggb") points = ggb_vpy.get_point_dicts("../ggb_files/gear cube points.ggb") points = snap_to_sphere(points) ggb_vpy.draw_cones(points) # points = snap_to_cube(points) # ggb_vpy.draw_points(points)
def set_observing_camera(self): self.c.clear() self.scene.center = vec(0, 0, 0) self.camera.pos = vec(0, 1250, -1000) self.camera.axis = -self.camera.pos
def aim_camera_position(self, fi, r=300): x = r * cos(fi) z = r * sin(fi) return vec(x, 50, z)
def create_pockets(self): pocket1 = cylinder(pos=vec(0, -WALL_WIDTH / 2.1, -WIDTH / 1.95), axis=vec(0, WALL_WIDTH, 0), radius=HOLE_RADIUS, color=color.black) pocket2 = cylinder(pos=vec(0, -WALL_WIDTH / 2.1, WIDTH / 1.95), axis=vec(0, WALL_WIDTH, 0), radius=HOLE_RADIUS, color=color.black) pocket3 = cylinder(pos=vec(-LENGTH / 2, -WALL_WIDTH / 2.1, -WIDTH / 2), axis=vec(0, WALL_WIDTH, 0), radius=HOLE_RADIUS, color=color.black) pocket4 = cylinder(pos=vec(LENGTH / 2, -WALL_WIDTH / 2.1, -WIDTH / 2), axis=vec(0, WALL_WIDTH, 0), radius=HOLE_RADIUS, color=color.black) pocket5 = cylinder(pos=vec(-LENGTH / 2, -WALL_WIDTH / 2.1, WIDTH / 2), axis=vec(0, WALL_WIDTH, 0), radius=HOLE_RADIUS, color=color.black) pocket6 = cylinder(pos=vec(LENGTH / 2, -WALL_WIDTH / 2.1, WIDTH / 2), axis=vec(0, WALL_WIDTH, 0), radius=HOLE_RADIUS, color=color.black) return [pocket1, pocket2, pocket3, pocket4, pocket5, pocket6]
def __init__(self): self.board = box(pos=POSITION, size=vec(LENGTH, 0, WIDTH), color=color.green) self.create_walls() self.pockets = self.create_pockets()
def render(obj, loadingspace, n): L, W, H = loadingspace.boundingBox scene = vpython.canvas() scene.title = ("<h1>" + obj.TypeString().capitalize() + " with id " + str(obj.id) + "</h1>" if n == 0 else "") + "<h2>Loadingspace with id " + str( loadingspace.id) + "</h2>" scene.background = vpython.color.white scene.center = vpython.vec(L / 2, H / 2, -W / 2) scene.forward = vpython.vec(0.0, 0.0, -1.0) scene.append_to_caption( "<table style='border-collapse: collapse;'><tr><th>Control</th><th>Function</th></tr>" +\ "<tr style='border-bottom: 1px solid black;'><td style='text-align: center;'><div style='margin-top: 15px; margin-bottom: 15px;'>" + r_drag + "</div><div style='margin-top: 15px; margin-bottom: 15px;'>" + ctrl + "+" + l_drag + "</div></td><td style='text-align: center;'>Rotate</td></tr>" +\ "<tr style='border-bottom: 1px solid black;'><td style='text-align: center;'><div style='margin-top: 15px; margin-bottom: 15px;'>" + m_drag + "</div><div style='margin-top: 15px; margin-bottom: 15px;'>" + alt + "+" + l_drag + "</div><div style='margin-top: 15px; margin-bottom: 15px;'>" + option + "+" + l_drag + "</div><div style='margin-top: 15px; margin-bottom: 15px;'>" + b_drag + "</div></td><td style='text-align: center;'>Zoom</td></tr>" +\ "<tr style='border-bottom: 1px solid black;'><td style='text-align: center;'><div style='margin-top: 15px; margin-bottom: 15px;'>" + shift + "+" + l_drag + "</div></td><td style='text-align: center;'>Pan</td></tr></table>") for n, placement in enumerate(loadingspace.placements): if args.color == 'file': if placement.color is not None: if len(placement.color) != 7 and len(placement.color) != 9 or\ placement.color[0] != "#" or\ any(map((lambda c: c.upper() not in ["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"]),placement.color[1:])): raise Exception( "Incorrectly formatted color attribute for placement with id " + str(placement.id)) c = vpython.vec( int(placement.color[1:3], 16) / 255, int(placement.color[3:5], 16) / 255, int(placement.color[5:7], 16) / 255) o = args.opacity if len(placement.color) == 9: o = int(placement.color[7:], 16) / 255 else: c = vpython.vec(0.9, 0.9, 0.9) o = args.opacity elif args.color == 'correct': if placement.correct: c = vpython.vec(0, 1, 0) o = args.opacity else: c = vpython.vec(1, 0, 0) o = 1 else: c = getColor(n, len(loadingspace.placements)) o = 1 x1 = placement.position x2 = [x + l for x, l in zip(x1, placement.boundingBox)] b = placement_to_box((x1, x2)) box(pos=vpython.vec(*b[0]), size=vpython.vec(*b[1]), color=c, opacity=o) # from common.Constraints import ReadableItemLabelConstraint # for dummy in ReadableItemLabelConstraint.GetDummies(loadingspace): # x1 = dummy.position # x2 = [x + l for x,l in zip(x1, dummy.boundingBox)] # b = placement_to_box((x1,x2)) # box(pos=vec(*b[0]), size=vec(*b[1]), color=vec(1,0,0), opacity=0.1) beam = 0.002 * max(L, W, H) box(pos=vpython.vec(L / 2, -beam / 2, -W / 2), size=vpython.vec(L, beam, W), color=vpython.vec(0.8, 0.8, 0.8)) box(pos=vpython.vec(-beam / 2, H / 2, beam / 2), size=vpython.vec(beam, H + 2 * beam, beam), color=vpython.color.black) box(pos=vpython.vec(-beam / 2, H / 2, -W - beam / 2), size=vpython.vec(beam, H + 2 * beam, beam), color=vpython.color.black) box(pos=vpython.vec(L + beam / 2, H / 2, beam / 2), size=vpython.vec(beam, H + 2 * beam, beam), color=vpython.color.black) box(pos=vpython.vec(L + beam / 2, H / 2, -W - beam / 2), size=vpython.vec(beam, H + 2 * beam, beam), color=vpython.color.black) box(pos=vpython.vec(L / 2, H + beam / 2, -W - beam / 2), size=vpython.vec(L, beam, beam), color=vpython.color.black) box(pos=vpython.vec(L / 2, H + beam / 2, beam / 2), size=vpython.vec(L, beam, beam), color=vpython.color.black) box(pos=vpython.vec(L / 2, -beam / 2, -W - beam / 2), size=vpython.vec(L, beam, beam), color=vpython.color.black) box(pos=vpython.vec(L / 2, -beam / 2, beam / 2), size=vpython.vec(L, beam, beam), color=vpython.color.black) box(pos=vpython.vec(L + beam / 2, H + beam / 2, -W / 2), size=vpython.vec(beam, beam, W), color=vpython.color.black) box(pos=vpython.vec(-beam / 2, H + beam / 2, -W / 2), size=vpython.vec(beam, beam, W), color=vpython.color.black) box(pos=vpython.vec(L + beam / 2, -beam / 2, -W / 2), size=vpython.vec(beam, beam, W), color=vpython.color.black) box(pos=vpython.vec(-beam / 2, -beam / 2, -W / 2), size=vpython.vec(beam, beam, W), color=vpython.color.black) M = min(L, W, H) vpython.arrow(pos=vpython.vec(0, 0, 0), axis=vpython.vec(+M / 4, +0, +0), color=vpython.color.red) vpython.arrow(pos=vpython.vec(0, 0, 0), axis=vpython.vec(+0, +M / 4, +0), color=vpython.color.blue) vpython.arrow(pos=vpython.vec(0, 0, 0), axis=vpython.vec(+0, +0, -M / 4), color=vpython.color.green) vpython.box(pos=vpython.vec(0, 0, 0), size=vpython.vec(M / 20, M / 20, M / 20), color=vpython.color.black)
def run(self): pos = array(self.pos_list) p = array(self.p_list) m = array(self.m_list) m.shape = (self.ctx.stars, 1 ) # Numeric Python: (1 by Nstars) vs. (Nstars by 1) radius = array(self.r_list) vcm = sum(p) / sum(m) # velocity of center of mass p = p - m * vcm # make total initial momentum equal zero dt = 50.0 pos = pos + (p / m) * (dt / 2.0) # initial half-step num_hits = 0 L = self.ctx.L while True: rate(50) L *= 1.0 + self.ctx.h0 * dt # strength of force to allow for external mass con = 1.0 * self.ctx.G * self.ctx.stars * self.ctx.Msun / L**3 # Compute all forces on all stars r = pos - pos[:, newaxis] # all pairs of star-to-star vectors for i in range(self.ctx.stars): r[i, i] = 1e6 # otherwise the self-forces are infinite rmag = sqrt(add.reduce(r**2, -1)) # star-to-star scalar distances hit = less_equal(rmag, radius + radius[:, newaxis]) - identity( self.ctx.stars) # 1,2 encoded as 1 * stars + 2 hit_list = sort(nonzero(hit.flat)[0]).tolist() F = self.ctx.G * m * m[:, newaxis] * r / rmag[:, :, newaxis]**3 # all force pairs for i in range(self.ctx.stars): F[i, i] = 0 # no self-forces p = p + sum(F, 1) * dt + pos * con * dt * m # Having updated all momenta, now update all positions pos += (p / m) * dt # Expand universe pos *= 1.0 + self.ctx.h0 * dt # Update positions of display objects; add trail for i in range(self.ctx.stars): v = pos[i] self.stars[i].pos = vec(v[0], v[1], v[2]) # If any collisions took place, merge those stars for hit in hit_list: i, j = divmod(hit, self.ctx.stars) # decode star pair if not (self.stars[i].visible or self.stars[j].visible): continue # m[i] is a one-element list, e.g. [6e30] # m[i,0] is an ordinary number, e.g. 6e30 new_pos = (pos[i] * m[i, 0] + pos[j] * m[j, 0]) / (m[i, 0] + m[j, 0]) new_mass = m[i, 0] + m[j, 0] new_p = p[i] + p[j] new_radius = self.ctx.Rsun * ( (new_mass / self.ctx.Msun)**(1.0 / 3.0)) i_set, j_set = i, j if radius[j] > radius[i]: i_set, j_set = j, i self.stars[i_set].radius = new_radius m[i_set, 0] = new_mass pos[i_set] = new_pos p[i_set] = new_p self.stars[j_set].visible = 0 p[j_set] = vec(0, 0, 0) m[j_set, 0] = self.ctx.Msun * 1e-30 # give it a tiny mass num_hits += 1 pos[j_set] = (10.0 * L * num_hits, 0, 0) # put it far away
def change_B(slider): global B_mag B_mag = 10**slider.value cyclotron.b_field = vec(0, 0, -B_mag) B_text.text = "|B|={:.2e}s:".format(B_mag)
def plot_vpython(network, Psize='pore.diameter', Tsize='throat.diameter', Pcolor=None, Tcolor=None, cmap='jet', **kwargs): # pragma: no cover r""" Quickly visualize a network in 3D using VPython. Parameters ---------- network : GenericNetwork The network to visualize. Psize : str (default = 'pore.diameter') The dictionary key pointing to the pore property by which sphere diameters should be scaled Tsize : str (default = 'throat.diameter') The dictionary key pointing to the throat property by which cylinder diameters should be scaled Pcolor : str The dictionary key pointing to the pore property which will control the sphere colors. The default is None, which results in a bright red for all pores. Tcolor : str The dictionary key pointing to the throat property which will control the cylinder colors. The default is None, which results in a unform pale blue for all throats. cmap : str or Matplotlib colormap object (default is 'jet') The color map to use when converting pore and throat properties to RGB colors. Can either be a string indicating which color map to fetch from matplotlib.cmap, or an actual cmap object. kwargs : dict Any additional kwargs that are received are passed to the VPython ``canvas`` object. Default options are: *'height' = 500* - Height of canvas *'width' = 800* - Width of canvas *'background' = [0, 0, 0]* - Sets the background color of canvas *'ambient' = [0.2, 0.2, 0.3]* - Sets the brightness of lighting Returns ------- canvas : VPython Canvas object The canvas object containing the generated scene. The object has several useful methods. Notes ----- **Important** a) This does not work in Spyder. It should only be called from a Jupyter Notebook. b) This is only meant for relatively small networks. For proper visualization use Paraview. """ import matplotlib.pyplot as plt try: from vpython import canvas, vec, sphere, cylinder except ModuleNotFoundError: raise Exception('VPython must be installed to use this function') if isinstance(cmap, str): cmap = getattr(plt.cm, cmap) if Pcolor is None: Pcolor = [vec(230/255, 57/255, 0/255)]*network.Np else: a = cmap(network[Pcolor]/network[Pcolor].max()) Pcolor = [vec(row[0], row[1], row[2]) for row in a] if Tcolor is None: Tcolor = [vec(51/255, 153/255, 255/255)]*network.Nt else: a = cmap(network[Tcolor]/network[Tcolor].max()) Tcolor = [vec(row[0], row[1], row[2]) for row in a] # Set default values for canvas properties if 'background' not in kwargs.keys(): kwargs['background'] = vec(1.0, 1.0, 1.0) if 'height' not in kwargs.keys(): kwargs['height'] = 500 if 'width' not in kwargs.keys(): kwargs['width'] = 800 # Parse any given values for canvas properties for item in kwargs.keys(): try: kwargs[item] = vec(*kwargs[item]) except TypeError: pass scene = canvas(title=network.name, **kwargs) for p in network.Ps: r = network[Psize][p]/2 xyz = network['pore.coords'][p] c = Pcolor[p] sphere(pos=vec(*xyz), radius=r, color=c, shininess=.5) for t in network.Ts: head = network['throat.endpoints.head'][t] tail = network['throat.endpoints.tail'][t] v = tail - head r = network[Tsize][t] L = np.sqrt(np.sum((head-tail)**2)) c = Tcolor[t] cylinder(pos=vec(*head), axis=vec(*v), opacity=1, size=vec(L, r, r), color=c) return scene
from vpython import sphere, vec, mag, dot, cross, pi from math import sqrt RADIUS = 23.5 CUE_BALL_POS = vec(-600, 0, 0) BALL_ORDER = [[1], [10, 3], [6, 8, 13], [9, 4, 15, 2], [14, 11, 5, 12, 7]] RACK_POS = 400 HOLE_RADIUS = 37 class Ball: def __init__(self, number, pos=vec(0, 0, 0)): self.number = number self.velocity = vec(0, 0, 0) self.rotation_axis = vec(0, 0, 0) if number in range(1, 16): self.ball = sphere( radius=RADIUS, pos=pos, texture={'file': 'textures/ball{}.jpg'.format(self.number)}) else: self.ball = sphere(radius=RADIUS, pos=CUE_BALL_POS) def set_velocity(self, velocity): self.velocity = velocity self.calculate_rotation_axis() def calculate_rotation_axis(self): self.rotation_axis = cross(vec(0, 1, 0), self.velocity) def move(self, dt):
def render(self, mode, render_step=10): assert isinstance(self._dyn, BallBalancerDynamics ), "Missing dynamics properties for simulation!" # Cheap printing to console if self._step_count % render_step == 0: print( "time step: {:3} | in bounds: {:1} | state: {} | action: {}" .format(self._step_count, self.state_space.contains(self._state), self._state, self._curr_action)) if not self.state_space.contains(self._state): # State is out of bounds np.set_printoptions(precision=3) print("min state : ", self.state_space.low) print("last state: ", self._state) print("max state : ", self.state_space.high) # Render using VPython import vpython as vp vp.rate(30) d_plate = 0.01 # only for animation # Init render objects on first call if self._anim_canvas is None: self._anim_canvas = vp.canvas(width=800, height=600, title="Quanser Ball Balancer") self._anim_ball = vp.sphere( pos=vp.vector(self._state[2], self._state[3], self._dyn.r_ball + d_plate / 2.), radius=self._dyn.r_ball, mass=self._dyn.m_ball, color=vp.color.red, canvas=self._anim_canvas, ) self._anim_plate = vp.box( pos=vp.vector(0, 0, 0), size=vp.vector(self._dyn.l_plate, self._dyn.l_plate, d_plate), color=vp.color.green, canvas=self._anim_canvas, ) # Compute plate orientation a = -self._plate_angs[0] # plate's angle around the y axis (alpha) b = self._plate_angs[1] # plate's angle around the x axis (beta) # Axis runs along the x direction self._anim_plate.axis = vp.vec( vp.cos(a), 0, vp.sin(a), ) * self._dyn.l_plate # Up runs along the y direction (vpython coordinate system is weird) self._anim_plate.up = vp.vec( 0, vp.cos(b), vp.sin(b), ) # Compute ball position x = self._state[2] # ball position along the x axis y = self._state[3] # ball position along the y axis self._anim_ball.pos = vp.vec( x * vp.cos(a), y * vp.cos(b), self._dyn.r_ball + x * vp.sin(a) + y * vp.sin(b) + vp.cos(a) * d_plate / 2., ) # Set caption text self._anim_canvas.caption = f"""
def calculate_rotation_axis(self): self.rotation_axis = cross(vec(0, 1, 0), self.velocity)
def draw(self, entity: Entity, state: PhysicsState, origin: Entity): self._update_obj(entity, state, origin) self._obj.boosters.pos = self._obj.pos self._obj.boosters.axis = self._obj.axis # Attach the parachute to the forward cone of the habitat. self._obj.parachute.pos = ( self._obj.pos + calc.angle_to_vpy(entity.heading) * entity.r * 0.8) parachute_is_visible = ((state.craft == entity.name) and state.parachute_deployed) if parachute_is_visible: drag = calc.drag(state) drag_mag = np.inner(drag, drag) for parachute in [self._obj.parachute, self._small_habitat.parachute]: if not parachute_is_visible or drag_mag < 0.00001: # If parachute_is_visible == False, don't show the parachute. # If the drag is basically zero, don't show the parachute. parachute.visible = False continue if drag_mag > 0.1: parachute.width = self.PARACHUTE_RADIUS * 2 parachute.height = self.PARACHUTE_RADIUS * 2 else: # Below a certain threshold the parachute deflates. parachute.width = self.PARACHUTE_RADIUS parachute.height = self.PARACHUTE_RADIUS parachute.axis = -vpython.vec(*drag, 0) parachute.visible = True if not self._broken and entity.broken: # We weren't broken before, but looking at new data we realize # we're now broken. Change the habitat texture. new_texture = self._obj.texture.replace('Habitat.jpg', 'Habitat-broken.jpg') assert new_texture != self._obj.texture, \ f'{new_texture!r} == {self._obj.texture!r}' self._obj.texture = new_texture self._small_habitat.texture = new_texture self._broken = entity.broken elif self._broken and not entity.broken: # We were broken before, but we've repaired ourselves somehow. new_texture = self._obj.texture.replace('Habitat-broken.jpg', 'Habitat.jpg') assert new_texture != self._obj.texture, \ f'{new_texture!r} == {self._obj.texture!r}' self._obj.texture = new_texture self._small_habitat.texture = new_texture self._broken = entity.broken # Set reference and target arrows of the minimap habitat. same = state.reference == entity.name default = vpython.vector(0, 0, -1) ref_arrow_axis = (entity.screen_pos(state.reference_entity()).norm() * entity.r * -1.2) v = entity.v - state.reference_entity().v velocity_arrow_axis = \ vpython.vector(*v, 0).norm() * entity.r self._ref_arrow.axis = default if same else ref_arrow_axis self._velocity_arrow.axis = default if same else velocity_arrow_axis self._small_habitat.axis = self._obj.axis self._small_habitat.boosters.axis = self._obj.axis # Invisibile-ize the SRBs if we ran out. if state.srb_time == common.SRB_EMPTY and self._obj.boosters.visible: self._obj.boosters.visible = False self._small_habitat.boosters.visible = False
def pocket_collision(self, pockets, info): for pocket in pockets: if mag(self.ball.pos - pocket.pos) < HOLE_RADIUS + RADIUS: self.set_velocity(vec(0, 0, 0)) self.ball.visible = False info.score(self)
bind = change_dt) vis.wtext(pos = scene.title_anchor, text = " ") vis.checkbox(pos = scene.title_anchor, text = "Enable infoboxes", checked = True, bind = toggle_infobox) vis.wtext(pos = scene.title_anchor, text = " ") vis.checkbox(pos = scene.title_anchor, text = "Show controls", checked = False, bind = toggle_controls) # Define constants and global variables ================================================================================ # Color constants for your convenience COLOR_BLACK = vis.color.black COLOR_WHITE = vis.color.white COLOR_RED = vis.color.red COLOR_GREEN = vis.color.green COLOR_BLUE = vis.color.blue COLOR_DARK_BLUE = vec(0, 0, 0.6) COLOR_LIGHT_BLUE = vec(0.31, 0.49, 1.0) COLOR_YELLOW = vis.color.yellow COLOR_CYAN = vis.color.cyan COLOR_MAGENTA = vis.color.magenta COLOR_ORANGE = vis.color.orange COLOR_ORANGE_RED = vec(1, 0.3, 0) COLOR_ORANGE_YELLOW = vec(1, 0.8, 0) COLOR_PURPLE = vis.color.purple COLOR_LIGHT_GREY = vis.color.gray(0.7) COLOR_DARK_GREY = vis.color.gray(0.5) # Physical constants G = 6.674e-11 # gravitational constant, m^3 kg^-1 s^-2 AU = 1.496e11 # 1AU = 1.496 * 10^11 meters: you can also define your orbital parameters in AU instead of meters
R_1 = 12.0e-3 / 2 R_2 = 30.0e-3 / 2 R_m = 1.1 * R_2 * sqrt(2.0) U_r = 3.5e3 k = 2 * U_r / (R_m**2 * log(R_2 / R_1) - (R_2**2 - R_1**2) / 2) N_t = 2**13 kappa = 100 # particle settings u = scipy.constants.physical_constants["atomic mass constant"][0] q = 1 * scipy.constants.e m = 12 * u R = (3 * R_1 + R_2) / 4 v_phi = sqrt((k / 2) * (q / m) * (R_m**2 - R**2)) v = vec(-v_phi, 0, 0) r = vec(0, R, 12e-3) def U(r, z): return (k / 2) * (z**2 - (r**2 - R_1**2) / 2 + R_m**2 * log(r / R_1)) - U_r def dU(r): return (k / 2) * (R_m**2 / r - r) def E(p): r = sqrt(p.x**2 + p.y**2) phi = atan2(p.y, p.x) E_r = -(k / 2) * (R_m**2 / r - r)
def set_clip_poly(self, shape_str="cuboid", size=None, show_edges=True): """ define a polyhedron to set the shape of the puzzle. saves the polyhedron as self.clip_poly and displays it with low opacity inputs: ------- shape_str - (str) - the shape of the polyhedron current options: - 'cuboid' = 'c' (default) - 'cube' - 'octahedron' = 'oct' - 'tetrahedron' = 'tet' size - (float) or (vpy.vector) - if shape is a cuboid, this has to be a vpython vector, otherwise it needs to be a float raises: ------- - ValueError if the shape is not valid - TypeError if the shape is not given as a string """ if not isinstance(shape_str, str): raise TypeError(f"'shape_str' should be of type 'str' \ but was of type '{type(shape_str)}'") if hasattr(self, "clip_poly"): self.clip_poly.obj.visible = False # if isinstance(self.clip_poly, Polyhedron): # self.clip_poly.toggle_visible(False) # else: if shape_str in ("cuboid", "c"): if size == None: xsize = max([obj.pos.x for obj in self.vpy_objects]) \ + abs(min([obj.pos.x for obj in self.vpy_objects])) ysize = max([obj.pos.y for obj in self.vpy_objects]) \ + abs(min([obj.pos.y for obj in self.vpy_objects])) zsize = max([obj.pos.z for obj in self.vpy_objects]) \ + abs(min([obj.pos.z for obj in self.vpy_objects])) size = vpy.vec(xsize, ysize, zsize) elif isinstance(size, (float, int)): size = vpy.vec(size, size, size) corners, faces = shapes["cuboid"](size=size) elif shape_str in ("tetrahedron", "tet"): if size == None: size = 2 * max([obj.pos.mag for obj in self.vpy_objects]) corners, faces = shapes["tetrahedron"](radius=size) elif shape_str in ("cube"): if size == None: size = 2*max( [max([abs(obj.pos.x), abs(obj.pos.y), abs(obj.pos.z)]) \ for obj in self.vpy_objects]) corners, faces = shapes["cube"](sidelength=size) elif shape_str in ("octahedron", "oct"): if size == None: size = 2 * max([obj.pos.mag for obj in self.vpy_objects]) corners, faces = shapes["octahedron"](radius=size) elif shape_str in ("cylinder", "cyl"): if size == None: size = max([ vpy.sqrt(obj.pos.x**2 + obj.pos.y**2) for obj in self.vpy_objects ]) height = max([obj.pos.z for obj in self.vpy_objects]) \ + abs(min([obj.pos.z for obj in self.vpy_objects])) corners, faces = shapes["cylinder"](radius=size, height=height) else: raise ValueError( f"Invalid shape. Got {shape_str} but expected one of ['c', 'cuboid', 'tetrahedron', 'cube', 'oct', 'octahedron']." ) self.clip_poly = Polyhedron(corners, faces, opacity=.2, color=vpy.vec(0.4, 0, 0.6), show_edges=show_edges, show_corners=show_edges)
def E(p): r = sqrt(p.x**2 + p.y**2) phi = atan2(p.y, p.x) E_r = -(k / 2) * (R_m**2 / r - r) return vec(E_r * cos(phi), E_r * sin(phi), -k * p.z)
# coding: utf-8 # In[ ]: from vpython import sphere, canvas, box, vec, color, rate # In[ ]: win=600 L = 10. # container is a cube L on a side gray = vec(0.7,0.7,0.7) # color of edges of container up = vec(0, 0, 1) # In[ ]: scene = canvas(title="Fans", width=win, height=win, x=0, y=0, center=vec(0, 0, 0), forward=vec(1,0,-0.5), up=up) scene.autoscale = False scene.range = 10 h = 0.1 mybox = box(pos=vec(0, 0, -h/2), length=L, height=h, width=L, up=up, color=gray) m = 1 # kg
def point(self, i, phi, mirror=False): z = i * self.dz r = self.r_Newton(z) if (mirror): z *= -1 return vec(r * cos(phi), r * sin(phi), z)
import vpython as vp N = 100 m = 8 vp.scene.width = vp.scene.height = N * m vp.scene.center = vp.vec(N * m / 2, N * m / 2, 0) vp.scene.range = 0.5 * N * m v = [] quads = [] for x in range(N): for y in range(N): c = vp.color.hsv_to_rgb(vp.vec(x / N, 1, 1)) v.append( vp.vertex(pos=vp.vec(x, y, 0), color=c, normal=vp.vec(0, 0, 1))) for x in range(N - 1): for y in range(N - 1): quads.append( vp.quad(vs=[ v[N * x + y], v[N * x + N + y], v[N * x + N + y + 1], v[N * x + y + 1] ])) q = vp.compound(quads) clones = [] n = N - 1 for x in range(m): for y in range(m): clones.append(q.clone(pos=vp.vec(n * x + N / 2, n * y + N / 2, 0))) q.visible = False # make the original object invisible
from vpython import box, vec, color, cylinder, shapes LENGTH = 2000 WIDTH = 1000 WALL_WIDTH = 50 HOLE_RADIUS = 37 POSITION = vec(0, -23.5, 0) class Table: def __init__(self): self.board = box(pos=POSITION, size=vec(LENGTH, 0, WIDTH), color=color.green) self.create_walls() self.pockets = self.create_pockets() def create_walls(self): brown = vec(0.55, 0.27, 0.07) wall_right = box(pos=vec(0, 0, (WIDTH + WALL_WIDTH) / 2), size=vec(LENGTH, WALL_WIDTH, WALL_WIDTH), color=brown) wall_left = box(pos=vec(0, 0, -(WIDTH + WALL_WIDTH) / 2), size=vec(LENGTH, WALL_WIDTH, WALL_WIDTH), color=brown) wall_up = box(pos=vec((LENGTH + WALL_WIDTH) / 2, 0, 0), size=vec(WALL_WIDTH, WALL_WIDTH, WIDTH + 2 * WALL_WIDTH), color=brown) wall_down = box(pos=vec(-(LENGTH + WALL_WIDTH) / 2, 0, 0), size=vec(WALL_WIDTH, WALL_WIDTH, WIDTH + 2 * WALL_WIDTH),