mirror of
https://github.com/3b1b/manim.git
synced 2025-09-01 00:48:45 +00:00
commit
1728faf81e
13 changed files with 4237 additions and 119 deletions
|
@ -57,6 +57,10 @@ class ShowShadows(ThreeDScene):
|
||||||
"camera_config": {
|
"camera_config": {
|
||||||
"light_source_start_point": 10 * OUT,
|
"light_source_start_point": 10 * OUT,
|
||||||
"frame_center": [0, 0, 0.5],
|
"frame_center": [0, 0, 0.5],
|
||||||
|
},
|
||||||
|
"initial_orientation_config": {
|
||||||
|
"phi": 60 * DEGREES,
|
||||||
|
"theta": -120 * DEGREES,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,8 +148,7 @@ class ShowShadows(ThreeDScene):
|
||||||
temp_shadow = updating_mobject_from_func(lambda: get_shadow(obj3d))
|
temp_shadow = updating_mobject_from_func(lambda: get_shadow(obj3d))
|
||||||
self.add(temp_shadow)
|
self.add(temp_shadow)
|
||||||
self.move_camera(
|
self.move_camera(
|
||||||
phi=60 * DEGREES,
|
**self.initial_orientation_config,
|
||||||
theta=-120 * DEGREES,
|
|
||||||
added_anims=[
|
added_anims=[
|
||||||
LaggedStart(DrawBorderThenFill, obj3d)
|
LaggedStart(DrawBorderThenFill, obj3d)
|
||||||
],
|
],
|
||||||
|
|
|
@ -300,7 +300,7 @@ class Camera(object):
|
||||||
ctx.set_matrix(cairo.Matrix(
|
ctx.set_matrix(cairo.Matrix(
|
||||||
fdiv(pw, fw), 0,
|
fdiv(pw, fw), 0,
|
||||||
0, -fdiv(ph, fh),
|
0, -fdiv(ph, fh),
|
||||||
(pw / 2) + fc[0] * fdiv(pw, fw),
|
(pw / 2) - fc[0] * fdiv(pw, fw),
|
||||||
(ph / 2) + fc[1] * fdiv(ph, fh),
|
(ph / 2) + fc[1] * fdiv(ph, fh),
|
||||||
))
|
))
|
||||||
self.cache_cairo_context(pixel_array, ctx)
|
self.cache_cairo_context(pixel_array, ctx)
|
||||||
|
|
|
@ -11,6 +11,7 @@ from animation.creation import DrawBorderThenFill
|
||||||
from animation.creation import Write
|
from animation.creation import Write
|
||||||
from animation.creation import FadeIn
|
from animation.creation import FadeIn
|
||||||
from animation.creation import FadeOut
|
from animation.creation import FadeOut
|
||||||
|
from continual_animation.continual_animation import ContinualMovement
|
||||||
from mobject.svg.tex_mobject import TextMobject
|
from mobject.svg.tex_mobject import TextMobject
|
||||||
from mobject.types.vectorized_mobject import VGroup
|
from mobject.types.vectorized_mobject import VGroup
|
||||||
from scene.scene import Scene
|
from scene.scene import Scene
|
||||||
|
@ -18,12 +19,15 @@ from scene.moving_camera_scene import MovingCameraScene
|
||||||
from for_3b1b_videos.pi_creature_animations import Blink
|
from for_3b1b_videos.pi_creature_animations import Blink
|
||||||
from for_3b1b_videos.pi_creature import Mortimer
|
from for_3b1b_videos.pi_creature import Mortimer
|
||||||
from for_3b1b_videos.pi_creature import Randolph
|
from for_3b1b_videos.pi_creature import Randolph
|
||||||
|
from for_3b1b_videos.pi_creature_scene import PiCreatureScene
|
||||||
from mobject.geometry import Line
|
from mobject.geometry import Line
|
||||||
from mobject.geometry import DashedLine
|
from mobject.geometry import DashedLine
|
||||||
from mobject.geometry import Rectangle
|
from mobject.geometry import Rectangle
|
||||||
from mobject.geometry import Square
|
from mobject.geometry import Square
|
||||||
from mobject.svg.drawings import PatreonLogo
|
from mobject.svg.drawings import PatreonLogo
|
||||||
from mobject.svg.drawings import Logo
|
from mobject.svg.drawings import Logo
|
||||||
|
from utils.space_ops import get_norm
|
||||||
|
from utils.space_ops import normalize
|
||||||
|
|
||||||
|
|
||||||
class OpeningQuote(Scene):
|
class OpeningQuote(Scene):
|
||||||
|
@ -147,7 +151,7 @@ class PatreonThanks(Scene):
|
||||||
last_group = group
|
last_group = group
|
||||||
|
|
||||||
|
|
||||||
class PatreonEndScreen(PatreonThanks):
|
class PatreonEndScreen(PatreonThanks, PiCreatureScene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"n_patron_columns": 3,
|
"n_patron_columns": 3,
|
||||||
"max_patron_width": 3.5,
|
"max_patron_width": 3.5,
|
||||||
|
@ -155,6 +159,7 @@ class PatreonEndScreen(PatreonThanks):
|
||||||
"randomize_order": True,
|
"randomize_order": True,
|
||||||
"capitalize": True,
|
"capitalize": True,
|
||||||
"name_y_spacing": 0.7,
|
"name_y_spacing": 0.7,
|
||||||
|
"thanks_words": "Funded by the community, with special thanks to:",
|
||||||
}
|
}
|
||||||
|
|
||||||
def construct(self):
|
def construct(self):
|
||||||
|
@ -169,10 +174,10 @@ class PatreonEndScreen(PatreonThanks):
|
||||||
for patron in self.specific_patrons
|
for patron in self.specific_patrons
|
||||||
]
|
]
|
||||||
|
|
||||||
self.add_title()
|
# self.add_title()
|
||||||
self.scroll_through_patrons()
|
self.scroll_through_patrons()
|
||||||
|
|
||||||
def add_title(self):
|
def create_pi_creatures(self):
|
||||||
title = self.title = TextMobject("Clicky Stuffs")
|
title = self.title = TextMobject("Clicky Stuffs")
|
||||||
title.scale(1.5)
|
title.scale(1.5)
|
||||||
title.to_edge(UP, buff=MED_SMALL_BUFF)
|
title.to_edge(UP, buff=MED_SMALL_BUFF)
|
||||||
|
@ -184,6 +189,7 @@ class PatreonEndScreen(PatreonThanks):
|
||||||
pi.look(DOWN)
|
pi.look(DOWN)
|
||||||
pi.next_to(title, vect, buff=MED_LARGE_BUFF)
|
pi.next_to(title, vect, buff=MED_LARGE_BUFF)
|
||||||
self.add_foreground_mobjects(title, randy, morty)
|
self.add_foreground_mobjects(title, randy, morty)
|
||||||
|
return self.pi_creatures
|
||||||
|
|
||||||
def scroll_through_patrons(self):
|
def scroll_through_patrons(self):
|
||||||
logo_box = Square(side_length=2.5)
|
logo_box = Square(side_length=2.5)
|
||||||
|
@ -202,12 +208,13 @@ class PatreonEndScreen(PatreonThanks):
|
||||||
line = DashedLine(FRAME_X_RADIUS * LEFT, FRAME_X_RADIUS * RIGHT)
|
line = DashedLine(FRAME_X_RADIUS * LEFT, FRAME_X_RADIUS * RIGHT)
|
||||||
line.move_to(ORIGIN)
|
line.move_to(ORIGIN)
|
||||||
|
|
||||||
thanks = TextMobject("Funded by the community, with special thanks to:")
|
thanks = TextMobject(self.thanks_words)
|
||||||
thanks.scale(0.9)
|
thanks.scale(0.9)
|
||||||
thanks.next_to(black_rect.get_bottom(), UP, SMALL_BUFF)
|
thanks.next_to(black_rect.get_bottom(), UP, SMALL_BUFF)
|
||||||
thanks.set_color(YELLOW)
|
thanks.set_color(YELLOW)
|
||||||
underline = Line(LEFT, RIGHT)
|
underline = Line(LEFT, RIGHT)
|
||||||
underline.set_width(thanks.get_width() + MED_SMALL_BUFF)
|
underline.match_width(thanks)
|
||||||
|
underline.scale(1.1)
|
||||||
underline.next_to(thanks, DOWN, SMALL_BUFF)
|
underline.next_to(thanks, DOWN, SMALL_BUFF)
|
||||||
thanks.add(underline)
|
thanks.add(underline)
|
||||||
|
|
||||||
|
@ -233,13 +240,22 @@ class PatreonEndScreen(PatreonThanks):
|
||||||
thanks.to_edge(RIGHT)
|
thanks.to_edge(RIGHT)
|
||||||
columns.next_to(thanks, DOWN, 3 * LARGE_BUFF)
|
columns.next_to(thanks, DOWN, 3 * LARGE_BUFF)
|
||||||
|
|
||||||
self.add(columns, black_rect, line, thanks)
|
columns.generate_target()
|
||||||
self.play(
|
columns.target.move_to(2 * DOWN, DOWN)
|
||||||
columns.move_to, 2 * DOWN, DOWN,
|
columns.target.align_to(
|
||||||
columns.align_to, thanks, {"alignment_vect": RIGHT},
|
thanks, alignment_vect=RIGHT
|
||||||
rate_func=None,
|
|
||||||
run_time=self.run_time,
|
|
||||||
)
|
)
|
||||||
|
vect = columns.target.get_center() - columns.get_center()
|
||||||
|
distance = get_norm(vect)
|
||||||
|
wait_time = 20
|
||||||
|
columns_shift = ContinualMovement(
|
||||||
|
columns,
|
||||||
|
direction=normalize(vect),
|
||||||
|
rate=(distance / wait_time)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.add(columns_shift, black_rect, line, thanks)
|
||||||
|
self.wait(wait_time)
|
||||||
|
|
||||||
|
|
||||||
class LogoGenerationTemplate(MovingCameraScene):
|
class LogoGenerationTemplate(MovingCameraScene):
|
||||||
|
|
|
@ -481,6 +481,19 @@ class DashedLine(Line):
|
||||||
return self.end
|
return self.end
|
||||||
|
|
||||||
|
|
||||||
|
class Elbow(VMobject):
|
||||||
|
CONFIG = {
|
||||||
|
"width": 0.2,
|
||||||
|
"angle": 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
VMobject.__init__(self, **kwargs)
|
||||||
|
self.set_points_as_corners([UP, UP + RIGHT, RIGHT])
|
||||||
|
self.set_width(self.width, about_point=ORIGIN)
|
||||||
|
self.rotate(self.angle, about_point=ORIGIN)
|
||||||
|
|
||||||
|
|
||||||
class Arrow(Line):
|
class Arrow(Line):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"tip_length": 0.25,
|
"tip_length": 0.25,
|
||||||
|
|
|
@ -18,7 +18,6 @@ from utils.iterables import list_update
|
||||||
from utils.iterables import remove_list_redundancies
|
from utils.iterables import remove_list_redundancies
|
||||||
from utils.paths import straight_path
|
from utils.paths import straight_path
|
||||||
from utils.space_ops import angle_of_vector
|
from utils.space_ops import angle_of_vector
|
||||||
from utils.space_ops import complex_to_R3
|
|
||||||
from utils.space_ops import rotation_matrix
|
from utils.space_ops import rotation_matrix
|
||||||
from utils.simple_functions import get_num_args
|
from utils.simple_functions import get_num_args
|
||||||
from utils.space_ops import get_norm
|
from utils.space_ops import get_norm
|
||||||
|
@ -270,10 +269,15 @@ class Mobject(Container):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def apply_complex_function(self, function, **kwargs):
|
def apply_complex_function(self, function, **kwargs):
|
||||||
return self.apply_function(
|
def R3_func(point):
|
||||||
lambda x_y_z: complex_to_R3(function(complex(x_y_z[0], x_y_z[1]))),
|
x, y, z = point
|
||||||
**kwargs
|
xy_complex = function(complex(x, y))
|
||||||
)
|
return [
|
||||||
|
xy_complex.real,
|
||||||
|
xy_complex.imag,
|
||||||
|
z
|
||||||
|
]
|
||||||
|
return self.apply_function(R3_func)
|
||||||
|
|
||||||
def wag(self, direction=RIGHT, axis=DOWN, wag_factor=1.0):
|
def wag(self, direction=RIGHT, axis=DOWN, wag_factor=1.0):
|
||||||
for mob in self.family_members_with_points():
|
for mob in self.family_members_with_points():
|
||||||
|
|
|
@ -42,7 +42,7 @@ class ParametricSurface(VGroup):
|
||||||
if self.should_make_jagged:
|
if self.should_make_jagged:
|
||||||
self.make_jagged()
|
self.make_jagged()
|
||||||
|
|
||||||
def setup_in_uv_space(self):
|
def get_u_values_and_v_values(self):
|
||||||
res = tuplify(self.resolution)
|
res = tuplify(self.resolution)
|
||||||
if len(res) == 1:
|
if len(res) == 1:
|
||||||
u_res = v_res = res[0]
|
u_res = v_res = res[0]
|
||||||
|
@ -55,9 +55,14 @@ class ParametricSurface(VGroup):
|
||||||
|
|
||||||
u_values = np.linspace(u_min, u_max, u_res + 1)
|
u_values = np.linspace(u_min, u_max, u_res + 1)
|
||||||
v_values = np.linspace(v_min, v_max, v_res + 1)
|
v_values = np.linspace(v_min, v_max, v_res + 1)
|
||||||
|
|
||||||
|
return u_values, v_values
|
||||||
|
|
||||||
|
def setup_in_uv_space(self):
|
||||||
|
u_values, v_values = self.get_u_values_and_v_values()
|
||||||
faces = VGroup()
|
faces = VGroup()
|
||||||
for i in range(u_res):
|
for i in range(len(u_values) - 1):
|
||||||
for j in range(v_res):
|
for j in range(len(v_values) - 1):
|
||||||
u1, u2 = u_values[i:i + 2]
|
u1, u2 = u_values[i:i + 2]
|
||||||
v1, v2 = v_values[j:j + 2]
|
v1, v2 = v_values[j:j + 2]
|
||||||
face = ThreeDVMobject()
|
face = ThreeDVMobject()
|
||||||
|
|
|
@ -41,3 +41,13 @@ class ExponentialValueTracker(ValueTracker):
|
||||||
|
|
||||||
def set_value(self, value):
|
def set_value(self, value):
|
||||||
return ValueTracker.set_value(self, np.log(value))
|
return ValueTracker.set_value(self, np.log(value))
|
||||||
|
|
||||||
|
|
||||||
|
class ComplexValueTracker(ValueTracker):
|
||||||
|
def get_value(self):
|
||||||
|
return complex(*self.points[0, :2])
|
||||||
|
|
||||||
|
def set_value(self, z):
|
||||||
|
z = complex(z)
|
||||||
|
self.points[0, :2] = (z.real, z.imag)
|
||||||
|
return self
|
||||||
|
|
339
old_projects/for_flammy.py
Normal file
339
old_projects/for_flammy.py
Normal file
|
@ -0,0 +1,339 @@
|
||||||
|
from big_ol_pile_of_manim_imports import *
|
||||||
|
from old_projects.sphere_area import *
|
||||||
|
|
||||||
|
|
||||||
|
class MadAtMathologer(PiCreatureScene):
|
||||||
|
def create_pi_creature(self):
|
||||||
|
return Mortimer().to_corner(DR)
|
||||||
|
|
||||||
|
def construct(self):
|
||||||
|
morty = self.pi_creature
|
||||||
|
self.play(morty.change, "angry")
|
||||||
|
self.wait(3)
|
||||||
|
self.play(morty.change, "heistant")
|
||||||
|
self.wait(2)
|
||||||
|
self.play(morty.change, "shruggie")
|
||||||
|
self.wait(3)
|
||||||
|
|
||||||
|
|
||||||
|
class JustTheIntegral(Scene):
|
||||||
|
def construct(self):
|
||||||
|
tex = TexMobject("\\int_0^{\\pi / 2} \\cos(\\theta)d\\theta")
|
||||||
|
tex.scale(2)
|
||||||
|
self.add(tex)
|
||||||
|
|
||||||
|
|
||||||
|
class SphereVideoWrapper(Scene):
|
||||||
|
def construct(self):
|
||||||
|
title = TextMobject("Surface area of a sphere")
|
||||||
|
title.scale(1.5)
|
||||||
|
title.to_edge(UP)
|
||||||
|
rect = ScreenRectangle(height=6)
|
||||||
|
rect.next_to(title, DOWN)
|
||||||
|
self.add(title)
|
||||||
|
self.play(ShowCreation(rect))
|
||||||
|
self.wait()
|
||||||
|
|
||||||
|
|
||||||
|
class SphereRings(SecondProof):
|
||||||
|
CONFIG = {
|
||||||
|
"sphere_config": {
|
||||||
|
"resolution": (60, 60),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
def construct(self):
|
||||||
|
self.setup_shapes()
|
||||||
|
self.grow_rings()
|
||||||
|
self.show_one_ring()
|
||||||
|
self.show_radial_line()
|
||||||
|
self.show_thickness()
|
||||||
|
self.flash_through_rings()
|
||||||
|
|
||||||
|
def grow_rings(self):
|
||||||
|
sphere = self.sphere
|
||||||
|
rings = self.rings
|
||||||
|
north_rings = rings[:len(rings) // 2]
|
||||||
|
sphere.set_fill(opacity=0)
|
||||||
|
sphere.set_stroke(WHITE, 0.5, opacity=0.5)
|
||||||
|
southern_mesh = VGroup(*[
|
||||||
|
face.copy() for face in sphere
|
||||||
|
if face.get_center()[2] < 0
|
||||||
|
])
|
||||||
|
southern_mesh.set_stroke(WHITE, 0.1, 0.5)
|
||||||
|
|
||||||
|
self.play(Write(sphere))
|
||||||
|
self.wait()
|
||||||
|
self.play(
|
||||||
|
FadeOut(sphere),
|
||||||
|
FadeIn(southern_mesh),
|
||||||
|
FadeIn(north_rings),
|
||||||
|
)
|
||||||
|
self.wait(4)
|
||||||
|
|
||||||
|
self.north_rings = north_rings
|
||||||
|
self.southern_mesh = southern_mesh
|
||||||
|
|
||||||
|
def show_one_ring(self):
|
||||||
|
north_rings = self.north_rings
|
||||||
|
index = len(north_rings) // 2
|
||||||
|
ring = north_rings[index]
|
||||||
|
to_fade = VGroup(*[
|
||||||
|
nr for nr in north_rings
|
||||||
|
if nr is not ring
|
||||||
|
])
|
||||||
|
|
||||||
|
north_rings.save_state()
|
||||||
|
|
||||||
|
circle = Circle()
|
||||||
|
circle.set_stroke(PINK, 5)
|
||||||
|
circle.set_width(ring.get_width())
|
||||||
|
circle.move_to(ring, IN)
|
||||||
|
|
||||||
|
thickness = ring.get_depth() * np.sqrt(2)
|
||||||
|
brace = Brace(Line(ORIGIN, 0.2 * RIGHT), UP)
|
||||||
|
brace.set_width(thickness)
|
||||||
|
brace.rotate(90 * DEGREES, RIGHT)
|
||||||
|
brace.rotate(45 * DEGREES, UP)
|
||||||
|
brace.move_to(1.5 * (RIGHT + OUT))
|
||||||
|
brace.set_stroke(WHITE, 1)
|
||||||
|
word = TextMobject("Thickness")
|
||||||
|
word.rotate(90 * DEGREES, RIGHT)
|
||||||
|
word.next_to(brace, RIGHT + OUT, buff=0)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
to_fade.set_fill, {"opacity": 0.2},
|
||||||
|
to_fade.set_stroke, {"opacity": 0.0},
|
||||||
|
)
|
||||||
|
self.move_camera(
|
||||||
|
phi=0, theta=-90 * DEGREES,
|
||||||
|
run_time=2,
|
||||||
|
)
|
||||||
|
self.stop_ambient_camera_rotation()
|
||||||
|
self.play(ShowCreation(circle))
|
||||||
|
self.play(FadeOut(circle))
|
||||||
|
self.move_camera(
|
||||||
|
phi=70 * DEGREES,
|
||||||
|
theta=-100 * DEGREES,
|
||||||
|
run_time=2,
|
||||||
|
)
|
||||||
|
self.begin_ambient_camera_rotation(0.02)
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(brace),
|
||||||
|
Write(word),
|
||||||
|
)
|
||||||
|
self.wait(2)
|
||||||
|
self.play(FadeOut(VGroup(brace, word)))
|
||||||
|
|
||||||
|
self.circum_circle = circle
|
||||||
|
self.thickness_label = VGroup(brace, word)
|
||||||
|
self.ring = ring
|
||||||
|
|
||||||
|
def show_radial_line(self):
|
||||||
|
ring = self.ring
|
||||||
|
|
||||||
|
point = ring.get_corner(RIGHT + IN)
|
||||||
|
R_line = Line(ORIGIN, point)
|
||||||
|
xy_line = Line(ORIGIN, self.sphere.get_right())
|
||||||
|
theta = np.arccos(np.dot(
|
||||||
|
normalize(R_line.get_vector()),
|
||||||
|
normalize(xy_line.get_vector())
|
||||||
|
))
|
||||||
|
arc = Arc(angle=theta, radius=0.5)
|
||||||
|
arc.rotate(90 * DEGREES, RIGHT, about_point=ORIGIN)
|
||||||
|
|
||||||
|
theta = TexMobject("\\theta")
|
||||||
|
theta.rotate(90 * DEGREES, RIGHT)
|
||||||
|
theta.next_to(arc, RIGHT)
|
||||||
|
theta.shift(SMALL_BUFF * (LEFT + OUT))
|
||||||
|
|
||||||
|
R_label = TexMobject("R")
|
||||||
|
R_label.rotate(90 * DEGREES, RIGHT)
|
||||||
|
R_label.next_to(
|
||||||
|
R_line.get_center(), OUT + LEFT,
|
||||||
|
buff=SMALL_BUFF
|
||||||
|
)
|
||||||
|
VGroup(R_label, R_line).set_color(YELLOW)
|
||||||
|
|
||||||
|
z_axis_point = np.array(point)
|
||||||
|
z_axis_point[:2] = 0
|
||||||
|
r_line = DashedLine(z_axis_point, point)
|
||||||
|
r_line.set_color(RED)
|
||||||
|
r_label = TexMobject("R\\cos(\\theta)")
|
||||||
|
r_label.rotate(90 * DEGREES, RIGHT)
|
||||||
|
r_label.scale(0.7)
|
||||||
|
r_label.match_color(r_line)
|
||||||
|
r_label.set_stroke(width=0, background=True)
|
||||||
|
r_label.next_to(r_line, OUT, 0.5 * SMALL_BUFF)
|
||||||
|
|
||||||
|
VGroup(
|
||||||
|
R_label, xy_line, arc, R_label,
|
||||||
|
r_line, r_label,
|
||||||
|
).set_shade_in_3d(True)
|
||||||
|
|
||||||
|
# self.stop_ambient_camera_rotation()
|
||||||
|
self.move_camera(
|
||||||
|
phi=85 * DEGREES,
|
||||||
|
theta=-100 * DEGREES,
|
||||||
|
added_anims=[
|
||||||
|
ring.set_fill, {"opacity": 0.5},
|
||||||
|
ring.set_stroke, {"opacity": 0.1},
|
||||||
|
ShowCreation(R_line),
|
||||||
|
FadeInFrom(R_label, IN),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.wait()
|
||||||
|
self.play(
|
||||||
|
FadeIn(xy_line),
|
||||||
|
ShowCreation(arc),
|
||||||
|
Write(theta),
|
||||||
|
)
|
||||||
|
self.wait()
|
||||||
|
self.play(
|
||||||
|
ShowCreation(r_line),
|
||||||
|
FadeInFrom(r_label, IN),
|
||||||
|
)
|
||||||
|
self.wait()
|
||||||
|
self.move_camera(
|
||||||
|
phi=70 * DEGREES,
|
||||||
|
theta=-110 * DEGREES,
|
||||||
|
run_time=3
|
||||||
|
)
|
||||||
|
self.wait(2)
|
||||||
|
|
||||||
|
def show_thickness(self):
|
||||||
|
brace, word = self.thickness_label
|
||||||
|
R_dtheta = TexMobject("R \\, d\\theta")
|
||||||
|
R_dtheta.rotate(90 * DEGREES, RIGHT)
|
||||||
|
R_dtheta.move_to(word, LEFT)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(brace),
|
||||||
|
Write(R_dtheta)
|
||||||
|
)
|
||||||
|
self.wait(3)
|
||||||
|
|
||||||
|
def flash_through_rings(self):
|
||||||
|
rings = self.north_rings.copy()
|
||||||
|
rings.fade(1)
|
||||||
|
rings.sort_submobjects(lambda p: p[2])
|
||||||
|
|
||||||
|
for x in range(8):
|
||||||
|
self.play(LaggedStart(
|
||||||
|
ApplyMethod, rings,
|
||||||
|
lambda m: (m.set_fill, PINK, 0.5),
|
||||||
|
rate_func=there_and_back,
|
||||||
|
lag_ratio=0.1,
|
||||||
|
run_time=2,
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
class IntegralSymbols(Scene):
|
||||||
|
def construct(self):
|
||||||
|
int_sign = TexMobject("\\displaystyle \\int")
|
||||||
|
int_sign.set_height(1.5)
|
||||||
|
int_sign.move_to(5 * LEFT)
|
||||||
|
|
||||||
|
circumference, times, thickness = ctt = TextMobject(
|
||||||
|
"circumference", "$\\times$", "thickness"
|
||||||
|
)
|
||||||
|
circumference.set_color(MAROON_B)
|
||||||
|
ctt.next_to(int_sign, RIGHT, SMALL_BUFF)
|
||||||
|
area_brace = Brace(ctt, DOWN)
|
||||||
|
area_text = area_brace.get_text("Area of a ring")
|
||||||
|
|
||||||
|
all_rings = TextMobject("All rings")
|
||||||
|
all_rings.scale(0.5)
|
||||||
|
all_rings.next_to(int_sign, DOWN, SMALL_BUFF)
|
||||||
|
all_rings.shift(SMALL_BUFF * LEFT)
|
||||||
|
|
||||||
|
circum_formula = TexMobject(
|
||||||
|
"2\\pi", "R\\cos(\\theta)",
|
||||||
|
)
|
||||||
|
circum_formula[1].set_color(RED)
|
||||||
|
circum_formula.move_to(circumference)
|
||||||
|
circum_brace = Brace(circum_formula, UP)
|
||||||
|
|
||||||
|
R_dtheta = TexMobject("R \\, d\\theta")
|
||||||
|
R_dtheta.move_to(thickness, LEFT)
|
||||||
|
R_dtheta_brace = Brace(R_dtheta, UP)
|
||||||
|
|
||||||
|
zero, pi_halves = bounds = TexMobject("0", "\\pi / 2")
|
||||||
|
bounds.scale(0.5)
|
||||||
|
zero.move_to(all_rings)
|
||||||
|
pi_halves.next_to(int_sign, UP, SMALL_BUFF)
|
||||||
|
pi_halves.shift(SMALL_BUFF * RIGHT)
|
||||||
|
|
||||||
|
self.add(int_sign)
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(area_brace),
|
||||||
|
FadeInFrom(area_text, UP),
|
||||||
|
)
|
||||||
|
self.wait()
|
||||||
|
self.play(FadeInFromDown(circumference))
|
||||||
|
self.play(
|
||||||
|
FadeInFromDown(thickness),
|
||||||
|
Write(times)
|
||||||
|
)
|
||||||
|
self.play(Write(all_rings))
|
||||||
|
self.wait()
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
circumference.next_to, circum_brace, UP, MED_SMALL_BUFF,
|
||||||
|
circumference.shift, SMALL_BUFF * UR,
|
||||||
|
GrowFromCenter(circum_brace),
|
||||||
|
)
|
||||||
|
self.play(FadeInFrom(circum_formula, UP))
|
||||||
|
self.wait()
|
||||||
|
self.play(
|
||||||
|
thickness.next_to, circumference, RIGHT, MED_SMALL_BUFF,
|
||||||
|
GrowFromCenter(R_dtheta_brace),
|
||||||
|
area_brace.stretch, 0.84, 0, {"about_edge": LEFT},
|
||||||
|
MaintainPositionRelativeTo(area_text, area_brace),
|
||||||
|
)
|
||||||
|
self.play(FadeInFrom(R_dtheta, UP))
|
||||||
|
self.wait()
|
||||||
|
self.play(ReplacementTransform(all_rings, bounds))
|
||||||
|
self.wait()
|
||||||
|
|
||||||
|
# RHS
|
||||||
|
rhs = TexMobject(
|
||||||
|
"\\displaystyle =", "2\\pi R^2", "\\int_0^{\\pi / 2}",
|
||||||
|
"\\cos(\\theta)", "d\\theta",
|
||||||
|
)
|
||||||
|
rhs.set_color_by_tex("cos", RED)
|
||||||
|
rhs.next_to(R_dtheta, RIGHT)
|
||||||
|
int_brace = Brace(rhs[2:], DOWN)
|
||||||
|
q_marks = int_brace.get_text("???")
|
||||||
|
one = TexMobject("1")
|
||||||
|
one.move_to(q_marks)
|
||||||
|
|
||||||
|
self.play(FadeInFrom(rhs, 4 * LEFT))
|
||||||
|
self.wait()
|
||||||
|
self.play(CircleThenFadeAround(rhs[1]))
|
||||||
|
self.wait()
|
||||||
|
self.play(CircleThenFadeAround(rhs[2:]))
|
||||||
|
self.wait()
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(int_brace),
|
||||||
|
LaggedStart(
|
||||||
|
FadeInFrom, q_marks,
|
||||||
|
lambda m: (m, UP),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.wait()
|
||||||
|
self.play(ReplacementTransform(q_marks, one))
|
||||||
|
self.wait()
|
||||||
|
|
||||||
|
|
||||||
|
class ShamelessPlug(TeacherStudentsScene):
|
||||||
|
def construct(self):
|
||||||
|
self.student_says(
|
||||||
|
"But why $4\\pi R^2$?",
|
||||||
|
target_mode="maybe"
|
||||||
|
)
|
||||||
|
self.change_student_modes(
|
||||||
|
"erm", "maybe", "happy",
|
||||||
|
added_anims=[self.teacher.change, "happy"]
|
||||||
|
)
|
||||||
|
self.wait(3)
|
|
@ -1,47 +1,4 @@
|
||||||
from big_ol_pile_of_manim_imports import *
|
from big_ol_pile_of_manim_imports import *
|
||||||
# from pprint import pprint
|
|
||||||
|
|
||||||
|
|
||||||
# Helpers
|
|
||||||
def get_three_d_scene_config(high_quality=True):
|
|
||||||
hq_config = {
|
|
||||||
"camera_config": {
|
|
||||||
"should_apply_shading": True,
|
|
||||||
"exponential_projection": True,
|
|
||||||
},
|
|
||||||
"three_d_axes_config": {
|
|
||||||
"num_axis_pieces": 1,
|
|
||||||
"number_line_config": {
|
|
||||||
"unit_size": 2,
|
|
||||||
# "tick_frequency": 0.5,
|
|
||||||
"tick_frequency": 1,
|
|
||||||
"numbers_with_elongated_ticks": [0, 1, 2],
|
|
||||||
"stroke_width": 2,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sphere_config": {
|
|
||||||
"radius": 2,
|
|
||||||
"resolution": (24, 48),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lq_added_config = {
|
|
||||||
"camera_config": {
|
|
||||||
"should_apply_shading": False,
|
|
||||||
},
|
|
||||||
"three_d_axes_config": {
|
|
||||||
"num_axis_pieces": 1,
|
|
||||||
},
|
|
||||||
"sphere_config": {
|
|
||||||
"resolution": (12, 24),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if high_quality:
|
|
||||||
return hq_config
|
|
||||||
else:
|
|
||||||
return merge_config([
|
|
||||||
lq_added_config,
|
|
||||||
hq_config
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
def q_mult(q1, q2):
|
def q_mult(q1, q2):
|
||||||
|
@ -459,53 +416,6 @@ class RubiksCube(VGroup):
|
||||||
|
|
||||||
|
|
||||||
# Abstract scenes
|
# Abstract scenes
|
||||||
class SpecialThreeDScene(ThreeDScene):
|
|
||||||
CONFIG = {
|
|
||||||
"cut_axes_at_radius": True,
|
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
digest_config(self, kwargs)
|
|
||||||
if self.frame_duration == PRODUCTION_QUALITY_FRAME_DURATION:
|
|
||||||
high_quality = True
|
|
||||||
else:
|
|
||||||
high_quality = False
|
|
||||||
default_config = get_three_d_scene_config(high_quality)
|
|
||||||
config = merge_config([self.CONFIG, kwargs, default_config])
|
|
||||||
ThreeDScene.__init__(self, **config)
|
|
||||||
|
|
||||||
def get_axes(self):
|
|
||||||
axes = ThreeDAxes(**self.three_d_axes_config)
|
|
||||||
for axis in axes:
|
|
||||||
if self.cut_axes_at_radius:
|
|
||||||
p0 = axis.main_line.get_start()
|
|
||||||
p1 = axis.number_to_point(-1)
|
|
||||||
p2 = axis.number_to_point(1)
|
|
||||||
p3 = axis.main_line.get_end()
|
|
||||||
new_pieces = VGroup(
|
|
||||||
Line(p0, p1), Line(p1, p2), Line(p2, p3),
|
|
||||||
)
|
|
||||||
for piece in new_pieces:
|
|
||||||
piece.shade_in_3d = True
|
|
||||||
new_pieces.match_style(axis.pieces)
|
|
||||||
axis.pieces.submobjects = new_pieces.submobjects
|
|
||||||
for tick in axis.tick_marks:
|
|
||||||
tick.add(VectorizedPoint(
|
|
||||||
1.5 * tick.get_center(),
|
|
||||||
))
|
|
||||||
return axes
|
|
||||||
|
|
||||||
def get_sphere(self):
|
|
||||||
return Sphere(**self.sphere_config)
|
|
||||||
|
|
||||||
def get_default_camera_position(self):
|
|
||||||
return {
|
|
||||||
"phi": 70 * DEGREES,
|
|
||||||
"theta": -110 * DEGREES,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Animated scenes
|
|
||||||
|
|
||||||
|
|
||||||
class ManyNumberSystems(Scene):
|
class ManyNumberSystems(Scene):
|
||||||
|
|
3708
old_projects/sphere_area.py
Normal file
3708
old_projects/sphere_area.py
Normal file
File diff suppressed because it is too large
Load diff
|
@ -3265,18 +3265,23 @@ class Thumbnail(ZetaTransformationScene):
|
||||||
"anchor_density" : 35
|
"anchor_density" : 35
|
||||||
}
|
}
|
||||||
def construct(self):
|
def construct(self):
|
||||||
|
self.y_min = -4
|
||||||
|
self.y_max = 4
|
||||||
|
self.x_min = 1
|
||||||
|
self.x_max = int(FRAME_X_RADIUS+2)
|
||||||
self.add_transformable_plane()
|
self.add_transformable_plane()
|
||||||
self.add_extra_plane_lines_for_zeta()
|
self.add_extra_plane_lines_for_zeta()
|
||||||
self.add_reflected_plane()
|
self.add_reflected_plane()
|
||||||
self.apply_zeta_function()
|
# self.apply_zeta_function()
|
||||||
self.plane.set_stroke(width = 4)
|
self.plane.set_stroke(width = 4)
|
||||||
|
|
||||||
div_sum = TexMobject("-\\frac{1}{12} = ", "1+2+3+4+\\cdots")
|
div_sum = TexMobject("-\\frac{1}{12} = ", "1+2+3+4+\\cdots")
|
||||||
div_sum.set_width(FRAME_WIDTH-1)
|
div_sum.set_width(FRAME_WIDTH-1)
|
||||||
div_sum.to_edge(DOWN)
|
div_sum.to_edge(DOWN)
|
||||||
div_sum.set_color(YELLOW)
|
div_sum.set_color(YELLOW)
|
||||||
for mob in div_sum.submobjects:
|
div_sum.set_background_stroke(width=8)
|
||||||
mob.add_to_back(BackgroundRectangle(mob))
|
# for mob in div_sum.submobjects:
|
||||||
|
# mob.add_to_back(BackgroundRectangle(mob))
|
||||||
|
|
||||||
zeta = TexMobject("\\zeta(s)")
|
zeta = TexMobject("\\zeta(s)")
|
||||||
zeta.set_height(FRAME_Y_RADIUS-1)
|
zeta.set_height(FRAME_Y_RADIUS-1)
|
||||||
|
@ -3286,7 +3291,7 @@ class Thumbnail(ZetaTransformationScene):
|
||||||
million.set_width(FRAME_X_RADIUS+1)
|
million.set_width(FRAME_X_RADIUS+1)
|
||||||
million.to_edge(UP+RIGHT)
|
million.to_edge(UP+RIGHT)
|
||||||
million.set_color(GREEN_B)
|
million.set_color(GREEN_B)
|
||||||
million.add_background_rectangle()
|
million.set_background_stroke(width=8)
|
||||||
|
|
||||||
self.add(div_sum, million, zeta)
|
self.add(div_sum, million, zeta)
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,26 @@
|
||||||
from constants import *
|
from constants import DEGREES
|
||||||
|
from constants import PRODUCTION_QUALITY_FRAME_DURATION
|
||||||
from continual_animation.update import ContinualGrowValue
|
from continual_animation.update import ContinualGrowValue
|
||||||
from animation.transform import ApplyMethod
|
from animation.transform import ApplyMethod
|
||||||
from camera.three_d_camera import ThreeDCamera
|
from camera.three_d_camera import ThreeDCamera
|
||||||
|
from mobject.coordinate_systems import ThreeDAxes
|
||||||
|
from mobject.geometry import Line
|
||||||
|
from mobject.three_dimensions import Sphere
|
||||||
|
from mobject.types.vectorized_mobject import VGroup
|
||||||
|
from mobject.types.vectorized_mobject import VectorizedPoint
|
||||||
from scene.scene import Scene
|
from scene.scene import Scene
|
||||||
|
from utils.config_ops import digest_config
|
||||||
|
from utils.config_ops import merge_config
|
||||||
|
|
||||||
|
|
||||||
class ThreeDScene(Scene):
|
class ThreeDScene(Scene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"camera_class": ThreeDCamera,
|
"camera_class": ThreeDCamera,
|
||||||
"ambient_camera_rotation": None,
|
"ambient_camera_rotation": None,
|
||||||
|
"default_angled_camera_orientation_kwargs": {
|
||||||
|
"phi": 70 * DEGREES,
|
||||||
|
"theta": -135 * DEGREES,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def set_camera_orientation(self, phi=None, theta=None, distance=None, gamma=None):
|
def set_camera_orientation(self, phi=None, theta=None, distance=None, gamma=None):
|
||||||
|
@ -22,7 +33,7 @@ class ThreeDScene(Scene):
|
||||||
if gamma is not None:
|
if gamma is not None:
|
||||||
self.camera.set_gamma(gamma)
|
self.camera.set_gamma(gamma)
|
||||||
|
|
||||||
def begin_ambient_camera_rotation(self, rate=0.05):
|
def begin_ambient_camera_rotation(self, rate=0.02):
|
||||||
self.ambient_camera_rotation = ContinualGrowValue(
|
self.ambient_camera_rotation = ContinualGrowValue(
|
||||||
self.camera.theta_tracker,
|
self.camera.theta_tracker,
|
||||||
rate=rate
|
rate=rate
|
||||||
|
@ -86,3 +97,90 @@ class ThreeDScene(Scene):
|
||||||
|
|
||||||
def remove_fixed_in_frame_mobjects(self, *mobjects):
|
def remove_fixed_in_frame_mobjects(self, *mobjects):
|
||||||
self.camera.remove_fixed_in_frame_mobjects(*mobjects)
|
self.camera.remove_fixed_in_frame_mobjects(*mobjects)
|
||||||
|
|
||||||
|
##
|
||||||
|
def set_to_default_angled_camera_orientation(self, **kwargs):
|
||||||
|
config = dict(self.default_camera_orientation_kwargs)
|
||||||
|
config.update(kwargs)
|
||||||
|
self.set_camera_orientation(**config)
|
||||||
|
|
||||||
|
|
||||||
|
class SpecialThreeDScene(ThreeDScene):
|
||||||
|
CONFIG = {
|
||||||
|
"cut_axes_at_radius": True,
|
||||||
|
"camera_config": {
|
||||||
|
"should_apply_shading": True,
|
||||||
|
"exponential_projection": True,
|
||||||
|
},
|
||||||
|
"three_d_axes_config": {
|
||||||
|
"num_axis_pieces": 1,
|
||||||
|
"number_line_config": {
|
||||||
|
"unit_size": 2,
|
||||||
|
"tick_frequency": 1,
|
||||||
|
"numbers_with_elongated_ticks": [0, 1, 2],
|
||||||
|
"stroke_width": 2,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sphere_config": {
|
||||||
|
"radius": 2,
|
||||||
|
"resolution": (24, 48),
|
||||||
|
},
|
||||||
|
"default_angled_camera_position": {
|
||||||
|
"phi": 70 * DEGREES,
|
||||||
|
"theta": -110 * DEGREES,
|
||||||
|
},
|
||||||
|
# When scene is extracted with -l flag, this
|
||||||
|
# configuration will override the above configuration.
|
||||||
|
"low_quality_config": {
|
||||||
|
"camera_config": {
|
||||||
|
"should_apply_shading": False,
|
||||||
|
},
|
||||||
|
"three_d_axes_config": {
|
||||||
|
"num_axis_pieces": 1,
|
||||||
|
},
|
||||||
|
"sphere_config": {
|
||||||
|
"resolution": (12, 24),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
digest_config(self, kwargs)
|
||||||
|
if self.frame_duration == PRODUCTION_QUALITY_FRAME_DURATION:
|
||||||
|
config = {}
|
||||||
|
else:
|
||||||
|
config = self.low_quality_config
|
||||||
|
ThreeDScene.__init__(self, **merge_config([kwargs, config]))
|
||||||
|
|
||||||
|
def get_axes(self):
|
||||||
|
axes = ThreeDAxes(**self.three_d_axes_config)
|
||||||
|
for axis in axes:
|
||||||
|
if self.cut_axes_at_radius:
|
||||||
|
p0 = axis.main_line.get_start()
|
||||||
|
p1 = axis.number_to_point(-1)
|
||||||
|
p2 = axis.number_to_point(1)
|
||||||
|
p3 = axis.main_line.get_end()
|
||||||
|
new_pieces = VGroup(
|
||||||
|
Line(p0, p1), Line(p1, p2), Line(p2, p3),
|
||||||
|
)
|
||||||
|
for piece in new_pieces:
|
||||||
|
piece.shade_in_3d = True
|
||||||
|
new_pieces.match_style(axis.pieces)
|
||||||
|
axis.pieces.submobjects = new_pieces.submobjects
|
||||||
|
for tick in axis.tick_marks:
|
||||||
|
tick.add(VectorizedPoint(
|
||||||
|
1.5 * tick.get_center(),
|
||||||
|
))
|
||||||
|
return axes
|
||||||
|
|
||||||
|
def get_sphere(self, **kwargs):
|
||||||
|
config = merge_config([kwargs, self.sphere_config])
|
||||||
|
return Sphere(**config)
|
||||||
|
|
||||||
|
def get_default_camera_position(self):
|
||||||
|
return self.default_angled_camera_position
|
||||||
|
|
||||||
|
def set_camera_to_default_position(self):
|
||||||
|
self.set_camera_orientation(
|
||||||
|
**self.default_angled_camera_position
|
||||||
|
)
|
||||||
|
|
|
@ -57,6 +57,13 @@ def digest_config(obj, kwargs, caller_locals={}):
|
||||||
|
|
||||||
|
|
||||||
def merge_config(all_dicts):
|
def merge_config(all_dicts):
|
||||||
|
"""
|
||||||
|
Creates a dict whose keyset is the union of all the
|
||||||
|
input dictionaries. The value for each key is based
|
||||||
|
on the first dict in the list with that key.
|
||||||
|
|
||||||
|
When values are dictionaries, it is applied recursively
|
||||||
|
"""
|
||||||
all_config = reduce(op.add, [list(d.items()) for d in all_dicts])
|
all_config = reduce(op.add, [list(d.items()) for d in all_dicts])
|
||||||
config = dict()
|
config = dict()
|
||||||
for c in all_config:
|
for c in all_config:
|
||||||
|
|
Loading…
Add table
Reference in a new issue