mirror of
https://github.com/3b1b/manim.git
synced 2025-08-19 13:01:00 +00:00
BreakApartSum and UnmixMixedPaint from fourier project
This commit is contained in:
parent
5d9eb8d5a0
commit
2b80c582dd
1 changed files with 161 additions and 7 deletions
|
@ -122,7 +122,6 @@ class AddingPureFrequencies(PiCreatureScene):
|
||||||
Write(time),
|
Write(time),
|
||||||
ShowCreation(axes.x_axis)
|
ShowCreation(axes.x_axis)
|
||||||
)
|
)
|
||||||
self.dither()
|
|
||||||
self.broadcast(
|
self.broadcast(
|
||||||
ShowCreation(graph, run_time = 4, rate_func = None),
|
ShowCreation(graph, run_time = 4, rate_func = None),
|
||||||
ShowCreation(equilibrium_line),
|
ShowCreation(equilibrium_line),
|
||||||
|
@ -133,7 +132,7 @@ class AddingPureFrequencies(PiCreatureScene):
|
||||||
GrowFromCenter(brace),
|
GrowFromCenter(brace),
|
||||||
Write(words)
|
Write(words)
|
||||||
)
|
)
|
||||||
self.dither(2)
|
self.dither()
|
||||||
graph.save_state()
|
graph.save_state()
|
||||||
self.play(
|
self.play(
|
||||||
FadeOut(brace),
|
FadeOut(brace),
|
||||||
|
@ -325,7 +324,10 @@ class AddingPureFrequencies(PiCreatureScene):
|
||||||
])
|
])
|
||||||
result *= 0.5
|
result *= 0.5
|
||||||
return result + self.equilibrium_height
|
return result + self.equilibrium_height
|
||||||
new_sum_graph = self.axes.get_graph(new_sum_func)
|
new_sum_graph = self.axes.get_graph(
|
||||||
|
new_sum_func,
|
||||||
|
num_graph_points = 200
|
||||||
|
)
|
||||||
new_sum_graph.highlight(BLUE_C)
|
new_sum_graph.highlight(BLUE_C)
|
||||||
|
|
||||||
self.play(*it.chain(
|
self.play(*it.chain(
|
||||||
|
@ -408,10 +410,162 @@ class AddingPureFrequencies(PiCreatureScene):
|
||||||
|
|
||||||
return UpdateFromAlphaFunc(line, update_line, **kwargs)
|
return UpdateFromAlphaFunc(line, update_line, **kwargs)
|
||||||
|
|
||||||
|
class BreakApartSum(Scene):
|
||||||
|
CONFIG = {
|
||||||
|
"frequencies" : [0.5, 1.5, 2, 2.5, 5],
|
||||||
|
"equilibrium_height" : 2.0,
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
self.show_initial_sound()
|
||||||
|
self.decompose_sound()
|
||||||
|
self.ponder_question()
|
||||||
|
|
||||||
|
def show_initial_sound(self):
|
||||||
|
def func(x):
|
||||||
|
return self.equilibrium_height + 0.2*np.sum([
|
||||||
|
np.cos(2*np.pi*f*x)
|
||||||
|
for f in self.frequencies
|
||||||
|
])
|
||||||
|
axes = Axes(
|
||||||
|
x_min = 0, x_max = 5,
|
||||||
|
y_min = -1, y_max = 5,
|
||||||
|
x_axis_config = {
|
||||||
|
"include_tip" : False,
|
||||||
|
"unit_size" : 2.0,
|
||||||
|
},
|
||||||
|
y_axis_config = {
|
||||||
|
"include_tip" : False,
|
||||||
|
"unit_size" : 0.5,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
axes.stretch_to_fit_width(2*SPACE_WIDTH - 2)
|
||||||
|
axes.stretch_to_fit_height(3)
|
||||||
|
axes.center()
|
||||||
|
axes.to_edge(LEFT)
|
||||||
|
graph = axes.get_graph(func, num_graph_points = 200)
|
||||||
|
graph.highlight(YELLOW)
|
||||||
|
|
||||||
|
v_line = Line(ORIGIN, 4*UP)
|
||||||
|
v_line.move_to(axes.coords_to_point(0, 0), DOWN)
|
||||||
|
dot = Dot(color = PINK)
|
||||||
|
dot.move_to(graph.point_from_proportion(0))
|
||||||
|
|
||||||
|
self.add(axes, graph)
|
||||||
|
self.play(
|
||||||
|
v_line.move_to, axes.coords_to_point(5, 0), DOWN,
|
||||||
|
MoveAlongPath(dot, graph),
|
||||||
|
run_time = 8,
|
||||||
|
rate_func = None,
|
||||||
|
)
|
||||||
|
self.play(*map(FadeOut, [dot, v_line]))
|
||||||
|
|
||||||
|
self.set_variables_as_attrs(axes, graph)
|
||||||
|
|
||||||
|
def decompose_sound(self):
|
||||||
|
axes, graph = self.axes, self.graph
|
||||||
|
|
||||||
|
pure_graphs = VGroup(*[
|
||||||
|
axes.get_graph(
|
||||||
|
lambda x : 0.5*np.cos(2*np.pi*freq*x),
|
||||||
|
num_graph_points = 100,
|
||||||
|
)
|
||||||
|
for freq in self.frequencies
|
||||||
|
])
|
||||||
|
pure_graphs.gradient_highlight(BLUE, RED)
|
||||||
|
pure_graphs.arrange_submobjects(DOWN, buff = MED_LARGE_BUFF)
|
||||||
|
h_line = DashedLine(6*LEFT, 6*RIGHT)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
FadeOut(axes),
|
||||||
|
graph.to_edge, UP
|
||||||
|
)
|
||||||
|
pure_graphs.next_to(graph, DOWN, LARGE_BUFF)
|
||||||
|
h_line.next_to(graph, DOWN, MED_LARGE_BUFF)
|
||||||
|
self.play(ShowCreation(h_line))
|
||||||
|
for pure_graph in reversed(pure_graphs):
|
||||||
|
self.play(ReplacementTransform(graph.copy(), pure_graph))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
self.all_graphs = VGroup(graph, h_line, pure_graphs)
|
||||||
|
self.pure_graphs = pure_graphs
|
||||||
|
|
||||||
|
def ponder_question(self):
|
||||||
|
all_graphs = self.all_graphs
|
||||||
|
pure_graphs = self.pure_graphs
|
||||||
|
randy = Randolph()
|
||||||
|
randy.to_corner(DOWN+LEFT)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
FadeIn(randy),
|
||||||
|
all_graphs.scale, 0.75,
|
||||||
|
all_graphs.to_corner, UP+RIGHT,
|
||||||
|
)
|
||||||
|
self.play(randy.change, "pondering", all_graphs)
|
||||||
|
self.play(Blink(randy))
|
||||||
|
rect = SurroundingRectangle(pure_graphs, color = WHITE)
|
||||||
|
self.play(
|
||||||
|
ShowCreation(rect),
|
||||||
|
LaggedStart(
|
||||||
|
ApplyFunction, pure_graphs,
|
||||||
|
lambda g : (lambda m : m.shift(SMALL_BUFF*UP).highlight(YELLOW), g),
|
||||||
|
rate_func = wiggle
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.play(FadeOut(rect))
|
||||||
|
self.play(Blink(randy))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class Quadrant(Mobject1D):
|
||||||
|
CONFIG = {
|
||||||
|
"radius" : 2,
|
||||||
|
"stroke_width": 2,
|
||||||
|
"density" : 75,
|
||||||
|
}
|
||||||
|
def generate_points(self):
|
||||||
|
self.add_points([
|
||||||
|
r*(np.cos(theta)*RIGHT + np.sin(theta)*UP)
|
||||||
|
for r in np.arange(0, self.radius, self.epsilon)
|
||||||
|
for theta in np.arange(0, np.pi/2, self.epsilon/r)
|
||||||
|
])
|
||||||
|
|
||||||
|
class UnmixMixedPaint(Scene):
|
||||||
|
CONFIG = {
|
||||||
|
"colors" : [BLUE, RED, YELLOW, GREEN],
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
angles = np.arange(4)*np.pi/2
|
||||||
|
quadrants = PMobject(*[
|
||||||
|
Quadrant().rotate(angle).highlight(color)
|
||||||
|
for color, angle in zip(self.colors, angles)
|
||||||
|
])
|
||||||
|
quadrants.ingest_submobjects()
|
||||||
|
quadrants.sort_points(lambda p : np.random.random())
|
||||||
|
|
||||||
|
start_rgbas = np.array(quadrants.rgbas)
|
||||||
|
target_rgbas = np.zeros(start_rgbas.shape)
|
||||||
|
mud_color = average_color(*self.colors)
|
||||||
|
target_rgbas[:,:] = color_to_rgba(mud_color)
|
||||||
|
|
||||||
|
background_circle = Circle(
|
||||||
|
radius = 2,
|
||||||
|
stroke_width = 0,
|
||||||
|
fill_color = mud_color,
|
||||||
|
fill_opacity = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
def update_color(quadrants, alpha):
|
||||||
|
quadrants.rgbas = interpolate(start_rgbas, target_rgbas, alpha)
|
||||||
|
|
||||||
|
self.add(background_circle, quadrants)
|
||||||
|
self.play(
|
||||||
|
PhaseFlow(
|
||||||
|
lambda p : rotate_vector(p, np.pi/2+0.01)/(max(np.linalg.norm(p), 0.001)),
|
||||||
|
quadrants,
|
||||||
|
virtual_time = 20,
|
||||||
|
),
|
||||||
|
UpdateFromAlphaFunc(quadrants, update_color),
|
||||||
|
run_time = 10,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue