mirror of
https://github.com/3b1b/manim.git
synced 2025-09-01 00:48:45 +00:00
animations for listening to pixels explanation
This commit is contained in:
parent
f21f6619a5
commit
5848f03249
1 changed files with 271 additions and 15 deletions
|
@ -1,26 +1,46 @@
|
|||
from mobject import Mobject, Point
|
||||
from mobject.tex_mobject import TexMobject, TextMobject, Brace
|
||||
from mobject.image_mobject import ImageMobject
|
||||
from mobject.tex_mobject import \
|
||||
TexMobject, TextMobject, Brace
|
||||
from mobject.image_mobject import \
|
||||
ImageMobject, MobjectFromRegion
|
||||
|
||||
from scene import Scene
|
||||
|
||||
from animation import Animation
|
||||
from animation.transform import Transform, CounterclockwiseTransform, \
|
||||
ApplyMethod, GrowFromCenter
|
||||
from animation.simple_animations import ShowCreation, ShimmerIn
|
||||
from animation.meta_animations import DelayByOrder, TransformAnimations
|
||||
from animation.playground import VibratingString
|
||||
from animation.transform import \
|
||||
Transform, CounterclockwiseTransform, ApplyMethod,\
|
||||
GrowFromCenter, ClockwiseTransform
|
||||
from animation.simple_animations import \
|
||||
ShowCreation, ShimmerIn, FadeOut, FadeIn
|
||||
from animation.meta_animations import \
|
||||
DelayByOrder, TransformAnimations
|
||||
from animation.playground import Vibrate
|
||||
|
||||
from topics.geometry import Line, Dot, Arrow
|
||||
from topics.geometry import \
|
||||
Line, Dot, Arrow, Grid, Square, Point
|
||||
from topics.characters import ThoughtBubble
|
||||
from topics.number_line import UnitInterval
|
||||
from topics.three_dimensions import Stars
|
||||
|
||||
from region import region_from_polygon_vertices
|
||||
|
||||
import displayer as disp
|
||||
|
||||
from hilbert.curves import \
|
||||
TransformOverIncreasingOrders, FlowSnake
|
||||
|
||||
|
||||
from helpers import *
|
||||
from hilbert.curves import TransformOverIncreasingOrders, FlowSnake
|
||||
|
||||
|
||||
|
||||
def get_grid():
|
||||
return Grid(64, 64)
|
||||
|
||||
def get_freq_line():
|
||||
return UnitInterval().shift(2*DOWN) ##Change?
|
||||
|
||||
|
||||
class AboutSpaceFillingCurves(TransformOverIncreasingOrders):
|
||||
@staticmethod
|
||||
def args_to_string():
|
||||
|
@ -131,7 +151,7 @@ class WriteSomeSoftware(Scene):
|
|||
|
||||
class ImageToSound(Scene):
|
||||
def construct(self):
|
||||
string = VibratingString(color = BLUE_D, run_time = 5)
|
||||
string = Vibrate(color = BLUE_D, run_time = 5)
|
||||
picture = ImageMobject("lion", invert = False)
|
||||
picture.scale(0.8)
|
||||
picture_copy = picture.copy()
|
||||
|
@ -181,11 +201,11 @@ class SoundDataIsOneDimensional(Scene):
|
|||
def construct(self):
|
||||
overtones = 5
|
||||
floor = 2*DOWN
|
||||
main_string = VibratingString(color = BLUE_D)
|
||||
main_string = Vibrate(color = BLUE_D)
|
||||
component_strings = [
|
||||
VibratingString(
|
||||
Vibrate(
|
||||
num_periods = k+1,
|
||||
overtones = 2,
|
||||
overtones = 1,
|
||||
color = color,
|
||||
center = 2*DOWN + UP*k
|
||||
)
|
||||
|
@ -202,7 +222,7 @@ class SoundDataIsOneDimensional(Scene):
|
|||
for string in component_strings
|
||||
]
|
||||
|
||||
freq_line = UnitInterval()
|
||||
freq_line = get_freq_line()
|
||||
freq_line.shift(floor)
|
||||
freq_line.sort_points(np.linalg.norm)
|
||||
brace = Brace(freq_line, UP)
|
||||
|
@ -242,7 +262,243 @@ class SoundDataIsOneDimensional(Scene):
|
|||
)
|
||||
self.dither(0.5)
|
||||
|
||||
|
||||
class GridOfPixels(Scene):
|
||||
def construct(self):
|
||||
low_res = ImageMobject("low_resolution_lion", invert = False)
|
||||
high_res = ImageMobject("Lion", invert = False)
|
||||
grid = get_grid()
|
||||
for mob in low_res, high_res:
|
||||
mob.replace(grid, stretch = True)
|
||||
for mob in low_res, high_res, grid:
|
||||
mob.sort_points(np.linalg.norm)
|
||||
side_brace = Brace(grid, LEFT)
|
||||
top_brace = Brace(grid, UP)
|
||||
top_words = TextMobject("256 Px", size = "\\normal")
|
||||
side_words = top_words.copy().rotate(np.pi/2)
|
||||
top_words.next_to(top_brace, UP)
|
||||
side_words.next_to(side_brace, LEFT)
|
||||
|
||||
self.add(high_res)
|
||||
self.dither()
|
||||
self.play(DelayByOrder(Transform(high_res, low_res)))
|
||||
self.dither()
|
||||
self.play(DelayByOrder(Transform(high_res, grid)))
|
||||
self.clear()
|
||||
self.add(grid)
|
||||
self.play(
|
||||
GrowFromCenter(top_brace),
|
||||
GrowFromCenter(side_brace),
|
||||
ShimmerIn(top_words),
|
||||
ShimmerIn(side_words)
|
||||
)
|
||||
self.dither()
|
||||
|
||||
|
||||
class ShowFrequencySpace(Scene):
|
||||
def construct(self):
|
||||
freq_line = get_freq_line()
|
||||
|
||||
self.add(freq_line)
|
||||
self.dither()
|
||||
for tex, vect in zip(["20 Hz", "20{,}000 Hz"], [LEFT, RIGHT]):
|
||||
tex_mob = TextMobject(tex)
|
||||
tex_mob.to_edge(vect)
|
||||
tex_mob.shift(UP)
|
||||
arrow = Arrow(tex_mob, freq_line.get_edge_center(vect))
|
||||
self.play(
|
||||
ShimmerIn(tex_mob),
|
||||
ShowCreation(arrow)
|
||||
)
|
||||
self.dither()
|
||||
|
||||
|
||||
|
||||
class AssociatePixelWithFrequency(Scene):
|
||||
def construct(self):
|
||||
big_grid_dim = 20.
|
||||
small_grid_dim = 6.
|
||||
big_grid = Grid(64, 64, height = big_grid_dim, width = big_grid_dim)
|
||||
big_grid.to_corner(UP+RIGHT, buff = 2)
|
||||
small_grid = big_grid.copy()
|
||||
small_grid.scale(small_grid_dim/big_grid_dim)
|
||||
small_grid.center()
|
||||
pixel = MobjectFromRegion(
|
||||
region_from_polygon_vertices(*0.2*np.array([
|
||||
RIGHT+DOWN,
|
||||
RIGHT+UP,
|
||||
LEFT+UP,
|
||||
LEFT+DOWN
|
||||
]))
|
||||
)
|
||||
pixel.set_color(WHITE)
|
||||
pixel_width = big_grid.width/big_grid.columns
|
||||
pixel.scale_to_fit_width(pixel_width)
|
||||
pixel.to_corner(UP+RIGHT, buff = 2)
|
||||
pixel.shift(5*pixel_width*(2*LEFT+DOWN))
|
||||
|
||||
freq_line = get_freq_line()
|
||||
dot = Dot()
|
||||
dot.shift(freq_line.get_center() + 2*RIGHT)
|
||||
string = Line(LEFT, RIGHT, color = GREEN)
|
||||
arrow = Arrow(
|
||||
dot, string.get_center(),
|
||||
color = YELLOW_C
|
||||
)
|
||||
vibration_config = {
|
||||
"overtones" : 1,
|
||||
"spatial_period" : 2,
|
||||
}
|
||||
vibration, loud_vibration, quiet_vibration = [
|
||||
Vibrate(string.copy(), amplitude = a, **vibration_config)
|
||||
for a in [0.5, 1., 0.25]
|
||||
]
|
||||
|
||||
self.add(small_grid)
|
||||
self.dither()
|
||||
self.play(
|
||||
Transform(small_grid, big_grid)
|
||||
)
|
||||
self.play(FadeIn(pixel))
|
||||
self.dither()
|
||||
self.play(
|
||||
FadeOut(small_grid),
|
||||
ShowCreation(freq_line)
|
||||
)
|
||||
self.remove(small_grid)
|
||||
self.play(
|
||||
Transform(pixel, dot),
|
||||
)
|
||||
self.dither()
|
||||
self.play(ShowCreation(arrow))
|
||||
self.play(loud_vibration)
|
||||
self.play(
|
||||
TransformAnimations(loud_vibration, quiet_vibration),
|
||||
ApplyMethod(dot.fade, 0.1)
|
||||
)
|
||||
self.clear()
|
||||
self.add(freq_line, dot, arrow)
|
||||
self.play(quiet_vibration)
|
||||
|
||||
|
||||
class ListenToAllPixels(Scene):
|
||||
def construct(self):
|
||||
grid = get_grid()
|
||||
grid.sort_points(np.linalg.norm)
|
||||
freq_line = get_freq_line()
|
||||
freq_line.sort_points(lambda p : p[0])
|
||||
red, blue = Color(RED), Color(BLUE)
|
||||
freq_line.gradient_highlight(red, blue)
|
||||
|
||||
colors = [
|
||||
Color(rgb = interpolate(
|
||||
np.array(red.rgb),
|
||||
np.array(blue.rgb),
|
||||
alpha
|
||||
))
|
||||
for alpha in np.arange(4)/3.
|
||||
]
|
||||
string = Line(3*LEFT, 3*RIGHT, color = colors[1])
|
||||
vibration = Vibrate(string)
|
||||
vibration_copy = vibration.copy()
|
||||
vibration_copy.mobject.point_thickness = 1
|
||||
sub_vibrations = [
|
||||
Vibrate(
|
||||
string.copy().shift((n-1)*UP).highlight(colors[n]),
|
||||
overtones = 1,
|
||||
spatial_period = 6./(n+1),
|
||||
temporal_period = 1./(n+1),
|
||||
amplitude = 0.5/(n+1)
|
||||
)
|
||||
for n in range(4)
|
||||
]
|
||||
words = TexMobject("&\\vdots \\\\ \\text{thousands }& \\text{of frequencies} \\\\ &\\vdots")
|
||||
words.to_edge(UP, buff = 0.1)
|
||||
|
||||
self.add(grid)
|
||||
self.dither()
|
||||
self.play(DelayByOrder(ApplyMethod(
|
||||
grid.gradient_highlight, red, blue
|
||||
)))
|
||||
self.play(Transform(grid, freq_line))
|
||||
self.dither()
|
||||
self.play(
|
||||
ShimmerIn(
|
||||
words,
|
||||
alpha_func = squish_alpha_func(smooth, 0, 0.2)
|
||||
),
|
||||
*sub_vibrations,
|
||||
run_time = 5
|
||||
)
|
||||
self.play(
|
||||
*[
|
||||
TransformAnimations(
|
||||
sub_vib, vibration
|
||||
)
|
||||
for sub_vib in sub_vibrations
|
||||
]+[FadeOut(words)]
|
||||
)
|
||||
self.clear()
|
||||
self.add(freq_line)
|
||||
self.play(vibration)
|
||||
|
||||
|
||||
class LayAsideSpeculation(Scene):
|
||||
def construct(self):
|
||||
words = TextMobject("Would this actually work?")
|
||||
grid = get_grid()
|
||||
grid.scale_to_fit_width(6)
|
||||
grid.to_edge(LEFT)
|
||||
freq_line = get_freq_line()
|
||||
freq_line.scale_to_fit_width(6)
|
||||
freq_line.center().to_edge(RIGHT)
|
||||
mapping = Mobject(
|
||||
grid, freq_line, Arrow(grid, freq_line)
|
||||
)
|
||||
mapping.ingest_sub_mobjects()
|
||||
lower_left = Point().to_corner(DOWN+LEFT, buff = 0)
|
||||
lower_right = Point().to_corner(DOWN+RIGHT, buff = 0)
|
||||
|
||||
self.add(words)
|
||||
self.dither()
|
||||
self.play(
|
||||
Transform(words, lower_right),
|
||||
Transform(lower_left, mapping)
|
||||
)
|
||||
self.dither()
|
||||
|
||||
|
||||
class RandomMapping(Scene):
|
||||
def construct(self):
|
||||
grid = get_grid()
|
||||
grid.scale_to_fit_width(6)
|
||||
grid.to_edge(LEFT)
|
||||
freq_line = get_freq_line()
|
||||
freq_line.scale_to_fit_width(6)
|
||||
freq_line.center().to_edge(RIGHT)
|
||||
# for mob in grid, freq_line:
|
||||
# indices = np.arange(mob.get_num_points())
|
||||
# random.shuffle(indices)
|
||||
# mob.points = mob.points[indices]
|
||||
stars = Stars(point_thickness = grid.point_thickness)
|
||||
|
||||
self.add(grid)
|
||||
targets = [stars, freq_line]
|
||||
alphas = [not_quite_there(rush_into), rush_from]
|
||||
for target, alpha_func in zip(targets, alphas):
|
||||
self.play(Transform(
|
||||
grid, target,
|
||||
run_time = 3,
|
||||
alpha_func = alpha_func,
|
||||
interpolation_function = path_along_arc(-np.pi/2)
|
||||
))
|
||||
self.dither()
|
||||
|
||||
|
||||
|
||||
class LeverageExistingIntuitions(Scene):
|
||||
def construct(self):
|
||||
self.add(TextMobject("Leverage existing intuitions"))
|
||||
self.dither()
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue