ManimCommunity / ManimCommunity/manim
Unexpected scaling behavior (especially complicated VGroup object)
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:
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)
```
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**.
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.
## 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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