manim
manim copied to clipboard
get_axis_labels() not working properly for rotated axis
Description of bug / unexpected behavior
get_axis_labels() is the function needed to add labels to the axes. It is not working properly when I rotated the axis. This problem is especially prominent for:
- Rotations not integer multiple of PI/2
- Axis that has only positive direction
Expected behavior
The labels should be near the tips of each axis.
How to reproduce the issue
Case 1
class GetAxisLabelsExample(Scene):
def construct(self):
ax = Axes(x_length=4, y_length=4).rotate(0.5*PI/2)
labels = ax.get_axis_labels(Tex("x"), Text("y"))
self.add(ax, labels)
Case 2
class GetAxisLabelsExample(Scene):
def construct(self):
ax = Axes(x_length=4, y_length=4, x_range=[0, 12]).rotate(2*PI/2)
labels = ax.get_axis_labels(Tex("x"), Text("y"))
self.add(ax, labels)
Additional media files
Case 1
Case 2
I solved case 2 using get_x_axis_label() and get_y_axis_label():
class GetAxisLabelsExample(Scene):
def construct(self):
ax = Axes(x_length=4, y_length=4, x_range=[0, 12]).rotate(2*PI/2)
labels = [ax.get_x_axis_label(Tex("x"), edge=UL, direction=UL), ax.get_y_axis_label(Tex("y"))]
self.add(ax, *labels)
But this whole process needs a huge refinement. I should be able to set the labels using Axes.label(x_label = 'x', y_label = 'y').
The issue is that the method get_axis_labels assumes that the Axes are not rotated.
By default the label on the x-axis is put on the top right corner of the bounding box of the axis, the label is shifted in the UP + RIGHT = UR direction. This can be found on line 259 in coordinate_systems.py
def get_x_axis_label(
self,
label: float | str | Mobject,
edge: Sequence[float] = UR,
direction: Sequence[float] = UR,
buff: float = SMALL_BUFF,
**kwargs,
) -> Mobject:
Similarly the label on the y-axis is put on the upper right corner of the bounding box, but now shifted more to the right than upwards.
This is found line 302 in coordinate_systems.py
def get_y_axis_label(
self,
label: float | str | Mobject,
edge: Sequence[float] = UR,
direction: Sequence[float] = UP * 0.5 + RIGHT,
buff: float = SMALL_BUFF,
**kwargs,
) -> Mobject:
If you want more control over the placement of the axis labels you have to call these methods directly.
Please see this example below:
from manim import *
class GetAxisLabelsExample(Scene):
def construct(self):
ax1 = Axes(x_length=2, y_length=2, x_range=[0, 12]).move_to(3*LEFT + 2*UP)
labels1 = ax1.get_axis_labels(x_label=Tex("x"), y_label=Tex("y"))
self.add(ax1, labels1)
ax2 = Axes(x_length=2, y_length=2, x_range=[0, 12]).rotate(PI/2).move_to(2*UP)
labels2 = ax2.get_axis_labels(x_label=Tex("x"), y_label=Tex("y"))
self.add(ax2, labels2)
ax3 = Axes(x_length=2, y_length=2, x_range=[0, 12]).rotate(2*PI/2).move_to(3*RIGHT + 2*UP)
labels3 = ax3.get_axis_labels(x_label=Tex("x"),
y_label=Tex("y"))
self.add(ax3, labels3)
ax4 = Axes(x_length=2, y_length=2, x_range=[0, 12]).move_to(3*LEFT + 2*DOWN)
labels4x = ax4.get_x_axis_label(Tex("x"))
labels4y = ax4.get_y_axis_label(Tex("y"))
self.add(ax4, labels4x, labels4y)
ax5 = Axes(x_length=2, y_length=2, x_range=[0, 12]).rotate(PI/2).move_to(2*DOWN)
labels5x = ax5.get_x_axis_label(Tex("x"))
labels5y = ax5.get_y_axis_label(Tex("y"), edge=LEFT+UP)
self.add(ax5, labels5x, labels5y)
ax6 = Axes(x_length=2, y_length=2, x_range=[0, 12]).rotate(2*PI/2).move_to(3*RIGHT + 2*DOWN)
labels6x = ax6.get_x_axis_label(Tex("x"), edge=LEFT + UP)
labels6y = ax6.get_y_axis_label(Tex("y"), edge=RIGHT + DOWN)
self.add(ax6, labels6x, labels6y)
Which renders as