Skip to content
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

Select SVG shapes by id #3941

Open
tobiasBora opened this issue Sep 30, 2024 · 4 comments
Open

Select SVG shapes by id #3941

tobiasBora opened this issue Sep 30, 2024 · 4 comments
Labels
new feature Enhancement specifically adding a new feature (feature request should be used for issues instead)

Comments

@tobiasBora
Copy link

Description of proposed feature

In the SVG format, it is possible to add an id attribute on a shape/group of shapes. It would be great to allow manim to get the list of sub-objects corresponding to a given id (for now get_mobjects_from will not be stable if later-on I add elements to my object).

How can the new feature be used?

I could do a complicated drawing in inkscape, and animate it in manim, for instance by hiding/showing/moving elements based on their ID etc.

@tobiasBora tobiasBora added the new feature Enhancement specifically adding a new feature (feature request should be used for issues instead) label Sep 30, 2024
@uwezi
Copy link
Contributor

uwezi commented Oct 1, 2024

you can already now address all separate paths and features from an SVG file by its position in the file - they all get an index in the list of sub-mobjects depending on their ordering in the SVG file. But yes, this is easily confused when you later modify the file.

@tobiasBora
Copy link
Author

Yes exactly. And I guess it is not obvious how to find the good element in a huge list.

@uwezi
Copy link
Contributor

uwezi commented Oct 2, 2024

My approach:

bild

class index(Scene):
    def construct(self):
        for x in range(-7, 8):
            for y in range(-4, 5):
                if (x==0) and (y==0):
                    self.add(Dot(np.array([x, y, 0]),radius=0.03, color=RED))
                else:
                    self.add(Dot(np.array([x, y, 0]),radius=0.03, color=DARK_GREY))

        circuit = SVGMobject(r"bilder/20240924_rinrut_03.svg",
            stroke_color=WHITE, stroke_width=3, fill_color=WHITE,width=10)

        self.add(circuit)
        #self.wait(2)

        bbox = Rectangle(height=circuit.height, width=circuit.width).move_to(circuit.get_center(),ORIGIN)
        bbox.scale(1.4)
        loc = bbox.get_critical_point(UL)
        w = bbox.width
        h = bbox.height
        cf = 2*w + 2*h
        dl = cf / (len(circuit)+3)

        dir   = [dl,0,0]
        edge = 0
        positions = []
        for i in range(len(circuit)):
            positions.append(loc)
            loc = loc + dir
            if (edge == 0) and (loc[0] > bbox.get_critical_point(UP+RIGHT)[0]):
                edge = 1
                loc = loc - dir
                dir = [0,-dl,0]
                loc = loc + dir

            if (edge == 1) and (loc[1] < bbox.get_critical_point(DOWN+RIGHT)[1]):
                edge = 2
                loc = loc - dir
                dir = [-dl,0,0]
                loc = loc + dir

            if (edge == 2) and (loc[0] < bbox.get_critical_point(DOWN+LEFT)[0]):
                edge = 3
                loc = loc - dir
                dir = [0,+dl,0]
                loc = loc + dir

        for i in range(len(circuit)):
            shortest = 1e6
            found = 0
            for j in range(len(positions)):
                dist = np.sqrt((circuit[i].get_center()[0]-positions[j][0])**2 + (circuit[i].get_center()[1]-positions[j][1])**2)
                if dist < shortest:
                    shortest = dist
                    found = j


            color = [BLUE,GREEN,RED,YELLOW,PURPLE][i%5]
            circuit[i].set_color(color)
            txt = Text("{}".format(i)).scale(0.15).move_to(positions[found]).set_color(color)

            line = Line(circuit[i].get_center(),end=txt.get_center(), stroke_width=1).set_color(color)

            self.add(line)
            self.add(txt)
            # self.wait(1)

            positions.pop(found)

@tobiasBora
Copy link
Author

Ahah fun workaround to identify the element on medium-sized picture, thanks. Another advantage of id also is that it would (hopefully) also work for groups, so that I can refer to hundred elements at once using a single name.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new feature Enhancement specifically adding a new feature (feature request should be used for issues instead)
Projects
Status: 🆕 New
Development

No branches or pull requests

2 participants