mirror of
https://github.com/3b1b/manim.git
synced 2025-08-31 17:28:29 +00:00
Merge branch 'master' into eop
This commit is contained in:
commit
282c0a19fe
5 changed files with 238 additions and 11 deletions
221
active_projects/eola2/gauss.py
Normal file
221
active_projects/eola2/gauss.py
Normal file
|
@ -0,0 +1,221 @@
|
|||
from fractions import Fraction
|
||||
|
||||
from big_ol_pile_of_manim_imports import *
|
||||
|
||||
|
||||
class FractionMobject(VGroup):
|
||||
CONFIG = {
|
||||
"max_height": 1,
|
||||
}
|
||||
|
||||
def __init__(self, fraction, **kwargs):
|
||||
VGroup.__init__(self, **kwargs)
|
||||
numerator = self.numerator = Integer(fraction.numerator)
|
||||
self.add(numerator)
|
||||
if fraction.denominator != 1:
|
||||
denominator = Integer(fraction.denominator)
|
||||
line = TexMobject("/")
|
||||
numerator.next_to(line, LEFT, SMALL_BUFF)
|
||||
denominator.next_to(line, RIGHT, SMALL_BUFF)
|
||||
self.add(numerator, line, denominator)
|
||||
self.scale_to_fit_height(min(self.max_height, self.get_height()))
|
||||
self.value = fraction
|
||||
|
||||
def add_plus_if_needed(self):
|
||||
if self.value > 0:
|
||||
plus = TexMobject("+")
|
||||
plus.next_to(self, LEFT, SMALL_BUFF)
|
||||
plus.match_color(self)
|
||||
self.add_to_back(plus)
|
||||
|
||||
|
||||
class ShowRowReduction(Scene):
|
||||
CONFIG = {
|
||||
"matrices": [
|
||||
[
|
||||
[2, -1, -1],
|
||||
[0, 3, -4],
|
||||
[-3, 2, 1],
|
||||
],
|
||||
[
|
||||
[1, 0, 0],
|
||||
[0, 1, 0],
|
||||
[0, 0, 1],
|
||||
],
|
||||
# [[1], [2], [3]],
|
||||
],
|
||||
"h_spacing": 2,
|
||||
"extra_h_spacing": 0.5,
|
||||
"v_spacing": 1,
|
||||
"include_separation_lines": True,
|
||||
"changing_row_color": YELLOW,
|
||||
"reference_row_color": BLUE,
|
||||
}
|
||||
|
||||
def construct(self):
|
||||
self.initialize_terms()
|
||||
|
||||
self.apply_row_rescaling(0, Fraction(1, 2))
|
||||
self.add_row_multiple_to_row(2, 0, 3)
|
||||
self.apply_row_rescaling(1, Fraction(1, 3))
|
||||
self.add_row_multiple_to_row(2, 1, Fraction(-1, 2))
|
||||
self.apply_row_rescaling(2, Fraction(6))
|
||||
self.add_row_multiple_to_row(0, 1, Fraction(1, 2))
|
||||
self.add_row_multiple_to_row(0, 2, Fraction(7, 6))
|
||||
self.add_row_multiple_to_row(1, 2, Fraction(4, 3))
|
||||
self.wait()
|
||||
|
||||
def initialize_terms(self):
|
||||
full_matrix = reduce(
|
||||
lambda m, v: np.append(m, v, axis=1),
|
||||
self.matrices
|
||||
)
|
||||
mobject_matrix = np.vectorize(FractionMobject)(full_matrix)
|
||||
rows = self.rows = VGroup(*it.starmap(VGroup, mobject_matrix))
|
||||
for i, row in enumerate(rows):
|
||||
for j, term in enumerate(row):
|
||||
term.move_to(
|
||||
i * self.v_spacing * DOWN +
|
||||
j * self.h_spacing * RIGHT
|
||||
)
|
||||
|
||||
# Visually seaprate distinct parts
|
||||
separation_lines = self.separation_lines = VGroup()
|
||||
lengths = [len(m[0]) for m in self.matrices]
|
||||
for partial_sum in np.cumsum(lengths)[:-1]:
|
||||
VGroup(*mobject_matrix[:, partial_sum:].flatten()).shift(
|
||||
self.extra_h_spacing * RIGHT
|
||||
)
|
||||
c1 = VGroup(*mobject_matrix[:, partial_sum - 1])
|
||||
c2 = VGroup(*mobject_matrix[:, partial_sum])
|
||||
line = DashedLine(c1.get_top(), c1.get_bottom())
|
||||
line.move_to(VGroup(c1, c2))
|
||||
separation_lines.add(line)
|
||||
|
||||
if self.include_separation_lines:
|
||||
group = VGroup(rows, separation_lines)
|
||||
else:
|
||||
group = rows
|
||||
group.center().to_edge(DOWN, buff=2)
|
||||
self.add(group)
|
||||
|
||||
def add_variables(self):
|
||||
# If it is meant to represent a system of equations
|
||||
pass
|
||||
|
||||
def apply_row_rescaling(self, row_index, scale_factor):
|
||||
row = self.rows[row_index]
|
||||
new_row = VGroup()
|
||||
for element in row:
|
||||
target = FractionMobject(element.value * scale_factor)
|
||||
target.move_to(element)
|
||||
new_row.add(target)
|
||||
new_row.set_color(self.changing_row_color)
|
||||
|
||||
label = VGroup(
|
||||
TexMobject("r_%d" % (row_index + 1)),
|
||||
TexMobject("\\rightarrow"),
|
||||
TexMobject("("),
|
||||
FractionMobject(scale_factor),
|
||||
TexMobject(")"),
|
||||
TexMobject("r_%d" % (row_index + 1)),
|
||||
)
|
||||
label.arrange_submobjects(RIGHT, buff=SMALL_BUFF)
|
||||
label.to_edge(UP)
|
||||
VGroup(label[0], label[-1]).set_color(self.changing_row_color)
|
||||
|
||||
scalar_mob = FractionMobject(scale_factor)
|
||||
scalar_mob.add_to_back(
|
||||
TexMobject("\\times").next_to(scalar_mob, LEFT, SMALL_BUFF)
|
||||
)
|
||||
scalar_mob.scale(0.5)
|
||||
scalar_mob.next_to(row[0], DR, SMALL_BUFF)
|
||||
|
||||
# Do do, fancier illustrations here
|
||||
self.play(
|
||||
FadeIn(label),
|
||||
row.set_color, self.changing_row_color,
|
||||
)
|
||||
self.play(FadeIn(scalar_mob))
|
||||
for elem, new_elem in zip(row, new_row):
|
||||
self.play(scalar_mob.next_to, elem, DR, SMALL_BUFF)
|
||||
self.play(ReplacementTransform(elem, new_elem, path_arc=30 * DEGREES))
|
||||
self.play(FadeOut(scalar_mob))
|
||||
self.play(new_row.set_color, WHITE)
|
||||
self.play(FadeOut(label))
|
||||
self.rows.submobjects[row_index] = new_row
|
||||
|
||||
def add_row_multiple_to_row(self, row1_index, row2_index, scale_factor):
|
||||
row1 = self.rows[row1_index]
|
||||
row2 = self.rows[row2_index]
|
||||
new_row1 = VGroup()
|
||||
scaled_row2 = VGroup()
|
||||
for elem1, elem2 in zip(row1, row2):
|
||||
target = FractionMobject(elem1.value + scale_factor * elem2.value)
|
||||
target.move_to(elem1)
|
||||
new_row1.add(target)
|
||||
|
||||
scaled_term = FractionMobject(scale_factor * elem2.value)
|
||||
scaled_term.move_to(elem2)
|
||||
scaled_row2.add(scaled_term)
|
||||
new_row1.set_color(self.changing_row_color)
|
||||
scaled_row2.set_color(self.reference_row_color)
|
||||
|
||||
for elem1, elem2 in zip(row1, scaled_row2):
|
||||
elem2.add_plus_if_needed()
|
||||
elem2.scale(0.5)
|
||||
elem2.next_to(elem1, UL, buff=SMALL_BUFF)
|
||||
|
||||
label = VGroup(
|
||||
TexMobject("r_%d" % (row1_index + 1)),
|
||||
TexMobject("\\rightarrow"),
|
||||
TexMobject("r_%d" % (row1_index + 1)),
|
||||
TexMobject("+"),
|
||||
TexMobject("("),
|
||||
FractionMobject(scale_factor),
|
||||
TexMobject(")"),
|
||||
TexMobject("r_%d" % (row2_index + 1)),
|
||||
)
|
||||
label.arrange_submobjects(RIGHT, buff=SMALL_BUFF)
|
||||
label.to_edge(UP)
|
||||
VGroup(label[0], label[2]).set_color(self.changing_row_color)
|
||||
label[-1].set_color(self.reference_row_color)
|
||||
|
||||
self.play(
|
||||
FadeIn(label),
|
||||
row1.set_color, self.changing_row_color,
|
||||
row2.set_color, self.reference_row_color,
|
||||
)
|
||||
row1.target.next_to(self.rows, UP, buff=2)
|
||||
row1.target.align_to(row1, LEFT)
|
||||
|
||||
row2.target.next_to(row1.target, DOWN, buff=MED_LARGE_BUFF)
|
||||
lp, rp = row2_parens = TexMobject("()")
|
||||
row2_parens.scale_to_fit_height(row2.get_height() + 2 * SMALL_BUFF)
|
||||
lp.next_to(row2, LEFT, SMALL_BUFF)
|
||||
rp.next_to(row2, RIGHT, SMALL_BUFF)
|
||||
scalar = FractionMobject(scale_factor)
|
||||
scalar.next_to(lp, LEFT, SMALL_BUFF)
|
||||
scalar.add_plus_if_needed()
|
||||
|
||||
self.play(
|
||||
FadeIn(row2_parens),
|
||||
Write(scalar),
|
||||
)
|
||||
self.play(ReplacementTransform(row2.copy(), scaled_row2))
|
||||
self.wait()
|
||||
for elem, new_elem, s_elem in zip(row1, new_row1, scaled_row2):
|
||||
self.play(
|
||||
FadeOut(elem),
|
||||
FadeIn(new_elem),
|
||||
Transform(s_elem, new_elem.copy().fade(1), remover=True)
|
||||
)
|
||||
self.wait()
|
||||
self.play(
|
||||
FadeOut(label),
|
||||
FadeOut(row2_parens),
|
||||
FadeOut(scalar),
|
||||
new_row1.set_color, WHITE,
|
||||
row2.set_color, WHITE,
|
||||
)
|
||||
self.rows.submobjects[row1_index] = new_row1
|
|
@ -21,6 +21,7 @@ HELP_MESSAGE = """
|
|||
-p preview in low quality
|
||||
-s show and save picture of last frame
|
||||
-w write result to file [this is default if nothing else is stated]
|
||||
-o <file_name> write to a different file_name
|
||||
-l use low quality
|
||||
-m use medium quality
|
||||
-a run and save every scene in the script, or all args for the given scene
|
||||
|
|
|
@ -545,9 +545,6 @@ class Scene(Container):
|
|||
|
||||
def save_image(self, name=None, mode="RGB", dont_update=False):
|
||||
path = self.get_image_file_path(name, dont_update)
|
||||
directory_path = os.path.dirname(path)
|
||||
if not os.path.exists(directory_path):
|
||||
os.makedirs(directory_path)
|
||||
if not dont_update:
|
||||
self.update_frame(dont_update_when_skipping=False)
|
||||
image = self.get_image()
|
||||
|
|
|
@ -12,6 +12,12 @@ def add_extension_if_not_present(file_name, extension):
|
|||
return file_name
|
||||
|
||||
|
||||
def guarantee_existance(path):
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
return path
|
||||
|
||||
|
||||
def get_scene_output_directory(scene_class):
|
||||
file_path = os.path.abspath(inspect.getfile(scene_class))
|
||||
|
||||
|
@ -22,7 +28,7 @@ def get_scene_output_directory(scene_class):
|
|||
file_path = os.path.join(*sub_parts)
|
||||
file_path = file_path.replace(".pyc", "")
|
||||
file_path = file_path.replace(".py", "")
|
||||
return os.path.join(ANIMATIONS_DIR, file_path)
|
||||
return guarantee_existance(os.path.join(ANIMATIONS_DIR, file_path))
|
||||
|
||||
|
||||
def get_movie_output_directory(scene_class, camera_config, frame_duration):
|
||||
|
@ -31,8 +37,9 @@ def get_movie_output_directory(scene_class, camera_config, frame_duration):
|
|||
camera_config["pixel_shape"][0],
|
||||
int(1.0 / frame_duration)
|
||||
)
|
||||
return os.path.join(directory, sub_dir)
|
||||
return guarantee_existance(os.path.join(directory, sub_dir))
|
||||
|
||||
|
||||
def get_image_output_directory(scene_class, sub_dir="images"):
|
||||
return os.path.join(get_scene_output_directory(scene_class), sub_dir)
|
||||
directory = get_scene_output_directory(scene_class)
|
||||
return guarantee_existance(os.path.join(directory, sub_dir))
|
||||
|
|
|
@ -33,13 +33,14 @@ def there_and_back(t, inflection=10.0):
|
|||
return smooth(new_t, inflection)
|
||||
|
||||
|
||||
def there_and_back_with_pause(t):
|
||||
if t < 1. / 3:
|
||||
return smooth(3 * t)
|
||||
elif t < 2. / 3:
|
||||
def there_and_back_with_pause(t, pause_ratio=1. / 3):
|
||||
a = 1. / pause_ratio
|
||||
if t < 0.5 - pause_ratio / 2:
|
||||
return smooth(a * t)
|
||||
elif t < 0.5 + pause_ratio / 2:
|
||||
return 1
|
||||
else:
|
||||
return smooth(3 - 3 * t)
|
||||
return smooth(a - a * t)
|
||||
|
||||
|
||||
def running_start(t, pull_factor=-0.5):
|
||||
|
|
Loading…
Add table
Reference in a new issue