mirror of
https://github.com/3b1b/manim.git
synced 2025-08-05 16:49:03 +00:00
debugged existing scenes, working on BackToEulerSum
This commit is contained in:
parent
fa481a1cb8
commit
ad5ffc5fdc
2 changed files with 162 additions and 118 deletions
|
@ -88,7 +88,7 @@ class LightIndicator(Mobject):
|
|||
|
||||
def generate_points(self):
|
||||
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.set_stroke(color=INDICATOR_STROKE_COLOR,width=INDICATOR_STROKE_WIDTH)
|
||||
|
||||
|
@ -579,11 +579,9 @@ class SingleLighthouseScene(PiCreatureScene):
|
|||
|
||||
def construct(self):
|
||||
|
||||
self.force_skipping()
|
||||
self.setup_elements()
|
||||
self.setup_trackers() # spotlight and angle msmt change when screen rotates
|
||||
self.rotate_screen()
|
||||
self.revert_to_original_skipping_status()
|
||||
self.setup_angle() # spotlight and angle msmt change when screen rotates
|
||||
#self.rotate_screen()
|
||||
self.morph_lighthouse_into_sun()
|
||||
|
||||
|
||||
|
@ -613,61 +611,67 @@ class SingleLighthouseScene(PiCreatureScene):
|
|||
morty = self.get_primary_pi_creature()
|
||||
morty.scale(0.5)
|
||||
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(
|
||||
SwitchOn(self.light_source.ambient_light)
|
||||
)
|
||||
|
||||
# Screen
|
||||
|
||||
self.light_source.set_screen(Line([3,-1,0],[3,1,0]))
|
||||
self.light_source.spotlight.screen.rotate(-TAU/6)
|
||||
self.light_source.spotlight.screen.next_to(morty,LEFT)
|
||||
self.screen = Rectangle(
|
||||
width = 0.1,
|
||||
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
|
||||
|
||||
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()
|
||||
|
||||
|
||||
# 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)
|
||||
|
||||
self.play(
|
||||
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)
|
||||
|
||||
|
||||
|
||||
|
||||
def setup_trackers(self):
|
||||
def setup_angle(self):
|
||||
|
||||
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(self.light_source.move_source_to,ORIGIN)
|
||||
|
||||
#self.play(self.spotlight.move_to,ORIGIN)
|
||||
|
||||
# angle msmt (arc)
|
||||
|
||||
arc_angle = self.light_source.spotlight.opening_angle()
|
||||
|
@ -696,7 +700,7 @@ class SingleLighthouseScene(PiCreatureScene):
|
|||
ShowCreation(self.angle_arc),
|
||||
ShowCreation(self.angle_indicator)
|
||||
)
|
||||
#self.add_foreground_mobject(self.angle_indicator)
|
||||
|
||||
self.wait()
|
||||
|
||||
def rotate_screen(self):
|
||||
|
@ -723,7 +727,7 @@ class SingleLighthouseScene(PiCreatureScene):
|
|||
|
||||
|
||||
|
||||
sun_position = [-100,0,0]
|
||||
sun_position = ORIGIN #[-100,0,0]
|
||||
|
||||
|
||||
self.play(
|
||||
|
@ -731,32 +735,33 @@ class SingleLighthouseScene(PiCreatureScene):
|
|||
FadeOut(self.angle_indicator)
|
||||
)
|
||||
|
||||
self.sun = LightSource(
|
||||
opacity_function = inverse_quadratic(1,2,1),
|
||||
num_levels = NUM_LEVELS,
|
||||
radius = 150,
|
||||
max_opacity_ambient = AMBIENT_FULL
|
||||
)
|
||||
self.sun = self.light_source.deepcopy()
|
||||
|
||||
|
||||
|
||||
self.sun.set_screen(self.light_source.spotlight.screen)
|
||||
self.sun.spotlight.change_opacity_function(lambda r: 0.5)
|
||||
#self.sun.ambient_light.opacity_function = inverse_quadratic(1,2,1)
|
||||
#self.sun.num_levels = NUM_LEVELS,
|
||||
#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.spotlight.recalculate_sectors()
|
||||
# self.sun.update()
|
||||
|
||||
# self.add(self.sun)
|
||||
# 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(
|
||||
ReplacementTransform(self.light_source.lighthouse, self.sun.lighthouse),
|
||||
ReplacementTransform(self.light_source.ambient_light, self.sun.ambient_light),
|
||||
ReplacementTransform(self.light_source.spotlight, self.sun.spotlight),
|
||||
self.light_source.spotlight.move_source_to,sun_position,
|
||||
)
|
||||
|
||||
self.add(ScreenTracker(self.sun.spotlight))
|
||||
#self.add(ScreenTracker(self.sun))
|
||||
|
||||
self.wait()
|
||||
|
||||
|
@ -835,11 +840,10 @@ class EarthScene(Scene):
|
|||
# Add elements to scene
|
||||
|
||||
self.add(self.sun,self.screen)
|
||||
self.bring_to_back(self.sun.spotlight.shadow)
|
||||
screen_tracker = MovingScreenTracker(self.screen, light_source = self.sun)
|
||||
sun_tracker = MovingSourceTracker(self.sun)
|
||||
self.bring_to_back(self.sun.shadow)
|
||||
screen_tracker = ScreenTracker(self.sun)
|
||||
|
||||
self.add(sun_tracker, screen_tracker)
|
||||
self.add(screen_tracker)
|
||||
|
||||
self.wait()
|
||||
|
||||
|
@ -847,7 +851,7 @@ class EarthScene(Scene):
|
|||
self.bring_to_back(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.scale(0.3)
|
||||
screen_on_earth.move_to(np.array([
|
||||
|
@ -937,8 +941,9 @@ class ScreenShapingScene(ThreeDScene):
|
|||
opacity_function = inverse_quadratic(1,5,1),
|
||||
num_levels = NUM_LEVELS,
|
||||
radius = 10,
|
||||
screen = self.screen
|
||||
#screen = self.screen
|
||||
)
|
||||
self.light_source.set_screen(self.screen)
|
||||
self.light_source.move_source_to([-5,0,0])
|
||||
|
||||
# abbreviations
|
||||
|
@ -946,9 +951,11 @@ class ScreenShapingScene(ThreeDScene):
|
|||
self.spotlight = self.light_source.spotlight
|
||||
self.lighthouse = self.light_source.lighthouse
|
||||
|
||||
screen_tracker = ScreenTracker(self.spotlight)
|
||||
screen_tracker = ScreenTracker(self.light_source)
|
||||
self.add(screen_tracker)
|
||||
|
||||
self.add_foreground_mobject(self.light_source.shadow)
|
||||
|
||||
# Morty
|
||||
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.wait()
|
||||
|
||||
self.add_foreground_mobject(self.screen)
|
||||
|
||||
dimmed_ambient_light = self.ambient_light.copy()
|
||||
dimmed_ambient_light.dimming(AMBIENT_DIMMED)
|
||||
self.light_source.set_max_opacity_spotlight(0.001)
|
||||
|
||||
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)
|
||||
)
|
||||
|
||||
|
@ -1002,7 +1013,7 @@ class ScreenShapingScene(ThreeDScene):
|
|||
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()
|
||||
# for unslanting the screen later
|
||||
|
||||
|
@ -1149,15 +1160,17 @@ class ScreenShapingScene(ThreeDScene):
|
|||
|
||||
def morph_into_3d(self):
|
||||
|
||||
axes = ThreeDAxes()
|
||||
self.add(axes)
|
||||
#axes = ThreeDAxes()
|
||||
#self.add(axes)
|
||||
|
||||
phi0 = self.camera.get_phi() # default is 0 degs
|
||||
theta0 = self.camera.get_theta() # default is -90 degs
|
||||
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)
|
||||
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, ")"
|
||||
|
||||
# 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)
|
||||
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(
|
||||
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()
|
||||
|
@ -1236,13 +1257,13 @@ class BackToEulerSumScene(PiCreatureScene):
|
|||
bubble = ThoughtBubble(direction = RIGHT,
|
||||
width = 4, height = 3,
|
||||
file_name = "Bubbles_thought.svg")
|
||||
bubble.next_to(randy,DOWN+LEFT)
|
||||
bubble.next_to(randy,LEFT)
|
||||
bubble.set_fill(color = BLACK, opacity = 1)
|
||||
|
||||
# self.play(
|
||||
# randy.change, "wave_2",
|
||||
# ShowCreation(bubble),
|
||||
# )
|
||||
self.play(
|
||||
randy.change, "wave_2",
|
||||
ShowCreation(bubble),
|
||||
)
|
||||
|
||||
|
||||
euler_sum = TexMobject("1", "+", "{1\over 4}",
|
||||
|
@ -1274,32 +1295,74 @@ class BackToEulerSumScene(PiCreatureScene):
|
|||
self.play(FadeIn(light_source.lighthouse))
|
||||
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):
|
||||
|
||||
previous_point = self.number_line.number_to_point(i - 1)
|
||||
point = self.number_line.number_to_point(i)
|
||||
|
||||
moving_light_source = light_source.deepcopy()
|
||||
moving_light_source.set_max_opacity_ambient(0.0001)
|
||||
self.add(moving_light_source.ambient_light)
|
||||
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()
|
||||
indicator_copy = indicator.deepcopy()
|
||||
indicator_copy.move_to(previous_point)
|
||||
self.add(indicator_copy)
|
||||
|
||||
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(
|
||||
Transform(moving_light_source, target_light_source),
|
||||
#MoveToTarget(moving_light_source.ambient_light),
|
||||
Transform(bubble_indicator,bubble_indicator_target)
|
||||
)
|
||||
|
||||
# light_source = moving_light_source
|
||||
self.play(
|
||||
Transform(ls[-2], ls[-1]),
|
||||
Transform(indicator_copy,indicator_target),
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# 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):
|
||||
|
||||
|
|
|
@ -19,9 +19,9 @@ from topics.three_dimensions import *
|
|||
|
||||
from scipy.spatial import ConvexHull
|
||||
|
||||
import traceback
|
||||
|
||||
LIGHT_COLOR = YELLOW
|
||||
SHADOW_COLOR = BLACK
|
||||
SWITCH_ON_RUN_TIME = 1.5
|
||||
FAST_SWITCH_ON_RUN_TIME = 0.1
|
||||
NUM_LEVELS = 30
|
||||
|
@ -62,7 +62,6 @@ class LightSource(VMobject):
|
|||
}
|
||||
|
||||
def generate_points(self):
|
||||
print "LightSource.generate_points"
|
||||
self.lighthouse = Lighthouse()
|
||||
self.ambient_light = AmbientLight(
|
||||
source_point = self.source_point,
|
||||
|
@ -85,7 +84,7 @@ class LightSource(VMobject):
|
|||
else:
|
||||
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.ambient_light.move_source_to(self.source_point)
|
||||
|
||||
|
@ -134,15 +133,15 @@ class LightSource(VMobject):
|
|||
|
||||
|
||||
def move_source_to(self,point):
|
||||
print "LightSource.move_source_to"
|
||||
|
||||
apoint = np.array(point)
|
||||
v = apoint - self.source_point
|
||||
self.source_point = apoint
|
||||
self.lighthouse.next_to(apoint,DOWN,buff = 0)
|
||||
self.ambient_light.move_source_to(apoint)
|
||||
#if self.has_screen():
|
||||
# self.spotlight.move_source_to(apoint)
|
||||
#self.update()
|
||||
if self.has_screen():
|
||||
self.spotlight.move_source_to(apoint)
|
||||
self.update()
|
||||
return self
|
||||
|
||||
|
||||
|
@ -157,13 +156,12 @@ class LightSource(VMobject):
|
|||
self.spotlight.radius = new_radius
|
||||
|
||||
def update(self):
|
||||
print "LightSource.update"
|
||||
self.spotlight.update_sectors()
|
||||
self.update_shadow()
|
||||
|
||||
|
||||
def update_shadow(self):
|
||||
|
||||
|
||||
point = self.source_point
|
||||
projected_screen_points = []
|
||||
if not self.has_screen():
|
||||
|
@ -171,6 +169,10 @@ class LightSource(VMobject):
|
|||
for point in self.screen.get_anchors():
|
||||
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_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)
|
||||
self.shadow.set_points_as_corners(new_anchors)
|
||||
|
||||
# shift it one unit closer to the camera so it is in front of the spotlight
|
||||
#self.shadow.shift(-500*self.projection_direction())
|
||||
# shift it closer to the camera so it is in front of the spotlight
|
||||
self.shadow.shift(1e-5*self.spotlight.projection_direction())
|
||||
self.shadow.mark_paths_closed = True
|
||||
|
||||
|
||||
|
@ -287,7 +289,6 @@ class AmbientLight(VMobject):
|
|||
}
|
||||
|
||||
def generate_points(self):
|
||||
print "AmbientLight.generate_points"
|
||||
self.source_point = np.array(self.source_point)
|
||||
|
||||
# in theory, this method is only called once, right?
|
||||
|
@ -313,13 +314,7 @@ class AmbientLight(VMobject):
|
|||
|
||||
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
|
||||
print "test"
|
||||
self.source_point = np.array(point)
|
||||
self.shift(v)
|
||||
return self
|
||||
|
@ -379,8 +374,6 @@ class Spotlight(VMobject):
|
|||
new_sector = self.new_sector(r,dr,lower_angle,upper_angle)
|
||||
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):
|
||||
|
||||
|
@ -426,6 +419,7 @@ class Spotlight(VMobject):
|
|||
|
||||
viewing_angles = np.array(map(self.viewing_angle_of_point,
|
||||
projected_screen_points))
|
||||
|
||||
lower_angle = upper_angle = 0
|
||||
if len(viewing_angles) != 0:
|
||||
lower_angle = np.min(viewing_angles)
|
||||
|
|
Loading…
Add table
Reference in a new issue