Merge pull request #1888 from 3b1b/video-work

Video work
This commit is contained in:
Grant Sanderson 2022-11-03 16:05:34 -07:00 committed by GitHub
commit 834c806e83
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 11 deletions

View file

@ -5,9 +5,9 @@ import numbers
import numpy as np import numpy as np
from manimlib.constants import BLACK, BLUE, BLUE_D, GREEN, GREY_A, WHITE from manimlib.constants import BLACK, BLUE, BLUE_D, GREEN, GREY_A, WHITE, RED
from manimlib.constants import DEGREES, PI from manimlib.constants import DEGREES, PI
from manimlib.constants import DL, DOWN, DR, LEFT, ORIGIN, OUT, RIGHT, UP from manimlib.constants import DL, UL, DOWN, DR, LEFT, ORIGIN, OUT, RIGHT, UP
from manimlib.constants import FRAME_HEIGHT, FRAME_WIDTH from manimlib.constants import FRAME_HEIGHT, FRAME_WIDTH
from manimlib.constants import FRAME_X_RADIUS, FRAME_Y_RADIUS from manimlib.constants import FRAME_X_RADIUS, FRAME_Y_RADIUS
from manimlib.constants import MED_SMALL_BUFF, SMALL_BUFF from manimlib.constants import MED_SMALL_BUFF, SMALL_BUFF
@ -19,6 +19,7 @@ from manimlib.mobject.geometry import Rectangle
from manimlib.mobject.number_line import NumberLine from manimlib.mobject.number_line import NumberLine
from manimlib.mobject.svg.tex_mobject import Tex from manimlib.mobject.svg.tex_mobject import Tex
from manimlib.mobject.types.vectorized_mobject import VGroup from manimlib.mobject.types.vectorized_mobject import VGroup
from manimlib.mobject.types.dot_cloud import DotCloud
from manimlib.utils.config_ops import digest_config from manimlib.utils.config_ops import digest_config
from manimlib.utils.config_ops import merge_dicts_recursively from manimlib.utils.config_ops import merge_dicts_recursively
from manimlib.utils.simple_functions import binary_search from manimlib.utils.simple_functions import binary_search
@ -233,6 +234,19 @@ class CoordinateSystem(ABC):
""" """
return self.input_to_graph_point(x, graph) return self.input_to_graph_point(x, graph)
def bind_graph_to_func(self, graph, func, jagged=False):
"""
Use for graphing functions which might change over time, or change with
conditions
"""
graph.x_values = [self.x_axis.p2n(p) for p in graph.get_points()]
graph.add_updater(lambda g: g.set_points([self.c2p(x, func(x)) for x in g.x_values]))
if jagged:
graph.add_updater(lambda g: g.make_jagged())
else:
graph.add_updater(lambda g: g.make_approximately_smooth())
return graph
def get_graph_label( def get_graph_label(
self, self,
graph: ParametricCurve, graph: ParametricCurve,
@ -274,6 +288,12 @@ class CoordinateSystem(ABC):
def get_h_line_to_graph(self, x: float, graph: ParametricCurve, **kwargs): def get_h_line_to_graph(self, x: float, graph: ParametricCurve, **kwargs):
return self.get_h_line(self.i2gp(x, graph), **kwargs) return self.get_h_line(self.i2gp(x, graph), **kwargs)
def get_scatterplot(self,
x_values: np.ndarray,
y_values: np.ndarray,
**dot_config):
return DotCloud(self.c2p(x_values, y_values), **dot_config)
# For calculus # For calculus
def angle_of_tangent( def angle_of_tangent(
self, self,
@ -316,6 +336,7 @@ class CoordinateSystem(ABC):
stroke_color: ManimColor = BLACK, stroke_color: ManimColor = BLACK,
fill_opacity: float = 1, fill_opacity: float = 1,
colors: Iterable[ManimColor] = (BLUE, GREEN), colors: Iterable[ManimColor] = (BLUE, GREEN),
negative_color: ManimColor = RED,
stroke_background: bool = True, stroke_background: bool = True,
show_signed_area: bool = True show_signed_area: bool = True
) -> VGroup: ) -> VGroup:
@ -338,12 +359,13 @@ class CoordinateSystem(ABC):
sample = 0.5 * x0 + 0.5 * x1 sample = 0.5 * x0 + 0.5 * x1
else: else:
raise Exception("Invalid input sample type") raise Exception("Invalid input sample type")
height = get_norm( height_vect = self.i2gp(sample, graph) - self.c2p(sample, 0)
self.i2gp(sample, graph) - self.c2p(sample, 0) rect = Rectangle(
width=self.x_axis.n2p(x1)[0] - self.x_axis.n2p(x0)[0],
height=get_norm(height_vect),
) )
rect = Rectangle(width=self.x_axis.n2p(x1)[0] - self.x_axis.n2p(x0)[0], rect.positive = height_vect[1] > 0
height=height) rect.move_to(self.c2p(x0, 0), DL if rect.positive else UL)
rect.move_to(self.c2p(x0, 0), DL)
rects.append(rect) rects.append(rect)
result = VGroup(*rects) result = VGroup(*rects)
result.set_submobject_colors_by_gradient(*colors) result.set_submobject_colors_by_gradient(*colors)
@ -353,6 +375,9 @@ class CoordinateSystem(ABC):
fill_opacity=fill_opacity, fill_opacity=fill_opacity,
stroke_background=stroke_background stroke_background=stroke_background
) )
for rect in result:
if not rect.positive:
rect.set_fill(negative_color)
return result return result
def get_area_under_graph(self, graph, x_range, fill_color=BLUE, fill_opacity=1): def get_area_under_graph(self, graph, x_range, fill_color=BLUE, fill_opacity=1):
@ -647,7 +672,7 @@ class ComplexPlane(NumberPlane):
if abs(z.imag) > abs(z.real): if abs(z.imag) > abs(z.real):
axis = self.get_y_axis() axis = self.get_y_axis()
value = z.imag value = z.imag
kwargs["unit"] = "i" kwargs["unit_tex"] = "i"
else: else:
axis = self.get_x_axis() axis = self.get_x_axis()
value = z.real value = z.real

View file

@ -1449,7 +1449,7 @@ class Mobject(object):
return interpolate(points[i], points[i + 1], subalpha) return interpolate(points[i], points[i + 1], subalpha)
def pfp(self, alpha): def pfp(self, alpha):
"""Abbreviation fo point_from_proportion""" """Abbreviation for point_from_proportion"""
return self.point_from_proportion(alpha) return self.point_from_proportion(alpha)
def get_pieces(self, n_pieces: int) -> Group: def get_pieces(self, n_pieces: int) -> Group:

View file

@ -143,17 +143,21 @@ class NumberLine(Line):
x: float, x: float,
direction: np.ndarray | None = None, direction: np.ndarray | None = None,
buff: float | None = None, buff: float | None = None,
unit: float = 1.0,
unit_tex: str = "",
**number_config **number_config
) -> DecimalNumber: ) -> DecimalNumber:
number_config = merge_dicts_recursively( number_config = merge_dicts_recursively(
self.decimal_number_config, number_config self.decimal_number_config, number_config,
) )
if direction is None: if direction is None:
direction = self.line_to_number_direction direction = self.line_to_number_direction
if buff is None: if buff is None:
buff = self.line_to_number_buff buff = self.line_to_number_buff
if unit_tex:
number_config["unit"] = unit_tex
num_mob = DecimalNumber(x, **number_config) num_mob = DecimalNumber(x / unit, **number_config)
num_mob.next_to( num_mob.next_to(
self.number_to_point(x), self.number_to_point(x),
direction=direction, direction=direction,
@ -162,6 +166,10 @@ class NumberLine(Line):
if x < 0 and direction[0] == 0: if x < 0 and direction[0] == 0:
# Align without the minus sign # Align without the minus sign
num_mob.shift(num_mob[0].get_width() * LEFT / 2) num_mob.shift(num_mob[0].get_width() * LEFT / 2)
if x == unit and unit_tex:
center = num_mob.get_center()
num_mob.remove(num_mob[0])
num_mob.move_to(center)
return num_mob return num_mob
def add_numbers( def add_numbers(