mirror of
https://github.com/3b1b/manim.git
synced 2025-08-01 17:29:06 +08:00
DivergenceAsNewFunction
This commit is contained in:
@ -19,8 +19,10 @@ def get_flow_start_points(x_min=-8, x_max=8,
|
|||||||
y_min=-5, y_max=5,
|
y_min=-5, y_max=5,
|
||||||
delta_x=0.5, delta_y=0.5,
|
delta_x=0.5, delta_y=0.5,
|
||||||
n_repeats=1,
|
n_repeats=1,
|
||||||
noise_factor=0.01
|
noise_factor=None
|
||||||
):
|
):
|
||||||
|
if noise_factor is None:
|
||||||
|
noise_factor = delta_y / 2
|
||||||
return np.array([
|
return np.array([
|
||||||
x * RIGHT + y * UP + noise_factor * np.random.random(3)
|
x * RIGHT + y * UP + noise_factor * np.random.random(3)
|
||||||
for n in xrange(n_repeats)
|
for n in xrange(n_repeats)
|
||||||
@ -1262,6 +1264,7 @@ class DefineDivergence(ChangingElectricField):
|
|||||||
"n_anchors_per_line": 10,
|
"n_anchors_per_line": 10,
|
||||||
"min_magnitude": 0,
|
"min_magnitude": 0,
|
||||||
"max_magnitude": 6,
|
"max_magnitude": 6,
|
||||||
|
"stroke_width": 2,
|
||||||
},
|
},
|
||||||
"stream_line_animation_config": {
|
"stream_line_animation_config": {
|
||||||
"line_anim_class": ShowPassingFlash,
|
"line_anim_class": ShowPassingFlash,
|
||||||
@ -1391,14 +1394,14 @@ class DefineDivergence(ChangingElectricField):
|
|||||||
for point in negative_points:
|
for point in negative_points:
|
||||||
self.play(circle.move_to, point)
|
self.play(circle.move_to, point)
|
||||||
self.wait(2)
|
self.wait(2)
|
||||||
self.wait(2)
|
self.wait(4)
|
||||||
self.remove(div_tex_update)
|
# self.remove(div_tex_update)
|
||||||
self.remove(div_value_update)
|
# self.remove(div_value_update)
|
||||||
self.play(
|
# self.play(
|
||||||
ApplyMethod(circle.scale, 0, remover=True),
|
# ApplyMethod(circle.scale, 0, remover=True),
|
||||||
FadeOut(div_tex),
|
# FadeOut(div_tex),
|
||||||
FadeOut(div_value),
|
# FadeOut(div_value),
|
||||||
)
|
# )
|
||||||
|
|
||||||
|
|
||||||
class DefineDivergenceJustFlow(DefineDivergence):
|
class DefineDivergenceJustFlow(DefineDivergence):
|
||||||
@ -1434,9 +1437,7 @@ class DivergenceAtSlowFastPoint(Scene):
|
|||||||
|
|
||||||
def construct(self):
|
def construct(self):
|
||||||
def func(point):
|
def func(point):
|
||||||
return 4 * inverse_interpolate(
|
return 3 * sigmoid(point[0]) * RIGHT
|
||||||
-FRAME_WIDTH / 2, FRAME_WIDTH / 2, point[0]
|
|
||||||
) * RIGHT
|
|
||||||
vector_field = self.vector_field = VectorField(
|
vector_field = self.vector_field = VectorField(
|
||||||
func, **self.vector_field_config
|
func, **self.vector_field_config
|
||||||
)
|
)
|
||||||
@ -1486,7 +1487,245 @@ class DivergenceAsNewFunction(Scene):
|
|||||||
self.add(plane)
|
self.add(plane)
|
||||||
|
|
||||||
def show_vector_field_function(self):
|
def show_vector_field_function(self):
|
||||||
pass
|
func = self.func
|
||||||
|
unscaled_vector_field = VectorField(
|
||||||
|
func,
|
||||||
|
length_func=lambda norm: norm,
|
||||||
|
colors=[BLUE_C, YELLOW, RED],
|
||||||
|
delta_x=np.inf,
|
||||||
|
delta_y=np.inf,
|
||||||
|
)
|
||||||
|
|
||||||
|
in_dot = Dot(color=PINK)
|
||||||
|
in_dot.move_to(3.75 * LEFT + 1.25 * UP)
|
||||||
|
|
||||||
|
def get_input():
|
||||||
|
return in_dot.get_center()
|
||||||
|
|
||||||
|
def get_out_vect():
|
||||||
|
return unscaled_vector_field.get_vector(get_input())
|
||||||
|
|
||||||
|
# Tex
|
||||||
|
func_tex = TexMobject(
|
||||||
|
"\\textbf{F}(", "+0.00", ",", "+0.00", ")", "=",
|
||||||
|
)
|
||||||
|
dummy_in_x, dummy_in_y = func_tex.get_parts_by_tex("+0.00")
|
||||||
|
func_tex.add_background_rectangle()
|
||||||
|
rhs = DecimalMatrix(
|
||||||
|
[[0], [0]],
|
||||||
|
element_to_mobject_config={
|
||||||
|
"num_decimal_places": 2,
|
||||||
|
"include_sign": True,
|
||||||
|
},
|
||||||
|
include_background_rectangle=True
|
||||||
|
)
|
||||||
|
rhs.next_to(func_tex, RIGHT)
|
||||||
|
dummy_out_x, dummy_out_y = rhs.get_mob_matrix().flatten()
|
||||||
|
|
||||||
|
VGroup(func_tex, rhs).to_corner(UL, buff=MED_SMALL_BUFF)
|
||||||
|
|
||||||
|
VGroup(
|
||||||
|
dummy_in_x, dummy_in_y,
|
||||||
|
dummy_out_x, dummy_out_y,
|
||||||
|
).set_fill(BLACK, opacity=0)
|
||||||
|
|
||||||
|
# Changing decimals
|
||||||
|
in_x, in_y, out_x, out_y = [
|
||||||
|
DecimalNumber(0, include_sign=True)
|
||||||
|
for x in range(4)
|
||||||
|
]
|
||||||
|
VGroup(in_x, in_y).set_color(in_dot.get_color())
|
||||||
|
VGroup(out_x, out_y).set_color(get_out_vect().get_fill_color())
|
||||||
|
in_x_update = ContinualChangingDecimal(
|
||||||
|
in_x, lambda a: get_input()[0],
|
||||||
|
position_update_func=lambda m: m.move_to(dummy_in_x)
|
||||||
|
)
|
||||||
|
in_y_update = ContinualChangingDecimal(
|
||||||
|
in_y, lambda a: get_input()[1],
|
||||||
|
position_update_func=lambda m: m.move_to(dummy_in_y)
|
||||||
|
)
|
||||||
|
out_x_update = ContinualChangingDecimal(
|
||||||
|
out_x, lambda a: func(get_input())[0],
|
||||||
|
position_update_func=lambda m: m.move_to(dummy_out_x)
|
||||||
|
)
|
||||||
|
out_y_update = ContinualChangingDecimal(
|
||||||
|
out_y, lambda a: func(get_input())[1],
|
||||||
|
position_update_func=lambda m: m.move_to(dummy_out_y)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.add(func_tex, rhs)
|
||||||
|
# self.add(ContinualUpdateFromFunc(
|
||||||
|
# rhs, lambda m: m.next_to(func_tex, RIGHT)
|
||||||
|
# ))
|
||||||
|
|
||||||
|
# Where those decimals actually change
|
||||||
|
self.add(in_x_update, in_y_update)
|
||||||
|
|
||||||
|
in_dot.save_state()
|
||||||
|
in_dot.move_to(ORIGIN)
|
||||||
|
self.play(in_dot.restore)
|
||||||
|
self.wait()
|
||||||
|
self.play(*[
|
||||||
|
ReplacementTransform(
|
||||||
|
VGroup(mob.copy().fade(1)),
|
||||||
|
VGroup(out_x, out_y),
|
||||||
|
)
|
||||||
|
for mob in in_x, in_y
|
||||||
|
])
|
||||||
|
out_vect = get_out_vect()
|
||||||
|
VGroup(out_x, out_y).match_style(out_vect)
|
||||||
|
out_vect.save_state()
|
||||||
|
out_vect.move_to(rhs)
|
||||||
|
out_vect.set_fill(opacity=0)
|
||||||
|
self.play(out_vect.restore)
|
||||||
|
self.out_vect_update = ContinualUpdateFromFunc(
|
||||||
|
out_vect,
|
||||||
|
lambda ov: Transform(ov, get_out_vect()).update(1)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.add(self.out_vect_update)
|
||||||
|
self.add(out_x_update, out_y_update)
|
||||||
|
|
||||||
|
self.add(ContinualUpdateFromFunc(
|
||||||
|
VGroup(out_x, out_y),
|
||||||
|
lambda m: m.match_style(out_vect)
|
||||||
|
))
|
||||||
|
self.wait()
|
||||||
|
|
||||||
|
for vect in DOWN, 2 * RIGHT, UP:
|
||||||
|
self.play(
|
||||||
|
in_dot.shift, 3 * vect,
|
||||||
|
run_time=3
|
||||||
|
)
|
||||||
|
self.wait()
|
||||||
|
|
||||||
|
self.in_dot = in_dot
|
||||||
|
self.out_vect = out_vect
|
||||||
|
self.func_equation = VGroup(func_tex, rhs)
|
||||||
|
self.out_x, self.out_y = out_x, out_y
|
||||||
|
self.in_x, self.in_y = out_x, out_y
|
||||||
|
self.in_x_update = in_x_update
|
||||||
|
self.in_y_update = in_y_update
|
||||||
|
self.out_x_update = out_x_update
|
||||||
|
self.out_y_update = out_y_update
|
||||||
|
|
||||||
def show_divergence_function(self):
|
def show_divergence_function(self):
|
||||||
|
vector_field = VectorField(self.func)
|
||||||
|
vector_field.remove(*[
|
||||||
|
v for v in vector_field
|
||||||
|
if v.get_start()[0] < 0 and v.get_start()[1] > 2
|
||||||
|
])
|
||||||
|
vector_field.set_fill(opacity=0.5)
|
||||||
|
in_dot = self.in_dot
|
||||||
|
|
||||||
|
def get_neighboring_points(step_sizes=[0.3], n_angles=12):
|
||||||
|
point = in_dot.get_center()
|
||||||
|
return list(it.chain(*[
|
||||||
|
[
|
||||||
|
point + step_size * step
|
||||||
|
for step in compass_directions(n_angles)
|
||||||
|
]
|
||||||
|
for step_size in step_sizes
|
||||||
|
]))
|
||||||
|
|
||||||
|
def get_vector_ring():
|
||||||
|
return VGroup(*[
|
||||||
|
vector_field.get_vector(point)
|
||||||
|
for point in get_neighboring_points()
|
||||||
|
])
|
||||||
|
|
||||||
|
def get_stream_lines():
|
||||||
|
return StreamLines(
|
||||||
|
self.func,
|
||||||
|
start_points_generator=get_neighboring_points,
|
||||||
|
start_points_generator_config={
|
||||||
|
"step_sizes": np.arange(0.1, 0.5, 0.1)
|
||||||
|
},
|
||||||
|
virtual_time=1
|
||||||
|
)
|
||||||
|
|
||||||
|
def show_flow():
|
||||||
|
stream_lines = get_stream_lines()
|
||||||
|
random.shuffle(stream_lines.submobjects)
|
||||||
|
self.play(LaggedStart(
|
||||||
|
ShowCreationThenDestruction,
|
||||||
|
stream_lines,
|
||||||
|
remover=True
|
||||||
|
))
|
||||||
|
|
||||||
|
vector_ring = get_vector_ring()
|
||||||
|
vector_ring_update = ContinualUpdateFromFunc(
|
||||||
|
vector_ring,
|
||||||
|
lambda vr: Transform(vr, get_vector_ring()).update(1)
|
||||||
|
)
|
||||||
|
|
||||||
|
func_tex, rhs = self.func_equation
|
||||||
|
out_x, out_y = self.out_x, self.out_y
|
||||||
|
out_x_update = self.out_x_update
|
||||||
|
out_y_update = self.out_y_update
|
||||||
|
div_tex = TexMobject("\\text{div}")
|
||||||
|
div_tex.add_background_rectangle()
|
||||||
|
div_tex.move_to(func_tex, LEFT)
|
||||||
|
div_tex.shift(2 * SMALL_BUFF * RIGHT)
|
||||||
|
|
||||||
|
self.remove(out_x_update, out_y_update)
|
||||||
|
self.remove(self.out_vect_update)
|
||||||
|
self.add(self.in_x_update, self.in_y_update)
|
||||||
|
self.play(
|
||||||
|
func_tex.next_to, div_tex, RIGHT, SMALL_BUFF,
|
||||||
|
{"submobject_to_align": func_tex[1][0]},
|
||||||
|
Write(div_tex),
|
||||||
|
FadeOut(self.out_vect),
|
||||||
|
FadeOut(out_x),
|
||||||
|
FadeOut(out_y),
|
||||||
|
FadeOut(rhs),
|
||||||
|
)
|
||||||
|
# This line is a dumb hack around a Scene bug
|
||||||
|
self.add(*[
|
||||||
|
ContinualUpdateFromFunc(
|
||||||
|
mob, lambda m: m.set_fill(None, 0)
|
||||||
|
)
|
||||||
|
for mob in out_x, out_y
|
||||||
|
])
|
||||||
|
self.add_foreground_mobjects(div_tex)
|
||||||
|
self.play(
|
||||||
|
LaggedStart(GrowArrow, vector_field),
|
||||||
|
LaggedStart(GrowArrow, vector_ring),
|
||||||
|
)
|
||||||
|
self.add(vector_ring_update)
|
||||||
|
self.wait()
|
||||||
|
|
||||||
|
div_func = divergence(self.func)
|
||||||
|
div_rhs = DecimalNumber(
|
||||||
|
0, include_sign=True,
|
||||||
|
include_background_rectangle=True
|
||||||
|
)
|
||||||
|
div_rhs_update = ContinualChangingDecimal(
|
||||||
|
div_rhs, lambda a: div_func(in_dot.get_center()),
|
||||||
|
position_update_func=lambda d: d.next_to(func_tex, RIGHT, SMALL_BUFF)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.play(FadeIn(div_rhs))
|
||||||
|
self.add(div_rhs_update)
|
||||||
|
show_flow()
|
||||||
|
|
||||||
|
for vect in 2 * RIGHT, 3 * DOWN, 2 * LEFT:
|
||||||
|
self.play(in_dot.shift, vect, run_time=3)
|
||||||
|
show_flow()
|
||||||
|
self.wait()
|
||||||
|
|
||||||
|
def func(self, point):
|
||||||
|
x, y = point[:2]
|
||||||
|
return np.sin(x + y) * RIGHT + np.sin(y * x / 3) * UP
|
||||||
|
|
||||||
|
|
||||||
|
class DivergenceZeroCondition(Scene):
|
||||||
|
def construct(self):
|
||||||
|
self.add_title()
|
||||||
|
self.begin_flow()
|
||||||
|
|
||||||
|
def add_title(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def begin_flow(self):
|
||||||
pass
|
pass
|
||||||
|
Reference in New Issue
Block a user