ManimCommunity / ManimCommunity/manim

Unexpected scaling behavior (especially complicated VGroup object)

Open
#4,836 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
40.9k
Forks
3.1k
Avg merge
3d 12h
Merged PRs (30d)
25

Description

## Description of bug / unexpected behavior
When using VGroup.scale(), some unexpected behavior emerges. The stroke width gets funny.
I know there's a "scale_stroke" parameter which does the trick, but the result is quite undesired when it comes to SVGMobject and it's derivatives (e.g. Text, MathTex, Tex...)
I'll provide a detailed example below.

## Example
Recently, I drew an Arduino UNO using manim. It looks like this:

Image

However, when I wanted to shrink it... I wrote:

```py
from manim import *
class ArduinoUNO(Scene):
def construct(self):
#Code to construct the whole thing
board.scale(0.3)
self.add(board)
```

Image

So, the stoke width looks horrible.
Later, I learned that setting **scale_stroke=True** does the trick. So...

```py
from manim import *
class ArduinoUNO(Scene):
def construct(self):
#Code to construct the whole thing
board.scale(0.3,scale_stroke=True)
self.add(board)
```

Yes, almost everyting's okay... except **Text, MathTex and Tex**.
The texts looked as if they were set **bold**.

Image

Conclusion:
- scale(): texts are okay, others are not
- scale(scale_stroke): texts are not okay, others are
- so I need a function that scales everything correctly.

## Repairing
So, after a bit of work I managed to solve the issue. I created a new function, and I merged it into VGroup.

```py
class MixGroup:
def proportional_scale(self,factor,**kwargs):
self.scale(factor)
for mob in self.get_family():
if not (isinstance(mob,SVGMobject) or isinstance(mob,VDict) or isinstance(mob,VGroup)):
w = mob.get_stroke_width()
if w > 0:
mob.set_stroke(width=abs(factor) * w)
mob.set_stroke(
width=abs(factor) * mob.get_stroke_width(background=True),
background=True,
)

return self

class VGroup(MixGroup,VGroup): pass
```

```py
from manim import *
class ArduinoUNO(Scene):
def construct(self):
#Code to construct the whole thing
board.proportional_scale(scale_stroke=True)
self.add(board)

```

Explanation: this newly created `proportional_scale` works by treating `SVGMobject` and other objects differently. It first scales everything, and then it fixes the stroke width of non-SVGMobjects.

So far, everything behaves as expected.

Image

## System specifications

System Details

- OS: Zorin OS 17 (Linux lenovo-xiaoxinair-14iml-2019-linux 6.8.0-90-generic #91~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Nov 20 15:20:45 UTC 2 x86_64 x86_64 x86_64 GNU/Linux)
- RAM: 12 GB
- Python version (`python/py/python3 --version`): Python 3.10.12
- Installed modules (provide output from `pip list`):
```
Package Version
----------------------- ----------------------
aiohappyeyeballs 2.6.1
aiohttp 3.13.3
aioquic 1.2.0
aiosignal 1.4.0
apturl 0.5.2
asgiref 3.8.1
async-timeout 5.0.1
attrs 25.3.0
av 13.1.0
Babel 2.8.0
bcrypt 3.2.0
beautifulsoup4 4.14.2
blinker 1.9.0
Brlapi 0.8.3
Brotli 1.1.0
bsddb3 6.2.9
certifi 2026.1.4
cffi 1.17.1
chardet 4.0.0
charset-normalizer 3.4.4
click 8.1.8
cloup 3.0.8
colorama 0.4.4
command-not-found 0.3
cryptography 44.0.3
cupshelpers 1.0
dbus-python 1.2.18
decorator 5.2.1
defer 1.0.6
distro 1.7.0
distro-info 1.1+ubuntu0.2
dnspython 2.1.0
duplicity 0.8.21
edge-tts 7.2.7
evdev 1.4.0
fasteners 0.14.1
Flask 3.1.0
fleep 1.0.1
folder-color 0.2.0
frozenlist 1.8.0
fusepy 3.0.1
future 0.18.2
glcontext 3.0.0
h11 0.14.0
h2 4.1.0
hpack 4.1.0
httplib2 0.20.2
hyperframe 6.0.1
icoextract 0.1.2
idna 3.3
ifaddr 0.2.0
importlib-metadata 4.6.4
isosurfaces 0.1.2
itsdangerous 2.2.0
jeepney 0.7.1
Jinja2 3.1.6
kaitaistruct 0.10
keyring 23.5.0
language-selector 0.1
launchpadlib 1.10.16
lazr.restfulclient 0.14.4
lazr.uri 1.0.6
ldap3 2.9.1
libarchive-c 5.3
lockfile 0.12.2
louis 3.20.0
macaroonbakery 1.3.1
Mako 1.1.3
manim 0.19.1
ManimPango 0.6.1
mapbox_earcut 1.0.3
markdown-it-py 4.0.0
MarkupSafe 3.0.2
mdurl 0.1.2
mitmproxy 11.0.2
mitmproxy_rs 0.10.7
moderngl 5.12.0
moderngl-window 3.1.1
monotonic 1.6
more-itertools 8.10.0
msgpack 1.1.0
multidict 6.7.0
mutagen 1.47.0
netifaces 0.11.0
networkx 3.4.2
numpy 2.2.6
oauthlib 3.2.0
olefile 0.46
paramiko 2.9.3
passlib 1.7.4
pefile 2021.9.3
pexpect 4.8.0
pillow 12.0.0
pip 22.0.2
pip-autoremove 0.10.0
propcache 0.4.1
protobuf 3.12.4
psutil 5.9.0
ptyprocess 0.7.0
publicsuffix2 2.20191221
pyasn1 0.6.1
pyasn1_modules 0.4.2
PyAudio 0.2.11
pycairo 1.20.1
pycparser 2.22
pycups 2.0.1
pydub 0.25.1
pyelftools 0.27
pygame 2.6.1
pyglet 2.1.11
pyglm 2.8.2
Pygments 2.19.2
PyGObject 3.42.1
pyinotify 0.9.6
PyJWT 2.3.0
pylsqpack 0.3.22
pymacaroons 0.13.0
PyNaCl 1.5.0
pynput 1.8.1
pyOpenSSL 24.3.0
pyparsing 2.4.7
pyperclip 1.9.0
pyRFC3339 1.1
python-apt 2.4.0-ubuntu4.1-zorin1
python-dateutil 2.8.1
python-debian 0.1.43+ubuntu1.1
python-dotenv 0.21.1
python-slugify 8.0.4
python-xlib 0.33
pytz 2022.1
pyxdg 0.27
PyYAML 5.4.1
reportlab 3.6.8
requests 2.32.5
requests-toolbelt 0.9.1
rich 14.1.0
ruamel.yaml 0.18.6
ruamel.yaml.clib 0.2.12
scipy 1.15.3
screen-resolution-extra 0.0.0
screeninfo 0.8.1
SecretStorage 3.3.1
service-identity 24.2.0
setuptools 59.6.0
simplejson 3.17.6
six 1.16.0
skia-pathops 0.8.0.post2
sortedcontainers 2.4.0
soupsieve 2.8
sox 1.5.0
srt 3.5.3
svgelements 1.9.6
tabulate 0.9.0
text-unidecode 1.3
tornado 6.4.2
tqdm 4.67.1
typing_extensions 4.15.0
ubuntu-drivers-common 0.0.0
ufw 0.36.1
unattended-upgrades 0.1
urllib3 1.26.5
urwid 2.6.16
vboxapi 1.0
wadllib 1.3.6
watchdog 6.0.0
wcwidth 0.2.13
Werkzeug 3.1.3
wheel 0.37.1
wsproto 1.2.0
xdg 5
xkit 0.0.0
yarl 1.22.0
zeroconf 0.147.2
zipp 1.0.0
zorin-appearance 5.3
zorin-connect 1.2
zorin-exec-guard 1.5
zstandard 0.23.0
```

LaTeX details

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading VGroup.scale(), the scale_stroke option, and the scaling behavior of SVGMobject, Text, MathTex, and Tex. Reproduce the supplied Arduino UNO examples and compare ordinary scaling with scale_stroke; done means one scaling operation preserves appropriate stroke widths for both drawn objects and text.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
computer-graphics
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.