from mobject import Mobject, Point, Mobject1D from mobject.tex_mobject import \ TexMobject, TextMobject, Brace from mobject.image_mobject import \ ImageMobject, MobjectFromRegion from scene import Scene from animation import Animation from animation.transform import \ Transform, CounterclockwiseTransform, ApplyMethod,\ GrowFromCenter, ClockwiseTransform, ApplyPointwiseFunction, \ ShrinkToCenter from animation.simple_animations import \ ShowCreation, ShimmerIn, FadeOut, FadeIn from animation.meta_animations import \ DelayByOrder, TransformAnimations from animation.playground import Vibrate from topics.geometry import \ Line, Dot, Arrow, Grid, Square, Point from topics.characters import \ ThoughtBubble, SpeechBubble, Mathematician from topics.number_line import UnitInterval, NumberLine from topics.three_dimensions import Stars from region import region_from_polygon_vertices, Region import displayer as disp from hilbert.curves import \ TransformOverIncreasingOrders, FlowSnake, HilbertCurve, \ SnakeCurve, PeanoCurve from hilbert.section1 import get_mathy_and_bubble from scipy.spatial.distance import cdist from helpers import * def get_time_line(): length = 5.2*SPACE_WIDTH year_range = 400 time_line = NumberLine( numerical_radius = year_range/2, unit_length_to_spatial_width = length/year_range, tick_frequency = 10, leftmost_tick = 1720, number_at_center = 1870, numbers_with_elongated_ticks = range(1700, 2100, 100) ) time_line.sort_points(lambda p : p[0]) time_line.gradient_highlight( PeanoCurve.DEFAULT_CONFIG["start_color"], PeanoCurve.DEFAULT_CONFIG["end_color"] ) time_line.add_numbers( 2020, *range(1800, 2050, 50) ) return time_line class SectionTwo(Scene): def construct(self): self.add(TextMobject("Section 2: Filling space")) self.dither() class HilbertCurveIsPerfect(Scene): def construct(self): curve = HilbertCurve(order = 6) curve.highlight(WHITE) colored_curve = curve.copy() colored_curve.thin_out(3) lion = ImageMobject("lion", invert = False) lion.replace(curve, stretch = True) sparce_lion = lion.copy() sparce_lion.thin_out(100) distance_matrix = cdist(colored_curve.points, sparce_lion.points) closest_point_indices = np.apply_along_axis( np.argmin, 1, distance_matrix ) colored_curve.rgbs = sparce_lion.rgbs[closest_point_indices] line = Line(5*LEFT, 5*RIGHT) Mobject.align_data(line, colored_curve) line.rgbs = colored_curve.rgbs self.add(lion) self.play(ShowCreation(curve, run_time = 3)) self.play( FadeOut(lion), Transform(curve, colored_curve), run_time = 3 ) self.dither() self.play(Transform(curve, line, run_time = 5)) self.dither() class AskMathematicianFriend(Scene): def construct(self): mathy, bubble = get_mathy_and_bubble() bubble.sort_points(lambda p : np.dot(p, UP+RIGHT)) self.add(mathy) self.dither() self.play(ApplyMethod( mathy.blink, rate_func = squish_rate_func(there_and_back) )) self.dither() self.play(ShowCreation(bubble)) self.dither() self.play( ApplyMethod(mathy.shift, 3*(DOWN+LEFT)), ApplyPointwiseFunction( lambda p : 15*p/np.linalg.norm(p), bubble ), run_time = 3 ) class TimeLineAboutSpaceFilling(Scene): def construct(self): curve = PeanoCurve(order = 5) curve.stretch_to_fit_width(2*SPACE_WIDTH) curve.stretch_to_fit_height(2*SPACE_HEIGHT) curve_start = curve.copy() curve_start.apply_over_attr_arrays( lambda arr : arr[:200] ) time_line = get_time_line() time_line.shift(-time_line.number_to_point(2000)) self.add(time_line) self.play(ApplyMethod( time_line.shift, -time_line.number_to_point(1900), run_time = 3 )) brace = Brace( Mobject( Point(time_line.number_to_point(1865)), Point(time_line.number_to_point(1888)), ), UP ) words = TextMobject(""" Cantor drives himself (and the \\\\ mathematical community at large) \\\\ crazy with research on infinity. """) words.next_to(brace, UP) self.play( GrowFromCenter(brace), ShimmerIn(words) ) self.dither() self.play( Transform(time_line, curve_start), FadeOut(brace), FadeOut(words) ) self.play(ShowCreation( curve, run_time = 5, rate_func = None )) self.dither() class NotPixelatedSpace(Scene): def construct(self): grid = Grid(64, 64) space_region = Region() space_mobject = MobjectFromRegion(space_region, DARK_GREY) curve = PeanoCurve(order = 5).replace(space_mobject) line = Line(5*LEFT, 5*RIGHT) line.gradient_highlight(curve.start_color, curve.end_color) for mob in grid, space_mobject: mob.sort_points(np.linalg.norm) infinitely = TextMobject("Infinitely") detailed = TextMobject("detailed") extending = TextMobject("extending") detailed.next_to(infinitely, RIGHT) extending.next_to(infinitely, RIGHT) Mobject(extending, infinitely, detailed).center() arrows = Mobject(*[ Arrow(2*p, 4*p) for theta in np.arange(np.pi/6, 2*np.pi, np.pi/3) for p in [rotate_vector(RIGHT, theta)] ]) self.add(grid) self.dither() self.play(Transform(grid, space_mobject, run_time = 5)) self.remove(grid) self.highlight_region(space_region, DARK_GREY) self.dither() self.add(infinitely, detailed) self.dither() self.play(DelayByOrder(Transform(detailed, extending))) self.play(ShowCreation(arrows)) self.dither() self.clear() self.highlight_region(space_region, DARK_GREY) self.play(ShowCreation(line)) self.play(Transform(line, curve, run_time = 5)) class HistoryOfDiscover(Scene): def construct(self): time_line = get_time_line() time_line.shift(-time_line.number_to_point(1900)) hilbert_curve = HilbertCurve(order = 3) peano_curve = PeanoCurve(order = 2) for curve in hilbert_curve, peano_curve: curve.scale(0.5) hilbert_curve.to_corner(DOWN+RIGHT) peano_curve.to_corner(UP+LEFT) squares = Mobject(*[ Square(side_length=3, color=WHITE).replace(curve) for curve in hilbert_curve, peano_curve ]) self.add(time_line) self.dither() for year, curve, vect, text in [ (1890, peano_curve, UP, "Peano Curve"), (1891, hilbert_curve, DOWN, "Hilbert Curve"), ]: point = time_line.number_to_point(year) point[1] = 0.2 arrow = Arrow(point+2*vect, point, buff = 0.1) arrow.gradient_highlight(curve.start_color, curve.end_color) year_mob = TexMobject(str(year)) year_mob.next_to(arrow, vect) words = TextMobject(text) words.next_to(year_mob, vect) self.play( ShowCreation(arrow), ShimmerIn(year_mob), ShimmerIn(words) ) self.play(ShowCreation(curve)) self.dither() self.play(ShowCreation(squares)) self.dither() self.play(ApplyMethod( Mobject(*self.mobjects).shift, 20*(DOWN+RIGHT) )) class DefinitionOfCurve(Scene): 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.dither() self.play(Transform(start_words, end_words)) self.dither() self.play(ShowCreation(curve)) self.dither() self.play(ShowCreation( dots, run_time = 3, )) self.dither() self.clear() self.play(ShowCreation(fine_curve, run_time = 5)) self.dither() self.play(ShimmerIn(space_filling_fractal)) self.dither() class PseudoHilbertCurvesDontFillSpace(Scene): def construct(self): curve = HilbertCurve(order = 1) grid = Grid(2, 2, point_thickness=1) self.add(grid, curve) for order in range(2, 6): self.dither() new_grid = Grid(2**order, 2**order, point_thickness=1) self.play( ShowCreation(new_grid), Animation(curve) ) self.remove(grid) grid = new_grid self.play(Transform( curve, HilbertCurve(order = order) )) square = Square(side_length = 6, color = WHITE) square.corner = Mobject1D() square.corner.add_line(3*DOWN, ORIGIN) square.corner.add_line(ORIGIN, 3*RIGHT) square.digest_mobject_attrs() square.scale(2**(-5)) square.corner.highlight( Color(rgb = curve.rgbs[curve.get_num_points()/3]) ) square.shift( grid.get_corner(UP+LEFT)-\ square.get_corner(UP+LEFT) ) self.dither() self.play( FadeOut(grid), FadeOut(curve), FadeIn(square) ) self.play( ApplyMethod(square.replace, grid) ) self.dither() class HilbertCurveIsLimit(Scene): def construct(self): mathy, bubble = get_mathy_and_bubble() bubble.write( "A Hilbert curve is the \\\\ limit of all these \\dots" ) self.add(mathy, bubble) self.play(ShimmerIn(bubble.content)) self.dither() class DefiningCurves(Scene): def construct(self): words = TextMobject( ["One does not simply define the limit \\\\ \ of a sequence of","curves","\\dots"] ) top_words = TextMobject([ "curves", "are functions" ]).to_edge(UP) curves1 = words.split()[1] curves2 = top_words.split()[0] words.ingest_sub_mobjects() number = TexMobject("0.27") pair = TexMobject("(0.53, 0.02)") pair.next_to(number, buff = 2) arrow = Arrow(number, pair) Mobject(number, arrow, pair).center().shift(UP) number_line = UnitInterval() number_line.stretch_to_fit_width(5) number_line.to_edge(LEFT).shift(DOWN) grid = Grid(4, 4).scale(0.4) grid.next_to(number_line, buff = 2) low_arrow = Arrow(number_line, grid) self.play(ShimmerIn(words)) self.dither() self.play( FadeOut(words), ApplyMethod(curves1.replace, curves2), ShimmerIn(top_words.split()[1]) ) self.dither() self.play(FadeIn(number)) self.play(ShowCreation(arrow)) self.play(FadeIn(pair)) self.dither() self.play(ShowCreation(number_line)) self.play(ShowCreation(low_arrow)) self.play(ShowCreation(grid)) self.dither() class PseudoHilbertCurveAsFunctionExample(Scene): args_list = [(2,), (3,)] # For subclasses to turn args in the above # list into stings which can be appended to the name @staticmethod def args_to_string(order): return "Order%d"%order @staticmethod def string_to_args(order_str): return int(order_str) 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.dither() self.remove(function_arrow, function) self.play(ShowCreation(line)) self.dither() self.play( ShimmerIn(arg), ShowCreation(arrow1), ShowCreation(dot1) ) self.dither() self.remove(arrow1) self.play( FadeIn(grid), Transform(line, curve), Transform(dot1, dot2), run_time = 2 ) self.dither() self.play( ShimmerIn(result), ShowCreation(arrow2) ) self.dither() class ContinuityRequired(Scene): def construct(self): words = TextMobject([ "A function must be", "\\emph{continuous}", "if it is to represent a curve." ]) words.split()[1].highlight(YELLOW_C) self.add(words) self.dither() class FormalDefinitionOfContinuity(Scene): def construct(self): self.play(ShimmerIn(TextMobject(" ".join([ "$f : A \\to B$ is continuous if: \\\\ \n\n", "$\\forall x \\in A$,", "$\\forall \\epsilon > 0$,", "$\\exists \\delta > 0$ such that", "$|f(y) - f(x)| < \\epsilon$", "for all $y \\in A$ satisfying $|x-y|<\\delta$.", ])))) self.dither()