mirror of
https://github.com/ManimCommunity/manim.git
synced 2026-06-22 10:01:47 +00:00
Fix empty submobjects distorting width/height of parent Mobject (#4088)
* Issue-4087 Add bug test * Issue-4087 Fix bug * Issue-4087 Fix comment and add type hint * Issue-4087 Fix comment * Issue-4087 Improve previous test instead of adding a new one * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update tests/module/mobject/mobject/test_mobject.py * Enhance docstring for reduce_across_dimension method Updated docstring for reduce_across_dimension method to clarify its purpose and parameters. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Remove float typehints for coords in length_over_dim * Modify test for empty VMobject dimensions * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Francisco Manríquez Novoa <49853152+chopan050@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
82522795f1
commit
852ebd1c60
2 changed files with 60 additions and 26 deletions
|
|
@ -2162,13 +2162,31 @@ class Mobject:
|
|||
|
||||
def reduce_across_dimension(
|
||||
self, reduce_func: Callable[[Iterable[float]], float], dim: int
|
||||
) -> float:
|
||||
"""Find the min or max value from a dimension across all points in this and submobjects."""
|
||||
) -> float | None:
|
||||
"""Find the min or max value from a dimension across all points in this Mobject and its
|
||||
submobjects. This allows for using :meth:`~.length_over_dim` to calculate its length over
|
||||
a dimension, i.e. its height, width or depth. If this Mobject is empty, return ``None``,
|
||||
since this Mobject should not be taken into account when calculating lengths.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
reduce_func
|
||||
The reducer function to use in order to calculate a value over a dimension.
|
||||
dim
|
||||
The dimension to use. It should be 0, 1 or 2, representing the X, Y or Z coordinate,
|
||||
respectively.
|
||||
|
||||
Returns
|
||||
-------
|
||||
float | None
|
||||
The min or max value over the dimension specified by ``dim``, or ``None`` if this
|
||||
Mobject is empty.
|
||||
"""
|
||||
assert dim >= 0
|
||||
assert dim <= 2
|
||||
if len(self.submobjects) == 0 and len(self.points) == 0:
|
||||
# If we have no points and no submobjects, return 0 (e.g. center)
|
||||
return 0
|
||||
# If we have no points and no submobjects, return None
|
||||
return None
|
||||
|
||||
# If we do not have points (but do have submobjects)
|
||||
# use only the points from those.
|
||||
|
|
@ -2181,8 +2199,10 @@ class Mobject:
|
|||
# smallest dimension they have and compare it to the return value.
|
||||
for mobj in self.submobjects:
|
||||
value = mobj.reduce_across_dimension(reduce_func, dim)
|
||||
rv = value if rv is None else reduce_func([value, rv])
|
||||
assert rv is not None
|
||||
if rv is None:
|
||||
rv = value
|
||||
elif value is not None:
|
||||
rv = reduce_func([value, rv])
|
||||
return rv
|
||||
|
||||
def nonempty_submobjects(self) -> Sequence[Mobject]:
|
||||
|
|
@ -2336,11 +2356,10 @@ class Mobject:
|
|||
|
||||
def length_over_dim(self, dim: int) -> float:
|
||||
"""Measure the length of an :class:`~.Mobject` in a certain direction."""
|
||||
max_coord: float = self.reduce_across_dimension(
|
||||
max,
|
||||
dim,
|
||||
)
|
||||
min_coord: float = self.reduce_across_dimension(min, dim)
|
||||
max_coord = self.reduce_across_dimension(max, dim)
|
||||
min_coord = self.reduce_across_dimension(min, dim)
|
||||
if max_coord is None or min_coord is None:
|
||||
return 0
|
||||
return max_coord - min_coord
|
||||
|
||||
def get_coord(self, dim: int, direction: Vector3DLike = ORIGIN) -> float:
|
||||
|
|
|
|||
|
|
@ -3,7 +3,20 @@ from __future__ import annotations
|
|||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from manim import DL, PI, UR, Circle, Mobject, Rectangle, Square, Triangle, VGroup
|
||||
from manim import (
|
||||
DL,
|
||||
DR,
|
||||
PI,
|
||||
UL,
|
||||
UR,
|
||||
Circle,
|
||||
Mobject,
|
||||
Rectangle,
|
||||
Square,
|
||||
Triangle,
|
||||
VGroup,
|
||||
VMobject,
|
||||
)
|
||||
|
||||
|
||||
def test_mobject_add():
|
||||
|
|
@ -135,22 +148,24 @@ def test_mobject_dimensions_nested_mobjects():
|
|||
assert is_close(vg.depth, 0.775), vg.depth
|
||||
|
||||
|
||||
def test_mobject_dimensions_mobjects_with_no_points_are_at_origin():
|
||||
rect = Rectangle(width=2, height=3)
|
||||
rect.move_to([-4, -5, 0])
|
||||
outer_group = VGroup(rect)
|
||||
def test_mobject_dimensions_mobjects_with_no_points():
|
||||
empty_mob = VMobject()
|
||||
assert empty_mob.width == 0
|
||||
assert empty_mob.height == 0
|
||||
|
||||
# This is as one would expect
|
||||
assert outer_group.width == 2
|
||||
assert outer_group.height == 3
|
||||
for direction in [DL, DR, UL, UR]:
|
||||
rect = Rectangle(width=2, height=3)
|
||||
rect.move_to(direction * 10)
|
||||
outer_group = VGroup(rect)
|
||||
|
||||
# Adding a mobject with no points has a quirk of adding a "point"
|
||||
# to [0, 0, 0] (the origin). This changes the size of the outer
|
||||
# group because now the bottom left corner is at [-5, -6.5, 0]
|
||||
# but the upper right corner is [0, 0, 0] instead of [-3, -3.5, 0]
|
||||
outer_group.add(VGroup())
|
||||
assert outer_group.width == 5
|
||||
assert outer_group.height == 6.5
|
||||
# This is as one would expect
|
||||
assert outer_group.width == 2
|
||||
assert outer_group.height == 3
|
||||
|
||||
# Adding a submobject with no points does not change the group size
|
||||
outer_group.add(empty_mob)
|
||||
assert outer_group.width == 2
|
||||
assert outer_group.height == 3
|
||||
|
||||
|
||||
def test_mobject_dimensions_has_points_and_children():
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue