Skip to content
33 changes: 32 additions & 1 deletion manim/mobject/mobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -2561,10 +2561,23 @@ def arrange(
direction: Vector3DLike = RIGHT,
buff: float = DEFAULT_MOBJECT_TO_MOBJECT_BUFFER,
center: bool = True,
reference: Mobject | None = None,
**kwargs: Any,
) -> Self:
"""Sorts :class:`~.Mobject` next to each other on screen.

Parameters
----------
direction
The direction in which the submobjects should be arranged.
buff
The distance between neighboring submobjects.
center
Whether to center the mobject after arranging.
reference
The submobject to use as the reference for the arrangement. If not
set, the first submobject is used.

Examples
--------

Expand All @@ -2580,8 +2593,26 @@ def construct(self):
x = VGroup(s1, s2, s3, s4).set_x(0).arrange(buff=1.0)
self.add(x)
"""
for m1, m2 in zip(self.submobjects[:-1], self.submobjects[1:], strict=True):
submobjects = list(self.submobjects)

if reference is None:
reference_index = 0
else:
reference_index = submobjects.index(reference)

for m1, m2 in zip(
submobjects[reference_index:],
submobjects[reference_index + 1 :],
):
m2.next_to(m1, direction, buff, **kwargs)

for m1, m2 in zip(
reversed(submobjects[:reference_index]),
reversed(submobjects[1 : reference_index + 1]),
strict=True,
):
m1.next_to(m2, -direction, buff, **kwargs)

if center:
self.center()
return self
Expand Down
16 changes: 16 additions & 0 deletions tests/module/mobject/mobject/test_mobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,3 +243,19 @@ def test_apply_matrix_about_vertex_view():
# The first vertex should remain in the same position (within numerical precision)
transformed_vertices = triangle.get_vertices()
np.testing.assert_allclose(transformed_vertices[0], first_vertex, atol=1e-6)


def test_mobject_arrange_reference():
"""Test Mobject.arrange() can use a submobject as the reference."""
square1 = Square()
square2 = Square()
square3 = Square()

group = VGroup(square1, square2, square3)
original_reference_center = square3.get_center().copy()

group.arrange(reference=square3, center=False)

assert np.allclose(square3.get_center(), original_reference_center)
assert square1.get_x() < square2.get_x()
assert square2.get_x() < square3.get_x()
Loading