def create_path(self): path = VGroup() self.get_path_xyz() if len(self.path_xyz) > 1: for i in range(len(self.path_xyz) - 1): if type(self.trail_color) == str: path.add( Line(self.path_xyz[i], self.path_xyz[i + 1], stroke_color=self.trail_color, stroke_opacity=self.rate_func(i / len(self.path_xyz)), plot_depth=self.rate_func(2 - i / len(self.path_xyz)), stroke_width=self.max_width * self.rate_func(i / len(self.path_xyz)))) else: path.add( Line(self.path_xyz[i], self.path_xyz[i + 1], stroke_color=self.colors[i], stroke_opacity=self.rate_func(i / len(self.path_xyz)), plot_depth=self.rate_func(2 - i / len(self.path_xyz)), stroke_width=self.max_width * self.rate_func(i / len(self.path_xyz)))) # print('i = %d' % i) # # print(self.path_xyz) # print(self.color) # print(self.rate_func(i/len(self.path_xyz))) # print(self.max_width*self.rate_func(i/len(self.path_xyz))) return path
def add_size(self, text, scale=1, buff=0.1, **moreargs): linea_referencia = Line(self[0][0].get_start(), self[0][-1].get_end()) texto = TextMobject(text, **moreargs) ancho = texto.get_height() / 2 texto.rotate(linea_referencia.get_angle()) texto.shift(self.direccion * (buff + 1) * ancho) return self.add(texto)
def __init__(self, text, texmob=None, **kwargs): digest_config(self, kwargs) VGroup.__init__(self, **kwargs) pre_coord_dl = text.get_corner(DL) pre_coord_ur = text.get_corner(UR) reference_line = Line(pre_coord_dl, pre_coord_ur) reference_unit_vector = reference_line.get_unit_vector() coord_dl = text.get_corner( DL) - text.get_center() - reference_unit_vector * self.buff_line coord_ur = text.get_corner( UR) - text.get_center() + reference_unit_vector * self.buff_line if texmob == None: line = Line(coord_dl, coord_ur, **self.line_kwargs) self.add(line) else: arrow = Arrow(coord_dl, coord_ur, **self.line_kwargs) unit_vector = arrow.get_unit_vector() if self.buff_text == None: self.buff_text = get_norm( (texmob.get_center() - texmob.get_critical_point(unit_vector)) / 2) * 2 texmob.move_to(arrow.get_end() + unit_vector * self.buff_text) self.add(arrow, texmob)
class Arrow3d(VGroup): CONFIG = { "cone_config": { "height": .5, "base_radius": .25, }, "color": WHITE, } def __init__(self, start=LEFT, end=RIGHT, **kwargs): VGroup.__init__(self, **kwargs) # TODO: inherit color self.line = Line(start, end) self.line.set_color(self.color) self.cone = Cone(direction=self.direction, **self.cone_config) self.cone.shift(self.end) self.cone.set_color(self.color) self.add(self.line, self.cone) @property def start(self): return self.line.start @property def end(self): return self.line.end @property def direction(self): return self.end - self.start
def __init__(self, **kwargs): SVGMobject.__init__(self, **kwargs) self.set_height(self.height) self.set_stroke(color=WHITE, width=0) self.set_fill(self.color, opacity=1) from manimlib.for_3b1b_videos.pi_creature import Randolph randy = Randolph(mode="happy") randy.set_height(0.6 * self.get_height()) randy.stretch(0.8, 0) randy.look(RIGHT) randy.move_to(self) randy.shift(0.07 * self.height * (RIGHT + UP)) self.randy = self.pi_creature = randy self.add_to_back(randy) orientation_line = Line(self.get_left(), self.get_right()) orientation_line.set_stroke(width=0) self.add(orientation_line) self.orientation_line = orientation_line for light, color in zip(self.get_lights(), self.light_colors): light.set_fill(color, 1) light.is_subpath = False self.add_treds_to_tires()
def get_tex(self, tex, scale=1, buff=1, invert_dir=False, invert_texto=False, remove_rot=True, **moreargs): linea_referencia = Line(self[0][0].get_start(), self[0][-1].get_end()) texto = TexMobject(tex, **moreargs) ancho = texto.get_height() / 2 if invert_texto: inv = PI else: inv = 0 if remove_rot: texto.scale(scale).move_to(self) else: texto.rotate( linea_referencia.get_angle()).scale(scale).move_to(self) texto.rotate(inv) if invert_dir: inv = -1 else: inv = 1 texto.shift(self.direccion * (buff + 1) * ancho) return texto
def get_axes(self): """ Returns a set of 3D Axes. Returns ------- ThreeDAxes object """ axes = ThreeDAxes(**self.three_d_axes_config) for axis in axes: if self.cut_axes_at_radius: p0 = axis.get_start() p1 = axis.number_to_point(-1) p2 = axis.number_to_point(1) p3 = axis.get_end() new_pieces = VGroup( Line(p0, p1), Line(p1, p2), Line(p2, p3), ) for piece in new_pieces: piece.shade_in_3d = True new_pieces.match_style(axis.pieces) axis.pieces.submobjects = new_pieces.submobjects for tick in axis.tick_marks: tick.add(VectorizedPoint(1.5 * tick.get_center(), )) return axes
def __init__(self, corner=ORIGIN, angle=0, **kwargs): VGroup.__init__(self, **kwargs) self.corner = ORIGIN self.angle = 0 r = UR if self.on_the_right else UL self.add( Polygon(ORIGIN, RIGHT * self.size * r, UR * self.size * r, UP * self.size * r, stroke_width=0, fill_color=self.fill_color, fill_opacity=self.fill_opacity), Line(RIGHT * self.size * r, UR * self.size * r + UP * self.stroke_width / 100 / 2 * 0.8, stroke_width=self.stroke_width, stroke_color=self.stroke_color), Line(UR * self.size * r + RIGHT * self.stroke_width / 100 / 2 * r * 0.8, UP * self.size * r, stroke_width=self.stroke_width, stroke_color=self.stroke_color), ) self.move_corner_to(corner) self.change_angle_to(angle)
def __init__(self, mobject, **kwargs): VGroup.__init__(self, Line(UP + LEFT, DOWN + RIGHT), Line(UP + RIGHT, DOWN + LEFT), ) self.replace(mobject, stretch=True) self.set_stroke(self.stroke_color, self.stroke_width)
def __init__(self, mobject, **kwargs): super().__init__( Line(UL, DR), Line(UR, DL), ) self.insert_n_curves(2) self.replace(mobject, stretch=True) self.set_stroke(self.stroke_color, width=self.stroke_width)
def get_cross(self): cross = VGroup(Line(UP + LEFT, DOWN + RIGHT, **self.cross_kwargs), Line(UP + RIGHT, DOWN + LEFT, **self.cross_kwargs)) cross.stretch_to_fit_width(self.box.get_width()) cross.stretch_to_fit_height(self.box.get_height()) cross.scale(0.5) cross.move_to(self.box) return cross
class LinearNumberSlider(ControlMobject): CONFIG = { # Since, only slider circle listnes to drag event "listen_to_events": False, "value_type": np.float64, "min_value": -10.0, "max_value": 10.0, "step": 1.0, "rounded_rect_kwargs": { "height": 0.075, "width": 2, "corner_radius": 0.0375 }, "circle_kwargs": { "radius": 0.1, "stroke_color": GREY_A, "fill_color": GREY_A, "fill_opacity": 1.0 } } def __init__(self, value=0, **kwargs): digest_config(self, kwargs) self.bar = RoundedRectangle(**self.rounded_rect_kwargs) self.slider = Circle(**self.circle_kwargs) self.slider_axis = Line(start=self.bar.get_bounding_box_point(LEFT), end=self.bar.get_bounding_box_point(RIGHT)) self.slider_axis.set_opacity(0.0) self.slider.move_to(self.slider_axis) self.slider.listen_to_events = True self.slider.on_mouse_drag = self.slider_on_mouse_drag super().__init__(value, self.bar, self.slider, self.slider_axis, **kwargs) def assert_value(self, value): assert (self.min_value <= value <= self.max_value) def set_value_anim(self, value): prop = (value - self.min_value) / (self.max_value - self.min_value) self.slider.move_to(self.slider_axis.point_from_proportion(prop)) def slider_on_mouse_drag(self, point, d_point, buttons, modifiers): self.set_value(self.get_value_from_point(point)) return False # Helper Methods def get_value_from_point(self, point): start, end = self.slider_axis.get_start_and_end() point_on_line = get_closest_point_on_line(start, end, point) prop = get_norm(point_on_line - start) / get_norm(end - start) value = self.min_value + prop * (self.max_value - self.min_value) no_of_steps = int((value - self.min_value) / self.step) value_nearest_to_step = self.min_value + no_of_steps * self.step return value_nearest_to_step
class LinearNumberSlider(ControlMobject): CONFIG = { "value_type": np.float64, "min_value": -10.0, "max_value": 10.0, "step": 1.0, "rounded_rect_kwargs": { "height": 0.075, "width": 2, "corner_radius": 0.0375 }, "circle_kwargs": { "radius": 0.1, "stroke_color": GREY_A, "fill_color": GREY_A, "fill_opacity": 1.0 } } def __init__(self, value: float = 0, **kwargs): digest_config(self, kwargs) self.bar = RoundedRectangle(**self.rounded_rect_kwargs) self.slider = Circle(**self.circle_kwargs) self.slider_axis = Line( start=self.bar.get_bounding_box_point(LEFT), end=self.bar.get_bounding_box_point(RIGHT) ) self.slider_axis.set_opacity(0.0) self.slider.move_to(self.slider_axis) self.slider.add_mouse_drag_listner(self.slider_on_mouse_drag) super().__init__(value, self.bar, self.slider, self.slider_axis, **kwargs) def assert_value(self, value: float) -> None: assert(self.min_value <= value <= self.max_value) def set_value_anim(self, value: float) -> None: prop = (value - self.min_value) / (self.max_value - self.min_value) self.slider.move_to(self.slider_axis.point_from_proportion(prop)) def slider_on_mouse_drag(self, mob, event_data: dict[str, np.ndarray]) -> bool: self.set_value(self.get_value_from_point(event_data["point"])) return False # Helper Methods def get_value_from_point(self, point: np.ndarray) -> float: start, end = self.slider_axis.get_start_and_end() point_on_line = get_closest_point_on_line(start, end, point) prop = get_norm(point_on_line - start) / get_norm(end - start) value = self.min_value + prop * (self.max_value - self.min_value) no_of_steps = int((value - self.min_value) / self.step) value_nearest_to_step = self.min_value + no_of_steps * self.step return value_nearest_to_step
def __init__(self, A, O, B, **kwargs): VMobject.__init__(self, **kwargs) OA, OB = A-O, B-O theta = np.angle(complex(*OA[:2])/complex(*OB[:2])) # angle of OB to OA self.add(Arc(start_angle=Line(O, B).get_angle(), angle=theta, radius=self.radius/2, stroke_width=100 * self.radius, color=self.color).set_stroke(opacity=self.opacity).move_arc_center_to(O)) self.add(Arc(start_angle=Line(O, B).get_angle(), angle=theta, radius=self.radius, stroke_width=self.stroke_width, color=self.color).move_arc_center_to(O))
def get_checkmark(self): checkmark = VGroup( Line(UP / 2 + 2 * LEFT, DOWN + LEFT, **self.checkmark_kwargs), Line(DOWN + LEFT, UP + RIGHT, **self.checkmark_kwargs)) checkmark.stretch_to_fit_width(self.box.get_width()) checkmark.stretch_to_fit_height(self.box.get_height()) checkmark.scale(0.5) checkmark.move_to(self.box) return checkmark
def coords_to_vector(self, vector, coords_start=2 * RIGHT + 2 * UP, clean_up=True): starting_mobjects = list(self.submobjects) array = Matrix(vector) array.shift(coords_start) arrow = Vector(vector) x_line = Line(ORIGIN, vector[0] * RIGHT) y_line = Line(x_line.get_end(), arrow.get_end()) x_line.set_color(X_COLOR) y_line.set_color(Y_COLOR) x_coord, y_coord = array.get_mob_matrix().flatten() self.play(Write(array, run_time=1)) self.wait() self.play( ApplyFunction( lambda x: self.position_x_coordinate(x, x_line, vector), x_coord)) self.play(ShowCreation(x_line)) self.play( ApplyFunction( lambda y: self.position_y_coordinate(y, y_line, vector), y_coord), FadeOut(array.get_brackets())) y_coord, brackets = self.get_mobjects_from_last_animation() self.play(ShowCreation(y_line)) self.play(ShowCreation(arrow)) self.wait() if clean_up: self.clear() self.add(*starting_mobjects)
def __init__(self, value=0, **kwargs): digest_config(self, kwargs) self.bar = RoundedRectangle(**self.rounded_rect_kwargs) self.slider = Circle(**self.circle_kwargs) self.slider_axis = Line(start=self.bar.get_bounding_box_point(LEFT), end=self.bar.get_bounding_box_point(RIGHT)) self.slider_axis.set_opacity(0.0) self.slider.move_to(self.slider_axis) super().__init__(value, self.bar, self.slider, self.slider_axis, **kwargs)
def vector_to_coords(self, vector, integer_labels=True, clean_up=True): """ This method displays vector as a Vector() based vector, and then shows the corresponding lines that make up the x and y components of the vector. Then, a column matrix (henceforth called the label) is created near the head of the Vector. Parameters ---------- vector Union(np.ndarray, list, tuple) The vector to show. integer_label (bool=True) Whether or not to round the value displayed. in the vector's label to the nearest integer clean_up (bool=True) Whether or not to remove whatever this method did after it's done. """ starting_mobjects = list(self.mobjects) show_creation = False if isinstance(vector, Arrow): arrow = vector vector = arrow.get_end()[:2] else: arrow = Vector(vector) show_creation = True array = vector_coordinate_label(arrow, integer_labels=integer_labels) x_line = Line(ORIGIN, vector[0] * RIGHT) y_line = Line(x_line.get_end(), arrow.get_end()) x_line.set_color(X_COLOR) y_line.set_color(Y_COLOR) x_coord, y_coord = array.get_mob_matrix().flatten() x_coord_start = self.position_x_coordinate(x_coord.copy(), x_line, vector) y_coord_start = self.position_y_coordinate(y_coord.copy(), y_line, vector) brackets = array.get_brackets() if show_creation: self.play(ShowCreation(arrow)) self.play(ShowCreation(x_line), Write(x_coord_start), run_time=1) self.play(ShowCreation(y_line), Write(y_coord_start), run_time=1) self.wait() self.play( Transform(x_coord_start, x_coord, lag_ratio=0), Transform(y_coord_start, y_coord, lag_ratio=0), Write(brackets, run_time=1), ) self.wait() self.remove(x_coord_start, y_coord_start, brackets) self.add(array) if clean_up: self.clear() self.add(*starting_mobjects) return array, x_line, y_line
def get_crosshair(self): line = Line(LEFT, RIGHT) line.insert_n_curves(1) lines = line.replicate(2) lines[1].rotate(PI / 2) crosshair = VMobject() crosshair.set_points([*lines[0].get_points(), *lines[1].get_points()]) crosshair.set_width(self.crosshair_width) crosshair.set_stroke(self.crosshair_color, width=[2, 0, 2, 2, 0, 2]) crosshair.set_animating_status(True) crosshair.fix_in_frame() return crosshair
def __init__(self, start=LEFT, end=RIGHT, **kwargs): VGroup.__init__(self, **kwargs) # TODO: inherit color self.line = Line(start, end) self.line.set_color(self.color) self.cone = Cone(direction=self.direction, **self.cone_config) self.cone.shift(self.end) self.cone.set_color(self.color) self.add(self.line, self.cone)
def construct(self): axes = Axes(x_axis_config={ "include_ticks": False }, y_axis_config={ "include_ticks": False }, number_line_config={ "color": self.axes_color }).scale(0.9) self.add(axes) ellipse = Ellipse(width=self.width, height=self.height) ellipse_x_axis = DashedLine(self.width / 2 * LEFT, self.width / 2 * RIGHT, color=BLACK) ellipse_y_axis = DashedLine(self.height / 2 * UP, self.height / 2 * DOWN, color=BLACK) elipticity_line = Line(self.width / 2 * LEFT, self.height / 2 * UP, color=BLUE) elipticity_arc = Arc(0, math.atan(self.height / self.width)).shift( self.width / 2 * LEFT) ellipse_group = VGroup(ellipse, ellipse_x_axis, ellipse_y_axis, elipticity_arc, elipticity_line) ellipse_group.rotate(self.azimuth) self.add(ellipse_group) rightest = self.get_ellipse_rightest_point(self.width / 2, self.height / 2, self.azimuth) highest = self.get_ellipse_highest_point(self.width / 2, self.height / 2, self.azimuth) vertical_line = Line(rightest * RIGHT, rightest * RIGHT + highest * UP, color=GREEN) horizontal_line = Line(highest * UP, highest * UP + rightest * RIGHT, color=GREEN) self.bring_to_back(vertical_line, horizontal_line) azimuth_arc = Arc(0, self.azimuth) self.add(azimuth_arc) self.wait()
def add_lines(self, left, right): line_kwargs = { "color": BLUE, "stroke_width": 2, } left_rows = [VGroup(*row) for row in left.get_mob_matrix()] h_lines = VGroup() for row in left_rows[:-1]: h_line = Line(row.get_left(), row.get_right(), **line_kwargs) h_line.next_to(row, DOWN, buff=left.v_buff / 2.) h_lines.add(h_line) right_cols = [ VGroup(*col) for col in np.transpose(right.get_mob_matrix()) ] v_lines = VGroup() for col in right_cols[:-1]: v_line = Line(col.get_top(), col.get_bottom(), **line_kwargs) v_line.next_to(col, RIGHT, buff=right.h_buff / 2.) v_lines.add(v_line) self.play(ShowCreation(h_lines)) self.play(ShowCreation(v_lines)) self.wait() self.show_frame()
def __init__(self, **kwargs): digest_config(self, kwargs) start = self.unit_size * self.x_min * RIGHT end = self.unit_size * self.x_max * RIGHT Line.__init__(self, start, end, **kwargs) self.shift(-self.number_to_point(self.number_at_center)) self.init_leftmost_tick() if self.include_tip: self.add_tip() if self.include_ticks: self.add_tick_marks() if self.include_numbers: self.add_numbers()
def __init__(self, mobject, **kwargs): if not hasattr(self, "args"): self.args = serialize_args([mobject]) if not hasattr(self, "config"): self.config = serialize_config({ **kwargs, }) VGroup.__init__( self, Line(UP + LEFT, DOWN + RIGHT), Line(UP + RIGHT, DOWN + LEFT), ) self.replace(mobject, stretch=True) self.set_stroke(self.stroke_color, self.stroke_width)
def add_axes(self): x_axis = Line(self.tick_width * LEFT / 2, self.width * RIGHT) y_axis = Line(MED_LARGE_BUFF * DOWN, self.height * UP) ticks = VGroup() heights = np.linspace(0, self.height, self.n_ticks + 1) values = np.linspace(0, self.max_value, self.n_ticks + 1) for y, value in zip(heights, values): tick = Line(LEFT, RIGHT) tick.set_width(self.tick_width) tick.move_to(y * UP) ticks.add(tick) y_axis.add(ticks) self.add(x_axis, y_axis) self.x_axis, self.y_axis = x_axis, y_axis if self.label_y_axis: labels = VGroup() for tick, value in zip(ticks, values): label = TexMobject(str(np.round(value, 2))) label.set_height(self.y_axis_label_height) label.next_to(tick, LEFT, SMALL_BUFF) labels.add(label) self.y_axis_labels = labels self.add(labels)
def coords_to_vector(self, vector, coords_start=2 * RIGHT + 2 * UP, clean_up=True): """ This method writes the vector as a column matrix (henceforth called the label), takes the values in it one by one, and form the corresponding lines that make up the x and y components of the vector. Then, an Vector() based vector is created between the lines on the Screen. Parameters ---------- vector Union(np.ndarray, list, tuple) The vector to show. coords_start Union(np.ndarray,list,tuple) The starting point of the location of the label of the vector that shows it numerically. Defaults to 2 * RIGHT + 2 * UP or (2,2) clean_up (bool=True) Whether or not to remove whatever this method did after it's done. """ starting_mobjects = list(self.mobjects) array = Matrix(vector) array.shift(coords_start) arrow = Vector(vector) x_line = Line(ORIGIN, vector[0] * RIGHT) y_line = Line(x_line.get_end(), arrow.get_end()) x_line.set_color(X_COLOR) y_line.set_color(Y_COLOR) x_coord, y_coord = array.get_mob_matrix().flatten() self.play(Write(array, run_time=1)) self.wait() self.play( ApplyFunction( lambda x: self.position_x_coordinate(x, x_line, vector), x_coord)) self.play(ShowCreation(x_line)) self.play( ApplyFunction( lambda y: self.position_y_coordinate(y, y_line, vector), y_coord), FadeOut(array.get_brackets())) y_coord, brackets = self.get_mobjects_from_last_animation() self.play(ShowCreation(y_line)) self.play(ShowCreation(arrow)) self.wait() if clean_up: self.clear() self.add(*starting_mobjects)
def add_treds_to_tires(self): for tire in self.get_tires(): radius = tire.get_width() / 2 center = tire.get_center() tred = Line(0.9 * radius * RIGHT, 1.4 * radius * RIGHT, stroke_width=2, color=BLACK) tred.rotate_in_place(np.pi / 4) for theta in np.arange(0, 2 * np.pi, np.pi / 4): new_tred = tred.copy() new_tred.rotate(theta, about_point=ORIGIN) new_tred.shift(center) tire.add(new_tred) return self
def get_tick(self, x, size=None): if size is None: size = self.tick_size result = Line(size * DOWN, size * UP) result.rotate(self.get_angle()) result.move_to(self.number_to_point(x)) result.match_style(self) return result
def __init__(self, **kwargs): circle = Circle(color=WHITE) ticks = [] for x in range(12): alpha = x / 12. point = complex_to_R3(np.exp(2 * np.pi * alpha * complex(0, 1))) length = 0.2 if x % 3 == 0 else 0.1 ticks.append(Line(point, (1 - length) * point)) self.hour_hand = Line(ORIGIN, 0.3 * UP) self.minute_hand = Line(ORIGIN, 0.6 * UP) # for hand in self.hour_hand, self.minute_hand: # #Balance out where the center is # hand.add(VectorizedPoint(-hand.get_end())) VGroup.__init__(self, circle, self.hour_hand, self.minute_hand, *ticks)
def init_points(self): start_angle = np.pi / 2 + self.arc_angle / 2 end_angle = np.pi / 2 - self.arc_angle / 2 self.add(Arc(start_angle=start_angle, angle=-self.arc_angle)) tick_angle_range = np.linspace(start_angle, end_angle, self.num_ticks) for index, angle in enumerate(tick_angle_range): vect = rotate_vector(RIGHT, angle) tick = Line((1 - self.tick_length) * vect, vect) label = TexMobject(str(10 * index)) label.set_height(self.tick_length) label.shift((1 + self.tick_length) * vect) self.add(tick, label) needle = Polygon(LEFT, UP, RIGHT, stroke_width=0, fill_opacity=1, fill_color=self.needle_color) needle.stretch_to_fit_width(self.needle_width) needle.stretch_to_fit_height(self.needle_height) needle.rotate(start_angle - np.pi / 2, about_point=ORIGIN) self.add(needle) self.needle = needle self.center_offset = self.get_center()
def update_trail(self, trail): err = 1e-9 pos_new = self[0].get_center() pos_old = self.pos_old self.pos_old = pos_new # if np.sqrt(sum((pos_new - pos_old) ** 2))>err: if sum(abs(pos_new - pos_old)) > err: trail.add( Line(pos_old, pos_new, color=self.trail_color, plot_depth=0)) if len(trail) > self.nums: trail.remove(trail[0]) # for k in range(self.nums): # trail[k].set_stroke(width=self.max_width * self.rate_func(k/self.nums), # opacity=self.rate_func(k/self.nums)) for l in trail: k = trail.submobjects.index(l) l.set_stroke(width=self.max_width * self.rate_func(k / self.nums), opacity=self.rate_func(k / self.nums)) if len(trail) <= self.nums and len(trail) > 0: # for k in range(len(trail)): # trail[k].set_stroke(width=self.max_width * self.rate_func(k/len(trail)), # opacity=self.rate_func(k/len(trail))) for l in trail: k = trail.submobjects.index(l) l.set_stroke(width=self.max_width * self.rate_func(k / len(trail)), opacity=self.rate_func(k / len(trail)))
def add_treds_to_tires(self): for tire in self.get_tires(): radius = tire.get_width() / 2 center = tire.get_center() tred = Line( 0.7 * radius * RIGHT, 1.1 * radius * RIGHT, stroke_width=2, color=BLACK ) tred.rotate(PI / 5, about_point=tred.get_end()) for theta in np.arange(0, 2 * np.pi, np.pi / 4): new_tred = tred.copy() new_tred.rotate(theta, about_point=ORIGIN) new_tred.shift(center) tire.add(new_tred) return self
def coords_to_vector(self, vector, coords_start=2 * RIGHT + 2 * UP, clean_up=True): starting_mobjects = list(self.mobjects) array = Matrix(vector) array.shift(coords_start) arrow = Vector(vector) x_line = Line(ORIGIN, vector[0] * RIGHT) y_line = Line(x_line.get_end(), arrow.get_end()) x_line.set_color(X_COLOR) y_line.set_color(Y_COLOR) x_coord, y_coord = array.get_mob_matrix().flatten() self.play(Write(array, run_time=1)) self.wait() self.play(ApplyFunction( lambda x: self.position_x_coordinate(x, x_line, vector), x_coord )) self.play(ShowCreation(x_line)) self.play( ApplyFunction( lambda y: self.position_y_coordinate(y, y_line, vector), y_coord ), FadeOut(array.get_brackets()) ) y_coord, brackets = self.get_mobjects_from_last_animation() self.play(ShowCreation(y_line)) self.play(ShowCreation(arrow)) self.wait() if clean_up: self.clear() self.add(*starting_mobjects)
def add_lines(self, left, right): line_kwargs = { "color": BLUE, "stroke_width": 2, } left_rows = [ VGroup(*row) for row in left.get_mob_matrix() ] h_lines = VGroup() for row in left_rows[:-1]: h_line = Line(row.get_left(), row.get_right(), **line_kwargs) h_line.next_to(row, DOWN, buff=left.v_buff / 2.) h_lines.add(h_line) right_cols = [ VGroup(*col) for col in np.transpose(right.get_mob_matrix()) ] v_lines = VGroup() for col in right_cols[:-1]: v_line = Line(col.get_top(), col.get_bottom(), **line_kwargs) v_line.next_to(col, RIGHT, buff=right.h_buff / 2.) v_lines.add(v_line) self.play(ShowCreation(h_lines)) self.play(ShowCreation(v_lines)) self.wait() self.show_frame()
def __init__(self, *text_parts, **kwargs): TextMobject.__init__(self, *text_parts, **kwargs) self.scale(self.scale_factor) self.to_edge(UP) if self.include_underline: underline = Line(LEFT, RIGHT) underline.next_to(self, DOWN, buff=self.underline_buff) if self.match_underline_width_to_text: underline.match_width(self) else: underline.set_width(self.underline_width) self.add(underline) self.underline = underline
def __init__(self, **kwargs): SVGMobject.__init__(self, **kwargs) path = self.submobjects[0] subpaths = path.get_subpaths() path.clear_points() for indices in [(0, 1), (2, 3), (4, 6, 7), (5,), (8,)]: part = VMobject() for index in indices: part.append_points(subpaths[index]) path.add(part) self.set_height(self.height) self.set_stroke(color=WHITE, width=0) self.set_fill(self.color, opacity=1) from manimlib.for_3b1b_videos.pi_creature import Randolph randy = Randolph(mode="happy") randy.set_height(0.6 * self.get_height()) randy.stretch(0.8, 0) randy.look(RIGHT) randy.move_to(self) randy.shift(0.07 * self.height * (RIGHT + UP)) self.randy = self.pi_creature = randy self.add_to_back(randy) orientation_line = Line(self.get_left(), self.get_right()) orientation_line.set_stroke(width=0) self.add(orientation_line) self.orientation_line = orientation_line for light, color in zip(self.get_lights(), self.light_colors): light.set_fill(color, 1) light.is_subpath = False self.add_treds_to_tires()
def vector_to_coords(self, vector, integer_labels=True, clean_up=True): starting_mobjects = list(self.mobjects) show_creation = False if isinstance(vector, Arrow): arrow = vector vector = arrow.get_end()[:2] else: arrow = Vector(vector) show_creation = True array = vector_coordinate_label(arrow, integer_labels=integer_labels) x_line = Line(ORIGIN, vector[0] * RIGHT) y_line = Line(x_line.get_end(), arrow.get_end()) x_line.set_color(X_COLOR) y_line.set_color(Y_COLOR) x_coord, y_coord = array.get_mob_matrix().flatten() x_coord_start = self.position_x_coordinate( x_coord.copy(), x_line, vector ) y_coord_start = self.position_y_coordinate( y_coord.copy(), y_line, vector ) brackets = array.get_brackets() if show_creation: self.play(ShowCreation(arrow)) self.play( ShowCreation(x_line), Write(x_coord_start), run_time=1 ) self.play( ShowCreation(y_line), Write(y_coord_start), run_time=1 ) self.wait() self.play( Transform(x_coord_start, x_coord, lag_ratio=0), Transform(y_coord_start, y_coord, lag_ratio=0), Write(brackets, run_time=1), ) self.wait() self.remove(x_coord_start, y_coord_start, brackets) self.add(array) if clean_up: self.clear() self.add(*starting_mobjects) return array, x_line, y_line
def scroll_through_patrons(self): logo_box = Square(side_length=2.5) logo_box.to_corner(DOWN + LEFT, buff=MED_LARGE_BUFF) total_width = FRAME_X_RADIUS - logo_box.get_right()[0] black_rect = Rectangle( fill_color=BLACK, fill_opacity=1, stroke_width=3, stroke_color=BLACK, width=FRAME_WIDTH, height=0.6 * FRAME_HEIGHT, ) black_rect.to_edge(UP, buff=0) line = DashedLine(FRAME_X_RADIUS * LEFT, FRAME_X_RADIUS * RIGHT) line.move_to(ORIGIN) thanks = TextMobject(self.thanks_words) thanks.scale(0.9) thanks.next_to(black_rect.get_bottom(), UP, SMALL_BUFF) thanks.set_color(YELLOW) underline = Line(LEFT, RIGHT) underline.match_width(thanks) underline.scale(1.1) underline.next_to(thanks, DOWN, SMALL_BUFF) thanks.add(underline) changed_patron_names = map( self.modify_patron_name, self.specific_patrons, ) patrons = VGroup(*map( TextMobject, changed_patron_names, )) patrons.scale(self.patron_scale_val) for patron in patrons: if patron.get_width() > self.max_patron_width: patron.set_width(self.max_patron_width) columns = VGroup(*[ VGroup(*patrons[i::self.n_patron_columns]) for i in range(self.n_patron_columns) ]) for column in columns: for n, name in enumerate(column): name.shift(n * self.name_y_spacing * DOWN) columns.arrange( RIGHT, buff=LARGE_BUFF, aligned_edge=UP, ) if columns.get_width() > self.max_patron_width: columns.set_width(total_width - 1) thanks.to_edge(RIGHT, buff=MED_SMALL_BUFF) columns.next_to(underline, DOWN, buff=2) columns.generate_target() columns.target.to_edge(DOWN, buff=2) vect = columns.target.get_center() - columns.get_center() distance = get_norm(vect) wait_time = 20 always_shift( columns, direction=normalize(vect), rate=(distance / wait_time) ) self.add(columns, black_rect, line, thanks) self.wait(wait_time)