From 9705f03c15192367c0c40f21f5a63dddb70b760f Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Tue, 26 Jan 2016 10:22:29 -0800 Subject: [PATCH] Moved Hilbert project out of main directory --- hilbert/__init__.py | 0 hilbert/fractal_porn.py | 347 ------- hilbert/section1.py | 1089 ---------------------- hilbert/section2.py | 1095 ----------------------- hilbert/section3.py | 310 ------- hilbert/curves.py => topics/fractals.py | 0 6 files changed, 2841 deletions(-) delete mode 100644 hilbert/__init__.py delete mode 100644 hilbert/fractal_porn.py delete mode 100644 hilbert/section1.py delete mode 100644 hilbert/section2.py delete mode 100644 hilbert/section3.py rename hilbert/curves.py => topics/fractals.py (100%) diff --git a/hilbert/__init__.py b/hilbert/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/hilbert/fractal_porn.py b/hilbert/fractal_porn.py deleted file mode 100644 index ee9c27be..00000000 --- a/hilbert/fractal_porn.py +++ /dev/null @@ -1,347 +0,0 @@ -from mobject import Mobject, Point, Mobject1D -from scene import Scene -from animation.transform import \ - Transform, ShimmerIn, FadeIn, FadeOut, ApplyMethod -from animation.simple_animations import \ - ShowCreation, DelayByOrder -from topics.geometry import Line, Arc, Arrow -from mobject.tex_mobject import TexMobject, TextMobject - -from helpers import * -from hilbert.curves import * - -class Intro(TransformOverIncreasingOrders): - @staticmethod - def args_to_string(*args): - return "" - - @staticmethod - def string_to_args(string): - raise Exception("string_to_args Not Implemented!") - - def construct(self): - words1 = TextMobject( - "If you watched my video about Hilbert's space-filling curve\\dots" - ) - words2 = TextMobject( - "\\dots you might be curious to see what a few other space-filling curves look like." - ) - words2.scale(0.8) - for words in words1, words2: - words.to_edge(UP, buff = 0.2) - - self.setup(HilbertCurve) - self.play(ShimmerIn(words1)) - for x in range(4): - self.increase_order() - self.remove(words1) - self.increase_order( - ShimmerIn(words2) - ) - for x in range(4): - self.increase_order() - - - -class BringInPeano(Intro): - def construct(self): - words1 = TextMobject(""" - For each one, see if you can figure out what - the pattern of construction is. - """) - words2 = TextMobject(""" - This one is the Peano curve. - """) - words3 = TextMobject(""" - It is the original space-filling curve. - """) - self.setup(PeanoCurve) - self.play(ShimmerIn(words1)) - self.dither(5) - self.remove(words1) - self.add(words2.to_edge(UP)) - for x in range(3): - self.increase_order() - self.remove(words2) - self.increase_order(ShimmerIn(words3.to_edge(UP))) - for x in range(2): - self.increase_order() - - -class FillOtherShapes(Intro): - def construct(self): - words1 = TextMobject(""" - But of course, there's no reason we should limit - ourselves to filling in squares. - """) - words2 = TextMobject(""" - Here's a simple triangle-filling curve I defined - in a style reflective of a Hilbert curve. - """) - words1.to_edge(UP) - words2.scale(0.8).to_edge(UP, buff = 0.2) - - self.setup(TriangleFillingCurve) - self.play(ShimmerIn(words1)) - for x in range(3): - self.increase_order() - self.remove(words1) - self.add(words2) - for x in range(5): - self.increase_order() - -class SmallerFlowSnake(FlowSnake): - DEFAULT_CONFIG = { - "radius" : 4 - } - -class MostDelightfulName(Intro): - def construct(self): - words1 = TextMobject(""" - This one has the most delightful name, - thanks to mathematician/programmer Bill Gosper: - """) - words2 = TextMobject("``Flow Snake''") - words3 = TextMobject(""" - What makes this one particularly interesting - is that the boundary itself is a fractal. - """) - for words in words1, words2, words3: - words.to_edge(UP) - - self.setup(SmallerFlowSnake) - self.play(ShimmerIn(words1)) - for x in range(3): - self.increase_order() - self.remove(words1) - self.add(words2) - for x in range(3): - self.increase_order() - self.remove(words2) - self.play(ShimmerIn(words3)) - - - -class SurpriseFractal(Intro): - def construct(self): - words = TextMobject(""" - It might come as a surprise how some well-known - fractals can be described with curves. - """) - words.to_edge(UP) - - self.setup(Sierpinski) - self.add(TextMobject("Speaking of other fractals\\dots")) - self.dither(3) - self.clear() - self.play(ShimmerIn(words)) - for x in range(9): - self.increase_order() - - -class IntroduceKoch(Intro): - def construct(self): - words = map(TextMobject, [ - "This is another famous fractal.", - "The ``Koch Snowflake''", - "Let's finish things off by seeing how to turn \ - this into a space-filling curve" - ]) - for text in words: - text.to_edge(UP) - - self.setup(KochCurve) - self.add(words[0]) - for x in range(3): - self.increase_order() - self.remove(words[0]) - self.add(words[1]) - for x in range(4): - self.increase_order() - self.remove(words[1]) - self.add(words[2]) - self.dither(6) - -class StraightKoch(KochCurve): - DEFAULT_CONFIG = { - "axiom" : "A" - } - -class SharperKoch(StraightKoch): - DEFAULT_CONFIG = { - "angle" : 0.9*np.pi/2, - } - -class DullerKoch(StraightKoch): - DEFAULT_CONFIG = { - "angle" : np.pi/6, - } - -class SpaceFillingKoch(StraightKoch): - DEFAULT_CONFIG = { - "angle" : np.pi/2, - } - - - -class FromKochToSpaceFilling(Scene): - def construct(self): - self.max_order = 7 - - self.revisit_koch() - self.show_angles() - self.show_change_side_by_side() - - - def revisit_koch(self): - words = map(TextMobject, [ - "First, look at how one section of this curve is made.", - "This pattern of four lines is the ``seed''", - "With each iteration, every straight line is \ - replaced with an appropriately small copy of the seed", - ]) - for text in words: - text.to_edge(UP) - - self.add(words[0]) - curve = StraightKoch(order = self.max_order) - self.play(Transform( - curve, - StraightKoch(order = 1), - run_time = 5 - )) - self.remove(words[0]) - self.add(words[1]) - self.dither(4) - self.remove(words[1]) - self.add(words[2]) - self.dither(3) - for order in range(2, self.max_order): - self.play(Transform( - curve, - StraightKoch(order = order) - )) - if order == 2: - self.dither(2) - elif order == 3: - self.dither() - self.clear() - - - - def show_angles(self): - words = TextMobject(""" - Let's see what happens as we change - the angle in this seed - """) - words.to_edge(UP) - koch, sharper_koch, duller_koch = curves = [ - CurveClass(order = 1) - for CurveClass in StraightKoch, SharperKoch, DullerKoch - ] - arcs = [ - Arc( - 2*(np.pi/2 - curve.angle), - radius = r, - start_angle = np.pi+curve.angle - ).shift(curve.points[curve.get_num_points()/2]) - for curve, r in zip(curves, [0.6, 0.7, 0.4]) - ] - theta = TexMobject("\\theta") - theta.shift(arcs[0].get_center()+2.5*DOWN) - arrow = Arrow(theta, arcs[0]) - - self.add(words, koch) - self.play(ShowCreation(arcs[0])) - self.play( - ShowCreation(arrow), - ShimmerIn(theta) - ) - self.dither(2) - self.remove(theta, arrow) - self.play( - Transform(koch, duller_koch), - Transform(arcs[0], arcs[2]), - ) - self.play( - Transform(koch, sharper_koch), - Transform(arcs[0], arcs[1]), - ) - self.clear() - - def show_change_side_by_side(self): - - seed = TextMobject("Seed") - seed.shift(3*LEFT+2*DOWN) - fractal = TextMobject("Fractal") - fractal.shift(3*RIGHT+2*DOWN) - words = map(TextMobject, [ - "A sharper angle results in a richer curve", - "A more obtuse angle gives a sparser curve", - "And as the angle approaches 0\\dots", - "We have a new space-filling curve." - ]) - for text in words: - text.to_edge(UP) - sharper, duller, space_filling = [ - CurveClass(order = 1).shift(3*LEFT) - for CurveClass in SharperKoch, DullerKoch, SpaceFillingKoch - ] - shaper_f, duller_f, space_filling_f = [ - CurveClass(order = self.max_order).shift(3*RIGHT) - for CurveClass in SharperKoch, DullerKoch, SpaceFillingKoch - ] - - self.add(words[0]) - left_curve = SharperKoch(order = 1) - right_curve = SharperKoch(order = 1) - self.play( - Transform(left_curve, sharper), - ApplyMethod(right_curve.shift, 3*RIGHT), - ) - self.play( - Transform( - right_curve, - SharperKoch(order = 2).shift(3*RIGHT) - ), - ShimmerIn(seed), - ShimmerIn(fractal) - ) - for order in range(3, self.max_order): - self.play(Transform( - right_curve, - SharperKoch(order = order).shift(3*RIGHT) - )) - self.remove(words[0]) - self.add(words[1]) - kwargs = { - "run_time" : 4, - } - self.play( - Transform(left_curve, duller, **kwargs), - Transform(right_curve, duller_f, **kwargs) - ) - self.dither() - kwargs["run_time"] = 7 - kwargs["rate_func"] = None - self.remove(words[1]) - self.add(words[2]) - self.play( - Transform(left_curve, space_filling, **kwargs), - Transform(right_curve, space_filling_f, **kwargs) - ) - self.remove(words[2]) - self.add(words[3]) - self.dither() - - - - - - - - - - - - diff --git a/hilbert/section1.py b/hilbert/section1.py deleted file mode 100644 index 0f1244c1..00000000 --- a/hilbert/section1.py +++ /dev/null @@ -1,1089 +0,0 @@ -from mobject import Mobject, Point -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,\ - TransformAnimations, ShimmerIn, FadeOut, FadeIn -from animation.simple_animations import \ - ShowCreation, DelayByOrder -from animation.playground import Vibrate - -from topics.geometry import \ - Line, Dot, Arrow, Grid, Square, Point -from topics.characters import \ - ThoughtBubble, SpeechBubble, Mathematician, Randolph -from topics.number_line import UnitInterval -from topics.three_dimensions import Stars - -from region import region_from_polygon_vertices - -import displayer as disp - -from hilbert.curves import \ - TransformOverIncreasingOrders, FlowSnake, HilbertCurve, \ - SnakeCurve - - -from helpers import * - - - -def get_grid(): - return Grid(64, 64) - -def get_freq_line(): - return UnitInterval().shift(2*DOWN) ##Change? - -def get_mathy_and_bubble(): - mathy = Mathematician() - mathy.to_edge(DOWN).shift(4*LEFT) - bubble = SpeechBubble(initial_width = 8) - bubble.pin_to(mathy) - return mathy, bubble - -class AboutSpaceFillingCurves(TransformOverIncreasingOrders): - @staticmethod - def args_to_string(): - return "" - - @staticmethod - def string_to_args(arg_str): - return () - - def construct(self): - self.bubble = ThoughtBubble().ingest_sub_mobjects() - self.bubble.scale(1.5) - - TransformOverIncreasingOrders.construct(self, FlowSnake, 7) - self.play(Transform(self.curve, self.bubble)) - self.show_infinite_objects() - self.pose_question() - self.dither() - - def show_infinite_objects(self): - sigma, summand, equals, result = TexMobject([ - "\\sum_{n = 1}^{\\infty}", - "\\dfrac{1}{n^2}", - "=", - "\\dfrac{\pi^2}{6}" - ]).split() - alt_summand = TexMobject("n").replace(summand) - alt_result = TexMobject("-\\dfrac{1}{12}").replace(result) - - rationals, other_equals, naturals = TexMobject([ - "|\\mathds{Q}|", - "=", - "|\\mathds{N}|" - ]).scale(2).split() - infinity = TexMobject("\\infty").scale(2) - local_mobjects = filter( - lambda m : isinstance(m, Mobject), - locals().values(), - ) - for mob in local_mobjects: - mob.sort_points(np.linalg.norm) - - self.play(ShimmerIn(infinity)) - self.dither() - self.play( - ShimmerIn(summand), - ShimmerIn(equals), - ShimmerIn(result), - DelayByOrder(Transform(infinity, sigma)) - ) - self.dither() - self.play( - Transform(summand, alt_summand), - Transform(result, alt_result), - ) - self.dither() - self.remove(infinity) - self.play(*[ - CounterclockwiseTransform( - Mobject(summand, equals, result, sigma), - Mobject(rationals, other_equals, naturals) - ) - ]) - self.dither() - self.clear() - self.add(self.bubble) - - def pose_question(self): - infinity, rightarrow, N = TexMobject([ - "\\infty", "\\rightarrow", "N" - ]).scale(2).split() - question_mark = TextMobject("?").scale(2) - - self.add(question_mark) - self.dither() - self.play(*[ - ShimmerIn(mob) - for mob in infinity, rightarrow, N - ] + [ - ApplyMethod(question_mark.next_to, rightarrow, UP), - ]) - self.dither() - - - -class PostponePhilosophizing(Scene): - def construct(self): - abstract, arrow, concrete = TextMobject([ - "Abstract", " $\\rightarrow$ ", "Concrete" - ]).scale(2).split() - - self.add(abstract, arrow, concrete) - self.dither() - self.play(*[ - ApplyMethod( - word1.replace, word2, - path_func = path_along_arc(np.pi/2) - ) - for word1, word2 in it.permutations([abstract, concrete]) - ]) - self.dither() - - -class GrowHilbertWithName(Scene): - def construct(self): - curve = HilbertCurve(order = 1) - words = TextMobject("``Hilbert Curve''") - words.to_edge(UP, buff = 0.2) - self.play( - ShimmerIn(words), - Transform(curve, HilbertCurve(order = 2)), - run_time = 2 - ) - for n in range(3, 8): - self.play( - Transform(curve, HilbertCurve(order = n)), - run_time = 5. /n - ) - - -class SectionOne(Scene): - def construct(self): - self.add(TextMobject("Section 1: Seeing with your ears")) - self.dither() - -class WriteSomeSoftware(Scene): - pass #Done viea screen capture, written here for organization - - - -class ImageToSound(Scene): - def construct(self): - string = Vibrate(color = BLUE_D, run_time = 5) - picture = ImageMobject("lion", invert = False) - picture.scale(0.8) - picture_copy = picture.copy() - picture.sort_points(np.linalg.norm) - string.mobject.sort_points(lambda p : -np.linalg.norm(p)) - - self.add(picture) - self.dither() - self.play(Transform( - picture, string.mobject, - run_time = 3, - rate_func = rush_into - )) - self.remove(picture) - self.play(string) - - for mob in picture_copy, string.mobject: - mob.sort_points(lambda p : np.linalg.norm(p)%1) - - self.play(Transform( - string.mobject, picture_copy, - run_time = 5, - rate_func = rush_from - )) - -class LinksInDescription(Scene): - def construct(self): - text = TextMobject(""" - See links in the description for more on - sight via sound. - """) - self.play(ShimmerIn(text)) - self.play(ShowCreation(Arrow(text, 3*DOWN))) - self.dither(2) - - -class ImageDataIsTwoDimensional(Scene): - def construct(self): - image = ImageMobject("lion", invert = False) - image.scale(0.5) - image.shift(2*LEFT) - - self.add(image) - for vect, num in zip([DOWN, RIGHT], [1, 2]): - brace = Brace(image, vect) - words_mob = TextMobject("Dimension %d"%num) - words_mob.next_to(image, vect, buff = 1) - self.play( - Transform(Point(brace.get_center()), brace), - ShimmerIn(words_mob), - run_time = 2 - ) - self.dither() - - -class SoundDataIsOneDimensional(Scene): - 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 GridOfPixels(Scene): - def construct(self): - low_res = ImageMobject("low_resolution_lion", invert = False) - high_res = ImageMobject("Lion", invert = False) - grid = get_grid().scale(0.8) - for mob in low_res, high_res: - mob.replace(grid, stretch = True) - side_brace = Brace(low_res, LEFT) - top_brace = Brace(low_res, UP) - top_words = TextMobject("256 Px", size = "\\normal") - side_words = top_words.copy().rotate(np.pi/2) - top_words.next_to(top_brace, UP) - side_words.next_to(side_brace, LEFT) - - self.add(high_res) - self.dither() - self.play(DelayByOrder(Transform(high_res, low_res))) - self.dither() - self.play( - GrowFromCenter(top_brace), - GrowFromCenter(side_brace), - ShimmerIn(top_words), - ShimmerIn(side_words) - ) - self.dither() - for mob in grid, high_res: - mob.sort_points(np.linalg.norm) - self.play(DelayByOrder(Transform(high_res, grid))) - self.dither() - - -class ShowFrequencySpace(Scene): - def construct(self): - freq_line = get_freq_line() - - self.add(freq_line) - self.dither() - for tex, vect in zip(["20 Hz", "20{,}000 Hz"], [LEFT, RIGHT]): - tex_mob = TextMobject(tex) - tex_mob.to_edge(vect) - tex_mob.shift(UP) - arrow = Arrow(tex_mob, freq_line.get_edge_center(vect)) - self.play( - ShimmerIn(tex_mob), - ShowCreation(arrow) - ) - self.dither() - - - -class AssociatePixelWithFrequency(Scene): - 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 ListenToAllPixels(Scene): - def construct(self): - grid = get_grid() - grid.sort_points(np.linalg.norm) - freq_line = get_freq_line() - freq_line.sort_points(lambda p : p[0]) - red, blue = Color(RED), Color(BLUE) - freq_line.gradient_highlight(red, blue) - - colors = [ - Color(rgb = interpolate( - np.array(red.rgb), - np.array(blue.rgb), - alpha - )) - for alpha in np.arange(4)/3. - ] - string = Line(3*LEFT, 3*RIGHT, color = colors[1]) - vibration = Vibrate(string) - vibration_copy = vibration.copy() - vibration_copy.mobject.point_thickness = 1 - sub_vibrations = [ - Vibrate( - string.copy().shift((n-1)*UP).highlight(colors[n]), - overtones = 1, - spatial_period = 6./(n+1), - temporal_period = 1./(n+1), - amplitude = 0.5/(n+1) - ) - for n in range(4) - ] - words = TexMobject("&\\vdots \\\\ \\text{thousands }& \\text{of frequencies} \\\\ &\\vdots") - words.to_edge(UP, buff = 0.1) - - self.add(grid) - self.dither() - self.play(DelayByOrder(ApplyMethod( - grid.gradient_highlight, red, blue - ))) - self.play(Transform(grid, freq_line)) - self.dither() - self.play( - ShimmerIn( - words, - rate_func = squish_rate_func(smooth, 0, 0.2) - ), - *sub_vibrations, - run_time = 5 - ) - self.play( - *[ - TransformAnimations( - sub_vib, vibration - ) - for sub_vib in sub_vibrations - ]+[FadeOut(words)] - ) - self.clear() - self.add(freq_line) - self.play(vibration) - - -class LayAsideSpeculation(Scene): - def construct(self): - words = TextMobject("Would this actually work?") - 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) - mapping = Mobject( - grid, freq_line, Arrow(grid, freq_line) - ) - mapping.ingest_sub_mobjects() - lower_left = Point().to_corner(DOWN+LEFT, buff = 0) - lower_right = Point().to_corner(DOWN+RIGHT, buff = 0) - - self.add(words) - self.dither() - self.play( - Transform(words, lower_right), - Transform(lower_left, mapping) - ) - self.dither() - - -class RandomMapping(Scene): - 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) - # for mob in grid, freq_line: - # indices = np.arange(mob.get_num_points()) - # random.shuffle(indices) - # mob.points = mob.points[indices] - stars = Stars(point_thickness = grid.point_thickness) - - self.add(grid) - targets = [stars, freq_line] - alphas = [not_quite_there(rush_into), rush_from] - for target, rate_func in zip(targets, alphas): - self.play(Transform( - grid, target, - run_time = 3, - rate_func = rate_func, - path_func = path_along_arc(-np.pi/2) - )) - self.dither() - - - -class DataScrambledAnyway(Scene): - def construct(self): - self.add(TextMobject("Data is scrambled anyway, right?")) - self.dither() - - -class LeverageExistingIntuitions(Scene): - def construct(self): - self.add(TextMobject("Leverage existing intuitions")) - self.dither() - - - - -class ThinkInTermsOfReverseMapping(Scene): - 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() - - -class WeaveLineThroughPixels(Scene): - @staticmethod - def args_to_string(order): - return str(order) - - @staticmethod - def string_to_args(order_str): - return int(order_str) - - def construct(self, order): - start_color, end_color = RED, GREEN - curve = HilbertCurve(order = order) - line = Line(5*LEFT, 5*RIGHT) - for mob in curve, line: - mob.gradient_highlight(start_color, end_color) - freq_line = get_freq_line() - freq_line.replace(line, stretch = True) - - unit = 6./(2**order) #sidelength of pixel - up = unit*UP - right = unit*RIGHT - lower_left = 3*(LEFT+DOWN) - squares = Mobject(*[ - Square( - side_length = unit, - color = WHITE - ).shift(x*right+y*up) - for x, y in it.product(range(2**order), range(2**order)) - ]) - squares.center() - targets = Mobject() - for square in squares.sub_mobjects: - center = square.get_center() - distances = np.apply_along_axis( - lambda p : np.linalg.norm(p-center), - 1, - curve.points - ) - index_along_curve = np.argmin(distances) - fraction_along_curve = index_along_curve/float(curve.get_num_points()) - target = square.copy().center().scale(0.8/(2**order)) - line_index = int(fraction_along_curve*line.get_num_points()) - target.shift(line.points[line_index]) - targets.add(target) - - - self.add(squares) - self.play(ShowCreation( - curve, - run_time = 5, - rate_func = None - )) - self.dither() - self.play( - Transform(curve, line), - Transform(squares, targets), - run_time = 3 - ) - self.dither() - self.play(ShowCreation(freq_line)) - self.dither() - - -class WellPlayedGameOfSnake(Scene): - def construct(self): - grid = Grid(16, 16).fade() - snake_curve = SnakeCurve(order = 4) - words = TextMobject("``Snake Curve''") - words.next_to(grid, UP) - - self.add(grid) - self.play(ShowCreation( - snake_curve, - run_time = 7, - rate_func = None - )) - self.dither() - self.play(ShimmerIn(words)) - self.dither() - - -class TellMathematicianFriend(Scene): - def construct(self): - mathy, bubble = get_mathy_and_bubble() - squiggle_mouth = mathy.mouth.copy() - squiggle_mouth.apply_function( - lambda (x, y, z) : (x, y+0.02*np.sin(50*x), z) - ) - bubble.ingest_sub_mobjects() - bubble.write("Why not use a Hilbert curve \\textinterrobang ") - words1 = bubble.content - bubble.write("So, it's not one curve but an infinite family of curves \\dots") - words2 = bubble.content - bubble.write("Well, no, it \\emph{is} just one thing, but I need \\\\ \ - to tell you about a certain infinite family first.") - words3 = bubble.content - description = TextMobject("Mathematician friend", size = "\\small") - description.next_to(mathy, buff = 2) - arrow = Arrow(description, mathy) - - self.add(mathy) - self.play( - ShowCreation(arrow), - ShimmerIn(description) - ) - self.dither() - point = Point(bubble.get_tip()) - self.play( - Transform(point, bubble), - ) - self.remove(point) - self.add(bubble) - self.play(ShimmerIn(words1)) - self.dither() - self.remove(description, arrow) - self.play( - Transform(mathy.mouth, squiggle_mouth), - ApplyMethod(mathy.arm.wag, 0.2*RIGHT, LEFT), - ) - self.remove(words1) - self.add(words2) - self.dither(2) - self.remove(words2) - self.add(words3) - self.dither(2) - self.play( - ApplyPointwiseFunction( - lambda p : 15*p/np.linalg.norm(p), - bubble - ), - ApplyMethod(mathy.shift, 5*(DOWN+LEFT)), - FadeOut(words3), - run_time = 3 - ) - - -class Order1PseudoHilbertCurve(Scene): - 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() - -class Order2PseudoHilbertCurve(Scene): - def construct(self): - words = TextMobject("Order 2 Pseudo-Hilbert Curve") - words.to_edge(UP, buff = 0.3) - words.highlight(GREEN) - grid2 = Grid(2, 2) - grid4 = Grid(4, 4, point_thickness = 2) - # order_1_curve = HilbertCurve(order = 1) - # squaggle_curve = order_1_curve.copy().apply_function( - # lambda (x, y, z) : (x + np.cos(3*y), y + np.sin(3*x), z) - # ) - # squaggle_curve.show() - mini_curves = [ - HilbertCurve(order = 1).scale(0.5).shift(1.5*vect) - for vect in [ - LEFT+DOWN, - LEFT+UP, - RIGHT+UP, - RIGHT+DOWN - ] - ] - last_curve = mini_curves[0] - naive_curve = Mobject(last_curve) - for mini_curve in mini_curves[1:]: - line = Line(last_curve.points[-1], mini_curve.points[0]) - naive_curve.add(line, mini_curve) - last_curve = mini_curve - naive_curve.ingest_sub_mobjects() - naive_curve.gradient_highlight(RED, GREEN) - order_2_curve = HilbertCurve(order = 2) - - self.add(words, grid2) - self.dither() - self.play(ShowCreation(grid4)) - self.play(*[ - ShowCreation(mini_curve) - for mini_curve in mini_curves - ]) - self.dither() - self.play(ShowCreation(naive_curve, run_time = 5)) - self.remove(*mini_curves) - self.dither() - self.play(Transform(naive_curve, order_2_curve)) - self.dither() - - -class Order3PseudoHilbertCurve(Scene): - def construct(self): - words = TextMobject("Order 3 Pseudo-Hilbert Curve") - words.highlight(GREEN) - words.to_edge(UP) - grid4 = Mobject( - Grid(2, 2), - Grid(4, 4, point_thickness = 2) - ) - grid8 = Grid(8, 8, point_thickness = 1) - order_3_curve = HilbertCurve(order = 3) - mini_curves = [ - HilbertCurve(order = 2).scale(0.5).shift(1.5*vect) - for vect in [ - LEFT+DOWN, - LEFT+UP, - RIGHT+UP, - RIGHT+DOWN - ] - ] - - self.add(words, grid4) - self.dither() - self.play(ShowCreation(grid8)) - self.dither() - self.play(*map(GrowFromCenter, mini_curves)) - self.dither() - self.clear() - self.add(words, grid8, *mini_curves) - self.play(*[ - ApplyMethod(curve.rotate_in_place, np.pi, axis) - for curve, axis in [ - (mini_curves[0], UP+RIGHT), - (mini_curves[3], UP+LEFT) - ] - ]) - self.play(ShowCreation(order_3_curve, run_time = 5)) - self.dither() - -class GrowToOrder8PseudoHilbertCurve(Scene): - def construct(self): - self.curve = HilbertCurve(order = 1) - self.add(self.curve) - self.dither() - while self.curve.order < 8: - self.increase_order() - - - def increase_order(self): - mini_curves = [ - self.curve.copy().scale(0.5).shift(1.5*vect) - for vect in [ - LEFT+DOWN, - LEFT+UP, - RIGHT+UP, - RIGHT+DOWN - ] - ] - self.remove(self.curve) - self.play( - Transform(self.curve.copy(), mini_curves[0]) - ) - self.play(*[ - GrowFromCenter(mini_curve) - for mini_curve in mini_curves[1:] - ]) - self.dither() - self.clear() - self.add(*mini_curves) - self.play(*[ - ApplyMethod(curve.rotate_in_place, np.pi, axis) - for curve, axis in [ - (mini_curves[0], UP+RIGHT), - (mini_curves[3], UP+LEFT) - ] - ]) - self.curve = HilbertCurve(order = self.curve.order+1) - self.play(ShowCreation(self.curve, run_time = 2)) - self.remove(*mini_curves) - self.dither() - - -class UseOrder8(Scene): - def construct(self): - mathy, bubble = get_mathy_and_bubble() - bubble.write("For a 256x256 pixel array...") - words = TextMobject("Order 8 Pseudo-Hilbert Curve") - words.highlight(GREEN) - words.to_edge(UP, buff = 0.3) - curve = HilbertCurve(order = 8) - - self.add(mathy, bubble) - self.play(ShimmerIn(bubble.content)) - self.dither() - self.clear() - self.add(words) - self.play(ShowCreation( - curve, run_time = 7, rate_func = None - )) - self.dither() - - - -class HilbertBetterThanSnakeQ(Scene): - def construct(self): - hilbert_curves, snake_curves = [ - [ - CurveClass(order = n) - for n in range(2, 7) - ] - for CurveClass in HilbertCurve, SnakeCurve - ] - for curve in hilbert_curves+snake_curves: - curve.scale(0.8) - for curve in hilbert_curves: - curve.to_edge(LEFT) - for curve in snake_curves: - curve.to_edge(RIGHT) - greater_than = TexMobject(">") - question_mark = TextMobject("?") - question_mark.next_to(greater_than, UP) - - self.add(greater_than, question_mark) - hilbert_curve = hilbert_curves[0] - snake_curve = snake_curves[0] - for new_hc, new_sc in zip(hilbert_curves[1:], snake_curves[1:]): - self.play(*[ - Transform(hilbert_curve, new_hc), - Transform(snake_curve, new_sc) - ]) - self.dither() - - -class ImagineItWorks(Scene): - def construct(self): - self.add(TextMobject("Imagine your project succeeds...")) - self.dither() - - -class RandyWithHeadphones(Scene): - def construct(self): - headphones = ImageMobject("Headphones.png") - headphones.scale(0.1) - headphones.stretch(2, 0) - headphones.shift(1.2*UP+0.05*LEFT) - headphones.highlight(GREY) - randy = Randolph() - - self.add(randy, headphones) - self.dither(2) - self.play(ApplyMethod(randy.blink)) - self.dither(4) - - -class IncreaseResolution(Scene): - def construct(self): - grids = [ - Grid( - 2**order, 2**order, - point_thickness = 1 - ).shift(0.3*DOWN) - for order in 6, 7 - ] - grid = grids[0] - side_brace = Brace(grid, LEFT) - top_brace = Brace(grid, UP) - top_words = TextMobject("256") - new_top_words = TextMobject("512") - side_words = top_words.copy() - new_side_words = new_top_words.copy() - for words in top_words, new_top_words: - words.next_to(top_brace, UP, buff = 0.1) - for words in side_words, new_side_words: - words.next_to(side_brace, LEFT) - - self.add(grid) - self.play( - GrowFromCenter(side_brace), - GrowFromCenter(top_brace), - ShimmerIn(top_words), - ShimmerIn(side_words) - ) - self.dither() - self.play( - DelayByOrder(Transform(*grids)), - Transform(top_words, new_top_words), - Transform(side_words, new_side_words) - ) - self.dither() - - -class IncreasingResolutionWithSnakeCurve(Scene): - 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() - - -class TrackSpecificCurvePoint(Scene): - CURVE_CLASS = None #Fillin - 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() - - -class TrackSpecificSnakeCurvePoint(TrackSpecificCurvePoint): - CURVE_CLASS = SnakeCurve - - -class NeedToRelearn(Scene): - def construct(self): - top_words = TextMobject("Different pixel-frequency association") - bottom_words = TextMobject("Need to relearn sight-via-sound") - top_words.shift(UP) - bottom_words.shift(DOWN) - arrow = Arrow(top_words, bottom_words) - - self.play(ShimmerIn(top_words)) - self.dither() - self.play(ShowCreation(arrow)) - self.play(ShimmerIn(bottom_words)) - self.dither() - - -class TrackSpecificHilbertCurvePoint(TrackSpecificCurvePoint): - CURVE_CLASS = HilbertCurve - - - diff --git a/hilbert/section2.py b/hilbert/section2.py deleted file mode 100644 index 35a885de..00000000 --- a/hilbert/section2.py +++ /dev/null @@ -1,1095 +0,0 @@ -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, ShimmerIn, FadeOut, FadeIn -from animation.simple_animations import \ - ShowCreation, Homotopy -from animation.meta_animations import \ - DelayByOrder, TransformAnimations -from animation.playground import Vibrate - -from topics.geometry import \ - Line, Dot, Arrow, Grid, Square, Point, Circle -from topics.characters import \ - ThoughtBubble, SpeechBubble, Mathematician -from topics.number_line import UnitInterval, NumberLine -from topics.three_dimensions import Stars -from topics.functions import ParametricFunction - -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.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 - - - -class VaryCircles(Animation): - def __init__(self, scene, input_value, radius, **kwargs): - digest_locals(self) - Animation.__init__(self, Mobject(), **kwargs) - - def update_mobject(self, alpha): - radius = self.radius + 0.9*self.radius*np.sin(1.5*np.pi*alpha) - self.mobject = Mobject(*self.scene.get_circles_and_points( - self.input_value-radius, - self.input_value+radius - )).ingest_sub_mobjects() - - -class FunctionIsContinuousText(Scene): - def construct(self): - all_points = TextMobject("$f$ is continuous at every input point") - continuous = TextMobject("$f$ is continuous") - all_points.shift(UP) - continuous.shift(DOWN) - arrow = Arrow(all_points, continuous) - - self.play(ShimmerIn(all_points)) - self.play(ShowCreation(arrow)) - self.play(ShimmerIn(continuous)) - self.dither() - - -class DefineActualHilbertCurveText(Scene): - def construct(self): - self.add(TextMobject(""" - Finally define a Hilbert Curve\\dots - """)) - self.dither() - - -class ReliesOnWonderfulProperty(Scene): - def construct(self): - self.add(TextMobject(""" - \\dots which relies on a certain property - of Pseudo-Hilbert-curves. - """)) - self.dither() - - -class WonderfulPropertyOfPseudoHilbertCurves(Scene): - 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.dither() - 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.dither() - - 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(), point_thickness=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.dither() - -class FollowManyPoints(Scene): - 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_sub_mobjects() - starter_dots.shift(2*UP) - - self.add(curve, text) - self.dither() - self.play(DelayByOrder(ApplyMethod(starter_dots.shift, 2*DOWN))) - self.dither() - 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), - ) - # self.dither() - - -class FormalDefinitionOfHilbertCurve(Scene): - 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.dither() - self.remove(explanation, exp_arrow) - self.play(ShowCreation(curve)) - self.play( - ApplyMethod(x1.highlight, BLUE), - ShowCreation(x_arrow), - ShowCreation(dot) - ) - self.dither() - self.remove(x_arrow) - limit = Mobject(*text.split()[3:]).ingest_sub_mobjects() - limit.point_thickness = 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), - ) - - -class CouldNotDefineForSnakeCurve(Scene): - def construct(self): - self.add(TextMobject(""" - You could not define a limit curve from - snake curves. - """)) - self.dither() - -class ThreeThingsToProve(Scene): - def construct(self): - definition = TexMobject([ - "\\text{HC}(", "x", ")", - "=\\lim_{n \\to \\infty}\\text{PHC}_n(", "x", ")" - ]) - definition.to_edge(UP) - definition.split()[1].highlight(BLUE) - definition.split()[-2].highlight(BLUE) - intro = TextMobject("Three things need to be proven") - prove_that = TextMobject("Prove that HC is $\\dots$") - prove_that.scale(0.7) - prove_that.to_edge(LEFT) - items = TextMobject([ - "\\begin{enumerate}", - "\\item Well-defined: ", - "Points on Pseudo-Hilbert-curves really do converge", - "\\item A Curve: ", - "HC is continuous", - "\\item Space-filling: ", - "Each point in the unit square is an output of HC", - "\\end{enumerate}", - ]).split() - items[1].highlight(GREEN) - items[3].highlight(YELLOW_C) - items[5].highlight(MAROON) - Mobject(*items).to_edge(RIGHT) - - self.add(definition) - self.play(ShimmerIn(intro)) - self.dither() - self.play(Transform(intro, prove_that)) - for item in items[1:-1]: - self.play(ShimmerIn(item)) - self.dither() - - - -class TilingSpace(Scene): - def construct(self): - coords_set = [ORIGIN] - for n in range(int(2*SPACE_WIDTH)): - for vect in UP, RIGHT: - for k in range(n): - new_coords = coords_set[-1]+((-1)**n)*vect - coords_set.append(new_coords) - square = Square(side_length = 1, color = WHITE) - squares = Mobject(*[ - square.copy().shift(coords) - for coords in coords_set - ]).ingest_sub_mobjects() - self.play( - DelayByOrder(FadeIn(squares)), - run_time = 3 - ) - curve = HilbertCurve(order = 6).scale(1./6) - all_curves = Mobject(*[ - curve.copy().shift(coords) - for coords in coords_set - ]).ingest_sub_mobjects() - all_curves.thin_out(10) - self.play(ShowCreation( - all_curves, - rate_func = None, - run_time = 15 - )) - - -class ColorIntervals(Scene): - def construct(self): - number_line = NumberLine( - numerical_radius = 5, - number_at_center = 5, - leftmost_tick = 0, - density = 2*DEFAULT_POINT_DENSITY_1D - ) - number_line.shift(2*RIGHT) - number_line.add_numbers() - number_line.scale(2) - brace = Brace(Mobject( - *number_line.sub_mobjects[:2] - )) - - self.add(number_line) - for n in range(0, 10, 2): - if n == 0: - brace_anim = GrowFromCenter(brace) - else: - brace_anim = ApplyMethod(brace.shift, 2*RIGHT) - self.play( - ApplyMethod( - number_line.highlight, - RED, - lambda p : p[0] > n-6.2 and p[0] < n-4 and p[1] > -0.4 - ), - brace_anim - ) - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/hilbert/section3.py b/hilbert/section3.py deleted file mode 100644 index 5b25a9c2..00000000 --- a/hilbert/section3.py +++ /dev/null @@ -1,310 +0,0 @@ -from mobject import Mobject, Point -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,\ - TransformAnimations, ShimmerIn, FadeOut, FadeIn -from animation.simple_animations import \ - ShowCreation, DelayByOrder -from animation.playground import Vibrate - -from topics.geometry import \ - Line, Dot, Arrow, Grid, Square, Point, Polygon -from topics.characters import \ - ThoughtBubble, SpeechBubble, Mathematician, Mortimer -from topics.number_line import UnitInterval -from topics.three_dimensions import Stars - -from region import region_from_polygon_vertices - -import displayer as disp - -from hilbert.curves import \ - TransformOverIncreasingOrders, FlowSnake, HilbertCurve, \ - SnakeCurve, Sierpinski -from hilbert.section1 import get_mathy_and_bubble - - -from helpers import * - - - -class SectionThree(Scene): - def construct(self): - self.add(TextMobject("A few words on the usefulness of infinite math")) - self.dither() - - -class InfiniteResultsFiniteWorld(Scene): - def construct(self): - left_words = TextMobject("Infinite result") - right_words = TextMobject("Finite world") - for words in left_words, right_words: - words.scale(0.8) - left_formula = TexMobject( - "\\sum_{n = 0}^{\\infty} 2^n = -1" - ) - right_formula = TexMobject("111\\cdots111") - for formula in left_formula, right_formula: - formula.add( - Brace(formula, UP), - ) - formula.ingest_sub_mobjects() - right_overwords = TextMobject( - "\\substack{\ - \\text{How computers} \\\\ \ - \\text{represent $-1$}\ - }" - ).scale(1.5) - - left_mobs = [left_words, left_formula] - right_mobs = [right_words, right_formula] - for mob in left_mobs: - mob.to_edge(RIGHT, buff = 1) - mob.shift(SPACE_WIDTH*LEFT) - for mob in right_mobs: - mob.to_edge(LEFT, buff = 1) - mob.shift(SPACE_WIDTH*RIGHT) - arrow = Arrow(left_words, right_words) - right_overwords.next_to(right_formula, UP) - - self.play(ShimmerIn(left_words)) - self.play(ShowCreation(arrow)) - self.play(ShimmerIn(right_words)) - self.dither() - self.play( - ShimmerIn(left_formula), - ApplyMethod(left_words.next_to, left_formula, UP) - ) - self.dither() - self.play( - ShimmerIn(right_formula), - Transform(right_words, right_overwords) - ) - self.dither() - self.finite_analog( - Mobject(left_formula, left_words), - arrow, - Mobject(right_formula, right_words) - ) - - - def finite_analog(self, left_mob, arrow, right_mob): - self.clear() - self.add(left_mob, arrow, right_mob) - ex = TextMobject("\\times") - ex.highlight(RED) - # ex.shift(arrow.get_center()) - middle = TexMobject( - "\\sum_{n=0}^N 2^n \\equiv -1 \\mod 2^{N+1}" - ) - finite_analog = TextMobject("Finite analog") - finite_analog.scale(0.8) - brace = Brace(middle, UP) - finite_analog.next_to(brace, UP) - new_left = left_mob.copy().to_edge(LEFT) - new_right = right_mob.copy().to_edge(RIGHT) - left_arrow, right_arrow = [ - Arrow( - mob1.get_right()[0]*RIGHT, - mob2.get_left()[0]*RIGHT, - buff = 0 - ) - for mob1, mob2 in [ - (new_left, middle), - (middle, new_right) - ] - ] - for mob in ex, middle: - mob.sort_points(np.linalg.norm) - - self.play(GrowFromCenter(ex)) - self.dither() - self.play( - Transform(left_mob, new_left), - Transform(arrow.copy(), left_arrow), - DelayByOrder(Transform(ex, middle)), - Transform(arrow, right_arrow), - Transform(right_mob, new_right) - ) - self.play( - GrowFromCenter(brace), - ShimmerIn(finite_analog) - ) - self.dither() - self.equivalence( - left_mob, - left_arrow, - Mobject(middle, brace, finite_analog) - ) - - def equivalence(self, left_mob, arrow, right_mob): - self.clear() - self.add(left_mob, arrow, right_mob) - words = TextMobject("is equivalent to") - words.shift(0.25*LEFT) - words.highlight(BLUE) - new_left = left_mob.copy().shift(RIGHT) - new_right = right_mob.copy() - new_right.shift( - (words.get_right()[0]-\ - right_mob.get_left()[0]+\ - 0.5 - )*RIGHT - ) - for mob in arrow, words: - mob.sort_points(np.linalg.norm) - - self.play( - ApplyMethod(left_mob.shift, RIGHT), - Transform(arrow, words), - ApplyMethod(right_mob.to_edge, RIGHT) - ) - self.dither() - - -class HilbertCurvesStayStable(Scene): - def construct(self): - scale_factor = 0.9 - grid = Grid(4, 4, point_thickness = 1) - curve = HilbertCurve(order = 2) - for mob in grid, curve: - mob.scale(scale_factor) - words = TextMobject(""" - Sequence of curves is stable - $\\leftrightarrow$ existence of limit curve - """, size = "\\normal") - words.scale(1.25) - words.to_edge(UP) - - self.add(curve, grid) - self.dither() - for n in range(3, 7): - if n == 5: - self.play(ShimmerIn(words)) - new_grid = Grid(2**n, 2**n, point_thickness = 1) - new_curve = HilbertCurve(order = n) - for mob in new_grid, new_curve: - mob.scale(scale_factor) - self.play( - ShowCreation(new_grid), - Animation(curve) - ) - self.remove(grid) - grid = new_grid - self.play(Transform(curve, new_curve)) - self.dither() - - - -class InfiniteObjectsEncapsulateFiniteObjects(Scene): - def get_triangles(self): - triangle = Polygon( - LEFT/np.sqrt(3), - UP, - RIGHT/np.sqrt(3), - color = GREEN - ) - triangles = Mobject( - triangle.copy().scale(0.5).shift(LEFT), - triangle, - triangle.copy().scale(0.3).shift(0.5*UP+RIGHT) - ) - triangles.center() - return triangles - - def construct(self): - words =[ - TextMobject(text, size = "\\large") - for text in [ - "Truths about infinite objects", - " encapsulate ", - "facts about finite objects" - ] - ] - - words[0].highlight(RED) - words[1].next_to(words[0]) - words[2].highlight(GREEN).next_to(words[1]) - Mobject(*words).center().to_edge(UP) - infinite_objects = [ - TexMobject( - "\\sum_{n=0}^\\infty", - size = "\\normal" - ).highlight(RED_E), - Sierpinski(order = 8).scale(0.3), - TextMobject( - "$\\exists$ something infinite $\\dots$" - ).highlight(RED_B) - ] - finite_objects = [ - TexMobject( - "\\sum_{n=0}^N", - size = "\\normal" - ).highlight(GREEN_E), - self.get_triangles(), - TextMobject( - "$\\forall$ finite somethings $\\dots$" - ).highlight(GREEN_B) - ] - for infinite, finite, n in zip(infinite_objects, finite_objects, it.count(1, 2)): - infinite.next_to(words[0], DOWN, buff = n) - finite.next_to(words[2], DOWN, buff = n) - - self.play(ShimmerIn(words[0])) - self.dither() - self.play(ShimmerIn(infinite_objects[0])) - self.play(ShowCreation(infinite_objects[1])) - self.play(ShimmerIn(infinite_objects[2])) - self.dither() - self.play(ShimmerIn(words[1]), ShimmerIn(words[2])) - self.play(ShimmerIn(finite_objects[0])) - self.play(ShowCreation(finite_objects[1])) - self.play(ShimmerIn(finite_objects[2])) - self.dither() - - -class StatementRemovedFromReality(Scene): - def construct(self): - mathy, bubble = get_mathy_and_bubble() - bubble.stretch_to_fit_width(4) - mathy.to_corner(DOWN+LEFT) - bubble.pin_to(mathy) - bubble.shift(LEFT) - morty = Mortimer() - morty.to_corner(DOWN+RIGHT) - morty_bubble = SpeechBubble() - morty_bubble.stretch_to_fit_width(4) - morty_bubble.pin_to(morty) - bubble.write(""" - Did you know a curve \\\\ - can fill all space? - """) - morty_bubble.write("Who cares?") - - self.add(mathy, morty) - for bub, buddy in [(bubble, mathy), (morty_bubble, morty)]: - self.play(Transform( - Point(bub.get_tip()), - bub - )) - self.play(ShimmerIn(bub.content)) - self.play(ApplyMethod( - buddy.blink, - rate_func = squish_rate_func(there_and_back) - )) - - - - - - - - diff --git a/hilbert/curves.py b/topics/fractals.py similarity index 100% rename from hilbert/curves.py rename to topics/fractals.py