mirror of
https://github.com/3b1b/manim.git
synced 2025-07-31 14:03:59 +08:00
Beginning highD project
This commit is contained in:
@ -267,7 +267,6 @@ class MaintainPositionRelativeTo(Animation):
|
||||
self.diff
|
||||
)
|
||||
|
||||
|
||||
### Animation modifiers ###
|
||||
|
||||
class ApplyToCenters(Animation):
|
||||
|
@ -186,8 +186,8 @@ def main():
|
||||
try:
|
||||
handle_scene(SceneClass(**scene_kwargs), **config)
|
||||
play_finish_sound()
|
||||
# except RuntimeError as e:
|
||||
# play_finish_sound()
|
||||
except RuntimeError as e:
|
||||
play_finish_sound()
|
||||
except:
|
||||
print "\n\n"
|
||||
traceback.print_exc()
|
||||
|
237
highD.py
Normal file
237
highD.py
Normal file
@ -0,0 +1,237 @@
|
||||
from helpers import *
|
||||
|
||||
from mobject.tex_mobject import TexMobject
|
||||
from mobject import Mobject
|
||||
from mobject.image_mobject import ImageMobject
|
||||
from mobject.vectorized_mobject import *
|
||||
|
||||
from animation.animation import Animation
|
||||
from animation.transform import *
|
||||
from animation.simple_animations import *
|
||||
from animation.playground import *
|
||||
from topics.geometry import *
|
||||
from topics.characters import *
|
||||
from topics.functions import *
|
||||
from topics.fractals import *
|
||||
from topics.number_line import *
|
||||
from topics.combinatorics import *
|
||||
from topics.numerals import *
|
||||
from topics.three_dimensions import *
|
||||
from topics.objects import *
|
||||
from topics.probability import *
|
||||
from topics.complex_numbers import *
|
||||
from topics.common_scenes import *
|
||||
from scene import Scene
|
||||
from scene.reconfigurable_scene import ReconfigurableScene
|
||||
from scene.zoomed_scene import *
|
||||
from camera import Camera
|
||||
from mobject.svg_mobject import *
|
||||
from mobject.tex_mobject import *
|
||||
|
||||
##########
|
||||
#revert_to_original_skipping_status
|
||||
|
||||
class MathIsATease(Scene):
|
||||
def construct(self):
|
||||
randy = Randolph()
|
||||
lashes = VGroup()
|
||||
for eye in randy.eyes:
|
||||
for angle in np.linspace(-np.pi/3, np.pi/3, 12):
|
||||
lash = Line(ORIGIN, RIGHT)
|
||||
lash.set_stroke(DARK_GREY, 2)
|
||||
lash.scale_to_fit_width(0.27)
|
||||
lash.next_to(ORIGIN, RIGHT, buff = 0)
|
||||
lash.rotate(angle + np.pi/2)
|
||||
lash.shift(eye.get_center())
|
||||
lashes.add(lash)
|
||||
lashes.do_in_place(lashes.stretch, 0.8, 1)
|
||||
lashes.shift(0.04*DOWN)
|
||||
|
||||
|
||||
fan = SVGMobject(
|
||||
file_name = "fan",
|
||||
fill_opacity = 1,
|
||||
fill_color = YELLOW,
|
||||
stroke_width = 2,
|
||||
stroke_color = YELLOW,
|
||||
height = 0.7,
|
||||
)
|
||||
VGroup(*fan[-12:]).set_fill(YELLOW_E)
|
||||
fan.rotate(-np.pi/4)
|
||||
fan.move_to(randy)
|
||||
fan.shift(0.85*UP+0.25*LEFT)
|
||||
|
||||
self.add(randy)
|
||||
self.play(
|
||||
ShowCreation(lashes, submobject_mode = "all_at_once"),
|
||||
randy.change, "tease",
|
||||
randy.look, OUT,
|
||||
)
|
||||
self.add_foreground_mobjects(fan)
|
||||
eye_bottom_y = randy.eyes.get_bottom()[1]
|
||||
self.play(
|
||||
ApplyMethod(
|
||||
lashes.apply_function,
|
||||
lambda p : [p[0], eye_bottom_y, p[2]],
|
||||
rate_func = Blink.CONFIG["rate_func"],
|
||||
),
|
||||
Blink(randy),
|
||||
DrawBorderThenFill(fan),
|
||||
)
|
||||
self.play(
|
||||
ApplyMethod(
|
||||
lashes.apply_function,
|
||||
lambda p : [p[0], eye_bottom_y, p[2]],
|
||||
rate_func = Blink.CONFIG["rate_func"],
|
||||
),
|
||||
Blink(randy),
|
||||
)
|
||||
self.dither()
|
||||
|
||||
class TODODeterminants(TODOStub):
|
||||
CONFIG = {
|
||||
"message" : "Determinants clip"
|
||||
}
|
||||
|
||||
class CircleToPairsOfPoints(Scene):
|
||||
def construct(self):
|
||||
plane = NumberPlane(written_coordinate_height = 0.3)
|
||||
plane.scale(2)
|
||||
plane.add_coordinates(y_vals = [-1, 1])
|
||||
background_plane = plane.copy()
|
||||
background_plane.highlight(GREY)
|
||||
background_plane.fade()
|
||||
circle = Circle(radius = 2, color = YELLOW)
|
||||
dot = Dot(circle.get_right(), color = LIGHT_GREY)
|
||||
|
||||
equation = TexMobject("x", "^2", "+", "y", "^2", "=", "1")
|
||||
equation.highlight_by_tex("x", GREEN)
|
||||
equation.highlight_by_tex("y", RED)
|
||||
equation.to_corner(UP+LEFT)
|
||||
equation.add_background_rectangle()
|
||||
|
||||
x, y = 1, 0
|
||||
coord_pair = TexMobject("(", "-%.02f"%x, ",", "-%.02f"%y, ")")
|
||||
fixed_numbers = coord_pair.get_parts_by_tex(".00")
|
||||
fixed_numbers.set_fill(opacity = 0)
|
||||
coord_pair.add_background_rectangle()
|
||||
coord_pair.next_to(dot, UP+RIGHT, SMALL_BUFF)
|
||||
numbers = VGroup(*[
|
||||
DecimalNumber(val).replace(num, dim_to_match = 1)
|
||||
for val, num in zip([x, y], fixed_numbers)
|
||||
])
|
||||
numbers[0].highlight(GREEN)
|
||||
numbers[1].highlight(RED)
|
||||
|
||||
def get_update_func(i):
|
||||
return lambda t : dot.get_center()[i]/2.0
|
||||
|
||||
|
||||
self.add(background_plane, plane)
|
||||
self.play(ShowCreation(circle))
|
||||
self.play(Write(equation))
|
||||
self.play(
|
||||
LaggedStart(FadeIn, coord_pair),
|
||||
ShowCreation(dot),
|
||||
*[
|
||||
ReplacementTransform(
|
||||
equation.get_parts_by_tex(tex).copy(),
|
||||
number
|
||||
)
|
||||
for tex, number in zip("xy", numbers)
|
||||
]
|
||||
)
|
||||
self.play(
|
||||
Rotating(
|
||||
dot, run_time = 7, in_place = False,
|
||||
rate_func = smooth,
|
||||
),
|
||||
MaintainPositionRelativeTo(coord_pair, dot),
|
||||
*[
|
||||
ChangingDecimal(
|
||||
num, get_update_func(i),
|
||||
tracked_mobject = fixed_num
|
||||
)
|
||||
for num, i, fixed_num in zip(
|
||||
numbers, (0, 1), fixed_numbers
|
||||
)
|
||||
]
|
||||
)
|
||||
self.dither()
|
||||
|
||||
######### Rotation equations ##########
|
||||
|
||||
rot_equation = TexMobject(
|
||||
"\\Rightarrow"
|
||||
"\\big(\\cos(\\theta)x - \\sin(\\theta)y\\big)^2 + ",
|
||||
"\\big(\\sin(\\theta)x + \\cos(\\theta)y\\big)^2 = 1",
|
||||
)
|
||||
rot_equation.scale(0.9)
|
||||
rot_equation.next_to(equation, RIGHT)
|
||||
rot_equation.add_background_rectangle()
|
||||
|
||||
words = TextMobject("Rotational \\\\ symmetry")
|
||||
words.next_to(ORIGIN, UP)
|
||||
words.to_edge(RIGHT)
|
||||
words.add_background_rectangle()
|
||||
|
||||
arrow = Arrow(
|
||||
words.get_left(), rot_equation.get_bottom(),
|
||||
path_arc = -np.pi/6
|
||||
)
|
||||
randy = Randolph().to_corner(DOWN+LEFT)
|
||||
|
||||
self.play(
|
||||
Write(rot_equation, run_time = 2),
|
||||
FadeOut(coord_pair),
|
||||
FadeOut(numbers),
|
||||
FadeOut(dot),
|
||||
FadeIn(randy)
|
||||
)
|
||||
self.play(randy.change, "confused", rot_equation)
|
||||
self.play(Blink(randy))
|
||||
self.play(
|
||||
Write(words, run_time = 1),
|
||||
ShowCreation(arrow),
|
||||
randy.look_at, words
|
||||
)
|
||||
plane.remove(*plane.coordinate_labels)
|
||||
self.play(
|
||||
Rotate(
|
||||
plane, np.pi/3,
|
||||
run_time = 4,
|
||||
rate_func = there_and_back
|
||||
),
|
||||
Animation(equation),
|
||||
Animation(rot_equation),
|
||||
Animation(words),
|
||||
Animation(arrow),
|
||||
Animation(circle),
|
||||
randy.change, "hooray"
|
||||
)
|
||||
self.dither()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -643,7 +643,6 @@ class Mobject(object):
|
||||
self.points = np.array([mobject.points[0]])
|
||||
return self
|
||||
|
||||
|
||||
def push_self_into_submobjects(self):
|
||||
copy = self.copy()
|
||||
copy.submobjects = []
|
||||
|
@ -72,6 +72,7 @@ class PiCreature(SVGMobject):
|
||||
self.submobjects[LEFT_EYE_INDEX],
|
||||
self.submobjects[RIGHT_EYE_INDEX]
|
||||
])
|
||||
self.eye_parts = VGroup(self.eyes, self.pupils)
|
||||
self.parts_named = True
|
||||
|
||||
def init_colors(self):
|
||||
@ -151,9 +152,9 @@ class PiCreature(SVGMobject):
|
||||
self.eyes.submobjects[1].get_center()[0]
|
||||
|
||||
def blink(self):
|
||||
eye_bottom_y = self.eyes.get_bottom()[1]
|
||||
for mob in self.eyes, self.pupils:
|
||||
mob.apply_function(
|
||||
eye_parts = self.eye_parts
|
||||
eye_bottom_y = eye_parts.get_bottom()[1]
|
||||
eye_parts.apply_function(
|
||||
lambda p : [p[0], eye_bottom_y, p[2]]
|
||||
)
|
||||
return self
|
||||
|
@ -150,7 +150,13 @@ class ExternallyAnimatedScene(Scene):
|
||||
def construct(self):
|
||||
raise Exception("Don't actually run this class.")
|
||||
|
||||
|
||||
class TODOStub(Scene):
|
||||
CONFIG = {
|
||||
"message" : ""
|
||||
}
|
||||
def construct(self):
|
||||
self.add(TextMobject("TODO: %s"%self.message))
|
||||
self.dither()
|
||||
|
||||
|
||||
|
||||
|
@ -222,10 +222,11 @@ class NumberPlane(VMobject):
|
||||
return self.axes.get_height() / (2.0*self.y_radius)
|
||||
|
||||
def get_coordinate_labels(self, x_vals = None, y_vals = None):
|
||||
result = []
|
||||
if x_vals == None and y_vals == None:
|
||||
x_vals = range(-int(self.x_radius), int(self.x_radius))
|
||||
y_vals = range(-int(self.y_radius), int(self.y_radius))
|
||||
coordinate_labels = VGroup()
|
||||
if x_vals == None:
|
||||
x_vals = range(-int(self.x_radius), int(self.x_radius)+1)
|
||||
if y_vals == None:
|
||||
y_vals = range(-int(self.y_radius), int(self.y_radius)+1)
|
||||
for index, vals in enumerate([x_vals, y_vals]):
|
||||
num_pair = [0, 0]
|
||||
for val in vals:
|
||||
@ -238,10 +239,10 @@ class NumberPlane(VMobject):
|
||||
num.scale_to_fit_height(
|
||||
self.written_coordinate_height
|
||||
)
|
||||
vect = DOWN if index == 0 else LEFT
|
||||
num.next_to(point, vect, buff = SMALL_BUFF)
|
||||
result.append(num)
|
||||
return result
|
||||
num.next_to(point, DOWN+LEFT, buff = SMALL_BUFF)
|
||||
coordinate_labels.add(num)
|
||||
self.coordinate_labels = coordinate_labels
|
||||
return coordinate_labels
|
||||
|
||||
def get_axes(self):
|
||||
return self.axes
|
||||
|
@ -1,6 +1,5 @@
|
||||
|
||||
|
||||
from mobject.vectorized_mobject import VMobject, VGroup
|
||||
from mobject.vectorized_mobject import VMobject, VGroup, VectorizedPoint
|
||||
from mobject.tex_mobject import TexMobject
|
||||
from animation import Animation
|
||||
from scene import Scene
|
||||
@ -44,61 +43,55 @@ class Integer(VGroup):
|
||||
|
||||
#Todo, this class is now broken
|
||||
|
||||
class RangingValue(Animation):
|
||||
class ChangingDecimal(Animation):
|
||||
CONFIG = {
|
||||
"num_decimal_points" : 2,
|
||||
"rate_func" : None,
|
||||
"spare_parts" : 2,
|
||||
"position_update_func" : None,
|
||||
"tracked_mobject" : None,
|
||||
"tracked_mobject_next_to_kwargs" : {},
|
||||
"scale_factor" : None,
|
||||
"color" : WHITE,
|
||||
}
|
||||
def __init__(self, value_function, **kwargs):
|
||||
"""
|
||||
Value function should return a real value
|
||||
depending on the state of the surrounding scene
|
||||
"""
|
||||
def __init__(self, decimal_number, number_update_func, **kwargs):
|
||||
digest_config(self, kwargs, locals())
|
||||
self.update_mobject()
|
||||
Animation.__init__(self, self.mobject, **kwargs)
|
||||
|
||||
def update_mobject(self, alpha = 0):
|
||||
mobject = DecimalNumber(
|
||||
self.value_function(alpha),
|
||||
num_decimal_points = self.num_decimal_points,
|
||||
color = self.color,
|
||||
decimal_number.add(*[
|
||||
VectorizedPoint(decimal_number.get_corner(DOWN+LEFT))
|
||||
for x in range(self.spare_parts)]
|
||||
)
|
||||
if not hasattr(self, "mobject"):
|
||||
self.mobject = mobject
|
||||
else:
|
||||
self.mobject.points = mobject.points
|
||||
self.mobject.submobjects = mobject.submobjects
|
||||
if self.scale_factor:
|
||||
self.mobject.scale(self.scale_factor)
|
||||
elif self.tracked_mobject:
|
||||
self.mobject.next_to(
|
||||
self.tracked_mobject,
|
||||
**self.tracked_mobject_next_to_kwargs
|
||||
)
|
||||
return self
|
||||
Animation.__init__(self, decimal_number, **kwargs)
|
||||
|
||||
def update_mobject(self, alpha):
|
||||
self.update_number(alpha)
|
||||
self.update_position()
|
||||
|
||||
def update_number(self, alpha):
|
||||
decimal = self.decimal_number
|
||||
new_decimal = DecimalNumber(self.number_update_func(alpha))
|
||||
new_decimal.replace(decimal, dim_to_match = 1)
|
||||
new_decimal.highlight(decimal.get_color())
|
||||
decimal.align_data(new_decimal)
|
||||
families = [
|
||||
mob.family_members_with_points()
|
||||
for mob in decimal, new_decimal
|
||||
]
|
||||
for sm1, sm2 in zip(*families):
|
||||
sm1.interpolate(sm1, sm2, 1)
|
||||
|
||||
def update_position(self):
|
||||
if self.position_update_func is not None:
|
||||
self.position_update_func(self.decimal_number)
|
||||
elif self.tracked_mobject is not None:
|
||||
self.decimal_number.move_to(self.tracked_mobject)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class RangingValueScene(Scene):
|
||||
CONFIG = {
|
||||
"ranging_values" : []
|
||||
}
|
||||
|
||||
def add_ranging_value(self, value_function, **kwargs):
|
||||
self.ranging_values.append(
|
||||
RangingValue(value_function, **kwargs)
|
||||
)
|
||||
|
||||
def update_frame(self, *args, **kwargs):
|
||||
for val in self.ranging_values:
|
||||
self.remove(val.mobject)
|
||||
val.update_mobject()
|
||||
self.add(val.mobject)
|
||||
return Scene.update_frame(self, *args, **kwargs)
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user