def draw_snooker_table(pt1, pt2, z): # pt1 = left top corner # pt2 = right bottom corner # z = ball radius print('Drawing table', pt1, pt2, z) length = pt2[0] - pt1[0] width = pt2[1] - pt1[1] height = 10 # Create table, note that the position is determined by the center of the box table = vp.box( pos=vp.vec(pt2[0] - length / 2, z - height / 2, pt2[1] - width / 2), length=int(length), height=10, width=int(width), color=vp.vec(0, 103 / 255, 1 / 255) # Green , texture={ 'file': './snooker_texture.jpg', 'place': 'all' }) table.shininess = 100000 corner_pocket_br = vp.extrusion( path=vp.paths.arc(radius=height, angle1=-pi / 2, angle2=+pi / 2), color=vp.vector(0.8, 0.8, 0.8), shape=[[vp.shapes.rectangle(pos=(1, 0), width=height, height=height)]]) # corner_pocket_br.rotate(angle=3 * pi / 4, axis=vp.vec(0, 1, 0)) corner_pocket_br.pos = vp.vec(pt1[0], 0, pt1[1]) corner_pocket_tr = corner_pocket_br.clone(pos=vp.vector(pt1[0], 0, pt2[1])) corner_pocket_tr.rotate(angle=pi / 2, axis=vp.vec(0, 1, 0)) corner_pocket_tl = corner_pocket_tr.clone(pos=vp.vector(pt2[0], 0, pt2[1])) corner_pocket_tl.rotate(angle=pi / 2, axis=vp.vec(0, 1, 0)) corner_pocket_bl = corner_pocket_tl.clone(pos=vp.vector(pt2[0], 0, pt1[1])) corner_pocket_bl.rotate(angle=pi / 2, axis=vp.vec(0, 1, 0))
def __init__(self): self._landing_graphic = vpython.extrusion( path=[vpython.vec(0, 0, 0), vpython.vec(1, 0, 0)], shape=vpython.shapes.circle(radius=1), up=common.DEFAULT_UP, forward=common.DEFAULT_FORWARD) self._attached_3dobj: Optional[ThreeDeeObj] = None
def __init__(self, name, vpline, p): color = vp.color.gray(0.5) shape = vp.shapes.rectangle(pos=(0, 0), width=1, height=largeur_station) dp = 3 # (m) pos = np.arange(p - azur_train_lenght - 3, p + 3, dp) path = [] for p in pos: x, y = vpline.get_pos(p, 0) path.append(vp.vector(x, y, station_depth)) self.visual = vp.extrusion(path=path, shape=shape, color=color)
def apply(self): for l in self.layers.layers: extr = extrusion(path=[vec(0,0,l.depth), vec(0,0,0)], color=color.cyan, shape=[ l.path ], pos=(self.vector_to_vec(l.position) + vec(0,0,l.depth / 2)), angle=l.angle, axis=self.vector_to_vec(l.axis)) if l.showAxis: self.draw_axis(l) if l.showPoints: self.draw_points(l)
def _create_obj(self, entity: Entity, origin: Entity, texture_path: Optional[str]) -> vpython.sphere: ship = vpython.cone(pos=vpython.vector(5, 0, 0), axis=vpython.vector(5, 0, 0), radius=3) entrance = vpython.extrusion( path=[vpython.vec(0, 0, 0), vpython.vec(4, 0, 0)], shape=[ vpython.shapes.circle(radius=3), vpython.shapes.rectangle(pos=[0, 0], width=0.5, height=0.5) ], pos=vpython.vec(3, 0, 0)) docking_arm = vpython.extrusion( path=[ vpython.vec(0, 0, 0), vpython.vec(1.5, 0, 0), vpython.vec(1.5, 0.5, 0) ], shape=[vpython.shapes.circle(radius=0.03)]) obj = vpython.compound([ship, entrance, docking_arm], make_trail=True, texture=vpython.textures.metal, bumpmap=vpython.bumpmaps.gravel) obj.pos = entity.screen_pos(origin) obj.axis = calc.angle_to_vpy(entity.heading) obj.length = entity.r * 2 obj.height = entity.r * 2 obj.width = entity.r * 2 # A compound object doesn't actually have a radius, but we need to # monkey-patch this for when we recentre the camera, to determine the # relevant_range of the space station obj.radius = entity.r return obj
def __init__(self, vel=(0.0, 0.0, 0.0), mass=1.0, rotation_speed=0.0, name='Sphere', simple=False, massive=True, labelled=False, luminous=False, primary=None, light_color='white', impulses=None, maneuver=None, preset=None, show_axes=False, obliquity=0, real_radius=None, synchronous=False, **kwargs): """ :param pos: (tuple/VPython vector) Position of the sphere; if primary is given, will be w.r.t the primary (default is vector(0, 0, 0)). :param vel: (tuple/VPython vector) Velocity of the sphere; if primary is given, will be w.r.t the primary (default is vector(0, 0, 0)). :param mass: (float) The mass of the sphere (default is 1.0). :param rotation_speed: (float) The rotational_speed of the Sphere in rads/s (default is 0.0). :param name: (str) The name of the Sphere (default is 'Sphere'). :param simple: (bool) If True will generate VPython simple_sphere instead of sphere (default is False). :param massive: (bool) False indicates that the Sphere' mass can be considered negligible (default is True). :param luminous: (bool) If True, will create a VPython local_light object at the Sphere pos (default is False). :param labelled: (bool) If True, creates a VPython label that contains some Sphere attribute values (default is False). :param primary: (Sphere) The self.pos and self.vel values are with respect to the pos and vel of this primary (default is None). :param light_color: (str) The color of the class attribute, light (default is 'white'). :param impulses: (tuple/tuple(tuples)) The impulse instructions ((time, delta v, burn angle), ...) or (time, delta v, burn angle) for only one impulse (default is None). :param maneuver: (class) A named maneuver class; will automatically created impulses instructions based off of the maneuver; will need to add the appropriate instance attributes for the maneuver. :param preset: (params class) Some pre-made parameters class (contains radius, mass, rotational speed, etc) (default is None). :param show_axes: (bool) If True, will display the cartesian axes and labels of the sphere; can be removed and/or replaced afterwards using toggle_axes() (default is False). :param obliquity: (float) The angle of obliquity in radians (default is 0). :param real_radius: (float) The radius value that is used in collision calculations (default is radius). :param synchronous: (bool) True if the Sphere has a synchronous rotation with respect to its primary; only useful if using a specific celestial body texture like the moon or Io (default is False). The parameters from simple_sphere, sphere, and Maneuver are also available. """ self.primary = primary self.massive = massive self.light_color = light_color self._labelled = labelled self.preset = preset self.synchronous = synchronous self._ring = None keys = kwargs.keys() # If a maneuver class is given, will create the appropriate impulse instructions. # If impulses is given with no maneuver class given, will use those instructions instead. if maneuver is not None: attrs = [ 'initial_radius', 'final_radius', 'transfer_apoapsis', 'transfer_eccentricity', 'inclination_change', 'start_time' ] params = {elem: kwargs.pop(elem) for elem in attrs if elem in keys} Maneuver.__init__( self, maneuver=maneuver, gravitational_parameter=self.primary.grav_parameter, **params) else: self.impulses = impulses # If a maneuver class is given or own impulse instructions given, will get a list of the impulse times. if self.impulses is not None: try: self.times = list(zip(*self.impulses))[0] except TypeError: self.times = [self.impulses[0]] self._vel = self._velocity = self.vpython_rotation( self.__try_vector(vel)) if 'pos' in keys: self._position = kwargs['pos'] = self.vpython_rotation( self.__try_vector(kwargs['pos'])) else: self._position = vector(0, 0, 0) # If primary is another Sphere, pos and vel are with respect to the primary; # This will update pos and vel to be with respect to the origin of the VPython reference frame. if isinstance(self.primary, Sphere): kwargs['pos'] = self._position + self.primary.pos self._vel = self._velocity + self.primary.vel self._k_hat = hat(cross(self._position, self._velocity)) if isinstance(self.primary, Sphere): self._up = self._k_hat else: self._up = self._zaxis # If a preset is given, uses preset attributes instead of the given attributes. if self.preset: self.mass = self.preset.mass self.rotation_speed = self.preset.angular_rotation self.grav_parameter = self.preset.gravitational_parameter self.name = str(self.preset()) kwargs['radius'] = self.preset.radius kwargs['texture'] = self.preset.texture if isinstance(self.primary, Sphere): self.obliquity = self.preset.obliquity angles = np.arange(0, 2 * math.pi, 0.05) arbitrary_r = rotate_y(ran.choice(angles)).dot( np.array([self._xaxis.x, self._xaxis.y, self._xaxis.z])) self._up = vector( *rodrigues_rotation(arbitrary_r, self.obliquity).dot( np.array([self._up.x, self._up.y, self._up.z]))) if self.name == 'Saturn': s = shapes.circle(radius=self.preset.ring_outer, thickness=0.4) p = paths.line(start=kwargs['pos'], end=(kwargs['pos'] + (7 * self._up))) self._ring = extrusion(shape=s, path=p, texture=self.preset.ring_texture, shininess=self.shininess, up=self._up) else: self.mass = mass self.rotation_speed = rotation_speed self.name = name self.grav_parameter = self.mass * gravity() self.obliquity = obliquity for col in ['color', 'trail_color', 'light_color']: if col == 'light_color': self.light_color = getattr(color, self.light_color) elif col in keys: if isinstance(kwargs[col], str): kwargs[col] = getattr(color, kwargs[col]) else: kwargs[col] = self.__try_vector(kwargs[col]) if 'texture' in keys and isinstance(kwargs['texture'], str): try: kwargs['texture'] = getattr(textures, kwargs['texture']) except AttributeError: pass if self.synchronous: kwargs['up'] = self._k_hat else: kwargs['up'] = self._up kwargs['shininess'] = self.shininess if simple: simple_sphere.__init__(self, **kwargs) else: sphere.__init__(self, **kwargs) # If the Sphere has a synchronous rotation with its primary, will rotate the Sphere so that the proper side # is facing the primary (before obliquity is added to the Sphere). if self.synchronous: axis = vector_to_np(hat(cross(vector(0, 1, 0), self.up))) angle = math.acos(dot(self.up, vector(0, 1, 0))) face = vector_to_np(getattr(SphereFace, self.preset.name)) rot_z = -1 * self.__try_vector( rodrigues_rotation(axis, angle).dot(face)) dot_product = dot(hat(cross(self._position, rot_z)), self.up) theta = math.acos(dot(hat(self._position), rot_z)) if theta == math.pi: self.rotate(angle=theta, axis=self.pos + self.up) elif math.isclose(dot_product, 1.0): self.rotate(angle=-theta, axis=self.up) elif math.isclose(dot_product, -1.0): self.rotate(angle=theta, axis=self.up) self.up = self._up self._luminous = self.emissive = luminous if self._luminous: self.__make_light() if self._labelled: self.__make_label() self.show_axes = show_axes if self.show_axes: self.__axes() if real_radius: self.real_radius = real_radius else: self.real_radius = self.radius
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
def __create_object(self): """ Create the physical graphical object :returns: The graphical entity :rtype: class:`vpython.baseobj` """ if self.shape == '': # 2D coords of the circle boundary shape_path = shapes.circle(radius=self.__marker_size / 2) elif self.shape == '+': # 2D coords of the cross boundary shape_path = shapes.cross(width=self.__marker_size, thickness=self.__marker_size / 5) elif self.shape == 'o': # 2D coords of the circle boundary shape_path = shapes.circle(radius=self.__marker_size / 2) elif self.shape == '*': # 2D coords of the star boundary shape_path = shapes.star(radius=self.__marker_size / 2, n=6) elif self.shape == '.': # 2D coords of the square boundary shape_path = shapes.rectangle(width=self.__marker_size, height=self.__marker_size) elif self.shape == 'x': # 2D coords of the cross boundary shape_path = shapes.cross(width=self.__marker_size, thickness=self.__marker_size / 5, rotate=radians(45)) elif self.shape == 's': # 2D coords of the square boundary shape_path = shapes.rectangle(width=self.__marker_size, height=self.__marker_size, thickness=self.__marker_size) elif self.shape == 'd': # 2D coords of the diamond boundary shape_path = shapes.rectangle(width=self.__marker_size, height=self.__marker_size, thickness=self.__marker_size, rotate=radians(45)) elif self.shape == '^': # 2D coords of the triangle boundary shape_path = shapes.triangle(length=self.__marker_size) elif self.shape == 'v': # 2D coords of the triangle boundary shape_path = shapes.triangle(length=self.__marker_size, rotate=radians(180)) elif self.shape == '<': # 2D coords of the triangle boundary shape_path = shapes.triangle(length=self.__marker_size, rotate=radians(90)) elif self.shape == '>': # 2D coords of the triangle boundary shape_path = shapes.triangle(length=self.__marker_size, rotate=radians(-90)) elif self.shape == 'p': # 2D coords of the pentagon boundary shape_path = shapes.pentagon(length=self.__marker_size) elif self.shape == 'h': # 2D coords of the hexagon boundary shape_path = shapes.hexagon(length=self.__marker_size) # CURRENTLY UNUSED # elif self.__shape == 'o': # # 2D coords of the octagon boundary # shape_path = shapes.octagon(length=1) # elif self.__shape == 'r': # # 2D coords of the ring boundary (with thickness = 10%) # shape_path = shapes.circle(radius=0.5, thickness=0.1) else: raise ValueError("Invalid shape given") # Create the shape x = self.se2.t[0] y = self.se2.t[1] obj = extrusion(scene=self.scene, path=[vector(x, y, 0.001), vector(x, y, -0.001)], shape=shape_path, color=self.colourVec, shininess=0) self.size = obj.size if self.shape == '': obj.visible = False return obj
def init_visual(self): # read data file with open(self.data_file) as json_file: json_data = json.load(json_file) # Find center of the map if self.long_center is None: westmost = 180 eastmost = -180 for station in json_data['stations']: longitude = station['coord'][1] if longitude < westmost: westmost = longitude if longitude > eastmost: eastmost = longitude self.long_center = (westmost + eastmost) / 2 if self.lat_center is None: northmost = -90 southmost = 90 for station in json_data['stations']: lattitude = station['coord'][0] if lattitude < southmost: southmost = lattitude if lattitude > northmost: northmost = lattitude self.lat_center = (northmost + southmost) / 2 # convert x,y and get speed limits x = [] y = [] dist = [0] for station in json_data['stations']: coord = station['coord'] station_x, station_y = coord2xy(coord[0], coord[1], self.lat_center, self.long_center) x.append(station_x) y.append(station_y) next_dist = station['next_dist'] if next_dist is not None: dist.append(next_dist + dist[-1]) # Make spline self.spline = Spline(dist, x, y) # Make stations self.stations = [] for i, station_data in enumerate(json_data['stations']): if i in [0, len(json_data['stations']) - 1]: continue # No visual for hangars self.stations.append(VPStation(station['name'], self, dist[i])) # Make visual color = getattr(vp.color, json_data['color']) shape = vp.shapes.rectangle(pos=(0, 0), width=1, height=largeur_wagon * 2 + distance_voix) path = [] dp = 10 # (m) pos = np.arange(0, dist[-1], dp) for p in pos: x, y = self.get_pos(p) path.append(vp.vector(x, y, tunnel_depth)) # print(path) print('Initializing line visual') self.visual = vp.extrusion(path=path, shape=shape, color=color) print('Done initializing line visual')
import vpython from vpython import shapes, extrusion, color, vector, box, scene, rate, label, textures rect = shapes.rectangle(width=1, height=1) rect_side = shapes.rectangle(width=1, height=0.01) rect_side_2 = shapes.rectangle(width=0.01, height=1) ex = extrusion(path=[vector(0, 0, 0), vector(0, 0.01, 0)], shape=rect, color=color.red, texture=textures.stucco) ex.pos = vector(0, 0, 0) ex2 = extrusion(path=[vector(0, 0, 0), vector(0, 1, 0)], shape=rect_side, color=color.red, texture=textures.stucco) ex2.pos = vector(-0.5, 0.5, 0) ex3 = extrusion(path=[vector(0, 0, 0), vector(0, 1, 0)], shape=rect_side_2, color=color.red, texture=textures.stucco) ex3.pos = vector(0, 0.5, -0.5) orangebox = box(color=color.orange, height=0.5, pos=vector(0, 0.25, 0)) purplebox = box(color=color.purple, height=0.5, width=0.5, length=1, pos=vector(0, 0.75, 0.25))
lenArrowOrigin*=1.05 lenArrowTarget*=1.05 mTextOriginX = text(text='z', pos=mPosOrigin + vector(-lenArrowOrigin, 0, 0)*0.6, color=color.black, depth=0.05) mTextOriginY = text(text='y', pos=mPosOrigin + vector(0, lenArrowOrigin, 0), color=color.black, depth=0.05) mTextOriginZ = text(text='x', pos=mPosOrigin + vector(0, 0, lenArrowOrigin), color=color.black, depth=0.05) mTextTargetX = text(text="z'", pos=mPosTarget + vector(-lenArrowTarget, 0, 0), color=color.black, depth=0.05) mTextTargetY = text(text="y'", pos=mPosTarget + vector(0, lenArrowTarget, 0), color=color.black, depth=0.05) mTextTargetZ = text(text="x'", pos=mPosTarget + vector(0, 0, lenArrowTarget), color=color.black, depth=0.05) listArrowsText=[mTextOriginX, mTextOriginY, mTextOriginZ, mTextTargetX, mTextTargetY, mTextTargetZ] for item in listArrowsText: item.length = 0.1*item.length item.height = 0.1 * item.height item.rotate( angle=1.5 ) mTextTitle = text(text=LabelShow, pos=vector(-1,-0.6,-0.2), align='center', color=color.black,depth=0.01) mTextTitle.length = 0.15*mTextTitle.length mTextTitle.height = 0.15 * mTextTitle.height mTextTitle.rotate( angle=1.0 ) listArrowsText.append(mTextTitle) curveTheta = curve(mPosTarget, mPosTarget+vector(-1,0.8,0), color = color.black, radius=0.005) mAngleThetaBase = shapes.arc(radius=0.2, angle1=0, angle2=np.arctan(0.8)) mAngleTheta = extrusion(path=[mPosTarget-vector(0,0,0.01), mPosTarget+vector(0,0,0.01)], shape=mAngleThetaBase, color=color.black) listAngle = [curveTheta, mAngleTheta] objs=listBase + listArrows + listArrowsText + listAngle objs=listBase + listArrows + listArrowsText for item in objs: item.rotate(angle=-0.7,axis=vector(1,0,0),origin=vector(0,0,0)) item.rotate(angle=0.5, axis=vector(0, 0, 1), origin=vector(0, 0, 0))
def launch(sample_rate, position, orientation, COM, COP, thrust, gravity, lift, drag): for step in range(len(position)): position[step][2] = -position[step][2] force_scale = 0.01 l = 2 rad = 0.09 steps = len(position) # Initialization of enviorment render = vp.canvas(height=600, width=1200, background=vp.vector(0.8, 0.8, 0.8), forward=vp.vector(1, 0, 0), up=vp.vector(0, 0, 1)) render.select() render.caption = "Loading..." render.visible = False # Initialization of body and cone body = vp.cylinder(pos=vp.vector(-l, 0, 0), axis=vp.vector(l*0.8, 0, 0), radius=rad) cone = vp.cone(pos=vp.vector(-l*0.2, 0, 0), axis=vp.vector(l*0.2, 0, 0), radius=rad) # Initialization of fins a_fins = vp.box(pos=vp.vector(-l + (l*0.05), 0, 0), size=vp.vector(l*0.1, rad*4, rad*0.25)) b_fins = vp.box(pos=vp.vector(-l + (l*0.05), 0, 0), size=vp.vector(l*0.1, rad*0.25, rad*4)) inv_box = vp.box(pos=vp.vector(l/2, 0, 0), size=vp.vector(l, 10e-10, 10e-10), visible=False) # Initialization of rocket rocket = vp.compound([body, cone, a_fins, b_fins, inv_box], pos=vp.vector(0, 0, 1), axis=vp.vector(1, 0, 0), up=vp.vector(0, 0, 1), color=vp.vector(1,1,1), opacity=0.5) COM_sphere = vp.sphere(radius = 0.04, color=vp.vector(0, 0, 0)) COP_sphere = vp.sphere(radius = 0.04, color=vp.vector(0, 0, 0)) thrust_pointer = vp.arrow(shaftwidth = 0.1, color=vp.vector(1, 1, 0)) gravity_pointer = vp.arrow(shaftwidth = 0.1, color=vp.vector(0, 1, 1)) lift_pointer = vp.arrow(shaftwidth = 0.1, color=vp.vector(1, 0, 1)) drag_pointer = vp.arrow(shaftwidth = 0.1, color=vp.vector(0, 0, 1)) a = 4 c = 0.3 b = a - c sqr_out = [[-a, a],[a, a],[a, -a],[-a, -a], [-a, a]] sqr_in1 = [[-b, b - 3*c],[b, b - 3*c],[b, -b],[-b, -b], [-b, b - 3*c]] sqr_in2 = [[-b, b],[b, b], [b, b - 2*c],[-b, b - 2*c], [-b, b]] ref_box = vp.extrusion(path=[vp.vector(-c/2, 0, 0), vp.vector(c/2, 0, 0)], shape=[sqr_out, sqr_in1, sqr_in2], color=vp.vector(0.5, 0.5, 0.5)) render.camera.follow(rocket) render.autoscale = False launch_pad = vp.box(pos=vp.vector(position[0][0], position[0][1], -1), size=vp.vector(16, 16, 2), color=vp.vector(0.2, 0.2, 0.2)) launch_pad = vp.box(pos=vp.vector(position[-1][0], position[-1][1], -1), size=vp.vector(16, 16, 2), color=vp.vector(0.2, 0.2, 0.2)) rocket.normal = vp.cross(rocket.up, rocket.axis) #vp.attach_arrow(rocket, 'up', color=vp.color.green) #vp.attach_arrow(rocket, 'axis', color=vp.color.blue) #vp.attach_arrow(rocket, 'normal', color=vp.color.red) roll = 0 vp.attach_trail(rocket, radius=rad/3, color=vp.color.red) sqr_out = [[-a, a],[a, a],[a, -a],[-a, -a], [-a, a]] sqr_in1 = [[-b, b - 3*c],[b, b - 3*c],[b, -b],[-b, -b], [-b, b - 3*c]] sqr_in2 = [[-b, b],[b, b], [b, b - 2*c],[-b, b - 2*c], [-b, b]] for step in range(2, steps): if not step % 5: a = 4 c = 0.3 b = a - c ref = vp.extrusion(path=[vp.vector(0, 0, 0), vp.vector(c, 0, 0)], shape=[sqr_out, sqr_in1, sqr_in2], axis=vp.vector(1, 0, 0), up=vp.vector(0, 1, 0), pos=vp.vector(position[step][0], position[step][1], position[step][2])) ref.up = vp.vector(0, 0, 1) ref.rotate(angle=orientation[step][0], axis=vp.cross(ref.axis, ref.up)) ref.rotate(angle=orientation[step][1], axis=ref.up) ref.rotate(angle=orientation[step][2], axis=ref.axis) render.caption = "Running" render.visible = True for step in range(steps): x = position[step][0] y = position[step][1] z = position[step][2] rocket.normal = vp.cross(rocket.axis, rocket.up) pitch, yaw, roll = orientation[step][0], orientation[step][1], orientation[step][2] COM_x = x + COM[step] * np.cos(yaw) * np.cos(pitch) COM_y = y + COM[step] * np.sin(yaw) * np.cos(pitch) COM_z = z + COM[step] * np.sin(pitch) COP_x = x + COP[step] * np.cos(yaw) * np.cos(pitch) COP_y = y + COP[step] * np.sin(yaw) * np.cos(pitch) COP_z = z + COP[step] * np.sin(pitch) thrust_x = x + (-l) * np.cos(yaw) * np.cos(pitch) thrust_y = y + (-l) * np.sin(yaw) * np.cos(pitch) thrust_z = z + (-l) * np.sin(pitch) thrust_mag = np.linalg.norm(thrust[step]) * force_scale thrust_ax_x = thrust_mag * np.cos(yaw) * np.cos(pitch) thrust_ax_y = thrust_mag * np.sin(yaw) * np.cos(pitch) thrust_ax_z = thrust_mag * np.sin(pitch) lift_mag = lift[step][0] * force_scale lift_ax_x = 0 lift_ax_y = 0 lift_ax_z = lift_mag drag_mag = np.linalg.norm(drag[step]) * force_scale print(lift_mag) drag_ax_x = drag_mag drag_ax_y = 0 drag_ax_z = 0 gravity_mag = np.linalg.norm(gravity[step]) * force_scale thrust_pointer.pos = vp.vector(thrust_x, thrust_y, thrust_z) thrust_pointer.axis = vp.vector(thrust_ax_x, thrust_ax_y, thrust_ax_z) gravity_pointer.pos = vp.vector(COM_x, COM_y, COM_z) gravity_pointer.axis = vp.vector(0, 0, -gravity_mag) lift_pointer.pos = vp.vector(COP_x, COP_y, COP_z) lift_pointer.axis = vp.vector(lift_ax_x, lift_ax_y, lift_ax_z) drag_pointer.pos = vp.vector(COP_x, COP_y, COP_z) drag_pointer.axis = vp.vector(drag_ax_x,drag_ax_y, drag_ax_z) rocket.rotate(angle=pitch, axis=rocket.normal) rocket.rotate(angle=yaw, axis=rocket.up) rocket.rotate(angle=roll, axis=rocket.axis) COM_sphere.pos = vp.vector(COM_x, COM_y, COM_z) COP_sphere.pos = vp.vector(COP_x, COP_y, COP_z) rocket.pos = vp.vector(x, y, z) vp.sleep(1/sample_rate) if step + 1 != steps: rocket.rotate(angle=-roll, axis=rocket.axis) rocket.rotate(angle=-yaw, axis=rocket.up) rocket.rotate(angle=-pitch, axis=rocket.normal) render.caption = "Done"
def draw_particle(particle, paint, **kwargs): """Draw a (non-spherical) particle with a given paint""" import vpython vec = vpython.vec if type(particle) is miepy.sphere: return vpython.sphere(pos=vec(*particle.position)/nm, radius=particle.radius/nm, texture=paint.texture, color=paint.color, **kwargs) else: q = particle.orientation theta, phi = miepy.quaternion.as_spherical_coords(q) axis = vec(np.sin(theta)*np.cos(phi), np.sin(theta)*np.sin(phi), np.cos(theta)) rot_vec = miepy.quaternion.as_rotation_vector(q) angle = np.linalg.norm(rot_vec) if angle != 0: axis_rot = rot_vec/angle else: axis_rot = [0,0,1] if type(particle) is miepy.cylinder: return vpython.cylinder(pos=(vec(*particle.position) - particle.height/2*axis)/nm, radius=particle.radius/nm, length=particle.height/nm, texture=paint.texture, axis=axis, color=paint.color, shininess=paint.shininess, **kwargs) elif type(particle) is miepy.spheroid: return vpython.ellipsoid(pos=vec(*particle.position)/nm, width=2*particle.axis_xy/nm, height=2*particle.axis_xy/nm, length=2*particle.axis_z/nm, texture=paint.texture, axis=axis, color=paint.color, shininess=paint.shininess, **kwargs) elif type(particle) is miepy.ellipsoid: obj = vpython.ellipsoid(pos=vec(*particle.position)/nm, width=2*particle.rx/nm, height=2*particle.ry/nm, length=2*particle.rz/nm, texture=paint.texture, color=paint.color, axis=vec(0,0,1), shininess=paint.shininess, **kwargs) obj.rotate(angle=angle, axis=vec(*axis_rot)) return obj elif type(particle) is miepy.regular_prism: rotate = -(2*np.pi - (particle.N-2)*np.pi/(particle.N))/2 shape = vpython.shapes.ngon(np=particle.N, length=particle.width/nm, rotate=rotate) path = [vec(0,0,0), vec(0,0,particle.height/nm)] obj = vpython.extrusion(pos=vec(*particle.position)/nm, path=path, shape=shape, texture=paint.texture, color=paint.color, shininess=paint.shininess, **kwargs) obj.rotate(angle=angle, axis=vec(*axis_rot)) return obj