mirror of
https://github.com/3b1b/manim.git
synced 2025-08-20 05:14:12 +00:00
Incremental
This commit is contained in:
parent
24dacb4b07
commit
f84eeda546
2 changed files with 148 additions and 38 deletions
|
@ -52,8 +52,10 @@ class EquationSolver1d(GraphScene, ZoomedScene):
|
||||||
self.add(self.graph)
|
self.add(self.graph)
|
||||||
|
|
||||||
if self.graph_label != None:
|
if self.graph_label != None:
|
||||||
self.add(self.get_graph_label(self.graph, self.graph_label,
|
curve_label = self.get_graph_label(self.graph, self.graph_label,
|
||||||
x_val = 4, direction = RIGHT))
|
x_val = 4, direction = LEFT)
|
||||||
|
curve_label.shift(LEFT)
|
||||||
|
self.add(curve_label)
|
||||||
|
|
||||||
if self.show_target_line:
|
if self.show_target_line:
|
||||||
target_line_object = DashedLine(
|
target_line_object = DashedLine(
|
||||||
|
@ -66,14 +68,20 @@ class EquationSolver1d(GraphScene, ZoomedScene):
|
||||||
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.play(FadeOut(target_line_label)) # Reduce clutter
|
||||||
|
|
||||||
|
print "For reference, graphOrigin: ", self.coords_to_point(0, 0)
|
||||||
|
print "targetYPoint: ", self.coords_to_point(0, self.targetY)
|
||||||
|
|
||||||
def solveEquation(self):
|
def solveEquation(self):
|
||||||
leftBrace = TexMobject("[")
|
leftBrace = TexMobject("|") # Not using [ and ] because they end up crossing over
|
||||||
rightBrace = TexMobject("]")
|
rightBrace = TexMobject("|")
|
||||||
xBraces = Group(leftBrace, rightBrace)
|
xBraces = Group(leftBrace, rightBrace)
|
||||||
xBraces.stretch(2, 0)
|
xBraces.stretch(2, 0)
|
||||||
|
|
||||||
downBrace = TexMobject("[")
|
downBrace = TexMobject("|")
|
||||||
upBrace = TexMobject("]")
|
upBrace = TexMobject("|")
|
||||||
yBraces = Group(downBrace, upBrace)
|
yBraces = Group(downBrace, upBrace)
|
||||||
yBraces.stretch(2, 0)
|
yBraces.stretch(2, 0)
|
||||||
yBraces.rotate(TAU/4)
|
yBraces.rotate(TAU/4)
|
||||||
|
@ -83,7 +91,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 = LEFT)
|
leftBrace.move_to(self.coords_to_point(lowerX, 0)) #, 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,
|
||||||
|
@ -91,7 +99,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 = RIGHT)
|
rightBrace.move_to(self.coords_to_point(upperX, 0)) #, 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,
|
||||||
|
@ -99,7 +107,7 @@ class EquationSolver1d(GraphScene, ZoomedScene):
|
||||||
tracked_mobject = rightBrace)
|
tracked_mobject = rightBrace)
|
||||||
self.add(rightBraceLabelAnimation)
|
self.add(rightBraceLabelAnimation)
|
||||||
|
|
||||||
downBrace.move_to(self.coords_to_point(0, lowerY), aligned_edge = DOWN)
|
downBrace.move_to(self.coords_to_point(0, lowerY)) #, aligned_edge = UP)
|
||||||
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,
|
||||||
|
@ -107,7 +115,7 @@ class EquationSolver1d(GraphScene, ZoomedScene):
|
||||||
tracked_mobject = downBrace)
|
tracked_mobject = downBrace)
|
||||||
self.add(downBraceLabelAnimation)
|
self.add(downBraceLabelAnimation)
|
||||||
|
|
||||||
upBrace.move_to(self.coords_to_point(0, upperY), aligned_edge = UP)
|
upBrace.move_to(self.coords_to_point(0, upperY)) #, aligned_edge = DOWN)
|
||||||
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,
|
||||||
|
@ -166,9 +174,24 @@ class EquationSolver1d(GraphScene, ZoomedScene):
|
||||||
midCoords = self.coords_to_point(midX, midY)
|
midCoords = self.coords_to_point(midX, midY)
|
||||||
midColor = RED
|
midColor = RED
|
||||||
midXPoint = Dot(self.coords_to_point(midX, 0), color = midColor)
|
midXPoint = Dot(self.coords_to_point(midX, 0), 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.move_to(0.9 * SPACE_HEIGHT * DOWN)
|
||||||
|
x_guess_label_caption.next_to(x_guess_label_num, LEFT)
|
||||||
|
x_guess_label = Group(x_guess_label_caption, x_guess_label_num)
|
||||||
|
y_guess_label_caption = TextMobject(", y = ", fill_color = midColor)
|
||||||
|
y_guess_label_num = DecimalNumber(midY, fill_color = midColor)
|
||||||
|
y_guess_label_caption.next_to(x_guess_label_num, RIGHT)
|
||||||
|
y_guess_label_num.next_to(y_guess_label_caption, RIGHT)
|
||||||
|
y_guess_label = Group(y_guess_label_caption, y_guess_label_num)
|
||||||
|
guess_labels = Group(x_guess_label, y_guess_label)
|
||||||
|
|
||||||
self.play(
|
self.play(
|
||||||
ReplacementTransform(leftBrace.copy(), midXPoint),
|
ReplacementTransform(leftBrace.copy(), midXPoint),
|
||||||
ReplacementTransform(rightBrace.copy(), midXPoint))
|
ReplacementTransform(rightBrace.copy(), midXPoint),
|
||||||
|
FadeIn(x_guess_label))
|
||||||
|
|
||||||
midXLine = Line(self.coords_to_point(midX, 0), midCoords, color = midColor)
|
midXLine = Line(self.coords_to_point(midX, 0), midCoords, color = midColor)
|
||||||
self.play(ShowCreation(midXLine))
|
self.play(ShowCreation(midXLine))
|
||||||
midDot = Dot(midCoords, color = midColor)
|
midDot = Dot(midCoords, color = midColor)
|
||||||
|
@ -177,14 +200,15 @@ class EquationSolver1d(GraphScene, ZoomedScene):
|
||||||
midDot.scale_in_place(inverseZoomFactor)
|
midDot.scale_in_place(inverseZoomFactor)
|
||||||
self.add(midDot)
|
self.add(midDot)
|
||||||
midYLine = Line(midCoords, self.coords_to_point(0, midY), color = midColor)
|
midYLine = Line(midCoords, self.coords_to_point(0, midY), color = midColor)
|
||||||
self.play(ShowCreation(midYLine))
|
self.play(ShowCreation(midYLine), FadeIn(y_guess_label))
|
||||||
|
|
||||||
if midY < self.targetY:
|
if midY < self.targetY:
|
||||||
movingGroup = Group(lowerDot,
|
movingGroup = Group(lowerDot,
|
||||||
leftBrace, downBrace,
|
leftBrace, downBrace,
|
||||||
lowerXLine, lowerYLine)
|
lowerXLine, lowerYLine)
|
||||||
self.play(
|
self.play(
|
||||||
UpdateFromAlphaFunc(movingGroup, makeUpdater(lowerX)))
|
UpdateFromAlphaFunc(movingGroup, makeUpdater(lowerX)),
|
||||||
|
FadeOut(guess_labels))
|
||||||
lowerX = midX
|
lowerX = midX
|
||||||
lowerY = midY
|
lowerY = midY
|
||||||
|
|
||||||
|
@ -193,7 +217,8 @@ class EquationSolver1d(GraphScene, ZoomedScene):
|
||||||
rightBrace, upBrace,
|
rightBrace, upBrace,
|
||||||
upperXLine, upperYLine)
|
upperXLine, upperYLine)
|
||||||
self.play(
|
self.play(
|
||||||
UpdateFromAlphaFunc(movingGroup, makeUpdater(upperX)))
|
UpdateFromAlphaFunc(movingGroup, makeUpdater(upperX)),
|
||||||
|
FadeOut(guess_labels))
|
||||||
upperX = midX
|
upperX = midX
|
||||||
upperY = midY
|
upperY = midY
|
||||||
self.remove(midXLine, midDot, midYLine)
|
self.remove(midXLine, midDot, midYLine)
|
||||||
|
@ -319,7 +344,7 @@ class RectangleData():
|
||||||
return tuple([mid(x, y) for (x, y) in sides])
|
return tuple([mid(x, y) for (x, y) in sides])
|
||||||
|
|
||||||
def complex_to_pair(c):
|
def complex_to_pair(c):
|
||||||
return (c.real, c.imag)
|
return np.array((c.real, c.imag))
|
||||||
|
|
||||||
def plane_poly_with_roots(*points):
|
def plane_poly_with_roots(*points):
|
||||||
def f((x, y)):
|
def f((x, y)):
|
||||||
|
@ -723,7 +748,9 @@ class ArrowCircleTest(Scene):
|
||||||
return x
|
return x
|
||||||
|
|
||||||
num_arrows = 8 * 3
|
num_arrows = 8 * 3
|
||||||
arrows = [rev_rotate(base_arrow.copy(), (fdiv(i, num_arrows))) for i in range(num_arrows)]
|
|
||||||
|
# 0.5 - fdiv below so as to get a clockwise rotation from left
|
||||||
|
arrows = [rev_rotate(base_arrow.copy(), 0.5 - (fdiv(i, num_arrows))) for i in range(num_arrows)]
|
||||||
arrows_vgroup = VGroup(*arrows)
|
arrows_vgroup = VGroup(*arrows)
|
||||||
|
|
||||||
self.play(ShowCreation(arrows_vgroup), run_time = 2.5, rate_func = None)
|
self.play(ShowCreation(arrows_vgroup), run_time = 2.5, rate_func = None)
|
||||||
|
@ -803,7 +830,7 @@ class FirstSqrtScene(EquationSolver1d):
|
||||||
"x_max" : 2.5,
|
"x_max" : 2.5,
|
||||||
"y_min" : 0,
|
"y_min" : 0,
|
||||||
"y_max" : 2.5**2,
|
"y_max" : 2.5**2,
|
||||||
"graph_origin" : 2*DOWN + 5 * LEFT,
|
"graph_origin" : 2.5*DOWN + 5.5*LEFT,
|
||||||
"x_axis_width" : 12,
|
"x_axis_width" : 12,
|
||||||
"zoom_factor" : 3,
|
"zoom_factor" : 3,
|
||||||
"zoomed_canvas_center" : 2.25 * UP + 1.75 * LEFT,
|
"zoomed_canvas_center" : 2.25 * UP + 1.75 * LEFT,
|
||||||
|
@ -818,31 +845,110 @@ class FirstSqrtScene(EquationSolver1d):
|
||||||
"show_target_line" : True,
|
"show_target_line" : True,
|
||||||
}
|
}
|
||||||
|
|
||||||
class SecondSqrtScene(FirstSqrtScene, ReconfigurableScene):
|
FirstSqrtSceneConfig = FirstSqrtScene.CONFIG
|
||||||
# TODO: Don't bother with ReconfigurableScene; just use new config from start
|
shiftVal = FirstSqrtSceneConfig["targetY"]
|
||||||
# (But can also use this as written, and just cut into middle in Premiere)
|
|
||||||
|
|
||||||
def setup(self):
|
class SecondSqrtScene(FirstSqrtScene):
|
||||||
FirstSqrtScene.setup(self)
|
CONFIG = {
|
||||||
ReconfigurableScene.setup(self)
|
"func" : lambda x : FirstSqrtSceneConfig["func"](x) - shiftVal,
|
||||||
|
"targetY" : 0,
|
||||||
def construct(self):
|
"graph_label" : FirstSqrtSceneConfig["graph_label"] + " - " + str(shiftVal),
|
||||||
shiftVal = self.targetY
|
"y_min" : FirstSqrtSceneConfig["y_min"] - shiftVal,
|
||||||
|
"y_max" : FirstSqrtSceneConfig["y_max"] - shiftVal,
|
||||||
self.drawGraph()
|
"show_target_line" : False,
|
||||||
newOrigin = self.coords_to_point(0, shiftVal)
|
# 0.96 hacked in by checking calculations above
|
||||||
self.transition_to_alt_config(
|
"graph_origin" : 0.96 * shiftVal * UP + FirstSqrtSceneConfig["graph_origin"],
|
||||||
func = lambda x : x**2 - shiftVal,
|
}
|
||||||
targetY = 0,
|
|
||||||
graph_label = "y = x^2 - " + str(shiftVal),
|
|
||||||
y_min = self.y_min - shiftVal,
|
|
||||||
y_max = self.y_max - shiftVal,
|
|
||||||
show_target_line = False,
|
|
||||||
graph_origin = newOrigin)
|
|
||||||
self.solveEquation()
|
|
||||||
|
|
||||||
# TODO: Pi creatures intrigued
|
# TODO: Pi creatures intrigued
|
||||||
|
|
||||||
|
class SignsExplanation(Scene):
|
||||||
|
def construct(self):
|
||||||
|
num_line = NumberLine(stroke_width = 1)
|
||||||
|
largest_num = 10
|
||||||
|
num_line.add_numbers(*range(-largest_num, largest_num + 1))
|
||||||
|
self.add(num_line)
|
||||||
|
self.wait()
|
||||||
|
|
||||||
|
pos_num = 3
|
||||||
|
neg_num = -pos_num
|
||||||
|
|
||||||
|
pos_arrow = Arrow(
|
||||||
|
num_line.number_to_point(0),
|
||||||
|
num_line.number_to_point(pos_num),
|
||||||
|
buff = 0,
|
||||||
|
color = YELLOW)
|
||||||
|
neg_arrow = Arrow(
|
||||||
|
num_line.number_to_point(0),
|
||||||
|
num_line.number_to_point(neg_num),
|
||||||
|
buff = 0,
|
||||||
|
color = RED)
|
||||||
|
|
||||||
|
#num_line.add_numbers(pos_num)
|
||||||
|
self.play(ShowCreation(pos_arrow))
|
||||||
|
|
||||||
|
#num_line.add_numbers(neg_num)
|
||||||
|
self.play(ShowCreation(neg_arrow))
|
||||||
|
|
||||||
|
class VectorField(Scene):
|
||||||
|
CONFIG = {
|
||||||
|
"func" : plane_func_from_complex_func(lambda p : p**2 + 2),
|
||||||
|
"granularity" : 10,
|
||||||
|
"arrow_scale_factor" : 0.1,
|
||||||
|
"normalized_arrow_scale_factor" : 5
|
||||||
|
}
|
||||||
|
|
||||||
|
def construct(self):
|
||||||
|
num_plane = NumberPlane()
|
||||||
|
self.add(num_plane)
|
||||||
|
|
||||||
|
x_min, y_min = num_plane.point_to_coords(SPACE_WIDTH * LEFT + SPACE_HEIGHT * UP)
|
||||||
|
x_max, y_max = num_plane.point_to_coords(SPACE_WIDTH * RIGHT + SPACE_HEIGHT * DOWN)
|
||||||
|
|
||||||
|
x_points = range_via_num_steps(x_min, x_max, self.granularity)
|
||||||
|
y_points = range_via_num_steps(y_min, y_max, self.granularity)
|
||||||
|
points = it.product(x_points, y_points)
|
||||||
|
|
||||||
|
sized_arrows = Group()
|
||||||
|
unsized_arrows = Group()
|
||||||
|
for (x, y) in points:
|
||||||
|
output = self.func((x, y))
|
||||||
|
output_size = np.sqrt(sum(output**2))
|
||||||
|
normalized_output = output * fdiv(self.normalized_arrow_scale_factor, output_size) # Assume output has nonzero size here
|
||||||
|
arrow = Vector(output * self.arrow_scale_factor)
|
||||||
|
normalized_arrow = Vector(normalized_output * self.arrow_scale_factor)
|
||||||
|
arrow.move_to(num_plane.coords_to_point(x, y))
|
||||||
|
normalized_arrow.move_to(arrow)
|
||||||
|
sized_arrows.add(arrow)
|
||||||
|
unsized_arrows.add(normalized_arrow)
|
||||||
|
|
||||||
|
self.add(sized_arrows)
|
||||||
|
self.wait()
|
||||||
|
|
||||||
|
self.play(ReplacementTransform(sized_arrows, unsized_arrows))
|
||||||
|
self.wait()
|
||||||
|
|
||||||
|
class HasItsLimitations(Scene):
|
||||||
|
def construct(self):
|
||||||
|
num_line = NumberLine()
|
||||||
|
num_line.add_numbers()
|
||||||
|
self.add(num_line)
|
||||||
|
|
||||||
|
self.wait()
|
||||||
|
|
||||||
|
num_plane = NumberPlane()
|
||||||
|
num_plane.add_coordinates()
|
||||||
|
|
||||||
|
self.play(FadeOut(num_line), FadeIn(num_plane))
|
||||||
|
|
||||||
|
self.wait()
|
||||||
|
|
||||||
|
complex_plane = ComplexPlane()
|
||||||
|
complex_plane.add_coordinates()
|
||||||
|
|
||||||
|
self.play(FadeOut(num_plane), FadeIn(complex_plane))
|
||||||
|
|
||||||
|
|
||||||
class ComplexPlaneIs2d(Scene):
|
class ComplexPlaneIs2d(Scene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
com_plane = ComplexPlane()
|
com_plane = ComplexPlane()
|
||||||
|
|
|
@ -671,6 +671,10 @@ class DictAsObject(object):
|
||||||
def fdiv(a, b):
|
def fdiv(a, b):
|
||||||
return np.true_divide(a,b)
|
return np.true_divide(a,b)
|
||||||
|
|
||||||
|
def range_via_num_steps(start, end, num_steps, include_end = True):
|
||||||
|
num_points = num_steps + (1 if include_end else 0)
|
||||||
|
return [interpolate(start, end, fdiv(i, num_steps)) for i in range(num_points)]
|
||||||
|
|
||||||
# For debugging purposes
|
# For debugging purposes
|
||||||
|
|
||||||
def print_mobject_family(mob, n_tabs = 0):
|
def print_mobject_family(mob, n_tabs = 0):
|
||||||
|
|
Loading…
Add table
Reference in a new issue