Skip to content

Type annotation work in manim/mobject/geometry/ #3961

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 44 commits into from
Oct 27, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
35597d5
Removed type annotation errors
henrikmidtiby Oct 17, 2024
cd73909
Removed type annotation errors
henrikmidtiby Oct 17, 2024
1ba82f7
Removed typing errors in mobject/geometry/arc.py
henrikmidtiby Oct 17, 2024
3b38bba
Removed typing errors in mobject/geometry/shape_matchers.py
henrikmidtiby Oct 18, 2024
b6f8e38
Added type annotations fo mobject/types/image_mobject.py and a few ot…
henrikmidtiby Oct 18, 2024
5bf79dc
Avoid overwriting the invert method of the superclass
henrikmidtiby Oct 18, 2024
612068d
Adding type annotations to types/point_cloud_mobject.py
henrikmidtiby Oct 18, 2024
774c136
Fixing issues revealed by type annotations in types/point_cloud_mobje…
henrikmidtiby Oct 18, 2024
be3938d
Fix issue in the CI step related to the Camera class.
henrikmidtiby Oct 18, 2024
5be34e3
Removed type errors by replacing Point3D with InternalPoint3D
henrikmidtiby Oct 18, 2024
bbfb247
Adding type annotations to geometry/line.py
henrikmidtiby Oct 18, 2024
d294e6f
Fix issues identified by type annotations.
henrikmidtiby Oct 18, 2024
00a0b1f
Work on type annotations in geometry/polygram.py
henrikmidtiby Oct 18, 2024
257c023
Ignore type errors related to super and sub class in line.py and shap…
henrikmidtiby Oct 19, 2024
6b88833
Remove return value from the internal method _account_for_buff
henrikmidtiby Oct 19, 2024
16716a4
Dealing with some issues and ignoring others identified by type checking
henrikmidtiby Oct 19, 2024
efe49b7
Ignored a number of type issues related to float and floating[Any].
henrikmidtiby Oct 20, 2024
68a3d66
Help mypy to determine types.
henrikmidtiby Oct 20, 2024
80226e2
Fix issues identified by mypy
henrikmidtiby Oct 20, 2024
0018f8d
Change example in docs for _convert_2d_to_3d_array
henrikmidtiby Oct 21, 2024
56d2a94
Change example in docs for _convert_2d_to_3d_array to make the doctes…
henrikmidtiby Oct 21, 2024
66d2cea
More work on addressing typing issues.
henrikmidtiby Oct 21, 2024
33da68d
Reverting two changes that triggers an error in the automatic testing.
henrikmidtiby Oct 21, 2024
e498903
Further work on type hinting.
henrikmidtiby Oct 21, 2024
e18a644
Added comment to why these mypy errors can be ignored
henrikmidtiby Oct 22, 2024
80ae857
Avoid forwarding positional arguments from Arrow to Line in the const…
henrikmidtiby Oct 22, 2024
d477c9a
Activate mypy check of mobject.geometry.*
henrikmidtiby Oct 22, 2024
a14b99a
Revert "Avoid forwarding positional arguments from Arrow to Line in t…
henrikmidtiby Oct 22, 2024
07bbe3f
Removed several type ignore statements and addressed comments from Ja…
henrikmidtiby Oct 22, 2024
46bbcba
Revert "Activate mypy check of mobject.geometry.*"
henrikmidtiby Oct 22, 2024
61a9168
Revert "Removed several type ignore statements and addressed comments…
henrikmidtiby Oct 22, 2024
50169c2
Update manim/mobject/geometry/arc.py
henrikmidtiby Oct 25, 2024
daa6a08
Remove redundant type annotations.
henrikmidtiby Oct 25, 2024
7647209
Change np.array to np.asarray
henrikmidtiby Oct 25, 2024
581c72a
Avoid type annotations in comments.
henrikmidtiby Oct 25, 2024
ed422ce
Change from np.array to np.asarray
henrikmidtiby Oct 25, 2024
601072d
Switch to StrPath for typing in two locations.
henrikmidtiby Oct 25, 2024
ecd9357
Change the type annotation Any to something more specific.
henrikmidtiby Oct 25, 2024
3e30555
Change InternalPoint3D to Point3D for an argument to the Polygram con…
henrikmidtiby Oct 25, 2024
9a92bf5
Remove unneccessary noqa
JasonGrace2282 Oct 27, 2024
5bfc25e
Merge branch 'main' of https://github.com/ManimCommunity/manim into t…
JasonGrace2282 Oct 27, 2024
53ba462
enable mypy type-checking on manim.mobject.geometry.*
JasonGrace2282 Oct 27, 2024
d288979
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 27, 2024
01e566a
fix mypy ci
JasonGrace2282 Oct 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 68 additions & 52 deletions manim/mobject/geometry/arc.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,20 @@
)

if TYPE_CHECKING:
from collections.abc import Iterable
from typing import Any

import manim.mobject.geometry.tips as tips
from manim.mobject.mobject import Mobject
from manim.mobject.text.tex_mobject import SingleStringMathTex, Tex
from manim.mobject.text.text_mobject import Text
from manim.typing import CubicBezierPoints, Point3D, QuadraticBezierPoints, Vector3D
from manim.typing import (
CubicBezierPoints,
InternalPoint3D,
Point3D,
QuadraticBezierPoints,
Vector3D,
)


class TipableVMobject(VMobject, metaclass=ConvertToOpenGL):
Expand All @@ -93,7 +102,7 @@
tip_length: float = DEFAULT_ARROW_TIP_LENGTH,
normal_vector: Vector3D = OUT,
tip_style: dict = {},
**kwargs,
**kwargs: Any,
) -> None:
self.tip_length: float = tip_length
self.normal_vector: Vector3D = normal_vector
Expand Down Expand Up @@ -126,10 +135,10 @@
def create_tip(
self,
tip_shape: type[tips.ArrowTip] | None = None,
tip_length: float = None,
tip_width: float = None,
tip_length: float | None = None,
tip_width: float | None = None,
at_start: bool = False,
):
) -> tips.ArrowTip | tips.ArrowTriangleFilledTip:
"""Stylises the tip, positions it spatially, and returns
the newly instantiated tip to the caller.
"""
Expand All @@ -142,13 +151,13 @@
tip_shape: type[tips.ArrowTip] | None = None,
tip_length: float | None = None,
tip_width: float | None = None,
):
) -> tips.ArrowTip | tips.ArrowTriangleFilledTip:
"""Returns a tip that has been stylistically configured,
but has not yet been given a position in space.
"""
from manim.mobject.geometry.tips import ArrowTriangleFilledTip

style = {}
style: dict[str, Any] = {}

if tip_shape is None:
tip_shape = ArrowTriangleFilledTip
Expand All @@ -166,7 +175,7 @@
tip = tip_shape(length=tip_length, **style)
return tip

def position_tip(self, tip: tips.ArrowTip, at_start: bool = False):
def position_tip(self, tip: tips.ArrowTip, at_start: bool = False) -> tips.ArrowTip:
# Last two control points, defining both
# the end, and the tangency direction
if at_start:
Expand All @@ -180,11 +189,13 @@
angles[1] - PI - tip.tip_angle,
) # Rotates the tip along the azimuthal
if not hasattr(self, "_init_positioning_axis"):
axis = [
np.sin(angles[1]),
-np.cos(angles[1]),
0,
] # Obtains the perpendicular of the tip
axis = np.array(
[
np.sin(angles[1]),
-np.cos(angles[1]),
0,
]
) # Obtains the perpendicular of the tip
tip.rotate(
-angles[2] + PI / 2,
axis=axis,
Expand Down Expand Up @@ -244,7 +255,7 @@
result.add(self.start_tip)
return result

def get_tip(self):
def get_tip(self) -> VMobject:
"""Returns the TipableVMobject instance's (first) tip,
otherwise throws an exception.
"""
Expand All @@ -263,19 +274,19 @@
def get_last_handle(self) -> Point3D:
return self.points[-2]

def get_end(self) -> Point3D:
def get_end(self) -> InternalPoint3D:
if self.has_tip():
return self.tip.get_start()
return self.tip.get_start() # type: ignore[return-value]
else:
return super().get_end()
return super().get_end() # type: ignore[return-value]

def get_start(self) -> Point3D:
def get_start(self) -> InternalPoint3D:
if self.has_start_tip():
return self.start_tip.get_start()
return self.start_tip.get_start() # type: ignore[return-value]
else:
return super().get_start()
return super().get_start() # type: ignore[return-value]

def get_length(self) -> np.floating:
def get_length(self) -> float:
start, end = self.get_start_and_end()
return np.linalg.norm(start - end)

Expand All @@ -297,18 +308,18 @@

def __init__(
self,
radius: float = 1.0,
radius: float | None = 1.0,
start_angle: float = 0,
angle: float = TAU / 4,
num_components: int = 9,
arc_center: Point3D = ORIGIN,
**kwargs,
arc_center: InternalPoint3D = ORIGIN,
**kwargs: Any,
):
if radius is None: # apparently None is passed by ArcBetweenPoints
radius = 1.0
self.radius = radius
self.num_components: int = num_components
self.arc_center: Point3D = arc_center
self.arc_center: InternalPoint3D = arc_center
self.start_angle: float = start_angle
self.angle: float = angle
self._failed_to_get_center: bool = False
Expand Down Expand Up @@ -379,7 +390,7 @@
handles2 = anchors[1:] - (d_theta / 3) * tangent_vectors[1:]
self.set_anchors_and_handles(anchors[:-1], handles1, handles2, anchors[1:])

def get_arc_center(self, warning: bool = True) -> Point3D:
def get_arc_center(self, warning: bool = True) -> InternalPoint3D:
"""Looks at the normals to the first two
anchors, and finds their intersection points
"""
Expand Down Expand Up @@ -407,7 +418,7 @@
self._failed_to_get_center = True
return np.array(ORIGIN)

def move_arc_center_to(self, point: Point3D) -> Self:
def move_arc_center_to(self, point: InternalPoint3D) -> Self:
self.shift(point - self.get_arc_center())
return self

Expand Down Expand Up @@ -439,8 +450,8 @@
start: Point3D,
end: Point3D,
angle: float = TAU / 4,
radius: float = None,
**kwargs,
radius: float | None = None,
**kwargs: Any,
) -> None:
if radius is not None:
self.radius = radius
Expand All @@ -460,19 +471,20 @@

super().__init__(radius=radius, angle=angle, **kwargs)
if angle == 0:
self.set_points_as_corners([LEFT, RIGHT])
self.set_points_as_corners(np.array([LEFT, RIGHT]))
self.put_start_and_end_on(start, end)

if radius is None:
center = self.get_arc_center(warning=False)
if not self._failed_to_get_center:
self.radius = np.linalg.norm(np.array(start) - np.array(center))
temp_radius: float = np.linalg.norm(np.array(start) - np.array(center)) # type: ignore[assignment]
self.radius = temp_radius
else:
self.radius = np.inf


class CurvedArrow(ArcBetweenPoints):
def __init__(self, start_point: Point3D, end_point: Point3D, **kwargs) -> None:
def __init__(self, start_point: Point3D, end_point: Point3D, **kwargs: Any) -> None:
from manim.mobject.geometry.tips import ArrowTriangleFilledTip

tip_shape = kwargs.pop("tip_shape", ArrowTriangleFilledTip)
Expand All @@ -481,7 +493,7 @@


class CurvedDoubleArrow(CurvedArrow):
def __init__(self, start_point: Point3D, end_point: Point3D, **kwargs) -> None:
def __init__(self, start_point: Point3D, end_point: Point3D, **kwargs: Any) -> None:
if "tip_shape_end" in kwargs:
kwargs["tip_shape"] = kwargs.pop("tip_shape_end")
from manim.mobject.geometry.tips import ArrowTriangleFilledTip
Expand Down Expand Up @@ -520,7 +532,7 @@
self,
radius: float | None = None,
color: ParsableManimColor = RED,
**kwargs,
**kwargs: Any,
) -> None:
super().__init__(
radius=radius,
Expand Down Expand Up @@ -617,7 +629,9 @@
return self.point_from_proportion(proportion)

@staticmethod
def from_three_points(p1: Point3D, p2: Point3D, p3: Point3D, **kwargs) -> Self:
def from_three_points(
p1: Point3D, p2: Point3D, p3: Point3D, **kwargs: Any
) -> Circle:
"""Returns a circle passing through the specified
three points.

Expand All @@ -637,10 +651,10 @@
self.add(NumberPlane(), circle, dots)
"""
center = line_intersection(
perpendicular_bisector([p1, p2]),
perpendicular_bisector([p2, p3]),
perpendicular_bisector([np.array(p1), np.array(p2)]),
perpendicular_bisector([np.array(p2), np.array(p3)]),
)
radius = np.linalg.norm(p1 - center)
radius: float = np.linalg.norm(p1 - center) # type: ignore[assignment]
return Circle(radius=radius, **kwargs).shift(center)


Expand Down Expand Up @@ -682,7 +696,7 @@
stroke_width: float = 0,
fill_opacity: float = 1.0,
color: ParsableManimColor = WHITE,
**kwargs,
**kwargs: Any,
) -> None:
super().__init__(
arc_center=point,
Expand All @@ -703,7 +717,7 @@
stroke_width: float = 5,
stroke_color: ParsableManimColor = WHITE,
fill_color: ParsableManimColor = BLUE,
**kwargs,
**kwargs: Any,
) -> None:
super().__init__(
radius=radius,
Expand Down Expand Up @@ -752,12 +766,12 @@
self,
label: str | SingleStringMathTex | Text | Tex,
radius: float | None = None,
**kwargs,
**kwargs: Any,
) -> None:
if isinstance(label, str):
from manim import MathTex

rendered_label = MathTex(label, color=BLACK)
rendered_label: VMobject = MathTex(label, color=BLACK)
else:
rendered_label = label

Expand Down Expand Up @@ -793,7 +807,7 @@
self.add(ellipse_group)
"""

def __init__(self, width: float = 2, height: float = 1, **kwargs) -> None:
def __init__(self, width: float = 2, height: float = 1, **kwargs: Any) -> None:
super().__init__(**kwargs)
self.stretch_to_fit_width(width)
self.stretch_to_fit_height(height)
Expand Down Expand Up @@ -854,7 +868,7 @@
fill_opacity: float = 1,
stroke_width: float = 0,
color: ParsableManimColor = WHITE,
**kwargs,
**kwargs: Any,
) -> None:
self.inner_radius = inner_radius
self.outer_radius = outer_radius
Expand Down Expand Up @@ -903,7 +917,7 @@
self.add(sector, sector2)
"""

def __init__(self, radius: float = 1, **kwargs) -> None:
def __init__(self, radius: float = 1, **kwargs: Any) -> None:
super().__init__(inner_radius=0, outer_radius=radius, **kwargs)


Expand Down Expand Up @@ -933,13 +947,13 @@

def __init__(
self,
inner_radius: float | None = 1,
outer_radius: float | None = 2,
inner_radius: float = 1,
outer_radius: float = 2,
fill_opacity: float = 1,
stroke_width: float = 0,
color: ParsableManimColor = WHITE,
mark_paths_closed: bool = False,
**kwargs,
**kwargs: Any,
) -> None:
self.mark_paths_closed = mark_paths_closed # is this even used?
self.inner_radius = inner_radius
Expand Down Expand Up @@ -989,7 +1003,7 @@
start_handle: CubicBezierPoints,
end_handle: CubicBezierPoints,
end_anchor: CubicBezierPoints,
**kwargs,
**kwargs: Any,
) -> None:
super().__init__(**kwargs)
self.add_cubic_bezier_curve(start_anchor, start_handle, end_handle, end_anchor)
Expand Down Expand Up @@ -1080,14 +1094,16 @@
angle: float = PI / 4,
radius: float | None = None,
arc_config: list[dict] | None = None,
**kwargs,
**kwargs: Any,
) -> None:
n = len(vertices)
point_pairs = [(vertices[k], vertices[(k + 1) % n]) for k in range(n)]

if not arc_config:
if radius:
all_arc_configs = itertools.repeat({"radius": radius}, len(point_pairs))
all_arc_configs: Iterable[dict] = itertools.repeat(
{"radius": radius}, len(point_pairs)
)
else:
all_arc_configs = itertools.repeat({"angle": angle}, len(point_pairs))
elif isinstance(arc_config, dict):
Expand Down Expand Up @@ -1219,7 +1235,7 @@
self.wait(2)
"""

def __init__(self, *arcs: Arc | ArcBetweenPoints, **kwargs) -> None:
def __init__(self, *arcs: Arc | ArcBetweenPoints, **kwargs: Any) -> None:
if not all(isinstance(m, (Arc, ArcBetweenPoints)) for m in arcs):
raise ValueError(
"All ArcPolygon submobjects must be of type Arc/ArcBetweenPoints",
Expand Down
Loading
Loading