def construct(self): words, s = TextMobject(["Pseudo-Hilbert Curve", "s"]).split() pre_words = TextMobject("Order 1") pre_words.next_to(words, LEFT, buff = 0.5) s.next_to(words, RIGHT, buff = 0.05, aligned_edge = DOWN) cluster = Mobject(pre_words, words, s) cluster.center() cluster.scale(0.7) cluster.to_edge(UP, buff = 0.3) cluster.highlight(GREEN) grid1 = Grid(1, 1) grid2 = Grid(2, 2) curve = HilbertCurve(order = 1) self.add(words, s) self.dither() self.play(Transform( s, pre_words, path_func = path_along_arc(-np.pi/3) )) self.dither() self.play(ShowCreation(grid1)) self.dither() self.play(ShowCreation(grid2)) self.dither() kwargs = { "run_time" : 5, "rate_func" : None } self.play(ShowCreation(curve, **kwargs)) self.dither()
def construct(self): n_terms = 4 def func((x, y, ignore)): z = complex(x, y) if (np.abs(x%1 - 0.5)<0.01 and y < 0.01) or np.abs(z)<0.01: return ORIGIN out_z = 1./(2*np.tan(np.pi*z)*(z**2)) return out_z.real*RIGHT - out_z.imag*UP arrows = Mobject(*[ Arrow(ORIGIN, np.sqrt(2)*point) for point in compass_directions(4, RIGHT+UP) ]) arrows.highlight(YELLOW) arrows.ingest_submobjects() all_arrows = Mobject(*[ arrows.copy().scale(0.3/(x)).shift(x*RIGHT) for x in range(1, n_terms+2) ]) terms = TexMobject([ "\\dfrac{1}{%d^2} + "%(x+1) for x in range(n_terms) ]+["\\cdots"]) terms.shift(2*UP) plane = NumberPlane(color = BLUE_E) axes = Mobject(NumberLine(), NumberLine().rotate(np.pi/2)) axes.highlight(WHITE) for term in terms.split(): self.play(ShimmerIn(term, run_time = 0.5)) self.dither() self.play(ShowCreation(plane), ShowCreation(axes)) self.play(*[ Transform(*pair) for pair in zip(terms.split(), all_arrows.split()) ]) self.play(PhaseFlow( func, plane, run_time = 5, virtual_time = 8 ))
class FluidFlow(Scene): DEFAULT_CONFIG = { "arrow_spacing" : 1, "dot_spacing" : 0.5, "dot_color" : BLUE_B, "text_color" : WHITE, "arrow_color" : GREEN_A, "points_height" : SPACE_HEIGHT, "points_width" : SPACE_WIDTH, } def use_function(self, function): self.function = function def get_points(self, spacing): x_radius, y_radius = [ val-val%spacing for val in self.points_width, self.points_height ] return map(np.array, it.product( np.arange(-x_radius, x_radius+spacing, spacing), np.arange(-y_radius, y_radius+spacing, spacing), [0] )) def add_plane(self): self.add(NumberPlane().fade()) def add_dots(self): points = self.get_points(self.dot_spacing) self.dots = Mobject(*map(Dot, points)) self.dots.highlight(self.dot_color) self.play(ShowCreation(self.dots)) self.dither() def add_arrows(self, true_length = False): if not hasattr(self, "function"): raise Exception("Must run use_function first") points = self.get_points(self.arrow_spacing) points = filter( lambda p : np.linalg.norm(self.function(p)) > 0.01, points ) angles = map(angle_of_vector, map(self.function, points)) prototype = Arrow( ORIGIN, RIGHT*self.arrow_spacing/2., color = self.arrow_color, tip_length = 0.1, buff = 0 ) arrows = [] for point in points: arrow = prototype.copy() output = self.function(point) if true_length: arrow.scale(np.linalg.norm(output)) arrow.rotate(angle_of_vector(output)) arrow.shift(point) arrows.append(arrow) self.arrows = Mobject(*arrows) self.play(ShowCreation(self.arrows)) self.dither() def add_paddle(self): pass def flow(self, **kwargs): if not hasattr(self, "function"): raise Exception("Must run use_function first") self.play(ApplyToCenters( PhaseFlow, self.dots.split(), function = self.function, **kwargs )) def label(self, text, time = 5): mob = TextMobject(text) mob.scale(1.5) mob.to_edge(UP) rectangle = region_from_polygon_vertices(*[ mob.get_corner(vect) + 0.3*vect for vect in [ UP+RIGHT, UP+LEFT, DOWN+LEFT, DOWN+RIGHT ] ]) mob.highlight(self.text_color) rectangle = MobjectFromRegion(rectangle, "#111111") rectangle.point_thickness = 3 self.add(rectangle, mob) self.dither(time) self.remove(mob, rectangle)
class FormalDefinitionOfContinuity(Scene): def construct(self): self.setup() self.label_spaces() self.move_dot() self.label_jump() self.draw_circles() self.vary_circle_sizes() self.discontinuous_point() def setup(self): self.input_color = YELLOW_C self.output_color = RED def spiril(t): theta = 2*np.pi*t return t*np.cos(theta)*RIGHT+t*np.sin(theta)*UP self.spiril1 = ParametricFunction( lambda t : 1.5*RIGHT + DOWN + 2*spiril(t), density = 5*DEFAULT_POINT_DENSITY_1D, ) self.spiril2 = ParametricFunction( lambda t : 5.5*RIGHT + UP - 2*spiril(1-t), density = 5*DEFAULT_POINT_DENSITY_1D, ) Mobject.align_data(self.spiril1, self.spiril2) self.output = Mobject(self.spiril1, self.spiril2) self.output.ingest_submobjects() self.output.highlight(GREEN_A) self.interval = UnitInterval() self.interval.scale_to_fit_width(SPACE_WIDTH-1) self.interval.to_edge(LEFT) self.input_dot = Dot(color = self.input_color) self.output_dot = self.input_dot.copy().highlight(self.output_color) left, right = self.interval.get_left(), self.interval.get_right() self.input_homotopy = lambda (x, y, z, t) : (x, y, t) + interpolate(left, right, t) output_size = self.output.get_num_points()-1 output_points = self.output.points self.output_homotopy = lambda (x, y, z, t) : (x, y, z) + output_points[int(t*output_size)] def get_circles_and_points(self, min_input, max_input): input_left, input_right = [ self.interval.number_to_point(num) for num in min_input, max_input ] input_circle = Circle( radius = np.linalg.norm(input_left-input_right)/2, color = WHITE ) input_circle.shift((input_left+input_right)/2) input_points = Line( input_left, input_right, color = self.input_color ) output_points = Mobject(color = self.output_color) n = self.output.get_num_points() output_points.add_points( self.output.points[int(min_input*n):int(max_input*n)] ) output_center = output_points.points[int(0.5*output_points.get_num_points())] max_distance = np.linalg.norm(output_center-output_points.points[-1]) output_circle = Circle( radius = max_distance, color = WHITE ) output_circle.shift(output_center) return ( input_circle, input_points, output_circle, output_points ) def label_spaces(self): input_space = TextMobject("Input Space") input_space.to_edge(UP) input_space.shift(LEFT*SPACE_WIDTH/2) output_space = TextMobject("Output Space") output_space.to_edge(UP) output_space.shift(RIGHT*SPACE_WIDTH/2) line = Line( UP*SPACE_HEIGHT, DOWN*SPACE_HEIGHT, color = WHITE ) self.play( ShimmerIn(input_space), ShimmerIn(output_space), ShowCreation(line), ShowCreation(self.interval), ) self.wait() def move_dot(self): kwargs = { "rate_func" : None, "run_time" : 3 } self.play( Homotopy(self.input_homotopy, self.input_dot, **kwargs), Homotopy(self.output_homotopy, self.output_dot, **kwargs), ShowCreation(self.output, **kwargs) ) self.wait() def label_jump(self): jump_points = Mobject( Point(self.spiril1.points[-1]), Point(self.spiril2.points[0]) ) self.brace = Brace(jump_points, RIGHT) self.jump = TextMobject("Jump") self.jump.next_to(self.brace, RIGHT) self.play( GrowFromCenter(self.brace), ShimmerIn(self.jump) ) self.wait() self.remove(self.brace, self.jump) def draw_circles(self): input_value = 0.45 input_radius = 0.04 for dot in self.input_dot, self.output_dot: dot.center() kwargs = { "rate_func" : lambda t : interpolate(1, input_value, smooth(t)) } self.play( Homotopy(self.input_homotopy, self.input_dot, **kwargs), Homotopy(self.output_homotopy, self.output_dot, **kwargs) ) A, B = map(Mobject.get_center, [self.input_dot, self.output_dot]) A_text = TextMobject("A") A_text.shift(A+2*(LEFT+UP)) A_arrow = Arrow( A_text, self.input_dot, color = self.input_color ) B_text = TextMobject("B") B_text.shift(B+2*RIGHT+DOWN) B_arrow = Arrow( B_text, self.output_dot, color = self.output_color ) tup = self.get_circles_and_points( input_value-input_radius, input_value+input_radius ) input_circle, input_points, output_circle, output_points = tup for text, arrow in [(A_text, A_arrow), (B_text, B_arrow)]: self.play( ShimmerIn(text), ShowCreation(arrow) ) self.wait() self.remove(A_text, A_arrow, B_text, B_arrow) self.play(ShowCreation(input_circle)) self.wait() self.play(ShowCreation(input_points)) self.wait() input_points_copy = input_points.copy() self.play( Transform(input_points_copy, output_points), run_time = 2 ) self.wait() self.play(ShowCreation(output_circle)) self.wait() self.wait() self.remove(*[ input_circle, input_points, output_circle, input_points_copy ]) def vary_circle_sizes(self): input_value = 0.45 radius = 0.04 vary_circles = VaryCircles( self, input_value, radius, run_time = 5, ) self.play(vary_circles) self.wait() text = TextMobject("Function is ``Continuous at A''") text.shift(2*UP).to_edge(LEFT) arrow = Arrow(text, self.input_dot) self.play( ShimmerIn(text), ShowCreation(arrow) ) self.wait() self.remove(vary_circles.mobject, text, arrow) def discontinuous_point(self): point_description = TextMobject( "Point where the function jumps" ) point_description.shift(3*RIGHT) discontinuous_at_A = TextMobject( "``Discontinuous at A''", size = "\\Large" ) discontinuous_at_A.shift(2*UP).to_edge(LEFT) text = TextMobject(""" Circle around ouput \\\\ points can never \\\\ be smaller than \\\\ the jump """) text.scale(0.75) text.shift(3.5*RIGHT) input_value = 0.5 input_radius = 0.04 vary_circles = VaryCircles( self, input_value, input_radius, run_time = 5, ) for dot in self.input_dot, self.output_dot: dot.center() kwargs = { "rate_func" : lambda t : interpolate(0.45, input_value, smooth(t)) } self.play( Homotopy(self.input_homotopy, self.input_dot, **kwargs), Homotopy(self.output_homotopy, self.output_dot, **kwargs) ) discontinuous_arrow = Arrow(discontinuous_at_A, self.input_dot) arrow = Arrow( point_description, self.output_dot, buff = 0.05, color = self.output_color ) self.play( ShimmerIn(point_description), ShowCreation(arrow) ) self.wait() self.remove(point_description, arrow) tup = self.get_circles_and_points( input_value-input_radius, input_value+input_radius ) input_circle, input_points, output_circle, output_points = tup input_points_copy = input_points.copy() self.play(ShowCreation(input_circle)) self.play(ShowCreation(input_points)) self.play( Transform(input_points_copy, output_points), run_time = 2 ) self.play(ShowCreation(output_circle)) self.wait() self.play(ShimmerIn(text)) self.remove(input_circle, input_points, output_circle, input_points_copy) self.play(vary_circles) self.wait() self.play( ShimmerIn(discontinuous_at_A), ShowCreation(discontinuous_arrow) ) self.wait(3) self.remove(vary_circles.mobject, discontinuous_at_A, discontinuous_arrow) def continuous_point(self): pass
class PiCreature(Mobject): DEFAULT_CONFIG = { "color" : BLUE_E } PART_NAMES = [ 'arm', 'body', 'left_eye', 'right_eye', 'left_leg', 'right_leg', 'mouth', ] WHITE_PART_NAMES = ['left_eye', 'right_eye', 'mouth'] MOUTH_NAMES = ["smile", "frown", "straight_mouth"] def __init__(self, **kwargs): Mobject.__init__(self, **kwargs) for part_name in self.PART_NAMES: mob = ImageMobject( part_name_to_directory(part_name), should_center = False ) if part_name not in self.WHITE_PART_NAMES: mob.highlight(self.color) setattr(self, part_name, mob) self.eyes = Mobject(self.left_eye, self.right_eye) self.legs = Mobject(self.left_leg, self.right_leg) mouth_center = self.get_mouth_center() self.mouth.center() self.smile = self.mouth self.frown = self.mouth.copy().rotate(np.pi, RIGHT) self.straight_mouth = TexMobject("-").scale(0.7) for mouth in self.smile, self.frown, self.straight_mouth: mouth.sort_points(lambda p : p[0]) mouth.highlight(self.color) ##to blend into background mouth.shift(mouth_center) self.digest_mobject_attrs() self.give_smile() self.add(self.mouth) self.scale(PI_CREATURE_SCALE_VAL) def get_parts(self): return [getattr(self, pn) for pn in self.PART_NAMES] def get_white_parts(self): return [ getattr(self, pn) for pn in self.WHITE_PART_NAMES+self.MOUTH_NAMES ] def get_mouth_center(self): result = self.body.get_center() result[0] = self.eyes.get_center()[0] return result # left_center = self.left_eye.get_center() # right_center = self.right_eye.get_center() # l_to_r = right_center-left_center # eyes_to_mouth = rotate_vector(l_to_r, -np.pi/2, OUT) # eyes_to_mouth /= np.linalg.norm(eyes_to_mouth) # return left_center/2 + right_center/2 + \ # PI_CREATURE_MOUTH_TO_EYES_DISTANCE*eyes_to_mouth def highlight(self, color, condition = None): for part in set(self.get_parts()).difference(self.get_white_parts()): part.highlight(color, condition) return self def move_to(self, destination): self.shift(destination-self.get_bottom()) return self def change_mouth_to(self, mouth_name): #TODO, This is poorly implemented self.mouth = getattr(self, mouth_name) self.sub_mobjects = list_update( self.sub_mobjects, self.get_parts() ) self.mouth.highlight(WHITE) return self def give_smile(self): return self.change_mouth_to("smile") def give_frown(self): return self.change_mouth_to("frown") def give_straight_face(self): return self.change_mouth_to("straight_mouth") def get_eye_center(self): return self.eyes.get_center() def make_mean(self): eye_x, eye_y = self.get_eye_center()[:2] def should_delete((x, y, z)): return y - eye_y > 0.3*abs(x - eye_x) self.eyes.highlight("black", should_delete) self.give_straight_face() return self def make_sad(self): eye_x, eye_y = self.get_eye_center()[:2] eye_y += 0.15 def should_delete((x, y, z)): return y - eye_y > -0.3*abs(x - eye_x) self.eyey.highlight("black", should_delete) self.give_frown() return self def get_step_intermediate(self, pi_creature): vect = pi_creature.get_center() - self.get_center() result = self.copy().shift(vect / 2.0) left_forward = vect[0] > 0 if self.right_leg.get_center()[0] < self.left_leg.get_center()[0]: #For Mortimer's case left_forward = not left_forward if left_forward: result.left_leg.wag(vect/2.0, DOWN) result.right_leg.wag(-vect/2.0, DOWN) else: result.right_leg.wag(vect/2.0, DOWN) result.left_leg.wag(-vect/2.0, DOWN) return result def blink(self): bottom = self.eyes.get_bottom() self.eyes.apply_function( lambda (x, y, z) : (x, bottom[1], z) ) return self def shift_eyes(self): for eye in self.left_eye, self.right_eye: eye.rotate_in_place(np.pi, UP) return self def to_symbol(self): Mobject.__init__( self, *list(set(self.get_parts()).difference(self.get_white_parts())) )
class PiCreature(Mobject): DEFAULT_CONFIG = {"color": BLUE_E} PART_NAMES = [ 'arm', 'body', 'left_eye', 'right_eye', 'left_leg', 'right_leg', 'mouth', ] WHITE_PART_NAMES = ['left_eye', 'right_eye', 'mouth'] MOUTH_NAMES = ["smile", "frown", "straight_mouth"] def __init__(self, **kwargs): Mobject.__init__(self, **kwargs) for part_name in self.PART_NAMES: mob = ImageMobject(part_name_to_directory(part_name), should_center=False) if part_name not in self.WHITE_PART_NAMES: mob.highlight(self.color) setattr(self, part_name, mob) self.eyes = Mobject(self.left_eye, self.right_eye) self.legs = Mobject(self.left_leg, self.right_leg) mouth_center = self.get_mouth_center() self.mouth.center() self.smile = self.mouth self.frown = self.mouth.copy().rotate(np.pi, RIGHT) self.straight_mouth = TexMobject("-").scale(0.7) for mouth in self.smile, self.frown, self.straight_mouth: mouth.sort_points(lambda p: p[0]) mouth.highlight(self.color) ##to blend into background mouth.shift(mouth_center) self.digest_mobject_attrs() self.give_smile() self.add(self.mouth) self.scale(PI_CREATURE_SCALE_VAL) def get_parts(self): return [getattr(self, pn) for pn in self.PART_NAMES] def get_white_parts(self): return [ getattr(self, pn) for pn in self.WHITE_PART_NAMES + self.MOUTH_NAMES ] def get_mouth_center(self): result = self.body.get_center() result[0] = self.eyes.get_center()[0] return result # left_center = self.left_eye.get_center() # right_center = self.right_eye.get_center() # l_to_r = right_center-left_center # eyes_to_mouth = rotate_vector(l_to_r, -np.pi/2, OUT) # eyes_to_mouth /= np.linalg.norm(eyes_to_mouth) # return left_center/2 + right_center/2 + \ # PI_CREATURE_MOUTH_TO_EYES_DISTANCE*eyes_to_mouth def highlight(self, color, condition=None): for part in set(self.get_parts()).difference(self.get_white_parts()): part.highlight(color, condition) return self def move_to(self, destination): self.shift(destination - self.get_bottom()) return self def change_mouth_to(self, mouth_name): #TODO, This is poorly implemented self.mouth = getattr(self, mouth_name) self.sub_mobjects = list_update(self.sub_mobjects, self.get_parts()) self.mouth.highlight(WHITE) return self def give_smile(self): return self.change_mouth_to("smile") def give_frown(self): return self.change_mouth_to("frown") def give_straight_face(self): return self.change_mouth_to("straight_mouth") def get_eye_center(self): return self.eyes.get_center() def make_mean(self): eye_x, eye_y = self.get_eye_center()[:2] def should_delete((x, y, z)): return y - eye_y > 0.3 * abs(x - eye_x) self.eyes.highlight("black", should_delete) self.give_straight_face() return self def make_sad(self): eye_x, eye_y = self.get_eye_center()[:2] eye_y += 0.15 def should_delete((x, y, z)): return y - eye_y > -0.3 * abs(x - eye_x) self.eyey.highlight("black", should_delete) self.give_frown() return self def get_step_intermediate(self, pi_creature): vect = pi_creature.get_center() - self.get_center() result = self.copy().shift(vect / 2.0) left_forward = vect[0] > 0 if self.right_leg.get_center()[0] < self.left_leg.get_center()[0]: #For Mortimer's case left_forward = not left_forward if left_forward: result.left_leg.wag(vect / 2.0, DOWN) result.right_leg.wag(-vect / 2.0, DOWN) else: result.right_leg.wag(vect / 2.0, DOWN) result.left_leg.wag(-vect / 2.0, DOWN) return result def blink(self): bottom = self.eyes.get_bottom() self.eyes.apply_function(lambda (x, y, z): (x, bottom[1], z)) return self def shift_eyes(self): for eye in self.left_eye, self.right_eye: eye.rotate_in_place(np.pi, UP) return self def to_symbol(self): Mobject.__init__( self, *list(set(self.get_parts()).difference(self.get_white_parts())))
class FormalDefinitionOfContinuity(Scene): def construct(self): self.setup() self.label_spaces() self.move_dot() self.label_jump() self.draw_circles() self.vary_circle_sizes() self.discontinuous_point() def setup(self): self.input_color = YELLOW_C self.output_color = RED def spiril(t): theta = 2*np.pi*t return t*np.cos(theta)*RIGHT+t*np.sin(theta)*UP self.spiril1 = ParametricFunction( lambda t : 1.5*RIGHT + DOWN + 2*spiril(t), density = 5*DEFAULT_POINT_DENSITY_1D, ) self.spiril2 = ParametricFunction( lambda t : 5.5*RIGHT + UP - 2*spiril(1-t), density = 5*DEFAULT_POINT_DENSITY_1D, ) Mobject.align_data(self.spiril1, self.spiril2) self.output = Mobject(self.spiril1, self.spiril2) self.output.ingest_sub_mobjects() self.output.highlight(GREEN_A) self.interval = UnitInterval() self.interval.scale_to_fit_width(SPACE_WIDTH-1) self.interval.to_edge(LEFT) self.input_dot = Dot(color = self.input_color) self.output_dot = self.input_dot.copy().highlight(self.output_color) left, right = self.interval.get_left(), self.interval.get_right() self.input_homotopy = lambda (x, y, z, t) : (x, y, t) + interpolate(left, right, t) output_size = self.output.get_num_points()-1 output_points = self.output.points self.output_homotopy = lambda (x, y, z, t) : (x, y, z) + output_points[int(t*output_size)] def get_circles_and_points(self, min_input, max_input): input_left, input_right = [ self.interval.number_to_point(num) for num in min_input, max_input ] input_circle = Circle( radius = np.linalg.norm(input_left-input_right)/2, color = WHITE ) input_circle.shift((input_left+input_right)/2) input_points = Line( input_left, input_right, color = self.input_color ) output_points = Mobject(color = self.output_color) n = self.output.get_num_points() output_points.add_points( self.output.points[int(min_input*n):int(max_input*n)] ) output_center = output_points.points[int(0.5*output_points.get_num_points())] max_distance = np.linalg.norm(output_center-output_points.points[-1]) output_circle = Circle( radius = max_distance, color = WHITE ) output_circle.shift(output_center) return ( input_circle, input_points, output_circle, output_points ) def label_spaces(self): input_space = TextMobject("Input Space") input_space.to_edge(UP) input_space.shift(LEFT*SPACE_WIDTH/2) output_space = TextMobject("Output Space") output_space.to_edge(UP) output_space.shift(RIGHT*SPACE_WIDTH/2) line = Line( UP*SPACE_HEIGHT, DOWN*SPACE_HEIGHT, color = WHITE ) self.play( ShimmerIn(input_space), ShimmerIn(output_space), ShowCreation(line), ShowCreation(self.interval), ) self.dither() def move_dot(self): kwargs = { "rate_func" : None, "run_time" : 3 } self.play( Homotopy(self.input_homotopy, self.input_dot, **kwargs), Homotopy(self.output_homotopy, self.output_dot, **kwargs), ShowCreation(self.output, **kwargs) ) self.dither() def label_jump(self): jump_points = Mobject( Point(self.spiril1.points[-1]), Point(self.spiril2.points[0]) ) self.brace = Brace(jump_points, RIGHT) self.jump = TextMobject("Jump") self.jump.next_to(self.brace, RIGHT) self.play( GrowFromCenter(self.brace), ShimmerIn(self.jump) ) self.dither() self.remove(self.brace, self.jump) def draw_circles(self): input_value = 0.45 input_radius = 0.04 for dot in self.input_dot, self.output_dot: dot.center() kwargs = { "rate_func" : lambda t : interpolate(1, input_value, smooth(t)) } self.play( Homotopy(self.input_homotopy, self.input_dot, **kwargs), Homotopy(self.output_homotopy, self.output_dot, **kwargs) ) A, B = map(Mobject.get_center, [self.input_dot, self.output_dot]) A_text = TextMobject("A") A_text.shift(A+2*(LEFT+UP)) A_arrow = Arrow( A_text, self.input_dot, color = self.input_color ) B_text = TextMobject("B") B_text.shift(B+2*RIGHT+DOWN) B_arrow = Arrow( B_text, self.output_dot, color = self.output_color ) tup = self.get_circles_and_points( input_value-input_radius, input_value+input_radius ) input_circle, input_points, output_circle, output_points = tup for text, arrow in [(A_text, A_arrow), (B_text, B_arrow)]: self.play( ShimmerIn(text), ShowCreation(arrow) ) self.dither() self.remove(A_text, A_arrow, B_text, B_arrow) self.play(ShowCreation(input_circle)) self.dither() self.play(ShowCreation(input_points)) self.dither() input_points_copy = input_points.copy() self.play( Transform(input_points_copy, output_points), run_time = 2 ) self.dither() self.play(ShowCreation(output_circle)) self.dither() self.dither() self.remove(*[ input_circle, input_points, output_circle, input_points_copy ]) def vary_circle_sizes(self): input_value = 0.45 radius = 0.04 vary_circles = VaryCircles( self, input_value, radius, run_time = 5, ) self.play(vary_circles) self.dither() text = TextMobject("Function is ``Continuous at A''") text.shift(2*UP).to_edge(LEFT) arrow = Arrow(text, self.input_dot) self.play( ShimmerIn(text), ShowCreation(arrow) ) self.dither() self.remove(vary_circles.mobject, text, arrow) def discontinuous_point(self): point_description = TextMobject( "Point where the function jumps" ) point_description.shift(3*RIGHT) discontinuous_at_A = TextMobject( "``Discontinuous at A''", size = "\\Large" ) discontinuous_at_A.shift(2*UP).to_edge(LEFT) text = TextMobject(""" Circle around ouput \\\\ points can never \\\\ be smaller than \\\\ the jump """) text.scale(0.75) text.shift(3.5*RIGHT) input_value = 0.5 input_radius = 0.04 vary_circles = VaryCircles( self, input_value, input_radius, run_time = 5, ) for dot in self.input_dot, self.output_dot: dot.center() kwargs = { "rate_func" : lambda t : interpolate(0.45, input_value, smooth(t)) } self.play( Homotopy(self.input_homotopy, self.input_dot, **kwargs), Homotopy(self.output_homotopy, self.output_dot, **kwargs) ) discontinuous_arrow = Arrow(discontinuous_at_A, self.input_dot) arrow = Arrow( point_description, self.output_dot, buff = 0.05, color = self.output_color ) self.play( ShimmerIn(point_description), ShowCreation(arrow) ) self.dither() self.remove(point_description, arrow) tup = self.get_circles_and_points( input_value-input_radius, input_value+input_radius ) input_circle, input_points, output_circle, output_points = tup input_points_copy = input_points.copy() self.play(ShowCreation(input_circle)) self.play(ShowCreation(input_points)) self.play( Transform(input_points_copy, output_points), run_time = 2 ) self.play(ShowCreation(output_circle)) self.dither() self.play(ShimmerIn(text)) self.remove(input_circle, input_points, output_circle, input_points_copy) self.play(vary_circles) self.dither() self.play( ShimmerIn(discontinuous_at_A), ShowCreation(discontinuous_arrow) ) self.dither(3) self.remove(vary_circles.mobject, discontinuous_at_A, discontinuous_arrow) def continuous_point(self): pass