3b1b-manim/manimlib/animation/movement.py

118 lines
3.2 KiB
Python
Raw Normal View History

from __future__ import annotations
from manimlib.animation.animation import Animation
from manimlib.utils.rate_functions import linear
from typing import TYPE_CHECKING
if TYPE_CHECKING:
2022-04-12 19:19:59 +08:00
from typing import Callable, Sequence
import numpy as np
2022-04-12 19:19:59 +08:00
from manimlib.mobject.mobject import Mobject
class Homotopy(Animation):
2022-12-14 14:58:25 -08:00
apply_function_config: dict = dict()
def __init__(
self,
homotopy: Callable[[float, float, float, float], Sequence[float]],
mobject: Mobject,
2022-12-14 14:58:25 -08:00
run_time: float = 3.0,
**kwargs
):
"""
Homotopy is a function from
(x, y, z, t) to (x', y', z')
"""
self.homotopy = homotopy
2022-12-14 14:58:25 -08:00
super().__init__(mobject, run_time=run_time, **kwargs)
2022-12-14 14:58:25 -08:00
def function_at_time_t(self, t: float) -> Callable[[np.ndarray], Sequence[float]]:
def result(p):
return self.homotopy(*p, t)
return result
def interpolate_submobject(
self,
submob: Mobject,
start: Mobject,
alpha: float
) -> None:
2021-01-12 07:27:32 -10:00
submob.match_points(start)
submob.apply_function(
self.function_at_time_t(alpha),
2022-12-14 14:58:25 -08:00
**self.apply_function_config
)
class SmoothedVectorizedHomotopy(Homotopy):
2022-12-14 14:58:25 -08:00
apply_function_config: dict = dict(make_smooth=True)
class ComplexHomotopy(Homotopy):
def __init__(
self,
2022-12-14 14:58:25 -08:00
complex_homotopy: Callable[[complex, float], complex],
mobject: Mobject,
**kwargs
):
"""
2021-02-05 19:58:29 -08:00
Given a function form (z, t) -> w, where z and w
are complex numbers and t is time, this animates
the state over time
"""
2018-05-18 16:53:46 -07:00
def homotopy(x, y, z, t):
c = complex_homotopy(complex(x, y), t)
return (c.real, c.imag, z)
2022-12-14 14:58:25 -08:00
2021-02-05 19:58:29 -08:00
super().__init__(homotopy, mobject, **kwargs)
class PhaseFlow(Animation):
def __init__(
self,
function: Callable[[np.ndarray], np.ndarray],
mobject: Mobject,
2022-12-14 14:58:25 -08:00
virtual_time: float | None = None,
suspend_mobject_updating: bool = False,
rate_func: Callable[[float], float] = linear,
run_time: float =3.0,
**kwargs
):
self.function = function
2022-12-14 14:58:25 -08:00
self.virtual_time = virtual_time or run_time
super().__init__(
mobject,
rate_func=rate_func,
run_time=run_time,
suspend_mobject_updating=suspend_mobject_updating,
**kwargs
)
def interpolate_mobject(self, alpha: float) -> None:
if hasattr(self, "last_alpha"):
dt = self.virtual_time * (alpha - self.last_alpha)
self.mobject.apply_function(
lambda p: p + dt * self.function(p)
)
self.last_alpha = alpha
class MoveAlongPath(Animation):
2022-12-14 14:58:25 -08:00
def __init__(
self,
mobject: Mobject,
path: Mobject,
suspend_mobject_updating: bool = False,
**kwargs
):
self.path = path
2022-12-14 14:58:25 -08:00
super().__init__(mobject, suspend_mobject_updating=suspend_mobject_updating, **kwargs)
def interpolate_mobject(self, alpha: float) -> None:
point = self.path.point_from_proportion(alpha)
self.mobject.move_to(point)