mirror of
https://github.com/3b1b/manim.git
synced 2025-09-01 00:48:45 +00:00
Added ManipulateLightsourceSetups
This commit is contained in:
parent
0bf9f0b644
commit
3a59795330
1 changed files with 108 additions and 249 deletions
|
@ -56,7 +56,6 @@ inverse_power_law = lambda maxint,scale,cutoff,exponent: \
|
||||||
(lambda r: maxint * (cutoff/(r/scale+cutoff))**exponent)
|
(lambda r: maxint * (cutoff/(r/scale+cutoff))**exponent)
|
||||||
inverse_quadratic = lambda maxint,scale,cutoff: inverse_power_law(maxint,scale,cutoff,2)
|
inverse_quadratic = lambda maxint,scale,cutoff: inverse_power_law(maxint,scale,cutoff,2)
|
||||||
|
|
||||||
|
|
||||||
A = np.array([5.,-3.,0.])
|
A = np.array([5.,-3.,0.])
|
||||||
B = np.array([-5.,3.,0.])
|
B = np.array([-5.,3.,0.])
|
||||||
C = np.array([-5.,-3.,0.])
|
C = np.array([-5.,-3.,0.])
|
||||||
|
@ -74,9 +73,6 @@ prelim_vector = np.array([xB * yA - xA * yB, xC * (xA - xB) + yC * (yA - yB)])
|
||||||
H2 = np.linalg.solve(prelim_matrix,prelim_vector)
|
H2 = np.linalg.solve(prelim_matrix,prelim_vector)
|
||||||
H = np.append(H2, 0.)
|
H = np.append(H2, 0.)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class AngleUpdater(ContinualAnimation):
|
class AngleUpdater(ContinualAnimation):
|
||||||
def __init__(self, angle_arc, spotlight, **kwargs):
|
def __init__(self, angle_arc, spotlight, **kwargs):
|
||||||
self.angle_arc = angle_arc
|
self.angle_arc = angle_arc
|
||||||
|
@ -1713,6 +1709,10 @@ class InverseSquareLaw(ThreeDScene):
|
||||||
self.play(
|
self.play(
|
||||||
screen_group.scale, 2, {"about_edge" : IN + DOWN},
|
screen_group.scale, 2, {"about_edge" : IN + DOWN},
|
||||||
screen_group.shift, unit_distance*RIGHT,
|
screen_group.shift, unit_distance*RIGHT,
|
||||||
|
UpdateFromAlphaFunc(
|
||||||
|
four_copies,
|
||||||
|
lambda nc, a : nc.set_stroke(width = a).set_fill(opacity = 0.5*a)
|
||||||
|
),
|
||||||
four_copies_update_anim,
|
four_copies_update_anim,
|
||||||
screen_copy.shift, 0.25*OUT, #WHY?
|
screen_copy.shift, 0.25*OUT, #WHY?
|
||||||
run_time = 2,
|
run_time = 2,
|
||||||
|
@ -1737,8 +1737,7 @@ class InverseSquareLaw(ThreeDScene):
|
||||||
Write(three, rate_func = squish_rate_func(smooth, 0.5, 1)),
|
Write(three, rate_func = squish_rate_func(smooth, 0.5, 1)),
|
||||||
run_time = 2,
|
run_time = 2,
|
||||||
)
|
)
|
||||||
self.wait()
|
self.wait(10)
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
|
|
||||||
|
@ -1751,261 +1750,121 @@ class InverseSquareLaw(ThreeDScene):
|
||||||
anims += added_anims
|
anims += added_anims
|
||||||
self.play(*anims, run_time = 2)
|
self.play(*anims, run_time = 2)
|
||||||
|
|
||||||
|
class ScreensIntroWrapper(TeacherStudentsScene):
|
||||||
class IndicatorScalingScene(Scene):
|
|
||||||
|
|
||||||
def construct(self):
|
def construct(self):
|
||||||
|
point = VectorizedPoint(SPACE_WIDTH*LEFT/2 + SPACE_HEIGHT*UP/2)
|
||||||
|
self.play(self.teacher.change, "raise_right_hand")
|
||||||
|
self.change_student_modes(
|
||||||
|
"pondering", "erm", "confused",
|
||||||
|
look_at_arg = point,
|
||||||
|
)
|
||||||
|
self.play(self.teacher.look_at, point)
|
||||||
|
self.wait(5)
|
||||||
|
|
||||||
unit_intensity = 0.6
|
class ManipulateLightsourceSetups(PiCreatureScene):
|
||||||
|
CONFIG = {
|
||||||
indicator1 = LightIndicator(show_reading = False, color = LIGHT_COLOR)
|
"num_levels" : 100,
|
||||||
indicator1.set_intensity(unit_intensity)
|
"radius" : 10,
|
||||||
reading1 = TexMobject("1")
|
}
|
||||||
reading1.move_to(indicator1)
|
|
||||||
|
|
||||||
|
|
||||||
indicator2 = LightIndicator(show_reading = False, color = LIGHT_COLOR)
|
|
||||||
indicator2.shift(2*RIGHT)
|
|
||||||
indicator2.set_intensity(unit_intensity/4)
|
|
||||||
reading2 = TexMobject("{1\over 4}").scale(0.8)
|
|
||||||
reading2.move_to(indicator2)
|
|
||||||
|
|
||||||
indicator3 = LightIndicator(show_reading = False, color = LIGHT_COLOR)
|
|
||||||
indicator3.shift(4*RIGHT)
|
|
||||||
indicator3.set_intensity(unit_intensity/9)
|
|
||||||
reading3 = TexMobject("{1\over 9}").scale(0.8)
|
|
||||||
reading3.move_to(indicator3)
|
|
||||||
|
|
||||||
|
|
||||||
self.play(FadeIn(indicator1))
|
|
||||||
self.play(FadeIn(reading1))
|
|
||||||
self.wait()
|
|
||||||
self.play(FadeOut(reading1))
|
|
||||||
self.play(Transform(indicator1, indicator2))
|
|
||||||
self.play(FadeIn(reading2))
|
|
||||||
self.wait()
|
|
||||||
self.play(FadeOut(reading2))
|
|
||||||
self.play(Transform(indicator1, indicator3))
|
|
||||||
self.play(FadeIn(reading3))
|
|
||||||
self.wait()
|
|
||||||
|
|
||||||
class BackToEulerSumScene(PiCreatureScene):
|
|
||||||
|
|
||||||
|
|
||||||
def construct(self):
|
def construct(self):
|
||||||
self.remove(self.get_primary_pi_creature())
|
unit_distance = 3
|
||||||
|
|
||||||
NUM_CONES = 7
|
# Morty
|
||||||
NUM_VISIBLE_CONES = 6
|
morty = self.pi_creature
|
||||||
INDICATOR_RADIUS = 0.5
|
morty.flip()
|
||||||
OPACITY_FOR_UNIT_INTENSITY = 1.0
|
morty.scale(0.5)
|
||||||
|
morty.move_to(2*LEFT + SPACE_HEIGHT*DOWN/2)
|
||||||
|
observer_point = morty.eyes[1].get_center()
|
||||||
|
|
||||||
self.number_line = NumberLine(
|
bubble = ThoughtBubble(height = 3, width = 4, direction = RIGHT)
|
||||||
x_min = 0,
|
bubble.set_fill(BLACK, 1)
|
||||||
color = WHITE,
|
bubble.pin_to(morty)
|
||||||
number_at_center = 1.6,
|
|
||||||
stroke_width = 1,
|
# Indicator
|
||||||
numbers_with_elongated_ticks = range(1,5),
|
light_indicator = LightIndicator(
|
||||||
numbers_to_show = range(1,5),
|
opacity_for_unit_intensity = 0.5,
|
||||||
unit_size = 2,
|
fill_color = YELLOW,
|
||||||
tick_frequency = 0.2,
|
radius = 0.4,
|
||||||
line_to_number_buff = LARGE_BUFF,
|
reading_height = 0.2,
|
||||||
label_direction = UP,
|
|
||||||
)
|
)
|
||||||
|
light_indicator.move_to(bubble.get_bubble_center())
|
||||||
|
def update_light_indicator(light_indicator):
|
||||||
|
distance = np.linalg.norm(light_source.get_source_point()-observer_point)
|
||||||
|
light_indicator.set_intensity((unit_distance/distance)**2)
|
||||||
|
|
||||||
self.number_line.label_direction = DOWN
|
#Light source
|
||||||
#self.number_line.shift(3*UP)
|
light_source = LightSource(
|
||||||
|
opacity_function = inverse_quadratic(1,2,1),
|
||||||
|
num_levels = self.num_levels,
|
||||||
|
radius = self.radius,
|
||||||
|
max_opacity_ambient = AMBIENT_FULL,
|
||||||
|
)
|
||||||
|
light_source.move_to(observer_point + unit_distance*RIGHT)
|
||||||
|
|
||||||
self.number_line_labels = self.number_line.get_number_mobjects()
|
#Light source copies
|
||||||
self.add(self.number_line,self.number_line_labels)
|
light_source_copies = VGroup(*[light_source.copy() for x in range(2)])
|
||||||
|
for lsc, vect in zip(light_source_copies, [RIGHT, UP]):
|
||||||
|
lsc.move_to(observer_point + np.sqrt(2)*unit_distance*vect)
|
||||||
|
|
||||||
|
self.add(light_source)
|
||||||
|
self.add_foreground_mobjects(morty, bubble, light_indicator)
|
||||||
|
self.add(ContinualUpdateFromFunc(light_indicator, update_light_indicator))
|
||||||
|
self.play(
|
||||||
|
ApplyMethod(
|
||||||
|
light_source.shift, 0.66*unit_distance*LEFT,
|
||||||
|
rate_func = wiggle,
|
||||||
|
run_time = 5,
|
||||||
|
),
|
||||||
|
morty.change, "erm",
|
||||||
|
)
|
||||||
|
self.play(
|
||||||
|
UpdateFromAlphaFunc(
|
||||||
|
light_source,
|
||||||
|
lambda ls, a : ls.move_to(
|
||||||
|
observer_point + rotate_vector(
|
||||||
|
unit_distance*RIGHT, (1+1./8)*a*TAU
|
||||||
|
)
|
||||||
|
),
|
||||||
|
run_time = 6,
|
||||||
|
rate_func = bezier([0, 0, 1, 1])
|
||||||
|
),
|
||||||
|
morty.change, "pondering",
|
||||||
|
UpdateFromFunc(morty, lambda m : m.look_at(light_source))
|
||||||
|
)
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
origin_point = self.number_line.number_to_point(0)
|
plus = TexMobject("+")
|
||||||
|
point = light_indicator.get_center()
|
||||||
self.default_pi_creature_class = Randolph
|
plus.move_to(point)
|
||||||
randy = self.get_primary_pi_creature()
|
light_indicator_copy = light_indicator.copy()
|
||||||
|
self.add_foreground_mobjects(plus, light_indicator_copy)
|
||||||
randy.scale(0.5)
|
|
||||||
randy.flip()
|
|
||||||
right_pupil = randy.pupils[1]
|
|
||||||
randy.next_to(origin_point, LEFT, buff = 0, submobject_to_align = right_pupil)
|
|
||||||
|
|
||||||
randy_copy = randy.copy()
|
|
||||||
randy_copy.target = randy.copy().shift(DOWN)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bubble = ThoughtBubble(direction = RIGHT,
|
|
||||||
width = 4, height = 3,
|
|
||||||
file_name = "Bubbles_thought.svg")
|
|
||||||
bubble.next_to(randy,LEFT+UP)
|
|
||||||
bubble.set_fill(color = BLACK, opacity = 1)
|
|
||||||
|
|
||||||
self.play(
|
self.play(
|
||||||
randy.change, "wave_2",
|
ReplacementTransform(
|
||||||
ShowCreation(bubble),
|
light_source, light_source_copies[0]
|
||||||
|
),
|
||||||
|
ReplacementTransform(
|
||||||
|
light_source.copy().fade(1),
|
||||||
|
light_source_copies[1]
|
||||||
|
),
|
||||||
|
FadeIn(plus),
|
||||||
|
UpdateFromFunc(
|
||||||
|
light_indicator_copy,
|
||||||
|
lambda li : update_light_indicator(li),
|
||||||
|
),
|
||||||
|
UpdateFromAlphaFunc(
|
||||||
|
light_indicator, lambda m, a : m.move_to(
|
||||||
|
point + a*0.75*RIGHT,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
UpdateFromAlphaFunc(
|
||||||
|
light_indicator_copy, lambda m, a : m.move_to(
|
||||||
|
point + a*0.75*LEFT,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
run_time = 2
|
||||||
)
|
)
|
||||||
|
self.play(morty.change, "hooray")
|
||||||
|
self.wait(2)
|
||||||
euler_sum = TexMobject("1", "+", "{1\over 4}",
|
|
||||||
"+", "{1\over 9}", "+", "{1\over 16}", "+", "{1\over 25}", "+", "\cdots", " ")
|
|
||||||
# the last entry is a dummy element which makes looping easier
|
|
||||||
# used just for putting the fractions into the light indicators
|
|
||||||
|
|
||||||
intensities = np.array([1./(n+1)**2 for n in range(NUM_CONES)])
|
|
||||||
opacities = intensities * OPACITY_FOR_UNIT_INTENSITY
|
|
||||||
|
|
||||||
# repeat:
|
|
||||||
|
|
||||||
# fade in lighthouse
|
|
||||||
# switch on / fade in ambient light
|
|
||||||
# show creation / write light indicator
|
|
||||||
# move indicator onto origin
|
|
||||||
# while morphing and dimming
|
|
||||||
# move indicator into thought bubble
|
|
||||||
# while indicators already inside shift to the back
|
|
||||||
# and while term appears in the series below
|
|
||||||
|
|
||||||
point = self.number_line.number_to_point(1)
|
|
||||||
v = point - self.number_line.number_to_point(0)
|
|
||||||
light_source = LightSource()
|
|
||||||
light_source.move_source_to(point)
|
|
||||||
#light_source.ambient_light.move_source_to(point)
|
|
||||||
#light_source.lighthouse.move_to(point)
|
|
||||||
|
|
||||||
self.play(FadeIn(light_source.lighthouse))
|
|
||||||
self.play(SwitchOn(light_source.ambient_light))
|
|
||||||
|
|
||||||
|
|
||||||
# create an indicator that will move along the number line
|
|
||||||
indicator = LightIndicator(color = LIGHT_COLOR,
|
|
||||||
radius = INDICATOR_RADIUS,
|
|
||||||
opacity_for_unit_intensity = OPACITY_FOR_UNIT_INTENSITY,
|
|
||||||
show_reading = False
|
|
||||||
)
|
|
||||||
indicator_reading = euler_sum[0]
|
|
||||||
indicator_reading.scale_to_fit_height(0.5 * indicator.get_height())
|
|
||||||
indicator_reading.move_to(indicator.get_center())
|
|
||||||
indicator.add(indicator_reading)
|
|
||||||
indicator.tex_reading = indicator_reading
|
|
||||||
# the TeX reading is too bright at full intensity
|
|
||||||
indicator.tex_reading.set_fill(color = BLACK)
|
|
||||||
indicator.foreground.set_fill(None,opacities[0])
|
|
||||||
|
|
||||||
|
|
||||||
indicator.move_to(point)
|
|
||||||
indicator.set_intensity(intensities[0])
|
|
||||||
|
|
||||||
self.play(FadeIn(indicator))
|
|
||||||
self.add_foreground_mobject(indicator)
|
|
||||||
|
|
||||||
collection_point = np.array([-6.,2.,0.])
|
|
||||||
left_shift = 0.2*LEFT
|
|
||||||
collected_indicators = Mobject()
|
|
||||||
|
|
||||||
|
|
||||||
for i in range(2, NUM_VISIBLE_CONES + 1):
|
|
||||||
|
|
||||||
previous_point = self.number_line.number_to_point(i - 1)
|
|
||||||
point = self.number_line.number_to_point(i)
|
|
||||||
|
|
||||||
|
|
||||||
v = point - previous_point
|
|
||||||
#print v
|
|
||||||
# Create and position the target indicator (next on number line).
|
|
||||||
indicator_target = indicator.deepcopy()
|
|
||||||
indicator_target.shift(v)
|
|
||||||
|
|
||||||
|
|
||||||
# Here we make a copy that will move into the thought bubble.
|
|
||||||
bubble_indicator = indicator.deepcopy()
|
|
||||||
# And its target
|
|
||||||
bubble_indicator_target = bubble_indicator.deepcopy()
|
|
||||||
bubble_indicator_target.set_intensity(intensities[i - 2])
|
|
||||||
|
|
||||||
# give the target the appropriate reading
|
|
||||||
euler_sum[2*i-4].move_to(bubble_indicator_target)
|
|
||||||
bubble_indicator_target.remove(bubble_indicator_target.tex_reading)
|
|
||||||
bubble_indicator_target.tex_reading = euler_sum[2*i-4].copy()
|
|
||||||
bubble_indicator_target.add(bubble_indicator_target.tex_reading)
|
|
||||||
# center it in the indicator
|
|
||||||
|
|
||||||
if bubble_indicator_target.tex_reading.get_tex_string() != "1":
|
|
||||||
bubble_indicator_target.tex_reading.scale_to_fit_height(0.8*indicator.get_height())
|
|
||||||
# the target is less bright, possibly switch to a white text color
|
|
||||||
if bubble_indicator_target.intensity < 0.7:
|
|
||||||
bubble_indicator.tex_reading.set_fill(color = WHITE)
|
|
||||||
|
|
||||||
# position the target in the thought bubble
|
|
||||||
bubble_indicator_target.move_to(collection_point)
|
|
||||||
|
|
||||||
|
|
||||||
self.add_foreground_mobject(bubble_indicator)
|
|
||||||
|
|
||||||
|
|
||||||
self.wait()
|
|
||||||
|
|
||||||
self.play(
|
|
||||||
Transform(bubble_indicator,bubble_indicator_target),
|
|
||||||
collected_indicators.shift,left_shift,
|
|
||||||
)
|
|
||||||
|
|
||||||
collected_indicators.add(bubble_indicator)
|
|
||||||
|
|
||||||
new_light = light_source.deepcopy()
|
|
||||||
w = new_light.get_source_point()
|
|
||||||
new_light.move_source_to(w + (i-2)*v)
|
|
||||||
w2 = new_light.get_source_point()
|
|
||||||
|
|
||||||
self.add(new_light.lighthouse)
|
|
||||||
self.play(
|
|
||||||
Transform(indicator,indicator_target),
|
|
||||||
new_light.lighthouse.shift,v,
|
|
||||||
)
|
|
||||||
new_light.move_source_to(w + (i-1)*v)
|
|
||||||
new_light.lighthouse.move_to(w + (i-1)*v)
|
|
||||||
|
|
||||||
self.play(SwitchOn(new_light.ambient_light),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# quickly switch on off-screen light cones
|
|
||||||
for i in range(NUM_VISIBLE_CONES,NUM_CONES):
|
|
||||||
indicator_start_time = 0.5 * (i+1) * FAST_SWITCH_ON_RUN_TIME/light_source.ambient_light.radius * self.number_line.unit_size
|
|
||||||
indicator_stop_time = indicator_start_time + FAST_INDICATOR_UPDATE_TIME
|
|
||||||
indicator_rate_func = squish_rate_func(#smooth, 0.8, 0.9)
|
|
||||||
smooth,indicator_start_time,indicator_stop_time)
|
|
||||||
ls = LightSource()
|
|
||||||
point = point = self.number_line.number_to_point(i)
|
|
||||||
ls.move_source_to(point)
|
|
||||||
self.play(
|
|
||||||
SwitchOn(ls.ambient_light, run_time = FAST_SWITCH_ON_RUN_TIME),
|
|
||||||
)
|
|
||||||
|
|
||||||
# and morph indicator stack into limit value
|
|
||||||
|
|
||||||
sum_indicator = LightIndicator(color = LIGHT_COLOR,
|
|
||||||
radius = INDICATOR_RADIUS,
|
|
||||||
opacity_for_unit_intensity = OPACITY_FOR_UNIT_INTENSITY,
|
|
||||||
show_reading = False
|
|
||||||
)
|
|
||||||
sum_indicator.set_intensity(intensities[0] * np.pi**2/6)
|
|
||||||
sum_indicator_reading = TexMobject("{\pi^2 \over 6}")
|
|
||||||
sum_indicator_reading.set_fill(color = BLACK)
|
|
||||||
sum_indicator_reading.scale_to_fit_height(0.8 * sum_indicator.get_height())
|
|
||||||
sum_indicator.add(sum_indicator_reading)
|
|
||||||
sum_indicator.move_to(collection_point)
|
|
||||||
|
|
||||||
self.play(
|
|
||||||
FadeOut(collected_indicators),
|
|
||||||
FadeIn(sum_indicator)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
self.wait()
|
|
||||||
|
|
||||||
class TwoLightSourcesScene(PiCreatureScene):
|
class TwoLightSourcesScene(PiCreatureScene):
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue