mirror of
https://github.com/3b1b/manim.git
synced 2026-04-26 03:00:23 -04:00
Merge branch 'master' into eop
This commit is contained in:
@@ -1 +0,0 @@
|
||||
|
||||
|
||||
103
active_projects/eop/chapter2.py
Normal file
103
active_projects/eop/chapter2.py
Normal file
@@ -0,0 +1,103 @@
|
||||
from big_ol_pile_of_manim_imports import *
|
||||
|
||||
def print_permutation(index_list):
|
||||
|
||||
|
||||
n = max(max(index_list), len(index_list))
|
||||
for i in range(0,n):
|
||||
if index_list[i] > n - i:
|
||||
raise Exception("Impossible indices!")
|
||||
|
||||
#print "given index list:", index_list
|
||||
perm_list = n * ["_"]
|
||||
alphabet = ["A", "B", "C", "D", "E", "F",
|
||||
"G", "H", "I", "J", "K", "L",
|
||||
"M", "N", "O", "P", "Q", "R",
|
||||
"S", "T", "U", "V", "W", "X",
|
||||
"Y", "Z"]
|
||||
free_indices = range(n)
|
||||
free_indices_p1 = range(1,n + 1)
|
||||
#print perm_list
|
||||
for i in range(n):
|
||||
findex = index_list[i] - 1
|
||||
#print "place next letter at", findex + 1, "th free place"
|
||||
tindex = free_indices[findex]
|
||||
#print "so at position", tindex + 1
|
||||
perm_list[tindex] = alphabet[i]
|
||||
free_indices.remove(tindex)
|
||||
free_indices_p1.remove(tindex + 1)
|
||||
#print "remaining free places:", free_indices_p1
|
||||
#print perm_list
|
||||
|
||||
return "".join(perm_list)
|
||||
|
||||
|
||||
class PermutationGrid(Scene):
|
||||
|
||||
def text_box(self, str):
|
||||
box = TextMobject(str).scale(0.3)
|
||||
box.add(SurroundingRectangle(box, stroke_color = DARK_GREY))
|
||||
return box
|
||||
|
||||
|
||||
def construct(self):
|
||||
|
||||
|
||||
N = 5
|
||||
|
||||
index_list = []
|
||||
perm5_box = VGroup()
|
||||
for i in range(1, N + 1):
|
||||
index_list.append(i)
|
||||
perm4_box = VGroup()
|
||||
for j in range(1, N):
|
||||
index_list.append(j)
|
||||
perm3_box = VGroup()
|
||||
for k in range(1, N - 1):
|
||||
index_list.append(k)
|
||||
perm2_box = VGroup()
|
||||
for l in range(1, N - 2):
|
||||
index_list.append(l)
|
||||
index_list.append(1)
|
||||
perm_box = self.text_box(print_permutation(index_list))
|
||||
if l > 1:
|
||||
perm_box.next_to(perm2_box[-1], DOWN, buff = 0)
|
||||
perm2_box.add(perm_box)
|
||||
index_list.pop()
|
||||
index_list.pop()
|
||||
if k > 1:
|
||||
perm2_box.next_to(perm3_box[-1], RIGHT, buff = 0.08)
|
||||
perm3_box.add(perm2_box)
|
||||
index_list.pop()
|
||||
perm3_box.add(SurroundingRectangle(perm3_box, buff = 0.12, stroke_color = LIGHT_GRAY))
|
||||
if j > 1:
|
||||
perm3_box.next_to(perm4_box[-1], DOWN, buff = 0)
|
||||
perm4_box.add(perm3_box)
|
||||
index_list.pop()
|
||||
if i > 1:
|
||||
perm4_box.next_to(perm5_box[-1], RIGHT, buff = 0.16)
|
||||
perm5_box.add(perm4_box)
|
||||
index_list.pop()
|
||||
|
||||
perm5_box.move_to(ORIGIN)
|
||||
self.add(perm5_box)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#!/usr/bin/env python2
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from big_ol_pile_of_manim_imports import *
|
||||
|
||||
NAME_WITH_SPACES = "Prime Meridian"
|
||||
@@ -5,71 +8,100 @@ DIAMETER = 3.0
|
||||
RADIUS = DIAMETER / 2
|
||||
LETTER_SCALE = 1
|
||||
|
||||
|
||||
class NameAnimationScene(Scene):
|
||||
CONFIG = {
|
||||
"animated_name": "Prime Meridian"
|
||||
}
|
||||
|
||||
def construct(self):
|
||||
|
||||
name = ''.join(NAME_WITH_SPACES.split(' '))
|
||||
letters = list(name)
|
||||
nb_letters = len(letters)
|
||||
name = self.animated_name
|
||||
letter_mobs = TextMobject(name)
|
||||
nb_letters = len(letter_mobs)
|
||||
randy = PiCreature()
|
||||
randy.move_to(ORIGIN).scale_to_fit_height(0.5 * DIAMETER)
|
||||
randy.set_color(BLUE_E)
|
||||
randy.look_at(UP + RIGHT)
|
||||
self.add(randy)
|
||||
dtheta = TAU/nb_letters
|
||||
angles = np.arange(TAU/4,-3 * TAU / 4,-dtheta)
|
||||
dtheta = TAU / nb_letters
|
||||
angles = np.arange(TAU / 4, -3 * TAU / 4, -dtheta)
|
||||
name_mob = VGroup()
|
||||
for (letter, angle) in zip(letters, angles):
|
||||
letter_mob = TextMobject(letter).scale(LETTER_SCALE)
|
||||
for (letter_mob, angle) in zip(letter_mobs, angles):
|
||||
letter_mob.scale(LETTER_SCALE)
|
||||
pos = RADIUS * np.cos(angle) * RIGHT + RADIUS * np.sin(angle) * UP
|
||||
letter_mob.move_to(pos)
|
||||
name_mob.add(letter_mob)
|
||||
|
||||
pos2 = RADIUS * np.cos(angles[2]) * RIGHT + RADIUS * np.sin(angles[2]) * UP
|
||||
pos2 = RADIUS * np.cos(angles[2]) * RIGHT + \
|
||||
RADIUS * np.sin(angles[2]) * UP
|
||||
|
||||
times_n_label = VGroup(
|
||||
TexMobject("\\times"),
|
||||
Integer(1)
|
||||
)
|
||||
times_n_label.arrange_submobjects(RIGHT)
|
||||
times_n_label.shift(FRAME_WIDTH * RIGHT / 4)
|
||||
times_n_label.to_edge(UP)
|
||||
|
||||
self.play(
|
||||
LaggedStart(Write, name_mob, run_time = 3),
|
||||
ApplyMethod(randy.look_at, pos2, run_time = 3)
|
||||
LaggedStart(FadeIn, name_mob, run_time=3),
|
||||
ApplyMethod(randy.change, "pondering", pos2, run_time=1),
|
||||
FadeIn(times_n_label)
|
||||
)
|
||||
|
||||
for i in range(2,nb_letters + 2):
|
||||
for n in range(2, nb_letters + 2):
|
||||
|
||||
group = []
|
||||
|
||||
for (j,letter_mob) in enumerate(name_mob.submobjects):
|
||||
for (j, letter_mob) in enumerate(name_mob.submobjects):
|
||||
|
||||
new_angle = TAU / 4 - i * j * dtheta
|
||||
new_pos = RADIUS * np.cos(new_angle) * RIGHT + RADIUS * np.sin(new_angle) * UP
|
||||
new_angle = TAU / 4 - n * j * dtheta
|
||||
new_pos = RADIUS * np.cos(new_angle) * \
|
||||
RIGHT + RADIUS * np.sin(new_angle) * UP
|
||||
letter_mob.target = letter_mob.copy().move_to(new_pos)
|
||||
anim = MoveToTarget(letter_mob, path_arc = - j * dtheta)
|
||||
anim = MoveToTarget(letter_mob, path_arc=- j * dtheta)
|
||||
group.append(anim)
|
||||
|
||||
new_n = Integer(n)
|
||||
new_n.move_to(times_n_label[1])
|
||||
self.play(
|
||||
AnimationGroup(*group, run_time = 3),
|
||||
ApplyMethod(randy.look_at,name_mob.submobjects[2], run_time = 3)
|
||||
AnimationGroup(*group, run_time=3),
|
||||
UpdateFromFunc(randy, lambda r: r.look_at(name_mob.submobjects[2])),
|
||||
FadeOut(times_n_label[1]),
|
||||
FadeIn(new_n)
|
||||
)
|
||||
times_n_label.submobjects[1] = new_n
|
||||
self.wait(0.5)
|
||||
|
||||
|
||||
thank_you = TextMobject("Thank You!").next_to(randy, DOWN)
|
||||
new_randy = randy.copy()
|
||||
new_randy.change("hooray")
|
||||
new_randy.set_color(BLUE_E)
|
||||
new_randy.look_at(ORIGIN)
|
||||
self.play(
|
||||
Transform(name_mob, thank_you),
|
||||
ReplacementTransform(name_mob, VGroup(*thank_you)),
|
||||
Transform(randy, new_randy)
|
||||
)
|
||||
self.play(Blink(randy))
|
||||
|
||||
def __str__(self):
|
||||
return self.animated_name.replace(" ", "") + "Animation"
|
||||
|
||||
|
||||
names = []
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
for name in names:
|
||||
try:
|
||||
NameAnimationScene(
|
||||
frame_duration=PRODUCTION_QUALITY_FRAME_DURATION,
|
||||
camera_config=PRODUCTION_QUALITY_CAMERA_CONFIG,
|
||||
animated_name=name,
|
||||
write_to_movie=True,
|
||||
output_directory=os.path.join(
|
||||
ANIMATIONS_DIR,
|
||||
"active_projects",
|
||||
"name_animations",
|
||||
),
|
||||
)
|
||||
except Exception as e:
|
||||
print "Could not animate %s: %s" % (name, e)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -39,7 +39,7 @@ class PiCreatureScene(Scene):
|
||||
}
|
||||
|
||||
def setup(self):
|
||||
self.pi_creatures = self.create_pi_creatures()
|
||||
self.pi_creatures = VGroup(*self.create_pi_creatures())
|
||||
self.pi_creature = self.get_primary_pi_creature()
|
||||
if self.pi_creatures_start_on_screen:
|
||||
self.add(*self.pi_creatures)
|
||||
|
||||
@@ -439,7 +439,13 @@ class DashedLine(Line):
|
||||
|
||||
def generate_points(self):
|
||||
length = np.linalg.norm(self.end - self.start)
|
||||
if length == 0:
|
||||
self.add(Line(self.start, self.end))
|
||||
return self
|
||||
num_interp_points = int(length / self.dashed_segment_length)
|
||||
# Even number ensures that start and end points are hit
|
||||
if num_interp_points % 2 == 1:
|
||||
num_interp_points += 1
|
||||
points = [
|
||||
interpolate(self.start, self.end, alpha)
|
||||
for alpha in np.linspace(0, 1, num_interp_points)
|
||||
|
||||
@@ -115,7 +115,7 @@ class Mobject(Container):
|
||||
def copy(self):
|
||||
# TODO, either justify reason for shallow copy, or
|
||||
# remove this redundancy everywhere
|
||||
#return self.deepcopy()
|
||||
# return self.deepcopy()
|
||||
|
||||
copy_mobject = copy.copy(self)
|
||||
copy_mobject.points = np.array(self.points)
|
||||
|
||||
@@ -2,6 +2,7 @@ from __future__ import absolute_import
|
||||
|
||||
from constants import *
|
||||
|
||||
from mobject.types.vectorized_mobject import VMobject
|
||||
from mobject.geometry import Rectangle
|
||||
from mobject.geometry import Line
|
||||
from mobject.types.vectorized_mobject import VGroup
|
||||
@@ -39,8 +40,21 @@ class BackgroundRectangle(SurroundingRectangle):
|
||||
self.set_fill(opacity=b * self.original_fill_opacity)
|
||||
return self
|
||||
|
||||
def set_color(self):
|
||||
# Can't be changin' me!
|
||||
def set_style_data(self,
|
||||
stroke_color=None,
|
||||
stroke_width=None,
|
||||
fill_color=None,
|
||||
fill_opacity=None,
|
||||
family=True
|
||||
):
|
||||
# Unchangable style, except for fill_opacity
|
||||
VMobject.set_style_data(
|
||||
self,
|
||||
stroke_color=BLACK,
|
||||
stroke_width=0,
|
||||
fill_color=BLACK,
|
||||
fill_opacity=fill_opacity
|
||||
)
|
||||
return self
|
||||
|
||||
def get_fill_color(self):
|
||||
|
||||
@@ -226,6 +226,7 @@ class Laptop(VGroup):
|
||||
body.set_fill(self.shaded_body_color, opacity=1)
|
||||
body.sort_submobjects(lambda p: p[2])
|
||||
body[-1].set_fill(self.body_color)
|
||||
screen_plate = body.copy()
|
||||
keyboard = VGroup(*[
|
||||
VGroup(*[
|
||||
Square(**self.key_color_kwargs)
|
||||
@@ -243,7 +244,6 @@ class Laptop(VGroup):
|
||||
keyboard.shift(MED_SMALL_BUFF * UP)
|
||||
body.add(keyboard)
|
||||
|
||||
screen_plate = body.copy()
|
||||
screen_plate.stretch(self.screen_thickness /
|
||||
self.body_dimensions[2], dim=2)
|
||||
screen = Rectangle(
|
||||
|
||||
@@ -165,7 +165,7 @@ class SVGMobject(VMobject):
|
||||
# input preprocessing
|
||||
if fill_color in ["", "none", "#FFF", "#FFFFFF"] or Color(fill_color) == Color(WHITE):
|
||||
opacity = 0
|
||||
fill_color = BLACK # shdn't be necessary but avoids error msgs
|
||||
fill_color = BLACK # shdn't be necessary but avoids error msgs
|
||||
if fill_color in ["#000", "#000000"]:
|
||||
fill_color = WHITE
|
||||
if stroke_color in ["", "none", "#FFF", "#FFFFFF"] or Color(stroke_color) == Color(WHITE):
|
||||
@@ -175,10 +175,6 @@ class SVGMobject(VMobject):
|
||||
stroke_color = WHITE
|
||||
if stroke_width in ["", "none", "0"]:
|
||||
stroke_width = 0
|
||||
|
||||
# is there sth to draw?
|
||||
if opacity == 0 and stroke_width == 0:
|
||||
return
|
||||
|
||||
if corner_radius in ["", "0", "none"]:
|
||||
corner_radius = 0
|
||||
@@ -187,22 +183,22 @@ class SVGMobject(VMobject):
|
||||
|
||||
if corner_radius == 0:
|
||||
mob = Rectangle(
|
||||
width = float(rect_element.getAttribute("width")),
|
||||
height = float(rect_element.getAttribute("height")),
|
||||
stroke_width = stroke_width,
|
||||
stroke_color = stroke_color,
|
||||
fill_color = fill_color,
|
||||
fill_opacity = opacity
|
||||
width=float(rect_element.getAttribute("width")),
|
||||
height=float(rect_element.getAttribute("height")),
|
||||
stroke_width=stroke_width,
|
||||
stroke_color=stroke_color,
|
||||
fill_color=fill_color,
|
||||
fill_opacity=opacity
|
||||
)
|
||||
else:
|
||||
mob = RoundedRectangle(
|
||||
width = float(rect_element.getAttribute("width")),
|
||||
height = float(rect_element.getAttribute("height")),
|
||||
stroke_width = stroke_width,
|
||||
stroke_color = stroke_color,
|
||||
fill_color = fill_color,
|
||||
fill_opacity = opacity,
|
||||
corner_radius = corner_radius
|
||||
width=float(rect_element.getAttribute("width")),
|
||||
height=float(rect_element.getAttribute("height")),
|
||||
stroke_width=stroke_width,
|
||||
stroke_color=stroke_color,
|
||||
fill_color=fill_color,
|
||||
fill_opacity=opacity,
|
||||
corner_radius=corner_radius
|
||||
)
|
||||
|
||||
mob.shift(mob.get_center() - mob.get_corner(UP + LEFT))
|
||||
|
||||
@@ -3,7 +3,7 @@ import numpy as np
|
||||
from scipy import linalg
|
||||
from utils.simple_functions import choose
|
||||
|
||||
CLOSED_THRESHOLD = 0.0
|
||||
CLOSED_THRESHOLD = 0.001
|
||||
|
||||
|
||||
def bezier(points):
|
||||
@@ -98,7 +98,8 @@ def get_smooth_handle_points(points):
|
||||
|
||||
def solve_func(b):
|
||||
return linalg.solve_banded((l, u), diag, b)
|
||||
if is_closed(points):
|
||||
use_closed_solve_function = is_closed(points)
|
||||
if use_closed_solve_function:
|
||||
# Get equations to relate first and last points
|
||||
matrix = diag_to_matrix((l, u), diag)
|
||||
# last row handles second derivative
|
||||
@@ -109,11 +110,15 @@ def get_smooth_handle_points(points):
|
||||
b[0] = 2 * points[0]
|
||||
b[-1] = np.zeros(dim)
|
||||
|
||||
def solve_func(b):
|
||||
def closed_curve_solve_func(b):
|
||||
return linalg.solve(matrix, b)
|
||||
|
||||
handle_pairs = np.zeros((2 * num_handles, dim))
|
||||
for i in range(dim):
|
||||
handle_pairs[:, i] = solve_func(b[:, i])
|
||||
if use_closed_solve_function:
|
||||
handle_pairs[:, i] = closed_curve_solve_func(b[:, i])
|
||||
else:
|
||||
handle_pairs[:, i] = solve_func(b[:, i])
|
||||
return handle_pairs[0::2], handle_pairs[1::2]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user