mirror of
https://github.com/3b1b/manim.git
synced 2025-08-05 16:49:03 +00:00
revert to earlier version
This commit is contained in:
parent
9e1216397a
commit
646e1856e8
3 changed files with 173 additions and 297 deletions
|
@ -1,7 +1,5 @@
|
||||||
from big_ol_pile_of_manim_imports import *
|
from big_ol_pile_of_manim_imports import *
|
||||||
|
|
||||||
import time
|
|
||||||
|
|
||||||
import mpmath
|
import mpmath
|
||||||
mpmath.mp.dps = 7
|
mpmath.mp.dps = 7
|
||||||
|
|
||||||
|
@ -409,9 +407,7 @@ def resit_near(x, m):
|
||||||
|
|
||||||
# TODO?: Perhaps use modulus of (uniform) continuity instead of num_checkpoints, calculating
|
# TODO?: Perhaps use modulus of (uniform) continuity instead of num_checkpoints, calculating
|
||||||
# latter as needed from former?
|
# latter as needed from former?
|
||||||
#
|
def make_alpha_winder(func, start, end, num_checkpoints):
|
||||||
# "cheap" argument only used for diagnostic testing right now
|
|
||||||
def make_alpha_winder(func, start, end, num_checkpoints, cheap = False):
|
|
||||||
check_points = [None for i in range(num_checkpoints)]
|
check_points = [None for i in range(num_checkpoints)]
|
||||||
check_points[0] = func(start)
|
check_points[0] = func(start)
|
||||||
step_size = fdiv(end - start, num_checkpoints)
|
step_size = fdiv(end - start, num_checkpoints)
|
||||||
|
@ -421,15 +417,9 @@ def make_alpha_winder(func, start, end, num_checkpoints, cheap = False):
|
||||||
func(start + (i + 1) * step_size),
|
func(start + (i + 1) * step_size),
|
||||||
check_points[i])
|
check_points[i])
|
||||||
def return_func(alpha):
|
def return_func(alpha):
|
||||||
if cheap:
|
|
||||||
return alpha # A test to see if this func is responsible for slowdown
|
|
||||||
|
|
||||||
index = clamp(0, num_checkpoints - 1, int(alpha * num_checkpoints))
|
index = clamp(0, num_checkpoints - 1, int(alpha * num_checkpoints))
|
||||||
x = interpolate(start, end, alpha)
|
x = interpolate(start, end, alpha)
|
||||||
if cheap:
|
return resit_near(func(x), check_points[index])
|
||||||
return check_points[index] # A more principled test that at least returns a reasonable answer
|
|
||||||
else:
|
|
||||||
return resit_near(func(x), check_points[index])
|
|
||||||
return return_func
|
return return_func
|
||||||
|
|
||||||
# The various inconsistent choices of what datatype to use where are a bit of a mess,
|
# The various inconsistent choices of what datatype to use where are a bit of a mess,
|
||||||
|
@ -566,7 +556,6 @@ def walker_animation_with_display(
|
||||||
show_arrows = True,
|
show_arrows = True,
|
||||||
scale_arrows = False,
|
scale_arrows = False,
|
||||||
num_decimal_points = 1,
|
num_decimal_points = 1,
|
||||||
include_background_rectangle = True,
|
|
||||||
**kwargs
|
**kwargs
|
||||||
):
|
):
|
||||||
|
|
||||||
|
@ -582,15 +571,13 @@ def walker_animation_with_display(
|
||||||
if number_update_func != None:
|
if number_update_func != None:
|
||||||
display = DecimalNumber(0,
|
display = DecimalNumber(0,
|
||||||
num_decimal_points = num_decimal_points,
|
num_decimal_points = num_decimal_points,
|
||||||
fill_color = WHITE if include_background_rectangle else BLACK,
|
fill_color = WHITE,
|
||||||
include_background_rectangle = include_background_rectangle)
|
include_background_rectangle = True)
|
||||||
if include_background_rectangle:
|
display.background_rectangle.fill_opacity = 0.5
|
||||||
display.background_rectangle.fill_opacity = 0.5
|
display.background_rectangle.fill_color = GREY
|
||||||
display.background_rectangle.fill_color = GREY
|
display.background_rectangle.scale(1.2)
|
||||||
display.background_rectangle.scale(1.2)
|
|
||||||
displaycement = 0.5 * DOWN # How about that pun, eh?
|
displaycement = 0.5 * DOWN # How about that pun, eh?
|
||||||
# display.move_to(walker.get_center() + displaycement)
|
display.move_to(walker.get_center() + displaycement)
|
||||||
display.next_to(walker, DOWN+RIGHT, SMALL_BUFF)
|
|
||||||
display_anim = ChangingDecimal(display,
|
display_anim = ChangingDecimal(display,
|
||||||
number_update_func,
|
number_update_func,
|
||||||
tracked_mobject = walker_anim.compound_walker.walker,
|
tracked_mobject = walker_anim.compound_walker.walker,
|
||||||
|
@ -608,7 +595,6 @@ def LinearWalker(
|
||||||
number_update_func = None,
|
number_update_func = None,
|
||||||
show_arrows = True,
|
show_arrows = True,
|
||||||
scale_arrows = False,
|
scale_arrows = False,
|
||||||
include_background_rectangle = True,
|
|
||||||
**kwargs
|
**kwargs
|
||||||
):
|
):
|
||||||
walk_func = lambda alpha : interpolate(start_coords, end_coords, alpha)
|
walk_func = lambda alpha : interpolate(start_coords, end_coords, alpha)
|
||||||
|
@ -619,7 +605,6 @@ def LinearWalker(
|
||||||
number_update_func = number_update_func,
|
number_update_func = number_update_func,
|
||||||
show_arrows = show_arrows,
|
show_arrows = show_arrows,
|
||||||
scale_arrows = scale_arrows,
|
scale_arrows = scale_arrows,
|
||||||
include_background_rectangle = include_background_rectangle,
|
|
||||||
**kwargs)
|
**kwargs)
|
||||||
|
|
||||||
class ColorMappedByFuncScene(Scene):
|
class ColorMappedByFuncScene(Scene):
|
||||||
|
@ -732,8 +717,7 @@ class PiWalker(ColorMappedByFuncScene):
|
||||||
"show_num_plane" : False,
|
"show_num_plane" : False,
|
||||||
"draw_lines" : True,
|
"draw_lines" : True,
|
||||||
"num_checkpoints" : 10,
|
"num_checkpoints" : 10,
|
||||||
"num_decimal_points" : 1,
|
"num_decimal_points" : 1
|
||||||
"include_background_rectangle" : False,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def construct(self):
|
def construct(self):
|
||||||
|
@ -789,7 +773,6 @@ class PiWalker(ColorMappedByFuncScene):
|
||||||
run_time = self.step_run_time,
|
run_time = self.step_run_time,
|
||||||
walker_stroke_color = WALKER_LIGHT_COLOR if self.color_foreground_not_background else BLACK,
|
walker_stroke_color = WALKER_LIGHT_COLOR if self.color_foreground_not_background else BLACK,
|
||||||
num_decimal_points = self.num_decimal_points,
|
num_decimal_points = self.num_decimal_points,
|
||||||
include_background_rectangle = self.include_background_rectangle,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.display_odometer:
|
if self.display_odometer:
|
||||||
|
@ -971,18 +954,6 @@ class EquationSolver2dNode(object):
|
||||||
bfs_nodes = self.hacky_bfs()
|
bfs_nodes = self.hacky_bfs()
|
||||||
return Succession(*map(lambda n : n.first_anim, bfs_nodes))
|
return Succession(*map(lambda n : n.first_anim, bfs_nodes))
|
||||||
|
|
||||||
def play_in_bfs(self, scene, border_anim):
|
|
||||||
bfs_nodes = self.hacky_bfs()
|
|
||||||
print "Number of nodes: ", len(bfs_nodes)
|
|
||||||
|
|
||||||
if len(bfs_nodes) < 1:
|
|
||||||
print "Less than 1 node! Aborting!"
|
|
||||||
return
|
|
||||||
|
|
||||||
scene.play(bfs_nodes[0].first_anim, border_anim)
|
|
||||||
for node in bfs_nodes[1:]:
|
|
||||||
scene.play(node.first_anim)
|
|
||||||
|
|
||||||
class EquationSolver2d(ColorMappedObjectsScene):
|
class EquationSolver2d(ColorMappedObjectsScene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"camera_config" : {"use_z_coordinate_for_display_order": True},
|
"camera_config" : {"use_z_coordinate_for_display_order": True},
|
||||||
|
@ -990,7 +961,7 @@ class EquationSolver2d(ColorMappedObjectsScene):
|
||||||
"initial_upper_x" : 5,
|
"initial_upper_x" : 5,
|
||||||
"initial_lower_y" : -3,
|
"initial_lower_y" : -3,
|
||||||
"initial_upper_y" : 3,
|
"initial_upper_y" : 3,
|
||||||
"num_iterations" : 0,
|
"num_iterations" : 1,
|
||||||
"num_checkpoints" : 10,
|
"num_checkpoints" : 10,
|
||||||
|
|
||||||
# Should really merge this into one enum-style variable
|
# Should really merge this into one enum-style variable
|
||||||
|
@ -998,9 +969,6 @@ class EquationSolver2d(ColorMappedObjectsScene):
|
||||||
"display_in_bfs" : False,
|
"display_in_bfs" : False,
|
||||||
|
|
||||||
"use_fancy_lines" : True,
|
"use_fancy_lines" : True,
|
||||||
"line_color" : WHITE, # Only used for non-fancy lines
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: Consider adding a "find_all_roots" flag, which could be turned off
|
# TODO: Consider adding a "find_all_roots" flag, which could be turned off
|
||||||
# to only explore one of the two candidate subrectangles when both are viable
|
# to only explore one of the two candidate subrectangles when both are viable
|
||||||
|
|
||||||
|
@ -1018,26 +986,18 @@ class EquationSolver2d(ColorMappedObjectsScene):
|
||||||
# Used for UhOhScene;
|
# Used for UhOhScene;
|
||||||
"manual_wind_override" : None,
|
"manual_wind_override" : None,
|
||||||
|
|
||||||
"show_cursor" : True,
|
"show_cursor" : False,
|
||||||
|
|
||||||
"linger_parameter" : 0.5,
|
"linger_parameter" : 0.2,
|
||||||
|
|
||||||
"use_separate_plays" : False,
|
|
||||||
|
|
||||||
"use_cheap_winding_numbers" : False, # To use this, make num_checkpoints large
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def construct(self):
|
def construct(self):
|
||||||
if self.num_iterations == 0:
|
|
||||||
print "You forgot to set num_iterations (maybe you meant to subclass something other than EquationSolver2d directly?)"
|
|
||||||
return
|
|
||||||
|
|
||||||
ColorMappedObjectsScene.construct(self)
|
ColorMappedObjectsScene.construct(self)
|
||||||
num_plane = self.num_plane
|
num_plane = self.num_plane
|
||||||
|
|
||||||
clockwise_val_func = lambda p : -point_to_rev(self.func(p))
|
clockwise_val_func = lambda p : -point_to_rev(self.func(p))
|
||||||
|
|
||||||
base_line = Line(UP, RIGHT, stroke_width = border_stroke_width, color = self.line_color)
|
base_line = Line(UP, RIGHT, stroke_width = border_stroke_width, color = WHITE)
|
||||||
|
|
||||||
if self.use_fancy_lines:
|
if self.use_fancy_lines:
|
||||||
base_line.color_using_background_image(self.background_image_file)
|
base_line.color_using_background_image(self.background_image_file)
|
||||||
|
@ -1077,7 +1037,7 @@ class EquationSolver2d(ColorMappedObjectsScene):
|
||||||
return EquationSolver2dNode(empty_animation)
|
return EquationSolver2dNode(empty_animation)
|
||||||
|
|
||||||
def draw_line_return_wind(start, end, start_wind, should_linger = False, draw_line = True):
|
def draw_line_return_wind(start, end, start_wind, should_linger = False, draw_line = True):
|
||||||
alpha_winder = make_alpha_winder(clockwise_val_func, start, end, self.num_checkpoints, cheap = self.use_cheap_winding_numbers)
|
alpha_winder = make_alpha_winder(clockwise_val_func, start, end, self.num_checkpoints)
|
||||||
a0 = alpha_winder(0)
|
a0 = alpha_winder(0)
|
||||||
rebased_winder = lambda alpha: alpha_winder(alpha) - a0 + start_wind
|
rebased_winder = lambda alpha: alpha_winder(alpha) - a0 + start_wind
|
||||||
colored_line = Line(num_plane.coords_to_point(*start) + IN, num_plane.coords_to_point(*end) + IN)
|
colored_line = Line(num_plane.coords_to_point(*start) + IN, num_plane.coords_to_point(*end) + IN)
|
||||||
|
@ -1132,7 +1092,7 @@ class EquationSolver2d(ColorMappedObjectsScene):
|
||||||
width = rect.get_width()
|
width = rect.get_width()
|
||||||
height = rect.get_height()
|
height = rect.get_height()
|
||||||
|
|
||||||
cursor.move_to(num_plane.coords_to_point(center_x, center_y) + 10 * IN)
|
cursor.move_to(num_plane.coords_to_point(center_x, center_y))
|
||||||
cursor.scale(min(width, height))
|
cursor.scale(min(width, height))
|
||||||
|
|
||||||
# Do a quick FadeIn, wait, and quick FadeOut on the cursor, matching rectangle-drawing time
|
# Do a quick FadeIn, wait, and quick FadeOut on the cursor, matching rectangle-drawing time
|
||||||
|
@ -1144,11 +1104,7 @@ class EquationSolver2d(ColorMappedObjectsScene):
|
||||||
|
|
||||||
anim = AnimationGroup(anim, cursor_anim)
|
anim = AnimationGroup(anim, cursor_anim)
|
||||||
|
|
||||||
override_wind = head(manual_wind_override)
|
total_wind = head(manual_wind_override) or round(wind_so_far)
|
||||||
if override_wind != None:
|
|
||||||
total_wind = override_wind
|
|
||||||
else:
|
|
||||||
total_wind = round(wind_so_far)
|
|
||||||
|
|
||||||
if total_wind == 0:
|
if total_wind == 0:
|
||||||
coords = [
|
coords = [
|
||||||
|
@ -1241,17 +1197,15 @@ class EquationSolver2d(ColorMappedObjectsScene):
|
||||||
rate_func = rect_rate
|
rate_func = rect_rate
|
||||||
)
|
)
|
||||||
|
|
||||||
print "About to do the big Play; for reference, the current time is ", time.strftime("%H:%M:%S")
|
self.play(anim, border_anim)
|
||||||
|
|
||||||
if self.use_separate_plays:
|
|
||||||
node.play_in_bfs(self, border_anim)
|
|
||||||
else:
|
|
||||||
self.play(anim, border_anim)
|
|
||||||
|
|
||||||
print "All done; for reference, the current time is ", time.strftime("%H:%M:%S")
|
|
||||||
|
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
|
# In case we wish to reference these later, as had been done in the
|
||||||
|
# WindingNumber_G/SearchSpacePerimeterVsArea scene at one point
|
||||||
|
self.node = node
|
||||||
|
self.anim = anim
|
||||||
|
|
||||||
# TODO: Perhaps have option for bullets (pulses) to fade out and in at ends of line, instead of
|
# TODO: Perhaps have option for bullets (pulses) to fade out and in at ends of line, instead of
|
||||||
# jarringly popping out and in?
|
# jarringly popping out and in?
|
||||||
#
|
#
|
||||||
|
@ -1264,7 +1218,7 @@ class LinePulser(ContinualAnimation):
|
||||||
self.pulse_time = pulse_time
|
self.pulse_time = pulse_time
|
||||||
self.bullets = [bullet_template.copy() for i in range(num_bullets)]
|
self.bullets = [bullet_template.copy() for i in range(num_bullets)]
|
||||||
self.output_func = output_func
|
self.output_func = output_func
|
||||||
ContinualAnimation.__init__(self, VGroup(*self.bullets), **kwargs)
|
ContinualAnimation.__init__(self, VGroup(line, VGroup(*self.bullets)), **kwargs)
|
||||||
|
|
||||||
def update_mobject(self, dt):
|
def update_mobject(self, dt):
|
||||||
alpha = self.external_time % self.pulse_time
|
alpha = self.external_time % self.pulse_time
|
||||||
|
@ -1999,9 +1953,7 @@ class LoopSplitScene(ColorMappedObjectsScene):
|
||||||
|
|
||||||
def flash_circles(circles):
|
def flash_circles(circles):
|
||||||
self.play(LaggedStart(FadeIn, VGroup(circles)))
|
self.play(LaggedStart(FadeIn, VGroup(circles)))
|
||||||
self.wait()
|
self.play(*map(FadeOut, circles))
|
||||||
self.play(FadeOut(VGroup(circles)))
|
|
||||||
self.wait()
|
|
||||||
|
|
||||||
self.add(left_square_lines_vmobject, right_square_lines_vmobject)
|
self.add(left_square_lines_vmobject, right_square_lines_vmobject)
|
||||||
self.remove(*midline_lines)
|
self.remove(*midline_lines)
|
||||||
|
@ -2015,17 +1967,15 @@ class LoopSplitScene(ColorMappedObjectsScene):
|
||||||
self.wait()
|
self.wait()
|
||||||
flash_circles([indicate_circle(l) for l in left_square_lines])
|
flash_circles([indicate_circle(l) for l in left_square_lines])
|
||||||
self.play(line_fade(faded, 1, right_square_lines_vmobject), *bullet_list_fade(1, 0, left_square_bullets))
|
self.play(line_fade(faded, 1, right_square_lines_vmobject), *bullet_list_fade(1, 0, left_square_bullets))
|
||||||
self.wait()
|
|
||||||
|
|
||||||
self.add(*right_square_anims)
|
self.add(*right_square_anims)
|
||||||
self.play(line_fade(1, faded, left_square_lines_vmobject), *bullet_list_fade(0, 1, right_square_bullets))
|
self.play(line_fade(1, faded, left_square_lines_vmobject), *bullet_list_fade(0, 1, right_square_bullets))
|
||||||
self.wait()
|
self.wait()
|
||||||
flash_circles([indicate_circle(l) for l in right_square_lines])
|
flash_circles([indicate_circle(l) for l in right_square_lines])
|
||||||
self.play(line_fade(faded, 1, left_square_lines_vmobject), *bullet_list_fade(1, 0, right_square_bullets))
|
self.play(line_fade(faded, 1, left_square_lines_vmobject), *bullet_list_fade(1, 0, right_square_bullets))
|
||||||
self.wait()
|
|
||||||
|
|
||||||
self.play(*bullet_list_fade(0, 1, left_square_bullets + right_square_bullets))
|
|
||||||
self.wait()
|
self.wait()
|
||||||
|
self.play(*bullet_list_fade(0, 1, left_square_bullets + right_square_bullets))
|
||||||
|
|
||||||
outside_circlers = [
|
outside_circlers = [
|
||||||
indicate_circle(left_line),
|
indicate_circle(left_line),
|
||||||
|
@ -2037,15 +1987,20 @@ class LoopSplitScene(ColorMappedObjectsScene):
|
||||||
|
|
||||||
inner_circle = indicate_circle(midline_lines[0])
|
inner_circle = indicate_circle(midline_lines[0])
|
||||||
self.play(FadeIn(inner_circle))
|
self.play(FadeIn(inner_circle))
|
||||||
self.wait()
|
|
||||||
self.play(FadeOut(inner_circle), line_fade(1, 0, midline_lines_vmobject), *bullet_list_fade(1, 0, midline_bullets))
|
self.play(FadeOut(inner_circle), line_fade(1, 0, midline_lines_vmobject), *bullet_list_fade(1, 0, midline_bullets))
|
||||||
self.wait()
|
|
||||||
|
self.wait(3)
|
||||||
# Repeat for effect, goes well with narration
|
|
||||||
self.play(FadeIn(inner_circle), line_fade(0, 1, midline_lines_vmobject), *bullet_list_fade(0, 1, midline_bullets))
|
# Is there a way to abstract this into a general process to derive a new mapped scene from an old scene?
|
||||||
self.wait()
|
class LoopSplitSceneMapped(LoopSplitScene):
|
||||||
self.play(FadeOut(inner_circle), line_fade(1, 0, midline_lines_vmobject), *bullet_list_fade(1, 0, midline_bullets))
|
|
||||||
self.wait()
|
def setup(self):
|
||||||
|
left_camera = Camera(**self.camera_config)
|
||||||
|
right_camera = MappingCamera(
|
||||||
|
mapping_func = lambda (x, y, z) : complex_to_R3(((complex(x,y) + 3)**1.1) - 3),
|
||||||
|
**self.camera_config)
|
||||||
|
split_screen_camera = SplitScreenCamera(left_camera, right_camera, **self.camera_config)
|
||||||
|
self.camera = split_screen_camera
|
||||||
|
|
||||||
# TODO: Perhaps do extra illustration of zooming out and winding around a large circle,
|
# TODO: Perhaps do extra illustration of zooming out and winding around a large circle,
|
||||||
# to illustrate relation between degree and large-scale winding number
|
# to illustrate relation between degree and large-scale winding number
|
||||||
|
@ -2053,121 +2008,16 @@ class FundThmAlg(EquationSolver2d):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"func" : plane_func_by_wind_spec((1, 2), (-1, 1.5), (-1, 1.5)),
|
"func" : plane_func_by_wind_spec((1, 2), (-1, 1.5), (-1, 1.5)),
|
||||||
"num_iterations" : 2,
|
"num_iterations" : 2,
|
||||||
|
"use_fancy_lines" : True,
|
||||||
}
|
}
|
||||||
|
|
||||||
class SolveX5MinusXMinus1(EquationSolver2d):
|
class SolveX5MinusXMinus1(EquationSolver2d):
|
||||||
CONFIG = {
|
|
||||||
"func" : plane_func_from_complex_func(lambda c : c**5 - c - 1),
|
|
||||||
"num_iterations" : 10,
|
|
||||||
"show_cursor" : True,
|
|
||||||
"display_in_bfs" : True,
|
|
||||||
}
|
|
||||||
|
|
||||||
class PureColorMapOfX5Thing(PureColorMap):
|
|
||||||
CONFIG = {
|
|
||||||
"func" : plane_func_from_complex_func(lambda c : c**5 - c - 1),
|
|
||||||
}
|
|
||||||
|
|
||||||
class X5ThingWithRightHalfGreyed(SolveX5MinusXMinus1):
|
|
||||||
CONFIG = {
|
|
||||||
"num_iterations" : 3,
|
|
||||||
"manual_wind_override" : (1, None, (1, (0, None, None), (0, None, None)))
|
|
||||||
}
|
|
||||||
|
|
||||||
class SolveX5MinusXMinus1_5Iterations(EquationSolver2d):
|
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"func" : plane_func_from_complex_func(lambda c : c**5 - c - 1),
|
"func" : plane_func_from_complex_func(lambda c : c**5 - c - 1),
|
||||||
"num_iterations" : 5,
|
"num_iterations" : 5,
|
||||||
"show_cursor" : True,
|
"use_fancy_lines" : True,
|
||||||
"display_in_bfs" : True,
|
|
||||||
"manual_wind_override" : (None, None, (None, (0, None, None), (0, None, None)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class X5_Monster_Red_Lines(SolveX5MinusXMinus1_5Iterations):
|
|
||||||
CONFIG = {
|
|
||||||
"use_separate_plays" : True,
|
|
||||||
"use_fancy_lines" : False,
|
|
||||||
"line_color" : RED,
|
|
||||||
}
|
|
||||||
|
|
||||||
class X5_Monster_Green_Lines(X5_Monster_Red_Lines):
|
|
||||||
CONFIG = {
|
|
||||||
"line_color" : GREEN,
|
|
||||||
}
|
|
||||||
|
|
||||||
class X5_Monster_Red_Lines_Long(X5_Monster_Red_Lines):
|
|
||||||
CONFIG = {
|
|
||||||
"num_iterations" : 6
|
|
||||||
}
|
|
||||||
|
|
||||||
class X5_Monster_Green_Lines_Long(X5_Monster_Green_Lines):
|
|
||||||
CONFIG = {
|
|
||||||
"num_iterations" : 6
|
|
||||||
}
|
|
||||||
|
|
||||||
class X5_Monster_Red_Lines_Little_More(X5_Monster_Red_Lines_Long):
|
|
||||||
CONFIG = {
|
|
||||||
"num_iterations" : 7
|
|
||||||
}
|
|
||||||
|
|
||||||
class X5_Monster_Green_Lines_Little_More(X5_Monster_Green_Lines_Long):
|
|
||||||
CONFIG = {
|
|
||||||
"num_iterations" : 7
|
|
||||||
}
|
|
||||||
|
|
||||||
class X5_Monster_Red_Lines_No_Numbers(X5_Monster_Red_Lines):
|
|
||||||
CONFIG = {
|
|
||||||
"num_iterations" : 3,
|
|
||||||
"show_winding_numbers" : False,
|
|
||||||
}
|
|
||||||
|
|
||||||
class X5_Monster_Green_Lines_No_Numbers(X5_Monster_Green_Lines):
|
|
||||||
CONFIG = {
|
|
||||||
"num_iterations" : 3,
|
|
||||||
"show_winding_numbers" : False,
|
|
||||||
}
|
|
||||||
|
|
||||||
class SolveX5MinusXMinus1_3Iterations(EquationSolver2d):
|
|
||||||
CONFIG = {
|
|
||||||
"func" : plane_func_from_complex_func(lambda c : c**5 - c - 1),
|
|
||||||
"num_iterations" : 3,
|
|
||||||
"show_cursor" : True,
|
|
||||||
"display_in_bfs" : True,
|
|
||||||
}
|
|
||||||
|
|
||||||
class Diagnostic(SolveX5MinusXMinus1_3Iterations):
|
|
||||||
CONFIG = {
|
|
||||||
# I think the combination of these two makes things slow
|
|
||||||
"use_separate_plays" : not False, # This one isn't important to set any particular way, so let's leave it like this
|
|
||||||
"use_fancy_lines" : True,
|
|
||||||
|
|
||||||
# This causes a small slowdown (before rendering, in particular), but not the big one, I think
|
|
||||||
"show_winding_numbers" : True,
|
|
||||||
|
|
||||||
# This doesn't significantly matter for rendering time, I think
|
|
||||||
"camera_config" : {"use_z_coordinate_for_display_order" : True}
|
|
||||||
}
|
|
||||||
|
|
||||||
# All above flags False (meaning not db = False): just under 30 it/s
|
|
||||||
# not db = True: 30
|
|
||||||
# use_fancy_lines = True: 30 at first (if scene.play(bfs_nodes[0].first_anim, border_anim is off), but then drops to 3 (or drops right away if that simultaneous play is on)
|
|
||||||
# use_z_coordinate = True: 30
|
|
||||||
# show_winding_numbers = True: 10
|
|
||||||
# winding AND use_fancy_lines: 10
|
|
||||||
# not db AND fancy_lines AND z_coords = true, winding = false: 3. Not 30, but 3. Slow.
|
|
||||||
# db AND use_fancy: 3. Slow.
|
|
||||||
# fancy AND z_coords: 30. Fast. [Hm, this may have been a mistake; fancy and z_coords is now slow?]
|
|
||||||
# fancy, winding, AND z_coords, but not (not db): 10
|
|
||||||
# not db, winding, AND z_coords, but not fancy: 10
|
|
||||||
|
|
||||||
# class DiagnosticB(Diagnostic):
|
|
||||||
# CONFIG = {
|
|
||||||
# "num_iterations" : 3,
|
|
||||||
# #"num_checkpoints" : 100,
|
|
||||||
# #"show_winding_numbers" : False,
|
|
||||||
# #"use_cheap_winding_numbers" : True,
|
|
||||||
# }
|
|
||||||
|
|
||||||
class SolveX5MinusXMinus1Parallel(SolveX5MinusXMinus1):
|
class SolveX5MinusXMinus1Parallel(SolveX5MinusXMinus1):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"display_in_parallel" : True
|
"display_in_parallel" : True
|
||||||
|
@ -2186,37 +2036,6 @@ class PreviewClip(EquationSolver2d):
|
||||||
"use_fancy_lines" : True,
|
"use_fancy_lines" : True,
|
||||||
}
|
}
|
||||||
|
|
||||||
class ParallelClip(EquationSolver2d):
|
|
||||||
CONFIG = {
|
|
||||||
"func" : plane_func_by_wind_spec(
|
|
||||||
(-3, -1.3, 2), (0.1, 0.2, 1), (2.8, -2, 1)
|
|
||||||
),
|
|
||||||
"num_iterations" : 5,
|
|
||||||
"display_in_parallel" : True,
|
|
||||||
}
|
|
||||||
|
|
||||||
class EquationSolver2dMatchBreakdown(EquationSolver2d):
|
|
||||||
CONFIG = {
|
|
||||||
"func" : plane_func_by_wind_spec(
|
|
||||||
(-2, 0.3, 2), (2, -0.2, 1) # Not an exact match, because our breakdown function has a zero along midlines...
|
|
||||||
),
|
|
||||||
"num_iterations" : 5,
|
|
||||||
"display_in_parallel" : True,
|
|
||||||
"show_cursor" : True
|
|
||||||
}
|
|
||||||
|
|
||||||
class EquationSolver2dMatchBreakdown_parallel(EquationSolver2dMatchBreakdown):
|
|
||||||
CONFIG = {
|
|
||||||
"display_in_parallel" : True,
|
|
||||||
"display_in_bfs" : False,
|
|
||||||
}
|
|
||||||
|
|
||||||
class EquationSolver2dMatchBreakdown_bfs(EquationSolver2dMatchBreakdown):
|
|
||||||
CONFIG = {
|
|
||||||
"display_in_parallel" : False,
|
|
||||||
"display_in_bfs" : True,
|
|
||||||
}
|
|
||||||
|
|
||||||
class QuickPreview(PreviewClip):
|
class QuickPreview(PreviewClip):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"num_iterations" : 3,
|
"num_iterations" : 3,
|
||||||
|
@ -2234,11 +2053,6 @@ class LongEquationSolver(EquationSolver2d):
|
||||||
"show_cursor" : True,
|
"show_cursor" : True,
|
||||||
}
|
}
|
||||||
|
|
||||||
class QuickPreviewUnfancy(LongEquationSolver):
|
|
||||||
CONFIG = {
|
|
||||||
# "use_fancy_lines" : False,
|
|
||||||
}
|
|
||||||
|
|
||||||
# TODO: Borsuk-Ulam visuals
|
# TODO: Borsuk-Ulam visuals
|
||||||
# Note: May want to do an ordinary square scene, then MappingCamera it into a circle
|
# Note: May want to do an ordinary square scene, then MappingCamera it into a circle
|
||||||
# class BorsukUlamScene(PiWalker):
|
# class BorsukUlamScene(PiWalker):
|
||||||
|
@ -2665,6 +2479,18 @@ class ShowBack(PiWalkerRect):
|
||||||
"func" : plane_func_by_wind_spec((1, 2), (-1, 1.5), (-1, 1.5))
|
"func" : plane_func_by_wind_spec((1, 2), (-1, 1.5), (-1, 1.5))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Diagnostic(Scene):
|
||||||
|
def construct(self):
|
||||||
|
testList = map(lambda n : (n, rev_to_rgba(n)), [0, 0.1, 0.2, 0.3, 0.4])
|
||||||
|
print "Here you go:", testList
|
||||||
|
self.wait()
|
||||||
|
|
||||||
|
class DiagnosticColorMap(PureColorMap):
|
||||||
|
CONFIG = {
|
||||||
|
"func" : lambda (x, y) : (25 * x, 25 * y),
|
||||||
|
"show_num_plane" : False,
|
||||||
|
}
|
||||||
|
|
||||||
class PiWalkerOdometerTest(PiWalkerExamplePlaneFunc):
|
class PiWalkerOdometerTest(PiWalkerExamplePlaneFunc):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"display_odometer" : True
|
"display_odometer" : True
|
|
@ -1896,20 +1896,6 @@ class TinyLoopAroundRed(TinyLoop):
|
||||||
"target_coords" : (-1, 1),
|
"target_coords" : (-1, 1),
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConfusedPiCreature(PiCreatureScene):
|
|
||||||
def construct(self):
|
|
||||||
morty = self.pi_creature
|
|
||||||
morty.set_color(YELLOW_E)
|
|
||||||
morty.flip()
|
|
||||||
morty.center()
|
|
||||||
|
|
||||||
self.play(morty.change, "awe", DOWN+3*RIGHT)
|
|
||||||
self.wait(2)
|
|
||||||
self.play(morty.change, "confused")
|
|
||||||
self.wait(2)
|
|
||||||
self.play(morty.change, "pondering")
|
|
||||||
self.wait(2)
|
|
||||||
|
|
||||||
class FailureOfComposition(ColorMappedObjectsScene):
|
class FailureOfComposition(ColorMappedObjectsScene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"func" : lambda p : (
|
"func" : lambda p : (
|
||||||
|
@ -2162,11 +2148,7 @@ class TransitionFromPathsToBoundaries(ColorMappedObjectsScene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"func" : plane_func_by_wind_spec(
|
"func" : plane_func_by_wind_spec(
|
||||||
(-2, 0, 2), (2, 0, 1)
|
(-2, 0, 2), (2, 0, 1)
|
||||||
),
|
)
|
||||||
"dot_fill_opacity" : 1,
|
|
||||||
"dot_stroke_width" : 1,
|
|
||||||
"include_walkers" : True,
|
|
||||||
"include_question_mark" : True,
|
|
||||||
}
|
}
|
||||||
def construct(self):
|
def construct(self):
|
||||||
ColorMappedObjectsScene.construct(self)
|
ColorMappedObjectsScene.construct(self)
|
||||||
|
@ -2196,10 +2178,7 @@ class TransitionFromPathsToBoundaries(ColorMappedObjectsScene):
|
||||||
|
|
||||||
#Setup region labels
|
#Setup region labels
|
||||||
|
|
||||||
sum_tex = "x+y"
|
for square, tex in (left_square, "x"), (right_square, "y"), (joint_rect, "x+y \\, ?"):
|
||||||
if self.include_question_mark:
|
|
||||||
sum_tex += "\\, ?"
|
|
||||||
for square, tex in (left_square, "x"), (right_square, "y"), (joint_rect, sum_tex):
|
|
||||||
square.label = TextMobject("Winding = ", "$%s$"%tex)
|
square.label = TextMobject("Winding = ", "$%s$"%tex)
|
||||||
square.label.move_to(square)
|
square.label.move_to(square)
|
||||||
|
|
||||||
|
@ -2253,7 +2232,7 @@ class TransitionFromPathsToBoundaries(ColorMappedObjectsScene):
|
||||||
path_arc = TAU/6
|
path_arc = TAU/6
|
||||||
),
|
),
|
||||||
FadeIn(joint_rect.label[1][1]),
|
FadeIn(joint_rect.label[1][1]),
|
||||||
FadeIn(joint_rect.label[1][3:]),
|
FadeIn(joint_rect.label[1][3]),
|
||||||
FadeOut(right_square.label[0]),
|
FadeOut(right_square.label[0]),
|
||||||
Transform(
|
Transform(
|
||||||
right_square.label[1], joint_rect.label[1][2],
|
right_square.label[1], joint_rect.label[1][2],
|
||||||
|
@ -2302,12 +2281,9 @@ class TransitionFromPathsToBoundaries(ColorMappedObjectsScene):
|
||||||
|
|
||||||
#Setup dot, arrow and label
|
#Setup dot, arrow and label
|
||||||
dot = self.dot = Dot(radius = 0.1)
|
dot = self.dot = Dot(radius = 0.1)
|
||||||
dot.set_stroke(WHITE, self.dot_stroke_width)
|
dot.set_stroke(WHITE, 1)
|
||||||
update_dot_color = ContinualUpdateFromFunc(
|
update_dot_color = ContinualUpdateFromFunc(
|
||||||
dot, lambda d : d.set_fill(
|
dot, lambda d : d.set_fill(get_output_color())
|
||||||
get_output_color(),
|
|
||||||
self.dot_fill_opacity
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
label = DecimalNumber(0, num_decimal_points = 1)
|
label = DecimalNumber(0, num_decimal_points = 1)
|
||||||
|
@ -2318,7 +2294,7 @@ class TransitionFromPathsToBoundaries(ColorMappedObjectsScene):
|
||||||
|
|
||||||
arrow_length = 0.75
|
arrow_length = 0.75
|
||||||
arrow = Vector(arrow_length*RIGHT)
|
arrow = Vector(arrow_length*RIGHT)
|
||||||
arrow.set_stroke(WHITE, self.dot_stroke_width)
|
arrow.set_stroke(WHITE, 1)
|
||||||
def arrow_update_func(arrow):
|
def arrow_update_func(arrow):
|
||||||
arrow.set_fill(get_output_color(), 1)
|
arrow.set_fill(get_output_color(), 1)
|
||||||
arrow.rotate(-TAU*get_output_rev() - arrow.get_angle())
|
arrow.rotate(-TAU*get_output_rev() - arrow.get_angle())
|
||||||
|
@ -2327,8 +2303,7 @@ class TransitionFromPathsToBoundaries(ColorMappedObjectsScene):
|
||||||
return arrow
|
return arrow
|
||||||
update_arrow = ContinualUpdateFromFunc(arrow, arrow_update_func)
|
update_arrow = ContinualUpdateFromFunc(arrow, arrow_update_func)
|
||||||
|
|
||||||
if self.include_walkers:
|
self.add(update_arrow, update_dot_color, label_upadte)
|
||||||
self.add(update_arrow, update_dot_color, label_upadte)
|
|
||||||
return dot
|
return dot
|
||||||
|
|
||||||
def position_dot(self, point):
|
def position_dot(self, point):
|
||||||
|
@ -2336,17 +2311,6 @@ class TransitionFromPathsToBoundaries(ColorMappedObjectsScene):
|
||||||
self.start_rev = self.get_output_rev()
|
self.start_rev = self.get_output_rev()
|
||||||
self.curr_winding = 0
|
self.curr_winding = 0
|
||||||
|
|
||||||
class TransitionFromPathsToBoundariesArrowless(TransitionFromPathsToBoundaries):
|
|
||||||
CONFIG = {
|
|
||||||
"func" : plane_func_by_wind_spec(
|
|
||||||
(-2, 0, 2), (2, 0, 1)
|
|
||||||
),
|
|
||||||
"dot_fill_opacity" : 0,
|
|
||||||
"dot_stroke_width" : 0,
|
|
||||||
"include_walkers" : False,
|
|
||||||
"include_question_mark" : False,
|
|
||||||
}
|
|
||||||
|
|
||||||
class BreakDownLoopWithNonzeroWinding(TransitionFromPathsToBoundaries):
|
class BreakDownLoopWithNonzeroWinding(TransitionFromPathsToBoundaries):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
zero_point = 2*LEFT
|
zero_point = 2*LEFT
|
||||||
|
@ -2625,7 +2589,9 @@ class PolynomialTerms(MonomialTerm):
|
||||||
|
|
||||||
class SearchSpacePerimeterVsArea(EquationSolver2d):
|
class SearchSpacePerimeterVsArea(EquationSolver2d):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"func" : example_plane_func,
|
"func" : plane_func_by_wind_spec(
|
||||||
|
(-3, -1.3, 2), (0.1, 0.2, 1), (2.8, -2, 1)
|
||||||
|
),
|
||||||
"num_iterations" : 15,
|
"num_iterations" : 15,
|
||||||
"display_in_parallel" : False,
|
"display_in_parallel" : False,
|
||||||
"use_fancy_lines" : True,
|
"use_fancy_lines" : True,
|
||||||
|
@ -2688,6 +2654,7 @@ class SearchSpacePerimeterVsArea(EquationSolver2d):
|
||||||
self.play(FadeOut(full_rect))
|
self.play(FadeOut(full_rect))
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
|
<<<<<<< HEAD:old_projects/WindingNumber_G.py
|
||||||
class ShowPolynomialFinalState(SolveX5MinusXMinus1):
|
class ShowPolynomialFinalState(SolveX5MinusXMinus1):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"num_iterations" : 15,
|
"num_iterations" : 15,
|
||||||
|
@ -2905,6 +2872,8 @@ class AllOfTheVideos(Scene):
|
||||||
self.play(LaggedStart(FadeIn, images, run_time = 4))
|
self.play(LaggedStart(FadeIn, images, run_time = 4))
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
|
=======
|
||||||
|
>>>>>>> parent of feeb9ec... Merge branch 'master' into eop:active_projects/WindingNumber_G.py
|
||||||
class EndingCredits(Scene):
|
class EndingCredits(Scene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
text = TextMobject(
|
text = TextMobject(
|
||||||
|
@ -3218,33 +3187,8 @@ class EndScreen(PatreonEndScreen, PiCreatureScene):
|
||||||
self.play(morty.change, mode)
|
self.play(morty.change, mode)
|
||||||
self.wait(2)
|
self.wait(2)
|
||||||
|
|
||||||
class Thumbnail(SearchSpacePerimeterVsArea):
|
|
||||||
CONFIG = {
|
|
||||||
"num_iterations" : 18,
|
|
||||||
"func" : plane_func_by_wind_spec(
|
|
||||||
(-3, -1.3, 2), (0.1, 0.2, 1), (2.8, -2, 1)
|
|
||||||
),
|
|
||||||
}
|
|
||||||
def construct(self):
|
|
||||||
self.force_skipping()
|
|
||||||
EquationSolver2d.construct(self)
|
|
||||||
self.revert_to_original_skipping_status()
|
|
||||||
|
|
||||||
mobjects = VGroup(*self.get_mobjects())
|
|
||||||
lines = VGroup()
|
|
||||||
rects = VGroup()
|
|
||||||
get_length = lambda mob : max(mob.get_width(), mob.get_height())
|
|
||||||
for mob in mobjects:
|
|
||||||
if mob.background_image_file is not None:
|
|
||||||
mob.set_stroke(width = 4*np.sqrt(get_length(mob)))
|
|
||||||
lines.add(mob)
|
|
||||||
elif isinstance(mob, Polygon):
|
|
||||||
rects.add(mob)
|
|
||||||
else:
|
|
||||||
self.remove(mob)
|
|
||||||
|
|
||||||
self.clear()
|
|
||||||
self.add(lines)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -156,6 +156,112 @@ class ComplexTransformationScene(Scene):
|
||||||
*added_anims
|
*added_anims
|
||||||
)
|
)
|
||||||
|
|
||||||
|
<<<<<<< HEAD:once_useful_constructs/complex_transformation_scene.py
|
||||||
|
=======
|
||||||
|
##### Unsure about what comes under here...
|
||||||
|
|
||||||
|
def complex_string(complex_num):
|
||||||
|
return filter(lambda c : c not in "()", str(complex_num))
|
||||||
|
|
||||||
|
class ComplexPlane(NumberPlane):
|
||||||
|
CONFIG = {
|
||||||
|
"color" : BLUE,
|
||||||
|
"unit_size" : 1,
|
||||||
|
"line_frequency" : 1,
|
||||||
|
"faded_line_frequency" : 0.5,
|
||||||
|
}
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
digest_config(self, kwargs)
|
||||||
|
kwargs.update({
|
||||||
|
"x_unit_size" : self.unit_size,
|
||||||
|
"y_unit_size" : self.unit_size,
|
||||||
|
"x_line_frequency" : self.line_frequency,
|
||||||
|
"x_faded_line_frequency" : self.faded_line_frequency,
|
||||||
|
"y_line_frequency" : self.line_frequency,
|
||||||
|
"y_faded_line_frequency" : self.faded_line_frequency,
|
||||||
|
})
|
||||||
|
NumberPlane.__init__(self, **kwargs)
|
||||||
|
|
||||||
|
def number_to_point(self, number):
|
||||||
|
number = complex(number)
|
||||||
|
return self.coords_to_point(number.real, number.imag)
|
||||||
|
|
||||||
|
def point_to_number(self, point):
|
||||||
|
x, y = self.point_to_coords(point)
|
||||||
|
return complex(x, y)
|
||||||
|
|
||||||
|
def get_coordinate_labels(self, *numbers):
|
||||||
|
# TODO: Should merge this with the code from NumberPlane.get_coordinate_labels
|
||||||
|
|
||||||
|
result = VGroup()
|
||||||
|
nudge = 0.1*(DOWN+RIGHT)
|
||||||
|
if len(numbers) == 0:
|
||||||
|
numbers = range(-int(self.x_radius), int(self.x_radius)+1)
|
||||||
|
numbers += [
|
||||||
|
complex(0, y)
|
||||||
|
for y in range(-int(self.y_radius), int(self.y_radius)+1)
|
||||||
|
]
|
||||||
|
for number in numbers:
|
||||||
|
if number == complex(0, 0):
|
||||||
|
continue
|
||||||
|
point = self.number_to_point(number)
|
||||||
|
num_str = str(number).replace("j", "i")
|
||||||
|
if num_str.startswith("0"):
|
||||||
|
num_str = "0"
|
||||||
|
elif num_str in ["1i", "-1i"]:
|
||||||
|
num_str = num_str.replace("1", "")
|
||||||
|
num_mob = TexMobject(num_str)
|
||||||
|
num_mob.add_background_rectangle()
|
||||||
|
num_mob.scale_to_fit_height(self.written_coordinate_height)
|
||||||
|
num_mob.next_to(point, DOWN+LEFT, SMALL_BUFF)
|
||||||
|
result.add(num_mob)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def add_coordinates(self, *numbers):
|
||||||
|
self.add(*self.get_coordinate_labels(*numbers))
|
||||||
|
return self
|
||||||
|
|
||||||
|
def add_spider_web(self, circle_freq = 1, angle_freq = np.pi/6):
|
||||||
|
# This code no longer works because it has this reference to self.fade_factor
|
||||||
|
# which is never initialized. Shall we delete this little-used function entirely?
|
||||||
|
self.fade(self.fade_factor)
|
||||||
|
config = {
|
||||||
|
"color" : self.color,
|
||||||
|
"density" : self.density,
|
||||||
|
}
|
||||||
|
for radius in np.arange(circle_freq, SPACE_WIDTH, circle_freq):
|
||||||
|
self.add(Circle(radius = radius, **config))
|
||||||
|
for angle in np.arange(0, 2*np.pi, angle_freq):
|
||||||
|
end_point = np.cos(angle)*RIGHT + np.sin(angle)*UP
|
||||||
|
end_point *= SPACE_WIDTH
|
||||||
|
self.add(Line(ORIGIN, end_point, **config))
|
||||||
|
return self
|
||||||
|
|
||||||
|
class ComplexFunction(ApplyPointwiseFunction):
|
||||||
|
def __init__(self, function, mobject = ComplexPlane, **kwargs):
|
||||||
|
if "path_func" not in kwargs:
|
||||||
|
self.path_func = path_along_arc(
|
||||||
|
np.log(function(complex(1))).imag
|
||||||
|
)
|
||||||
|
ApplyPointwiseFunction.__init__(
|
||||||
|
self,
|
||||||
|
lambda (x, y, z) : complex_to_R3(function(complex(x, y))),
|
||||||
|
instantiate(mobject),
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
class ComplexHomotopy(Homotopy):
|
||||||
|
def __init__(self, complex_homotopy, mobject = ComplexPlane, **kwargs):
|
||||||
|
"""
|
||||||
|
Complex Hootopy a function Cx[0, 1] to C
|
||||||
|
"""
|
||||||
|
def homotopy(event):
|
||||||
|
x, y, z, t = event
|
||||||
|
c = complex_homotopy((complex(x, y), t))
|
||||||
|
return (c.real, c.imag, z)
|
||||||
|
Homotopy.__init__(self, homotopy, mobject, *args, **kwargs)
|
||||||
|
|
||||||
|
>>>>>>> parent of feeb9ec... Merge branch 'master' into eop:topics/complex_numbers.py
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue