diff --git a/active_projects/basel.py b/active_projects/basel.py index 2e468e50..b46ed878 100644 --- a/active_projects/basel.py +++ b/active_projects/basel.py @@ -197,16 +197,13 @@ class ScaleLightSources(Transform): new_sp.scale(factor,about_point = about_point) submob.move_source_to(new_sp.get_location()) - #ambient_of = copy_func(submob.ambient_light.opacity_function) - #new_of = lambda r: ambient_of(r/factor) - #submob.ambient_light.opacity_function = new_of + ambient_of = copy_func(submob.ambient_light.opacity_function) + new_of = lambda r: ambient_of(r/factor) + submob.ambient_light.opacity_function = new_of - #spotlight_of = copy_func(submob.ambient_light.opacity_function) - #new_of = lambda r: spotlight_of(r/factor) - #submob.spotlight.change_opacity_function(new_of) - - new_r = factor * submob.radius - submob.set_radius(new_r) + spotlight_of = copy_func(submob.ambient_light.opacity_function) + new_of = lambda r: spotlight_of(r/factor) + submob.spotlight.change_opacity_function(new_of) new_r = factor * submob.ambient_light.radius submob.ambient_light.radius = new_r @@ -1004,7 +1001,6 @@ class ScreenShapingScene(ThreeDScene): def construct(self): - #self.force_skipping() self.setup_elements() self.deform_screen() self.create_brightness_rect() @@ -1014,10 +1010,8 @@ class ScreenShapingScene(ThreeDScene): self.add_distance_arrow() self.right_shift_screen_while_showing_light_indicator_and_distance_arrow() self.left_shift_again() - #self.revert_to_original_skipping_status() self.morph_into_3d() - self.prove_inverse_square_law() def setup_elements(self): @@ -1033,14 +1027,11 @@ class ScreenShapingScene(ThreeDScene): # light source self.light_source = LightSource( - opacity_function = inverse_quadratic(1,5,1), + opacity_function = inverse_quadratic(1,2,1), num_levels = NUM_LEVELS, radius = 10, - max_opacity = 0.2 #screen = self.screen ) - self.light_source.set_max_opacity_spotlight(0.2) - self.light_source.set_screen(self.screen) self.light_source.move_source_to([-5,0,0]) @@ -1257,9 +1248,6 @@ class ScreenShapingScene(ThreeDScene): def morph_into_3d(self): - - self.play(FadeOut(self.morty)) - axes = ThreeDAxes() self.add(axes) @@ -1267,6 +1255,11 @@ class ScreenShapingScene(ThreeDScene): theta0 = self.camera.get_theta() # default is -90 degs distance0 = self.camera.get_distance() + # 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) theta1 = -135 * DEGREES # azimuth (0 to 360) distance1 = distance0 @@ -1279,7 +1272,7 @@ class ScreenShapingScene(ThreeDScene): projection_direction = self.camera.spherical_coords_to_point(phi1,theta1, 1) new_screen0 = Rectangle(height = self.screen_height, - width = 0.1, stroke_color = RED, fill_color = RED, fill_opacity = 1) + width = 0.1, stroke_color = RED) new_screen0.rotate(TAU/4,axis = DOWN) new_screen0.move_to(self.screen.get_center()) self.add(new_screen0) @@ -1289,199 +1282,19 @@ class ScreenShapingScene(ThreeDScene): self.light_source.set_camera(self.camera) - new_screen = Rectangle(height = self.screen_height, - width = self.screen_height, stroke_color = RED, fill_color = RED, fill_opacity = 1) - new_screen.rotate(TAU/4,axis = DOWN) - new_screen.move_to(self.screen.get_center()) + new_screen = new_screen0.deepcopy() + new_screen.width = new_screen.height - self.add_foreground_mobject(self.ambient_light) - self.add_foreground_mobject(self.spotlight) - self.add_foreground_mobject(self.light_source.shadow) self.play( ApplyMethod(self.camera.rotation_mobject.move_to, camera_target_point), ) - self.remove(self.spotlight) - self.play(Transform(new_screen0,new_screen)) + #self.play(Transform(new_screen0,new_screen)) self.wait() - self.unit_screen = new_screen0 # better name - - - - def prove_inverse_square_law(self): - - def orientate(mob): - mob.move_to(self.unit_screen) - mob.rotate(TAU/4, axis = LEFT) - mob.rotate(TAU/4, axis = OUT) - mob.rotate(TAU/2, axis = LEFT) - return mob - - unit_screen_copy = self.unit_screen.copy() - fourfold_screen = self.unit_screen.copy() - fourfold_screen.scale(2,about_point = self.light_source.get_source_point()) - - self.remove(self.spotlight) - - - reading1 = TexMobject("1") - orientate(reading1) - - self.play(FadeIn(reading1)) - self.wait() - self.play(FadeOut(reading1)) - - - self.play( - Transform(self.unit_screen, fourfold_screen) - ) - - reading21 = TexMobject("{1\over 4}").scale(0.8) - orientate(reading21) - reading22 = reading21.deepcopy() - reading23 = reading21.deepcopy() - reading24 = reading21.deepcopy() - reading21.shift(0.5*OUT + 0.5*UP) - reading22.shift(0.5*OUT + 0.5*DOWN) - reading23.shift(0.5*IN + 0.5*UP) - reading24.shift(0.5*IN + 0.5*DOWN) - - - corners = fourfold_screen.get_anchors() - midpoint1 = (corners[0] + corners[1])/2 - midpoint2 = (corners[1] + corners[2])/2 - midpoint3 = (corners[2] + corners[3])/2 - midpoint4 = (corners[3] + corners[0])/2 - midline1 = Line(midpoint1, midpoint3) - midline2 = Line(midpoint2, midpoint4) - - self.play( - ShowCreation(midline1), - ShowCreation(midline2) - ) - - self.play( - FadeIn(reading21), - FadeIn(reading22), - FadeIn(reading23), - FadeIn(reading24), - ) - - self.wait() - - self.play( - FadeOut(reading21), - FadeOut(reading22), - FadeOut(reading23), - FadeOut(reading24), - FadeOut(midline1), - FadeOut(midline2) - ) - - ninefold_screen = unit_screen_copy.copy() - ninefold_screen.scale(3,about_point = self.light_source.get_source_point()) - - self.play( - Transform(self.unit_screen, ninefold_screen) - ) - - reading31 = TexMobject("{1\over 9}").scale(0.8) - orientate(reading31) - reading32 = reading31.deepcopy() - reading33 = reading31.deepcopy() - reading34 = reading31.deepcopy() - reading35 = reading31.deepcopy() - reading36 = reading31.deepcopy() - reading37 = reading31.deepcopy() - reading38 = reading31.deepcopy() - reading39 = reading31.deepcopy() - reading31.shift(IN + UP) - reading32.shift(IN) - reading33.shift(IN + DOWN) - reading34.shift(UP) - reading35.shift(ORIGIN) - reading36.shift(DOWN) - reading37.shift(OUT + UP) - reading38.shift(OUT) - reading39.shift(OUT + DOWN) - - corners = ninefold_screen.get_anchors() - midpoint11 = (2*corners[0] + corners[1])/3 - midpoint12 = (corners[0] + 2*corners[1])/3 - midpoint21 = (2*corners[1] + corners[2])/3 - midpoint22 = (corners[1] + 2*corners[2])/3 - midpoint31 = (2*corners[2] + corners[3])/3 - midpoint32 = (corners[2] + 2*corners[3])/3 - midpoint41 = (2*corners[3] + corners[0])/3 - midpoint42 = (corners[3] + 2*corners[0])/3 - midline11 = Line(midpoint11, midpoint32) - midline12 = Line(midpoint12, midpoint31) - midline21 = Line(midpoint21, midpoint42) - midline22 = Line(midpoint22, midpoint41) - - self.play( - ShowCreation(midline11), - ShowCreation(midline12), - ShowCreation(midline21), - ShowCreation(midline22), - ) - - self.play( - FadeIn(reading31), - FadeIn(reading32), - FadeIn(reading33), - FadeIn(reading34), - FadeIn(reading35), - FadeIn(reading36), - FadeIn(reading37), - FadeIn(reading38), - FadeIn(reading39), - ) - - - - -class IndicatorScalingScene(Scene): - - def construct(self): - - unit_intensity = 0.6 - - indicator1 = LightIndicator(show_reading = False, color = LIGHT_COLOR) - indicator1.set_intensity(unit_intensity) - 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() - @@ -2301,7 +2114,7 @@ class PondScene(Scene): return position - def split_light_source(i, step, show_steps = True, run_time = 1, ls_radius = 1): + 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) @@ -2333,28 +2146,17 @@ class PondScene(Scene): 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.all(np.abs(ls_old_loc) < 10) - onscreen_1 = np.all(np.abs(ls_new_loc1) < 10) - onscreen_2 = np.all(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) + 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), + ) def construction_step(n, scale_down = True, show_steps = True, run_time = 1, - simultaneous_splitting = False, ls_radius = 1): + simultaneous_splitting = False): # we assume that the scene contains: # an inner lake, self.inner_lake @@ -2415,12 +2217,7 @@ class PondScene(Scene): self.new_hypotenuses = [] for i in range(2**n): - split_light_source(i, - step = n, - show_steps = show_steps, - run_time = run_time, - ls_radius = ls_radius - ) + split_light_source(i, step = n, show_steps = show_steps, run_time = run_time) @@ -2482,12 +2279,6 @@ class PondScene(Scene): self.outer_lake.scale_about_point,0.5,OBSERVER_POINT, ) - # update the radii bc they haven't done so themselves - # bc reasons... - for ls in self.light_sources_array: - r = ls.radius - ls.set_radius(r*0.5) - else: # update the lake center and the radius self.lake_center = ls0_loc = self.outer_lake.get_center() + self.lake_radius * UP @@ -2528,12 +2319,8 @@ class PondScene(Scene): self.new_legs_2 = [] self.new_hypotenuses = [] - ls_radius = 25.0 - for i in range(3): - construction_step(i, scale_down = True, ls_radius = ls_radius/2**i) - - return + construction_step(i, scale_down = True) self.play( FadeOut(self.altitudes), @@ -2541,141 +2328,21 @@ class PondScene(Scene): FadeOut(self.legs) ) - for i in range(3,5): + for i in range(3,10): construction_step(i, scale_down = False, show_steps = False, run_time = 1.0/2**i, - simultaneous_splitting = True, ls_radius = ls_radius/2**3) - - - - - # Now create a straight number line and transform into it - MAX_N = 17 - - self.number_line = NumberLine( - x_min = -MAX_N, - x_max = MAX_N + 1, - color = WHITE, - number_at_center = 0, - stroke_width = LAKE_STROKE_WIDTH, - stroke_color = LAKE_STROKE_COLOR, - numbers_with_elongated_ticks = range(-MAX_N,MAX_N + 1), - numbers_to_show = range(-MAX_N,MAX_N + 1), - unit_size = LAKE0_RADIUS * TAU/4 / 4, - tick_frequency = 1, - line_to_number_buff = LARGE_BUFF, - label_direction = UP, - ).shift(2.5 * DOWN) - - self.number_line.label_direction = DOWN - - self.number_line_labels = self.number_line.get_number_mobjects() - self.wait() - - origin_point = self.number_line.number_to_point(0) - nl_sources = VMobject() - pond_sources = VMobject() - - for i in range(-MAX_N,MAX_N+1): - anchor = self.number_line.number_to_point(2*i + 1) - ls = self.light_sources_array[i].copy() - ls.move_source_to(anchor) - nl_sources.add(ls) - pond_sources.add(self.light_sources_array[i].copy()) - - self.add(pond_sources) - self.remove(self.light_sources) - - self.outer_lake.rotate(TAU/8) - - # open sea - open_sea = Rectangle( - width = 20, - height = 10, - stroke_width = LAKE_STROKE_WIDTH, - stroke_color = LAKE_STROKE_COLOR, - fill_color = LAKE_COLOR, - fill_opacity = LAKE_OPACITY, - ).flip().next_to(origin_point,UP,buff = 0) - - - - self.play( - Transform(pond_sources,nl_sources), - Transform(self.outer_lake,open_sea), - FadeOut(self.inner_lake) - ) - self.play(FadeIn(self.number_line)) - - - -class LabeledArc(Arc): - CONFIG = { - "length" : 1 - } - - def __init__(self, angle, **kwargs): - - BUFFER = 1.3 - - Arc.__init__(self,angle,**kwargs) - - label = DecimalNumber(self.length, num_decimal_points = 0) - r = BUFFER * self.radius - theta = self.start_angle + self.angle/2 - label_pos = r * np.array([np.cos(theta), np.sin(theta), 0]) - - label.move_to(label_pos) - self.add(label) - - - - -class ArcHighlightOverlayScene(Scene): - - def construct(self): - - BASELINE_YPOS = -2.5 - OBSERVER_POINT = [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 - - FLASH_TIME = 0.25 - - def flash_arcs(n): - - angle = TAU/2**n - arcs = [] - arcs.append(LabeledArc(angle/2, start_angle = -TAU/4, radius = LAKE0_RADIUS, length = 1)) - - for i in range(1,2**n): - arcs.append(LabeledArc(angle, start_angle = -TAU/4 + (i-0.5)*angle, radius = LAKE0_RADIUS, length = 2)) - - arcs.append(LabeledArc(angle/2, start_angle = -TAU/4 - angle/2, radius = LAKE0_RADIUS, length = 1)) - - self.play( - FadeIn(arcs[0], run_time = FLASH_TIME) - ) - - for i in range(1,2**n + 1): - self.play( - FadeOut(arcs[i-1], run_time = FLASH_TIME), - FadeIn(arcs[i], run_time = FLASH_TIME) - ) - - self.play( - FadeOut(arcs[2**n], run_time = FLASH_TIME), - ) - - - flash_arcs(3) + simultaneous_splitting = True) + + + + + + + + + + + +