Skip to content

ThreeDScene PolarPlane units are not aligned with actual drawing units #4241

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
edowson opened this issue May 8, 2025 · 4 comments
Open

Comments

@edowson
Copy link

edowson commented May 8, 2025

Description of bug / unexpected behavior

I created a ThreeDScene and added a PolarPlane.

I notice that the PolarPlane units are not aligned with actual drawing units in the render.
If I try to draw a circle with radius 2.0, on the PolarPlane, the circle is drawn with a radius of 4.

The units for the axes for the ThreeDScene and not aligned with the units of the axes for the PolarPlane.

Expected behavior

I expect both the ThreeDScene and PolarPlane axes units to be identical.

How to reproduce the issue

Code for reproducing the problem
from manim import *
from manim.opengl import *

class PolarPlane3D(ThreeDScene):
    def construct(self):
        axes = ThreeDAxes(
            x_range=[-10, 10, 2],   
            y_range=[-10, 10, 2],
            z_range=[ -6,  6, 2],
            x_length=10,
            y_length=10,
            z_length=10,
            axis_config={
                "stroke_color": WHITE,
                "stroke_width": 2,
                "include_ticks": False,
                "include_tip": False,
                "line_to_number_buff": SMALL_BUFF,
                "label_direction": DR,
            },
            make_smooth_after_applying_functions=True
        )

        axes_labels = axes.get_axis_labels(
            Tex("$x$").scale(0.9).set_color(RED),
            Tex("$y$").scale(0.9).set_color(GREEN).rotate(30),
            Tex("$z$").scale(0.9).set_color(BLUE))

        polar_plane = PolarPlane(
            radius_max=10.0,
            radius_step=1,
            azimuth_step=16,
            azimuth_units="degrees",
            azimuth_label_font_size=16,
            radius_config={"font_size": 16},
            faded_line_ratio=4,
            size=10,
        ).add_coordinates()

        circle=Circle(radius=2.0, color=RED)

        self.set_camera_orientation(phi=75 * DEGREES, theta=30 * DEGREES)
        self.add(axes, axes_labels, polar_plane, circle)
        self.interactive_embed()

Image

System specifications

System Details
  • OS: Ubuntu-24.04
  • RAM: 128GB
  • Python version: 3.12
  • Installed modules (provide output from pip list):
Package                 Version
----------------------- -----------
anyio                   4.9.0
asttokens               3.0.0
av                      13.1.0
backports.tarfile       1.2.0
beautifulsoup4          4.13.4
Brotli                  1.1.0
build                   1.2.2.post1
CacheControl            0.14.3
certifi                 2025.4.26
cffi                    1.17.1
charset-normalizer      3.4.2
cleo                    2.1.0
click                   8.1.8
cloup                   3.0.7
colorama                0.4.6
crashtest               0.4.1
cryptography            44.0.3
decorator               5.2.1
distlib                 0.3.9
dulwich                 0.22.8
exceptiongroup          1.2.2
executing               2.2.0
fastjsonschema          2.21.1
filelock                3.18.0
findiff                 0.12.1
findpython              0.6.3
glcontext               3.0.0
gmpy2                   2.2.1
h11                     0.16.0
h2                      4.2.0
hpack                   4.1.0
httpcore                1.0.9
httpx                   0.28.1
hyperframe              6.1.0
idna                    3.10
importlib_metadata      8.6.1
importlib_resources     6.5.2
installer               0.7.0
ipython                 9.2.0
ipython_pygments_lexers 1.1.1
isosurfaces             0.1.2
jaraco.classes          3.4.0
jaraco.context          6.0.1
jaraco.functools        4.1.0
jedi                    0.19.2
jeepney                 0.9.0
keyring                 25.6.0
manim                   0.19.0
ManimPango              0.6.0
mapbox_earcut           1.0.3
markdown-it-py          3.0.0
matplotlib-inline       0.1.7
mdurl                   0.1.2
moderngl                5.11.1
moderngl-window         3.1.1
more-itertools          10.7.0
mpmath                  1.3.0
msgpack                 1.1.0
networkx                3.4.2
numpy                   2.2.5
packaging               25.0
parso                   0.8.4
pbs-installer           2025.4.9
pexpect                 4.9.0
pickleshare             0.7.5
pillow                  11.1.0
pip                     25.1.1
pkginfo                 1.12.1.2
platformdirs            4.3.7
poetry                  2.1.2
poetry-core             2.1.2
prompt_toolkit          3.0.51
ptyprocess              0.7.0
pure_eval               0.2.3
pycairo                 1.28.0
pycparser               2.22
pydub                   0.25.1
pyglet                  2.1.6
pyglm                   2.8.2
Pygments                2.19.1
pyproject_hooks         1.2.0
PySocks                 1.7.1
PyYAML                  6.0.2
RapidFuzz               3.13.0
requests                2.32.3
requests-toolbelt       1.0.0
rich                    14.0.0
scipy                   1.15.2
screeninfo              0.8.1
SecretStorage           3.3.3
setuptools              80.1.0
shellingham             1.5.4
skia-pathops            0.8.0.post2
sniffio                 1.3.1
soupsieve               2.5
srt                     3.5.3
stack_data              0.6.3
svgelements             1.9.6
sympy                   1.14.0
tomli                   2.2.1
tomlkit                 0.13.2
tqdm                    4.67.1
traitlets               5.14.3
trove-classifiers       2025.5.1.12
typing_extensions       4.13.2
urllib3                 2.4.0
virtualenv              20.30.0
watchdog                6.0.0
wcwidth                 0.2.13
wheel                   0.45.1
zipp                    3.21.0
zstandard               0.23.0
LaTeX details
  • LaTeX distribution (e.g. TeX Live 2020): texlive-full
@edowson
Copy link
Author

edowson commented May 8, 2025

If I remove the size attribute from the PolarPlane, the axes align correctly.

        polar_plane = PolarPlane(
            radius_max=10.0,
            radius_step=1,
            azimuth_step=16,
            azimuth_units="degrees",
            azimuth_label_font_size=16,
            radius_config={"font_size": 16},
            faded_line_ratio=4,
            #size=10,
        ).add_coordinates()

Image

Q01: If I did have to specify the size attribute, what do I have to keep in mind when specifying a value for PolarPlane size to ensure alignment of the axes for ThreeDScene?

@uwezi
Copy link
Contributor

uwezi commented May 8, 2025

This is true for every coordinate system both in 2D and 3D. The coordinate system objects work as coordinate transformations between a local system inside the object and the global scene coordinates. You have always to choose the correct scaling to make the axes match - but normally you would not care to much to have your coordinate system fit to the (fixed) scene coordinates. That's just the great thing about the coordinate systems, that you can have as many as you wish... here in 2D:

Image

The size= attribute of your polar plane gives you the desired size, e.g. the diameter. So if your radial units range is 0-10 then the diameter for a 1:1 ratio should be 20. This is also similar to a hidden problem with your ThreeDAxes objects where the x_lenght (etc) parameter tells Manim how long in scene units you want your x-axis to be with its values ranging from -10 to +10, so also here you have a scaling 2:1 as compared to the scene units.

Image

So the way to go is to define your coordinate systems with whichever coordinate ranges you want, and then don't mix these with any placement of objects in scene coordinates, but rather always use the coordinate systems' coordinate translation functions, .coords_to_point() or .c2p() for cartesian systems and .polar_to_point() for polar coordinates.

https://docs.manim.community/en/stable/reference/manim.mobject.graphing.coordinate_systems.CoordinateSystem.html#manim.mobject.graphing.coordinate_systems.CoordinateSystem.polar_to_point

https://docs.manim.community/en/stable/reference/manim.mobject.graphing.coordinate_systems.Axes.html#manim.mobject.graphing.coordinate_systems.Axes.coords_to_point

@uwezi
Copy link
Contributor

uwezi commented May 8, 2025

This second version of the example also contains a polar plane:
https://gist.github.com/uwezi/37fff0e51eb9e7e50f0b1474845a78e3#file-20230627_coords-py

Image

@uwezi
Copy link
Contributor

uwezi commented May 8, 2025

So what should you do if you have an arbitrarily sized polar plane and want to draw a circle with a given in-plane radius?

unitradius = np.linalg.norm(pplane.pr2pt(1,0)-pplane.pr2pt(0,0))
circle = Circle(radius=3*unitradius, arc_center=pplane.pr2pt(0,0))
  • The first line gives you the actual distance between the point one unit along the x-axis and the Origin of the polar plane (which does not need to be at the origin of the scene).
  • The second line declares a circle object with a radius of 3 units on the polar plane and its center at the origin of the polar plane.

Image

class pplaneCirc(Scene):
    def construct(self):
        pplane = PolarPlane(
            radius_max=10,
            size=7,
            radius_step=2,
            azimuth_step=8
        ).add_coordinates().rotate(PI/8).shift([2,0,0])

        self.add(pplane)

        unitradius = np.linalg.norm(pplane.pr2pt(1,0)-pplane.pr2pt(0,0))
        circle = Circle(radius=3*unitradius, arc_center=pplane.pr2pt(0,0))

        self.add(circle)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: 🆕 New
Development

No branches or pull requests

2 participants