def init_colors(self): VMobject.init_colors(self) self.axes.set_stroke(self.axes_color, self.stroke_width) self.main_lines.set_stroke(self.color, self.stroke_width) self.secondary_lines.set_stroke(self.secondary_color, self.secondary_stroke_width) return self
def __init__(self, vmobject=None, **kwargs): VMobject.__init__(self, **kwargs) if vmobject is not None: self.points = np.array(vmobject.points) self.match_style(vmobject, family=False) self.submobjects = [ ThreeDVMobject(submob, **kwargs) for submob in vmobject.submobjects ]
def init_colors(self): VMobject.init_colors(self) internal_pis = [ pi for pi in self.submobject_family() if isinstance(pi, PiCreature) ] random.seed(self.random_seed) for pi in reversed(internal_pis): color = random.choice(self.colors) pi.set_color(color) pi.set_stroke(color, width=0)
def set_style_data(self, stroke_color=None, stroke_width=None, fill_color=None, fill_opacity=None, family=True): # Unchangable style, except for fill_opacity VMobject.set_style_data(self, stroke_color=BLACK, stroke_width=0, fill_color=BLACK, fill_opacity=fill_opacity) return self
def __init__(self, number, **kwargs): VMobject.__init__(self, **kwargs) self.number = number self.initial_config = kwargs if isinstance(number, complex): formatter = self.get_complex_formatter() else: formatter = self.get_formatter() num_string = formatter.format(number) if num_string.startswith("-") and number == 0: num_string = num_string[1:] self.add(*[ SingleStringTexMobject(char, **kwargs) for char in num_string ]) # Add non-numerical bits if self.show_ellipsis: self.add(SingleStringTexMobject("\\dots")) if num_string.startswith("-"): minus = self.submobjects[0] minus.next_to( self.submobjects[1], LEFT, buff=self.digit_to_digit_buff ) if self.unit is not None: self.unit_sign = SingleStringTexMobject(self.unit, color=self.color) self.add(self.unit_sign) self.arrange_submobjects( buff=self.digit_to_digit_buff, aligned_edge=DOWN ) # Handle alignment of parts that should be aligned # to the bottom for i, c in enumerate(num_string): if c == "-" and len(num_string) > i + 1: self[i].align_to(self[i + 1], alignment_vect=UP) elif c == ",": self[i].shift(self[i].get_height() * DOWN / 2) if self.unit and self.unit.startswith("^"): self.unit_sign.align_to(self, UP) # if self.include_background_rectangle: self.add_background_rectangle()
def __init__(self, obj, text, brace_direction=DOWN, **kwargs): VMobject.__init__(self, **kwargs) self.brace_direction = brace_direction if isinstance(obj, list): obj = VMobject(*obj) self.brace = Brace(obj, brace_direction, **kwargs) if isinstance(text, tuple) or isinstance(text, list): self.label = self.label_constructor(*text, **kwargs) else: self.label = self.label_constructor(str(text)) if self.label_scale != 1: self.label.scale(self.label_scale) self.brace.put_at_tip(self.label) self.submobjects = [self.brace, self.label]
def shift_brace(self, obj, **kwargs): if isinstance(obj, list): obj = VMobject(*obj) self.brace = Brace(obj, self.brace_direction, **kwargs) self.brace.put_at_tip(self.label) self.submobjects[0] = self.brace return self
def use_to_mobjects(self, use_element): # Remove initial "#" character ref = use_element.getAttribute("xlink:href")[1:] if ref not in self.ref_to_element: warnings.warn("%s not recognized" % ref) return VMobject() return self.get_mobjects_from( self.ref_to_element[ref] )
def __init__(self, matrix, **kwargs): """ Matrix can either either include numbres, tex_strings, or mobjects """ VMobject.__init__(self, **kwargs) matrix = np.array(matrix, ndmin=1) mob_matrix = self.matrix_to_mob_matrix(matrix) self.organize_mob_matrix(mob_matrix) self.elements = VGroup(*mob_matrix.flatten()) self.add(self.elements) self.add_brackets() self.center() self.mob_matrix = mob_matrix if self.add_background_rectangles_to_entries: for mob in self.elements: mob.add_background_rectangle() if self.include_background_rectangle: self.add_background_rectangle()
def add_pupil_light_spot(self, pupils): # Purely an artifact of how the SVGs were drawn. # In a perfect world, this wouldn't be needed for pupil in pupils: index = 16 sub_points = pupil.points[:index] pupil.points = pupil.points[index + 2:] circle = VMobject() circle.points = sub_points circle.set_stroke(width=0) circle.set_fill(WHITE, 1) pupil.add(circle)
def get_det_text(matrix, determinant=None, background_rect=True, initial_scale_factor=2): parens = TexMobject(["(", ")"]) parens.scale(initial_scale_factor) parens.stretch_to_fit_height(matrix.get_height()) l_paren, r_paren = parens.split() l_paren.next_to(matrix, LEFT, buff=0.1) r_paren.next_to(matrix, RIGHT, buff=0.1) det = TextMobject("det") det.scale(initial_scale_factor) det.next_to(l_paren, LEFT, buff=0.1) if background_rect: det.add_background_rectangle() det_text = VMobject(det, l_paren, r_paren) if determinant is not None: eq = TexMobject("=") eq.next_to(r_paren, RIGHT, buff=0.1) result = TexMobject(str(determinant)) result.next_to(eq, RIGHT, buff=0.2) det_text.add(eq, result) return det_text
def generate_points(self): self.add(self.source_point) self.lighthouse = Lighthouse() self.ambient_light = AmbientLight( source_point=VectorizedPoint(location=self.get_source_point()), color=self.color, num_levels=self.num_levels, radius=self.radius, opacity_function=self.opacity_function, max_opacity=self.max_opacity_ambient) if self.has_screen(): self.spotlight = Spotlight( source_point=VectorizedPoint(location=self.get_source_point()), color=self.color, num_levels=self.num_levels, radius=self.radius, screen=self.screen, opacity_function=self.opacity_function, max_opacity=self.max_opacity_spotlight, camera_mob=self.camera_mob) else: self.spotlight = Spotlight() self.shadow = VMobject(fill_color=SHADOW_COLOR, fill_opacity=1.0, stroke_color=BLACK) self.lighthouse.next_to(self.get_source_point(), DOWN, buff=0) self.ambient_light.move_source_to(self.get_source_point()) if self.has_screen(): self.spotlight.move_source_to(self.get_source_point()) self.update_shadow() self.add(self.ambient_light, self.spotlight, self.lighthouse, self.shadow)
def generate_points(self): if self.x_radius is None: center_to_edge = (FRAME_X_RADIUS + abs(self.center_point[0])) self.x_radius = center_to_edge / self.x_unit_size if self.y_radius is None: center_to_edge = (FRAME_Y_RADIUS + abs(self.center_point[1])) self.y_radius = center_to_edge / self.y_unit_size self.axes = VMobject() self.main_lines = VMobject() self.secondary_lines = VMobject() tuples = [ (self.x_radius, self.x_line_frequency, self.y_radius * DOWN, self.y_radius * UP, RIGHT), ( self.y_radius, self.y_line_frequency, self.x_radius * LEFT, self.x_radius * RIGHT, UP, ), ] for radius, freq, start, end, unit in tuples: main_range = np.arange(0, radius, freq) step = freq / float(freq + self.secondary_line_ratio) for v in np.arange(0, radius, step): line1 = Line(start + v * unit, end + v * unit) line2 = Line(start - v * unit, end - v * unit) if v == 0: self.axes.add(line1) elif v in main_range: self.main_lines.add(line1, line2) else: self.secondary_lines.add(line1, line2) self.add(self.secondary_lines, self.main_lines, self.axes) self.stretch(self.x_unit_size, 0) self.stretch(self.y_unit_size, 1) self.shift(self.center_point) # Put x_axis before y_axis y_axis, x_axis = self.axes.split() self.axes = VMobject(x_axis, y_axis)
def show_ghost_movement(self, vector): if isinstance(vector, Arrow): vector = vector.get_end() - vector.get_start() elif len(vector) == 2: vector = np.append(np.array(vector), 0.0) x_max = int(FRAME_X_RADIUS + abs(vector[0])) y_max = int(FRAME_Y_RADIUS + abs(vector[1])) dots = VMobject(*[ Dot(x * RIGHT + y * UP) for x in range(-x_max, x_max) for y in range(-y_max, y_max) ]) dots.set_fill(BLACK, opacity=0) dots_halfway = dots.copy().shift(vector / 2).set_fill(WHITE, 1) dots_end = dots.copy().shift(vector) self.play(Transform(dots, dots_halfway, rate_func=rush_into)) self.play(Transform(dots, dots_end, rate_func=rush_from)) self.remove(dots)
def get_mobjects_from(self, element): result = [] if not isinstance(element, minidom.Element): return result if element.tagName == 'defs': self.update_ref_to_element(element) elif element.tagName == 'style': pass # TODO, handle style elif element.tagName in ['g', 'svg']: result += it.chain(*[ self.get_mobjects_from(child) for child in element.childNodes ]) elif element.tagName == 'path': result.append(self.path_string_to_mobject( element.getAttribute('d') )) elif element.tagName == 'use': result += self.use_to_mobjects(element) elif element.tagName == 'rect': result.append(self.rect_to_mobject(element)) elif element.tagName == 'circle': result.append(self.circle_to_mobject(element)) elif element.tagName == 'ellipse': result.append(self.ellipse_to_mobject(element)) elif element.tagName in ['polygon', 'polyline']: result.append(self.polygon_to_mobject(element)) else: pass # TODO # warnings.warn("Unknown element type: " + element.tagName) result = [m for m in result if m is not None] self.handle_transforms(element, VMobject(*result)) if len(result) > 1 and not self.unpack_groups: result = [VGroup(*result)] return result
def __init__(self, mobject, **kwargs): VMobject.__init__(self, **kwargs) self.mobject = mobject self.submobjects = self.get_eyes().submobjects
class LightSource(VMobject): # combines: # a lighthouse # an ambient light # a spotlight # and a shadow CONFIG = { "source_point": VectorizedPoint(location=ORIGIN, stroke_width=0, fill_opacity=0), "color": LIGHT_COLOR, "num_levels": 10, "radius": 10.0, "screen": None, "opacity_function": inverse_quadratic(1, 2, 1), "max_opacity_ambient": AMBIENT_FULL, "max_opacity_spotlight": SPOTLIGHT_FULL, "camera_mob": None } def generate_points(self): self.add(self.source_point) self.lighthouse = Lighthouse() self.ambient_light = AmbientLight( source_point=VectorizedPoint(location=self.get_source_point()), color=self.color, num_levels=self.num_levels, radius=self.radius, opacity_function=self.opacity_function, max_opacity=self.max_opacity_ambient) if self.has_screen(): self.spotlight = Spotlight( source_point=VectorizedPoint(location=self.get_source_point()), color=self.color, num_levels=self.num_levels, radius=self.radius, screen=self.screen, opacity_function=self.opacity_function, max_opacity=self.max_opacity_spotlight, camera_mob=self.camera_mob) else: self.spotlight = Spotlight() self.shadow = VMobject(fill_color=SHADOW_COLOR, fill_opacity=1.0, stroke_color=BLACK) self.lighthouse.next_to(self.get_source_point(), DOWN, buff=0) self.ambient_light.move_source_to(self.get_source_point()) if self.has_screen(): self.spotlight.move_source_to(self.get_source_point()) self.update_shadow() self.add(self.ambient_light, self.spotlight, self.lighthouse, self.shadow) def has_screen(self): if self.screen is None: return False elif np.size(self.screen.points) == 0: return False else: return True def dim_ambient(self): self.set_max_opacity_ambient(AMBIENT_DIMMED) def set_max_opacity_ambient(self, new_opacity): self.max_opacity_ambient = new_opacity self.ambient_light.dimming(new_opacity) def dim_spotlight(self): self.set_max_opacity_spotlight(SPOTLIGHT_DIMMED) def set_max_opacity_spotlight(self, new_opacity): self.max_opacity_spotlight = new_opacity self.spotlight.dimming(new_opacity) def set_camera_mob(self, new_cam_mob): self.camera_mob = new_cam_mob self.spotlight.camera_mob = new_cam_mob def set_screen(self, new_screen): if self.has_screen(): self.spotlight.screen = new_screen else: # Note: See below index = self.submobjects.index(self.spotlight) camera_mob = self.spotlight.camera_mob self.remove(self.spotlight) self.spotlight = Spotlight( source_point=VectorizedPoint(location=self.get_source_point()), color=self.color, num_levels=self.num_levels, radius=self.radius, screen=new_screen, camera_mob=self.camera_mob, opacity_function=self.opacity_function, max_opacity=self.max_opacity_spotlight, ) self.spotlight.move_source_to(self.get_source_point()) # Note: This line will make spotlight show up at the end # of the submojects list, which can make it show up on # top of the shadow. To make it show up in the # same spot, you could try the following line, # where "index" is what I defined above: self.submobjects.insert(index, self.spotlight) # self.add(self.spotlight) # in any case self.screen = new_screen def move_source_to(self, point): apoint = np.array(point) v = apoint - self.get_source_point() # Note: As discussed, things stand to behave better if source # point is a submobject, so that it automatically interpolates # during an animation, and other updates can be defined wrt # that source point's location self.source_point.set_location(apoint) # self.lighthouse.next_to(apoint,DOWN,buff = 0) # self.ambient_light.move_source_to(apoint) self.lighthouse.shift(v) # self.ambient_light.shift(v) self.ambient_light.move_source_to(apoint) if self.has_screen(): self.spotlight.move_source_to(apoint) self.update() return self def change_spotlight_opacity_function(self, new_of): self.spotlight.change_opacity_function(new_of) def set_radius(self, new_radius): self.radius = new_radius self.ambient_light.radius = new_radius self.spotlight.radius = new_radius def update(self): self.update_lighthouse() self.update_ambient() self.spotlight.update_sectors() self.update_shadow() def update_lighthouse(self): self.lighthouse.move_to(self.get_source_point()) # new_lh = Lighthouse() # new_lh.move_to(ORIGIN) # new_lh.apply_matrix(self.rotation_matrix()) # new_lh.shift(self.get_source_point()) # self.lighthouse.submobjects = new_lh.submobjects def update_ambient(self): new_ambient_light = AmbientLight( source_point=VectorizedPoint(location=ORIGIN), color=self.color, num_levels=self.num_levels, radius=self.radius, opacity_function=self.opacity_function, max_opacity=self.max_opacity_ambient) new_ambient_light.apply_matrix(self.rotation_matrix()) new_ambient_light.move_source_to(self.get_source_point()) self.ambient_light.submobjects = new_ambient_light.submobjects def get_source_point(self): return self.source_point.get_location() def rotation_matrix(self): if self.camera_mob is None: return np.eye(3) phi = self.camera_mob.get_center()[0] theta = self.camera_mob.get_center()[1] R1 = np.array([[1, 0, 0], [0, np.cos(phi), -np.sin(phi)], [0, np.sin(phi), np.cos(phi)]]) R2 = np.array([[np.cos(theta + TAU / 4), -np.sin(theta + TAU / 4), 0], [np.sin(theta + TAU / 4), np.cos(theta + TAU / 4), 0], [0, 0, 1]]) R = np.dot(R2, R1) return R def update_shadow(self): point = self.get_source_point() projected_screen_points = [] if not self.has_screen(): return for point in self.screen.get_anchors(): projected_screen_points.append(self.spotlight.project(point)) projected_source = project_along_vector( self.get_source_point(), self.spotlight.projection_direction()) projected_point_cloud_3d = np.append(projected_screen_points, np.reshape( projected_source, (1, 3)), axis=0) # z_to_vector(self.spotlight.projection_direction()) rotation_matrix = self.rotation_matrix() back_rotation_matrix = rotation_matrix.T # i. e. its inverse rotated_point_cloud_3d = np.dot(projected_point_cloud_3d, back_rotation_matrix.T) # these points now should all have z = 0 point_cloud_2d = rotated_point_cloud_3d[:, :2] # now we can compute the convex hull hull_2d = ConvexHull(point_cloud_2d) # guaranteed to run ccw hull = [] # we also need the projected source point source_point_2d = np.dot( self.spotlight.project(self.get_source_point()), back_rotation_matrix.T)[:2] index = 0 for point in point_cloud_2d[hull_2d.vertices]: if np.all(np.abs(point - source_point_2d) < 1.0e-6): source_index = index index += 1 continue point_3d = np.array([point[0], point[1], 0]) hull.append(point_3d) index += 1 hull_mobject = VMobject() hull_mobject.set_points_as_corners(hull) hull_mobject.apply_matrix(rotation_matrix) anchors = hull_mobject.get_anchors() # add two control points for the outer cone if np.size(anchors) == 0: self.shadow.points = [] return ray1 = anchors[source_index - 1] - projected_source ray1 = ray1 / get_norm(ray1) * 100 ray2 = anchors[source_index] - projected_source ray2 = ray2 / get_norm(ray2) * 100 outpoint1 = anchors[source_index - 1] + ray1 outpoint2 = anchors[source_index] + ray2 new_anchors = anchors[:source_index] new_anchors = np.append(new_anchors, np.array([outpoint1, outpoint2]), axis=0) new_anchors = np.append(new_anchors, anchors[source_index:], axis=0) self.shadow.set_points_as_corners(new_anchors) # shift it closer to the camera so it is in front of the spotlight self.shadow.mark_paths_closed = True
def init_colors(self): VMobject.init_colors(self) self.set_color_by_gradient(*self.colors)
def init_colors(self): VMobject.init_colors(self) self.set_color_by_gradient(*self.colors) for order in sorted(self.order_to_stroke_width_map.keys()): if self.order >= order: self.set_stroke(width=self.order_to_stroke_width_map[order])
def __init__(self, path_string, **kwargs): digest_locals(self) VMobject.__init__(self, **kwargs)
def __init__(self, **kwargs): digest_config(self, kwargs, locals()) self.ensure_valid_file() VMobject.__init__(self, **kwargs) self.move_into_position()
def get_center(self): result = VMobject.get_center(self) if hasattr(self, "center_offset"): result -= self.center_offset return result
def clear(self): self.add_content(VMobject()) return self
def __init__(self, **kwargs): VMobject.__init__(self, **kwargs) self.add_iris_back() self.add_spikes() self.add_pupil()
def update_shadow(self): point = self.get_source_point() projected_screen_points = [] if not self.has_screen(): return for point in self.screen.get_anchors(): projected_screen_points.append(self.spotlight.project(point)) projected_source = project_along_vector( self.get_source_point(), self.spotlight.projection_direction()) projected_point_cloud_3d = np.append(projected_screen_points, np.reshape( projected_source, (1, 3)), axis=0) # z_to_vector(self.spotlight.projection_direction()) rotation_matrix = self.rotation_matrix() back_rotation_matrix = rotation_matrix.T # i. e. its inverse rotated_point_cloud_3d = np.dot(projected_point_cloud_3d, back_rotation_matrix.T) # these points now should all have z = 0 point_cloud_2d = rotated_point_cloud_3d[:, :2] # now we can compute the convex hull hull_2d = ConvexHull(point_cloud_2d) # guaranteed to run ccw hull = [] # we also need the projected source point source_point_2d = np.dot( self.spotlight.project(self.get_source_point()), back_rotation_matrix.T)[:2] index = 0 for point in point_cloud_2d[hull_2d.vertices]: if np.all(np.abs(point - source_point_2d) < 1.0e-6): source_index = index index += 1 continue point_3d = np.array([point[0], point[1], 0]) hull.append(point_3d) index += 1 hull_mobject = VMobject() hull_mobject.set_points_as_corners(hull) hull_mobject.apply_matrix(rotation_matrix) anchors = hull_mobject.get_anchors() # add two control points for the outer cone if np.size(anchors) == 0: self.shadow.points = [] return ray1 = anchors[source_index - 1] - projected_source ray1 = ray1 / get_norm(ray1) * 100 ray2 = anchors[source_index] - projected_source ray2 = ray2 / get_norm(ray2) * 100 outpoint1 = anchors[source_index - 1] + ray1 outpoint2 = anchors[source_index] + ray2 new_anchors = anchors[:source_index] new_anchors = np.append(new_anchors, np.array([outpoint1, outpoint2]), axis=0) new_anchors = np.append(new_anchors, anchors[source_index:], axis=0) self.shadow.set_points_as_corners(new_anchors) # shift it closer to the camera so it is in front of the spotlight self.shadow.mark_paths_closed = True
def __init__(self, function, **kwargs): self.function = function VMobject.__init__(self, **kwargs)
class NumberPlane(VMobject): CONFIG = { "color": BLUE_D, "secondary_color": BLUE_E, "axes_color": WHITE, "secondary_stroke_width": 1, # TODO: Allow coordinate center of NumberPlane to not be at (0, 0) "x_radius": None, "y_radius": None, "x_unit_size": 1, "y_unit_size": 1, "center_point": ORIGIN, "x_line_frequency": 1, "y_line_frequency": 1, "secondary_line_ratio": 1, "written_coordinate_height": 0.2, "propagate_style_to_family": False, "make_smooth_after_applying_functions": True, } def generate_points(self): if self.x_radius is None: center_to_edge = (FRAME_X_RADIUS + abs(self.center_point[0])) self.x_radius = center_to_edge / self.x_unit_size if self.y_radius is None: center_to_edge = (FRAME_Y_RADIUS + abs(self.center_point[1])) self.y_radius = center_to_edge / self.y_unit_size self.axes = VMobject() self.main_lines = VMobject() self.secondary_lines = VMobject() tuples = [ (self.x_radius, self.x_line_frequency, self.y_radius * DOWN, self.y_radius * UP, RIGHT), ( self.y_radius, self.y_line_frequency, self.x_radius * LEFT, self.x_radius * RIGHT, UP, ), ] for radius, freq, start, end, unit in tuples: main_range = np.arange(0, radius, freq) step = freq / float(freq + self.secondary_line_ratio) for v in np.arange(0, radius, step): line1 = Line(start + v * unit, end + v * unit) line2 = Line(start - v * unit, end - v * unit) if v == 0: self.axes.add(line1) elif v in main_range: self.main_lines.add(line1, line2) else: self.secondary_lines.add(line1, line2) self.add(self.secondary_lines, self.main_lines, self.axes) self.stretch(self.x_unit_size, 0) self.stretch(self.y_unit_size, 1) self.shift(self.center_point) # Put x_axis before y_axis y_axis, x_axis = self.axes.split() self.axes = VMobject(x_axis, y_axis) def init_colors(self): VMobject.init_colors(self) self.axes.set_stroke(self.axes_color, self.stroke_width) self.main_lines.set_stroke(self.color, self.stroke_width) self.secondary_lines.set_stroke(self.secondary_color, self.secondary_stroke_width) return self def get_center_point(self): return self.coords_to_point(0, 0) def coords_to_point(self, x, y): x, y = np.array([x, y]) result = self.axes.get_center() result += x * self.get_x_unit_size() * RIGHT result += y * self.get_y_unit_size() * UP return result def point_to_coords(self, point): new_point = point - self.axes.get_center() x = new_point[0] / self.get_x_unit_size() y = new_point[1] / self.get_y_unit_size() return x, y # Does not recompute center, unit_sizes for each call; useful for # iterating over large lists of points, but does assume these # attributes are kept accurate. (Could alternatively have a method # which returns a function dynamically created after a single # call to each of get_center(), get_x_unit_size(), etc.) def point_to_coords_cheap(self, point): new_point = point - self.center_point x = new_point[0] / self.x_unit_size y = new_point[1] / self.y_unit_size return x, y def get_x_unit_size(self): return self.axes.get_width() / (2.0 * self.x_radius) def get_y_unit_size(self): return self.axes.get_height() / (2.0 * self.y_radius) def get_coordinate_labels(self, x_vals=None, y_vals=None): coordinate_labels = VGroup() if x_vals is None: x_vals = list(range(-int(self.x_radius), int(self.x_radius) + 1)) if y_vals is None: y_vals = list(range(-int(self.y_radius), int(self.y_radius) + 1)) for index, vals in enumerate([x_vals, y_vals]): num_pair = [0, 0] for val in vals: if val == 0: continue num_pair[index] = val point = self.coords_to_point(*num_pair) num = TexMobject(str(val)) num.add_background_rectangle() num.set_height(self.written_coordinate_height) num.next_to(point, DOWN + LEFT, buff=SMALL_BUFF) coordinate_labels.add(num) self.coordinate_labels = coordinate_labels return coordinate_labels def get_axes(self): return self.axes def get_axis_labels(self, x_label="x", y_label="y"): x_axis, y_axis = self.get_axes().split() quads = [ (x_axis, x_label, UP, RIGHT), (y_axis, y_label, RIGHT, UP), ] labels = VGroup() for axis, tex, vect, edge in quads: label = TexMobject(tex) label.add_background_rectangle() label.next_to(axis, vect) label.to_edge(edge) labels.add(label) self.axis_labels = labels return labels def add_coordinates(self, x_vals=None, y_vals=None): self.add(*self.get_coordinate_labels(x_vals, y_vals)) return self def get_vector(self, coords, **kwargs): point = coords[0] * RIGHT + coords[1] * UP arrow = Arrow(ORIGIN, point, **kwargs) return arrow def prepare_for_nonlinear_transform(self, num_inserted_anchor_points=50): for mob in self.family_members_with_points(): num_anchors = mob.get_num_anchor_points() if num_inserted_anchor_points > num_anchors: mob.insert_n_anchor_points(num_inserted_anchor_points - num_anchors) mob.make_smooth() return self
def get_piece_movement(self, pieces): start = VMobject(*pieces) target = VMobject(*[mob.target for mob in pieces]) if self.leave_ghost_vectors: self.add(start.copy().fade(0.7)) return Transform(start, target, submobject_mode="all_at_once")
def g_to_mobjects(self, g_element): mob = VMobject(*self.get_mobjects_from(g_element)) self.handle_transforms(g_element, mob) return mob.submobjects