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 construct(self, order): if order == 2: result_tex = "(0.125, 0.75)" elif order == 3: result_tex = "(0.0758, 0.6875)" phc, arg, result = TexMobject([ "\\text{PHC}_%d"%order, "(0.3)", "= %s"%result_tex ]).to_edge(UP).split() function = TextMobject("Function", size = "\\normal") function.shift(phc.get_center()+DOWN+2*LEFT) function_arrow = Arrow(function, phc) line = Line(5*LEFT, 5*RIGHT) curve = HilbertCurve(order = order) line.match_colors(curve) grid = Grid(2**order, 2**order) grid.fade() for mob in curve, grid: mob.scale(0.7) index = int(0.3*line.get_num_points()) dot1 = Dot(line.points[index]) arrow1 = Arrow(arg, dot1, buff = 0.1) dot2 = Dot(curve.points[index]) arrow2 = Arrow(result.get_bottom(), dot2, buff = 0.1) self.add(phc) self.play( ShimmerIn(function), ShowCreation(function_arrow) ) self.wait() self.remove(function_arrow, function) self.play(ShowCreation(line)) self.wait() self.play( ShimmerIn(arg), ShowCreation(arrow1), ShowCreation(dot1) ) self.wait() self.remove(arrow1) self.play( FadeIn(grid), Transform(line, curve), Transform(dot1, dot2), run_time = 2 ) self.wait() self.play( ShimmerIn(result), ShowCreation(arrow2) ) self.wait()
def construct(self): val = 0.3 text = TextMobject([ "PHC", "$_n", "(", "%3.1f"%val, ")$", " has a ", "limit point ", "as $n \\to \\infty$" ]) func_parts = text.copy().split()[:5] Mobject(*func_parts).center().to_edge(UP) num_str, val_str = func_parts[1], func_parts[3] curve = UnitInterval() curve.sort_points(lambda p : p[0]) dot = Dot().shift(curve.number_to_point(val)) arrow = Arrow(val_str, dot, buff = 0.1) curve.add_numbers(0, 1) self.play(ShowCreation(curve)) self.play( ShimmerIn(val_str), ShowCreation(arrow), ShowCreation(dot) ) self.wait() self.play( FadeOut(arrow), *[ FadeIn(func_parts[i]) for i in 0, 1, 2, 4 ] ) for num in range(2,9): new_curve = HilbertCurve(order = num) new_curve.scale(0.8) new_dot = Dot(new_curve.points[int(val*new_curve.get_num_points())]) new_num_str = TexMobject(str(num)).replace(num_str) self.play( Transform(curve, new_curve), Transform(dot, new_dot), Transform(num_str, new_num_str) ) self.wait() text.to_edge(UP) text_parts = text.split() for index in 1, -1: text_parts[index].highlight() starters = Mobject(*func_parts + [ Point(mob.get_center(), stroke_width=1) for mob in text_parts[5:] ]) self.play(Transform(starters, text)) arrow = Arrow(text_parts[-2].get_bottom(), dot, buff = 0.1) self.play(ShowCreation(arrow)) self.wait()
def __init__(self, mobject_or_point, **kwargs): digest_config(self, kwargs) big_dot = Dot( radius = SPACE_WIDTH+SPACE_HEIGHT, stroke_width = 0, fill_color = self.color, fill_opacity = 0, ) little_dot = Dot(radius = 0) little_dot.set_fill(self.color, opacity = self.opacity) little_dot.move_to(mobject_or_point) Transform.__init__(self, big_dot, little_dot, **kwargs)
def construct(self): big_grid_dim = 20. small_grid_dim = 6. big_grid = Grid(64, 64, height=big_grid_dim, width=big_grid_dim) big_grid.to_corner(UP + RIGHT, buff=2) small_grid = big_grid.copy() small_grid.scale(small_grid_dim / big_grid_dim) small_grid.center() pixel = MobjectFromRegion( region_from_polygon_vertices( *0.2 * np.array([RIGHT + DOWN, RIGHT + UP, LEFT + UP, LEFT + DOWN]))) pixel.set_color(WHITE) pixel_width = big_grid.width / big_grid.columns pixel.scale_to_fit_width(pixel_width) pixel.to_corner(UP + RIGHT, buff=2) pixel.shift(5 * pixel_width * (2 * LEFT + DOWN)) freq_line = get_freq_line() dot = Dot() dot.shift(freq_line.get_center() + 2 * RIGHT) string = Line(LEFT, RIGHT, color=GREEN) arrow = Arrow(dot, string.get_center()) vibration_config = { "overtones": 1, "spatial_period": 2, } vibration, loud_vibration, quiet_vibration = [ Vibrate(string.copy(), amplitude=a, **vibration_config) for a in [0.5, 1., 0.25] ] self.add(small_grid) self.dither() self.play(Transform(small_grid, big_grid)) self.play(FadeIn(pixel)) self.dither() self.play(FadeOut(small_grid), ShowCreation(freq_line)) self.remove(small_grid) self.play(Transform(pixel, dot), ) self.dither() self.play(ShowCreation(arrow)) self.play(loud_vibration) self.play(TransformAnimations(loud_vibration, quiet_vibration), ApplyMethod(dot.fade, 0.9)) self.clear() self.add(freq_line, dot, arrow) self.play(quiet_vibration)
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 construct(self): start_curve = SnakeCurve(order = 6) end_curve = SnakeCurve(order = 7) start_dots, end_dots = [ Mobject(*[ Dot( curve.points[int(x*curve.get_num_points())], color = color ) for x, color in [ (0.202, GREEN), (0.48, BLUE), (0.7, RED) ] ]) for curve in start_curve, end_curve ] self.add(start_curve) self.dither() self.play( ShowCreation(start_dots, run_time = 2), ApplyMethod(start_curve.fade) ) end_curve.fade() self.play( Transform(start_curve, end_curve), Transform(start_dots, end_dots) ) self.dither()
def construct(self): line = get_freq_line().center() line.sort_points(lambda p: p[0]) curves = [self.CURVE_CLASS(order=order) for order in range(3, 10)] alpha = 0.48 dot = Dot(UP) start_dot = Dot(0.1 * LEFT) dots = [ Dot(curve.points[alpha * curve.get_num_points()]) for curve in curves ] self.play(ShowCreation(line)) self.play(Transform(dot, start_dot)) self.dither() for new_dot, curve in zip(dots, curves): self.play(Transform(line, curve), Transform(dot, new_dot)) self.dither()
def construct(self): val = 0.7 text = TexMobject([ "\\text{HC}(", "x", ")", "=\\lim_{n \\to \\infty}\\text{PHC}_n(", "x", ")" ]) text.to_edge(UP) x1 = text.split()[1] x2 = text.split()[-2] x2.highlight(BLUE) explanation = TextMobject("Actual Hilbert curve function") exp_arrow = Arrow(explanation, text.split()[0]) curve = UnitInterval() dot = Dot(curve.number_to_point(val)) x_arrow = Arrow(x1.get_bottom(), dot, buff = 0) curve.sort_points(lambda p : p[0]) curve.add_numbers(0, 1) self.add(*text.split()[:3]) self.play( ShimmerIn(explanation), ShowCreation(exp_arrow) ) self.wait() self.remove(explanation, exp_arrow) self.play(ShowCreation(curve)) self.play( ApplyMethod(x1.highlight, BLUE), ShowCreation(x_arrow), ShowCreation(dot) ) self.wait() self.remove(x_arrow) limit = Mobject(*text.split()[3:]).ingest_submobjects() limit.stroke_width = 1 self.play(ShimmerIn(limit)) for num in range(1, 9): new_curve = HilbertCurve(order = num) new_curve.scale(0.8) new_dot = Dot(new_curve.points[int(val*new_curve.get_num_points())]) self.play( Transform(curve, new_curve), Transform(dot, new_dot), )
def increment(self, run_time_per_anim = 1): moving_dot = Dot( self.counting_dot_starting_position, radius = self.count_dot_starting_radius, color = self.digit_place_colors[0], ) moving_dot.generate_target() moving_dot.set_fill(opacity = 0) kwargs = { "run_time" : run_time_per_anim } continue_rolling_over = True first_move = True place = 0 while continue_rolling_over: added_anims = [] if first_move: added_anims += self.get_digit_increment_animations() first_move = False moving_dot.target.replace( self.dot_template_iterators[place].next() ) self.play(MoveToTarget(moving_dot), *added_anims, **kwargs) self.curr_configurations[place].add(moving_dot) if len(self.curr_configurations[place].split()) == self.get_place_max(place): full_configuration = self.curr_configurations[place] self.curr_configurations[place] = VGroup() place += 1 center = full_configuration.get_center_of_mass() radius = 0.6*max( full_configuration.get_width(), full_configuration.get_height(), ) circle = Circle( radius = radius, stroke_width = 0, fill_color = self.digit_place_colors[place], fill_opacity = 0.5, ) circle.move_to(center) moving_dot = VGroup(circle, full_configuration) moving_dot.generate_target() moving_dot[0].set_fill(opacity = 0) else: continue_rolling_over = False
def construct(self): text = TextMobject([ "PHC", "_n", "(", "x", ")$", " has a limit point ", "as $n \\to \\infty$", "\\\\ for all $x$" ]) parts = text.split() parts[-1].next_to(Mobject(*parts[:-1]), DOWN) parts[-1].highlight(BLUE) parts[3].highlight(BLUE) parts[1].highlight() parts[-2].highlight() text.to_edge(UP) curve = UnitInterval() curve.sort_points(lambda p : p[0]) vals = np.arange(0.1, 1, 0.1) dots = Mobject(*[ Dot(curve.number_to_point(val)) for val in vals ]) curve.add_numbers(0, 1) starter_dots = dots.copy().ingest_submobjects() starter_dots.shift(2*UP) self.add(curve, text) self.wait() self.play(DelayByOrder(ApplyMethod(starter_dots.shift, 2*DOWN))) self.wait() self.remove(starter_dots) self.add(dots) for num in range(1, 10): new_curve = HilbertCurve(order = num) new_curve.scale(0.8) new_dots = Mobject(*[ Dot(new_curve.points[int(val*new_curve.get_num_points())]) for val in vals ]) self.play( Transform(curve, new_curve), Transform(dots, new_dots), )
def construct(self): grid = get_grid() grid.scale_to_fit_width(6) grid.to_edge(LEFT) freq_line = get_freq_line() freq_line.scale_to_fit_width(6) freq_line.center().to_edge(RIGHT) arrow = Arrow(grid, freq_line) color1, color2 = YELLOW_C, RED square_length = 0.01 dot1 = Dot(color = color1) dot1.shift(3*RIGHT) dot2 = Dot(color = color2) dot2.shift(3.1*RIGHT) arrow1 = Arrow(2*RIGHT+UP, dot1, color = color1, buff = 0.1) arrow2 = Arrow(4*RIGHT+UP, dot2, color = color2, buff = 0.1) dot3, arrow3 = [ mob.copy().shift(5*LEFT+UP) for mob in dot1, arrow1 ] dot4, arrow4 = [ mob.copy().shift(5*LEFT+0.9*UP) for mob in dot2, arrow2 ] self.add(grid, freq_line, arrow) self.dither() self.play(ApplyMethod( arrow.rotate, np.pi, path_func = clockwise_path() )) self.dither() self.play(ShowCreation(arrow1)) self.add(dot1) self.play(ShowCreation(arrow2)) self.add(dot2) self.dither() self.remove(arrow1, arrow2) self.play( Transform(dot1, dot3), Transform(dot2, dot4) ) self.play( ApplyMethod(grid.fade, 0.8), Animation(Mobject(dot3, dot4)) ) self.play(ShowCreation(arrow3)) self.play(ShowCreation(arrow4)) self.dither()
def get_dot_template(self, place): #This should be replaced for non-base-10 counting scenes down_right = (0.5) * RIGHT + (np.sqrt(3) / 2) * DOWN dots = VGroup(*[ Dot( point, radius=0.25, fill_opacity=0, stroke_width=2, stroke_color=WHITE, ) for point in self.get_template_configuration(place) ]) dots.scale_to_fit_height(self.dot_configuration_height) return dots
def __init__(self, mobject_or_point, **kwargs): digest_config(self, kwargs) big_dot = Dot( radius=SPACE_WIDTH + SPACE_HEIGHT, stroke_width=0, fill_color=self.color, fill_opacity=0, ) little_dot = Dot(radius=0) little_dot.set_fill(self.color, opacity=self.opacity) little_dot.move_to(mobject_or_point) Transform.__init__(self, big_dot, little_dot, **kwargs)
def __init__(self, mobject_or_point, **kwargs): digest_config(self, kwargs) big_dot = Dot( radius = FRAME_X_RADIUS+FRAME_Y_RADIUS, stroke_width = 0, fill_color = self.color, fill_opacity = 0, ) little_dot = Dot(radius = 0) little_dot.set_fill(self.color, opacity = self.opacity) little_dot.move_to(mobject_or_point) Transform.__init__(self, big_dot, little_dot, **kwargs)
def construct(self): start_words = TextMobject([ "``", "Space Filling", "Curve ''", ]).to_edge(TOP, buff = 0.25) quote, space_filling, curve_quote = start_words.copy().split() curve_quote.shift( space_filling.get_left()-\ curve_quote.get_left() ) space_filling = Point(space_filling.get_center()) end_words = Mobject(*[ quote, space_filling, curve_quote ]).center().to_edge(TOP, buff = 0.25) space_filling_fractal = TextMobject(""" ``Space Filling Fractal'' """).to_edge(UP) curve = HilbertCurve(order = 2).shift(DOWN) fine_curve = HilbertCurve(order = 8) fine_curve.replace(curve) dots = Mobject(*[ Dot( curve.points[n*curve.get_num_points()/15], color = YELLOW_C ) for n in range(1, 15) if n not in [4, 11] ]) start_words.shift(2*(UP+LEFT)) self.play( ApplyMethod(start_words.shift, 2*(DOWN+RIGHT)) ) self.wait() self.play(Transform(start_words, end_words)) self.wait() self.play(ShowCreation(curve)) self.wait() self.play(ShowCreation( dots, run_time = 3, )) self.wait() self.clear() self.play(ShowCreation(fine_curve, run_time = 5)) self.wait() self.play(ShimmerIn(space_filling_fractal)) self.wait()
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(SPACE_WIDTH + abs(vector[0])) y_max = int(SPACE_HEIGHT + 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 construct(self): overtones = 5 floor = 2 * DOWN main_string = Vibrate(color=BLUE_D) component_strings = [ Vibrate(num_periods=k + 1, overtones=1, color=color, center=2 * DOWN + UP * k) for k, color in zip(range(overtones), Color(BLUE_E).range_to(WHITE, overtones)) ] dots = [ Dot(string.mobject.get_center(), color=string.mobject.get_color()) for string in component_strings ] freq_line = get_freq_line() freq_line.shift(floor) freq_line.sort_points(np.linalg.norm) brace = Brace(freq_line, UP) words = TextMobject("Range of frequency values") words.next_to(brace, UP) self.play(*[ TransformAnimations(main_string.copy(), string, run_time=5) for string in component_strings ]) self.clear() self.play(*[ TransformAnimations(string, Animation(dot)) for string, dot in zip(component_strings, dots) ]) self.clear() self.play( ShowCreation(freq_line), GrowFromCenter(brace), ShimmerIn(words), *[ Transform(dot, dot.copy().scale(2).rotate(-np.pi / 2).shift(floor), path_func=path_along_arc(np.pi / 3)) for dot in dots ]) self.dither(0.5)
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
def construct(self): big_grid_dim = 20. small_grid_dim = 6. big_grid = Grid(64, 64, height = big_grid_dim, width = big_grid_dim) big_grid.to_corner(UP+RIGHT, buff = 2) small_grid = big_grid.copy() small_grid.scale(small_grid_dim/big_grid_dim) small_grid.center() pixel = MobjectFromRegion( region_from_polygon_vertices(*0.2*np.array([ RIGHT+DOWN, RIGHT+UP, LEFT+UP, LEFT+DOWN ])) ) pixel.set_color(WHITE) pixel_width = big_grid.width/big_grid.columns pixel.scale_to_fit_width(pixel_width) pixel.to_corner(UP+RIGHT, buff = 2) pixel.shift(5*pixel_width*(2*LEFT+DOWN)) freq_line = get_freq_line() dot = Dot() dot.shift(freq_line.get_center() + 2*RIGHT) string = Line(LEFT, RIGHT, color = GREEN) arrow = Arrow(dot, string.get_center()) vibration_config = { "overtones" : 1, "spatial_period" : 2, } vibration, loud_vibration, quiet_vibration = [ Vibrate(string.copy(), amplitude = a, **vibration_config) for a in [0.5, 1., 0.25] ] self.add(small_grid) self.dither() self.play( Transform(small_grid, big_grid) ) self.play(FadeIn(pixel)) self.dither() self.play( FadeOut(small_grid), ShowCreation(freq_line) ) self.remove(small_grid) self.play( Transform(pixel, dot), ) self.dither() self.play(ShowCreation(arrow)) self.play(loud_vibration) self.play( TransformAnimations(loud_vibration, quiet_vibration), ApplyMethod(dot.fade, 0.9) ) self.clear() self.add(freq_line, dot, arrow) self.play(quiet_vibration)
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