mirror of
https://github.com/3b1b/manim.git
synced 2025-09-01 00:48:45 +00:00
Preliminary Lens, Mirror and Glass scenes established
This commit is contained in:
parent
044e0b5c72
commit
601abf18f3
1 changed files with 205 additions and 27 deletions
|
@ -49,7 +49,9 @@ class Lens(Arc):
|
||||||
|
|
||||||
class PhotonScene(Scene):
|
class PhotonScene(Scene):
|
||||||
def wavify(self, mobject):
|
def wavify(self, mobject):
|
||||||
tangent_vectors = mobject.points[1:]-mobject.points[:-1]
|
result = mobject.copy()
|
||||||
|
result.ingest_sub_mobjects()
|
||||||
|
tangent_vectors = result.points[1:]-result.points[:-1]
|
||||||
lengths = np.apply_along_axis(
|
lengths = np.apply_along_axis(
|
||||||
np.linalg.norm, 1, tangent_vectors
|
np.linalg.norm, 1, tangent_vectors
|
||||||
)
|
)
|
||||||
|
@ -62,7 +64,6 @@ class PhotonScene(Scene):
|
||||||
nudge_sizes = 0.1*np.sin(2*np.pi*times)
|
nudge_sizes = 0.1*np.sin(2*np.pi*times)
|
||||||
thick_nudge_sizes = nudge_sizes.repeat(3).reshape((len(nudge_sizes), 3))
|
thick_nudge_sizes = nudge_sizes.repeat(3).reshape((len(nudge_sizes), 3))
|
||||||
nudges = thick_nudge_sizes*normal_vectors
|
nudges = thick_nudge_sizes*normal_vectors
|
||||||
result = mobject.copy()
|
|
||||||
result.points[1:] += nudges
|
result.points[1:] += nudges
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@ -84,29 +85,12 @@ class SimplePhoton(PhotonScene):
|
||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
|
|
||||||
class PhotonThroughLens(PhotonScene):
|
class MultipathPhotonScene(PhotonScene):
|
||||||
def construct(self):
|
DEFAULT_CONFIG = {
|
||||||
lens = Lens()
|
"num_paths" : 5
|
||||||
num_paths = 5
|
}
|
||||||
interval_values = np.arange(num_paths)/(num_paths-1.)
|
def run_along_paths(self):
|
||||||
first_contact = [
|
paths = self.get_paths()
|
||||||
lens.point_from_interval(0.4*v+0.55)
|
|
||||||
for v in reversed(interval_values)
|
|
||||||
]
|
|
||||||
second_contact = [
|
|
||||||
lens.point_from_interval(0.3*v + 0.1)
|
|
||||||
for v in interval_values
|
|
||||||
]
|
|
||||||
focal_point = 2*RIGHT
|
|
||||||
paths = [
|
|
||||||
Mobject(
|
|
||||||
Line(SPACE_WIDTH*LEFT + fc[1]*UP, fc),
|
|
||||||
Line(fc, sc),
|
|
||||||
Line(sc, focal_point),
|
|
||||||
Line(focal_point, 6*focal_point-5*sc)
|
|
||||||
).ingest_sub_mobjects()
|
|
||||||
for fc, sc in zip(first_contact, second_contact)
|
|
||||||
]
|
|
||||||
colors = Color(YELLOW).range_to(WHITE, len(paths))
|
colors = Color(YELLOW).range_to(WHITE, len(paths))
|
||||||
for path, color in zip(paths, colors):
|
for path, color in zip(paths, colors):
|
||||||
path.highlight(color)
|
path.highlight(color)
|
||||||
|
@ -114,7 +98,6 @@ class PhotonThroughLens(PhotonScene):
|
||||||
self.photon_run_along_path(path)
|
self.photon_run_along_path(path)
|
||||||
for path in paths
|
for path in paths
|
||||||
]
|
]
|
||||||
self.add(lens)
|
|
||||||
for photon_run, path in zip(photon_runs, paths):
|
for photon_run, path in zip(photon_runs, paths):
|
||||||
self.play(
|
self.play(
|
||||||
photon_run,
|
photon_run,
|
||||||
|
@ -125,7 +108,202 @@ class PhotonThroughLens(PhotonScene):
|
||||||
)
|
)
|
||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
|
def generate_paths(self):
|
||||||
|
raise Exception("Not Implemented")
|
||||||
|
|
||||||
|
|
||||||
|
class PhotonThroughLens(MultipathPhotonScene):
|
||||||
|
def construct(self):
|
||||||
|
self.lens = Lens()
|
||||||
|
self.add(self.lens)
|
||||||
|
self.run_along_paths()
|
||||||
|
|
||||||
|
|
||||||
|
def get_paths(self):
|
||||||
|
interval_values = np.arange(self.num_paths).astype('float')
|
||||||
|
interval_values /= (self.num_paths-1.)
|
||||||
|
first_contact = [
|
||||||
|
self.lens.point_from_proportion(0.4*v+0.55)
|
||||||
|
for v in reversed(interval_values)
|
||||||
|
]
|
||||||
|
second_contact = [
|
||||||
|
self.lens.point_from_proportion(0.3*v + 0.1)
|
||||||
|
for v in interval_values
|
||||||
|
]
|
||||||
|
focal_point = 2*RIGHT
|
||||||
|
return [
|
||||||
|
Mobject(
|
||||||
|
Line(SPACE_WIDTH*LEFT + fc[1]*UP, fc),
|
||||||
|
Line(fc, sc),
|
||||||
|
Line(sc, focal_point),
|
||||||
|
Line(focal_point, 6*focal_point-5*sc)
|
||||||
|
).ingest_sub_mobjects()
|
||||||
|
for fc, sc in zip(first_contact, second_contact)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class PhotonOffMirror(MultipathPhotonScene):
|
||||||
|
def construct(self):
|
||||||
|
self.mirror = Line(*SPACE_HEIGHT*np.array([DOWN, UP]))
|
||||||
|
self.mirror.highlight(GREY)
|
||||||
|
self.add(self.mirror)
|
||||||
|
self.run_along_paths()
|
||||||
|
|
||||||
|
def get_paths(self):
|
||||||
|
interval_values = np.arange(self.num_paths).astype('float')
|
||||||
|
interval_values /= (self.num_paths-1)
|
||||||
|
anchor_points = [
|
||||||
|
self.mirror.point_from_proportion(0.6*v+0.3)
|
||||||
|
for v in interval_values
|
||||||
|
]
|
||||||
|
start_point = 5*LEFT+3*UP
|
||||||
|
end_points = []
|
||||||
|
for point in anchor_points:
|
||||||
|
vect = start_point-point
|
||||||
|
vect[1] *= -1
|
||||||
|
end_points.append(point+2*vect)
|
||||||
|
return [
|
||||||
|
Mobject(
|
||||||
|
Line(start_point, anchor_point),
|
||||||
|
Line(anchor_point, end_point)
|
||||||
|
).ingest_sub_mobjects()
|
||||||
|
for anchor_point, end_point in zip(anchor_points, end_points)
|
||||||
|
]
|
||||||
|
|
||||||
|
class PhotonsInGlass(MultipathPhotonScene):
|
||||||
|
def construct(self):
|
||||||
|
glass = Region(lambda x, y : y < 0)
|
||||||
|
self.highlight_region(glass, BLUE_E)
|
||||||
|
self.run_along_paths()
|
||||||
|
|
||||||
|
def get_paths(self):
|
||||||
|
x, y = -3, 3
|
||||||
|
start_point = x*RIGHT + y*UP
|
||||||
|
angles = np.arange(np.pi/18, np.pi/3, np.pi/18)
|
||||||
|
midpoints = y*np.arctan(angles)
|
||||||
|
end_points = midpoints + SPACE_HEIGHT*np.arctan(2*angles)
|
||||||
|
return [
|
||||||
|
Mobject(
|
||||||
|
Line(start_point, [midpoint, 0, 0]),
|
||||||
|
Line([midpoint, 0, 0], [end_point, -SPACE_HEIGHT, 0])
|
||||||
|
).ingest_sub_mobjects()
|
||||||
|
for midpoint, end_point in zip(midpoints, end_points)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class ShowMultiplePathsScene(PhotonScene):
|
||||||
|
def construct(self):
|
||||||
|
text = TextMobject("Which path minimizes travel time?")
|
||||||
|
text.to_edge(UP)
|
||||||
|
self.generate_start_and_end_points()
|
||||||
|
point_a = Dot(self.start_point)
|
||||||
|
point_b = Dot(self.end_point)
|
||||||
|
A = TextMobject("A").next_to(point_a, UP)
|
||||||
|
B = TextMobject("B").next_to(point_b, DOWN)
|
||||||
|
paths = self.get_paths()
|
||||||
|
|
||||||
|
for point, letter in [(point_a, A), (point_b, B)]:
|
||||||
|
self.play(
|
||||||
|
ShowCreation(point),
|
||||||
|
ShimmerIn(letter)
|
||||||
|
)
|
||||||
|
self.play(ShimmerIn(text))
|
||||||
|
curr_path = paths[0].copy()
|
||||||
|
curr_path_copy = curr_path.copy().ingest_sub_mobjects()
|
||||||
|
self.play(
|
||||||
|
self.photon_run_along_path(curr_path),
|
||||||
|
ShowCreation(curr_path_copy, rate_func = rush_into)
|
||||||
|
)
|
||||||
|
self.remove(curr_path_copy)
|
||||||
|
for path in paths[1:] + [paths[0]]:
|
||||||
|
self.play(Transform(curr_path, path, run_time = 4))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
def generate_start_and_end_points(self):
|
||||||
|
raise Exception("Not Implemented")
|
||||||
|
|
||||||
|
def get_paths(self):
|
||||||
|
raise Exception("Not implemented")
|
||||||
|
|
||||||
|
|
||||||
|
class ShowMultiplePathsThroughLens(ShowMultiplePathsScene):
|
||||||
|
def construct(self):
|
||||||
|
self.lens = Lens()
|
||||||
|
self.add(self.lens)
|
||||||
|
ShowMultiplePathsScene.construct(self)
|
||||||
|
|
||||||
|
def generate_start_and_end_points(self):
|
||||||
|
self.start_point = 3*LEFT + UP
|
||||||
|
self.end_point = 2*RIGHT
|
||||||
|
|
||||||
|
def get_paths(self):
|
||||||
|
alphas = [0.2, 0.45, 0.55, 0.8]
|
||||||
|
lower_right, upper_right, upper_left, lower_left = map(
|
||||||
|
self.lens.point_from_proportion, alphas
|
||||||
|
)
|
||||||
|
return [
|
||||||
|
Mobject(
|
||||||
|
Line(self.start_point, a),
|
||||||
|
Line(a, b),
|
||||||
|
Line(b, self.end_point)
|
||||||
|
).highlight(color)
|
||||||
|
for (a, b), color in zip(
|
||||||
|
[
|
||||||
|
(upper_left, upper_right),
|
||||||
|
(upper_left, lower_right),
|
||||||
|
(lower_left, lower_right),
|
||||||
|
(lower_left, upper_right),
|
||||||
|
],
|
||||||
|
Color(YELLOW).range_to(WHITE, 4)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class ShowMultiplePathsOffMirror(ShowMultiplePathsScene):
|
||||||
|
def construct(self):
|
||||||
|
mirror = Line(*SPACE_HEIGHT*np.array([DOWN, UP]))
|
||||||
|
mirror.highlight(GREY)
|
||||||
|
self.add(mirror)
|
||||||
|
ShowMultiplePathsScene.construct(self)
|
||||||
|
|
||||||
|
def generate_start_and_end_points(self):
|
||||||
|
self.start_point = 4*LEFT + 2*UP
|
||||||
|
self.end_point = 4*LEFT + 2*DOWN
|
||||||
|
|
||||||
|
def get_paths(self):
|
||||||
|
return [
|
||||||
|
Mobject(
|
||||||
|
Line(self.start_point, midpoint),
|
||||||
|
Line(midpoint, self.end_point)
|
||||||
|
).highlight(color)
|
||||||
|
for midpoint, color in zip(
|
||||||
|
[2*UP, 2*DOWN],
|
||||||
|
Color(YELLOW).range_to(WHITE, 2)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class ShowMultiplePathsInGlass(ShowMultiplePathsScene):
|
||||||
|
def construct(self):
|
||||||
|
glass = Region(lambda x, y : y < 0)
|
||||||
|
self.highlight_region(glass, BLUE_E)
|
||||||
|
ShowMultiplePathsScene.construct(self)
|
||||||
|
|
||||||
|
def generate_start_and_end_points(self):
|
||||||
|
self.start_point = 3*LEFT + 2*UP
|
||||||
|
self.end_point = 3*RIGHT + 2*DOWN
|
||||||
|
|
||||||
|
def get_paths(self):
|
||||||
|
return [
|
||||||
|
Mobject(
|
||||||
|
Line(self.start_point, midpoint),
|
||||||
|
Line(midpoint, self.end_point)
|
||||||
|
).highlight(color)
|
||||||
|
for midpoint, color in zip(
|
||||||
|
[3*LEFT, 3*RIGHT],
|
||||||
|
Color(YELLOW).range_to(WHITE, 2)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue