End of fractal_dimension project

This commit is contained in:
Grant Sanderson
2017-01-24 14:55:05 -08:00
parent 9676aef253
commit ebd825a3a2
4 changed files with 354 additions and 34 deletions

167
fractal_charm.py Normal file
View File

@ -0,0 +1,167 @@
from helpers import *
from mobject.tex_mobject import TexMobject
from mobject import Mobject
from mobject.image_mobject import ImageMobject
from mobject.vectorized_mobject import *
from animation.animation import Animation
from animation.transform import *
from animation.simple_animations import *
from animation.playground import *
from topics.geometry import *
from topics.characters import *
from topics.functions import *
from topics.fractals import *
from topics.number_line import *
from topics.combinatorics import *
from topics.numerals import *
from topics.three_dimensions import *
from scene import Scene
from camera import Camera
from mobject.svg_mobject import *
from mobject.tex_mobject import *
class FractalCreation(Scene):
CONFIG = {
"fractal_class" : PentagonalFractal,
"max_order" : 5,
"transform_kwargs" : {
"path_arc" : np.pi/6,
"submobject_mode" : "lagged_start",
"run_time" : 2,
},
"fractal_kwargs" : {},
"modify_stroke_width" : True,
}
def construct(self):
fractal = self.fractal_class(order = 0, **self.fractal_kwargs)
self.play(FadeIn(fractal))
for order in range(1, self.max_order+1):
new_fractal = self.fractal_class(
order = order,
**self.fractal_kwargs
)
if self.modify_stroke_width:
smallest = new_fractal.family_members_with_points()[0]
if smallest.get_width() < 0.25:
new_fractal.set_stroke(width = 2)
if smallest.get_width() < 0.1:
new_fractal.set_stroke(width = 1)
self.play(Transform(
fractal, new_fractal,
**self.transform_kwargs
))
self.dither()
self.dither()
self.fractal = fractal
class PentagonalFractalCreation(FractalCreation):
pass
class DiamondFractalCreation(FractalCreation):
CONFIG = {
"fractal_class" : DiamondFractal,
"max_order" : 6,
"fractal_kwargs" : {"height" : 6}
}
class PiCreatureFractalCreation(FractalCreation):
CONFIG = {
"fractal_class" : PiCreatureFractal,
"max_order" : 5,
"fractal_kwargs" : {"height" : 6},
"transform_kwargs" : {
"submobject_mode" : "all_at_once",
"run_time" : 2,
},
}
def construct(self):
FractalCreation.construct(self)
fractal = self.fractal
smallest_pi = fractal[0][0]
zoom_factor = 0.1/smallest_pi.get_height()
fractal.generate_target()
fractal.target.shift(-smallest_pi.get_corner(UP+LEFT))
fractal.target.scale(zoom_factor)
self.play(MoveToTarget(fractal, run_time = 10))
self.dither()
class QuadraticKochFractalCreation(FractalCreation):
CONFIG = {
"fractal_class" : QuadraticKoch,
"max_order" : 5,
"fractal_kwargs" : {"radius" : 10},
# "transform_kwargs" : {
# "submobject_mode" : "all_at_once",
# "run_time" : 2,
# },
}
class KochSnowFlakeFractalCreation(FractalCreation):
CONFIG = {
"fractal_class" : KochSnowFlake,
"max_order" : 5,
"fractal_kwargs" : {"radius" : 6},
"transform_kwargs" : {
"submobject_mode" : "lagged_start",
"path_arc" : np.pi/6,
"run_time" : 2,
},
}
class WonkyHexagonFractalCreation(FractalCreation):
CONFIG = {
"fractal_class" : WonkyHexagonFractal,
"max_order" : 5,
"fractal_kwargs" : {"height" : 6},
"transform_kwargs" : {
"submobject_mode" : "lagged_start",
"path_arc" : np.pi/6,
"run_time" : 2,
},
}

View File

@ -1,5 +1,3 @@
#!/usr/bin/env python
from helpers import *
from mobject.tex_mobject import TexMobject
@ -24,6 +22,8 @@ from camera import Camera
from mobject.svg_mobject import *
from mobject.tex_mobject import *
from fractal_charm import FractalCreation
from eoc.graph_scene import GraphScene
from eoc.chapter1 import PatreonThanks
@ -82,26 +82,7 @@ class SierpinskiTest(Scene):
# self.play(sierp.scale, 2, sierp.get_top())
# self.dither(3)
class FractalCreation(Scene):
CONFIG = {
"fractal_class" : PentagonalFractal,
"max_order" : 5,
"path_arc" : np.pi/6,
"submobject_mode" : "lagged_start"
}
def construct(self):
fractal = self.fractal_class(order = 0)
self.play(FadeIn(fractal))
for order in range(1, self.max_order+1):
new_fractal = self.fractal_class(order = order)
self.play(Transform(
fractal, new_fractal,
path_arc = self.path_arc,
submobject_mode = self.submobject_mode,
run_time = 2
))
self.dither()
self.dither()
###################################
@ -2312,7 +2293,7 @@ class IntroduceLogLogPlot(GraphScene):
class ManyBritainCounts(BoxCountingWithBritain):
CONFIG = {
"box_width" : 0.1,
"num_boundary_check_points" : 5000,
"num_boundary_check_points" : 10000,
"corner_rect_left_extension" : 1,
}
def construct(self):
@ -2325,8 +2306,8 @@ class ManyBritainCounts(BoxCountingWithBritain):
self.add(self.get_grid())
self.add(britain)
for width in range(1, 6):
self.play(britain.scale_to_fit_width, width)
for x in range(5):
self.play(britain.scale, 2, britain.point_from_proportion(0.8))
boxes = self.get_highlighted_boxes(britain)
self.play(ShowCreation(boxes))
self.dither()
@ -2360,6 +2341,49 @@ class DefineFractal(TeacherStudentsScene):
])
self.dither(3)
class RoughnessAndFractionalDimension(Scene):
def construct(self):
title = TextMobject(
"Non-integer dimension $\\Leftrightarrow$ Roughness"
)
title.to_edge(UP)
self.add(title)
randy = Randolph().scale(2)
randy.to_corner(DOWN+RIGHT)
self.add(randy)
target = randy.copy()
target.change_mode("hooray")
ponder_target = randy.copy()
ponder_target.change_mode("pondering")
for mob in target, ponder_target:
fractalify(mob, order = 2)
dimension_label = TextMobject("Boundary dimension = ", "1")
dimension_label.to_edge(LEFT)
one = dimension_label[1]
one.highlight(BLUE)
new_dim = TexMobject("1.2")
new_dim.move_to(one, DOWN+LEFT)
new_dim.highlight(one.get_color())
self.add(dimension_label)
self.play(Blink(randy))
self.play(
Transform(randy, target, run_time = 2),
Transform(one, new_dim)
)
self.dither()
self.play(Blink(randy))
self.play(randy.look, DOWN+RIGHT)
self.dither()
self.play(randy.look, DOWN+LEFT)
self.play(Blink(randy))
self.dither()
self.play(Transform(randy, ponder_target))
self.dither()
class DifferentSlopesAtDifferentScales(IntroduceLogLogPlot):
def construct(self):
self.setup_axes(animate = False)
@ -2401,14 +2425,53 @@ class DifferentSlopesAtDifferentScales(IntroduceLogLogPlot):
class HoldUpCoilExample(TeacherStudentsScene):
def construct(self):
point = UP+RIGHT
self.play(
self.get_teacher().change_mode, "raise_right_hand",
self.get_teacher().look, UP+LEFT
self.get_teacher().look_at, point
)
self.play(*[
ApplyMethod(pi.look_at, point)
for pi in self.get_students()
])
self.dither(5)
self.change_student_modes(*["thinking"]*3)
self.play(*[
ApplyMethod(pi.look_at, point)
for pi in self.get_students()
])
self.dither(5)
class SmoothHilbertZoom(Scene):
def construct(self):
hilbert = HilbertCurve(
order = 7,
color = MAROON_B,
monochromatic = True
)
hilbert.make_smooth()
self.add(hilbert)
two_d_title = TextMobject("2D at a distance...")
one_d_title = TextMobject("1D up close")
for title in two_d_title, one_d_title:
title.to_edge(UP)
self.add(two_d_title)
self.dither()
self.play(
ApplyMethod(
hilbert.scale, 100,
hilbert.point_from_proportion(0.3),
),
Transform(
two_d_title, one_d_title,
rate_func = squish_rate_func(smooth)
),
run_time = 3
)
self.dither()
class ListDimensionTypes(PiCreatureScene):
CONFIG = {
"use_morty" : False,
@ -2777,7 +2840,7 @@ class FractalNonFractalFlowChart(Scene):
class ShowPiCreatureFractalCreation(FractalCreation):
CONFIG = {
"fractal_class" : PiCreatureFractal,
"fractal_class" : PentagonalPiCreatureFractal,
"max_order" : 4,
}

View File

@ -177,6 +177,17 @@ class PiCreature(SVGMobject):
return self
def get_all_pi_creature_modes():
result = []
prefix = "PiCreatures_"
suffix = ".svg"
for file in os.listdir(PI_CREATURE_DIR):
if file.startswith(prefix) and file.endswith(suffix):
result.append(
file[len(prefix):-len(suffix)]
)
return result
class Randolph(PiCreature):
pass #Nothing more than an alternative name

View File

@ -3,8 +3,8 @@ from mobject.vectorized_mobject import VMobject, VGroup, VectorizedPoint
from scene import Scene
from animation.transform import Transform
from animation.simple_animations import ShowCreation
from topics.geometry import Line, Polygon, RegularPolygon
from characters import PiCreature, Randolph
from topics.geometry import Line, Polygon, RegularPolygon, Square
from characters import PiCreature, Randolph, get_all_pi_creature_modes
from helpers import *
@ -20,10 +20,7 @@ def fractalify(vmobject, order = 3, *args, **kwargs):
fractalification_iteration(vmobject)
return vmobject
def fractalification_iteration(vmobject,
dimension = 1.05,
num_inserted_anchors_range = range(1, 4)
):
def fractalification_iteration(vmobject, dimension = 1.05, num_inserted_anchors_range = range(1, 4)):
num_points = vmobject.get_num_points()
if num_points > 0:
# original_anchors = vmobject.get_anchors()
@ -147,7 +144,7 @@ class PentagonalFractal(SelfSimilarFractal):
part.shift(0.95*part.get_height()*UP)
part.rotate(2*np.pi*x/5)
class PiCreatureFractal(PentagonalFractal):
class PentagonalPiCreatureFractal(PentagonalFractal):
def init_colors(self):
SelfSimilarFractal.init_colors(self)
internal_pis = [
@ -170,6 +167,88 @@ class PiCreatureFractal(PentagonalFractal):
PentagonalFractal.arrange_subparts(self, *subparts)
class PiCreatureFractal(VMobject):
CONFIG = {
"order" : 7,
"scale_val" : 1.7,
"start_mode" : "hooray",
"height" : 6,
"colors" : [
BLUE_D, BLUE_B, MAROON_B, MAROON_D, GREY,
YELLOW, RED, GREY_BROWN, RED, RED_E,
],
"random_seed" : 0,
"stroke_width" : 0,
}
def init_colors(self):
VMobject.init_colors(self)
internal_pis = [
pi
for pi in self.submobject_family()
if isinstance(pi, PiCreature)
]
random.seed(self.random_seed)
for pi in reversed(internal_pis):
color = random.choice(self.colors)
pi.highlight(color)
pi.set_stroke(color, width = 0)
def generate_points(self):
random.seed(self.random_seed)
modes = get_all_pi_creature_modes()
seed = PiCreature(mode = self.start_mode)
seed.scale_to_fit_height(self.height)
seed.to_edge(DOWN)
creatures = [seed]
self.add(seed)
for x in range(self.order):
new_creatures = []
for creature in creatures:
for eye in creature.eyes:
new_creature = PiCreature(
mode = random.choice(modes)
)
new_creature.replace(eye)
new_creature.scale(
self.scale_val,
about_point = new_creature.get_bottom()
)
new_creatures.append(new_creature)
creature.blink()
self.add_to_back(VGroup(*new_creatures))
creatures = new_creatures
# def init_colors(self):
# VMobject.init_colors(self)
# self.gradient_highlight(*self.colors)
class WonkyHexagonFractal(SelfSimilarFractal):
CONFIG = {
"num_subparts" : 7
}
def get_seed_shape(self):
return RegularPolygon(n=6)
def arrange_subparts(self, *subparts):
for i, piece in enumerate(subparts):
piece.rotate(i*np.pi/12)
p1, p2, p3, p4, p5, p6, p7 = subparts
center_row = VGroup(p1, p4, p7)
center_row.arrange_submobjects(RIGHT, buff = 0)
for p in p2, p3, p5, p6:
p.scale_to_fit_width(p1.get_width())
p2.move_to(p1.get_top(), DOWN+LEFT)
p3.move_to(p1.get_bottom(), UP+LEFT)
p5.move_to(p4.get_top(), DOWN+LEFT)
p6.move_to(p4.get_bottom(), UP+LEFT)
######## Space filling curves ############
class FractalCurve(VMobject):