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=Color('WHITE'), width=0) self.set_fill(self.color, opacity=1) 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 __init__(self, mobject, **kwargs): VGroup.__init__(self, Line(consts.UP + consts.LEFT, consts.DOWN + consts.RIGHT), Line(consts.UP + consts.RIGHT, consts.DOWN + consts.LEFT), ) self.replace(mobject, stretch=True) self.set_stroke(self.stroke_color, self.stroke_width)
def coords_to_vector(self, vector, coords_start=2 * consts.RIGHT + 2 * consts.UP, clean_up=True): starting_mobjects = list(self.submobjects) array = Matrix(vector) array.shift(coords_start) arrow = Vector(vector) x_line = Line(consts.ORIGIN, vector[0] * consts.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, **kwargs): digest_config(self, kwargs) start = self.unit_size * self.x_min * consts.RIGHT end = self.unit_size * self.x_max * consts.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 get_tick(self, x, size=None): if size is None: size = self.tick_size result = Line(size * consts.DOWN, size * consts.UP) result.rotate(self.get_angle()) result.move_to(self.number_to_point(x)) result.match_style(self) return result
def generate_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(consts.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( consts.LEFT, consts.UP, consts.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=consts.ORIGIN) self.add(needle) self.needle = needle self.center_offset = self.get_center()
def __init__(self, **kwargs): super().__init__(**kwargs) body = Cube(side_length=1) for dim, scale_factor in enumerate(self.body_dimensions): body.stretch(scale_factor, dim=dim) body.set_width(self.width) body.set_fill(self.shaded_body_color, opacity=1) body.sort(lambda p: p[2]) body[-1].set_fill(self.body_color) screen_plate = body.copy() keyboard = VGroup(*[ VGroup(*[ Square(**self.key_color_kwargs) for x in range(12 - y % 2) ]).arrange(consts.RIGHT, buff=consts.SMALL_BUFF) for y in range(4) ]).arrange(consts.DOWN, buff=consts.MED_SMALL_BUFF) keyboard.stretch_to_fit_width( self.keyboard_width_to_body_width * body.get_width(), ) keyboard.stretch_to_fit_height( self.keyboard_height_to_body_height * body.get_height(), ) keyboard.next_to(body, consts.OUT, buff=0.1 * consts.SMALL_BUFF) keyboard.shift(consts.MED_SMALL_BUFF * consts.UP) body.add(keyboard) screen_plate.stretch(self.screen_thickness / self.body_dimensions[2], dim=2) screen = Rectangle( stroke_width=0, fill_color=Color('BLACK'), fill_opacity=1, ) screen.replace(screen_plate, stretch=True) screen.scale_in_place(self.screen_width_to_screen_plate_width) screen.next_to(screen_plate, consts.OUT, buff=0.1 * consts.SMALL_BUFF) screen_plate.add(screen) screen_plate.next_to(body, consts.UP, buff=0) screen_plate.rotate( self.open_angle, consts.RIGHT, about_point=screen_plate.get_bottom() ) self.screen_plate = screen_plate self.screen = screen axis = Line( body.get_corner(consts.UP + consts.LEFT + consts.OUT), body.get_corner(consts.UP + consts.RIGHT + consts.OUT), color=Color('BLACK'), stroke_width=2 ) self.axis = axis self.add(body, screen_plate, axis) self.rotate(5 * np.pi / 12, consts.LEFT, about_point=consts.ORIGIN) self.rotate(np.pi / 6, consts.DOWN, about_point=consts.ORIGIN)
def vector_to_coords(self, vector, integer_labels=True, clean_up=True): starting_mobjects = list(self.submobjects) 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(consts.ORIGIN, vector[0] * consts.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_lines_parallel_to_axis(self, axis1, axis2, freq, ratio): line = Line(axis1.get_start(), axis1.get_end()) dense_freq = (1 + ratio) step = (1 / dense_freq) * freq lines1 = VGroup() lines2 = VGroup() ranges = ( np.arange(0, axis2.x_max, step), np.arange(0, axis2.x_min, -step), ) for inputs in ranges: for k, x in enumerate(inputs): new_line = line.copy() new_line.move_to(axis2.number_to_point(x)) if k % (1 + ratio) == 0: lines1.add(new_line) else: lines2.add(new_line) return lines1, lines2
def __init__(self, *text_parts, **kwargs): TextMobject.__init__(self, *text_parts, **kwargs) self.scale(self.scale_factor) self.to_edge(consts.UP) if self.include_underline: underline = Line(consts.LEFT, consts.RIGHT) underline.next_to(self, consts.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 get_axes(self): 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, **kwargs): circle = Circle(color=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(consts.ORIGIN, 0.3 * consts.UP) self.minute_hand = Line(consts.ORIGIN, 0.6 * consts.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 create_lines(self): lines = VGroup() for angle in np.arange(0, consts.TAU, consts.TAU / self.num_lines): line = Line(consts.ORIGIN, self.line_length * consts.RIGHT) line.shift((self.flash_radius - self.line_length) * consts.RIGHT) line.rotate(angle, about_point=consts.ORIGIN) lines.add(line) lines.set_color(self.color) lines.set_stroke(width=3) lines.add_updater(lambda l: l.move_to(self.point)) return lines
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 * consts.RIGHT, 1.1 * radius * consts.RIGHT, stroke_width=2, color=Color('BLACK') ) tred.rotate(consts.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=consts.ORIGIN) new_tred.shift(center) tire.add(new_tred) return self
def get_secant_slope_group( self, x, graph, dx=None, dx_line_color=None, df_line_color=None, dx_label=None, df_label=None, include_secant_line=True, secant_line_color=None, secant_line_length=10, ): """ Resulting group is of the form VGroup( dx_line, df_line, dx_label, (if applicable) df_label, (if applicable) secant_line, (if applicable) ) with attributes of those names. """ kwargs = locals() kwargs.pop("self") group = VGroup() group.kwargs = kwargs dx = dx or float(self.x_max - self.x_min) / 10 dx_line_color = dx_line_color or self.default_input_color df_line_color = df_line_color or graph.get_color() p1 = self.input_to_graph_point(x, graph) p2 = self.input_to_graph_point(x + dx, graph) interim_point = p2[0] * consts.RIGHT + p1[1] * consts.UP group.dx_line = Line( p1, interim_point, color=dx_line_color ) group.df_line = Line( interim_point, p2, color=df_line_color ) group.add(group.dx_line, group.df_line) labels = VGroup() if dx_label is not None: group.dx_label = TexMobject(dx_label) labels.add(group.dx_label) group.add(group.dx_label) if df_label is not None: group.df_label = TexMobject(df_label) labels.add(group.df_label) group.add(group.df_label) if len(labels) > 0: max_width = 0.8 * group.dx_line.get_width() max_height = 0.8 * group.df_line.get_height() if labels.get_width() > max_width: labels.set_width(max_width) if labels.get_height() > max_height: labels.set_height(max_height) if dx_label is not None: group.dx_label.next_to( group.dx_line, np.sign(dx) * consts.DOWN, buff=group.dx_label.get_height() / 2 ) group.dx_label.set_color(group.dx_line.get_color()) if df_label is not None: group.df_label.next_to( group.df_line, np.sign(dx) * consts.RIGHT, buff=group.df_label.get_height() / 2 ) group.df_label.set_color(group.df_line.get_color()) if include_secant_line: secant_line_color = secant_line_color or self.default_derivative_color group.secant_line = Line(p1, p2, color=secant_line_color) group.secant_line.scale_in_place( secant_line_length / group.secant_line.get_length() ) group.add(group.secant_line) return group
def add_axes(self): x_axis = Line(self.tick_width * consts.LEFT / 2, self.width * consts.RIGHT) y_axis = Line(consts.MED_LARGE_BUFF * consts.DOWN, self.height * consts.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(consts.LEFT, consts.RIGHT) tick.set_width(self.tick_width) tick.move_to(y * consts.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, consts.LEFT, consts.SMALL_BUFF) labels.add(label) self.y_axis_labels = labels self.add(labels)