debugged existing scenes, working on BackToEulerSum

This commit is contained in:
Ben Hambrecht 2018-02-06 18:13:24 +01:00
parent fa481a1cb8
commit ad5ffc5fdc
2 changed files with 162 additions and 118 deletions

View file

@ -88,7 +88,7 @@ class LightIndicator(Mobject):
def generate_points(self): def generate_points(self):
self.background = Circle(color=BLACK, radius = self.radius) self.background = Circle(color=BLACK, radius = self.radius)
self.background.set_fill(opacity=1) self.background.set_fill(opacity=1.0)
self.foreground = Circle(color=self.color, radius = self.radius) self.foreground = Circle(color=self.color, radius = self.radius)
self.foreground.set_stroke(color=INDICATOR_STROKE_COLOR,width=INDICATOR_STROKE_WIDTH) self.foreground.set_stroke(color=INDICATOR_STROKE_COLOR,width=INDICATOR_STROKE_WIDTH)
@ -579,11 +579,9 @@ class SingleLighthouseScene(PiCreatureScene):
def construct(self): def construct(self):
self.force_skipping()
self.setup_elements() self.setup_elements()
self.setup_trackers() # spotlight and angle msmt change when screen rotates self.setup_angle() # spotlight and angle msmt change when screen rotates
self.rotate_screen() #self.rotate_screen()
self.revert_to_original_skipping_status()
self.morph_lighthouse_into_sun() self.morph_lighthouse_into_sun()
@ -613,61 +611,67 @@ class SingleLighthouseScene(PiCreatureScene):
morty = self.get_primary_pi_creature() morty = self.get_primary_pi_creature()
morty.scale(0.5) morty.scale(0.5)
morty.move_to(observer_point) morty.move_to(observer_point)
morty.shift(2*OUT)
self.add_foreground_mobject(morty)
self.add(self.light_source.lighthouse)
self.add(self.light_source.lighthouse,morty)
self.play( self.play(
SwitchOn(self.light_source.ambient_light) SwitchOn(self.light_source.ambient_light)
) )
# Screen # Screen
self.light_source.set_screen(Line([3,-1,0],[3,1,0])) self.screen = Rectangle(
self.light_source.spotlight.screen.rotate(-TAU/6) width = 0.1,
self.light_source.spotlight.screen.next_to(morty,LEFT) height = 2,
mark_paths_closed = True,
fill_color = WHITE,
fill_opacity = 1.0,
stroke_width = 0.0
)
self.screen.rotate(-TAU/6)
self.screen.next_to(morty,LEFT)
self.light_source.set_screen(self.screen)
# Animations # Animations
self.play(FadeIn(self.light_source.spotlight.screen)) self.play(FadeIn(self.screen))
self.light_source.set_max_opacity_spotlight(0.001)
self.add(self.light_source.spotlight)
updater = ScreenTracker(self.light_source)
self.add(updater)
self.wait() self.wait()
# just calling .dim_ambient via ApplyMethod does not work, why? # just calling .dim_ambient via ApplyMethod does not work, why?
dimmed_ambient_light = self.light_source.ambient_light.copy() dimmed_ambient_light = self.light_source.ambient_light.deepcopy()
dimmed_ambient_light.dimming(AMBIENT_DIMMED) dimmed_ambient_light.dimming(AMBIENT_DIMMED)
self.play( self.play(
Transform(self.light_source.ambient_light,dimmed_ambient_light), Transform(self.light_source.ambient_light,dimmed_ambient_light),
FadeIn(self.light_source.spotlight) self.light_source.set_max_opacity_spotlight,1.0,
FadeIn(self.light_source.shadow)
) )
self.add(self.light_source.spotlight.shadow)
self.add_foreground_mobject(morty) self.add_foreground_mobject(morty)
def setup_trackers(self): def setup_angle(self):
self.wait() self.wait()
# Make spotlight follow the screen
#self.screen_tracker = MovingScreenTracker(self.screen, light_source = self.light_source)
#self.source_tracker = MovingSourceTracker(self.light_source)
#self.add(self.screen_tracker, self.source_tracker)
self.screen_tracker = ScreenTracker(self.light_source.spotlight)
self.add(self.screen_tracker)
pointing_screen_at_source = Rotate(self.light_source.spotlight.screen,TAU/6) pointing_screen_at_source = Rotate(self.screen,TAU/6)
self.play(pointing_screen_at_source) self.play(pointing_screen_at_source)
self.play(self.light_source.move_source_to,ORIGIN)
#self.play(self.spotlight.move_to,ORIGIN)
# angle msmt (arc) # angle msmt (arc)
arc_angle = self.light_source.spotlight.opening_angle() arc_angle = self.light_source.spotlight.opening_angle()
@ -696,7 +700,7 @@ class SingleLighthouseScene(PiCreatureScene):
ShowCreation(self.angle_arc), ShowCreation(self.angle_arc),
ShowCreation(self.angle_indicator) ShowCreation(self.angle_indicator)
) )
#self.add_foreground_mobject(self.angle_indicator)
self.wait() self.wait()
def rotate_screen(self): def rotate_screen(self):
@ -723,7 +727,7 @@ class SingleLighthouseScene(PiCreatureScene):
sun_position = [-100,0,0] sun_position = ORIGIN #[-100,0,0]
self.play( self.play(
@ -731,32 +735,33 @@ class SingleLighthouseScene(PiCreatureScene):
FadeOut(self.angle_indicator) FadeOut(self.angle_indicator)
) )
self.sun = LightSource( self.sun = self.light_source.deepcopy()
opacity_function = inverse_quadratic(1,2,1),
num_levels = NUM_LEVELS,
radius = 150,
max_opacity_ambient = AMBIENT_FULL
)
#self.sun.ambient_light.opacity_function = inverse_quadratic(1,2,1)
#self.sun.num_levels = NUM_LEVELS,
self.sun.set_screen(self.light_source.spotlight.screen)
self.sun.spotlight.change_opacity_function(lambda r: 0.5)
#self.sun.set_radius(150) #self.sun.set_radius(150)
#self.sun.set_max_opacity_ambient(AMBIENT_FULL)
# self.sun.spotlight.change_opacity_function(lambda r: 0.5)
# self.sun.set_radius(150)
self.sun.move_source_to(sun_position) self.sun.move_source_to(sun_position)
self.sun.spotlight.recalculate_sectors() # self.sun.update()
# self.add(self.sun)
# temporarily remove the screen tracker while we move the source # temporarily remove the screen tracker while we move the source
self.remove(self.screen_tracker) #self.remove(self.screen_tracker)
print self.sun.spotlight.source_point
self.play( self.play(
ReplacementTransform(self.light_source.lighthouse, self.sun.lighthouse), self.light_source.spotlight.move_source_to,sun_position,
ReplacementTransform(self.light_source.ambient_light, self.sun.ambient_light),
ReplacementTransform(self.light_source.spotlight, self.sun.spotlight),
) )
self.add(ScreenTracker(self.sun.spotlight)) #self.add(ScreenTracker(self.sun))
self.wait() self.wait()
@ -835,11 +840,10 @@ class EarthScene(Scene):
# Add elements to scene # Add elements to scene
self.add(self.sun,self.screen) self.add(self.sun,self.screen)
self.bring_to_back(self.sun.spotlight.shadow) self.bring_to_back(self.sun.shadow)
screen_tracker = MovingScreenTracker(self.screen, light_source = self.sun) screen_tracker = ScreenTracker(self.sun)
sun_tracker = MovingSourceTracker(self.sun)
self.add(sun_tracker, screen_tracker) self.add(screen_tracker)
self.wait() self.wait()
@ -847,7 +851,7 @@ class EarthScene(Scene):
self.bring_to_back(earth) self.bring_to_back(earth)
# move screen onto Earth # move screen onto Earth
screen_on_earth = self.screen.copy() screen_on_earth = self.screen.deepcopy()
screen_on_earth.rotate(-theta) screen_on_earth.rotate(-theta)
screen_on_earth.scale(0.3) screen_on_earth.scale(0.3)
screen_on_earth.move_to(np.array([ screen_on_earth.move_to(np.array([
@ -937,8 +941,9 @@ class ScreenShapingScene(ThreeDScene):
opacity_function = inverse_quadratic(1,5,1), opacity_function = inverse_quadratic(1,5,1),
num_levels = NUM_LEVELS, num_levels = NUM_LEVELS,
radius = 10, radius = 10,
screen = self.screen #screen = self.screen
) )
self.light_source.set_screen(self.screen)
self.light_source.move_source_to([-5,0,0]) self.light_source.move_source_to([-5,0,0])
# abbreviations # abbreviations
@ -946,9 +951,11 @@ class ScreenShapingScene(ThreeDScene):
self.spotlight = self.light_source.spotlight self.spotlight = self.light_source.spotlight
self.lighthouse = self.light_source.lighthouse self.lighthouse = self.light_source.lighthouse
screen_tracker = ScreenTracker(self.spotlight) screen_tracker = ScreenTracker(self.light_source)
self.add(screen_tracker) self.add(screen_tracker)
self.add_foreground_mobject(self.light_source.shadow)
# Morty # Morty
self.morty = Mortimer().scale(0.3).next_to(self.screen, RIGHT, buff = 0.5) self.morty = Mortimer().scale(0.3).next_to(self.screen, RIGHT, buff = 0.5)
@ -960,11 +967,15 @@ class ScreenShapingScene(ThreeDScene):
self.play(FadeIn(self.screen)) self.play(FadeIn(self.screen))
self.wait() self.wait()
self.add_foreground_mobject(self.screen)
dimmed_ambient_light = self.ambient_light.copy() dimmed_ambient_light = self.ambient_light.copy()
dimmed_ambient_light.dimming(AMBIENT_DIMMED) dimmed_ambient_light.dimming(AMBIENT_DIMMED)
self.light_source.set_max_opacity_spotlight(0.001)
self.play( self.play(
FadeIn(self.spotlight), # this hides Morty for a moment, why? self.light_source.set_max_opacity_spotlight,1.0, # this hides Morty for a moment, why?
FadeIn(self.light_source.shadow),
Transform(self.ambient_light,dimmed_ambient_light) Transform(self.ambient_light,dimmed_ambient_light)
) )
@ -1002,7 +1013,7 @@ class ScreenShapingScene(ThreeDScene):
ReplacementTransform(brightness_rect0,self.brightness_rect) ReplacementTransform(brightness_rect0,self.brightness_rect)
) )
self.unslanted_screen = self.screen.copy() self.unslanted_screen = self.screen.deepcopy()
self.unslanted_brightness_rect = self.brightness_rect.copy() self.unslanted_brightness_rect = self.brightness_rect.copy()
# for unslanting the screen later # for unslanting the screen later
@ -1149,15 +1160,17 @@ class ScreenShapingScene(ThreeDScene):
def morph_into_3d(self): def morph_into_3d(self):
axes = ThreeDAxes() #axes = ThreeDAxes()
self.add(axes) #self.add(axes)
phi0 = self.camera.get_phi() # default is 0 degs phi0 = self.camera.get_phi() # default is 0 degs
theta0 = self.camera.get_theta() # default is -90 degs theta0 = self.camera.get_theta() # default is -90 degs
distance0 = self.camera.get_distance() distance0 = self.camera.get_distance()
self.play(FadeOut(self.ambient_light)) # this is an ugly hack bc remove, FadeOut and SwitchOff don't work
self.play(
self.light_source.set_max_opacity_ambient,0.001
)
phi1 = 60 * DEGREES # angle from zenith (0 to 180) phi1 = 60 * DEGREES # angle from zenith (0 to 180)
theta1 = -135 * DEGREES # azimuth (0 to 360) theta1 = -135 * DEGREES # azimuth (0 to 360)
@ -1169,15 +1182,23 @@ class ScreenShapingScene(ThreeDScene):
print "moving camera from (", phi0/DEGREES, ", ", theta0/DEGREES, ") to (", phi1/DEGREES, ", ", theta1/DEGREES, ")" print "moving camera from (", phi0/DEGREES, ", ", theta0/DEGREES, ") to (", phi1/DEGREES, ", ", theta1/DEGREES, ")"
# camera_tracker = MovingCameraTracker(self.camera.rotation_mobject,
# light_source = self.spotlight.source_point,
# screen = self.screen)
camera_target_point = target_point # self.camera.get_spherical_coords(45 * DEGREES, -60 * DEGREES) camera_target_point = target_point # self.camera.get_spherical_coords(45 * DEGREES, -60 * DEGREES)
projection_direction = self.camera.spherical_coords_to_point(phi1,theta1, 1) projection_direction = self.camera.spherical_coords_to_point(phi1,theta1, 1)
new_screen0 = Rectangle(height = self.screen_height,
width = 0.5, stroke_color = RED)
new_screen0.rotate(TAU/4,axis = DOWN)
new_screen0.move_to(self.screen.get_center())
self.add(new_screen0)
self.remove(self.screen)
self.light_source.set_screen(new_screen0)
# # new_screen = new_screen0.deepcopy()
# # new_screen.width = new_screen.height
self.play( self.play(
ApplyMethod(self.camera.rotation_mobject.move_to, camera_target_point) ApplyMethod(self.camera.rotation_mobject.move_to, camera_target_point),
# #Transform(new_screen0,new_screen)
) )
self.wait() self.wait()
@ -1236,13 +1257,13 @@ class BackToEulerSumScene(PiCreatureScene):
bubble = ThoughtBubble(direction = RIGHT, bubble = ThoughtBubble(direction = RIGHT,
width = 4, height = 3, width = 4, height = 3,
file_name = "Bubbles_thought.svg") file_name = "Bubbles_thought.svg")
bubble.next_to(randy,DOWN+LEFT) bubble.next_to(randy,LEFT)
bubble.set_fill(color = BLACK, opacity = 1) bubble.set_fill(color = BLACK, opacity = 1)
# self.play( self.play(
# randy.change, "wave_2", randy.change, "wave_2",
# ShowCreation(bubble), ShowCreation(bubble),
# ) )
euler_sum = TexMobject("1", "+", "{1\over 4}", euler_sum = TexMobject("1", "+", "{1\over 4}",
@ -1274,32 +1295,74 @@ class BackToEulerSumScene(PiCreatureScene):
self.play(FadeIn(light_source.lighthouse)) self.play(FadeIn(light_source.lighthouse))
self.play(SwitchOn(light_source.ambient_light)) self.play(SwitchOn(light_source.ambient_light))
# create an indicator and move a copy of it into the thought bubble
indicator = LightIndicator(color = LIGHT_COLOR,
radius = INDICATOR_RADIUS,
opacity_for_unit_intensity = 0.2, #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.foreground.set_fill(None,opacities[0])
indicator.move_to(point)
indicator.set_intensity(intensities[0])
self.play(FadeIn(indicator))
indicator_copy = indicator.deepcopy()
self.add(indicator_copy)
self.play(indicator_copy.move_to, bubble)
moving_light_source = light_source.deepcopy()
ls = []
ls.append(moving_light_source)
for i in range(2,NUM_VISIBLE_CONES + 1): 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) point = self.number_line.number_to_point(i)
moving_light_source = light_source.deepcopy() indicator_copy = indicator.deepcopy()
moving_light_source.set_max_opacity_ambient(0.0001) indicator_copy.move_to(previous_point)
self.add(moving_light_source.ambient_light) self.add(indicator_copy)
target_light_source = moving_light_source.deepcopy()
# # target_light_source.ambient_light.dimming(OPACITY_FOR_UNIT_INTENSITY)
# #target_light_source.move_to(point)
# target_light_source.move_source_to(point)
target_light_source.move_source_to(point)
target_light_source.set_max_opacity_ambient(0.5)
# target_light_source.lighthouse.move_to(point)
# target_light_source.set_max_opacity_ambient(1.0)
# #target_light_source.ambient_light.generate_points()
moving_light_source.ambient_light.target = target_light_source.ambient_light indicator_target = indicator.deepcopy()
indicator_target.move_to(point)
ls[-1].set_max_opacity_ambient(0.0001)
self.add(ls[-1].ambient_light)
ls.append(ls[-1].deepcopy())
ls[-1].move_source_to(point)
ls[-1].set_max_opacity_ambient(0.5)
bubble_indicator = indicator_copy.deepcopy()
bubble_indicator_target = bubble_indicator.deepcopy()
bubble_indicator_target.set_intensity(intensities[i-1])
bubble_indicator_target.reading = euler_sum[-2+2*i]
bubble_indicator_target.reading.scale_to_fit_height(0.8*indicator.get_height())
bubble_indicator_target.move_to(bubble)
self.add(bubble_indicator)
# #self.play(MoveToTarget(randy_copy))
self.play( self.play(
Transform(moving_light_source, target_light_source), Transform(bubble_indicator,bubble_indicator_target)
#MoveToTarget(moving_light_source.ambient_light),
) )
# light_source = moving_light_source self.play(
Transform(ls[-2], ls[-1]),
Transform(indicator_copy,indicator_target),
)
# switch on lights off-screen # switch on lights off-screen
@ -1312,19 +1375,6 @@ class BackToEulerSumScene(PiCreatureScene):
# for i in range(1,NUM_CONES+1):
# lighthouse = Lighthouse()
# point = self.number_line.number_to_point(i)
# ambient_light = AmbientLight(
# opacity_function = inverse_quadratic(1,2,1),
# num_levels = NUM_LEVELS,
# radius = 12.0)
# ambient_light.move_source_to(point)
# lighthouse.next_to(point,DOWN,0)
# lighthouses.append(lighthouse)
# ambient_lights.append(ambient_light)
# lighthouse_pos.append(point)
# for i in range(1,NUM_VISIBLE_CONES+1): # for i in range(1,NUM_VISIBLE_CONES+1):

View file

@ -19,9 +19,9 @@ from topics.three_dimensions import *
from scipy.spatial import ConvexHull from scipy.spatial import ConvexHull
import traceback
LIGHT_COLOR = YELLOW LIGHT_COLOR = YELLOW
SHADOW_COLOR = BLACK
SWITCH_ON_RUN_TIME = 1.5 SWITCH_ON_RUN_TIME = 1.5
FAST_SWITCH_ON_RUN_TIME = 0.1 FAST_SWITCH_ON_RUN_TIME = 0.1
NUM_LEVELS = 30 NUM_LEVELS = 30
@ -62,7 +62,6 @@ class LightSource(VMobject):
} }
def generate_points(self): def generate_points(self):
print "LightSource.generate_points"
self.lighthouse = Lighthouse() self.lighthouse = Lighthouse()
self.ambient_light = AmbientLight( self.ambient_light = AmbientLight(
source_point = self.source_point, source_point = self.source_point,
@ -85,7 +84,7 @@ class LightSource(VMobject):
else: else:
self.spotlight = Spotlight() self.spotlight = Spotlight()
self.shadow = VMobject(fill_color = "BLACK", fill_opacity = 1.0, stroke_color = BLACK) self.shadow = VMobject(fill_color = SHADOW_COLOR, fill_opacity = 1.0, stroke_color = BLACK)
self.lighthouse.next_to(self.source_point,DOWN,buff = 0) self.lighthouse.next_to(self.source_point,DOWN,buff = 0)
self.ambient_light.move_source_to(self.source_point) self.ambient_light.move_source_to(self.source_point)
@ -134,15 +133,15 @@ class LightSource(VMobject):
def move_source_to(self,point): def move_source_to(self,point):
print "LightSource.move_source_to"
apoint = np.array(point) apoint = np.array(point)
v = apoint - self.source_point v = apoint - self.source_point
self.source_point = apoint self.source_point = apoint
self.lighthouse.next_to(apoint,DOWN,buff = 0) self.lighthouse.next_to(apoint,DOWN,buff = 0)
self.ambient_light.move_source_to(apoint) self.ambient_light.move_source_to(apoint)
#if self.has_screen(): if self.has_screen():
# self.spotlight.move_source_to(apoint) self.spotlight.move_source_to(apoint)
#self.update() self.update()
return self return self
@ -157,13 +156,12 @@ class LightSource(VMobject):
self.spotlight.radius = new_radius self.spotlight.radius = new_radius
def update(self): def update(self):
print "LightSource.update"
self.spotlight.update_sectors() self.spotlight.update_sectors()
self.update_shadow() self.update_shadow()
def update_shadow(self): def update_shadow(self):
point = self.source_point point = self.source_point
projected_screen_points = [] projected_screen_points = []
if not self.has_screen(): if not self.has_screen():
@ -171,6 +169,10 @@ class LightSource(VMobject):
for point in self.screen.get_anchors(): for point in self.screen.get_anchors():
projected_screen_points.append(self.spotlight.project(point)) projected_screen_points.append(self.spotlight.project(point))
print "projected", self.screen.get_anchors(), "onto", projected_screen_points
projected_source = project_along_vector(self.source_point,self.spotlight.projection_direction()) projected_source = project_along_vector(self.source_point,self.spotlight.projection_direction())
projected_point_cloud_3d = np.append(projected_screen_points, projected_point_cloud_3d = np.append(projected_screen_points,
@ -221,8 +223,8 @@ class LightSource(VMobject):
new_anchors = np.append(new_anchors,anchors[index:],axis = 0) new_anchors = np.append(new_anchors,anchors[index:],axis = 0)
self.shadow.set_points_as_corners(new_anchors) self.shadow.set_points_as_corners(new_anchors)
# shift it one unit closer to the camera so it is in front of the spotlight # shift it closer to the camera so it is in front of the spotlight
#self.shadow.shift(-500*self.projection_direction()) self.shadow.shift(1e-5*self.spotlight.projection_direction())
self.shadow.mark_paths_closed = True self.shadow.mark_paths_closed = True
@ -287,7 +289,6 @@ class AmbientLight(VMobject):
} }
def generate_points(self): def generate_points(self):
print "AmbientLight.generate_points"
self.source_point = np.array(self.source_point) self.source_point = np.array(self.source_point)
# in theory, this method is only called once, right? # in theory, this method is only called once, right?
@ -313,13 +314,7 @@ class AmbientLight(VMobject):
def move_source_to(self,point): def move_source_to(self,point):
for line in traceback.format_stack():
print line.strip()
print "AmbientLight.move_source_to blablub"
v = np.array(point) - self.source_point v = np.array(point) - self.source_point
print "test"
self.source_point = np.array(point) self.source_point = np.array(point)
self.shift(v) self.shift(v)
return self return self
@ -379,8 +374,6 @@ class Spotlight(VMobject):
new_sector = self.new_sector(r,dr,lower_angle,upper_angle) new_sector = self.new_sector(r,dr,lower_angle,upper_angle)
self.add(new_sector) self.add(new_sector)
#self.update_shadow(point = self.source_point)
#self.add_to_back(self.shadow)
def new_sector(self,r,dr,lower_angle,upper_angle): def new_sector(self,r,dr,lower_angle,upper_angle):
@ -426,6 +419,7 @@ class Spotlight(VMobject):
viewing_angles = np.array(map(self.viewing_angle_of_point, viewing_angles = np.array(map(self.viewing_angle_of_point,
projected_screen_points)) projected_screen_points))
lower_angle = upper_angle = 0 lower_angle = upper_angle = 0
if len(viewing_angles) != 0: if len(viewing_angles) != 0:
lower_angle = np.min(viewing_angles) lower_angle = np.min(viewing_angles)