mirror of
https://github.com/3b1b/manim.git
synced 2025-09-19 04:41:56 +00:00
tweaking PondScene
This commit is contained in:
parent
342d6eaa82
commit
80b35918cf
2 changed files with 878 additions and 9 deletions
|
@ -103,7 +103,7 @@ class AngleUpdater(ContinualAnimation):
|
|||
|
||||
|
||||
|
||||
class LightIndicator(Mobject):
|
||||
class LightIndicator(VMobject):
|
||||
CONFIG = {
|
||||
"radius": 0.5,
|
||||
"intensity": 0,
|
||||
|
@ -2303,7 +2303,7 @@ class IPTScene2(Scene):
|
|||
|
||||
|
||||
|
||||
class PondScene(ThreeDScene):
|
||||
class InscribedAngleScene(ThreeDScene):
|
||||
|
||||
|
||||
|
||||
|
@ -2329,11 +2329,14 @@ class PondScene(ThreeDScene):
|
|||
|
||||
self.cumulated_zoom_factor = 1
|
||||
|
||||
#self.force_skipping()
|
||||
self.force_skipping()
|
||||
|
||||
|
||||
def zoom_out_scene(factor):
|
||||
|
||||
if self.mobjects.contains(self.ls0_dot):
|
||||
self.play(FadeOut(self.ls0_dot))
|
||||
|
||||
phi0 = self.camera.get_phi() # default is 0 degs
|
||||
theta0 = self.camera.get_theta() # default is -90 degs
|
||||
distance0 = self.camera.get_distance()
|
||||
|
@ -2349,6 +2352,9 @@ class PondScene(ThreeDScene):
|
|||
|
||||
self.cumulated_zoom_factor *= factor
|
||||
|
||||
if not self.mobjects.contains(self.ls0_dot):
|
||||
self.play(FadeIn(self.ls0_dot))
|
||||
|
||||
|
||||
def shift_scene(v):
|
||||
self.play(
|
||||
|
@ -2368,7 +2374,7 @@ class PondScene(ThreeDScene):
|
|||
|
||||
self.obs_dot = Dot(OBSERVER_POINT, fill_color = DOT_COLOR)
|
||||
ls0_dot = Dot(OBSERVER_POINT + 2 * LAKE0_RADIUS * UP, fill_color = WHITE)
|
||||
self.unzoomable_mobs.add(self.obs_dot, ls0_dot)
|
||||
self.unzoomable_mobs.add(self.obs_dot) #, ls0_dot)
|
||||
|
||||
# lake
|
||||
lake0 = Circle(radius = LAKE0_RADIUS,
|
||||
|
@ -2752,6 +2758,852 @@ class PondScene(ThreeDScene):
|
|||
|
||||
|
||||
|
||||
self.revert_to_original_skipping_status()
|
||||
|
||||
|
||||
ANGLE_COLOR1 = RED
|
||||
ANGLE_COLOR2 = GREEN
|
||||
|
||||
|
||||
for mob in self.mobjects:
|
||||
mob.fade(1.0)
|
||||
|
||||
for hyp in self.hypotenuses:
|
||||
hyp.set_stroke(width = 0)
|
||||
for alt in self.altitudes:
|
||||
alt.set_stroke(width = 0)
|
||||
for leg in self.legs:
|
||||
leg.set_stroke(width = 0)
|
||||
self.inner_lake.set_stroke(width = 0)
|
||||
self.outer_lake.set_stroke(width = 0)
|
||||
|
||||
self.wait()
|
||||
|
||||
inner_lake_center = self.inner_lake.get_center()
|
||||
inner_lake_radius = self.lake_radius * 0.25
|
||||
inner_ls = VGroup()
|
||||
for i in range(4):
|
||||
theta = -TAU/4 + (i+0.5) * TAU/4
|
||||
point = inner_lake_center + inner_lake_radius * np.array([np.cos(theta), np.sin(theta),0])
|
||||
dot = Dot(point, color = LAKE_STROKE_COLOR, radius = 0.3)
|
||||
inner_ls.add(dot)
|
||||
|
||||
self.add(inner_ls)
|
||||
|
||||
inner_ls1 = inner_ls.submobjects[0]
|
||||
inner_ls2 = inner_ls.submobjects[1]
|
||||
inner_ls1_center = inner_ls1.get_center()
|
||||
inner_ls2_center = inner_ls2.get_center()
|
||||
|
||||
outer_lake_center = self.outer_lake.get_center()
|
||||
outer_lake_radius = self.lake_radius * 0.5
|
||||
outer_ls = VGroup()
|
||||
for i in range(8):
|
||||
theta = -TAU/4 + (i+0.5) * TAU/8
|
||||
point = outer_lake_center + outer_lake_radius * np.array([np.cos(theta), np.sin(theta),0])
|
||||
dot = Dot(point, color = LAKE_STROKE_COLOR, radius = 0.3)
|
||||
outer_ls.add(dot)
|
||||
|
||||
self.add(outer_ls)
|
||||
|
||||
outer_ls1 = outer_ls.submobjects[0]
|
||||
outer_ls2 = outer_ls.submobjects[1]
|
||||
outer_ls1_center = outer_ls1.get_center()
|
||||
outer_ls2_center = outer_ls2.get_center()
|
||||
|
||||
self.wait()
|
||||
|
||||
arc_radius = 2.0
|
||||
|
||||
line1 = Line(inner_lake_center, inner_ls1_center, color = WHITE)
|
||||
line2 = Line(inner_lake_center, inner_ls2_center, color = WHITE)
|
||||
|
||||
|
||||
#arc_point1 = interpolate(inner_lake_center, inner_ls1_center, 0.2)
|
||||
#arc_point2 = interpolate(inner_lake_center, inner_ls2_center, 0.2)
|
||||
#inner_angle_arc = ArcBetweenPoints(arc_point1, arc_point2, angle = TAU/4)
|
||||
inner_angle_arc = Arc(angle = TAU/4, start_angle = -TAU/8, radius = arc_radius,
|
||||
stroke_color = ANGLE_COLOR1)
|
||||
inner_angle_arc.move_arc_center_to(inner_lake_center)
|
||||
|
||||
inner_label = TexMobject("\\theta", fill_color = ANGLE_COLOR1).scale(3).next_to(inner_angle_arc, LEFT, buff = -0.1)
|
||||
|
||||
self.play(
|
||||
ShowCreation(line1),
|
||||
ShowCreation(line2),
|
||||
)
|
||||
self.play(
|
||||
ShowCreation(inner_angle_arc),
|
||||
FadeIn(inner_label)
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
self.wait()
|
||||
|
||||
|
||||
|
||||
line3 = Line(outer_lake_center, inner_ls1_center, color = WHITE)
|
||||
line4 = Line(outer_lake_center, inner_ls2_center, color = WHITE)
|
||||
outer_angle_arc = Arc(angle = TAU/8, start_angle = -3*TAU/16, radius = arc_radius,
|
||||
stroke_color = ANGLE_COLOR2)
|
||||
outer_angle_arc.move_arc_center_to(outer_lake_center)
|
||||
|
||||
outer_label = TexMobject("{\\theta \over 2}", color = ANGLE_COLOR2).scale(2.5).move_to(outer_angle_arc)
|
||||
outer_label.shift([-2,-1,0])
|
||||
|
||||
self.play(
|
||||
ShowCreation(line3),
|
||||
ShowCreation(line4),
|
||||
)
|
||||
self.play(
|
||||
ShowCreation(outer_angle_arc),
|
||||
FadeIn(outer_label)
|
||||
)
|
||||
|
||||
|
||||
|
||||
self.wait()
|
||||
|
||||
|
||||
|
||||
line5 = Line(outer_lake_center, outer_ls1_center, color = WHITE)
|
||||
line6 = Line(outer_lake_center, outer_ls2_center, color = WHITE)
|
||||
|
||||
self.play(
|
||||
ShowCreation(line5),
|
||||
ShowCreation(line6)
|
||||
)
|
||||
|
||||
|
||||
self.wait()
|
||||
|
||||
self.play(
|
||||
FadeOut(line1),
|
||||
FadeOut(line2),
|
||||
FadeOut(line3),
|
||||
FadeOut(line4),
|
||||
FadeOut(line5),
|
||||
FadeOut(line6),
|
||||
FadeOut(inner_angle_arc),
|
||||
FadeOut(outer_angle_arc),
|
||||
FadeOut(inner_label),
|
||||
FadeOut(outer_label),
|
||||
)
|
||||
|
||||
|
||||
self.wait()
|
||||
|
||||
inner_lines = VGroup()
|
||||
inner_arcs = VGroup()
|
||||
|
||||
for i in range(-2,2):
|
||||
|
||||
theta = -TAU/4 + (i+0.5)*TAU/4
|
||||
ls_point = inner_lake_center + inner_lake_radius * np.array([
|
||||
np.cos(theta), np.sin(theta),0])
|
||||
line = Line(inner_lake_center, ls_point, color = WHITE)
|
||||
inner_lines.add(line)
|
||||
|
||||
arc = Arc(angle = TAU/4, start_angle = theta, radius = arc_radius,
|
||||
stroke_color = ANGLE_COLOR1)
|
||||
arc.move_arc_center_to(inner_lake_center)
|
||||
inner_arcs.add(arc)
|
||||
|
||||
if i == 1:
|
||||
arc.set_stroke(width = 0)
|
||||
|
||||
for line in inner_lines.submobjects:
|
||||
self.play(
|
||||
ShowCreation(line),
|
||||
)
|
||||
self.add_foreground_mobject(inner_lines)
|
||||
for arc in inner_arcs.submobjects:
|
||||
self.play(
|
||||
ShowCreation(arc)
|
||||
)
|
||||
|
||||
self.wait()
|
||||
|
||||
outer_lines = VGroup()
|
||||
outer_arcs = VGroup()
|
||||
|
||||
for i in range(-2,2):
|
||||
|
||||
theta = -TAU/4 + (i+0.5)*TAU/4
|
||||
|
||||
ls_point = inner_lake_center + inner_lake_radius * np.array([
|
||||
np.cos(theta), np.sin(theta),0])
|
||||
line = Line(outer_lake_center, ls_point, color = WHITE)
|
||||
outer_lines.add(line)
|
||||
|
||||
theta = -TAU/4 + (i+0.5)*TAU/8
|
||||
arc = Arc(angle = TAU/8, start_angle = theta, radius = arc_radius,
|
||||
stroke_color = ANGLE_COLOR2)
|
||||
arc.move_arc_center_to(outer_lake_center)
|
||||
outer_arcs.add(arc)
|
||||
|
||||
if i == 1:
|
||||
arc.set_stroke(width = 0)
|
||||
|
||||
|
||||
for line in outer_lines.submobjects:
|
||||
self.play(
|
||||
ShowCreation(line),
|
||||
)
|
||||
self.add_foreground_mobject(outer_lines)
|
||||
for arc in outer_arcs.submobjects:
|
||||
self.play(
|
||||
ShowCreation(arc)
|
||||
)
|
||||
|
||||
self.wait()
|
||||
|
||||
self.play(
|
||||
FadeOut(inner_lines),
|
||||
FadeOut(inner_arcs)
|
||||
)
|
||||
|
||||
|
||||
outer_lines2 = VGroup()
|
||||
|
||||
for i in range(-2,2):
|
||||
|
||||
theta = -TAU/4 + (i+0.5)*TAU/8
|
||||
ls_point = outer_lake_center + outer_lake_radius * np.array([
|
||||
np.cos(theta), np.sin(theta),0])
|
||||
line = Line(outer_lake_center, ls_point, color = WHITE)
|
||||
outer_lines2.add(line)
|
||||
|
||||
self.play(
|
||||
ShowCreation(outer_lines2),
|
||||
)
|
||||
|
||||
self.wait()
|
||||
|
||||
outer_lines3 = outer_lines2.copy().rotate(TAU/2, about_point = outer_lake_center)
|
||||
outer_arcs3 = outer_arcs.copy().rotate(TAU/2, about_point = outer_lake_center)
|
||||
|
||||
self.play(
|
||||
ShowCreation(outer_lines3),
|
||||
)
|
||||
self.add_foreground_mobject(outer_lines3)
|
||||
for arc in outer_arcs3.submobjects:
|
||||
self.play(
|
||||
ShowCreation(arc)
|
||||
)
|
||||
|
||||
last_arc = outer_arcs3.submobjects[0].copy()
|
||||
last_arc.rotate(-TAU/8, about_point = outer_lake_center)
|
||||
last_arc2 = last_arc.copy()
|
||||
last_arc2.rotate(TAU/2, about_point = outer_lake_center)
|
||||
|
||||
self.play(
|
||||
ShowCreation(last_arc),
|
||||
ShowCreation(last_arc2),
|
||||
)
|
||||
|
||||
self.wait()
|
||||
|
||||
self.play(
|
||||
FadeOut(outer_lines2),
|
||||
FadeOut(outer_lines3),
|
||||
FadeOut(outer_arcs),
|
||||
FadeOut(outer_arcs3),
|
||||
FadeOut(last_arc),
|
||||
FadeOut(last_arc2),
|
||||
)
|
||||
|
||||
self.play(
|
||||
FadeOut(inner_ls),
|
||||
FadeOut(outer_ls),
|
||||
)
|
||||
|
||||
|
||||
self.wait()
|
||||
|
||||
|
||||
class PondScene(ThreeDScene):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def construct(self):
|
||||
|
||||
BASELINE_YPOS = -2.5
|
||||
OBSERVER_POINT = np.array([0,BASELINE_YPOS,0])
|
||||
LAKE0_RADIUS = 1.5
|
||||
INDICATOR_RADIUS = 0.6
|
||||
TICK_SIZE = 0.5
|
||||
LIGHTHOUSE_HEIGHT = 0.2
|
||||
LAKE_COLOR = BLUE
|
||||
LAKE_OPACITY = 0.15
|
||||
LAKE_STROKE_WIDTH = 5.0
|
||||
LAKE_STROKE_COLOR = BLUE
|
||||
TEX_SCALE = 0.8
|
||||
DOT_COLOR = BLUE
|
||||
|
||||
LIGHT_MAX_INT = 1
|
||||
LIGHT_SCALE = 5
|
||||
LIGHT_CUTOFF = 1
|
||||
|
||||
RIGHT_ANGLE_SIZE = 0.3
|
||||
|
||||
|
||||
self.cumulated_zoom_factor = 1
|
||||
|
||||
#self.force_skipping()
|
||||
|
||||
|
||||
def right_angle(pointA, pointB, pointC):
|
||||
|
||||
v1 = pointA - pointB
|
||||
v1 = RIGHT_ANGLE_SIZE * v1/np.linalg.norm(v1)
|
||||
v2 = pointC - pointB
|
||||
v2 = RIGHT_ANGLE_SIZE * v2/np.linalg.norm(v2)
|
||||
|
||||
P = pointB
|
||||
Q = pointB + v1
|
||||
R = Q + v2
|
||||
S = R - v1
|
||||
angle_sign = VMobject()
|
||||
angle_sign.set_points_as_corners([P,Q,R,S,P])
|
||||
angle_sign.mark_paths_closed = True
|
||||
angle_sign.set_fill(color = WHITE, opacity = 1)
|
||||
angle_sign.set_stroke(width = 0)
|
||||
return angle_sign
|
||||
|
||||
|
||||
def triangle(pointA, pointB, pointC):
|
||||
|
||||
mob = VMobject()
|
||||
mob.set_points_as_corners([pointA, pointB, pointC, pointA])
|
||||
mob.mark_paths_closed = True
|
||||
mob.set_fill(color = WHITE, opacity = 0.5)
|
||||
mob.set_stroke(width = 0)
|
||||
return mob
|
||||
|
||||
|
||||
def zoom_out_scene(factor):
|
||||
|
||||
phi0 = self.camera.get_phi() # default is 0 degs
|
||||
theta0 = self.camera.get_theta() # default is -90 degs
|
||||
distance0 = self.camera.get_distance()
|
||||
|
||||
distance1 = 2 * distance0
|
||||
camera_target_point = self.camera.get_spherical_coords(phi0, theta0, distance1)
|
||||
|
||||
self.play(
|
||||
ApplyMethod(self.camera.rotation_mobject.move_to, camera_target_point),
|
||||
self.zoomable_mobs.shift, self.obs_dot.get_center(),
|
||||
self.unzoomable_mobs.scale,2,{"about_point" : ORIGIN},
|
||||
)
|
||||
|
||||
self.cumulated_zoom_factor *= factor
|
||||
|
||||
|
||||
def shift_scene(v):
|
||||
self.play(
|
||||
self.zoomable_mobs.shift,v,
|
||||
self.unzoomable_mobs.shift,v
|
||||
)
|
||||
|
||||
|
||||
self.zoomable_mobs = VMobject()
|
||||
self.unzoomable_mobs = VMobject()
|
||||
|
||||
|
||||
baseline = VMobject()
|
||||
baseline.set_points_as_corners([[-8,BASELINE_YPOS,0],[8,BASELINE_YPOS,0]])
|
||||
baseline.set_stroke(width = 0) # in case it gets accidentally added to the scene
|
||||
self.zoomable_mobs.add(baseline) # prob not necessary
|
||||
|
||||
self.obs_dot = Dot(OBSERVER_POINT, fill_color = DOT_COLOR)
|
||||
ls0_dot = Dot(OBSERVER_POINT + 2 * LAKE0_RADIUS * UP, fill_color = WHITE)
|
||||
self.unzoomable_mobs.add(self.obs_dot, ls0_dot)
|
||||
|
||||
# lake
|
||||
lake0 = Circle(radius = LAKE0_RADIUS,
|
||||
stroke_width = 0,
|
||||
fill_color = LAKE_COLOR,
|
||||
fill_opacity = LAKE_OPACITY
|
||||
)
|
||||
lake0.move_to(OBSERVER_POINT + LAKE0_RADIUS * UP)
|
||||
self.zoomable_mobs.add(lake0)
|
||||
|
||||
# Morty and indicator
|
||||
morty = Mortimer().scale(0.3)
|
||||
morty.next_to(OBSERVER_POINT,DOWN)
|
||||
indicator = LightIndicator(precision = 2,
|
||||
radius = INDICATOR_RADIUS,
|
||||
show_reading = False,
|
||||
color = LIGHT_COLOR
|
||||
)
|
||||
indicator.next_to(morty,LEFT)
|
||||
self.unzoomable_mobs.add(morty, indicator)
|
||||
|
||||
# first lighthouse
|
||||
original_op_func = inverse_quadratic(LIGHT_MAX_INT,LIGHT_SCALE,LIGHT_CUTOFF)
|
||||
ls0 = LightSource(opacity_function = original_op_func)
|
||||
ls0.move_source_to(OBSERVER_POINT + LAKE0_RADIUS * 2 * UP)
|
||||
self.zoomable_mobs.add(ls0, ls0.lighthouse, ls0.ambient_light)
|
||||
|
||||
self.add(lake0,morty,self.obs_dot,ls0_dot, ls0.lighthouse)
|
||||
self.add_foreground_mobject(morty)
|
||||
self.add_foreground_mobject(self.obs_dot)
|
||||
self.add_foreground_mobject(ls0_dot)
|
||||
self.wait()
|
||||
|
||||
|
||||
# shore arcs
|
||||
arc_left = Arc(-TAU/2,
|
||||
radius = LAKE0_RADIUS,
|
||||
start_angle = -TAU/4,
|
||||
stroke_width = LAKE_STROKE_WIDTH,
|
||||
stroke_color = LAKE_STROKE_COLOR
|
||||
)
|
||||
arc_left.move_arc_center_to(OBSERVER_POINT + LAKE0_RADIUS * UP)
|
||||
|
||||
one_left = TexMobject("1", color = LAKE_COLOR).scale(TEX_SCALE)
|
||||
one_left.next_to(arc_left,LEFT)
|
||||
|
||||
|
||||
arc_right = Arc(TAU/2,
|
||||
radius = LAKE0_RADIUS,
|
||||
start_angle = -TAU/4,
|
||||
stroke_width = LAKE_STROKE_WIDTH,
|
||||
stroke_color = LAKE_STROKE_COLOR
|
||||
)
|
||||
arc_right.move_arc_center_to(OBSERVER_POINT + LAKE0_RADIUS * UP)
|
||||
|
||||
one_right = TexMobject("1", color = LAKE_COLOR).scale(TEX_SCALE)
|
||||
one_right.next_to(arc_right,RIGHT)
|
||||
|
||||
self.play(
|
||||
ShowCreation(arc_left),
|
||||
Write(one_left),
|
||||
ShowCreation(arc_right),
|
||||
Write(one_right),
|
||||
)
|
||||
|
||||
|
||||
self.play(
|
||||
SwitchOn(ls0.ambient_light),
|
||||
lake0.set_stroke,{"color": LAKE_STROKE_COLOR, "width" : LAKE_STROKE_WIDTH},
|
||||
)
|
||||
|
||||
self.play(FadeIn(indicator))
|
||||
self.add_foreground_mobject(indicator)
|
||||
|
||||
self.play(
|
||||
indicator.set_intensity,0.5
|
||||
)
|
||||
|
||||
diameter_start = interpolate(OBSERVER_POINT,ls0.get_source_point(),0.05)
|
||||
diameter_stop = interpolate(OBSERVER_POINT,ls0.get_source_point(),0.95)
|
||||
|
||||
# diameter
|
||||
diameter = DoubleArrow(diameter_start,
|
||||
diameter_stop,
|
||||
buff = 0,
|
||||
color = WHITE,
|
||||
)
|
||||
diameter_text = TexMobject("d").scale(TEX_SCALE)
|
||||
diameter_text.next_to(diameter,RIGHT)
|
||||
|
||||
self.play(
|
||||
ShowCreation(diameter),
|
||||
Write(diameter_text),
|
||||
#FadeOut(self.obs_dot),
|
||||
FadeOut(ls0_dot)
|
||||
)
|
||||
|
||||
indicator_reading = TexMobject("{1\over d^2}").scale(TEX_SCALE)
|
||||
indicator_reading.move_to(indicator)
|
||||
self.unzoomable_mobs.add(indicator_reading)
|
||||
|
||||
self.play(
|
||||
FadeIn(indicator_reading)
|
||||
)
|
||||
self.add_foreground_mobject(indicator_reading)
|
||||
|
||||
# replace d with its value
|
||||
new_diameter_text = TexMobject("{2\over \pi}").scale(TEX_SCALE)
|
||||
new_diameter_text.color = LAKE_COLOR
|
||||
new_diameter_text.move_to(diameter_text)
|
||||
self.play(
|
||||
Transform(diameter_text,new_diameter_text)
|
||||
)
|
||||
|
||||
# insert into indicator reading
|
||||
new_reading = TexMobject("{\pi^2 \over 4}").scale(TEX_SCALE)
|
||||
new_reading.move_to(indicator)
|
||||
|
||||
self.play(
|
||||
Transform(indicator_reading,new_reading)
|
||||
)
|
||||
|
||||
self.wait()
|
||||
|
||||
self.play(
|
||||
FadeOut(one_left),
|
||||
FadeOut(one_right),
|
||||
FadeOut(diameter_text),
|
||||
FadeOut(arc_left),
|
||||
FadeOut(arc_right)
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
def indicator_wiggle():
|
||||
INDICATOR_WIGGLE_FACTOR = 1.3
|
||||
|
||||
self.play(
|
||||
ScaleInPlace(indicator, INDICATOR_WIGGLE_FACTOR, rate_func = wiggle),
|
||||
ScaleInPlace(indicator_reading, INDICATOR_WIGGLE_FACTOR, rate_func = wiggle)
|
||||
)
|
||||
|
||||
|
||||
def angle_for_index(i,step):
|
||||
return -TAU/4 + TAU/2**step * (i + 0.5)
|
||||
|
||||
|
||||
def position_for_index(i, step, scaled_down = False):
|
||||
|
||||
theta = angle_for_index(i,step)
|
||||
radial_vector = np.array([np.cos(theta),np.sin(theta),0])
|
||||
position = self.lake_center + self.lake_radius * radial_vector
|
||||
|
||||
if scaled_down:
|
||||
return position.scale_about_point(self.obs_dot.get_center(),0.5)
|
||||
else:
|
||||
return position
|
||||
|
||||
|
||||
def split_light_source(i, step, show_steps = True, run_time = 1):
|
||||
|
||||
ls_new_loc1 = position_for_index(i,step + 1)
|
||||
ls_new_loc2 = position_for_index(i + 2**step,step + 1)
|
||||
|
||||
hyp = VMobject()
|
||||
hyp1 = Line(self.lake_center,ls_new_loc1)
|
||||
hyp2 = Line(self.lake_center,ls_new_loc2)
|
||||
hyp.add(hyp2,hyp1)
|
||||
self.new_hypotenuses.append(hyp)
|
||||
|
||||
if show_steps == True:
|
||||
self.play(
|
||||
ShowCreation(hyp, run_time = run_time)
|
||||
)
|
||||
|
||||
leg1 = Line(self.obs_dot.get_center(),ls_new_loc1)
|
||||
leg2 = Line(self.obs_dot.get_center(),ls_new_loc2)
|
||||
self.new_legs_1.append(leg1)
|
||||
self.new_legs_2.append(leg2)
|
||||
|
||||
if show_steps == True:
|
||||
self.play(
|
||||
ShowCreation(leg1, run_time = run_time),
|
||||
ShowCreation(leg2, run_time = run_time),
|
||||
)
|
||||
|
||||
ls1 = self.light_sources_array[i]
|
||||
|
||||
|
||||
ls2 = ls1.copy()
|
||||
self.add(ls2)
|
||||
self.additional_light_sources.append(ls2)
|
||||
|
||||
# check if the light sources are on screen
|
||||
ls_old_loc = np.array(ls1.get_source_point())
|
||||
onscreen_old = np.any(np.abs(ls_old_loc) < 10)
|
||||
onscreen_1 = np.any(np.abs(ls_new_loc1) < 10)
|
||||
onscreen_2 = np.any(np.abs(ls_new_loc2) < 10)
|
||||
show_animation = (onscreen_old or onscreen_1 or onscreen_2)
|
||||
|
||||
if show_animation:
|
||||
self.play(
|
||||
ApplyMethod(ls1.move_source_to,ls_new_loc1, run_time = run_time),
|
||||
ApplyMethod(ls2.move_source_to,ls_new_loc2, run_time = run_time),
|
||||
)
|
||||
else:
|
||||
ls1.move_source_to(ls_new_loc1)
|
||||
ls2.move_source_to(ls_new_loc1)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def construction_step(n, show_steps = True, run_time = 1,
|
||||
simultaneous_splitting = False):
|
||||
|
||||
# we assume that the scene contains:
|
||||
# an inner lake, self.inner_lake
|
||||
# an outer lake, self.outer_lake
|
||||
# light sources, self.light_sources
|
||||
# legs from the observer point to each light source
|
||||
# self.legs
|
||||
# altitudes from the observer point to the
|
||||
# locations of the light sources in the previous step
|
||||
# self.altitudes
|
||||
# hypotenuses connecting antipodal light sources
|
||||
# self.hypotenuses
|
||||
|
||||
# these are mobjects!
|
||||
|
||||
|
||||
# first, fade out all of the hypotenuses and altitudes
|
||||
|
||||
if show_steps == True:
|
||||
self.zoomable_mobs.remove(self.hypotenuses, self.altitudes, self.inner_lake)
|
||||
self.play(
|
||||
FadeOut(self.hypotenuses),
|
||||
FadeOut(self.altitudes),
|
||||
FadeOut(self.inner_lake)
|
||||
)
|
||||
else:
|
||||
self.zoomable_mobs.remove(self.inner_lake)
|
||||
self.play(
|
||||
FadeOut(self.inner_lake)
|
||||
)
|
||||
|
||||
# create a new, outer lake
|
||||
self.lake_center = self.obs_dot.get_center() + self.lake_radius * UP
|
||||
|
||||
new_outer_lake = Circle(radius = self.lake_radius,
|
||||
stroke_width = LAKE_STROKE_WIDTH,
|
||||
fill_color = LAKE_COLOR,
|
||||
fill_opacity = LAKE_OPACITY,
|
||||
stroke_color = LAKE_STROKE_COLOR
|
||||
)
|
||||
new_outer_lake.move_to(self.lake_center)
|
||||
|
||||
if show_steps == True:
|
||||
self.play(
|
||||
FadeIn(new_outer_lake, run_time = run_time),
|
||||
FadeIn(ls0_dot)
|
||||
)
|
||||
else:
|
||||
self.play(
|
||||
FadeIn(new_outer_lake, run_time = run_time),
|
||||
)
|
||||
|
||||
self.wait()
|
||||
|
||||
self.inner_lake = self.outer_lake
|
||||
self.outer_lake = new_outer_lake
|
||||
self.altitudes = self.legs
|
||||
#self.lake_center = self.outer_lake.get_center()
|
||||
|
||||
self.additional_light_sources = []
|
||||
self.new_legs_1 = []
|
||||
self.new_legs_2 = []
|
||||
self.new_hypotenuses = []
|
||||
|
||||
for i in range(2**n):
|
||||
|
||||
split_light_source(i,
|
||||
step = n,
|
||||
show_steps = show_steps,
|
||||
run_time = run_time
|
||||
)
|
||||
|
||||
if n == 1 and i == 0:
|
||||
# show again where the right angles are
|
||||
A = self.light_sources[0].get_center()
|
||||
B = self.additional_light_sources[0].get_center()
|
||||
C = self.obs_dot.get_center()
|
||||
|
||||
triangle1 = triangle(
|
||||
A, C, B
|
||||
)
|
||||
right_angle1 = right_angle(
|
||||
A, C, B
|
||||
)
|
||||
|
||||
self.play(
|
||||
FadeIn(triangle1),
|
||||
FadeIn(right_angle1)
|
||||
)
|
||||
|
||||
self.wait()
|
||||
|
||||
self.play(
|
||||
FadeOut(triangle1),
|
||||
FadeOut(right_angle1)
|
||||
)
|
||||
|
||||
self.wait()
|
||||
|
||||
H = self.inner_lake.get_center() + self.lake_radius/2 * RIGHT
|
||||
triangle2 = triangle(
|
||||
B, H, C
|
||||
)
|
||||
|
||||
right_angle2 = right_angle(
|
||||
B, H, C
|
||||
)
|
||||
|
||||
self.play(
|
||||
FadeIn(triangle2),
|
||||
FadeIn(right_angle2)
|
||||
)
|
||||
|
||||
self.wait()
|
||||
|
||||
self.play(
|
||||
FadeOut(triangle2),
|
||||
FadeOut(right_angle2)
|
||||
)
|
||||
|
||||
self.wait()
|
||||
|
||||
|
||||
# collect the newly created mobs (in arrays)
|
||||
# into the appropriate Mobject containers
|
||||
|
||||
self.legs = VMobject()
|
||||
for leg in self.new_legs_1:
|
||||
self.legs.add(leg)
|
||||
self.zoomable_mobs.add(leg)
|
||||
for leg in self.new_legs_2:
|
||||
self.legs.add(leg)
|
||||
self.zoomable_mobs.add(leg)
|
||||
|
||||
for hyp in self.hypotenuses.submobjects:
|
||||
self.zoomable_mobs.remove(hyp)
|
||||
|
||||
self.hypotenuses = VMobject()
|
||||
for hyp in self.new_hypotenuses:
|
||||
self.hypotenuses.add(hyp)
|
||||
self.zoomable_mobs.add(hyp)
|
||||
|
||||
for ls in self.additional_light_sources:
|
||||
self.light_sources.add(ls)
|
||||
self.light_sources_array.append(ls)
|
||||
self.zoomable_mobs.add(ls)
|
||||
|
||||
# update scene
|
||||
self.add(
|
||||
self.light_sources,
|
||||
self.inner_lake,
|
||||
self.outer_lake,
|
||||
)
|
||||
self.zoomable_mobs.add(self.light_sources, self.inner_lake, self.outer_lake)
|
||||
|
||||
if show_steps == True:
|
||||
self.add(
|
||||
self.legs,
|
||||
self.hypotenuses,
|
||||
self.altitudes,
|
||||
)
|
||||
self.zoomable_mobs.add(self.legs, self.hypotenuses, self.altitudes)
|
||||
|
||||
|
||||
self.wait()
|
||||
|
||||
if show_steps == True:
|
||||
self.play(FadeOut(ls0_dot))
|
||||
|
||||
#self.lake_center = ls0_loc = self.obs_dot.get_center() + self.lake_radius * UP
|
||||
self.lake_radius *= 2
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
self.lake_center = ls0_loc = ls0.get_source_point()
|
||||
|
||||
self.inner_lake = VMobject()
|
||||
self.outer_lake = lake0
|
||||
self.legs = VMobject()
|
||||
self.legs.add(Line(OBSERVER_POINT,self.lake_center))
|
||||
self.altitudes = VMobject()
|
||||
self.hypotenuses = VMobject()
|
||||
self.light_sources_array = [ls0]
|
||||
self.light_sources = VMobject()
|
||||
self.light_sources.add(ls0)
|
||||
|
||||
self.lake_radius = 2 * LAKE0_RADIUS # don't ask...
|
||||
|
||||
self.zoomable_mobs.add(self.inner_lake, self.outer_lake, self.altitudes, self.light_sources)
|
||||
|
||||
self.add(self.inner_lake,
|
||||
self.outer_lake,
|
||||
self.legs,
|
||||
self.altitudes,
|
||||
self.hypotenuses
|
||||
)
|
||||
|
||||
self.play(FadeOut(diameter))
|
||||
|
||||
self.additional_light_sources = []
|
||||
self.new_legs_1 = []
|
||||
self.new_legs_2 = []
|
||||
self.new_hypotenuses = []
|
||||
|
||||
|
||||
construction_step(0)
|
||||
|
||||
my_triangle = triangle(
|
||||
self.light_sources[0].get_source_point(),
|
||||
OBSERVER_POINT,
|
||||
self.light_sources[1].get_source_point()
|
||||
)
|
||||
|
||||
angle_sign1 = right_angle(
|
||||
self.light_sources[0].get_source_point(),
|
||||
OBSERVER_POINT,
|
||||
self.light_sources[1].get_source_point(),
|
||||
)
|
||||
|
||||
self.play(
|
||||
FadeIn(angle_sign1),
|
||||
FadeIn(my_triangle)
|
||||
)
|
||||
|
||||
angle_sign2 = right_angle(
|
||||
self.light_sources[1].get_source_point(),
|
||||
self.lake_center,
|
||||
OBSERVER_POINT,
|
||||
)
|
||||
|
||||
self.play(
|
||||
FadeIn(angle_sign2)
|
||||
)
|
||||
|
||||
self.wait()
|
||||
|
||||
self.play(
|
||||
FadeOut(angle_sign1),
|
||||
FadeOut(angle_sign2),
|
||||
FadeOut(my_triangle)
|
||||
)
|
||||
|
||||
indicator_wiggle()
|
||||
self.play(FadeOut(ls0_dot))
|
||||
zoom_out_scene(2)
|
||||
self.play(FadeIn(ls0_dot))
|
||||
|
||||
construction_step(1)
|
||||
indicator_wiggle()
|
||||
#self.play(FadeOut(ls0_dot))
|
||||
zoom_out_scene(2)
|
||||
|
||||
return
|
||||
|
||||
construction_step(2)
|
||||
indicator_wiggle()
|
||||
self.play(FadeOut(ls0_dot))
|
||||
|
||||
|
||||
|
||||
|
||||
self.play(
|
||||
FadeOut(self.altitudes),
|
||||
|
@ -2839,6 +3691,7 @@ class PondScene(ThreeDScene):
|
|||
indicator.shift,v,
|
||||
indicator_reading.shift,v,
|
||||
open_sea.shift,v,
|
||||
self.obs_dot.shift,v,
|
||||
)
|
||||
self.number_line_labels.shift(v)
|
||||
|
||||
|
@ -2869,6 +3722,13 @@ class PondScene(ThreeDScene):
|
|||
|
||||
self.play(Write(two_sided_sum))
|
||||
|
||||
for i in range(0, MAX_N):
|
||||
self.play(SwitchOff(nl_sources.submobjects[i].ambient_light)
|
||||
)
|
||||
for i in range(MAX_N, 2 * MAX_N - 1):
|
||||
self.play(SwitchOn(nl_sources.submobjects[i].ambient_light)
|
||||
)
|
||||
|
||||
covering_rectangle = Rectangle(
|
||||
width = SPACE_WIDTH * scale,
|
||||
height = 2 * SPACE_HEIGHT * scale,
|
||||
|
@ -2883,6 +3743,7 @@ class PondScene(ThreeDScene):
|
|||
self.add_foreground_mobject(indicator)
|
||||
self.add_foreground_mobject(indicator_reading)
|
||||
|
||||
|
||||
half_indicator_reading = TexMobject("{\pi^2 \over 8}").scale(TEX_SCALE)
|
||||
half_indicator_reading.move_to(indicator)
|
||||
|
||||
|
@ -2890,18 +3751,19 @@ class PondScene(ThreeDScene):
|
|||
|
||||
self.play(
|
||||
FadeIn(covering_rectangle),
|
||||
ReplacementTransform(indicator_reading, half_indicator_reading),
|
||||
Transform(indicator_reading, half_indicator_reading),
|
||||
FadeOut(central_plus_sign)
|
||||
)
|
||||
|
||||
|
||||
equals_sign = TexMobject("=").scale(TEX_SCALE)
|
||||
equals_sign.move_to(central_plus_sign)
|
||||
p = 2 * scale * LEFT
|
||||
p = 2 * scale * LEFT + 0.3 * UP
|
||||
|
||||
self.play(
|
||||
indicator.move_to,p,
|
||||
half_indicator_reading.move_to,p,
|
||||
FadeIn(equals_sign)
|
||||
indicator_reading.move_to,p,
|
||||
FadeIn(equals_sign),
|
||||
)
|
||||
|
||||
# show Randy admiring the result
|
||||
|
@ -2911,6 +3773,11 @@ class PondScene(ThreeDScene):
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class WaitScene(TeacherStudentsScene):
|
||||
|
||||
def construct(self):
|
||||
|
|
|
@ -353,7 +353,9 @@ class SwitchOff(LaggedStart):
|
|||
class Lighthouse(SVGMobject):
|
||||
CONFIG = {
|
||||
"file_name" : "lighthouse",
|
||||
"height" : LIGHTHOUSE_HEIGHT
|
||||
"height" : LIGHTHOUSE_HEIGHT,
|
||||
"fill_color" : WHITE,
|
||||
"fill_opacity" : 1.0,
|
||||
}
|
||||
|
||||
def move_to(self,point):
|
||||
|
|
Loading…
Add table
Reference in a new issue