2022-04-12 20:03:48 +08:00
|
|
|
from __future__ import annotations
|
|
|
|
|
2020-02-21 12:01:39 -08:00
|
|
|
import math
|
2022-02-12 23:47:23 +08:00
|
|
|
|
|
|
|
import numpy as np
|
2018-03-31 15:11:35 -07:00
|
|
|
|
2018-12-24 12:37:51 -08:00
|
|
|
from manimlib.constants import OUT
|
|
|
|
from manimlib.utils.bezier import interpolate
|
|
|
|
from manimlib.utils.space_ops import get_norm
|
2020-02-18 22:29:56 -08:00
|
|
|
from manimlib.utils.space_ops import rotation_matrix_transpose
|
2018-03-30 18:19:23 -07:00
|
|
|
|
2022-04-12 20:03:48 +08:00
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
|
|
|
|
if TYPE_CHECKING:
|
|
|
|
from typing import Callable
|
2022-12-17 22:14:53 -08:00
|
|
|
from manimlib.typing import Vect3, Vect3Array
|
2022-04-12 20:03:48 +08:00
|
|
|
|
2022-04-12 19:19:59 +08:00
|
|
|
|
2018-03-30 18:42:32 -07:00
|
|
|
STRAIGHT_PATH_THRESHOLD = 0.01
|
2018-03-30 18:19:23 -07:00
|
|
|
|
2018-04-06 13:58:59 -07:00
|
|
|
|
2022-02-12 23:47:23 +08:00
|
|
|
def straight_path(
|
|
|
|
start_points: np.ndarray,
|
|
|
|
end_points: np.ndarray,
|
|
|
|
alpha: float
|
|
|
|
) -> np.ndarray:
|
2018-03-30 18:19:23 -07:00
|
|
|
"""
|
|
|
|
Same function as interpolate, but renamed to reflect
|
|
|
|
intent of being used to determine how a set of points move
|
|
|
|
to another set. For instance, it should be a specific case
|
|
|
|
of path_along_arc
|
|
|
|
"""
|
|
|
|
return interpolate(start_points, end_points, alpha)
|
|
|
|
|
2018-04-06 13:58:59 -07:00
|
|
|
|
2022-02-12 23:47:23 +08:00
|
|
|
def path_along_arc(
|
|
|
|
arc_angle: float,
|
2022-12-17 22:14:53 -08:00
|
|
|
axis: Vect3 = OUT
|
|
|
|
) -> Callable[[Vect3Array, Vect3Array, float], Vect3Array]:
|
2018-03-30 18:19:23 -07:00
|
|
|
"""
|
2018-04-06 13:58:59 -07:00
|
|
|
If vect is vector from start to end, [vect[:,1], -vect[:,0]] is
|
2018-03-30 18:19:23 -07:00
|
|
|
perpendicular to vect in the left direction.
|
|
|
|
"""
|
|
|
|
if abs(arc_angle) < STRAIGHT_PATH_THRESHOLD:
|
|
|
|
return straight_path
|
2018-08-15 17:30:24 -07:00
|
|
|
if get_norm(axis) == 0:
|
2018-03-30 18:19:23 -07:00
|
|
|
axis = OUT
|
2018-08-15 17:30:24 -07:00
|
|
|
unit_axis = axis / get_norm(axis)
|
2018-04-06 13:58:59 -07:00
|
|
|
|
2018-03-30 18:19:23 -07:00
|
|
|
def path(start_points, end_points, alpha):
|
|
|
|
vects = end_points - start_points
|
2018-04-06 13:58:59 -07:00
|
|
|
centers = start_points + 0.5 * vects
|
2018-03-30 18:19:23 -07:00
|
|
|
if arc_angle != np.pi:
|
2020-02-21 12:01:39 -08:00
|
|
|
centers += np.cross(unit_axis, vects / 2.0) / math.tan(arc_angle / 2)
|
2020-02-18 22:29:56 -08:00
|
|
|
rot_matrix_T = rotation_matrix_transpose(alpha * arc_angle, unit_axis)
|
|
|
|
return centers + np.dot(start_points - centers, rot_matrix_T)
|
|
|
|
|
2018-03-30 18:19:23 -07:00
|
|
|
return path
|
|
|
|
|
2018-04-06 13:58:59 -07:00
|
|
|
|
2022-12-17 22:14:53 -08:00
|
|
|
def clockwise_path() -> Callable[[Vect3Array, Vect3Array, float], Vect3Array]:
|
2018-03-30 18:19:23 -07:00
|
|
|
return path_along_arc(-np.pi)
|
|
|
|
|
2018-04-06 13:58:59 -07:00
|
|
|
|
2022-12-17 22:14:53 -08:00
|
|
|
def counterclockwise_path() -> Callable[[Vect3Array, Vect3Array, float], Vect3Array]:
|
2018-04-06 13:58:59 -07:00
|
|
|
return path_along_arc(np.pi)
|