From b06559053e276fc31c85a1254d1366bb1af3f516 Mon Sep 17 00:00:00 2001 From: Irvanal Haq Date: Wed, 30 Apr 2025 02:44:59 +0700 Subject: [PATCH 1/4] fix scale when scale_stroke is true --- manim/mobject/types/vectorized_mobject.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/manim/mobject/types/vectorized_mobject.py b/manim/mobject/types/vectorized_mobject.py index 321fe4287b..1a9ea72334 100644 --- a/manim/mobject/types/vectorized_mobject.py +++ b/manim/mobject/types/vectorized_mobject.py @@ -522,11 +522,12 @@ def construct(self): """ if scale_stroke: - self.set_stroke(width=abs(scale_factor) * self.get_stroke_width()) - self.set_stroke( - width=abs(scale_factor) * self.get_stroke_width(background=True), - background=True, - ) + for mob in self.family_members_with_points(): + mob.set_stroke(width=abs(scale_factor) * mob.get_stroke_width()) + mob.set_stroke( + width=abs(scale_factor) * mob.get_stroke_width(background=True), + background=True, + ) super().scale(scale_factor, **kwargs) return self From eb5d28d2c33f6b4e72853934e91999b296998689 Mon Sep 17 00:00:00 2001 From: Irvanal Haq Date: Wed, 30 Apr 2025 02:47:57 +0700 Subject: [PATCH 2/4] add test for scale stroke true --- .../types/vectorized_mobject/test_stroke.py | 55 ++++++++++++------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/tests/module/mobject/types/vectorized_mobject/test_stroke.py b/tests/module/mobject/types/vectorized_mobject/test_stroke.py index 25c09cd294..9d715e190b 100644 --- a/tests/module/mobject/types/vectorized_mobject/test_stroke.py +++ b/tests/module/mobject/types/vectorized_mobject/test_stroke.py @@ -1,7 +1,9 @@ from __future__ import annotations +import numpy as np + import manim.utils.color as C -from manim import VMobject +from manim import Square, VGroup, VMobject from manim.mobject.vector_field import StreamLines @@ -41,23 +43,34 @@ def test_streamline_attributes_for_single_color(): assert vector_field[0].stroke_opacity == 0.2 -def test_stroke_scale(): - a = VMobject() - b = VMobject() - a.set_stroke(width=50) - b.set_stroke(width=50) - a.scale(0.5) - b.scale(0.5, scale_stroke=True) - assert a.get_stroke_width() == 50 - assert b.get_stroke_width() == 25 - - -def test_background_stroke_scale(): - a = VMobject() - b = VMobject() - a.set_stroke(width=50, background=True) - b.set_stroke(width=50, background=True) - a.scale(0.5) - b.scale(0.5, scale_stroke=True) - assert a.get_stroke_width(background=True) == 50 - assert b.get_stroke_width(background=True) == 25 +def test_scale_with_scale_stroke_true_and_false(): + square = Square() + square.set_stroke(width=40) + square.set_stroke(width=60, background=True) + original_height = square.get_height() + original_stroke = square.get_stroke_width() + original_background = square.get_stroke_width(background=True) + + vg = VGroup(square) + + # Scale 1.0 (scale_stroke=True): No changes expected + vg.scale(1.0, scale_stroke=True) + assert np.isclose(square.get_height(), original_height) + assert square.get_stroke_width() == original_stroke + assert square.get_stroke_width(background=True) == original_background + + # Scale 0.5 (scale_stroke=True): Size and stroke width halved + vg.scale(0.5, scale_stroke=True) + assert np.isclose(square.get_height(), original_height * 0.5) + assert np.isclose(square.get_stroke_width(), original_stroke * 0.5) + assert np.isclose( + square.get_stroke_width(background=True), original_background * 0.5 + ) + + # Scale 2.0 (scale_stroke=False): Size doubled, stroke width unchanged + vg.scale(2.0, scale_stroke=False) + assert np.isclose(square.get_height(), original_height) + assert np.isclose(square.get_stroke_width(), original_stroke * 0.5) + assert np.isclose( + square.get_stroke_width(background=True), original_background * 0.5 + ) From 7e69b7346af1c0a15df792a4e853d61cb9a2af9d Mon Sep 17 00:00:00 2001 From: Irvanal Haq Date: Wed, 30 Apr 2025 03:30:25 +0700 Subject: [PATCH 3/4] change test value to number --- .../types/vectorized_mobject/test_stroke.py | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/tests/module/mobject/types/vectorized_mobject/test_stroke.py b/tests/module/mobject/types/vectorized_mobject/test_stroke.py index 9d715e190b..27176f57b2 100644 --- a/tests/module/mobject/types/vectorized_mobject/test_stroke.py +++ b/tests/module/mobject/types/vectorized_mobject/test_stroke.py @@ -47,30 +47,23 @@ def test_scale_with_scale_stroke_true_and_false(): square = Square() square.set_stroke(width=40) square.set_stroke(width=60, background=True) - original_height = square.get_height() - original_stroke = square.get_stroke_width() - original_background = square.get_stroke_width(background=True) vg = VGroup(square) # Scale 1.0 (scale_stroke=True): No changes expected vg.scale(1.0, scale_stroke=True) - assert np.isclose(square.get_height(), original_height) - assert square.get_stroke_width() == original_stroke - assert square.get_stroke_width(background=True) == original_background + assert np.isclose(square.side_length, 2) + assert square.get_stroke_width() == 40 + assert square.get_stroke_width(background=True) == 60 # Scale 0.5 (scale_stroke=True): Size and stroke width halved vg.scale(0.5, scale_stroke=True) - assert np.isclose(square.get_height(), original_height * 0.5) - assert np.isclose(square.get_stroke_width(), original_stroke * 0.5) - assert np.isclose( - square.get_stroke_width(background=True), original_background * 0.5 - ) + assert np.isclose(square.side_length, 1) + assert np.isclose(square.get_stroke_width(), 20) + assert np.isclose(square.get_stroke_width(background=True), 30) # Scale 2.0 (scale_stroke=False): Size doubled, stroke width unchanged vg.scale(2.0, scale_stroke=False) - assert np.isclose(square.get_height(), original_height) - assert np.isclose(square.get_stroke_width(), original_stroke * 0.5) - assert np.isclose( - square.get_stroke_width(background=True), original_background * 0.5 - ) + assert np.isclose(square.get_height(), 2) + assert np.isclose(square.get_stroke_width(), 20) + assert np.isclose(square.get_stroke_width(background=True), 30) From 41922188614acc8091182758268c25b7f7cd9106 Mon Sep 17 00:00:00 2001 From: Irvanal Haq Date: Wed, 30 Apr 2025 20:03:47 +0700 Subject: [PATCH 4/4] fix unintended recursive .set_stroke() --- manim/mobject/types/vectorized_mobject.py | 6 ++- .../types/vectorized_mobject/test_stroke.py | 50 +++++++++++-------- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/manim/mobject/types/vectorized_mobject.py b/manim/mobject/types/vectorized_mobject.py index 1a9ea72334..7a0e5e152e 100644 --- a/manim/mobject/types/vectorized_mobject.py +++ b/manim/mobject/types/vectorized_mobject.py @@ -523,10 +523,14 @@ def construct(self): """ if scale_stroke: for mob in self.family_members_with_points(): - mob.set_stroke(width=abs(scale_factor) * mob.get_stroke_width()) + mob.set_stroke( + width=abs(scale_factor) * mob.get_stroke_width(), + family=False, + ) mob.set_stroke( width=abs(scale_factor) * mob.get_stroke_width(background=True), background=True, + family=False, ) super().scale(scale_factor, **kwargs) return self diff --git a/tests/module/mobject/types/vectorized_mobject/test_stroke.py b/tests/module/mobject/types/vectorized_mobject/test_stroke.py index 27176f57b2..2dc815c0f3 100644 --- a/tests/module/mobject/types/vectorized_mobject/test_stroke.py +++ b/tests/module/mobject/types/vectorized_mobject/test_stroke.py @@ -1,9 +1,7 @@ from __future__ import annotations -import numpy as np - import manim.utils.color as C -from manim import Square, VGroup, VMobject +from manim import Rectangle, Square, VGroup, VMobject from manim.mobject.vector_field import StreamLines @@ -44,26 +42,38 @@ def test_streamline_attributes_for_single_color(): def test_scale_with_scale_stroke_true_and_false(): - square = Square() - square.set_stroke(width=40) - square.set_stroke(width=60, background=True) - - vg = VGroup(square) + sq = Square() + sq.set_stroke(width=40) + sq.set_stroke(width=120, background=True) + rec = Rectangle(height=4, width=5) + rec.set_stroke(width=10) + rec.set_stroke(width=20, background=True) + vg = VGroup(sq) + rec.add(vg) # Scale 1.0 (scale_stroke=True): No changes expected - vg.scale(1.0, scale_stroke=True) - assert np.isclose(square.side_length, 2) - assert square.get_stroke_width() == 40 - assert square.get_stroke_width(background=True) == 60 + rec.scale(1.0, scale_stroke=True) + assert sq.side_length == 2 + assert rec.height == 4 + assert sq.get_stroke_width() == 40 + assert sq.get_stroke_width(background=True) == 120 + assert rec.get_stroke_width() == 10 + assert rec.get_stroke_width(background=True) == 20 # Scale 0.5 (scale_stroke=True): Size and stroke width halved - vg.scale(0.5, scale_stroke=True) - assert np.isclose(square.side_length, 1) - assert np.isclose(square.get_stroke_width(), 20) - assert np.isclose(square.get_stroke_width(background=True), 30) + rec.scale(0.5, scale_stroke=True) + assert sq.side_length == 1 + assert rec.height == 2 + assert sq.get_stroke_width() == 20 + assert sq.get_stroke_width(background=True) == 60 + assert rec.get_stroke_width() == 5 + assert rec.get_stroke_width(background=True) == 10 # Scale 2.0 (scale_stroke=False): Size doubled, stroke width unchanged - vg.scale(2.0, scale_stroke=False) - assert np.isclose(square.get_height(), 2) - assert np.isclose(square.get_stroke_width(), 20) - assert np.isclose(square.get_stroke_width(background=True), 30) + rec.scale(2.0, scale_stroke=False) + assert sq.side_length == 2 + assert rec.height == 4 + assert sq.get_stroke_width() == 20 + assert sq.get_stroke_width(background=True) == 60 + assert rec.get_stroke_width() == 5 + assert rec.get_stroke_width(background=True) == 10