mirror of
https://github.com/3b1b/manim.git
synced 2025-09-01 00:48:45 +00:00
Incremental
This commit is contained in:
parent
0975f323db
commit
5a56e34435
1 changed files with 205 additions and 86 deletions
|
@ -42,6 +42,9 @@ border_stroke_width = 10
|
||||||
# Used for clockwise circling in some scenes
|
# Used for clockwise circling in some scenes
|
||||||
cw_circle = Circle(color = WHITE).stretch(-1, 0)
|
cw_circle = Circle(color = WHITE).stretch(-1, 0)
|
||||||
|
|
||||||
|
# Used when walker animations are on black backgrounds, in EquationSolver2d and PiWalker
|
||||||
|
WALKER_LIGHT_COLOR = DARK_GREY
|
||||||
|
|
||||||
# TODO/WARNING: There's a lot of refactoring and cleanup to be done in this code,
|
# TODO/WARNING: There's a lot of refactoring and cleanup to be done in this code,
|
||||||
# (and it will be done, but first I'll figure out what I'm doing with all this...)
|
# (and it will be done, but first I'll figure out what I'm doing with all this...)
|
||||||
# -SR
|
# -SR
|
||||||
|
@ -108,6 +111,7 @@ positive_color = rev_to_color(0)
|
||||||
negative_color = rev_to_color(0.5)
|
negative_color = rev_to_color(0.5)
|
||||||
neutral_color = rev_to_color(0.25)
|
neutral_color = rev_to_color(0.25)
|
||||||
|
|
||||||
|
# This, the first animation I made, has the messiest code, full of cruft, but so it goes
|
||||||
class EquationSolver1d(GraphScene, ZoomedScene):
|
class EquationSolver1d(GraphScene, ZoomedScene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"camera_config" :
|
"camera_config" :
|
||||||
|
@ -122,7 +126,9 @@ class EquationSolver1d(GraphScene, ZoomedScene):
|
||||||
"num_iterations" : 10,
|
"num_iterations" : 10,
|
||||||
"iteration_at_which_to_start_zoom" : None,
|
"iteration_at_which_to_start_zoom" : None,
|
||||||
"graph_label" : None,
|
"graph_label" : None,
|
||||||
"show_target_line" : True
|
"show_target_line" : True,
|
||||||
|
"base_line_y" : 0, # The y coordinate at which to draw our x guesses
|
||||||
|
"show_y_as_deviation" : False, # Displays y-values as deviations from target
|
||||||
}
|
}
|
||||||
|
|
||||||
def drawGraph(self):
|
def drawGraph(self):
|
||||||
|
@ -143,11 +149,14 @@ class EquationSolver1d(GraphScene, ZoomedScene):
|
||||||
dashed_segment_length = 0.1)
|
dashed_segment_length = 0.1)
|
||||||
self.add(target_line_object)
|
self.add(target_line_object)
|
||||||
|
|
||||||
target_line_label = TexMobject("y = " + str(self.targetY))
|
target_label_num = 0 if self.show_y_as_deviation else self.targetY
|
||||||
|
target_line_label = TexMobject("y = " + str(target_label_num))
|
||||||
target_line_label.next_to(target_line_object.get_left(), UP + RIGHT)
|
target_line_label.next_to(target_line_object.get_left(), UP + RIGHT)
|
||||||
self.add(target_line_label)
|
self.add(target_line_label)
|
||||||
|
|
||||||
self.wait() # Give us time to appreciate the graph
|
self.wait() # Give us time to appreciate the graph
|
||||||
|
|
||||||
|
if self.show_target_line:
|
||||||
self.play(FadeOut(target_line_label)) # Reduce clutter
|
self.play(FadeOut(target_line_label)) # Reduce clutter
|
||||||
|
|
||||||
print "For reference, graphOrigin: ", self.coords_to_point(0, 0)
|
print "For reference, graphOrigin: ", self.coords_to_point(0, 0)
|
||||||
|
@ -156,10 +165,30 @@ class EquationSolver1d(GraphScene, ZoomedScene):
|
||||||
# This is a mess right now (first major animation coded),
|
# This is a mess right now (first major animation coded),
|
||||||
# but it works; can be refactored later or never
|
# but it works; can be refactored later or never
|
||||||
def solveEquation(self):
|
def solveEquation(self):
|
||||||
startBrace = Dot() #TexMobject("[") # Not using [ and ] because they end up crossing over
|
# Under special conditions, used in GuaranteedZeroScene, we let the
|
||||||
startBrace.set_color(negative_color)
|
# "lower" guesses actually be too high, or vice versa, and color
|
||||||
endBrace = Dot()
|
# everything accordingly
|
||||||
endBrace.set_color(positive_color)
|
|
||||||
|
def color_by_comparison(val, ref):
|
||||||
|
if val > ref:
|
||||||
|
return positive_color
|
||||||
|
elif val < ref:
|
||||||
|
return negative_color
|
||||||
|
else:
|
||||||
|
return neutral_color
|
||||||
|
|
||||||
|
lower_color = color_by_comparison(self.func(self.initial_lower_x), self.targetY)
|
||||||
|
upper_color = color_by_comparison(self.func(self.initial_upper_x), self.targetY)
|
||||||
|
|
||||||
|
if self.show_y_as_deviation:
|
||||||
|
y_bias = -self.targetY
|
||||||
|
else:
|
||||||
|
y_bias = 0
|
||||||
|
|
||||||
|
startBrace = TexMobject("|", stroke_width = 10) #TexMobject("[") # Not using [ and ] because they end up crossing over
|
||||||
|
startBrace.set_color(lower_color)
|
||||||
|
endBrace = startBrace.copy().stretch(-1, 0)
|
||||||
|
endBrace.set_color(upper_color)
|
||||||
genericBraces = Group(startBrace, endBrace)
|
genericBraces = Group(startBrace, endBrace)
|
||||||
#genericBraces.scale(1.5)
|
#genericBraces.scale(1.5)
|
||||||
|
|
||||||
|
@ -177,7 +206,7 @@ class EquationSolver1d(GraphScene, ZoomedScene):
|
||||||
upperX = self.initial_upper_x
|
upperX = self.initial_upper_x
|
||||||
upperY = self.func(upperX)
|
upperY = self.func(upperX)
|
||||||
|
|
||||||
leftBrace.move_to(self.coords_to_point(lowerX, 0)) #, aligned_edge = RIGHT)
|
leftBrace.move_to(self.coords_to_point(lowerX, self.base_line_y)) #, aligned_edge = RIGHT)
|
||||||
leftBraceLabel = DecimalNumber(lowerX)
|
leftBraceLabel = DecimalNumber(lowerX)
|
||||||
leftBraceLabel.next_to(leftBrace, DOWN + LEFT, buff = SMALL_BUFF)
|
leftBraceLabel.next_to(leftBrace, DOWN + LEFT, buff = SMALL_BUFF)
|
||||||
leftBraceLabelAnimation = ContinualChangingDecimal(leftBraceLabel,
|
leftBraceLabelAnimation = ContinualChangingDecimal(leftBraceLabel,
|
||||||
|
@ -185,7 +214,7 @@ class EquationSolver1d(GraphScene, ZoomedScene):
|
||||||
tracked_mobject = leftBrace)
|
tracked_mobject = leftBrace)
|
||||||
self.add(leftBraceLabelAnimation)
|
self.add(leftBraceLabelAnimation)
|
||||||
|
|
||||||
rightBrace.move_to(self.coords_to_point(upperX, 0)) #, aligned_edge = LEFT)
|
rightBrace.move_to(self.coords_to_point(upperX, self.base_line_y)) #, aligned_edge = LEFT)
|
||||||
rightBraceLabel = DecimalNumber(upperX)
|
rightBraceLabel = DecimalNumber(upperX)
|
||||||
rightBraceLabel.next_to(rightBrace, DOWN + RIGHT, buff = SMALL_BUFF)
|
rightBraceLabel.next_to(rightBrace, DOWN + RIGHT, buff = SMALL_BUFF)
|
||||||
rightBraceLabelAnimation = ContinualChangingDecimal(rightBraceLabel,
|
rightBraceLabelAnimation = ContinualChangingDecimal(rightBraceLabel,
|
||||||
|
@ -197,7 +226,7 @@ class EquationSolver1d(GraphScene, ZoomedScene):
|
||||||
downBraceLabel = DecimalNumber(lowerY)
|
downBraceLabel = DecimalNumber(lowerY)
|
||||||
downBraceLabel.next_to(downBrace, LEFT + DOWN, buff = SMALL_BUFF)
|
downBraceLabel.next_to(downBrace, LEFT + DOWN, buff = SMALL_BUFF)
|
||||||
downBraceLabelAnimation = ContinualChangingDecimal(downBraceLabel,
|
downBraceLabelAnimation = ContinualChangingDecimal(downBraceLabel,
|
||||||
lambda alpha : self.point_to_coords(downBrace.get_center())[1],
|
lambda alpha : self.point_to_coords(downBrace.get_center())[1] + y_bias,
|
||||||
tracked_mobject = downBrace)
|
tracked_mobject = downBrace)
|
||||||
self.add(downBraceLabelAnimation)
|
self.add(downBraceLabelAnimation)
|
||||||
|
|
||||||
|
@ -205,28 +234,28 @@ class EquationSolver1d(GraphScene, ZoomedScene):
|
||||||
upBraceLabel = DecimalNumber(upperY)
|
upBraceLabel = DecimalNumber(upperY)
|
||||||
upBraceLabel.next_to(upBrace, LEFT + UP, buff = SMALL_BUFF)
|
upBraceLabel.next_to(upBrace, LEFT + UP, buff = SMALL_BUFF)
|
||||||
upBraceLabelAnimation = ContinualChangingDecimal(upBraceLabel,
|
upBraceLabelAnimation = ContinualChangingDecimal(upBraceLabel,
|
||||||
lambda alpha : self.point_to_coords(upBrace.get_center())[1],
|
lambda alpha : self.point_to_coords(upBrace.get_center())[1] + y_bias,
|
||||||
tracked_mobject = upBrace)
|
tracked_mobject = upBrace)
|
||||||
self.add(upBraceLabelAnimation)
|
self.add(upBraceLabelAnimation)
|
||||||
|
|
||||||
lowerDotPoint = self.input_to_graph_point(lowerX, self.graph)
|
lowerDotPoint = self.input_to_graph_point(lowerX, self.graph)
|
||||||
lowerDotXPoint = self.coords_to_point(lowerX, 0)
|
lowerDotXPoint = self.coords_to_point(lowerX, self.base_line_y)
|
||||||
lowerDotYPoint = self.coords_to_point(0, self.func(lowerX))
|
lowerDotYPoint = self.coords_to_point(0, self.func(lowerX))
|
||||||
lowerDot = Dot(lowerDotPoint + OUT, color = negative_color)
|
lowerDot = Dot(lowerDotPoint + OUT, color = lower_color)
|
||||||
upperDotPoint = self.input_to_graph_point(upperX, self.graph)
|
upperDotPoint = self.input_to_graph_point(upperX, self.graph)
|
||||||
upperDot = Dot(upperDotPoint + OUT, color = positive_color)
|
upperDot = Dot(upperDotPoint + OUT, color = upper_color)
|
||||||
upperDotXPoint = self.coords_to_point(upperX, 0)
|
upperDotXPoint = self.coords_to_point(upperX, self.base_line_y)
|
||||||
upperDotYPoint = self.coords_to_point(0, self.func(upperX))
|
upperDotYPoint = self.coords_to_point(0, self.func(upperX))
|
||||||
|
|
||||||
lowerXLine = Line(lowerDotXPoint, lowerDotPoint, color = negative_color)
|
lowerXLine = Line(lowerDotXPoint, lowerDotPoint, color = lower_color)
|
||||||
upperXLine = Line(upperDotXPoint, upperDotPoint, color = positive_color)
|
upperXLine = Line(upperDotXPoint, upperDotPoint, color = upper_color)
|
||||||
lowerYLine = Line(lowerDotYPoint, lowerDotPoint, color = negative_color)
|
lowerYLine = Line(lowerDotYPoint, lowerDotPoint, color = lower_color)
|
||||||
upperYLine = Line(upperDotYPoint, upperDotPoint, color = positive_color)
|
upperYLine = Line(upperDotYPoint, upperDotPoint, color = upper_color)
|
||||||
self.add(lowerXLine, upperXLine, lowerYLine, upperYLine)
|
self.add(lowerXLine, upperXLine, lowerYLine, upperYLine)
|
||||||
|
|
||||||
self.add(xBraces, yBraces, lowerDot, upperDot)
|
self.add_foreground_mobjects(xBraces, yBraces, lowerDot, upperDot)
|
||||||
|
|
||||||
x_guess_line = Line(lowerDotXPoint, upperDotXPoint, color = neutral_color)
|
x_guess_line = Line(lowerDotXPoint, upperDotXPoint, color = WHITE, stroke_width = 10)
|
||||||
self.add(x_guess_line)
|
self.add(x_guess_line)
|
||||||
|
|
||||||
lowerGroup = Group(
|
lowerGroup = Group(
|
||||||
|
@ -243,11 +272,11 @@ class EquationSolver1d(GraphScene, ZoomedScene):
|
||||||
x_guess_line
|
x_guess_line
|
||||||
)
|
)
|
||||||
|
|
||||||
initialLowerXDot = Dot(lowerDotXPoint, color = negative_color)
|
initialLowerXDot = Dot(lowerDotXPoint + OUT, color = lower_color)
|
||||||
initialUpperXDot = Dot(upperDotXPoint, color = positive_color)
|
initialUpperXDot = Dot(upperDotXPoint + OUT, color = upper_color)
|
||||||
initialLowerYDot = Dot(lowerDotYPoint, color = negative_color)
|
initialLowerYDot = Dot(lowerDotYPoint + OUT, color = lower_color)
|
||||||
initialUpperYDot = Dot(upperDotYPoint, color = positive_color)
|
initialUpperYDot = Dot(upperDotYPoint + OUT, color = upper_color)
|
||||||
self.add(initialLowerXDot, initialUpperXDot, initialLowerYDot, initialUpperYDot)
|
self.add_foreground_mobjects(initialLowerXDot, initialUpperXDot, initialLowerYDot, initialUpperYDot)
|
||||||
|
|
||||||
for i in range(self.num_iterations):
|
for i in range(self.num_iterations):
|
||||||
if i == self.iteration_at_which_to_start_zoom:
|
if i == self.iteration_at_which_to_start_zoom:
|
||||||
|
@ -268,26 +297,36 @@ class EquationSolver1d(GraphScene, ZoomedScene):
|
||||||
graphPoint = self.input_to_graph_point(newX,
|
graphPoint = self.input_to_graph_point(newX,
|
||||||
self.graph)
|
self.graph)
|
||||||
dot.move_to(graphPoint)
|
dot.move_to(graphPoint)
|
||||||
xAxisPoint = self.coords_to_point(newX, 0)
|
xAxisPoint = self.coords_to_point(newX, self.base_line_y)
|
||||||
xBrace.move_to(xAxisPoint)
|
xBrace.move_to(xAxisPoint)
|
||||||
yAxisPoint = self.coords_to_point(0, newY)
|
yAxisPoint = self.coords_to_point(0, newY)
|
||||||
yBrace.move_to(yAxisPoint)
|
yBrace.move_to(yAxisPoint)
|
||||||
xLine.put_start_and_end_on(xAxisPoint, graphPoint)
|
xLine.put_start_and_end_on(xAxisPoint, graphPoint)
|
||||||
yLine.put_start_and_end_on(yAxisPoint, graphPoint)
|
yLine.put_start_and_end_on(yAxisPoint, graphPoint)
|
||||||
fixed_guess_point = self.coords_to_point(fixed_guess_x, 0)
|
fixed_guess_point = self.coords_to_point(fixed_guess_x, self.base_line_y)
|
||||||
guess_line.put_start_and_end_on(xAxisPoint, fixed_guess_point)
|
guess_line.put_start_and_end_on(xAxisPoint, fixed_guess_point)
|
||||||
return group
|
return group
|
||||||
return updater
|
return updater
|
||||||
|
|
||||||
midX = (lowerX + upperX)/float(2)
|
midX = (lowerX + upperX)/float(2)
|
||||||
midY = self.func(midX)
|
midY = self.func(midX)
|
||||||
|
|
||||||
|
# If we run with an interval whose endpoints start off with same sign,
|
||||||
|
# then nothing after this branching can be trusted to do anything reasonable
|
||||||
|
# in terms of picking branches or assigning colors
|
||||||
in_negative_branch = midY < self.targetY
|
in_negative_branch = midY < self.targetY
|
||||||
sign_color = negative_color if in_negative_branch else positive_color
|
sign_color = negative_color if in_negative_branch else positive_color
|
||||||
|
|
||||||
midCoords = self.coords_to_point(midX, midY)
|
midCoords = self.coords_to_point(midX, midY)
|
||||||
midColor = neutral_color
|
midColor = neutral_color
|
||||||
# Hm... even the z buffer isn't helping keep this above x_guess_line
|
# Hm... even the z buffer isn't helping keep this above x_guess_line
|
||||||
midXPoint = Dot(self.coords_to_point(midX, 0) + OUT, color = midColor)
|
|
||||||
|
midXBrace = startBrace.copy() # Had start and endBrace been asymmetric, we'd do something different here
|
||||||
|
midXBrace.set_color(midColor)
|
||||||
|
midXBrace.move_to(self.coords_to_point(midX, self.base_line_y) + OUT)
|
||||||
|
|
||||||
|
# We only actually add this much later
|
||||||
|
midXPoint = Dot(self.coords_to_point(midX, self.base_line_y) + OUT, color = sign_color)
|
||||||
|
|
||||||
x_guess_label_caption = TextMobject("New guess: x = ", fill_color = midColor)
|
x_guess_label_caption = TextMobject("New guess: x = ", fill_color = midColor)
|
||||||
x_guess_label_num = DecimalNumber(midX, fill_color = midColor)
|
x_guess_label_num = DecimalNumber(midX, fill_color = midColor)
|
||||||
|
@ -302,11 +341,17 @@ class EquationSolver1d(GraphScene, ZoomedScene):
|
||||||
guess_labels = Group(x_guess_label, y_guess_label)
|
guess_labels = Group(x_guess_label, y_guess_label)
|
||||||
|
|
||||||
self.play(
|
self.play(
|
||||||
ReplacementTransform(leftBrace.copy(), midXPoint),
|
ReplacementTransform(leftBrace.copy(), midXBrace),
|
||||||
ReplacementTransform(rightBrace.copy(), midXPoint),
|
ReplacementTransform(rightBrace.copy(), midXBrace),
|
||||||
FadeIn(x_guess_label))
|
FadeIn(x_guess_label))
|
||||||
|
|
||||||
midXLine = DashedLine(self.coords_to_point(midX, 0), midCoords, color = midColor)
|
self.add_foreground_mobject(midXBrace)
|
||||||
|
|
||||||
|
midXLine = DashedLine(
|
||||||
|
self.coords_to_point(midX, self.base_line_y),
|
||||||
|
midCoords,
|
||||||
|
color = midColor
|
||||||
|
)
|
||||||
self.play(ShowCreation(midXLine))
|
self.play(ShowCreation(midXLine))
|
||||||
midDot = Dot(midCoords, color = sign_color)
|
midDot = Dot(midCoords, color = sign_color)
|
||||||
if(self.iteration_at_which_to_start_zoom != None and
|
if(self.iteration_at_which_to_start_zoom != None and
|
||||||
|
@ -317,10 +362,12 @@ class EquationSolver1d(GraphScene, ZoomedScene):
|
||||||
self.play(
|
self.play(
|
||||||
ShowCreation(midYLine),
|
ShowCreation(midYLine),
|
||||||
FadeIn(y_guess_label),
|
FadeIn(y_guess_label),
|
||||||
ApplyMethod(midXPoint.set_color, sign_color),
|
ApplyMethod(midXBrace.set_color, sign_color),
|
||||||
ApplyMethod(midXLine.set_color, sign_color))
|
ApplyMethod(midXLine.set_color, sign_color),
|
||||||
|
run_time = 0.25
|
||||||
|
)
|
||||||
midYPoint = Dot(self.coords_to_point(0, midY), color = sign_color)
|
midYPoint = Dot(self.coords_to_point(0, midY), color = sign_color)
|
||||||
self.add(midYPoint)
|
self.add(midXPoint, midYPoint)
|
||||||
|
|
||||||
if in_negative_branch:
|
if in_negative_branch:
|
||||||
self.play(
|
self.play(
|
||||||
|
@ -346,7 +393,7 @@ class EquationSolver1d(GraphScene, ZoomedScene):
|
||||||
upperX = midX
|
upperX = midX
|
||||||
upperY = midY
|
upperY = midY
|
||||||
#mid_group = Group(midXLine, midDot, midYLine) Removing groups doesn't flatten as expected?
|
#mid_group = Group(midXLine, midDot, midYLine) Removing groups doesn't flatten as expected?
|
||||||
self.remove(midXLine, midDot, midYLine)
|
self.remove(midXLine, midDot, midYLine, midXBrace)
|
||||||
|
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
|
@ -464,6 +511,9 @@ def point3d_func_from_plane_func(f):
|
||||||
return np.array((f_val[0], f_val[1], 0))
|
return np.array((f_val[0], f_val[1], 0))
|
||||||
return g
|
return g
|
||||||
|
|
||||||
|
def point3d_func_from_complex_func(f):
|
||||||
|
return point3d_func_from_plane_func(plane_func_from_complex_func(f))
|
||||||
|
|
||||||
# Returns a function from 2-ples to 2-ples
|
# Returns a function from 2-ples to 2-ples
|
||||||
# This function is specified by a list of (x, y, z) tuples,
|
# This function is specified by a list of (x, y, z) tuples,
|
||||||
# and has winding number z (or total of all specified z) around each (x, y)
|
# and has winding number z (or total of all specified z) around each (x, y)
|
||||||
|
@ -493,7 +543,7 @@ def plane_func_by_wind_spec(*specs):
|
||||||
return plane_func_from_complex_func(complex_func)
|
return plane_func_from_complex_func(complex_func)
|
||||||
|
|
||||||
# Used in Initial2dFunc scenes, VectorField scene, and ExamplePlaneFunc
|
# Used in Initial2dFunc scenes, VectorField scene, and ExamplePlaneFunc
|
||||||
example_plane_func_spec = [(1.1, 1, 1), (-3, -1.3, 2), (2.8, -2, -1)]
|
example_plane_func_spec = [(-3, -1.3, 2), (0.1, 0.2, 1), (2.8, -2, -1)]
|
||||||
example_plane_func = plane_func_by_wind_spec(*example_plane_func_spec)
|
example_plane_func = plane_func_by_wind_spec(*example_plane_func_spec)
|
||||||
|
|
||||||
empty_animation = EmptyAnimation()
|
empty_animation = EmptyAnimation()
|
||||||
|
@ -619,7 +669,9 @@ class ColorMappedByFuncScene(Scene):
|
||||||
"num_plane" : NumberPlane(),
|
"num_plane" : NumberPlane(),
|
||||||
"show_num_plane" : True,
|
"show_num_plane" : True,
|
||||||
|
|
||||||
"show_output" : False
|
"show_output" : False,
|
||||||
|
|
||||||
|
"hide_background" : False #Background used for color mapped objects, not as background
|
||||||
}
|
}
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
|
@ -675,7 +727,12 @@ class ColorMappedByFuncScene(Scene):
|
||||||
|
|
||||||
self.save_image(self.background_image_file, mode = "RGBA")
|
self.save_image(self.background_image_file, mode = "RGBA")
|
||||||
|
|
||||||
self.camera.background_image = self.background_image_file
|
if self.hide_background:
|
||||||
|
# Clearing background
|
||||||
|
self.camera.background_image = None
|
||||||
|
else:
|
||||||
|
# Even if we just computed the background, we switch to the file now
|
||||||
|
self.camera.background_image = self.background_image_file
|
||||||
self.camera.init_background()
|
self.camera.init_background()
|
||||||
|
|
||||||
if self.show_num_plane:
|
if self.show_num_plane:
|
||||||
|
@ -694,16 +751,10 @@ class PureColorMap(ColorMappedByFuncScene):
|
||||||
# This sets self.background_image_file, but does not display it as the background
|
# This sets self.background_image_file, but does not display it as the background
|
||||||
class ColorMappedObjectsScene(ColorMappedByFuncScene):
|
class ColorMappedObjectsScene(ColorMappedByFuncScene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"show_num_plane" : False
|
"show_num_plane" : False,
|
||||||
|
"hide_background" : True,
|
||||||
}
|
}
|
||||||
|
|
||||||
def construct(self):
|
|
||||||
ColorMappedByFuncScene.construct(self)
|
|
||||||
|
|
||||||
# Clearing background
|
|
||||||
self.camera.background_image = None
|
|
||||||
self.camera.init_background()
|
|
||||||
|
|
||||||
class PiWalker(ColorMappedByFuncScene):
|
class PiWalker(ColorMappedByFuncScene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"walk_coords" : [],
|
"walk_coords" : [],
|
||||||
|
@ -759,7 +810,7 @@ class PiWalker(ColorMappedByFuncScene):
|
||||||
scale_arrows = self.scale_arrows,
|
scale_arrows = self.scale_arrows,
|
||||||
number_update_func = number_update_func,
|
number_update_func = number_update_func,
|
||||||
run_time = self.step_run_time,
|
run_time = self.step_run_time,
|
||||||
walker_stroke_color = DARK_GREY if self.color_foreground_not_background else BLACK
|
walker_stroke_color = WALKER_LIGHT_COLOR if self.color_foreground_not_background else BLACK
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.display_odometer:
|
if self.display_odometer:
|
||||||
|
@ -851,7 +902,7 @@ class EquationSolver2d(ColorMappedObjectsScene):
|
||||||
|
|
||||||
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 = RED)
|
base_line = Line(UP, RIGHT, stroke_width = border_stroke_width, color = WHITE)
|
||||||
|
|
||||||
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
|
||||||
|
@ -881,7 +932,7 @@ class EquationSolver2d(ColorMappedObjectsScene):
|
||||||
val_func = self.func,
|
val_func = self.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 = WHITE,
|
walker_stroke_color = WALKER_LIGHT_COLOR,
|
||||||
|
|
||||||
show_arrows = self.show_arrows,
|
show_arrows = self.show_arrows,
|
||||||
scale_arrows = self.scale_arrows,
|
scale_arrows = self.scale_arrows,
|
||||||
|
@ -1153,27 +1204,43 @@ class FirstSqrtScene(EquationSolver1d):
|
||||||
"targetY" : 2,
|
"targetY" : 2,
|
||||||
"initial_lower_x" : 1,
|
"initial_lower_x" : 1,
|
||||||
"initial_upper_x" : 2,
|
"initial_upper_x" : 2,
|
||||||
"num_iterations" : 3,
|
"num_iterations" : 5,
|
||||||
"iteration_at_which_to_start_zoom" : 3,
|
"iteration_at_which_to_start_zoom" : 3,
|
||||||
"graph_label" : "y = x^2",
|
"graph_label" : "y = x^2",
|
||||||
"show_target_line" : True,
|
"show_target_line" : True,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TestFirstSqrtScene(FirstSqrtScene):
|
||||||
|
CONFIG = {
|
||||||
|
"num_iterations" : 1,
|
||||||
|
}
|
||||||
|
|
||||||
FirstSqrtSceneConfig = FirstSqrtScene.CONFIG
|
FirstSqrtSceneConfig = FirstSqrtScene.CONFIG
|
||||||
shiftVal = FirstSqrtSceneConfig["targetY"]
|
shiftVal = FirstSqrtSceneConfig["targetY"]
|
||||||
|
|
||||||
class SecondSqrtScene(FirstSqrtScene):
|
class SecondSqrtScene(FirstSqrtScene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"func" : lambda x : FirstSqrtSceneConfig["func"](x) - shiftVal,
|
|
||||||
"targetY" : 0,
|
|
||||||
"graph_label" : FirstSqrtSceneConfig["graph_label"] + " - " + str(shiftVal),
|
"graph_label" : FirstSqrtSceneConfig["graph_label"] + " - " + str(shiftVal),
|
||||||
"y_min" : FirstSqrtSceneConfig["y_min"] - shiftVal,
|
"show_y_as_deviation" : True,
|
||||||
"y_max" : FirstSqrtSceneConfig["y_max"] - shiftVal,
|
|
||||||
"show_target_line" : False,
|
|
||||||
# 0.96 hacked in by checking calculations above
|
|
||||||
"graph_origin" : 0.96 * shiftVal * UP + FirstSqrtSceneConfig["graph_origin"],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TestSecondSqrtScene(SecondSqrtScene):
|
||||||
|
CONFIG = {
|
||||||
|
"num_iterations" : 1
|
||||||
|
}
|
||||||
|
|
||||||
|
class GuaranteedZeroScene(SecondSqrtScene):
|
||||||
|
CONFIG = {
|
||||||
|
# Manual config values, not automatically synced to anything above
|
||||||
|
"initial_lower_x" : 1.75,
|
||||||
|
"initial_upper_x" : 2
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestGuaranteedZeroScene(GuaranteedZeroScene):
|
||||||
|
CONFIG = {
|
||||||
|
"num_iterations" : 1
|
||||||
|
}
|
||||||
|
|
||||||
# TODO: Pi creatures intrigued
|
# TODO: Pi creatures intrigued
|
||||||
|
|
||||||
class RewriteEquation(Scene):
|
class RewriteEquation(Scene):
|
||||||
|
@ -1292,6 +1359,9 @@ class VectorField(Scene):
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
class HasItsLimitations(Scene):
|
class HasItsLimitations(Scene):
|
||||||
|
CONFIG = {
|
||||||
|
"camera_config" : {"use_z_coordinate_for_display_order": True},
|
||||||
|
}
|
||||||
|
|
||||||
def construct(self):
|
def construct(self):
|
||||||
num_line = NumberLine()
|
num_line = NumberLine()
|
||||||
|
@ -1305,11 +1375,19 @@ class HasItsLimitations(Scene):
|
||||||
|
|
||||||
dot_color = ORANGE
|
dot_color = ORANGE
|
||||||
|
|
||||||
input_dot = Dot(base_point, color = dot_color)
|
DOT_Z = OUT
|
||||||
|
# Note: This z-buffer value is needed for our static scenes, but is
|
||||||
|
# not sufficient for everything, in that we still need to use
|
||||||
|
# the foreground_mobjects trick during animations.
|
||||||
|
# At some point, we should figure out how to have animations
|
||||||
|
# play well with z coordinates.
|
||||||
|
|
||||||
|
input_dot = Dot(base_point + DOT_Z, color = dot_color)
|
||||||
input_label = TexMobject("Input", fill_color = dot_color)
|
input_label = TexMobject("Input", fill_color = dot_color)
|
||||||
input_label.next_to(input_dot, UP + LEFT)
|
input_label.next_to(input_dot, UP + LEFT)
|
||||||
input_label.add_background_rectangle()
|
input_label.add_background_rectangle()
|
||||||
self.add(input_dot, input_label)
|
self.add_foreground_mobject(input_dot)
|
||||||
|
self.add(input_label)
|
||||||
|
|
||||||
curved_arrow = Arc(0, color = MAROON_E)
|
curved_arrow = Arc(0, color = MAROON_E)
|
||||||
curved_arrow.set_bound_angles(np.pi, 0)
|
curved_arrow.set_bound_angles(np.pi, 0)
|
||||||
|
@ -1319,12 +1397,13 @@ class HasItsLimitations(Scene):
|
||||||
# Could do something smoother, with arrowhead moving along partial arc?
|
# Could do something smoother, with arrowhead moving along partial arc?
|
||||||
self.play(ShowCreation(curved_arrow))
|
self.play(ShowCreation(curved_arrow))
|
||||||
|
|
||||||
output_dot = Dot(base_point + 2 * RIGHT, color = dot_color)
|
output_dot = Dot(base_point + 2 * RIGHT + DOT_Z, color = dot_color)
|
||||||
output_label = TexMobject("Output", fill_color = dot_color)
|
output_label = TexMobject("Output", fill_color = dot_color)
|
||||||
output_label.next_to(output_dot, UP + RIGHT)
|
output_label.next_to(output_dot, UP + RIGHT)
|
||||||
output_label.add_background_rectangle()
|
output_label.add_background_rectangle()
|
||||||
|
|
||||||
self.add(output_dot, output_label)
|
self.add_foreground_mobject(output_dot)
|
||||||
|
self.add(output_label)
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
num_plane = NumberPlane()
|
num_plane = NumberPlane()
|
||||||
|
@ -1429,7 +1508,11 @@ class NumberLineScene(Scene):
|
||||||
|
|
||||||
class Initial2dFuncSceneBase(Scene):
|
class Initial2dFuncSceneBase(Scene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"func" : point3d_func_from_plane_func(example_plane_func)
|
"func" : point3d_func_from_complex_func(lambda c : c**2 - c**3/5 + 1)
|
||||||
|
# We don't use example_plane_func because, unfortunately, the sort of examples
|
||||||
|
# which are good for demonstrating our color mapping haven't turned out to be
|
||||||
|
# good for visualizing in this manner; the gridlines run over themselves multiple
|
||||||
|
# times in too confusing a fashion
|
||||||
}
|
}
|
||||||
|
|
||||||
def show_planes(self):
|
def show_planes(self):
|
||||||
|
@ -1441,12 +1524,15 @@ class Initial2dFuncSceneBase(Scene):
|
||||||
line = Line(points[i], points[i + 1], color = RED)
|
line = Line(points[i], points[i + 1], color = RED)
|
||||||
self.obj_draw(line)
|
self.obj_draw(line)
|
||||||
|
|
||||||
# def wiggle_around(point):
|
def wiggle_around(point):
|
||||||
# radius = 0.2
|
radius = 0.2
|
||||||
# small_circle = Circle(radius = radius)
|
small_circle = cw_circle.copy()
|
||||||
# small_
|
small_circle.scale(radius)
|
||||||
|
small_circle.move_to(point + radius * RIGHT)
|
||||||
|
small_circle.set_color(RED)
|
||||||
|
self.obj_draw(small_circle)
|
||||||
|
|
||||||
# wiggle_around(points[-1])
|
wiggle_around(points[-1])
|
||||||
|
|
||||||
def obj_draw(self, input_object):
|
def obj_draw(self, input_object):
|
||||||
self.play(ShowCreation(input_object))
|
self.play(ShowCreation(input_object))
|
||||||
|
@ -1556,10 +1642,11 @@ class DemonstrateColorMapping(ColorMappedObjectsScene):
|
||||||
# (Just set up an OdometerScene with function matching the walking of the Pi
|
# (Just set up an OdometerScene with function matching the walking of the Pi
|
||||||
# creature from previous scene, then place it as a simultaneous inset with Premiere)
|
# creature from previous scene, then place it as a simultaneous inset with Premiere)
|
||||||
|
|
||||||
class LoopSplitScene(Scene):
|
class LoopSplitScene(ColorMappedObjectsScene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
# TODO: Change this to something more colorful down the midline
|
# TODO: Change this to something more colorful down the midline
|
||||||
"output_func" : plane_func_by_wind_spec((1.1, 1.1, 1), (-3.1, -1.3, 2), (2.8, -2.1, -1))
|
"func" : plane_func_by_wind_spec((0.1/2, 1.1/2, 1), (-4.1/2, -1.3/2, 2), (1.8/2, -2.1/2, -1)),
|
||||||
|
"use_fancy_lines" : True,
|
||||||
}
|
}
|
||||||
|
|
||||||
def PulsedLine(self,
|
def PulsedLine(self,
|
||||||
|
@ -1569,16 +1656,20 @@ class LoopSplitScene(Scene):
|
||||||
pulse_time = 1,
|
pulse_time = 1,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
line = Line(start, end, **kwargs)
|
line = Line(start, end, **kwargs)
|
||||||
|
if self.use_fancy_lines:
|
||||||
|
line.color_using_background_image(self.background_image_file)
|
||||||
anim = LinePulser(
|
anim = LinePulser(
|
||||||
line = line,
|
line = line,
|
||||||
bullet_template = bullet_template,
|
bullet_template = bullet_template,
|
||||||
num_bullets = num_bullets,
|
num_bullets = num_bullets,
|
||||||
pulse_time = pulse_time,
|
pulse_time = pulse_time,
|
||||||
output_func = self.output_func,
|
output_func = self.func,
|
||||||
**kwargs)
|
**kwargs)
|
||||||
return [VGroup(line, *anim.bullets), anim]
|
return [VGroup(line, *anim.bullets), anim]
|
||||||
|
|
||||||
def construct(self):
|
def construct(self):
|
||||||
|
ColorMappedObjectsScene.construct(self)
|
||||||
|
|
||||||
scale_factor = 2
|
scale_factor = 2
|
||||||
shift_term = 0
|
shift_term = 0
|
||||||
|
|
||||||
|
@ -1594,7 +1685,7 @@ class LoopSplitScene(Scene):
|
||||||
bl = scale_factor * (DOWN + LEFT) + shift_term
|
bl = scale_factor * (DOWN + LEFT) + shift_term
|
||||||
lm = scale_factor * LEFT + shift_term
|
lm = scale_factor * LEFT + shift_term
|
||||||
|
|
||||||
loop_color = BLUE
|
loop_color = WHITE
|
||||||
|
|
||||||
default_bullet = PiCreature(color = RED)
|
default_bullet = PiCreature(color = RED)
|
||||||
default_bullet.scale(0.15)
|
default_bullet.scale(0.15)
|
||||||
|
@ -1605,10 +1696,10 @@ class LoopSplitScene(Scene):
|
||||||
def SGroup(*args):
|
def SGroup(*args):
|
||||||
return VGroup(*[arg[0] for arg in args])
|
return VGroup(*[arg[0] for arg in args])
|
||||||
|
|
||||||
top_line = self.PulsedLine(tl, tr, default_bullet, color = BLUE)
|
top_line = self.PulsedLine(tl, tr, default_bullet, color = loop_color)
|
||||||
right_line = self.PulsedLine(tr, br, modified_bullet, color = BLUE)
|
right_line = self.PulsedLine(tr, br, modified_bullet, color = loop_color)
|
||||||
bottom_line = self.PulsedLine(br, bl, default_bullet, color = BLUE)
|
bottom_line = self.PulsedLine(br, bl, default_bullet, color = loop_color)
|
||||||
left_line = self.PulsedLine(bl, tl, default_bullet, color = BLUE)
|
left_line = self.PulsedLine(bl, tl, default_bullet, color = loop_color)
|
||||||
line_list = [top_line, right_line, bottom_line, left_line]
|
line_list = [top_line, right_line, bottom_line, left_line]
|
||||||
loop = SGroup(*line_list)
|
loop = SGroup(*line_list)
|
||||||
for line in line_list:
|
for line in line_list:
|
||||||
|
@ -1616,7 +1707,11 @@ class LoopSplitScene(Scene):
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
# Splits in middle
|
# Splits in middle
|
||||||
split_line = DashedLine(interpolate(tl, tr, 0.5), interpolate(bl, br, 0.5))
|
if self.use_fancy_lines:
|
||||||
|
split_line = Line(tm, bm)
|
||||||
|
split_line.color_using_background_image(self.background_image_file)
|
||||||
|
else:
|
||||||
|
split_line = DashedLine(tm, bm)
|
||||||
self.play(ShowCreation(split_line))
|
self.play(ShowCreation(split_line))
|
||||||
|
|
||||||
self.remove(*split_line)
|
self.remove(*split_line)
|
||||||
|
@ -1893,20 +1988,25 @@ class ExamplePlaneFunc(ColorMappedByFuncScene):
|
||||||
|
|
||||||
radius = 0.5
|
radius = 0.5
|
||||||
|
|
||||||
|
def circle_point(point):
|
||||||
|
circle = cw_circle.copy().scale(radius).move_to(point)
|
||||||
|
self.play(ShowCreation(circle))
|
||||||
|
return circle
|
||||||
|
|
||||||
|
def circle_spec(spec):
|
||||||
|
point = spec[0] * RIGHT + spec[1] * UP
|
||||||
|
return circle_point(point)
|
||||||
|
|
||||||
nonzero_point = ORIGIN # Manually chosen, not auto-synced with example_plane_func
|
nonzero_point = ORIGIN # Manually chosen, not auto-synced with example_plane_func
|
||||||
nonzero_point_circle = cw_circle.copy().scale(radius).move_to(nonzero_point)
|
nonzero_point_circle = circle_point(nonzero_point)
|
||||||
self.play(ShowCreation(red_point_circle))
|
|
||||||
self.wait()
|
self.wait()
|
||||||
self.play(FadeOut(red_point_circle))
|
self.play(FadeOut(nonzero_point_circle))
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
zero_circles = Group()
|
zero_circles = Group()
|
||||||
for spec in example_plane_func_spec:
|
|
||||||
point = spec[0] * RIGHT + spec[1] * UP
|
|
||||||
|
|
||||||
circle = cw_circle.copy().scale(radius).move_to(point)
|
for spec in example_plane_func_spec:
|
||||||
self.play(ShowCreation(circle))
|
zero_circles.add(circle_spec(spec))
|
||||||
zero_circles.add(circle)
|
|
||||||
|
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
|
@ -1916,7 +2016,20 @@ class ExamplePlaneFunc(ColorMappedByFuncScene):
|
||||||
# solely through Fade.
|
# solely through Fade.
|
||||||
#
|
#
|
||||||
# But for now, I'll just take care of this stuff myself here.
|
# But for now, I'll just take care of this stuff myself here.
|
||||||
self.play(*[FadeOut(zero_circle) for zero_circle in zero_circles])
|
# self.play(*[FadeOut(zero_circle) for zero_circle in zero_circles])
|
||||||
|
self.play(FadeOut(zero_circles))
|
||||||
|
self.wait()
|
||||||
|
|
||||||
|
# We can reuse our nonzero point from before for "Output doesn't go through ever color"
|
||||||
|
# Do re-use in Premiere
|
||||||
|
|
||||||
|
# We can also re-use the first of our zero-circles for "Output does go through every color",
|
||||||
|
# but just in case it would be useful, here's another one, all on its own
|
||||||
|
|
||||||
|
specific_spec_index = 0
|
||||||
|
temp_circle = circle_spec(example_plane_func_spec[specific_spec_index])
|
||||||
|
self.play(FadeOut(temp_circle))
|
||||||
|
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
class PiWalkerExamplePlaneFunc(PiWalkerRect):
|
class PiWalkerExamplePlaneFunc(PiWalkerRect):
|
||||||
|
@ -1945,6 +2058,12 @@ class TinyLoopOfBasicallySameColor(PureColorMap):
|
||||||
self.play(ShowCreation(circle))
|
self.play(ShowCreation(circle))
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
|
class UhOhScene(EquationSolver2d):
|
||||||
|
CONFIG = {
|
||||||
|
"show_winding_numbers" : False,
|
||||||
|
"replacement_background_image_file" : None
|
||||||
|
}
|
||||||
|
|
||||||
# TODO: Brouwer's fixed point theorem visuals
|
# TODO: Brouwer's fixed point theorem visuals
|
||||||
# class BFTScene(Scene):
|
# class BFTScene(Scene):
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue