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 add_axes(self): x_axis = Line(self.tick_width * LEFT / 2, self.width * RIGHT) y_axis = Line(MED_LARGE_BUFF * DOWN, self.height * UP) y_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): y_tick = Line(LEFT, RIGHT) y_tick.set_width(self.tick_width) y_tick.move_to(y * UP) y_ticks.add(y_tick) y_axis.add(y_ticks) if self.include_x_ticks == True: x_ticks = VGroup() widths = np.linspace(0, self.width, self.n_ticks_x + 1) label_values = np.linspace(0, len(self.bar_names), self.n_ticks_x + 1) for x, value in zip(widths, label_values): x_tick = Line(UP, DOWN) x_tick.set_height(self.tick_height) x_tick.move_to(x * RIGHT) x_ticks.add(x_tick) x_axis.add(x_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 y_tick, value in zip(y_ticks, values): label = Tex(str(np.round(value, 2))) label.set_height(self.y_axis_label_height) label.next_to(y_tick, LEFT, SMALL_BUFF) labels.add(label) self.y_axis_labels = labels self.add(labels)
def __init__(self, *vertices, **kwargs): VGroup.__init__(self, **kwargs) self.lines, self.dots = VGroup(plot_depth=1), VGroup(plot_depth=1) self.poly=Polygon(*vertices, fill_color=self.fill_color, fill_opacity=self.fill_opacity, plot_depth=0).set_stroke(width=0) self.add(self.poly, self.lines, self.dots) n = len(vertices) for i in range(n): self.lines.add(Line(vertices[i], vertices[(i+1) % n], color=self.stroke_color, stroke_width=self.stroke_width)) self.dots.add(Dot(vertices[i], color=self.stroke_color).set_height(self.stroke_width/100)) for dot in self.dots: dot.add_updater(lambda d: d.set_height(self.stroke_width/100))
def return_updater(mob, alpha): dx = interpolate(-PI / 2, PI / 2, alpha) mob.become(mob.init_state) mob.set_width(rectangle_width * np.cos(dx), stretch=True) # dx should not be zero sign = -abs(dx) / (dx + 0.00000000001) direction = LEFT * sign reference_line = Line( rectangle.init_state.get_corner(UP + direction), rectangle.init_state.get_corner(DOWN + direction)) mob.next_to(reference_line, -direction, buff=0) opacity = self.init_opacity + (self.max_opacity - self.init_opacity) * np.cos(dx) mob.set_style(fill_opacity=opacity) mob.set_color( interpolate_color(self.rectangle_kwargs["color"], midle_color, np.cos(dx)))
def generate_points(self): self.main_line = Line(self.x_min * RIGHT, self.x_max * RIGHT) self.tick_marks = VGroup() self.add(self.main_line, self.tick_marks) rounding_value = int(-np.log10(0.1 * self.tick_frequency)) rounded_numbers_with_elongated_ticks = np.round( self.numbers_with_elongated_ticks, rounding_value) for x in self.get_tick_numbers(): rounded_x = np.round(x, rounding_value) if rounded_x in rounded_numbers_with_elongated_ticks: tick_size_used = self.longer_tick_multiple * self.tick_size else: tick_size_used = self.tick_size self.add_tick(x, tick_size_used) self.stretch(self.unit_size, 0) self.shift(-self.number_to_point(self.number_at_center))
def get_lines_parallel_to_axis(self, axis1, axis2): freq = axis1.x_step ratio = self.faded_line_ratio line = Line(axis1.get_start(), axis1.get_end()) dense_freq = (1 + ratio) step = (1 / dense_freq) * freq lines1 = VGroup() lines2 = VGroup() inputs = np.arange(axis2.x_min, axis2.x_max + step, step) for i, x in enumerate(inputs): new_line = line.copy() new_line.shift(axis2.n2p(x) - axis2.n2p(0)) if i % (1 + ratio) == 0: lines1.add(new_line) else: lines2.add(new_line) return lines1, lines2
def __init__(self, path, partitions=120, **kwargs): VMobject.__init__(self, **kwargs) coords = [] for p in range(int(partitions) + 1): coord_i = path.point_from_proportion((p * 0.989 / partitions) % 1) coord_f = path.point_from_proportion( (p * 0.989 / partitions + 0.001) % 1) reference_line = Line(coord_i, coord_f).rotate(self.sign * PI / 2, about_point=coord_i) normal_unit_vector = reference_line.get_unit_vector() static_vector = normal_unit_vector * self.length random_dx = random.randint(0, self.dx_random) random_normal_vector = random_dx * normal_unit_vector / 100 point_coord = coord_i + random_normal_vector + static_vector coords.append(point_coord) if self.close: coords.append(coords[0]) self.set_points_smoothly(coords)
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): 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(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 __init__(self, *verticepairs, **kwargs): VMobject.__init__(self, **kwargs) for each in verticepairs: n = len(each) if isinstance(each, VMobject): self.append_vectorized_mobject(each) elif n == 1: if len(self.points) == 0: self.start_new_path(each) else: self.add_line_to(point, **kwargs) elif n == 2: self.append_vectorized_mobject(Line(*each, **kwargs)) elif n == 3: self.add_cubic_bezier_curve_to(*each, **kwargs) elif n == 4: self.add_cubic_bezier_curve(*each, **kwargs) elif n % 4 == 0: self.append_points(*each, **kwargs)
def __init__(self, **kwargs): if not hasattr(self, "args"): self.args = serialize_args([]) if not hasattr(self, "config"): self.config = serialize_config({ **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 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 get_basic_brace(self, direction): anchors = self.tiling.get_border().get_anchors() lines = [ Line(anchors[k], anchors[k + 1]) for k in range(len(anchors) - 1) ] if direction == "upleft": brace = Brace(lines[0], direction=DOWN) elif direction == "left": brace = self.get_basic_brace("upleft") brace.rotate(2 * np.pi / 3, axis=[1, -1, 1], about_point=anchors[1]) elif direction == "downleft": brace = Brace(lines[2], direction=RIGHT) elif direction == "downright": brace = Brace(lines[3], direction=UP) brace.rotate(-np.pi / 2., axis=RIGHT, about_point=anchors[3]) else: raise Exception("There's no such direction") return brace
def __init__(self, *text_parts, **kwargs): #### EULERTOUR_INIT_START #### if not hasattr(self, "args"): self.args = serialize_args(text_parts) if not hasattr(self, "config"): self.config = serialize_config({ **kwargs, }) #### EULERTOUR_INIT_START #### 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 generate_points(self): outer_rect = Rectangle( width=self.diameter, height=self.thickness, fill_color=self.fill_color, fill_opacity=self.fill_opacity, stroke_color=self.stroke_color, stroke_width=0, #self.stroke_width ) self.add(outer_rect) PI = TAU / 2 ridge_angles = np.arange(PI / self.nb_ridges, PI, PI / self.nb_ridges) ridge_positions = 0.5 * self.diameter * np.array( [np.cos(theta) for theta in ridge_angles]) ridge_color = interpolate_color(BLACK, self.stroke_color, 0.5) for x in ridge_positions: ridge = Line(x * RIGHT + 0.5 * self.thickness * DOWN, x * RIGHT + 0.5 * self.thickness * UP, stroke_color=ridge_color, stroke_width=self.stroke_width) self.add(ridge)
def construct(self): # construction of demo props lines = VGroup() for i in range(-5, 6): lines.add(Line(3 * UP + i * RIGHT, 3 * DOWN + i * RIGHT)) # LaggedStartMap is used when you want to apply one animation to lots of mobjects # with lagged start # run_time is for the whole LaggedStartMap animation, not for individual animations # lag_ratio - how much does it wait before running next animation (as a ratio of the time # of one animation) # rate_func applies for individual animations, launching the animations is always linear, # because lag_ratio is constant self.play( LaggedStartMap(ShowCreation, lines, run_time=10, lag_ratio=0.5, rate_func=linear)) self.wait()
def __init__(self, texmob, **kwargs): VMobject.__init__(self, **kwargs) rect = Rectangle(width=texmob.get_width() + self.margin, height=texmob.get_height() + self.margin) rect.move_to(texmob) w = rect.get_width() h = rect.get_height() alpha = w / h hp = np.ceil(self.partitions / (2 * (alpha + 1))) wp = np.ceil(alpha * hp) sides = VGroup(*[ Line(rect.get_corner(c1), rect.get_corner(c2)) for c1, c2 in zip([UL, UR, DR, DL], [UR, DR, DL, UL]) ]) total_points = [] for side, p in zip(sides, [wp, hp, wp, hp]): path = FreehandDraw(side, p).points for point in path: total_points.append(point) total_points.append(total_points[0]) self.set_points_smoothly(total_points)
def get_lines_parallel_to_axis(self, axis1, axis2, freq, ratio): freq = axis1.x_step ratio = self.faded_line_ratio line = Line(axis1.get_start(), axis1.get_end()) dense_freq = (1 + ratio) step = (1 / dense_freq) * freq lines1 = VGroup() lines2 = VGroup() #''' if axis2.x_min == -FRAME_X_RADIUS and axis2.x_max == FRAME_X_RADIUS: axis2x_min = int(axis2.x_min) axis2x_max = int(axis2.x_max) else: axis2x_min = axis2.x_min axis2x_max = axis2.x_max inputs = np.arange(axis2x_min, axis2x_max + step, step) for i, x in enumerate(inputs): new_line = line.copy() new_line.shift(axis2.n2p(x) - axis2.n2p(0)) if i % (1 + ratio) == 0: lines1.add(new_line) else: lines2.add(new_line) ''' 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 construct(self): circle = Circle(color=YELLOW).scale(self.radius) points = [] lines = [] for point in range(self.points): start_angle = (point / self.points) * 2 * np.pi start_point = (RIGHT * np.cos(start_angle) + UP * np.sin(start_angle)) * self.radius points.append(start_point) stop_angle = (point + point * self.step) / self.points * 2 * np.pi stop_point = (RIGHT * np.cos(stop_angle) + UP * np.sin(stop_angle)) * self.radius lines.append(Line(start_point, stop_point, **self.line_config)) self.play(ShowCreation(circle)) self.wait() points_group = VGroup(*[Dot(point, **self.dot_config) for point in points]) lines_group = VGroup(*lines) # self.play(ShowCreation(points_group), run_time=2) self.play(ShowCreation(lines_group), run_time=10, rate_func=linear) self.wait()
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_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] * RIGHT + p1[1] * 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) * 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) * 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 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, ) max_width = FRAME_WIDTH - 1 if columns.get_width() > max_width: columns.set_width(max_width) underline.match_width(columns) # 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)
def construct(self): # Add title title = self.title = TextMobject("Clicky Stuffs") title.scale(1.5) title.to_edge(UP, buff=MED_SMALL_BUFF) pi_creatures = VGroup(Randolph(), Mortimer()) for pi, vect in zip(pi_creatures, [LEFT, RIGHT]): pi.set_height(title.get_height()) pi.change_mode("thinking") pi.look(DOWN) pi.next_to(title, vect, buff=MED_LARGE_BUFF) self.add(title, pi_creatures) # Set the top of the screen logo_box = Square(side_length=2.5) logo_box.to_corner(DOWN + LEFT, buff=MED_LARGE_BUFF) 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) # Add thanks 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) # Build name list file_name = os.path.join(get_directories()["data"], "patrons.txt") with open(file_name, "r") as fp: names = [ self.modify_patron_name(name.strip()) for name in fp.readlines() ] if self.randomize_order: random.shuffle(names) else: names.sort() name_labels = VGroup(*map(TextMobject, names)) name_labels.scale(self.patron_scale_val) for label in name_labels: if label.get_width() > self.max_patron_width: label.set_width(self.max_patron_width) columns = VGroup(*[ VGroup(*name_labels[i::self.n_patron_columns]) for i in range(self.n_patron_columns) ]) column_x_spacing = 0.5 + max([c.get_width() for c in columns]) for i, column in enumerate(columns): for n, name in enumerate(column): name.shift(n * self.name_y_spacing * DOWN) name.align_to(ORIGIN, LEFT) column.move_to(i * column_x_spacing * RIGHT, UL) columns.center() max_width = FRAME_WIDTH - 1 if columns.get_width() > max_width: columns.set_width(max_width) underline.match_width(columns) columns.next_to(underline, DOWN, buff=3) # Set movement columns.generate_target() distance = columns.get_height() + 2 wait_time = self.scroll_time frame = self.camera.frame frame_shift = ApplyMethod( frame.shift, distance * DOWN, run_time=wait_time, rate_func=linear, ) blink_anims = [] blank_mob = Mobject() for x in range(wait_time): if random.random() < 0.25: blink_anims.append(Blink(random.choice(pi_creatures))) else: blink_anims.append(Animation(blank_mob)) blinks = Succession(*blink_anims) static_group = VGroup(black_rect, line, thanks, pi_creatures, title) static_group.fix_in_frame() self.add(columns, static_group) self.play(frame_shift, blinks)
def get_table(tabledict: dict, buff_length=0.3, line_color=WHITE, text_color=WHITE): def flatten(inlist): outlist = [] for element in inlist: for sub_element in element: outlist.append(sub_element) return outlist table = VGroup( ) #The table is a VGroup with all the fields, records and separators. fields = list(tabledict.keys( )) #Since the data is recieved as a dict, the keys will be the fields cell_length = TexMobject( max(fields + flatten(tabledict.values()), key=len) ).get_width( ) + 2 * buff_length #The length of a record/field of max length is the base cell size cell_height = TexMobject( max(fields + flatten(tabledict.values()), key=len)).get_height() + 2 * buff_length #The first position is set like so. field_position = [ (cell_length - TexMobject(fields[0]).get_width()) / 2 + TexMobject(fields[0]).get_width() / 2, 0, 0 ] #The initial position of the first field. This is #NOTE: Coordinates of TexMobjects in Manim are taken from centre, not top-right. Adjustments have been made. total_table_width = (cell_length - TexMobject(fields[0]).get_width()) / 2 total_table_height = cell_height * ( len(tabledict[max(tabledict.keys(), key=len)]) + 1) for n in range(len(fields)): field = TexMobject(fields[n]) field_length = field.get_width( ) #This is the length that the actual field name will take up on-screen if n + 1 < len( fields ): #This gets the nxt field if it exists and chooses an empty TexMobject if it doesn't next_field = TexMobject(fields[n + 1]) else: next_field = TexMobject("") next_field_length = next_field.get_width( ) #Gets the next fields length field.move_to(field_position) space_to_right_of_field = (cell_length - field_length) / 2 space_to_left_of_next_field = (cell_length - next_field_length) / 2 space_to_leave = space_to_right_of_field + space_to_left_of_next_field + next_field_length / 2 #next_field_length/2 is added to account for the fact that coordinates are taken from centre and not left edges. total_table_width += field_length + space_to_leave / 2 table.add(field) field_position = field.get_right() + (space_to_leave, 0, 0) for keynum in range(len(tabledict.keys())): key = list(tabledict.keys())[keynum] #gets the actual key recordlist = tabledict[key] #selects the list with the records for if recordlist != []: record_position = [ table[keynum].get_center()[0], -((cell_height - TexMobject(fields[keynum]).get_height()) / 2 + TexMobject(fields[keynum]).get_height() / 2 + cell_height), 0 ] #the record position is set to be the [center of the field it belongs to, buffer space above the record + centered height of the record, 0 ] for recordnum in range(len(recordlist)): # for each record for record = TexMobject( recordlist[recordnum]) # the selected field if recordnum + 1 < len( recordlist ): #This gets the nxt record if it exists and chooses an empty TexMobject if it doesn't next_record = TexMobject(recordlist[recordnum + 1]) else: next_record = TexMobject("") record.move_to(record_position) record_position = record.get_center() + (0, -cell_height, 0) table.add(record) else: pass line_hor = Line(start=(0, -2 * cell_height / 3, 0), end=(total_table_width, -2 * cell_height / 3, 0), color=line_color) table.add(line_hor) line_hor = Line(start=(0, cell_height / 2, 0), end=(total_table_width, cell_height / 2, 0), color=line_color) table.add(line_hor) for l in range(len(fields) - 1): line = Line(start=(table[l].get_center() + (cell_length / 2, cell_height / 2, 0)), end=(table[l].get_center() + (cell_length / 2, -total_table_height, 0))) table.add(line) line = Line(start=(table[0].get_center() + (-cell_length / 2, cell_height / 2, 0)), end=(table[0].get_center() + (-cell_length / 2, -total_table_height, 0))) table.add(line) #line=Line( start=(table[l].get_center()+ (total_table_width,cell_height/2,0)), end =(table[l].get_center()+ (total_table_width,-total_table_height,0))) line = Line(start=(total_table_width, cell_height / 2, 0), end=(total_table_width, -total_table_height, 0)) table.add(line) return table
def get_table(elts_list, buff_length=0.3, cell_length=1, cell_height=1, line_color=WHITE, text_color=WHITE, background_color=BLACK): nb_l = len(elts_list) nb_c = len(elts_list[0]) l_fill = 0.015 table = VGroup() grid = VGroup() result = VGroup() rec = Polygon( (-cell_length / 2, cell_height / 2, 0), (-cell_length / 2 + (nb_c * cell_length), cell_height / 2, 0), (-cell_length / 2 + (nb_c * cell_length), cell_height / 2 - (nb_l) * cell_height, 0), (-cell_length / 2, cell_height / 2 - (nb_l) * cell_height, 0), mark_paths_closed=True, close_new_points=True, fill_color=background_color, fill_opacity=1, color=background_color) for i in range(nb_l): for j in range(nb_c): #elt = Text(elts_list[i][j],color = text_color, font = "Open Sans Bold Italic") if elts_list[i][j] != " ": #TextMobject doesnt like " " strings elt = TextMobject(elts_list[i][j], color=text_color) elt.move_to([j * cell_length, -i * cell_height, 0]) table.add(elt) for i in range(nb_l + 1): # start_line_hor = (0, -i * cell_height,0) # + (-cell_length ,cell_height,0) # end_line_hor = ((nb_c * cell_length), -i * cell_height,0) # + (-cell_length ,cell_height,0) start_line_hor = (-cell_length / 2 - l_fill, cell_height / 2 - i * cell_height, 0 ) # + ( ,cell_height,0) end_line_hor = (-cell_length / 2 + (nb_c * cell_length) + l_fill, cell_height / 2 - i * cell_height, 0 ) # + (-cell_length ,cell_height,0) line_hor = Line(start=start_line_hor, end=end_line_hor, color=line_color) grid.add(line_hor) for j in range(nb_c + 1): start_line_ver = (-cell_length / 2 + j * cell_length, cell_height / 2 + l_fill, 0 ) # (-cell_length ,cell_height,0) end_line_ver = (-cell_length / 2 + j * cell_length, cell_height / 2 - (nb_l) * cell_height - l_fill, 0 ) # (-cell_length ,cell_height,0) line_ver = Line(start=start_line_ver, end=end_line_ver, color=line_color) grid.add(line_ver) #Rec = Rectangle() result.add(rec) result.add(table) result.add(grid) return result
def __init__(self, mobject=None, **kwargs): if mobject is None: mobject = Line(3 * LEFT, 3 * RIGHT) Animation.__init__(self, mobject, **kwargs)
def construct(self): if 1 == 1: try: self.add_sound( "sidewayoutput\\basicmanim\\transform001a_01_01_01_01_01.wav", time_offset=18) self.add_sound( "sidewayoutput\\basicmanim\\transform001a_01_01_01_02_01.wav", time_offset=93) self.add_sound( "sidewayoutput\\basicmanim\\transform001a_01_01_01_03_01.wav", time_offset=135) except: pass self.play( StartScreens01( [], [], [[r"\textbf{\textit{Basic-Manim from }\{Sideway\}}"], [r"\textbf{\textit{Transform}}\\{{Part\ \textspA{I}a}"], [ r"\tiny{\textrm{basic-manim.210200551v0\_transform001a}}" ], [], [ r"\scriptsize{\textbf{Warning:\ The\ content\ may\ contain\ errors,\ mistakes\ and\ inaccuracies.\ Information\ must\ be\ verified\ and\ evaluated\ before\ use.}}" ]], )) if 1 == 1: self.play( GrowFromCenter( TextMobject( r"\textit{\textbf{\underline{Transform}}}").shift( [0, 3.6, 0]))) squarea = Square() squareb = Square(side_length=4).shift([4, 0, 0]) circlea = Circle() circleb = Circle(radius=2).shift([-4, 0, 0]) linea = Line([-4, 3, 0], [4, 3, 0]) lineb = Line([-3, -3, 0], [3, -3, 0]) texta = TextMobject("AB").shift([0, -2.5, 0]) textb = TextMobject("HI").shift([0, 2.5, 0]) self.play( ShowCreation(Group(squarea, circlea, squareb, circleb, linea, lineb), lag_ratio=1, run_time=12)) self.play(Write(VGroup(texta, textb), lag_ratio=1, run_time=10)) self.play(Transform(circlea, squarea, run_time=5)) self.play(Transform(circlea, squareb, path_arc=3, run_time=5)) self.play(Transform(squarea, circleb, path_arc=3, run_time=5)) self.play(Transform(linea, lineb, path_arc=3, run_time=5)) self.play(Transform(linea, circleb, path_arc=3, run_time=5)) self.play(Transform(squareb, lineb, path_arc=3, run_time=5)) self.play(Transform(texta, textb, path_arc=3, run_time=5)) self.play(Transform(texta, circleb, path_arc=3, run_time=5)) self.play(Transform(squareb, textb, path_arc=3, run_time=5)) self.fadeout() if 1 == 1: self.play( GrowFromCenter( TextMobject( r"\textit{\textbf{\underline{Paths\ of\ Transform}}}"). shift([0, 3.6, 0]))) rows, cols = (7, 5) x0, y0 = axes_point([0, 2, cols - 1, -4], [2.3, -1, rows - 1, 3]) txtx = ["loc 1", "loc 2", "m1", "m2"] txty = [ "ClockwiseTransform", "Transform", "CounterclockwiseTransform" ] a1 = Group() a2 = Group() a3 = Group() a4 = Group() for j in range(1, rows): a1.add(Circle().scale(0.2).move_to([x0[1], y0[j], 0])) a2.add(Square().scale(0.2).move_to([x0[2], y0[j], 0])) a3.add( Dot([x0[3], y0[j], 0]).add_updater(lambda mob, obj=a1[ j - 1], x=x0[3], y=y0[j]: mob.become(obj.copy( ).move_to([x, y, 0]))).suspend_updating()) a4.add( Dot([x0[4], y0[j], 0]).add_updater(lambda mob, obj=a2[ j - 1], x=x0[4], y=y0[j]: mob.become(obj.copy( ).move_to([x, y, 0]))).suspend_updating()) self.play(FadeIn( Group( *[ TextMobject(txtx[i]).move_to(each) for i, each in enumerate(coord_grid(x0[1:], y0[0:1])) ], *[ TextMobject(txty[i]).move_to(each) for i, each in enumerate(coord_grid(x0[0:1], y0[1::2])) ], *[Dot(each) for each in coord_grid(x0[1:3], y0[1:])], TextMobject(r"$\rightarrow$").move_to( ([(x0[1] + x0[2]) / 2, y0[0], 0])), a1[::2], a2[::2], a3, a4, *[ Square(stroke_width=2, color="#FFFF00", fill_opacity=0.3).add_updater( lambda mob, obj=obj: mob.surround( obj, stretch=True, buff=0.2)) for obj in a1 ], *[ Square(stroke_width=2, color="#DC75CD").add_updater( lambda mob, obj=obj: mob.surround( obj, stretch=True, buff=0.3)) for obj in a2 ])), run_time=5) self.wait(2) self.play(AnimationGroup( ClockwiseTransform(a2[0], a1[0]), ClockwiseTransform(a1[1], a2[1]), Transform(a1[2], a2[2]), Transform(a2[3], a1[3]), CounterclockwiseTransform(a1[4], a2[4]), CounterclockwiseTransform(a2[5], a1[5]), ), run_time=25) self.wait(3) a1.shift([0.3, 0, 0]).set_color("#11FF00") self.wait(3) self.play(ApplyMethod(a1.shift, ([0.3, 0, 0])), run_time=3) self.fadeout() if 1 == 1: self.play( GrowFromCenter( TextMobject( r"\textit{\textbf{\underline{Methods\ of\ Transform}}}" ).shift([0, 3.6, 0]))) rows, cols = (9, 5) x0, y0 = axes_point([0, 2, cols - 1, -4], [2.3, -0.8, rows - 1, 3]) txtx = ["loc 1", "loc 2", "m1", "m2"] txty = [ "Transform", "ReplacementTransform", "TransformFromCopy", "MoveToTarget" ] a1 = Group() a2 = Group() a3 = Group() a4 = Group() for j in range(1, rows): a1.add(Circle().scale(0.2).move_to([x0[1], y0[j], 0])) a2.add(Square().scale(0.2).move_to([x0[2], y0[j], 0])) a3.add(Dot().move_to([x0[3], y0[j], 0]).add_updater( lambda mob, obj=a1[j - 1], x=x0[3], y=y0[j]: mob.become( obj.copy().move_to([x, y, 0]))).suspend_updating()) a4.add(Dot().move_to([x0[4], y0[j], 0]).add_updater( lambda mob, obj=a2[j - 1], x=x0[4], y=y0[j]: mob.become( obj.copy().move_to([x, y, 0]))).suspend_updating()) a1[6].target = a2[6] a1[7].target = a2[7] self.play(FadeIn( Group( *[ TextMobject(txtx[i]).move_to(each) for i, each in enumerate(coord_grid(x0[1:], y0[0:1])) ], *[ TextMobject(txty[i]).move_to(each) for i, each in enumerate(coord_grid(x0[0:1], y0[1::2])) ], *[Dot(each) for each in coord_grid(x0[1:3], y0[1:])], TextMobject(r"$\rightarrow$").move_to( ([(x0[1] + x0[2]) / 2, y0[0], 0])), a1[::2], a2[::2], a3, a4, Group(*[ Square( stroke_width=2, color="#FFFF00", fill_opacity=0.3). add_updater(lambda mob, obj=obj: mob.surround( obj, stretch=True, buff=0.2)) for obj in a1 ]), Group(*[ Square(stroke_width=2, color="#DC75CD").add_updater( lambda mob, obj=obj: mob.surround( obj, stretch=True, buff=0.3)) for obj in a2 ]))), run_time=5) self.wait(2) self.play(AnimationGroup(Transform(a1[0], a2[0]), Transform(a1[1], a2[1]), ReplacementTransform(a1[2], a2[2]), ReplacementTransform(a1[3], a2[3]), TransformFromCopy(a1[4], a2[4]), TransformFromCopy(a1[5], a2[5]), MoveToTarget(a1[6]), MoveToTarget(a1[7])), run_time=40) self.wait(3) a1.shift([0.3, 0, 0]).set_color("#11FF00") self.wait(10) self.play(ApplyMethod(a1.shift, ([0.3, 0, 0])), run_time=5) self.fadeout() if 1 == 1: self.play(EndScreen01()) self.wait(5)
def line_to_mobject(self, line: se.Line) -> Line: return Line(start=_convert_point_to_3d(line.x1, line.y1), end=_convert_point_to_3d(line.x2, line.y2))
def InsertPoint(self, point): net_insert_point_and_set_circumcirclecenter(point, self.net) self.voronoi = self.VisitVoronoi() self.become(VGroup(*[Line(*each, **self.kwargs) for each in self.voronoi])) 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, ): """ This method returns a VGroup of (two lines representing dx and df, the labels for dx and df, and the Secant to the Graph/curve at a particular x value. Parameters ---------- x (Union[float, int]) The x value at which the secant enters, and intersects the graph for the first time. graph (ParametricFunction) The curve/graph for which the secant must be found. dx (Union[float, int]) The change in x after which the secant exits. dx_line_color (str) The line color for the line that indicates the change in x. df_line_color (str) The line color for the line that indicates the change in y. dx_label (str) The label to be provided for the change in x. df_label (str) The label to be provided for the change in y. include_secant_line (bool=True) Whether or not to include the secant line in the graph, or just have the df and dx lines and labels. secant_line_color (str) The color of the secant line. secant_line_length (Union[float,int=10]) How long the secant line should be. Returns: -------- VGroup 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] * RIGHT + p1[1] * 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) * 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) * 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 __init__(self, radius=1, **kwargs): super().__init__(**kwargs) self.append_vectorized_mobject(Line()) self.append_vectorized_mobject(Arc(angle=PI)) self.scale(radius)