This commit is contained in:
viniciuspalmieri 2026-06-21 07:00:32 +08:00 committed by GitHub
commit 2768fd92f4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 76 additions and 27 deletions

View file

@ -327,7 +327,7 @@ class ManimConfig(MutableMapping):
}
def __init__(self) -> None:
self._d: dict[str, Any | None] = dict.fromkeys(self._OPTS)
self._d: dict[str, Any] = dict.fromkeys(self._OPTS)
# behave like a dict
def __iter__(self) -> Iterator[str]:
@ -423,13 +423,13 @@ class ManimConfig(MutableMapping):
"""See ManimConfig.copy()."""
return copy.deepcopy(self)
def __deepcopy__(self, memo: dict[str, Any]) -> Self:
def __deepcopy__(self, memo: dict[int, Any]) -> Self:
"""See ManimConfig.copy()."""
c = type(self)()
# Deepcopying the underlying dict is enough because all properties
# either read directly from it or compute their value on the fly from
# values read directly from it.
c._d = copy.deepcopy(self._d, memo) # type: ignore[arg-type]
c._d = copy.deepcopy(self._d, memo)
return c
# helper type-checking methods
@ -1142,24 +1142,22 @@ class ManimConfig(MutableMapping):
@property
def frame_y_radius(self) -> float:
"""Half the frame height (no flag)."""
return self._d["frame_height"] / 2 # type: ignore[operator]
return self._d["frame_height"] / 2
@frame_y_radius.setter
def frame_y_radius(self, value: float) -> None:
self._d.__setitem__("frame_y_radius", value) or self._d.__setitem__( # type: ignore[func-returns-value]
"frame_height", 2 * value
)
self._d["frame_y_radius"] = value
self._d["frame_height"] = 2 * value
@property
def frame_x_radius(self) -> float:
"""Half the frame width (no flag)."""
return self._d["frame_width"] / 2 # type: ignore[operator]
return self._d["frame_width"] / 2
@frame_x_radius.setter
def frame_x_radius(self, value: float) -> None:
self._d.__setitem__("frame_x_radius", value) or self._d.__setitem__( # type: ignore[func-returns-value]
"frame_width", 2 * value
)
self._d["frame_x_radius"] = value
self._d["frame_width"] = 2 * value
@property
def top(self) -> Vector3D:
@ -1290,9 +1288,8 @@ class ManimConfig(MutableMapping):
@frame_size.setter
def frame_size(self, value: tuple[int, int]) -> None:
self._d.__setitem__("pixel_width", value[0]) or self._d.__setitem__( # type: ignore[func-returns-value]
"pixel_height", value[1]
)
self._d["pixel_width"] = value[0]
self._d["pixel_height"] = value[1]
@property
def quality(self) -> str | None:

51
manim/mobject/_fit.py Normal file
View file

@ -0,0 +1,51 @@
"""Fit-to-size operations for :class:`~.Mobject`.
Standalone functions that take a mobject as their first argument; the
corresponding methods on :class:`Mobject` are thin delegations to these
helpers. This keeps :class:`Mobject`'s public API unchanged while moving
the implementation out of the already-large ``mobject.py``.
"""
from __future__ import annotations
from typing import TYPE_CHECKING, Any
if TYPE_CHECKING:
from manim.mobject.mobject import Mobject
def rescale_to_fit(
mob: Mobject, length: float, dim: int, stretch: bool = False, **kwargs: Any
) -> Mobject:
old_length = mob.length_over_dim(dim)
if old_length == 0:
return mob
if stretch:
mob.stretch(length / old_length, dim, **kwargs)
else:
mob.scale(length / old_length, **kwargs)
return mob
def scale_to_fit_width(mob: Mobject, width: float, **kwargs: Any) -> Mobject:
return rescale_to_fit(mob, width, 0, stretch=False, **kwargs)
def stretch_to_fit_width(mob: Mobject, width: float, **kwargs: Any) -> Mobject:
return rescale_to_fit(mob, width, 0, stretch=True, **kwargs)
def scale_to_fit_height(mob: Mobject, height: float, **kwargs: Any) -> Mobject:
return rescale_to_fit(mob, height, 1, stretch=False, **kwargs)
def stretch_to_fit_height(mob: Mobject, height: float, **kwargs: Any) -> Mobject:
return rescale_to_fit(mob, height, 1, stretch=True, **kwargs)
def scale_to_fit_depth(mob: Mobject, depth: float, **kwargs: Any) -> Mobject:
return rescale_to_fit(mob, depth, 2, stretch=False, **kwargs)
def stretch_to_fit_depth(mob: Mobject, depth: float, **kwargs: Any) -> Mobject:
return rescale_to_fit(mob, depth, 2, stretch=True, **kwargs)

View file

@ -22,6 +22,7 @@ from typing import TYPE_CHECKING, Any, cast
import numpy as np
from manim.data_structures import MethodWithArgs
from manim.mobject import _fit
from manim.mobject.opengl.opengl_compatibility import ConvertToOpenGL
from .. import config, logger
@ -1752,13 +1753,7 @@ class Mobject:
def rescale_to_fit(
self, length: float, dim: int, stretch: bool = False, **kwargs: Any
) -> Self:
old_length = self.length_over_dim(dim)
if old_length == 0:
return self
if stretch:
self.stretch(length / old_length, dim, **kwargs)
else:
self.scale(length / old_length, **kwargs)
_fit.rescale_to_fit(self, length, dim, stretch=stretch, **kwargs)
return self
def scale_to_fit_width(self, width: float, **kwargs: Any) -> Self:
@ -1784,7 +1779,8 @@ class Mobject:
>>> sq.height
np.float64(5.0)
"""
return self.rescale_to_fit(width, 0, stretch=False, **kwargs)
_fit.scale_to_fit_width(self, width, **kwargs)
return self
def stretch_to_fit_width(self, width: float, **kwargs: Any) -> Self:
"""Stretches the :class:`~.Mobject` to fit a width, not keeping height/depth proportional.
@ -1809,7 +1805,8 @@ class Mobject:
>>> sq.height
np.float64(2.0)
"""
return self.rescale_to_fit(width, 0, stretch=True, **kwargs)
_fit.stretch_to_fit_width(self, width, **kwargs)
return self
def scale_to_fit_height(self, height: float, **kwargs: Any) -> Self:
"""Scales the :class:`~.Mobject` to fit a height while keeping width/depth proportional.
@ -1834,7 +1831,8 @@ class Mobject:
>>> sq.width
np.float64(5.0)
"""
return self.rescale_to_fit(height, 1, stretch=False, **kwargs)
_fit.scale_to_fit_height(self, height, **kwargs)
return self
def stretch_to_fit_height(self, height: float, **kwargs: Any) -> Self:
"""Stretches the :class:`~.Mobject` to fit a height, not keeping width/depth proportional.
@ -1859,15 +1857,18 @@ class Mobject:
>>> sq.width
np.float64(2.0)
"""
return self.rescale_to_fit(height, 1, stretch=True, **kwargs)
_fit.stretch_to_fit_height(self, height, **kwargs)
return self
def scale_to_fit_depth(self, depth: float, **kwargs: Any) -> Self:
"""Scales the :class:`~.Mobject` to fit a depth while keeping width/height proportional."""
return self.rescale_to_fit(depth, 2, stretch=False, **kwargs)
_fit.scale_to_fit_depth(self, depth, **kwargs)
return self
def stretch_to_fit_depth(self, depth: float, **kwargs: Any) -> Self:
"""Stretches the :class:`~.Mobject` to fit a depth, not keeping width/height proportional."""
return self.rescale_to_fit(depth, 2, stretch=True, **kwargs)
_fit.stretch_to_fit_depth(self, depth, **kwargs)
return self
def set_coord(
self, value: float, dim: int, direction: Vector3DLike = ORIGIN