29
29
from manim .utils .simple_functions import choose
30
30
31
31
if TYPE_CHECKING :
32
- import numpy .typing as npt
33
-
34
32
from manim .typing import (
35
33
BezierPoints ,
36
34
BezierPoints_Array ,
37
35
BezierPointsLike ,
38
36
BezierPointsLike_Array ,
39
37
ColVector ,
40
- ManimFloat ,
41
38
MatrixMN ,
42
39
Point3D ,
43
40
Point3D_Array ,
@@ -64,7 +61,9 @@ def bezier(
64
61
) -> Callable [[float | ColVector ], Point3D_Array ]: ...
65
62
66
63
67
- def bezier (points ):
64
+ def bezier (
65
+ points : Point3D_Array | Sequence [Point3D_Array ],
66
+ ) -> Callable [[float | ColVector ], Point3D_Array ]:
68
67
"""Classic implementation of a Bézier curve.
69
68
70
69
Parameters
@@ -118,21 +117,21 @@ def bezier(points):
118
117
119
118
if degree == 0 :
120
119
121
- def zero_bezier (t ) :
120
+ def zero_bezier (t : float | ColVector ) -> Point3D | Point3D_Array :
122
121
return np .ones_like (t ) * P [0 ]
123
122
124
123
return zero_bezier
125
124
126
125
if degree == 1 :
127
126
128
- def linear_bezier (t ) :
127
+ def linear_bezier (t : float | ColVector ) -> Point3D | Point3D_Array :
129
128
return P [0 ] + t * (P [1 ] - P [0 ])
130
129
131
130
return linear_bezier
132
131
133
132
if degree == 2 :
134
133
135
- def quadratic_bezier (t ) :
134
+ def quadratic_bezier (t : float | ColVector ) -> Point3D | Point3D_Array :
136
135
t2 = t * t
137
136
mt = 1 - t
138
137
mt2 = mt * mt
@@ -142,7 +141,7 @@ def quadratic_bezier(t):
142
141
143
142
if degree == 3 :
144
143
145
- def cubic_bezier (t ) :
144
+ def cubic_bezier (t : float | ColVector ) -> Point3D | Point3D_Array :
146
145
t2 = t * t
147
146
t3 = t2 * t
148
147
mt = 1 - t
@@ -152,11 +151,12 @@ def cubic_bezier(t):
152
151
153
152
return cubic_bezier
154
153
155
- def nth_grade_bezier (t ) :
154
+ def nth_grade_bezier (t : float | ColVector ) -> Point3D | Point3D_Array :
156
155
is_scalar = not isinstance (t , np .ndarray )
157
156
if is_scalar :
158
157
B = np .empty ((1 , * P .shape ))
159
158
else :
159
+ assert isinstance (t , np .ndarray )
160
160
t = t .reshape (- 1 , * [1 for dim in P .shape ])
161
161
B = np .empty ((t .shape [0 ], * P .shape ))
162
162
B [:] = P
@@ -169,7 +169,8 @@ def nth_grade_bezier(t):
169
169
# In the end, there shall be the evaluation at t of a single Bezier curve of
170
170
# grade d, stored in the first slot of B
171
171
if is_scalar :
172
- return B [0 , 0 ]
172
+ val : Point3D = B [0 , 0 ]
173
+ return val
173
174
return B [:, 0 ]
174
175
175
176
return nth_grade_bezier
@@ -1026,7 +1027,11 @@ def interpolate(start: Point3D, end: Point3D, alpha: float) -> Point3D: ...
1026
1027
def interpolate (start : Point3D , end : Point3D , alpha : ColVector ) -> Point3D_Array : ...
1027
1028
1028
1029
1029
- def interpolate (start , end , alpha ):
1030
+ def interpolate (
1031
+ start : float | Point3D ,
1032
+ end : float | Point3D ,
1033
+ alpha : float | ColVector ,
1034
+ ) -> float | ColVector | Point3D | Point3D_Array :
1030
1035
"""Linearly interpolates between two values ``start`` and ``end``.
1031
1036
1032
1037
Parameters
@@ -1139,7 +1144,9 @@ def inverse_interpolate(start: Point3D, end: Point3D, value: Point3D) -> Point3D
1139
1144
1140
1145
1141
1146
def inverse_interpolate (
1142
- start : float | Point3D , end : float | Point3D , value : float | Point3D
1147
+ start : float | Point3D ,
1148
+ end : float | Point3D ,
1149
+ value : float | Point3D ,
1143
1150
) -> float | Point3D :
1144
1151
"""Perform inverse interpolation to determine the alpha
1145
1152
values that would produce the specified ``value``
@@ -1234,7 +1241,7 @@ def match_interpolate(
1234
1241
return interpolate (
1235
1242
new_start ,
1236
1243
new_end ,
1237
- old_alpha , # type: ignore[arg-type]
1244
+ old_alpha ,
1238
1245
)
1239
1246
1240
1247
@@ -1270,7 +1277,8 @@ def get_smooth_cubic_bezier_handle_points(
1270
1277
# they can only be an interpolation of these two anchors with alphas
1271
1278
# 1/3 and 2/3, which will draw a straight line between the anchors.
1272
1279
if n_anchors == 2 :
1273
- return interpolate (anchors [0 ], anchors [1 ], np .array ([[1 / 3 ], [2 / 3 ]]))
1280
+ val = interpolate (anchors [0 ], anchors [1 ], np .array ([[1 / 3 ], [2 / 3 ]]))
1281
+ return (val [0 ], val [1 ])
1274
1282
1275
1283
# Handle different cases depending on whether the points form a closed
1276
1284
# curve or not
@@ -1745,7 +1753,12 @@ def get_quadratic_approximation_of_cubic(
1745
1753
) -> QuadraticBezierPath : ...
1746
1754
1747
1755
1748
- def get_quadratic_approximation_of_cubic (a0 , h0 , h1 , a1 ):
1756
+ def get_quadratic_approximation_of_cubic (
1757
+ a0 : Point3D | Point3D_Array ,
1758
+ h0 : Point3D | Point3D_Array ,
1759
+ h1 : Point3D | Point3D_Array ,
1760
+ a1 : Point3D | Point3D_Array ,
1761
+ ) -> QuadraticSpline | QuadraticBezierPath :
1749
1762
r"""If ``a0``, ``h0``, ``h1`` and ``a1`` are the control points of a cubic
1750
1763
Bézier curve, approximate the curve with two quadratic Bézier curves and
1751
1764
return an array of 6 points, where the first 3 points represent the first
@@ -1849,33 +1862,33 @@ def get_quadratic_approximation_of_cubic(a0, h0, h1, a1):
1849
1862
If ``a0``, ``h0``, ``h1`` and ``a1`` have different dimensions, or
1850
1863
if their number of dimensions is not 1 or 2.
1851
1864
"""
1852
- a0 = np .asarray (a0 )
1853
- h0 = np .asarray (h0 )
1854
- h1 = np .asarray (h1 )
1855
- a1 = np .asarray (a1 )
1856
-
1857
- if all (arr .ndim == 1 for arr in (a0 , h0 , h1 , a1 )):
1858
- num_curves , dim = 1 , a0 .shape [0 ]
1859
- elif all (arr .ndim == 2 for arr in (a0 , h0 , h1 , a1 )):
1860
- num_curves , dim = a0 .shape
1865
+ a0c = np .asarray (a0 )
1866
+ h0c = np .asarray (h0 )
1867
+ h1c = np .asarray (h1 )
1868
+ a1c = np .asarray (a1 )
1869
+
1870
+ if all (arr .ndim == 1 for arr in (a0c , h0c , h1c , a1c )):
1871
+ num_curves , dim = 1 , a0c .shape [0 ]
1872
+ elif all (arr .ndim == 2 for arr in (a0c , h0c , h1c , a1c )):
1873
+ num_curves , dim = a0c .shape
1861
1874
else :
1862
1875
raise ValueError ("All arguments must be Point3D or Point3D_Array." )
1863
1876
1864
- m0 = 0.25 * (3 * h0 + a0 )
1865
- m1 = 0.25 * (3 * h1 + a1 )
1877
+ m0 = 0.25 * (3 * h0c + a0c )
1878
+ m1 = 0.25 * (3 * h1c + a1c )
1866
1879
k = 0.5 * (m0 + m1 )
1867
1880
1868
1881
result = np .empty ((6 * num_curves , dim ))
1869
- result [0 ::6 ] = a0
1882
+ result [0 ::6 ] = a0c
1870
1883
result [1 ::6 ] = m0
1871
1884
result [2 ::6 ] = k
1872
1885
result [3 ::6 ] = k
1873
1886
result [4 ::6 ] = m1
1874
- result [5 ::6 ] = a1
1887
+ result [5 ::6 ] = a1c
1875
1888
return result
1876
1889
1877
1890
1878
- def is_closed (points : Point3DLike_Array ) -> bool :
1891
+ def is_closed (points : Point3D_Array ) -> bool :
1879
1892
"""Returns ``True`` if the spline given by ``points`` is closed, by
1880
1893
checking if its first and last points are close to each other, or``False``
1881
1894
otherwise.
@@ -1952,7 +1965,7 @@ def proportions_along_bezier_curve_for_point(
1952
1965
point : Point3DLike ,
1953
1966
control_points : BezierPointsLike ,
1954
1967
round_to : float = 1e-6 ,
1955
- ) -> npt . NDArray [ ManimFloat ] :
1968
+ ) -> MatrixMN :
1956
1969
"""Obtains the proportion along the bezier curve corresponding to a given point
1957
1970
given the bezier curve's control points.
1958
1971
0 commit comments