mirror of
https://github.com/3b1b/manim.git
synced 2025-08-01 17:29:06 +08:00
Fixes to multilayered scnes
This commit is contained in:
@ -47,20 +47,15 @@ class Cycloid(ParametricFunction):
|
|||||||
class LoopTheLoop(ParametricFunction):
|
class LoopTheLoop(ParametricFunction):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"color" : YELLOW_D,
|
"color" : YELLOW_D,
|
||||||
"density" : 20*DEFAULT_POINT_DENSITY_1D
|
"density" : 10*DEFAULT_POINT_DENSITY_1D
|
||||||
}
|
}
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
digest_config(self, kwargs)
|
digest_config(self, kwargs)
|
||||||
pre_func = lambda t : [
|
def func(t):
|
||||||
t**3 - 1.5*t,
|
t = (6*np.pi/2)*(t-0.5)
|
||||||
t**2 + 0.6*(t**2 - 4)*(t**2 - 1),
|
return (t/2-np.sin(t))*RIGHT + \
|
||||||
0
|
(np.cos(t)+(t**2)/10)*UP
|
||||||
]
|
ParametricFunction.__init__(self, func, **kwargs)
|
||||||
ParametricFunction.__init__(
|
|
||||||
self,
|
|
||||||
lambda t : pre_func(4*t-2),
|
|
||||||
**kwargs
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class SlideWordDownCycloid(Animation):
|
class SlideWordDownCycloid(Animation):
|
||||||
|
@ -24,17 +24,6 @@ from brachistochrone.light import PhotonScene
|
|||||||
from brachistochrone.curves import *
|
from brachistochrone.curves import *
|
||||||
|
|
||||||
|
|
||||||
#Two to many
|
|
||||||
#race light in each
|
|
||||||
#n layers
|
|
||||||
#v_1, v_2, v_3
|
|
||||||
#proportional to sqrt y_1, y_2, y_3
|
|
||||||
#limiting process
|
|
||||||
#show sliding object and light
|
|
||||||
|
|
||||||
#which path is fastest
|
|
||||||
#instantaneously obey snell's law
|
|
||||||
|
|
||||||
class MultilayeredScene(Scene):
|
class MultilayeredScene(Scene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"n_layers" : 5,
|
"n_layers" : 5,
|
||||||
@ -293,7 +282,7 @@ class ShowLightAndSlidingObject(MultilayeredScene, TryManyPaths, PhotonScene):
|
|||||||
}
|
}
|
||||||
def construct(self):
|
def construct(self):
|
||||||
glass = self.get_continuous_glass()
|
glass = self.get_continuous_glass()
|
||||||
self.play(ApplyMethod(glass.fade, 0.3))
|
self.play(ApplyMethod(glass.fade, 0.8))
|
||||||
self.freeze_background()
|
self.freeze_background()
|
||||||
|
|
||||||
paths = self.get_paths()
|
paths = self.get_paths()
|
||||||
@ -301,14 +290,14 @@ class ShowLightAndSlidingObject(MultilayeredScene, TryManyPaths, PhotonScene):
|
|||||||
if path.get_height() > self.total_glass_height:
|
if path.get_height() > self.total_glass_height:
|
||||||
path.stretch(0.7, 1)
|
path.stretch(0.7, 1)
|
||||||
path.shift(self.top - path.get_top())
|
path.shift(self.top - path.get_top())
|
||||||
path.rgbs[:2] = 0
|
path.rgbs[:,2] = 0
|
||||||
loop = paths.pop(1) ##Bad!
|
loop = paths.pop(1) ##Bad!
|
||||||
randy = Randolph()
|
randy = Randolph()
|
||||||
randy.scale(RANDY_SCALE_VAL)
|
randy.scale(RANDY_SCALE_VAL)
|
||||||
randy.shift(-randy.get_bottom())
|
randy.shift(-randy.get_bottom())
|
||||||
photon_run = self.photon_run_along_path(
|
photon_run = self.photon_run_along_path(
|
||||||
loop,
|
loop,
|
||||||
rate_func = lambda t : smooth(t, 3),
|
rate_func = lambda t : smooth(1.2*t, 2),
|
||||||
run_time = 4.1
|
run_time = 4.1
|
||||||
)
|
)
|
||||||
text = self.get_text().to_edge(UP, buff = 0.2)
|
text = self.get_text().to_edge(UP, buff = 0.2)
|
||||||
@ -330,66 +319,106 @@ class ShowLightAndSlidingObject(MultilayeredScene, TryManyPaths, PhotonScene):
|
|||||||
))
|
))
|
||||||
|
|
||||||
|
|
||||||
class ContinuouslyObeyingSnellsLaw(MultilayeredScene, ZoomedScene):
|
class ContinuouslyObeyingSnellsLaw(MultilayeredScene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"arc_radius" : 0.1,
|
"arc_radius" : 0.5,
|
||||||
"RectClass" : FilledRectangle
|
"RectClass" : FilledRectangle
|
||||||
}
|
}
|
||||||
def construct(self):
|
def construct(self):
|
||||||
glass = self.get_continuous_glass()
|
glass = self.get_continuous_glass()
|
||||||
self.add(glass)
|
self.add(glass)
|
||||||
|
self.freeze_background()
|
||||||
|
|
||||||
line = Line(
|
cycloid = Cycloid()
|
||||||
UP, DOWN,
|
|
||||||
density = self.zoom_factor*DEFAULT_POINT_DENSITY_1D
|
|
||||||
)
|
|
||||||
theta = TexMobject("\\theta")
|
|
||||||
theta.scale(0.5/self.zoom_factor)
|
|
||||||
equation = TexMobject([
|
|
||||||
"\\dfrac{\\sin(\\theta)}",
|
|
||||||
"{\\sqrt{y}}",
|
|
||||||
" = \\text{constant}"
|
|
||||||
])
|
|
||||||
equation.next_to(Point(self.top), DOWN)
|
|
||||||
equation.shift(LEFT)
|
|
||||||
cycloid = Cycloid(end_theta = np.pi)
|
|
||||||
cycloid.highlight(YELLOW)
|
cycloid.highlight(YELLOW)
|
||||||
|
chopped_cycloid = cycloid.copy()
|
||||||
|
n = cycloid.get_num_points()
|
||||||
|
chopped_cycloid.filter_out(lambda p : p[1] > 1 and p[0] < 0)
|
||||||
|
chopped_cycloid.reverse_points()
|
||||||
|
|
||||||
|
|
||||||
for mob in equation.split():
|
|
||||||
self.play(GrowFromCenter(mob), run_time = 0.5)
|
|
||||||
self.play(ShowCreation(cycloid))
|
self.play(ShowCreation(cycloid))
|
||||||
self.activate_zooming()
|
self.snells_law_at_every_point(cycloid, chopped_cycloid)
|
||||||
little_square = self.get_zoomed_camera_mobject()
|
self.show_equation(chopped_cycloid)
|
||||||
|
|
||||||
self.add(line)
|
def snells_law_at_every_point(self, cycloid, chopped_cycloid):
|
||||||
indices = np.arange(
|
square = Square(side_length = 0.2, color = WHITE)
|
||||||
0, cycloid.get_num_points()-1, 10
|
words = TextMobject("Snell's law at every point")
|
||||||
|
words.next_to(square)
|
||||||
|
words.shift(0.3*UP)
|
||||||
|
combo = Mobject(square, words)
|
||||||
|
combo.get_center = lambda : square.get_center()
|
||||||
|
self.play(MoveAlongPath(
|
||||||
|
combo, cycloid,
|
||||||
|
run_time = 3
|
||||||
|
))
|
||||||
|
self.play(MoveAlongPath(
|
||||||
|
combo, chopped_cycloid,
|
||||||
|
run_time = 2
|
||||||
|
))
|
||||||
|
dot = Dot(combo.get_center())
|
||||||
|
self.play(Transform(combo.ingest_sub_mobjects(), dot))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
def get_marks(self, point1, point2):
|
||||||
|
vert_line = Line(2*DOWN, 2*UP)
|
||||||
|
tangent_line = vert_line.copy()
|
||||||
|
theta = TexMobject("\\theta")
|
||||||
|
theta.scale(0.5)
|
||||||
|
angle = angle_of_vector(point1 - point2)
|
||||||
|
tangent_line.rotate(
|
||||||
|
angle - tangent_line.get_angle()
|
||||||
)
|
)
|
||||||
for index in indices:
|
angle_from_vert = angle - np.pi/2
|
||||||
point = cycloid.points[index]
|
for mob in vert_line, tangent_line:
|
||||||
next_point = cycloid.points[index+1]
|
mob.shift(point1 - mob.get_center())
|
||||||
angle = angle_of_vector(point - next_point)-np.pi/2
|
arc = Arc(angle_from_vert, start_angle = np.pi/2)
|
||||||
for mob in little_square, line:
|
|
||||||
mob.shift(point - mob.get_center())
|
|
||||||
arc = Arc(angle, start_angle = np.pi/2)
|
|
||||||
arc.scale(self.arc_radius)
|
arc.scale(self.arc_radius)
|
||||||
arc.shift(point)
|
arc.shift(point1)
|
||||||
color = Color()
|
|
||||||
height = (self.top-self.point)[1]
|
|
||||||
color.set_rgb([height/self.total_glass_height]*3)
|
|
||||||
for mob in arc, theta, line:
|
|
||||||
mob.highlight(color)
|
|
||||||
if angle > np.pi/15:
|
|
||||||
self.add(arc)
|
self.add(arc)
|
||||||
if angle > np.pi/6:
|
vect_angle = angle_from_vert/2 + np.pi/2
|
||||||
vect_angle = angle/2 + np.pi/2
|
|
||||||
vect = rotate_vector(RIGHT, vect_angle)
|
vect = rotate_vector(RIGHT, vect_angle)
|
||||||
theta.center()
|
theta.center()
|
||||||
theta.shift(point)
|
theta.shift(point1)
|
||||||
theta.shift(1.5*self.arc_radius*vect)
|
theta.shift(1.5*self.arc_radius*vect)
|
||||||
self.add(theta)
|
return arc, theta, vert_line, tangent_line
|
||||||
self.dither(self.frame_duration)
|
|
||||||
self.remove(arc)
|
|
||||||
|
def show_equation(self, chopped_cycloid):
|
||||||
|
point1, point2 = chopped_cycloid.points[-2:]
|
||||||
|
arc, theta, vert_line, tangent_line = self.get_marks(
|
||||||
|
point1, point2
|
||||||
|
)
|
||||||
|
sin, sqrt_y = TexMobject([
|
||||||
|
"\\sin(\\theta)",
|
||||||
|
"\\over \\sqrt{y}",
|
||||||
|
]).split()
|
||||||
|
equation = Mobject(sin, sqrt_y)
|
||||||
|
equation.next_to(Point(self.top), DOWN)
|
||||||
|
equation.shift(LEFT)
|
||||||
|
const = TexMobject(" = \\text{constant}")
|
||||||
|
const.next_to(equation)
|
||||||
|
ceil_point = np.array(point)
|
||||||
|
ceil_point[1] = self.top[1]
|
||||||
|
brace = Brace(
|
||||||
|
Mobject(Point(point), Point(ceil_point)),
|
||||||
|
RIGHT
|
||||||
|
)
|
||||||
|
y_mob = TexMobject("y").next_to(brace)
|
||||||
|
|
||||||
|
self.play(GrowFromCenter(sin))
|
||||||
|
self.play(ShowCreation(vert_line))
|
||||||
|
self.play(ShowCreation(tangent_line))
|
||||||
|
self.play(ShowCreation(arc), GrowFromCenter(theta))
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(sqrt_y),
|
||||||
|
GrowFromCenter(brace),
|
||||||
|
GrowFromCenter(y_mob)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(ShimmerIn(const))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ LOW_QUALITY_CAMERA_CONFIG = {
|
|||||||
|
|
||||||
|
|
||||||
DEFAULT_POINT_DENSITY_2D = 25
|
DEFAULT_POINT_DENSITY_2D = 25
|
||||||
DEFAULT_POINT_DENSITY_1D = 200
|
DEFAULT_POINT_DENSITY_1D = 250
|
||||||
|
|
||||||
DEFAULT_POINT_THICKNESS = 3
|
DEFAULT_POINT_THICKNESS = 3
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user