mirror of
https://github.com/3b1b/manim.git
synced 2025-08-01 06:22:54 +08:00
Up to ShowHighVelocityCase in ode part 1
This commit is contained in:
@ -33,4 +33,8 @@ ALL_SCENE_CLASSES = [
|
|||||||
VisualizeStates,
|
VisualizeStates,
|
||||||
IntroduceVectorField,
|
IntroduceVectorField,
|
||||||
BreakingSecondOrderIntoTwoFirstOrder,
|
BreakingSecondOrderIntoTwoFirstOrder,
|
||||||
|
ShowPendulumPhaseFlow,
|
||||||
|
ShowHighVelocityCase,
|
||||||
|
TweakMuInFormula,
|
||||||
|
TweakMuInVectorField,
|
||||||
]
|
]
|
||||||
|
@ -90,6 +90,9 @@ class Pendulum(VGroup):
|
|||||||
self.get_fixed_point() + self.length * DOWN,
|
self.get_fixed_point() + self.length * DOWN,
|
||||||
**self.dashed_line_config
|
**self.dashed_line_config
|
||||||
)
|
)
|
||||||
|
line.add_updater(
|
||||||
|
lambda l: l.move_to(self.get_fixed_point(), UP)
|
||||||
|
)
|
||||||
self.add_to_back(line)
|
self.add_to_back(line)
|
||||||
|
|
||||||
def create_angle_arc(self):
|
def create_angle_arc(self):
|
||||||
|
@ -439,6 +439,9 @@ class VisualizeStates(Scene):
|
|||||||
top_point=rect.get_center(),
|
top_point=rect.get_center(),
|
||||||
**self.big_pendulum_config
|
**self.big_pendulum_config
|
||||||
)
|
)
|
||||||
|
pendulum.fixed_point_tracker.add_updater(
|
||||||
|
lambda m: m.move_to(rect.get_center())
|
||||||
|
)
|
||||||
|
|
||||||
state = VGroup(rect, pendulum)
|
state = VGroup(rect, pendulum)
|
||||||
state.rect = rect
|
state.rect = rect
|
||||||
@ -514,7 +517,7 @@ class IntroduceVectorField(VisualizeStates):
|
|||||||
# "delta_y": 2,
|
# "delta_y": 2,
|
||||||
},
|
},
|
||||||
"big_pendulum_config": {
|
"big_pendulum_config": {
|
||||||
"initial_theta": -60 * DEGREES,
|
"initial_theta": -80 * DEGREES,
|
||||||
"omega": 1,
|
"omega": 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -840,21 +843,24 @@ class IntroduceVectorField(VisualizeStates):
|
|||||||
bracket_v_buff=SMALL_BUFF,
|
bracket_v_buff=SMALL_BUFF,
|
||||||
element_to_mobject_config={
|
element_to_mobject_config={
|
||||||
"tex_to_color_map": {
|
"tex_to_color_map": {
|
||||||
|
"{\\theta}": BLUE,
|
||||||
"{\\dot\\theta}": YELLOW,
|
"{\\dot\\theta}": YELLOW,
|
||||||
|
"{\\omega}": YELLOW,
|
||||||
"{\\ddot\\theta}": RED,
|
"{\\ddot\\theta}": RED,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
element_alignment_corner=ORIGIN,
|
element_alignment_corner=ORIGIN,
|
||||||
).scale(0.9)
|
).scale(0.9)
|
||||||
|
|
||||||
def vector_field_func(self, point):
|
def vector_field_func(self, point):
|
||||||
x, y = self.plane.point_to_coords(point)
|
x, y = self.plane.point_to_coords(point)
|
||||||
pend = self.state.pendulum
|
mu, g, L = [
|
||||||
|
self.big_pendulum_config.get(key)
|
||||||
|
for key in ["damping", "gravity", "length"]
|
||||||
|
]
|
||||||
return pendulum_vector_field_func(
|
return pendulum_vector_field_func(
|
||||||
x * RIGHT + y * UP,
|
x * RIGHT + y * UP,
|
||||||
mu=pend.damping,
|
mu=mu, g=g, L=L
|
||||||
g=pend.gravity,
|
|
||||||
L=pend.length,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def ask_about_change(self):
|
def ask_about_change(self):
|
||||||
@ -890,3 +896,114 @@ class IntroduceVectorField(VisualizeStates):
|
|||||||
0.3 * d_vect.get_vector(),
|
0.3 * d_vect.get_vector(),
|
||||||
rate_func=there_and_back,
|
rate_func=there_and_back,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ShowPendulumPhaseFlow(IntroduceVectorField):
|
||||||
|
CONFIG = {
|
||||||
|
"coordinate_plane_config": {
|
||||||
|
"x_axis_config": {
|
||||||
|
"unit_size": 0.8,
|
||||||
|
},
|
||||||
|
"x_max": 9,
|
||||||
|
"x_min": -9,
|
||||||
|
},
|
||||||
|
"flow_time": 20,
|
||||||
|
}
|
||||||
|
|
||||||
|
def construct(self):
|
||||||
|
self.initialize_plane()
|
||||||
|
self.initialize_vector_field()
|
||||||
|
plane = self.plane
|
||||||
|
field = self.vector_field
|
||||||
|
self.add(plane, field)
|
||||||
|
|
||||||
|
stream_lines = StreamLines(
|
||||||
|
field.func,
|
||||||
|
delta_x=0.3,
|
||||||
|
delta_y=0.3,
|
||||||
|
)
|
||||||
|
animated_stream_lines = AnimatedStreamLines(
|
||||||
|
stream_lines,
|
||||||
|
line_anim_class=ShowPassingFlashWithThinningStrokeWidth,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.add(animated_stream_lines)
|
||||||
|
self.wait(self.flow_time)
|
||||||
|
|
||||||
|
|
||||||
|
class ShowHighVelocityCase(ShowPendulumPhaseFlow, MovingCameraScene):
|
||||||
|
CONFIG = {
|
||||||
|
"coordinate_plane_config": {
|
||||||
|
"x_max": 15,
|
||||||
|
"x_min": -15,
|
||||||
|
},
|
||||||
|
"vector_field_config": {
|
||||||
|
"x_max": 15,
|
||||||
|
},
|
||||||
|
"big_pendulum_config": {
|
||||||
|
"max_velocity_vector_length_to_length_ratio": 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
def setup(self):
|
||||||
|
MovingCameraScene.setup(self)
|
||||||
|
|
||||||
|
def construct(self):
|
||||||
|
self.initialize_plane()
|
||||||
|
self.add(self.plane)
|
||||||
|
self.initialize_vector_field()
|
||||||
|
self.add(self.vector_field)
|
||||||
|
self.add_flexible_state()
|
||||||
|
self.show_trajectory()
|
||||||
|
|
||||||
|
def show_trajectory(self):
|
||||||
|
state = self.state
|
||||||
|
plane = self.plane
|
||||||
|
field = self.vector_field
|
||||||
|
frame = self.camera_frame
|
||||||
|
|
||||||
|
state.to_edge(DOWN, buff=SMALL_BUFF),
|
||||||
|
start_point = plane.coords_to_point(0, 4)
|
||||||
|
dot = self.get_state_controlling_dot(state)
|
||||||
|
dot.move_to(start_point)
|
||||||
|
state.update()
|
||||||
|
|
||||||
|
traj = VMobject()
|
||||||
|
traj.start_new_path(start_point)
|
||||||
|
dt = 0.01
|
||||||
|
total_time = 25
|
||||||
|
for x in range(int(total_time / dt)):
|
||||||
|
end = traj.points[-1]
|
||||||
|
dp_dt = field.func(end)
|
||||||
|
traj.add_smooth_curve_to(end + dp_dt * dt)
|
||||||
|
|
||||||
|
traj.set_stroke(WHITE, 2)
|
||||||
|
|
||||||
|
self.add(traj, dot)
|
||||||
|
self.play(
|
||||||
|
ShowCreation(
|
||||||
|
traj,
|
||||||
|
rate_func=linear,
|
||||||
|
),
|
||||||
|
UpdateFromFunc(
|
||||||
|
dot, lambda d: d.move_to(traj.points[-1])
|
||||||
|
),
|
||||||
|
ApplyMethod(
|
||||||
|
frame.shift, TAU * RIGHT,
|
||||||
|
rate_func=squish_rate_func(
|
||||||
|
smooth, 0, 0.3,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
MaintainPositionRelativeTo(state.rect, frame),
|
||||||
|
run_time=total_time,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TweakMuInFormula(Scene):
|
||||||
|
def construct(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class TweakMuInVectorField(Scene):
|
||||||
|
def construct(self):
|
||||||
|
pass
|
||||||
|
@ -2,6 +2,7 @@ from big_ol_pile_of_manim_imports import *
|
|||||||
from active_projects.ode.part1.shared_constructs import *
|
from active_projects.ode.part1.shared_constructs import *
|
||||||
from active_projects.ode.part1.pendulum import Pendulum
|
from active_projects.ode.part1.pendulum import Pendulum
|
||||||
from active_projects.ode.part1.pendulum import ThetaVsTAxes
|
from active_projects.ode.part1.pendulum import ThetaVsTAxes
|
||||||
|
from active_projects.ode.part1.phase_space import IntroduceVectorField
|
||||||
|
|
||||||
|
|
||||||
# Scenes
|
# Scenes
|
||||||
@ -764,9 +765,80 @@ class ReferencePiCollisionStateSpaces(Scene):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class BreakingSecondOrderIntoTwoFirstOrder(Scene):
|
class BreakingSecondOrderIntoTwoFirstOrder(IntroduceVectorField):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
pass
|
ode = TexMobject(
|
||||||
|
"{\\ddot\\theta}", "(t)", "=",
|
||||||
|
"-\\mu", "{\\dot\\theta}", "(t)"
|
||||||
|
"-(g / L)\\sin\\big(", "{\\theta}", "(t)\\big)",
|
||||||
|
tex_to_color_map={
|
||||||
|
"{\\ddot\\theta}": RED,
|
||||||
|
"{\\dot\\theta}": YELLOW,
|
||||||
|
"{\\theta}": BLUE,
|
||||||
|
# "{t}": WHITE,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
so_word = TextMobject("Second order ODE")
|
||||||
|
sys_word = TextMobject("System of two first order ODEs")
|
||||||
|
|
||||||
|
system1 = self.get_system("{\\theta}", "{\\dot\\theta}")
|
||||||
|
system2 = self.get_system("{\\theta}", "{\\omega}")
|
||||||
|
|
||||||
|
so_word.to_edge(UP)
|
||||||
|
ode.next_to(so_word, DOWN)
|
||||||
|
sys_word.move_to(ORIGIN)
|
||||||
|
system1.next_to(sys_word, DOWN)
|
||||||
|
system2.move_to(system1)
|
||||||
|
|
||||||
|
self.add(ode)
|
||||||
|
self.play(FadeInFrom(so_word, 0.5 * DOWN))
|
||||||
|
self.wait()
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
TransformFromCopy(
|
||||||
|
ode[3:], system1[3].get_entries()[1],
|
||||||
|
),
|
||||||
|
TransformFromCopy(ode[2], system1[2]),
|
||||||
|
TransformFromCopy(
|
||||||
|
ode[:2], VGroup(
|
||||||
|
system1[0],
|
||||||
|
system1[1].get_entries()[1],
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
self.play(
|
||||||
|
FadeIn(system1[1].get_brackets()),
|
||||||
|
FadeIn(system1[1].get_entries()[0]),
|
||||||
|
FadeIn(system1[3].get_brackets()),
|
||||||
|
FadeIn(system1[3].get_entries()[0]),
|
||||||
|
)
|
||||||
|
self.play(
|
||||||
|
FadeInFromDown(sys_word)
|
||||||
|
)
|
||||||
|
self.wait()
|
||||||
|
|
||||||
|
self.play(ReplacementTransform(system1, system2))
|
||||||
|
self.wait()
|
||||||
|
|
||||||
|
def get_system(self, tex1, tex2):
|
||||||
|
system = VGroup(
|
||||||
|
TexMobject("d \\over dt"),
|
||||||
|
self.get_vector_symbol(
|
||||||
|
tex1 + "(t)",
|
||||||
|
tex2 + "(t)",
|
||||||
|
),
|
||||||
|
TexMobject("="),
|
||||||
|
self.get_vector_symbol(
|
||||||
|
tex2 + "(t)",
|
||||||
|
"".join([
|
||||||
|
"-\\mu", tex2, "(t)",
|
||||||
|
"-(g / L) \\sin\\big(",
|
||||||
|
tex1, "(t)", "\\big)",
|
||||||
|
])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
system.arrange(RIGHT)
|
||||||
|
return system
|
||||||
|
|
||||||
|
|
||||||
class NewSceneName(Scene):
|
class NewSceneName(Scene):
|
||||||
|
Reference in New Issue
Block a user