summaryrefslogtreecommitdiff
path: root/lib/extensions/break_apart.py
blob: 625ace55adc5e3bdef79d42eeb36a08679ad2466 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
from copy import deepcopy

from shapely.geometry import Polygon

import inkex

from ..elements import AutoFill, Fill
from ..i18n import _
from ..svg import get_correction_transform
from .base import InkstitchExtension


class BreakApart(InkstitchExtension):
    def effect(self):  # noqa: C901
        if not self.get_elements():
            return

        if not self.selected:
            inkex.errormsg(_("Please select one or more fill areas to break apart."))
            return

        for element in self.elements:
            if not isinstance(element, AutoFill) and not isinstance(element, Fill):
                continue
            if len(element.paths) <= 1:
                continue

            polygons = []
            multipolygons = []
            holes = []

            for path in element.paths:
                polygons.append(Polygon(path))

            # sort paths by size and convert to polygons
            polygons.sort(key=lambda polygon: polygon.area, reverse=True)

            for shape in polygons:
                if shape in holes:
                    continue
                polygon_list = [shape]

                for other in polygons:
                    if shape != other and shape.contains(other) and other not in holes:
                        # check if "other" is inside a hole, before we add it to the list
                        if any(p.contains(other) for p in polygon_list[1:]):
                            continue
                        polygon_list.append(other)
                        holes.append(other)
                multipolygons.append(polygon_list)
            self.element_to_nodes(multipolygons, element)

    def element_to_nodes(self, multipolygons, element):
        for polygons in multipolygons:
            el = deepcopy(element)
            d = ""
            for polygon in polygons:
                # copy element and replace path
                el.node.set('id', self.uniqueId(element.node.get('id') + "_"))
                d += "M"
                for x, y in polygon.exterior.coords:
                    d += "%s,%s " % (x, y)
                    d += " "
                d += "Z"
            el.node.set('d', d)
            el.node.set('transform', get_correction_transform(element.node))
            element.node.getparent().insert(0, el.node)
        element.node.getparent().remove(element.node)