Rename np_vector type to Vect3 or Vect4 to make context clearer

This commit is contained in:
Grant Sanderson 2022-12-16 20:35:26 -08:00
parent 43fd5e1aea
commit dec11a4b17
20 changed files with 284 additions and 285 deletions

View file

@ -29,14 +29,14 @@ if TYPE_CHECKING:
from manimlib.typing import ManimColor from manimlib.typing import ManimColor
from typing import Sequence from typing import Sequence
np_vector = np.ndarray[int, np.dtype[np.float64]] Vect3 = np.ndarray[int, np.dtype[np.float64]]
class CameraFrame(Mobject): class CameraFrame(Mobject):
def __init__( def __init__(
self, self,
frame_shape: tuple[float, float] = (FRAME_WIDTH, FRAME_HEIGHT), frame_shape: tuple[float, float] = (FRAME_WIDTH, FRAME_HEIGHT),
center_point: np_vector = ORIGIN, center_point: Vect3 = ORIGIN,
focal_dist_to_height: float = 2.0, focal_dist_to_height: float = 2.0,
**kwargs, **kwargs,
): ):

View file

@ -4,7 +4,7 @@ import numpy as np
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import List from typing import List
from manimlib.typing import ManimColor, np_vector from manimlib.typing import ManimColor, Vect3
# Sizes relevant to default camera frame # Sizes relevant to default camera frame
@ -31,27 +31,27 @@ DEFAULT_MOBJECT_TO_MOBJECT_BUFFER: float = MED_SMALL_BUFF
DEFAULT_WAIT_TIME: float = 1.0 DEFAULT_WAIT_TIME: float = 1.0
ORIGIN: np_vector = np.array([0., 0., 0.]) ORIGIN: Vect3 = np.array([0., 0., 0.])
UP: np_vector = np.array([0., 1., 0.]) UP: Vect3 = np.array([0., 1., 0.])
DOWN: np_vector = np.array([0., -1., 0.]) DOWN: Vect3 = np.array([0., -1., 0.])
RIGHT: np_vector = np.array([1., 0., 0.]) RIGHT: Vect3 = np.array([1., 0., 0.])
LEFT: np_vector = np.array([-1., 0., 0.]) LEFT: Vect3 = np.array([-1., 0., 0.])
IN: np_vector = np.array([0., 0., -1.]) IN: Vect3 = np.array([0., 0., -1.])
OUT: np_vector = np.array([0., 0., 1.]) OUT: Vect3 = np.array([0., 0., 1.])
X_AXIS: np_vector = np.array([1., 0., 0.]) X_AXIS: Vect3 = np.array([1., 0., 0.])
Y_AXIS: np_vector = np.array([0., 1., 0.]) Y_AXIS: Vect3 = np.array([0., 1., 0.])
Z_AXIS: np_vector = np.array([0., 0., 1.]) Z_AXIS: Vect3 = np.array([0., 0., 1.])
# Useful abbreviations for diagonals # Useful abbreviations for diagonals
UL: np_vector = UP + LEFT UL: Vect3 = UP + LEFT
UR: np_vector = UP + RIGHT UR: Vect3 = UP + RIGHT
DL: np_vector = DOWN + LEFT DL: Vect3 = DOWN + LEFT
DR: np_vector = DOWN + RIGHT DR: Vect3 = DOWN + RIGHT
TOP: np_vector = FRAME_Y_RADIUS * UP TOP: Vect3 = FRAME_Y_RADIUS * UP
BOTTOM: np_vector = FRAME_Y_RADIUS * DOWN BOTTOM: Vect3 = FRAME_Y_RADIUS * DOWN
LEFT_SIDE: np_vector = FRAME_X_RADIUS * LEFT LEFT_SIDE: Vect3 = FRAME_X_RADIUS * LEFT
RIGHT_SIDE: np_vector = FRAME_X_RADIUS * RIGHT RIGHT_SIDE: Vect3 = FRAME_X_RADIUS * RIGHT
PI: float = np.pi PI: float = np.pi
TAU: float = 2 * PI TAU: float = 2 * PI

View file

@ -12,7 +12,7 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Callable, List, Iterable from typing import Callable, List, Iterable
from manimlib.typing import ManimColor, np_vector from manimlib.typing import ManimColor, Vect3
class AnimatedBoundary(VGroup): class AnimatedBoundary(VGroup):
@ -97,7 +97,7 @@ class AnimatedBoundary(VGroup):
class TracedPath(VMobject): class TracedPath(VMobject):
def __init__( def __init__(
self, self,
traced_point_func: Callable[[], np_vector], traced_point_func: Callable[[], Vect3],
time_traced: float = np.inf, time_traced: float = np.inf,
time_per_anchor: float = 1.0 / 15, time_per_anchor: float = 1.0 / 15,
stroke_width: float | Iterable[float] = 2.0, stroke_width: float | Iterable[float] = 2.0,

View file

@ -34,7 +34,7 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Callable, Iterable, Sequence, Type, TypeVar from typing import Callable, Iterable, Sequence, Type, TypeVar
from manimlib.mobject.mobject import Mobject from manimlib.mobject.mobject import Mobject
from manimlib.typing import ManimColor, np_vector, RangeSpecifier from manimlib.typing import ManimColor, Vect3, RangeSpecifier
T = TypeVar("T", bound=Mobject) T = TypeVar("T", bound=Mobject)
@ -61,22 +61,22 @@ class CoordinateSystem(ABC):
self.num_sampled_graph_points_per_tick = num_sampled_graph_points_per_tick self.num_sampled_graph_points_per_tick = num_sampled_graph_points_per_tick
@abstractmethod @abstractmethod
def coords_to_point(self, *coords: float) -> np_vector: def coords_to_point(self, *coords: float) -> Vect3:
raise Exception("Not implemented") raise Exception("Not implemented")
@abstractmethod @abstractmethod
def point_to_coords(self, point: np_vector) -> tuple[float, ...]: def point_to_coords(self, point: Vect3) -> tuple[float, ...]:
raise Exception("Not implemented") raise Exception("Not implemented")
def c2p(self, *coords: float): def c2p(self, *coords: float):
"""Abbreviation for coords_to_point""" """Abbreviation for coords_to_point"""
return self.coords_to_point(*coords) return self.coords_to_point(*coords)
def p2c(self, point: np_vector): def p2c(self, point: Vect3):
"""Abbreviation for point_to_coords""" """Abbreviation for point_to_coords"""
return self.point_to_coords(point) return self.point_to_coords(point)
def get_origin(self) -> np_vector: def get_origin(self) -> Vect3:
return self.c2p(*[0] * self.dimension) return self.c2p(*[0] * self.dimension)
@abstractmethod @abstractmethod
@ -102,8 +102,8 @@ class CoordinateSystem(ABC):
def get_x_axis_label( def get_x_axis_label(
self, self,
label_tex: str, label_tex: str,
edge: np_vector = RIGHT, edge: Vect3 = RIGHT,
direction: np_vector = DL, direction: Vect3 = DL,
**kwargs **kwargs
) -> Tex: ) -> Tex:
return self.get_axis_label( return self.get_axis_label(
@ -114,8 +114,8 @@ class CoordinateSystem(ABC):
def get_y_axis_label( def get_y_axis_label(
self, self,
label_tex: str, label_tex: str,
edge: np_vector = UP, edge: Vect3 = UP,
direction: np_vector = DR, direction: Vect3 = DR,
**kwargs **kwargs
) -> Tex: ) -> Tex:
return self.get_axis_label( return self.get_axis_label(
@ -126,9 +126,9 @@ class CoordinateSystem(ABC):
def get_axis_label( def get_axis_label(
self, self,
label_tex: str, label_tex: str,
axis: np_vector, axis: Vect3,
edge: np_vector, edge: Vect3,
direction: np_vector, direction: Vect3,
buff: float = MED_SMALL_BUFF buff: float = MED_SMALL_BUFF
) -> Tex: ) -> Tex:
label = Tex(label_tex) label = Tex(label_tex)
@ -153,7 +153,7 @@ class CoordinateSystem(ABC):
def get_line_from_axis_to_point( def get_line_from_axis_to_point(
self, self,
index: int, index: int,
point: np_vector, point: Vect3,
line_func: Type[T] = DashedLine, line_func: Type[T] = DashedLine,
color: ManimColor = GREY_A, color: ManimColor = GREY_A,
stroke_width: float = 2 stroke_width: float = 2
@ -163,10 +163,10 @@ class CoordinateSystem(ABC):
line.set_stroke(color, stroke_width) line.set_stroke(color, stroke_width)
return line return line
def get_v_line(self, point: np_vector, **kwargs): def get_v_line(self, point: Vect3, **kwargs):
return self.get_line_from_axis_to_point(0, point, **kwargs) return self.get_line_from_axis_to_point(0, point, **kwargs)
def get_h_line(self, point: np_vector, **kwargs): def get_h_line(self, point: Vect3, **kwargs):
return self.get_line_from_axis_to_point(1, point, **kwargs) return self.get_line_from_axis_to_point(1, point, **kwargs)
# Useful for graphing # Useful for graphing
@ -184,7 +184,7 @@ class CoordinateSystem(ABC):
# sample frequency # sample frequency
t_range[2] /= self.num_sampled_graph_points_per_tick t_range[2] /= self.num_sampled_graph_points_per_tick
def parametric_function(t: float) -> np_vector: def parametric_function(t: float) -> Vect3:
return self.c2p(t, function(t)) return self.c2p(t, function(t))
graph = ParametricCurve( graph = ParametricCurve(
@ -198,7 +198,7 @@ class CoordinateSystem(ABC):
def get_parametric_curve( def get_parametric_curve(
self, self,
function: Callable[[float], np_vector], function: Callable[[float], Vect3],
**kwargs **kwargs
) -> ParametricCurve: ) -> ParametricCurve:
dim = self.dimension dim = self.dimension
@ -213,7 +213,7 @@ class CoordinateSystem(ABC):
self, self,
x: float, x: float,
graph: ParametricCurve graph: ParametricCurve
) -> np_vector | None: ) -> Vect3 | None:
if hasattr(graph, "underlying_function"): if hasattr(graph, "underlying_function"):
return self.coords_to_point(x, graph.underlying_function(x)) return self.coords_to_point(x, graph.underlying_function(x))
else: else:
@ -230,7 +230,7 @@ class CoordinateSystem(ABC):
else: else:
return None return None
def i2gp(self, x: float, graph: ParametricCurve) -> np_vector | None: def i2gp(self, x: float, graph: ParametricCurve) -> Vect3 | None:
""" """
Alias for input_to_graph_point Alias for input_to_graph_point
""" """
@ -265,7 +265,7 @@ class CoordinateSystem(ABC):
graph: ParametricCurve, graph: ParametricCurve,
label: str | Mobject = "f(x)", label: str | Mobject = "f(x)",
x: float | None = None, x: float | None = None,
direction: np_vector = RIGHT, direction: Vect3 = RIGHT,
buff: float = MED_SMALL_BUFF, buff: float = MED_SMALL_BUFF,
color: ManimColor | None = None color: ManimColor | None = None
) -> Tex | Mobject: ) -> Tex | Mobject:
@ -302,8 +302,8 @@ class CoordinateSystem(ABC):
return self.get_h_line(self.i2gp(x, graph), **kwargs) return self.get_h_line(self.i2gp(x, graph), **kwargs)
def get_scatterplot(self, def get_scatterplot(self,
x_values: np_vector, x_values: Vect3,
y_values: np_vector, y_values: Vect3,
**dot_config): **dot_config):
return DotCloud(self.c2p(x_values, y_values), **dot_config) return DotCloud(self.c2p(x_values, y_values), **dot_config)
@ -449,14 +449,14 @@ class Axes(VGroup, CoordinateSystem):
axis.shift(-axis.n2p(0)) axis.shift(-axis.n2p(0))
return axis return axis
def coords_to_point(self, *coords: float) -> np_vector: def coords_to_point(self, *coords: float) -> Vect3:
origin = self.x_axis.number_to_point(0) origin = self.x_axis.number_to_point(0)
return origin + sum( return origin + sum(
axis.number_to_point(coord) - origin axis.number_to_point(coord) - origin
for axis, coord in zip(self.get_axes(), coords) for axis, coord in zip(self.get_axes(), coords)
) )
def point_to_coords(self, point: np_vector) -> tuple[float, ...]: def point_to_coords(self, point: Vect3) -> tuple[float, ...]:
return tuple([ return tuple([
axis.point_to_number(point) axis.point_to_number(point)
for axis in self.get_axes() for axis in self.get_axes()
@ -492,7 +492,7 @@ class ThreeDAxes(Axes):
y_range: RangeSpecifier = (-5.0, 5.0, 1.0), y_range: RangeSpecifier = (-5.0, 5.0, 1.0),
z_range: RangeSpecifier = (-4.0, 4.0, 1.0), z_range: RangeSpecifier = (-4.0, 4.0, 1.0),
z_axis_config: dict = dict(), z_axis_config: dict = dict(),
z_normal: np_vector = DOWN, z_normal: Vect3 = DOWN,
depth: float = 6.0, depth: float = 6.0,
num_axis_pieces: int = 20, num_axis_pieces: int = 20,
gloss: float = 0.5, gloss: float = 0.5,
@ -664,18 +664,18 @@ class NumberPlane(Axes):
class ComplexPlane(NumberPlane): class ComplexPlane(NumberPlane):
def number_to_point(self, number: complex | float) -> np_vector: def number_to_point(self, number: complex | float) -> Vect3:
number = complex(number) number = complex(number)
return self.coords_to_point(number.real, number.imag) return self.coords_to_point(number.real, number.imag)
def n2p(self, number: complex | float) -> np_vector: def n2p(self, number: complex | float) -> Vect3:
return self.number_to_point(number) return self.number_to_point(number)
def point_to_number(self, point: np_vector) -> complex: def point_to_number(self, point: Vect3) -> complex:
x, y = self.point_to_coords(point) x, y = self.point_to_coords(point)
return complex(x, y) return complex(x, y)
def p2n(self, point: np_vector) -> complex: def p2n(self, point: Vect3) -> complex:
return self.point_to_number(point) return self.point_to_number(point)
def get_default_coordinate_values( def get_default_coordinate_values(

View file

@ -11,13 +11,13 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Callable, Sequence, Tuple from typing import Callable, Sequence, Tuple
from manimlib.typing import ManimColor, np_vector from manimlib.typing import ManimColor, Vect3
class ParametricCurve(VMobject): class ParametricCurve(VMobject):
def __init__( def __init__(
self, self,
t_func: Callable[[float], Sequence[float] | np_vector], t_func: Callable[[float], Sequence[float] | Vect3],
t_range: Tuple[float, float, float] = (0, 1, 0.1), t_range: Tuple[float, float, float] = (0, 1, 0.1),
epsilon: float = 1e-8, epsilon: float = 1e-8,
# TODO, automatically figure out discontinuities # TODO, automatically figure out discontinuities
@ -32,7 +32,7 @@ class ParametricCurve(VMobject):
self.use_smoothing = use_smoothing self.use_smoothing = use_smoothing
super().__init__(**kwargs) super().__init__(**kwargs)
def get_point_from_function(self, t: float) -> np_vector: def get_point_from_function(self, t: float) -> Vect3:
return np.array(self.t_func(t)) return np.array(self.t_func(t))
def init_points(self): def init_points(self):

View file

@ -30,7 +30,7 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Iterable from typing import Iterable
from manimlib.typing import ManimColor, np_vector from manimlib.typing import ManimColor, Vect3
DEFAULT_DOT_RADIUS = 0.08 DEFAULT_DOT_RADIUS = 0.08
@ -177,19 +177,19 @@ class TipableVMobject(VMobject):
def get_default_tip_length(self) -> float: def get_default_tip_length(self) -> float:
return self.tip_length return self.tip_length
def get_first_handle(self) -> np_vector: def get_first_handle(self) -> Vect3:
return self.get_points()[1] return self.get_points()[1]
def get_last_handle(self) -> np_vector: def get_last_handle(self) -> Vect3:
return self.get_points()[-2] return self.get_points()[-2]
def get_end(self) -> np_vector: def get_end(self) -> Vect3:
if self.has_tip(): if self.has_tip():
return self.tip.get_start() return self.tip.get_start()
else: else:
return VMobject.get_end(self) return VMobject.get_end(self)
def get_start(self) -> np_vector: def get_start(self) -> Vect3:
if self.has_start_tip(): if self.has_start_tip():
return self.start_tip.get_start() return self.start_tip.get_start()
else: else:
@ -207,7 +207,7 @@ class Arc(TipableVMobject):
angle: float = TAU / 4, angle: float = TAU / 4,
radius: float = 1.0, radius: float = 1.0,
n_components: int = 8, n_components: int = 8,
arc_center: np_vector = ORIGIN, arc_center: Vect3 = ORIGIN,
**kwargs **kwargs
): ):
super().__init__(**kwargs) super().__init__(**kwargs)
@ -225,7 +225,7 @@ class Arc(TipableVMobject):
angle: float, angle: float,
start_angle: float = 0, start_angle: float = 0,
n_components: int = 8 n_components: int = 8
) -> np_vector: ) -> Vect3:
samples = np.array([ samples = np.array([
[np.cos(a), np.sin(a), 0] [np.cos(a), np.sin(a), 0]
for a in np.linspace( for a in np.linspace(
@ -243,7 +243,7 @@ class Arc(TipableVMobject):
points[2::3] = samples[2::2] points[2::3] = samples[2::2]
return points return points
def get_arc_center(self) -> np_vector: def get_arc_center(self) -> Vect3:
""" """
Looks at the normals to the first two Looks at the normals to the first two
anchors, and finds their intersection points anchors, and finds their intersection points
@ -266,7 +266,7 @@ class Arc(TipableVMobject):
angle = angle_of_vector(self.get_end() - self.get_arc_center()) angle = angle_of_vector(self.get_end() - self.get_arc_center())
return angle % TAU return angle % TAU
def move_arc_center_to(self, point: np_vector): def move_arc_center_to(self, point: Vect3):
self.shift(point - self.get_arc_center()) self.shift(point - self.get_arc_center())
return self return self
@ -274,8 +274,8 @@ class Arc(TipableVMobject):
class ArcBetweenPoints(Arc): class ArcBetweenPoints(Arc):
def __init__( def __init__(
self, self,
start: np_vector, start: Vect3,
end: np_vector, end: Vect3,
angle: float = TAU / 4, angle: float = TAU / 4,
**kwargs **kwargs
): ):
@ -288,8 +288,8 @@ class ArcBetweenPoints(Arc):
class CurvedArrow(ArcBetweenPoints): class CurvedArrow(ArcBetweenPoints):
def __init__( def __init__(
self, self,
start_point: np_vector, start_point: Vect3,
end_point: np_vector, end_point: Vect3,
**kwargs **kwargs
): ):
super().__init__(start_point, end_point, **kwargs) super().__init__(start_point, end_point, **kwargs)
@ -299,8 +299,8 @@ class CurvedArrow(ArcBetweenPoints):
class CurvedDoubleArrow(CurvedArrow): class CurvedDoubleArrow(CurvedArrow):
def __init__( def __init__(
self, self,
start_point: np_vector, start_point: Vect3,
end_point: np_vector, end_point: Vect3,
**kwargs **kwargs
): ):
super().__init__(start_point, end_point, **kwargs) super().__init__(start_point, end_point, **kwargs)
@ -334,7 +334,7 @@ class Circle(Arc):
self.stretch((self.get_height() + 2 * buff) / self.get_height(), 1) self.stretch((self.get_height() + 2 * buff) / self.get_height(), 1)
return self return self
def point_at_angle(self, angle: float) -> np_vector: def point_at_angle(self, angle: float) -> Vect3:
start_angle = self.get_start_angle() start_angle = self.get_start_angle()
return self.point_from_proportion( return self.point_from_proportion(
((angle - start_angle) % TAU) / TAU ((angle - start_angle) % TAU) / TAU
@ -347,7 +347,7 @@ class Circle(Arc):
class Dot(Circle): class Dot(Circle):
def __init__( def __init__(
self, self,
point: np_vector = ORIGIN, point: Vect3 = ORIGIN,
radius: float = DEFAULT_DOT_RADIUS, radius: float = DEFAULT_DOT_RADIUS,
stroke_color: ManimColor = BLACK, stroke_color: ManimColor = BLACK,
stroke_width: float = 0.0, stroke_width: float = 0.0,
@ -369,7 +369,7 @@ class Dot(Circle):
class SmallDot(Dot): class SmallDot(Dot):
def __init__( def __init__(
self, self,
point: np_vector = ORIGIN, point: Vect3 = ORIGIN,
radius: float = DEFAULT_SMALL_DOT_RADIUS, radius: float = DEFAULT_SMALL_DOT_RADIUS,
**kwargs **kwargs
): ):
@ -395,7 +395,7 @@ class AnnularSector(VMobject):
start_angle: float = 0.0, start_angle: float = 0.0,
inner_radius: float = 1.0, inner_radius: float = 1.0,
outer_radius: float = 2.0, outer_radius: float = 2.0,
arc_center: np_vector = ORIGIN, arc_center: Vect3 = ORIGIN,
fill_color: ManimColor = GREY_A, fill_color: ManimColor = GREY_A,
fill_opacity: float = 1.0, fill_opacity: float = 1.0,
stroke_width: float = 0.0, stroke_width: float = 0.0,
@ -447,7 +447,7 @@ class Annulus(VMobject):
fill_opacity: float = 1.0, fill_opacity: float = 1.0,
stroke_width: float = 0.0, stroke_width: float = 0.0,
fill_color: ManimColor = GREY_A, fill_color: ManimColor = GREY_A,
center: np_vector = ORIGIN, center: Vect3 = ORIGIN,
**kwargs, **kwargs,
): ):
super().__init__( super().__init__(
@ -468,8 +468,8 @@ class Annulus(VMobject):
class Line(TipableVMobject): class Line(TipableVMobject):
def __init__( def __init__(
self, self,
start: np_vector | Mobject = LEFT, start: Vect3 | Mobject = LEFT,
end: np_vector | Mobject = RIGHT, end: Vect3 | Mobject = RIGHT,
buff: float = 0.0, buff: float = 0.0,
path_arc: float = 0.0, path_arc: float = 0.0,
**kwargs **kwargs
@ -481,8 +481,8 @@ class Line(TipableVMobject):
def set_points_by_ends( def set_points_by_ends(
self, self,
start: np_vector, start: Vect3,
end: np_vector, end: Vect3,
buff: float = 0, buff: float = 0,
path_arc: float = 0 path_arc: float = 0
): ):
@ -518,7 +518,7 @@ class Line(TipableVMobject):
self.path_arc = new_value self.path_arc = new_value
self.init_points() self.init_points()
def set_start_and_end_attrs(self, start: np_vector | Mobject, end: np_vector | Mobject): def set_start_and_end_attrs(self, start: Vect3 | Mobject, end: Vect3 | Mobject):
# If either start or end are Mobjects, this # If either start or end are Mobjects, this
# gives their centers # gives their centers
rough_start = self.pointify(start) rough_start = self.pointify(start)
@ -532,9 +532,9 @@ class Line(TipableVMobject):
def pointify( def pointify(
self, self,
mob_or_point: Mobject | np_vector, mob_or_point: Mobject | Vect3,
direction: np_vector | None = None direction: Vect3 | None = None
) -> np_vector: ) -> Vect3:
""" """
Take an argument passed into Line (or subclass) and turn Take an argument passed into Line (or subclass) and turn
it into a 3d point. it into a 3d point.
@ -551,7 +551,7 @@ class Line(TipableVMobject):
result[:len(point)] = point result[:len(point)] = point
return result return result
def put_start_and_end_on(self, start: np_vector, end: np_vector): def put_start_and_end_on(self, start: Vect3, end: Vect3):
curr_start, curr_end = self.get_start_and_end() curr_start, curr_end = self.get_start_and_end()
if np.isclose(curr_start, curr_end).all(): if np.isclose(curr_start, curr_end).all():
# Handle null lines more gracefully # Handle null lines more gracefully
@ -559,16 +559,16 @@ class Line(TipableVMobject):
return self return self
return super().put_start_and_end_on(start, end) return super().put_start_and_end_on(start, end)
def get_vector(self) -> np_vector: def get_vector(self) -> Vect3:
return self.get_end() - self.get_start() return self.get_end() - self.get_start()
def get_unit_vector(self) -> np_vector: def get_unit_vector(self) -> Vect3:
return normalize(self.get_vector()) return normalize(self.get_vector())
def get_angle(self) -> float: def get_angle(self) -> float:
return angle_of_vector(self.get_vector()) return angle_of_vector(self.get_vector())
def get_projection(self, point: np_vector) -> np_vector: def get_projection(self, point: Vect3) -> Vect3:
""" """
Return projection of a point onto the line Return projection of a point onto the line
""" """
@ -579,7 +579,7 @@ class Line(TipableVMobject):
def get_slope(self) -> float: def get_slope(self) -> float:
return np.tan(self.get_angle()) return np.tan(self.get_angle())
def set_angle(self, angle: float, about_point: np_vector | None = None): def set_angle(self, angle: float, about_point: Vect3 | None = None):
if about_point is None: if about_point is None:
about_point = self.get_start() about_point = self.get_start()
self.rotate( self.rotate(
@ -601,8 +601,8 @@ class Line(TipableVMobject):
class DashedLine(Line): class DashedLine(Line):
def __init__( def __init__(
self, self,
start: np_vector = LEFT, start: Vect3 = LEFT,
end: np_vector = RIGHT, end: Vect3 = RIGHT,
dash_length: float = DEFAULT_DASH_LENGTH, dash_length: float = DEFAULT_DASH_LENGTH,
positive_space_ratio: float = 0.5, positive_space_ratio: float = 0.5,
**kwargs **kwargs
@ -625,22 +625,22 @@ class DashedLine(Line):
except ZeroDivisionError: except ZeroDivisionError:
return 1 return 1
def get_start(self) -> np_vector: def get_start(self) -> Vect3:
if len(self.submobjects) > 0: if len(self.submobjects) > 0:
return self.submobjects[0].get_start() return self.submobjects[0].get_start()
else: else:
return Line.get_start(self) return Line.get_start(self)
def get_end(self) -> np_vector: def get_end(self) -> Vect3:
if len(self.submobjects) > 0: if len(self.submobjects) > 0:
return self.submobjects[-1].get_end() return self.submobjects[-1].get_end()
else: else:
return Line.get_end(self) return Line.get_end(self)
def get_first_handle(self) -> np_vector: def get_first_handle(self) -> Vect3:
return self.submobjects[0].get_points()[1] return self.submobjects[0].get_points()[1]
def get_last_handle(self) -> np_vector: def get_last_handle(self) -> Vect3:
return self.submobjects[-1].get_points()[-2] return self.submobjects[-1].get_points()[-2]
@ -675,8 +675,8 @@ class Elbow(VMobject):
class Arrow(Line): class Arrow(Line):
def __init__( def __init__(
self, self,
start: np_vector | Mobject, start: Vect3 | Mobject,
end: np_vector | Mobject, end: Vect3 | Mobject,
stroke_color: ManimColor = GREY_A, stroke_color: ManimColor = GREY_A,
stroke_width: float = 5, stroke_width: float = 5,
buff: float = 0.25, buff: float = 0.25,
@ -701,8 +701,8 @@ class Arrow(Line):
def set_points_by_ends( def set_points_by_ends(
self, self,
start: np_vector, start: Vect3,
end: np_vector, end: Vect3,
buff: float = 0, buff: float = 0,
path_arc: float = 0 path_arc: float = 0
): ):
@ -766,8 +766,8 @@ class Arrow(Line):
class FillArrow(Line): class FillArrow(Line):
def __init__( def __init__(
self, self,
start: np_vector | Mobject = LEFT, start: Vect3 | Mobject = LEFT,
end: np_vector | Mobject = LEFT, end: Vect3 | Mobject = LEFT,
fill_color: ManimColor = GREY_A, fill_color: ManimColor = GREY_A,
fill_opacity: float = 1.0, fill_opacity: float = 1.0,
stroke_width: float = 0.0, stroke_width: float = 0.0,
@ -795,8 +795,8 @@ class FillArrow(Line):
def set_points_by_ends( def set_points_by_ends(
self, self,
start: np_vector, start: Vect3,
end: np_vector, end: Vect3,
buff: float = 0, buff: float = 0,
path_arc: float = 0 path_arc: float = 0
) -> None: ) -> None:
@ -868,15 +868,15 @@ class FillArrow(Line):
) )
return self return self
def get_start(self) -> np_vector: def get_start(self) -> Vect3:
nppc = self.n_points_per_curve nppc = self.n_points_per_curve
points = self.get_points() points = self.get_points()
return (points[0] + points[-nppc]) / 2 return (points[0] + points[-nppc]) / 2
def get_end(self) -> np_vector: def get_end(self) -> Vect3:
return self.get_points()[self.tip_index] return self.get_points()[self.tip_index]
def put_start_and_end_on(self, start: np_vector, end: np_vector): def put_start_and_end_on(self, start: Vect3, end: Vect3):
self.set_points_by_ends(start, end, buff=0, path_arc=self.path_arc) self.set_points_by_ends(start, end, buff=0, path_arc=self.path_arc)
return self return self
@ -899,7 +899,7 @@ class FillArrow(Line):
class Vector(Arrow): class Vector(Arrow):
def __init__( def __init__(
self, self,
direction: np_vector = RIGHT, direction: Vect3 = RIGHT,
buff: float = 0.0, buff: float = 0.0,
**kwargs **kwargs
): ):
@ -911,10 +911,10 @@ class Vector(Arrow):
class CubicBezier(VMobject): class CubicBezier(VMobject):
def __init__( def __init__(
self, self,
a0: np_vector, a0: Vect3,
h0: np_vector, h0: Vect3,
h1: np_vector, h1: Vect3,
a1: np_vector, a1: Vect3,
**kwargs **kwargs
): ):
super().__init__(**kwargs) super().__init__(**kwargs)
@ -922,11 +922,11 @@ class CubicBezier(VMobject):
class Polygon(VMobject): class Polygon(VMobject):
def __init__(self, *vertices: np_vector, **kwargs): def __init__(self, *vertices: Vect3, **kwargs):
super().__init__(**kwargs) super().__init__(**kwargs)
self.set_points_as_corners([*vertices, vertices[0]]) self.set_points_as_corners([*vertices, vertices[0]])
def get_vertices(self) -> list[np_vector]: def get_vertices(self) -> list[Vect3]:
return self.get_start_anchors() return self.get_start_anchors()
def round_corners(self, radius: float | None = None): def round_corners(self, radius: float | None = None):
@ -976,7 +976,7 @@ class Polygon(VMobject):
class Polyline(VMobject): class Polyline(VMobject):
def __init__(self, *vertices: np_vector, **kwargs): def __init__(self, *vertices: Vect3, **kwargs):
super().__init__(**kwargs) super().__init__(**kwargs)
self.set_points_as_corners(vertices) self.set_points_as_corners(vertices)
@ -1031,13 +1031,13 @@ class ArrowTip(Triangle):
self.data["points"] = Dot().set_width(h).get_points() self.data["points"] = Dot().set_width(h).get_points()
self.rotate(angle) self.rotate(angle)
def get_base(self) -> np_vector: def get_base(self) -> Vect3:
return self.point_from_proportion(0.5) return self.point_from_proportion(0.5)
def get_tip_point(self) -> np_vector: def get_tip_point(self) -> Vect3:
return self.get_points()[0] return self.get_points()[0]
def get_vector(self) -> np_vector: def get_vector(self) -> Vect3:
return self.get_tip_point() - self.get_base() return self.get_tip_point() - self.get_base()
def get_angle(self) -> float: def get_angle(self) -> float:

View file

@ -21,7 +21,7 @@ if TYPE_CHECKING:
from typing import Sequence from typing import Sequence
import numpy.typing as npt import numpy.typing as npt
from manimlib.mobject.mobject import Mobject from manimlib.mobject.mobject import Mobject
from manimlib.typing import ManimColor, np_vector from manimlib.typing import ManimColor, Vect3
VECTOR_LABEL_SCALE_FACTOR = 0.8 VECTOR_LABEL_SCALE_FACTOR = 0.8
@ -82,7 +82,7 @@ class Matrix(VMobject):
add_background_rectangles_to_entries: bool = False, add_background_rectangles_to_entries: bool = False,
include_background_rectangle: bool = False, include_background_rectangle: bool = False,
element_config: dict = dict(), element_config: dict = dict(),
element_alignment_corner: np_vector = DOWN, element_alignment_corner: Vect3 = DOWN,
**kwargs **kwargs
): ):
""" """
@ -123,7 +123,7 @@ class Matrix(VMobject):
matrix: list[list[Mobject]], matrix: list[list[Mobject]],
v_buff: float, v_buff: float,
h_buff: float, h_buff: float,
aligned_corner: np_vector, aligned_corner: Vect3,
): ):
for i, row in enumerate(matrix): for i, row in enumerate(matrix):
for j, elem in enumerate(row): for j, elem in enumerate(row):
@ -193,7 +193,7 @@ class IntegerMatrix(Matrix):
def __init__( def __init__(
self, self,
matrix: npt.ArrayLike, matrix: npt.ArrayLike,
element_alignment_corner: np_vector = UP, element_alignment_corner: Vect3 = UP,
**kwargs **kwargs
): ):
super().__init__(matrix, element_alignment_corner=element_alignment_corner, **kwargs) super().__init__(matrix, element_alignment_corner=element_alignment_corner, **kwargs)

View file

@ -48,7 +48,7 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Callable, Iterable, Sequence, Union, Tuple from typing import Callable, Iterable, Sequence, Union, Tuple
import numpy.typing as npt import numpy.typing as npt
from manimlib.typing import ManimColor, np_vector from manimlib.typing import ManimColor, Vect3, Vect4
TimeBasedUpdater = Callable[["Mobject", float], None] TimeBasedUpdater = Callable[["Mobject", float], None]
NonTimeUpdater = Callable[["Mobject"], None] NonTimeUpdater = Callable[["Mobject"], None]
@ -200,8 +200,8 @@ class Mobject(object):
def apply_points_function( def apply_points_function(
self, self,
func: Callable[[np.ndarray], np.ndarray], func: Callable[[np.ndarray], np.ndarray],
about_point: np_vector = None, about_point: Vect3 = None,
about_edge: np_vector = ORIGIN, about_edge: Vect3 = ORIGIN,
works_on_bounding_box: bool = False works_on_bounding_box: bool = False
): ):
if about_point is None and about_edge is not None: if about_point is None and about_edge is not None:
@ -233,7 +233,7 @@ class Mobject(object):
self.set_points(mobject.get_points()) self.set_points(mobject.get_points())
return self return self
def get_points(self) -> np_vector: def get_points(self) -> Vect3:
return self.data["points"] return self.data["points"]
def clear_points(self) -> None: def clear_points(self) -> None:
@ -242,7 +242,7 @@ class Mobject(object):
def get_num_points(self) -> int: def get_num_points(self) -> int:
return len(self.data["points"]) return len(self.data["points"])
def get_all_points(self) -> np_vector: def get_all_points(self) -> Vect3:
if self.submobjects: if self.submobjects:
return np.vstack([sm.get_points() for sm in self.get_family()]) return np.vstack([sm.get_points() for sm in self.get_family()])
else: else:
@ -251,13 +251,13 @@ class Mobject(object):
def has_points(self) -> bool: def has_points(self) -> bool:
return self.get_num_points() > 0 return self.get_num_points() > 0
def get_bounding_box(self) -> np_vector: def get_bounding_box(self) -> Vect3:
if self.needs_new_bounding_box: if self.needs_new_bounding_box:
self.data["bounding_box"] = self.compute_bounding_box() self.data["bounding_box"] = self.compute_bounding_box()
self.needs_new_bounding_box = False self.needs_new_bounding_box = False
return self.data["bounding_box"] return self.data["bounding_box"]
def compute_bounding_box(self) -> np_vector: def compute_bounding_box(self) -> Vect3:
all_points = np.vstack([ all_points = np.vstack([
self.get_points(), self.get_points(),
*( *(
@ -289,7 +289,7 @@ class Mobject(object):
def are_points_touching( def are_points_touching(
self, self,
points: np_vector, points: Vect3,
buff: float = 0 buff: float = 0
) -> bool: ) -> bool:
bb = self.get_bounding_box() bb = self.get_bounding_box()
@ -299,7 +299,7 @@ class Mobject(object):
def is_point_touching( def is_point_touching(
self, self,
point: np_vector, point: Vect3,
buff: float = 0 buff: float = 0
) -> bool: ) -> bool:
return self.are_points_touching(np.array(point, ndmin=2), buff)[0] return self.are_points_touching(np.array(point, ndmin=2), buff)[0]
@ -424,7 +424,7 @@ class Mobject(object):
def arrange( def arrange(
self, self,
direction: np_vector = RIGHT, direction: Vect3 = RIGHT,
center: bool = True, center: bool = True,
**kwargs **kwargs
): ):
@ -444,7 +444,7 @@ class Mobject(object):
buff_ratio: float | None = None, buff_ratio: float | None = None,
h_buff_ratio: float = 0.5, h_buff_ratio: float = 0.5,
v_buff_ratio: float = 0.5, v_buff_ratio: float = 0.5,
aligned_edge: np_vector = ORIGIN, aligned_edge: Vect3 = ORIGIN,
fill_rows_first: bool = True fill_rows_first: bool = True
): ):
submobs = self.submobjects submobs = self.submobjects
@ -827,7 +827,7 @@ class Mobject(object):
# Transforming operations # Transforming operations
def shift(self, vector: np_vector): def shift(self, vector: Vect3):
self.apply_points_function( self.apply_points_function(
lambda points: points + vector, lambda points: points + vector,
about_edge=None, about_edge=None,
@ -839,8 +839,8 @@ class Mobject(object):
self, self,
scale_factor: float | npt.ArrayLike, scale_factor: float | npt.ArrayLike,
min_scale_factor: float = 1e-8, min_scale_factor: float = 1e-8,
about_point: np_vector | None = None, about_point: Vect3 | None = None,
about_edge: np_vector = ORIGIN about_edge: Vect3 = ORIGIN
): ):
""" """
Default behavior is to scale about the center of the mobject. Default behavior is to scale about the center of the mobject.
@ -877,14 +877,14 @@ class Mobject(object):
self.apply_points_function(func, works_on_bounding_box=True, **kwargs) self.apply_points_function(func, works_on_bounding_box=True, **kwargs)
return self return self
def rotate_about_origin(self, angle: float, axis: np_vector = OUT): def rotate_about_origin(self, angle: float, axis: Vect3 = OUT):
return self.rotate(angle, axis, about_point=ORIGIN) return self.rotate(angle, axis, about_point=ORIGIN)
def rotate( def rotate(
self, self,
angle: float, angle: float,
axis: np_vector = OUT, axis: Vect3 = OUT,
about_point: np_vector | None = None, about_point: Vect3 | None = None,
**kwargs **kwargs
): ):
rot_matrix_T = rotation_matrix_transpose(angle, axis) rot_matrix_T = rotation_matrix_transpose(angle, axis)
@ -895,7 +895,7 @@ class Mobject(object):
) )
return self return self
def flip(self, axis: np_vector = UP, **kwargs): def flip(self, axis: Vect3 = UP, **kwargs):
return self.rotate(TAU / 2, axis, **kwargs) return self.rotate(TAU / 2, axis, **kwargs)
def apply_function(self, function: Callable[[np.ndarray], np.ndarray], **kwargs): def apply_function(self, function: Callable[[np.ndarray], np.ndarray], **kwargs):
@ -946,8 +946,8 @@ class Mobject(object):
def wag( def wag(
self, self,
direction: np_vector = RIGHT, direction: Vect3 = RIGHT,
axis: np_vector = DOWN, axis: Vect3 = DOWN,
wag_factor: float = 1.0 wag_factor: float = 1.0
): ):
for mob in self.family_members_with_points(): for mob in self.family_members_with_points():
@ -969,7 +969,7 @@ class Mobject(object):
def align_on_border( def align_on_border(
self, self,
direction: np_vector, direction: Vect3,
buff: float = DEFAULT_MOBJECT_TO_EDGE_BUFFER buff: float = DEFAULT_MOBJECT_TO_EDGE_BUFFER
): ):
""" """
@ -985,27 +985,27 @@ class Mobject(object):
def to_corner( def to_corner(
self, self,
corner: np_vector = LEFT + DOWN, corner: Vect3 = LEFT + DOWN,
buff: float = DEFAULT_MOBJECT_TO_EDGE_BUFFER buff: float = DEFAULT_MOBJECT_TO_EDGE_BUFFER
): ):
return self.align_on_border(corner, buff) return self.align_on_border(corner, buff)
def to_edge( def to_edge(
self, self,
edge: np_vector = LEFT, edge: Vect3 = LEFT,
buff: float = DEFAULT_MOBJECT_TO_EDGE_BUFFER buff: float = DEFAULT_MOBJECT_TO_EDGE_BUFFER
): ):
return self.align_on_border(edge, buff) return self.align_on_border(edge, buff)
def next_to( def next_to(
self, self,
mobject_or_point: Mobject | np_vector, mobject_or_point: Mobject | Vect3,
direction: np_vector = RIGHT, direction: Vect3 = RIGHT,
buff: float = DEFAULT_MOBJECT_TO_MOBJECT_BUFFER, buff: float = DEFAULT_MOBJECT_TO_MOBJECT_BUFFER,
aligned_edge: np_vector = ORIGIN, aligned_edge: Vect3 = ORIGIN,
submobject_to_align: Mobject | None = None, submobject_to_align: Mobject | None = None,
index_of_submobject_to_align: int | slice | None = None, index_of_submobject_to_align: int | slice | None = None,
coor_mask: np_vector = np.array([1, 1, 1]), coor_mask: Vect3 = np.array([1, 1, 1]),
): ):
if isinstance(mobject_or_point, Mobject): if isinstance(mobject_or_point, Mobject):
mob = mobject_or_point mob = mobject_or_point
@ -1050,7 +1050,7 @@ class Mobject(object):
return True return True
return False return False
def stretch_about_point(self, factor: float, dim: int, point: np_vector): def stretch_about_point(self, factor: float, dim: int, point: Vect3):
return self.stretch(factor, dim, about_point=point) return self.stretch(factor, dim, about_point=point)
def stretch_in_place(self, factor: float, dim: int): def stretch_in_place(self, factor: float, dim: int):
@ -1115,20 +1115,20 @@ class Mobject(object):
self.set_depth(min_depth, **kwargs) self.set_depth(min_depth, **kwargs)
return self return self
def set_coord(self, value: float, dim: int, direction: np_vector = ORIGIN): def set_coord(self, value: float, dim: int, direction: Vect3 = ORIGIN):
curr = self.get_coord(dim, direction) curr = self.get_coord(dim, direction)
shift_vect = np.zeros(self.dim) shift_vect = np.zeros(self.dim)
shift_vect[dim] = value - curr shift_vect[dim] = value - curr
self.shift(shift_vect) self.shift(shift_vect)
return self return self
def set_x(self, x: float, direction: np_vector = ORIGIN): def set_x(self, x: float, direction: Vect3 = ORIGIN):
return self.set_coord(x, 0, direction) return self.set_coord(x, 0, direction)
def set_y(self, y: float, direction: np_vector = ORIGIN): def set_y(self, y: float, direction: Vect3 = ORIGIN):
return self.set_coord(y, 1, direction) return self.set_coord(y, 1, direction)
def set_z(self, z: float, direction: np_vector = ORIGIN): def set_z(self, z: float, direction: Vect3 = ORIGIN):
return self.set_coord(z, 2, direction) return self.set_coord(z, 2, direction)
def space_out_submobjects(self, factor: float = 1.5, **kwargs): def space_out_submobjects(self, factor: float = 1.5, **kwargs):
@ -1139,9 +1139,9 @@ class Mobject(object):
def move_to( def move_to(
self, self,
point_or_mobject: Mobject | np_vector, point_or_mobject: Mobject | Vect3,
aligned_edge: np_vector = ORIGIN, aligned_edge: Vect3 = ORIGIN,
coor_mask: np_vector = np.array([1, 1, 1]) coor_mask: Vect3 = np.array([1, 1, 1])
): ):
if isinstance(point_or_mobject, Mobject): if isinstance(point_or_mobject, Mobject):
target = point_or_mobject.get_bounding_box_point(aligned_edge) target = point_or_mobject.get_bounding_box_point(aligned_edge)
@ -1179,7 +1179,7 @@ class Mobject(object):
self.scale((length + buff) / length) self.scale((length + buff) / length)
return self return self
def put_start_and_end_on(self, start: np_vector, end: np_vector): def put_start_and_end_on(self, start: Vect3, end: Vect3):
curr_start, curr_end = self.get_start_and_end() curr_start, curr_end = self.get_start_and_end()
curr_vect = curr_end - curr_start curr_vect = curr_end - curr_start
if np.all(curr_vect == 0): if np.all(curr_vect == 0):
@ -1213,7 +1213,7 @@ class Mobject(object):
def set_color_by_rgba_func( def set_color_by_rgba_func(
self, self,
func: Callable[[np.ndarray], Sequence[float]], func: Callable[[Vect3], Vect4],
recurse: bool = True recurse: bool = True
): ):
""" """
@ -1226,7 +1226,7 @@ class Mobject(object):
def set_color_by_rgb_func( def set_color_by_rgb_func(
self, self,
func: Callable[[np.ndarray], Sequence[float]], func: Callable[[Vect3], Vect3],
opacity: float = 1, opacity: float = 1,
recurse: bool = True recurse: bool = True
): ):
@ -1373,7 +1373,7 @@ class Mobject(object):
# Getters # Getters
def get_bounding_box_point(self, direction: np_vector) -> np_vector: def get_bounding_box_point(self, direction: Vect3) -> Vect3:
bb = self.get_bounding_box() bb = self.get_bounding_box()
indices = (np.sign(direction) + 1).astype(int) indices = (np.sign(direction) + 1).astype(int)
return np.array([ return np.array([
@ -1381,10 +1381,10 @@ class Mobject(object):
for i in range(3) for i in range(3)
]) ])
def get_edge_center(self, direction: np_vector) -> np_vector: def get_edge_center(self, direction: Vect3) -> Vect3:
return self.get_bounding_box_point(direction) return self.get_bounding_box_point(direction)
def get_corner(self, direction: np_vector) -> np_vector: def get_corner(self, direction: Vect3) -> Vect3:
return self.get_bounding_box_point(direction) return self.get_bounding_box_point(direction)
def get_all_corners(self): def get_all_corners(self):
@ -1394,13 +1394,13 @@ class Mobject(object):
for indices in it.product([0, 2], repeat=3) for indices in it.product([0, 2], repeat=3)
]) ])
def get_center(self) -> np_vector: def get_center(self) -> Vect3:
return self.get_bounding_box()[1] return self.get_bounding_box()[1]
def get_center_of_mass(self) -> np_vector: def get_center_of_mass(self) -> Vect3:
return self.get_all_points().mean(0) return self.get_all_points().mean(0)
def get_boundary_point(self, direction: np_vector) -> np_vector: def get_boundary_point(self, direction: Vect3) -> Vect3:
all_points = self.get_all_points() all_points = self.get_all_points()
boundary_directions = all_points - self.get_center() boundary_directions = all_points - self.get_center()
norms = np.linalg.norm(boundary_directions, axis=1) norms = np.linalg.norm(boundary_directions, axis=1)
@ -1408,7 +1408,7 @@ class Mobject(object):
index = np.argmax(np.dot(boundary_directions, np.array(direction).T)) index = np.argmax(np.dot(boundary_directions, np.array(direction).T))
return all_points[index] return all_points[index]
def get_continuous_bounding_box_point(self, direction: np_vector) -> np_vector: def get_continuous_bounding_box_point(self, direction: Vect3) -> Vect3:
dl, center, ur = self.get_bounding_box() dl, center, ur = self.get_bounding_box()
corner_vect = (ur - center) corner_vect = (ur - center)
return center + direction / np.max(np.abs(np.true_divide( return center + direction / np.max(np.abs(np.true_divide(
@ -1417,22 +1417,22 @@ class Mobject(object):
where=((corner_vect) != 0) where=((corner_vect) != 0)
))) )))
def get_top(self) -> np_vector: def get_top(self) -> Vect3:
return self.get_edge_center(UP) return self.get_edge_center(UP)
def get_bottom(self) -> np_vector: def get_bottom(self) -> Vect3:
return self.get_edge_center(DOWN) return self.get_edge_center(DOWN)
def get_right(self) -> np_vector: def get_right(self) -> Vect3:
return self.get_edge_center(RIGHT) return self.get_edge_center(RIGHT)
def get_left(self) -> np_vector: def get_left(self) -> Vect3:
return self.get_edge_center(LEFT) return self.get_edge_center(LEFT)
def get_zenith(self) -> np_vector: def get_zenith(self) -> Vect3:
return self.get_edge_center(OUT) return self.get_edge_center(OUT)
def get_nadir(self) -> np_vector: def get_nadir(self) -> Vect3:
return self.get_edge_center(IN) return self.get_edge_center(IN)
def length_over_dim(self, dim: int) -> float: def length_over_dim(self, dim: int) -> float:
@ -1448,7 +1448,7 @@ class Mobject(object):
def get_depth(self) -> float: def get_depth(self) -> float:
return self.length_over_dim(2) return self.length_over_dim(2)
def get_coord(self, dim: int, direction: np_vector = ORIGIN) -> float: def get_coord(self, dim: int, direction: Vect3 = ORIGIN) -> float:
""" """
Meant to generalize get_x, get_y, get_z Meant to generalize get_x, get_y, get_z
""" """
@ -1463,20 +1463,20 @@ class Mobject(object):
def get_z(self, direction=ORIGIN) -> float: def get_z(self, direction=ORIGIN) -> float:
return self.get_coord(2, direction) return self.get_coord(2, direction)
def get_start(self) -> np_vector: def get_start(self) -> Vect3:
self.throw_error_if_no_points() self.throw_error_if_no_points()
return self.get_points()[0].copy() return self.get_points()[0].copy()
def get_end(self) -> np_vector: def get_end(self) -> Vect3:
self.throw_error_if_no_points() self.throw_error_if_no_points()
return self.get_points()[-1].copy() return self.get_points()[-1].copy()
def get_start_and_end(self) -> tuple[np_vector, np_vector]: def get_start_and_end(self) -> tuple[Vect3, Vect3]:
self.throw_error_if_no_points() self.throw_error_if_no_points()
points = self.get_points() points = self.get_points()
return (points[0].copy(), points[-1].copy()) return (points[0].copy(), points[-1].copy())
def point_from_proportion(self, alpha: float) -> np_vector: def point_from_proportion(self, alpha: float) -> Vect3:
points = self.get_points() points = self.get_points()
i, subalpha = integer_interpolate(0, len(points) - 1, alpha) i, subalpha = integer_interpolate(0, len(points) - 1, alpha)
return interpolate(points[i], points[i + 1], subalpha) return interpolate(points[i], points[i + 1], subalpha)
@ -1523,9 +1523,9 @@ class Mobject(object):
def match_coord( def match_coord(
self, self,
mobject_or_point: Mobject | np_vector, mobject_or_point: Mobject | Vect3,
dim: int, dim: int,
direction: np_vector = ORIGIN direction: Vect3 = ORIGIN
): ):
if isinstance(mobject_or_point, Mobject): if isinstance(mobject_or_point, Mobject):
coord = mobject_or_point.get_coord(dim, direction) coord = mobject_or_point.get_coord(dim, direction)
@ -1535,29 +1535,29 @@ class Mobject(object):
def match_x( def match_x(
self, self,
mobject_or_point: Mobject | np_vector, mobject_or_point: Mobject | Vect3,
direction: np_vector = ORIGIN direction: Vect3 = ORIGIN
): ):
return self.match_coord(mobject_or_point, 0, direction) return self.match_coord(mobject_or_point, 0, direction)
def match_y( def match_y(
self, self,
mobject_or_point: Mobject | np_vector, mobject_or_point: Mobject | Vect3,
direction: np_vector = ORIGIN direction: Vect3 = ORIGIN
): ):
return self.match_coord(mobject_or_point, 1, direction) return self.match_coord(mobject_or_point, 1, direction)
def match_z( def match_z(
self, self,
mobject_or_point: Mobject | np_vector, mobject_or_point: Mobject | Vect3,
direction: np_vector = ORIGIN direction: Vect3 = ORIGIN
): ):
return self.match_coord(mobject_or_point, 2, direction) return self.match_coord(mobject_or_point, 2, direction)
def align_to( def align_to(
self, self,
mobject_or_point: Mobject | np_vector, mobject_or_point: Mobject | Vect3,
direction: np_vector = ORIGIN direction: Vect3 = ORIGIN
): ):
""" """
Examples: Examples:
@ -1871,7 +1871,7 @@ class Mobject(object):
) )
return self return self
def get_resized_shader_data_array(self, length: int) -> np_vector: def get_resized_shader_data_array(self, length: int) -> Vect3:
# If possible, try to populate an existing array, rather # If possible, try to populate an existing array, rather
# than recreating it each frame # than recreating it each frame
if len(self.shader_data) != length: if len(self.shader_data) != length:
@ -1880,7 +1880,7 @@ class Mobject(object):
def read_data_to_shader( def read_data_to_shader(
self, self,
shader_data: np_vector, shader_data: Vect3,
shader_data_key: str, shader_data_key: str,
data_key: str data_key: str
): ):
@ -2024,7 +2024,7 @@ class Group(Mobject):
class Point(Mobject): class Point(Mobject):
def __init__( def __init__(
self, self,
location: np_vector = ORIGIN, location: Vect3 = ORIGIN,
artificial_width: float = 1e-6, artificial_width: float = 1e-6,
artificial_height: float = 1e-6, artificial_height: float = 1e-6,
**kwargs **kwargs
@ -2040,10 +2040,10 @@ class Point(Mobject):
def get_height(self) -> float: def get_height(self) -> float:
return self.artificial_height return self.artificial_height
def get_location(self) -> np_vector: def get_location(self) -> Vect3:
return self.get_points()[0].copy() return self.get_points()[0].copy()
def get_bounding_box_point(self, *args, **kwargs) -> np_vector: def get_bounding_box_point(self, *args, **kwargs) -> Vect3:
return self.get_location() return self.get_location()
def set_location(self, new_loc: npt.ArrayLike): def set_location(self, new_loc: npt.ArrayLike):

View file

@ -17,7 +17,7 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Iterable from typing import Iterable
from manimlib.typing import ManimColor, np_vector, RangeSpecifier from manimlib.typing import ManimColor, Vect3, RangeSpecifier
class NumberLine(Line): class NumberLine(Line):
@ -36,7 +36,7 @@ class NumberLine(Line):
# Change name # Change name
numbers_with_elongated_ticks: list[float] = [], numbers_with_elongated_ticks: list[float] = [],
include_numbers: bool = False, include_numbers: bool = False,
line_to_number_direction: np_vector = DOWN, line_to_number_direction: Vect3 = DOWN,
line_to_number_buff: float = MED_SMALL_BUFF, line_to_number_buff: float = MED_SMALL_BUFF,
include_tip: bool = False, include_tip: bool = False,
tip_config: dict = dict( tip_config: dict = dict(
@ -118,11 +118,11 @@ class NumberLine(Line):
def get_tick_marks(self) -> VGroup: def get_tick_marks(self) -> VGroup:
return self.ticks return self.ticks
def number_to_point(self, number: float | np.ndarray) -> np_vector: def number_to_point(self, number: float | np.ndarray) -> Vect3:
alpha = (number - self.x_min) / (self.x_max - self.x_min) alpha = (number - self.x_min) / (self.x_max - self.x_min)
return outer_interpolate(self.get_start(), self.get_end(), alpha) return outer_interpolate(self.get_start(), self.get_end(), alpha)
def point_to_number(self, point: np_vector) -> float: def point_to_number(self, point: Vect3) -> float:
points = self.get_points() points = self.get_points()
start = points[0] start = points[0]
end = points[-1] end = points[-1]
@ -133,11 +133,11 @@ class NumberLine(Line):
) )
return interpolate(self.x_min, self.x_max, proportion) return interpolate(self.x_min, self.x_max, proportion)
def n2p(self, number: float) -> np_vector: def n2p(self, number: float) -> Vect3:
"""Abbreviation for number_to_point""" """Abbreviation for number_to_point"""
return self.number_to_point(number) return self.number_to_point(number)
def p2n(self, point: np_vector) -> float: def p2n(self, point: Vect3) -> float:
"""Abbreviation for point_to_number""" """Abbreviation for point_to_number"""
return self.point_to_number(point) return self.point_to_number(point)
@ -147,7 +147,7 @@ class NumberLine(Line):
def get_number_mobject( def get_number_mobject(
self, self,
x: float, x: float,
direction: np_vector | None = None, direction: Vect3 | None = None,
buff: float | None = None, buff: float | None = None,
unit: float = 1.0, unit: float = 1.0,
unit_tex: str = "", unit_tex: str = "",

View file

@ -12,7 +12,7 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import TypeVar from typing import TypeVar
from manimlib.typing import ManimColor, np_vector from manimlib.typing import ManimColor, Vect3
T = TypeVar("T", bound=VMobject) T = TypeVar("T", bound=VMobject)
@ -31,7 +31,7 @@ class DecimalNumber(VMobject):
show_ellipsis: bool = False, show_ellipsis: bool = False,
unit: str | None = None, # Aligned to bottom unless it starts with "^" unit: str | None = None, # Aligned to bottom unless it starts with "^"
include_background_rectangle: bool = False, include_background_rectangle: bool = False,
edge_to_fix: np_vector = LEFT, edge_to_fix: Vect3 = LEFT,
font_size: int = 48, font_size: int = 48,
text_config: dict = dict(), # Do not pass in font_size here text_config: dict = dict(), # Do not pass in font_size here
**kwargs **kwargs

View file

@ -27,14 +27,14 @@ if TYPE_CHECKING:
from manimlib.animation.animation import Animation from manimlib.animation.animation import Animation
from manimlib.mobject.mobject import Mobject from manimlib.mobject.mobject import Mobject
from manimlib.typing import np_vector from manimlib.typing import Vect3
class Brace(SingleStringTex): class Brace(SingleStringTex):
def __init__( def __init__(
self, self,
mobject: Mobject, mobject: Mobject,
direction: np_vector = DOWN, direction: Vect3 = DOWN,
buff: float = 0.2, buff: float = 0.2,
tex_string: str = R"\underbrace{\qquad}", tex_string: str = R"\underbrace{\qquad}",
**kwargs **kwargs

View file

@ -60,7 +60,7 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Tuple, Sequence, Callable from typing import Tuple, Sequence, Callable
from manimlib.typing import ManimColor, np_vector from manimlib.typing import ManimColor, Vect3
class Checkmark(TexTextFromPresetString): class Checkmark(TexTextFromPresetString):
@ -342,8 +342,8 @@ class Bubble(SVGMobject):
def __init__( def __init__(
self, self,
direction: np_vector = LEFT, direction: Vect3 = LEFT,
center_point: np_vector = ORIGIN, center_point: Vect3 = ORIGIN,
content_scale_factor: float = 0.7, content_scale_factor: float = 0.7,
height: float = 4.0, height: float = 4.0,
width: float = 8.0, width: float = 8.0,

View file

@ -23,7 +23,7 @@ from manimlib.utils.space_ops import z_to_vector
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Tuple, TypeVar from typing import Tuple, TypeVar
from manimlib.typing import ManimColor, np_vector from manimlib.typing import ManimColor, Vect3
T = TypeVar("T", bound=Mobject) T = TypeVar("T", bound=Mobject)
@ -145,7 +145,7 @@ class Cylinder(Surface):
resolution: Tuple[int, int] = (101, 11), resolution: Tuple[int, int] = (101, 11),
height: float = 2, height: float = 2,
radius: float = 1, radius: float = 1,
axis: np_vector = OUT, axis: Vect3 = OUT,
**kwargs, **kwargs,
): ):
self.height = height self.height = height
@ -173,8 +173,8 @@ class Cylinder(Surface):
class Line3D(Cylinder): class Line3D(Cylinder):
def __init__( def __init__(
self, self,
start: np_vector, start: Vect3,
end: np_vector, end: Vect3,
width: float = 0.05, width: float = 0.05,
resolution: Tuple[int, int] = (21, 25), resolution: Tuple[int, int] = (21, 25),
**kwargs **kwargs

View file

@ -13,7 +13,7 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
import numpy.typing as npt import numpy.typing as npt
from typing import Sequence, Tuple from typing import Sequence, Tuple
from manimlib.typing import ManimColor, np_vector from manimlib.typing import ManimColor, Vect3
DEFAULT_DOT_RADIUS = 0.05 DEFAULT_DOT_RADIUS = 0.05
@ -32,7 +32,7 @@ class DotCloud(PMobject):
def __init__( def __init__(
self, self,
points: Sequence[np_vector] | None = None, points: Sequence[Vect3] | None = None,
color: ManimColor = GREY_C, color: ManimColor = GREY_C,
opacity: float = 1.0, opacity: float = 1.0,
radius: float = DEFAULT_DOT_RADIUS, radius: float = DEFAULT_DOT_RADIUS,
@ -160,7 +160,7 @@ class TrueDot(DotCloud):
class GlowDots(DotCloud): class GlowDots(DotCloud):
def __init__( def __init__(
self, self,
points: Sequence[np_vector] | None = None, points: Sequence[Vect3] | None = None,
color: ManimColor = YELLOW, color: ManimColor = YELLOW,
radius: float = DEFAULT_GLOW_DOT_RADIUS, radius: float = DEFAULT_GLOW_DOT_RADIUS,
glow_factor: float = 2.0, glow_factor: float = 2.0,

View file

@ -13,7 +13,7 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Sequence, Tuple from typing import Sequence, Tuple
from manimlib.typing import np_vector from manimlib.typing import Vect3
class ImageMobject(Mobject): class ImageMobject(Mobject):
@ -55,7 +55,7 @@ class ImageMobject(Mobject):
def set_color(self, color, opacity=None, recurse=None): def set_color(self, color, opacity=None, recurse=None):
return self return self
def point_to_rgb(self, point: np_vector) -> np_vector: def point_to_rgb(self, point: Vect3) -> Vect3:
x0, y0 = self.get_corner(UL)[:2] x0, y0 = self.get_corner(UL)[:2]
x1, y1 = self.get_corner(DR)[:2] x1, y1 = self.get_corner(DR)[:2]
x_alpha = inverse_interpolate(x0, x1, point[0]) x_alpha = inverse_interpolate(x0, x1, point[0])

View file

@ -15,7 +15,7 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Callable, Sequence from typing import Callable, Sequence
import numpy.typing as npt import numpy.typing as npt
from manimlib.typing import ManimColor, np_vector from manimlib.typing import ManimColor, Vect3
class PMobject(Mobject): class PMobject(Mobject):
@ -32,7 +32,7 @@ class PMobject(Mobject):
self.data[key] = resize_func(self.data[key], size) self.data[key] = resize_func(self.data[key], size)
return self return self
def set_points(self, points: np_vector): def set_points(self, points: Vect3):
if len(points) == 0: if len(points) == 0:
points = np.zeros((0, 3)) points = np.zeros((0, 3))
super().set_points(points) super().set_points(points)
@ -41,8 +41,8 @@ class PMobject(Mobject):
def add_points( def add_points(
self, self,
points: Sequence[np_vector], points: Sequence[Vect3],
rgbas: np_vector | None = None, rgbas: Vect3 | None = None,
color: ManimColor | None = None, color: ManimColor | None = None,
opacity: float | None = None opacity: float | None = None
): ):
@ -63,7 +63,7 @@ class PMobject(Mobject):
self.data["rgbas"][-len(rgbas):] = rgbas self.data["rgbas"][-len(rgbas):] = rgbas
return self return self
def add_point(self, point: np_vector, rgba=None, color=None, opacity=None): def add_point(self, point: Vect3, rgba=None, color=None, opacity=None):
rgbas = None if rgba is None else [rgba] rgbas = None if rgba is None else [rgba]
self.add_points([point], rgbas, color, opacity) self.add_points([point], rgbas, color, opacity)
return self return self
@ -90,7 +90,7 @@ class PMobject(Mobject):
mob.data[key] = mob.data[key][to_keep] mob.data[key] = mob.data[key][to_keep]
return self return self
def sort_points(self, function: Callable[[np_vector], None] = lambda p: p[0]): def sort_points(self, function: Callable[[Vect3], None] = lambda p: p[0]):
""" """
function is any map from R^3 to R function is any map from R^3 to R
""" """

View file

@ -18,7 +18,7 @@ if TYPE_CHECKING:
from typing import Callable, Iterable, Sequence, Tuple from typing import Callable, Iterable, Sequence, Tuple
from manimlib.camera.camera import Camera from manimlib.camera.camera import Camera
from manimlib.typing import ManimColor, np_vector from manimlib.typing import ManimColor, Vect3
class Surface(Mobject): class Surface(Mobject):
@ -114,12 +114,12 @@ class Surface(Mobject):
def get_surface_points_and_nudged_points( def get_surface_points_and_nudged_points(
self self
) -> tuple[np_vector, np_vector, np_vector]: ) -> tuple[Vect3, Vect3, Vect3]:
points = self.get_points() points = self.get_points()
k = len(points) // 3 k = len(points) // 3
return points[:k], points[k:2 * k], points[2 * k:] return points[:k], points[k:2 * k], points[2 * k:]
def get_unit_normals(self) -> np_vector: def get_unit_normals(self) -> Vect3:
s_points, du_points, dv_points = self.get_surface_points_and_nudged_points() s_points, du_points, dv_points = self.get_surface_points_and_nudged_points()
normals = np.cross( normals = np.cross(
(du_points - s_points) / self.epsilon, (du_points - s_points) / self.epsilon,
@ -150,12 +150,12 @@ class Surface(Mobject):
def get_partial_points_array( def get_partial_points_array(
self, self,
points: np_vector, points: Vect3,
a: float, a: float,
b: float, b: float,
resolution: Sequence[int], resolution: Sequence[int],
axis: int axis: int
) -> np_vector: ) -> Vect3:
if len(points) == 0: if len(points) == 0:
return points return points
nu, nv = resolution[:2] nu, nv = resolution[:2]
@ -188,7 +188,7 @@ class Surface(Mobject):
).reshape(shape) ).reshape(shape)
return points.reshape((nu * nv, *resolution[2:])) return points.reshape((nu * nv, *resolution[2:]))
def sort_faces_back_to_front(self, vect: np_vector = OUT): def sort_faces_back_to_front(self, vect: Vect3 = OUT):
tri_is = self.triangle_indices tri_is = self.triangle_indices
indices = list(range(len(tri_is) // 3)) indices = list(range(len(tri_is) // 3))
points = self.get_points() points = self.get_points()

View file

@ -42,7 +42,7 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Callable, Iterable, Sequence, Tuple from typing import Callable, Iterable, Sequence, Tuple
from manimlib.typing import ManimColor, np_vector from manimlib.typing import ManimColor, Vect3, Vect4
DEFAULT_STROKE_COLOR = GREY_A DEFAULT_STROKE_COLOR = GREY_A
DEFAULT_FILL_COLOR = GREY_C DEFAULT_FILL_COLOR = GREY_C
@ -149,7 +149,7 @@ class VMobject(Mobject):
def set_rgba_array( def set_rgba_array(
self, self,
rgba_array: np_vector, rgba_array: Vect3,
name: str | None = None, name: str | None = None,
recurse: bool = False recurse: bool = False
): ):
@ -213,10 +213,10 @@ class VMobject(Mobject):
self, self,
fill_color: ManimColor | Iterable[ManimColor] | None = None, fill_color: ManimColor | Iterable[ManimColor] | None = None,
fill_opacity: float | Iterable[float] | None = None, fill_opacity: float | Iterable[float] | None = None,
fill_rgba: np_vector | None = None, fill_rgba: Vect4 | None = None,
stroke_color: ManimColor | Iterable[ManimColor] | None = None, stroke_color: ManimColor | Iterable[ManimColor] | None = None,
stroke_opacity: float | Iterable[float] | None = None, stroke_opacity: float | Iterable[float] | None = None,
stroke_rgba: np_vector | None = None, stroke_rgba: Vect4 | None = None,
stroke_width: float | Iterable[float] | None = None, stroke_width: float | Iterable[float] | None = None,
stroke_background: bool = True, stroke_background: bool = True,
reflectiveness: float | None = None, reflectiveness: float | None = None,
@ -322,7 +322,7 @@ class VMobject(Mobject):
for rgba in self.data['fill_rgba'] for rgba in self.data['fill_rgba']
] ]
def get_fill_opacities(self) -> np_vector: def get_fill_opacities(self) -> np.ndarray:
return self.data['fill_rgba'][:, 3] return self.data['fill_rgba'][:, 3]
def get_stroke_colors(self) -> list[str]: def get_stroke_colors(self) -> list[str]:
@ -331,10 +331,10 @@ class VMobject(Mobject):
for rgba in self.data['stroke_rgba'] for rgba in self.data['stroke_rgba']
] ]
def get_stroke_opacities(self) -> np_vector: def get_stroke_opacities(self) -> np.ndarray:
return self.data['stroke_rgba'][:, 3] return self.data['stroke_rgba'][:, 3]
def get_stroke_widths(self) -> np_vector: def get_stroke_widths(self) -> np.ndarray:
return self.data['stroke_width'][:, 0] return self.data['stroke_width'][:, 0]
# TODO, it's weird for these to return the first of various lists # TODO, it's weird for these to return the first of various lists
@ -356,7 +356,7 @@ class VMobject(Mobject):
def get_stroke_color(self) -> str: def get_stroke_color(self) -> str:
return self.get_stroke_colors()[0] return self.get_stroke_colors()[0]
def get_stroke_width(self) -> float | np_vector: def get_stroke_width(self) -> float | np.ndarray:
return self.get_stroke_widths()[0] return self.get_stroke_widths()[0]
def get_stroke_opacity(self) -> float: def get_stroke_opacity(self) -> float:
@ -397,9 +397,9 @@ class VMobject(Mobject):
# Points # Points
def set_anchors_and_handles( def set_anchors_and_handles(
self, self,
anchors1: np_vector, anchors1: Vect3,
handles: np_vector, handles: Vect3,
anchors2: np_vector anchors2: Vect3
): ):
assert(len(anchors1) == len(handles) == len(anchors2)) assert(len(anchors1) == len(handles) == len(anchors2))
nppc = self.n_points_per_curve nppc = self.n_points_per_curve
@ -410,26 +410,26 @@ class VMobject(Mobject):
self.set_points(new_points) self.set_points(new_points)
return self return self
def start_new_path(self, point: np_vector): def start_new_path(self, point: Vect3):
assert(self.get_num_points() % self.n_points_per_curve == 0) assert(self.get_num_points() % self.n_points_per_curve == 0)
self.append_points([point]) self.append_points([point])
return self return self
def add_cubic_bezier_curve( def add_cubic_bezier_curve(
self, self,
anchor1: np_vector, anchor1: Vect3,
handle1: np_vector, handle1: Vect3,
handle2: np_vector, handle2: Vect3,
anchor2: np_vector anchor2: Vect3
): ):
new_points = get_quadratic_approximation_of_cubic(anchor1, handle1, handle2, anchor2) new_points = get_quadratic_approximation_of_cubic(anchor1, handle1, handle2, anchor2)
self.append_points(new_points) self.append_points(new_points)
def add_cubic_bezier_curve_to( def add_cubic_bezier_curve_to(
self, self,
handle1: np_vector, handle1: Vect3,
handle2: np_vector, handle2: Vect3,
anchor: np_vector anchor: Vect3
): ):
""" """
Add cubic bezier curve to the path. Add cubic bezier curve to the path.
@ -443,14 +443,14 @@ class VMobject(Mobject):
else: else:
self.append_points(quadratic_approx) self.append_points(quadratic_approx)
def add_quadratic_bezier_curve_to(self, handle: np_vector, anchor: np_vector): def add_quadratic_bezier_curve_to(self, handle: Vect3, anchor: Vect3):
self.throw_error_if_no_points() self.throw_error_if_no_points()
if self.has_new_path_started(): if self.has_new_path_started():
self.append_points([handle, anchor]) self.append_points([handle, anchor])
else: else:
self.append_points([self.get_last_point(), handle, anchor]) self.append_points([self.get_last_point(), handle, anchor])
def add_line_to(self, point: np_vector): def add_line_to(self, point: Vect3):
end = self.get_points()[-1] end = self.get_points()[-1]
alphas = np.linspace(0, 1, self.n_points_per_curve) alphas = np.linspace(0, 1, self.n_points_per_curve)
if self.long_lines: if self.long_lines:
@ -472,7 +472,7 @@ class VMobject(Mobject):
self.append_points(points) self.append_points(points)
return self return self
def add_smooth_curve_to(self, point: np_vector): def add_smooth_curve_to(self, point: Vect3):
if self.has_new_path_started(): if self.has_new_path_started():
self.add_line_to(point) self.add_line_to(point)
else: else:
@ -481,7 +481,7 @@ class VMobject(Mobject):
self.add_quadratic_bezier_curve_to(new_handle, point) self.add_quadratic_bezier_curve_to(new_handle, point)
return self return self
def add_smooth_cubic_curve_to(self, handle: np_vector, point: np_vector): def add_smooth_cubic_curve_to(self, handle: Vect3, point: Vect3):
self.throw_error_if_no_points() self.throw_error_if_no_points()
if self.get_num_points() == 1: if self.get_num_points() == 1:
new_handle = self.get_points()[-1] new_handle = self.get_points()[-1]
@ -492,10 +492,10 @@ class VMobject(Mobject):
def has_new_path_started(self) -> bool: def has_new_path_started(self) -> bool:
return self.get_num_points() % self.n_points_per_curve == 1 return self.get_num_points() % self.n_points_per_curve == 1
def get_last_point(self) -> np_vector: def get_last_point(self) -> Vect3:
return self.get_points()[-1] return self.get_points()[-1]
def get_reflection_of_last_handle(self) -> np_vector: def get_reflection_of_last_handle(self) -> Vect3:
points = self.get_points() points = self.get_points()
return 2 * points[-1] - points[-2] return 2 * points[-1] - points[-2]
@ -530,12 +530,12 @@ class VMobject(Mobject):
vmob.set_points(np.vstack(new_points)) vmob.set_points(np.vstack(new_points))
return self return self
def add_points_as_corners(self, points: Iterable[np_vector]): def add_points_as_corners(self, points: Iterable[Vect3]):
for point in points: for point in points:
self.add_line_to(point) self.add_line_to(point)
return points return points
def set_points_as_corners(self, points: Iterable[np_vector]): def set_points_as_corners(self, points: Iterable[Vect3]):
nppc = self.n_points_per_curve nppc = self.n_points_per_curve
points = np.array(points) points = np.array(points)
self.set_anchors_and_handles(*[ self.set_anchors_and_handles(*[
@ -546,7 +546,7 @@ class VMobject(Mobject):
def set_points_smoothly( def set_points_smoothly(
self, self,
points: Iterable[np_vector], points: Iterable[Vect3],
true_smooth: bool = False true_smooth: bool = False
): ):
self.set_points_as_corners(points) self.set_points_as_corners(points)
@ -601,7 +601,7 @@ class VMobject(Mobject):
self.change_anchor_mode("jagged") self.change_anchor_mode("jagged")
return self return self
def add_subpath(self, points: Sequence[np_vector]): def add_subpath(self, points: Sequence[Vect3]):
assert(len(points) % self.n_points_per_curve == 0) assert(len(points) % self.n_points_per_curve == 0)
self.append_points(points) self.append_points(points)
return self return self
@ -617,11 +617,11 @@ class VMobject(Mobject):
return self return self
# #
def consider_points_equals(self, p0: np_vector, p1: np_vector) -> bool: def consider_points_equals(self, p0: Vect3, p1: Vect3) -> bool:
return get_norm(p1 - p0) < self.tolerance_for_point_equality return get_norm(p1 - p0) < self.tolerance_for_point_equality
# Information about the curve # Information about the curve
def get_bezier_tuples_from_points(self, points: Sequence[np_vector]): def get_bezier_tuples_from_points(self, points: Sequence[Vect3]):
nppc = self.n_points_per_curve nppc = self.n_points_per_curve
remainder = len(points) % nppc remainder = len(points) % nppc
points = points[:len(points) - remainder] points = points[:len(points) - remainder]
@ -635,8 +635,8 @@ class VMobject(Mobject):
def get_subpaths_from_points( def get_subpaths_from_points(
self, self,
points: Sequence[np_vector] points: Sequence[Vect3]
) -> list[Sequence[np_vector]]: ) -> list[Sequence[Vect3]]:
nppc = self.n_points_per_curve nppc = self.n_points_per_curve
diffs = points[nppc - 1:-1:nppc] - points[nppc::nppc] diffs = points[nppc - 1:-1:nppc] - points[nppc::nppc]
splits = (diffs * diffs).sum(1) > self.tolerance_for_point_equality splits = (diffs * diffs).sum(1) > self.tolerance_for_point_equality
@ -653,28 +653,28 @@ class VMobject(Mobject):
if (i2 - i1) >= nppc if (i2 - i1) >= nppc
] ]
def get_subpaths(self) -> list[Sequence[np_vector]]: def get_subpaths(self) -> list[Sequence[Vect3]]:
return self.get_subpaths_from_points(self.get_points()) return self.get_subpaths_from_points(self.get_points())
def get_nth_curve_points(self, n: int) -> np_vector: def get_nth_curve_points(self, n: int) -> Vect3:
assert(n < self.get_num_curves()) assert(n < self.get_num_curves())
nppc = self.n_points_per_curve nppc = self.n_points_per_curve
return self.get_points()[nppc * n:nppc * (n + 1)] return self.get_points()[nppc * n:nppc * (n + 1)]
def get_nth_curve_function(self, n: int) -> Callable[[float], np_vector]: def get_nth_curve_function(self, n: int) -> Callable[[float], Vect3]:
return bezier(self.get_nth_curve_points(n)) return bezier(self.get_nth_curve_points(n))
def get_num_curves(self) -> int: def get_num_curves(self) -> int:
return self.get_num_points() // self.n_points_per_curve return self.get_num_points() // self.n_points_per_curve
def quick_point_from_proportion(self, alpha: float) -> np_vector: def quick_point_from_proportion(self, alpha: float) -> Vect3:
# Assumes all curves have the same length, so is inaccurate # Assumes all curves have the same length, so is inaccurate
num_curves = self.get_num_curves() num_curves = self.get_num_curves()
n, residue = integer_interpolate(0, num_curves, alpha) n, residue = integer_interpolate(0, num_curves, alpha)
curve_func = self.get_nth_curve_function(n) curve_func = self.get_nth_curve_function(n)
return curve_func(residue) return curve_func(residue)
def point_from_proportion(self, alpha: float) -> np_vector: def point_from_proportion(self, alpha: float) -> Vect3:
if alpha <= 0: if alpha <= 0:
return self.get_start() return self.get_start()
elif alpha >= 1: elif alpha >= 1:
@ -696,7 +696,7 @@ class VMobject(Mobject):
residue = inverse_interpolate(partials[i - 1] / full, partials[i] / full, alpha) residue = inverse_interpolate(partials[i - 1] / full, partials[i] / full, alpha)
return self.get_nth_curve_function(i - 1)(residue) return self.get_nth_curve_function(i - 1)(residue)
def get_anchors_and_handles(self) -> list[np_vector]: def get_anchors_and_handles(self) -> list[Vect3]:
""" """
returns anchors1, handles, anchors2, returns anchors1, handles, anchors2,
where (anchors1[i], handles[i], anchors2[i]) where (anchors1[i], handles[i], anchors2[i])
@ -710,14 +710,14 @@ class VMobject(Mobject):
for i in range(nppc) for i in range(nppc)
] ]
def get_start_anchors(self) -> list[np_vector]: def get_start_anchors(self) -> list[Vect3]:
return self.get_points()[0::self.n_points_per_curve] return self.get_points()[0::self.n_points_per_curve]
def get_end_anchors(self) -> np_vector: def get_end_anchors(self) -> Vect3:
nppc = self.n_points_per_curve nppc = self.n_points_per_curve
return self.get_points()[nppc - 1::nppc] return self.get_points()[nppc - 1::nppc]
def get_anchors(self) -> np_vector: def get_anchors(self) -> Vect3:
points = self.get_points() points = self.get_points()
if len(points) == 1: if len(points) == 1:
return points return points
@ -726,7 +726,7 @@ class VMobject(Mobject):
self.get_end_anchors(), self.get_end_anchors(),
)))) ))))
def get_points_without_null_curves(self, atol: float = 1e-9) -> np_vector: def get_points_without_null_curves(self, atol: float = 1e-9) -> Vect3:
nppc = self.n_points_per_curve nppc = self.n_points_per_curve
points = self.get_points() points = self.get_points()
distinct_curves = reduce(op.or_, [ distinct_curves = reduce(op.or_, [
@ -746,7 +746,7 @@ class VMobject(Mobject):
norms = np.array([get_norm(d) for d in diffs]) norms = np.array([get_norm(d) for d in diffs])
return norms.sum() return norms.sum()
def get_area_vector(self) -> np_vector: def get_area_vector(self) -> Vect3:
# Returns a vector whose length is the area bound by # Returns a vector whose length is the area bound by
# the polygon formed by the anchor points, pointing # the polygon formed by the anchor points, pointing
# in a direction perpendicular to the polygon according # in a direction perpendicular to the polygon according
@ -766,7 +766,7 @@ class VMobject(Mobject):
sum((p0[:, 0] + p1[:, 0]) * (p1[:, 1] - p0[:, 1])), # Add up (x1 + x2)*(y2 - y1) sum((p0[:, 0] + p1[:, 0]) * (p1[:, 1] - p0[:, 1])), # Add up (x1 + x2)*(y2 - y1)
]) ])
def get_unit_normal(self, recompute: bool = False) -> np_vector: def get_unit_normal(self, recompute: bool = False) -> Vect3:
if not recompute: if not recompute:
return self.data["unit_normal"][0] return self.data["unit_normal"][0]
@ -851,7 +851,7 @@ class VMobject(Mobject):
mob.set_points(new_points) mob.set_points(new_points)
return self return self
def insert_n_curves_to_point_list(self, n: int, points: np_vector): def insert_n_curves_to_point_list(self, n: int, points: Vect3):
nppc = self.n_points_per_curve nppc = self.n_points_per_curve
if len(points) == 1: if len(points) == 1:
return np.repeat(points, nppc * n, 0) return np.repeat(points, nppc * n, 0)
@ -953,7 +953,7 @@ class VMobject(Mobject):
mob.needs_new_triangulation = True mob.needs_new_triangulation = True
return self return self
def get_triangulation(self, normal_vector: np_vector | None = None): def get_triangulation(self, normal_vector: Vect3 | None = None):
# Figure out how to triangulate the interior to know # Figure out how to triangulate the interior to know
# how to send the points as to the vertex shader. # how to send the points as to the vertex shader.
# First triangles come directly from the points # First triangles come directly from the points
@ -1022,7 +1022,7 @@ class VMobject(Mobject):
return wrapper return wrapper
@triggers_refreshed_triangulation @triggers_refreshed_triangulation
def set_points(self, points: np_vector): def set_points(self, points: Vect3):
super().set_points(points) super().set_points(points)
return self return self
@ -1035,7 +1035,7 @@ class VMobject(Mobject):
@triggers_refreshed_triangulation @triggers_refreshed_triangulation
def apply_function( def apply_function(
self, self,
function: Callable[[np_vector], np_vector], function: Callable[[Vect3], Vect3],
make_smooth: bool = False, make_smooth: bool = False,
**kwargs **kwargs
): ):
@ -1044,7 +1044,7 @@ class VMobject(Mobject):
self.make_approximately_smooth() self.make_approximately_smooth()
return self return self
def flip(self, axis: np_vector = UP, **kwargs): def flip(self, axis: Vect3 = UP, **kwargs):
super().flip(axis, **kwargs) super().flip(axis, **kwargs)
self.refresh_unit_normal() self.refresh_unit_normal()
self.refresh_triangulation() self.refresh_triangulation()

View file

@ -23,7 +23,7 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Callable, Iterable, Sequence, TypeVar, Tuple from typing import Callable, Iterable, Sequence, TypeVar, Tuple
import numpy.typing as npt import numpy.typing as npt
from manimlib.typing import ManimColor, np_vector from manimlib.typing import ManimColor, Vect3
from manimlib.mobject.coordinate_systems import CoordinateSystem from manimlib.mobject.coordinate_systems import CoordinateSystem
from manimlib.mobject.mobject import Mobject from manimlib.mobject.mobject import Mobject
@ -35,7 +35,7 @@ def get_vectorized_rgb_gradient_function(
min_value: T, min_value: T,
max_value: T, max_value: T,
color_map: str color_map: str
) -> Callable[[npt.ArrayLike], np_vector]: ) -> Callable[[npt.ArrayLike], Vect3]:
rgbs = np.array(get_colormap_list(color_map)) rgbs = np.array(get_colormap_list(color_map))
def func(values): def func(values):
@ -57,14 +57,14 @@ def get_rgb_gradient_function(
min_value: T, min_value: T,
max_value: T, max_value: T,
color_map: str color_map: str
) -> Callable[[T], np_vector]: ) -> Callable[[T], Vect3]:
vectorized_func = get_vectorized_rgb_gradient_function(min_value, max_value, color_map) vectorized_func = get_vectorized_rgb_gradient_function(min_value, max_value, color_map)
return lambda value: vectorized_func([value])[0] return lambda value: vectorized_func([value])[0]
def move_along_vector_field( def move_along_vector_field(
mobject: Mobject, mobject: Mobject,
func: Callable[[np_vector], np_vector] func: Callable[[Vect3], Vect3]
) -> Mobject: ) -> Mobject:
mobject.add_updater( mobject.add_updater(
lambda m, dt: m.shift( lambda m, dt: m.shift(
@ -76,7 +76,7 @@ def move_along_vector_field(
def move_submobjects_along_vector_field( def move_submobjects_along_vector_field(
mobject: Mobject, mobject: Mobject,
func: Callable[[np_vector], np_vector] func: Callable[[Vect3], Vect3]
) -> Mobject: ) -> Mobject:
def apply_nudge(mob, dt): def apply_nudge(mob, dt):
for submob in mob: for submob in mob:
@ -107,7 +107,7 @@ def move_points_along_vector_field(
def get_sample_points_from_coordinate_system( def get_sample_points_from_coordinate_system(
coordinate_system: CoordinateSystem, coordinate_system: CoordinateSystem,
step_multiple: float step_multiple: float
) -> it.product[tuple[np_vector, ...]]: ) -> it.product[tuple[Vect3, ...]]:
ranges = [] ranges = []
for range_args in coordinate_system.get_all_ranges(): for range_args in coordinate_system.get_all_ranges():
_min, _max, step = range_args _min, _max, step = range_args
@ -224,7 +224,7 @@ class StreamLines(VGroup):
self.draw_lines() self.draw_lines()
self.init_style() self.init_style()
def point_func(self, point: np_vector) -> np_vector: def point_func(self, point: Vect3) -> Vect3:
in_coords = self.coordinate_system.p2c(point) in_coords = self.coordinate_system.p2c(point)
out_coords = self.func(*in_coords) out_coords = self.func(*in_coords)
return self.coordinate_system.c2p(*out_coords) return self.coordinate_system.c2p(*out_coords)
@ -254,7 +254,7 @@ class StreamLines(VGroup):
lines.append(line) lines.append(line)
self.set_submobjects(lines) self.set_submobjects(lines)
def get_start_points(self) -> np_vector: def get_start_points(self) -> Vect3:
cs = self.coordinate_system cs = self.coordinate_system
sample_coords = get_sample_points_from_coordinate_system( sample_coords = get_sample_points_from_coordinate_system(
cs, self.step_multiple, cs, self.step_multiple,

View file

@ -11,7 +11,6 @@ if TYPE_CHECKING:
# TODO, Nothing about these actually specifies length, # TODO, Nothing about these actually specifies length,
# they are so far just about code readability # they are so far just about code readability
np_vector = np.ndarray[int, np.dtype[np.float64]]
Vect2 = np.ndarray[int, np.dtype[np.float64]] # TODO, specify length of 2 Vect2 = np.ndarray[int, np.dtype[np.float64]] # TODO, specify length of 2
Vect3 = np.ndarray[int, np.dtype[np.float64]] # TODO, specify length of 3 Vect3 = np.ndarray[int, np.dtype[np.float64]] # TODO, specify length of 3
Vect4 = np.ndarray[int, np.dtype[np.float64]] # TODO, specify length of 4 Vect4 = np.ndarray[int, np.dtype[np.float64]] # TODO, specify length of 4