Search code examples
pythonmanim

Manim add labels near vertices


I have this example with manim package, I need to add labels near vertices (above, below, right or left of vertices ) the list of labels is :[A,B,C,D,E,F] for vertices [1,2,3,4,5,6]

from manim import 
import math

class MovingVertices(Scene):
def construct(self):
vertices = [1, 2, 3, 4 , 5 , 6]
edges = [(1, 2), (2, 3), (3, 4), (4,1) , (1,5) , (5,2) , (2,6) , (6,3) ]
lt = {1: [0, 0, 0], 2: [2, 0, 0], 3: [2, 2, 0], 4: [0, 2, 0] , 5: [1, math.sqrt(3), 0] , 6: [2+math.sqrt(3), 1, 0]}
g = Graph(vertices, edges, layout=lt)
g.shift(DOWN ,LEFT)
self.play(Create(g),run_time=5)
self.wait()

Solution

  • You can create a dict whose keys are the node numbers and the values the node names, for example like this:

            vertices = [1, 2, 3, 4 , 5 , 6]
            labels = "ABCDEF"
            label_dict = {i: label for i, label in zip(vertices, labels)}
    

    and you can pass that dictionary to the Graph() as parameter labels. For example:

            g = Graph(vertices, edges, labels=label_dict, layout=lt)
    

    This causes each node to be a filled circle with the label inside:

    Result

    Alternatively, you can create the graph without labels, and add them later via a loop, like in the following example:

    class Test(Scene):
        def construct(self):
            vertices = [1, 2, 3, 4 , 5 , 6]
            labels = "ABCDEF"
            label_dict = {i: label for i, label in zip(vertices, labels)}
            edges = [(1, 2), (2, 3), (3, 4), (4,1) , (1,5) , (5,2) , (2,6) , (6,3) ]
            lt = {1: [0, 0, 0], 2: [2, 0, 0], 3: [2, 2, 0], 4: [0, 2, 0] , 5: [1, math.sqrt(3), 0] , 6: [2+math.sqrt(3), 1, 0]}
            g = Graph(vertices, edges, layout=lt)
            g.shift(DOWN ,LEFT)
            self.play(Create(g),run_time=5)
            tex_labels = []
            for v in g.vertices:
                label = MathTex(label_dict[v]).scale(0.5).next_to(g.vertices[v], UR)
                tex_labels.append(label)
            self.play(Create(VGroup(*tex_labels)))
            self.wait()
    

    I use the same dict to retrieve the label assigned to each node, and iterate through g.vertices. Note how g.vertices[v] is the object shown in the scene (the little dot), which is used to position the label.

    The resulting animation is:

    Animation

    Finally, if you want to have finer control on the positions of the labels, you can define a dictionary which specifies not only the text of the label, but also its relative position with respect to the graph node. For example:

            vertices = [1, 2, 3, 4 , 5 , 6]
            label_dict = {
                1: ("A", DOWN),
                2: ("B", DOWN),
                3: ("C", UP),
                4: ("D", UP),
                5: ("E", RIGHT),
                6: ("F", RIGHT),
            }
    

    And later use it in the loop which writes the labels like this:

            tex_labels = []
            for v in g.vertices:
                label = (MathTex(label_dict[v][0])
                         .scale(0.5)
                         .next_to(g.vertices[v], label_dict[v][1])
                )
                tex_labels.append(label)
            self.play(Create(VGroup(*tex_labels)))
    

    The result is in this case:

    Result