mirror of
https://github.com/3b1b/manim.git
synced 2025-08-05 16:49:03 +00:00
commit
9e50d4b371
1 changed files with 111 additions and 23 deletions
|
@ -674,6 +674,12 @@ class ColorMappedByFuncScene(Scene):
|
||||||
"hide_background" : False #Background used for color mapped objects, not as background
|
"hide_background" : False #Background used for color mapped objects, not as background
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def short_path_to_long_path(self, filename_with_ext):
|
||||||
|
return os.path.join(
|
||||||
|
self.output_directory, "images",
|
||||||
|
filename_with_ext
|
||||||
|
)
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
# The composition of input_to_pos and pos_to_color
|
# The composition of input_to_pos and pos_to_color
|
||||||
# is to be equal to func (which turns inputs into colors)
|
# is to be equal to func (which turns inputs into colors)
|
||||||
|
@ -700,8 +706,7 @@ class ColorMappedByFuncScene(Scene):
|
||||||
# Thus, multiple scenes with same output image can re-use it
|
# Thus, multiple scenes with same output image can re-use it
|
||||||
# without recomputation
|
# without recomputation
|
||||||
full_hash = hash((func_hash, self.camera.pixel_shape))
|
full_hash = hash((func_hash, self.camera.pixel_shape))
|
||||||
self.background_image_file = os.path.join(
|
self.background_image_file = self.short_path_to_long_path(
|
||||||
self.output_directory, "images",
|
|
||||||
"color_mapped_bg_hash_" + str(full_hash) + ".png"
|
"color_mapped_bg_hash_" + str(full_hash) + ".png"
|
||||||
)
|
)
|
||||||
self.in_background_pass = not os.path.exists(self.background_image_file)
|
self.in_background_pass = not os.path.exists(self.background_image_file)
|
||||||
|
@ -724,7 +729,6 @@ class ColorMappedByFuncScene(Scene):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.save_image(self.background_image_file, mode = "RGBA")
|
self.save_image(self.background_image_file, mode = "RGBA")
|
||||||
|
|
||||||
if self.hide_background:
|
if self.hide_background:
|
||||||
|
@ -872,10 +876,10 @@ class PiWalkerCircle(PiWalker):
|
||||||
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},
|
||||||
"initial_lower_x" : -5.1,
|
"initial_lower_x" : -5,
|
||||||
"initial_upper_x" : 5.1,
|
"initial_upper_x" : 5,
|
||||||
"initial_lower_y" : -3.1,
|
"initial_lower_y" : -3,
|
||||||
"initial_upper_y" : 3.1,
|
"initial_upper_y" : 3,
|
||||||
"num_iterations" : 1,
|
"num_iterations" : 1,
|
||||||
"num_checkpoints" : 10,
|
"num_checkpoints" : 10,
|
||||||
"display_in_parallel" : True,
|
"display_in_parallel" : True,
|
||||||
|
@ -893,7 +897,9 @@ class EquationSolver2d(ColorMappedObjectsScene):
|
||||||
#
|
#
|
||||||
# replacement_background_image_file has to be manually configured
|
# replacement_background_image_file has to be manually configured
|
||||||
"show_winding_numbers" : True,
|
"show_winding_numbers" : True,
|
||||||
"replacement_background_image_file" : None,
|
|
||||||
|
# Used for UhOhScene;
|
||||||
|
"manual_wind_override" : None
|
||||||
}
|
}
|
||||||
|
|
||||||
def construct(self):
|
def construct(self):
|
||||||
|
@ -904,13 +910,35 @@ class EquationSolver2d(ColorMappedObjectsScene):
|
||||||
|
|
||||||
base_line = Line(UP, RIGHT, stroke_width = border_stroke_width, color = WHITE)
|
base_line = Line(UP, RIGHT, stroke_width = border_stroke_width, color = WHITE)
|
||||||
|
|
||||||
|
if self.use_fancy_lines:
|
||||||
|
base_line.color_using_background_image(self.background_image_file)
|
||||||
|
|
||||||
|
def match_style_with_bg(obj1, obj2):
|
||||||
|
obj1.match_style(obj2)
|
||||||
|
bg = obj2.get_background_image_file()
|
||||||
|
if bg != None:
|
||||||
|
obj1.color_using_background_image(bg)
|
||||||
|
|
||||||
run_time_base = 1
|
run_time_base = 1
|
||||||
run_time_with_lingering = run_time_base + 0.2
|
run_time_with_lingering = run_time_base + 0.2
|
||||||
base_rate = lambda t : t
|
base_rate = lambda t : t
|
||||||
linger_rate = squish_rate_func(lambda t : t, 0,
|
linger_rate = squish_rate_func(lambda t : t, 0,
|
||||||
fdiv(run_time_base, run_time_with_lingering))
|
fdiv(run_time_base, run_time_with_lingering))
|
||||||
|
|
||||||
def Animate2dSolver(cur_depth, rect, dim_to_split, sides_to_draw = [0, 1, 2, 3]):
|
# Helper functions for manual_wind_override
|
||||||
|
def head(m):
|
||||||
|
if m == None:
|
||||||
|
return None
|
||||||
|
return m[0]
|
||||||
|
|
||||||
|
def child(m, i):
|
||||||
|
if m == None or m == 0:
|
||||||
|
return None
|
||||||
|
return m[i + 1]
|
||||||
|
|
||||||
|
def Animate2dSolver(cur_depth, rect, dim_to_split,
|
||||||
|
sides_to_draw = [0, 1, 2, 3],
|
||||||
|
manual_wind_override = None):
|
||||||
print "Solver at depth: " + str(cur_depth)
|
print "Solver at depth: " + str(cur_depth)
|
||||||
|
|
||||||
if cur_depth >= self.num_iterations:
|
if cur_depth >= self.num_iterations:
|
||||||
|
@ -921,15 +949,13 @@ class EquationSolver2d(ColorMappedObjectsScene):
|
||||||
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)
|
||||||
colored_line.match_style(base_line)
|
match_style_with_bg(colored_line, base_line)
|
||||||
if self.use_fancy_lines:
|
|
||||||
colored_line.color_using_background_image(self.replacement_background_image_file or self.background_image_file)
|
|
||||||
|
|
||||||
walker_anim = LinearWalker(
|
walker_anim = LinearWalker(
|
||||||
start_coords = start,
|
start_coords = start,
|
||||||
end_coords = end,
|
end_coords = end,
|
||||||
coords_to_point = num_plane.coords_to_point,
|
coords_to_point = num_plane.coords_to_point,
|
||||||
val_func = self.func,
|
val_func = self.func, # Note: This is the image func, and not logic_func
|
||||||
number_update_func = rebased_winder if self.show_winding_numbers else None,
|
number_update_func = rebased_winder if self.show_winding_numbers else None,
|
||||||
remover = True,
|
remover = True,
|
||||||
walker_stroke_color = WALKER_LIGHT_COLOR,
|
walker_stroke_color = WALKER_LIGHT_COLOR,
|
||||||
|
@ -968,7 +994,7 @@ class EquationSolver2d(ColorMappedObjectsScene):
|
||||||
draw_line = i in sides_to_draw)
|
draw_line = i in sides_to_draw)
|
||||||
anim = Succession(anim, next_anim)
|
anim = Succession(anim, next_anim)
|
||||||
|
|
||||||
total_wind = round(wind_so_far)
|
total_wind = head(manual_wind_override) or round(wind_so_far)
|
||||||
|
|
||||||
if total_wind == 0:
|
if total_wind == 0:
|
||||||
coords = [
|
coords = [
|
||||||
|
@ -994,9 +1020,10 @@ class EquationSolver2d(ColorMappedObjectsScene):
|
||||||
cur_depth = cur_depth + 1,
|
cur_depth = cur_depth + 1,
|
||||||
rect = sub_rect,
|
rect = sub_rect,
|
||||||
dim_to_split = 1 - dim_to_split,
|
dim_to_split = 1 - dim_to_split,
|
||||||
sides_to_draw = [side_to_draw]
|
sides_to_draw = [side_to_draw],
|
||||||
|
manual_wind_override = child(manual_wind_override, index)
|
||||||
)
|
)
|
||||||
for (sub_rect, side_to_draw) in sub_rect_and_sides
|
for (index, (sub_rect, side_to_draw)) in enumerate(sub_rect_and_sides)
|
||||||
]
|
]
|
||||||
mid_line_coords = rect.split_line_on_dim(dim_to_split)
|
mid_line_coords = rect.split_line_on_dim(dim_to_split)
|
||||||
mid_line_points = [num_plane.coords_to_point(x, y) + 2 * IN for (x, y) in mid_line_coords]
|
mid_line_points = [num_plane.coords_to_point(x, y) + 2 * IN for (x, y) in mid_line_coords]
|
||||||
|
@ -1026,7 +1053,8 @@ class EquationSolver2d(ColorMappedObjectsScene):
|
||||||
cur_depth = 0,
|
cur_depth = 0,
|
||||||
rect = rect,
|
rect = rect,
|
||||||
dim_to_split = 0,
|
dim_to_split = 0,
|
||||||
sides_to_draw = []
|
sides_to_draw = [],
|
||||||
|
manual_wind_override = self.manual_wind_override
|
||||||
)
|
)
|
||||||
|
|
||||||
print "Done computing anim"
|
print "Done computing anim"
|
||||||
|
@ -1039,9 +1067,7 @@ class EquationSolver2d(ColorMappedObjectsScene):
|
||||||
rect.get_bottom_left(),
|
rect.get_bottom_left(),
|
||||||
]
|
]
|
||||||
border = Polygon(*map(lambda x : num_plane.coords_to_point(*x) + IN, rect_points))
|
border = Polygon(*map(lambda x : num_plane.coords_to_point(*x) + IN, rect_points))
|
||||||
border.match_style(base_line)
|
match_style_with_bg(border, base_line)
|
||||||
if self.use_fancy_lines:
|
|
||||||
border.color_using_background_image(self.background_image_file)
|
|
||||||
|
|
||||||
rect_time_without_linger = 4 * run_time_base
|
rect_time_without_linger = 4 * run_time_base
|
||||||
rect_time_with_linger = 3 * run_time_base + run_time_with_lingering
|
rect_time_with_linger = 3 * run_time_base + run_time_with_lingering
|
||||||
|
@ -2058,12 +2084,76 @@ class TinyLoopOfBasicallySameColor(PureColorMap):
|
||||||
self.play(ShowCreation(circle))
|
self.play(ShowCreation(circle))
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
|
def uhOhFunc((x, y)):
|
||||||
|
x = np.clip(x, -5, 5)/5
|
||||||
|
y = np.clip(y, -3, 3)/3
|
||||||
|
|
||||||
|
alpha = 0.5 # Most things will return green
|
||||||
|
|
||||||
|
# These next three things should really be abstracted into some "Interpolated triangle" function
|
||||||
|
|
||||||
|
if x >= 0 and y >= x and y <= 1:
|
||||||
|
alpha = interpolate(0.5, 1, y - x)
|
||||||
|
|
||||||
|
if x < 0 and y >= -2 * x and y <= 1:
|
||||||
|
alpha = interpolate(0.5, 1, y + 2 * x)
|
||||||
|
|
||||||
|
if x >= -1 and y >= 2 * (x + 1) and y <= 1:
|
||||||
|
alpha = interpolate(0.5, 0, y - 2 * (x + 1))
|
||||||
|
|
||||||
|
return complex_to_pair(100 * np.exp(complex(0, TAU * (0.5 - alpha))))
|
||||||
|
|
||||||
|
class UhOhFuncTest(PureColorMap):
|
||||||
|
CONFIG = {
|
||||||
|
"func" : uhOhFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class UhOhScene(EquationSolver2d):
|
class UhOhScene(EquationSolver2d):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
|
"func" : uhOhFunc,
|
||||||
|
"display_in_parallel" : True,
|
||||||
|
"manual_wind_override" : (1, (1, (1, None, None), None), None), # Tailored to UhOhFunc above
|
||||||
"show_winding_numbers" : False,
|
"show_winding_numbers" : False,
|
||||||
"replacement_background_image_file" : None
|
"num_iterations" : 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class UhOhSalientStill(ColorMappedObjectsScene):
|
||||||
|
CONFIG = {
|
||||||
|
"func" : uhOhFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
def construct(self):
|
||||||
|
ColorMappedObjectsScene.construct(self)
|
||||||
|
|
||||||
|
new_up = 3 * UP
|
||||||
|
new_left = 5 * LEFT
|
||||||
|
|
||||||
|
thin_line = Line(UP, RIGHT, color = WHITE)
|
||||||
|
|
||||||
|
main_points = [new_left + new_up, new_up, ORIGIN, new_left]
|
||||||
|
polygon = Polygon(*main_points, stroke_width = border_stroke_width)
|
||||||
|
thin_polygon = polygon.copy().match_style(thin_line)
|
||||||
|
polygon.color_using_background_image(self.background_image_file)
|
||||||
|
|
||||||
|
midline = Line(new_up + 0.5 * new_left, 0.5 * new_left, stroke_width = border_stroke_width)
|
||||||
|
thin_midline = midline.copy().match_style(thin_line)
|
||||||
|
midline.color_using_background_image(self.background_image_file)
|
||||||
|
|
||||||
|
self.add(polygon, midline)
|
||||||
|
|
||||||
|
self.wait()
|
||||||
|
|
||||||
|
everything_filler = FullScreenFadeRectangle(fill_opacity = 1)
|
||||||
|
everything_filler.color_using_background_image(self.background_image_file)
|
||||||
|
|
||||||
|
thin_white_copy = Group(thin_polygon, thin_midline)
|
||||||
|
|
||||||
|
self.play(FadeIn(everything_filler), FadeIn(thin_white_copy))
|
||||||
|
|
||||||
|
self.wait()
|
||||||
|
|
||||||
|
|
||||||
# TODO: Brouwer's fixed point theorem visuals
|
# TODO: Brouwer's fixed point theorem visuals
|
||||||
# class BFTScene(Scene):
|
# class BFTScene(Scene):
|
||||||
|
|
||||||
|
@ -2079,8 +2169,6 @@ class UhOhScene(EquationSolver2d):
|
||||||
|
|
||||||
# Writing new Pi walker scenes by parametrizing general template
|
# Writing new Pi walker scenes by parametrizing general template
|
||||||
|
|
||||||
# Domain coloring scenes by parametrizing general template
|
|
||||||
|
|
||||||
# (All the above are basically trivial tinkering at this point)
|
# (All the above are basically trivial tinkering at this point)
|
||||||
|
|
||||||
# ----
|
# ----
|
||||||
|
|
Loading…
Add table
Reference in a new issue