svgmapviewer-tools-floors 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/LICENSE +15 -0
  2. package/inkscape/extensions/Attic/fix_guides.inx +17 -0
  3. package/inkscape/extensions/Attic/fix_guides.py +30 -0
  4. package/inkscape/extensions/Attic/fix_symbol_links.inx +17 -0
  5. package/inkscape/extensions/Attic/fix_symbol_links.py +71 -0
  6. package/inkscape/extensions/Attic/flatten_style.inx +17 -0
  7. package/inkscape/extensions/Attic/flatten_style.py +31 -0
  8. package/inkscape/extensions/Attic/load_markers.inx +17 -0
  9. package/inkscape/extensions/Attic/load_markers.py +117 -0
  10. package/inkscape/extensions/Attic/load_patterns.inx +17 -0
  11. package/inkscape/extensions/Attic/load_patterns.py +116 -0
  12. package/inkscape/extensions/Attic/load_symbols.inx +17 -0
  13. package/inkscape/extensions/Attic/load_symbols.py +164 -0
  14. package/inkscape/extensions/Attic/renumber_tree.inx +24 -0
  15. package/inkscape/extensions/Attic/renumber_tree.py +39 -0
  16. package/inkscape/extensions/Attic/repeat_path.inx +17 -0
  17. package/inkscape/extensions/Attic/repeat_path.py +58 -0
  18. package/inkscape/extensions/Attic/resolve_facility_links.inx +19 -0
  19. package/inkscape/extensions/Attic/resolve_facility_links.py +16 -0
  20. package/inkscape/extensions/Attic/sort_symbols.inx +17 -0
  21. package/inkscape/extensions/Attic/sort_symbols.py +48 -0
  22. package/inkscape/extensions/Attic/symbol_load.inx +17 -0
  23. package/inkscape/extensions/Attic/symbol_load.py +99 -0
  24. package/inkscape/extensions/Attic/tidy_tree.inx +22 -0
  25. package/inkscape/extensions/Attic/tidy_tree.py +178 -0
  26. package/inkscape/extensions/Attic/use_shop.inx +22 -0
  27. package/inkscape/extensions/Attic/use_shop.py +26 -0
  28. package/inkscape/extensions/README.md +34 -0
  29. package/inkscape/extensions/daijimaps/__init__.py +72 -0
  30. package/inkscape/extensions/daijimaps/address_tree.py +231 -0
  31. package/inkscape/extensions/daijimaps/common.py +49 -0
  32. package/inkscape/extensions/daijimaps/generate_addresses.py +41 -0
  33. package/inkscape/extensions/daijimaps/guards.py +47 -0
  34. package/inkscape/extensions/daijimaps/map_layer.py +47 -0
  35. package/inkscape/extensions/daijimaps/name.py +167 -0
  36. package/inkscape/extensions/daijimaps/renumber.py +38 -0
  37. package/inkscape/extensions/daijimaps/resolve_labels.py +65 -0
  38. package/inkscape/extensions/daijimaps/resolve_names.py +170 -0
  39. package/inkscape/extensions/daijimaps/save_addresses.py +274 -0
  40. package/inkscape/extensions/daijimaps/types.py +128 -0
  41. package/inkscape/extensions/daijimaps/visit_parents.py +37 -0
  42. package/inkscape/extensions/extract_labels.py +79 -0
  43. package/inkscape/extensions/fixup_floor_svg.py +28 -0
  44. package/inkscape/extensions/fixup_texts.inx +15 -0
  45. package/inkscape/extensions/fixup_texts.py +110 -0
  46. package/inkscape/extensions/fixup_tree.inx +15 -0
  47. package/inkscape/extensions/fixup_tree.py +17 -0
  48. package/inkscape/extensions/flatten_transform.inx +17 -0
  49. package/inkscape/extensions/flatten_transform.py +63 -0
  50. package/inkscape/extensions/import_labels.inx +20 -0
  51. package/inkscape/extensions/import_labels.py +52 -0
  52. package/inkscape/extensions/import_shops.inx +20 -0
  53. package/inkscape/extensions/import_shops.py +47 -0
  54. package/inkscape/extensions/install.sh +14 -0
  55. package/inkscape/extensions/load_shops.inx +20 -0
  56. package/inkscape/extensions/load_shops.py +86 -0
  57. package/inkscape/extensions/renumber_group.inx +15 -0
  58. package/inkscape/extensions/renumber_group.py +17 -0
  59. package/inkscape/extensions/resolve_labels.inx +20 -0
  60. package/inkscape/extensions/resolve_labels.py +142 -0
  61. package/inkscape/extensions/resolve_shops.inx +20 -0
  62. package/inkscape/extensions/resolve_shops.py +73 -0
  63. package/inkscape/extensions/unresolve_labels.inx +20 -0
  64. package/inkscape/extensions/unresolve_labels.py +53 -0
  65. package/inkscape/extensions/unresolve_shops.inx +20 -0
  66. package/inkscape/extensions/unresolve_shops.py +56 -0
  67. package/inkscape/templates/floors.svg +665 -0
  68. package/map-extract-floors.js +821 -0
  69. package/package.json +19 -0
  70. package/pyproject.toml +20 -0
  71. package/scripts/inkex-inkscape +14 -0
  72. package/scripts/inkex-python +14 -0
  73. package/scripts/inkex-setup +6 -0
  74. package/scripts/labels.sh +18 -0
  75. package/scripts/regen.py +77 -0
  76. package/scripts/regen.sh +24 -0
package/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2025 Daiji Maps
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
14
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
+ PERFORMANCE OF THIS SOFTWARE.
@@ -0,0 +1,17 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
3
+ <name>Fix Guides</name>
4
+ <id>daijimaps.fix_guides</id>
5
+ <label>Fix guides</label>
6
+ <effect needs-live-preview="false">
7
+ <object-type>all</object-type>
8
+ <effects-menu>
9
+ <submenu name="Daiji Maps">
10
+ <submenu name="Fixup" />
11
+ </submenu>
12
+ </effects-menu>
13
+ </effect>
14
+ <script>
15
+ <command location="inx" interpreter="python">fix_guides.py</command>
16
+ </script>
17
+ </inkscape-extension>
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env python3
2
+ # coding=utf-8
3
+
4
+ import inkex
5
+
6
+
7
+ class FixGuides(inkex.EffectExtension):
8
+ def _show_guide(self, guide):
9
+ self.msg(
10
+ "guide:"
11
+ + f" id={guide.get('id')}"
12
+ + f" position={guide.raw_position}"
13
+ + f" orientation={guide.orientation}"
14
+ )
15
+
16
+ def _do_guide(self, guide):
17
+ # self._show_guide(guide)
18
+ p = guide.raw_position
19
+ h = self.svg.viewbox_height
20
+ x = p[0]
21
+ y = h - p[1]
22
+ guide.set_position(x, y, guide.orientation)
23
+
24
+ def effect(self):
25
+ for guide in self.svg.namedview.get_guides():
26
+ self._do_guide(guide)
27
+
28
+
29
+ if __name__ == "__main__":
30
+ FixGuides().run()
@@ -0,0 +1,17 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
3
+ <name>Fix Symbol Links</name>
4
+ <id>daijimaps.fix_symbol_links</id>
5
+ <label>Fix symbol links (href) under Content/Facilities</label>
6
+ <effect needs-live-preview="false">
7
+ <object-type>all</object-type>
8
+ <effects-menu>
9
+ <submenu name="Daiji Maps">
10
+ <submenu name="Fixup" />
11
+ </submenu>
12
+ </effects-menu>
13
+ </effect>
14
+ <script>
15
+ <command location="inx" interpreter="python">fix_symbol_links.py</command>
16
+ </script>
17
+ </inkscape-extension>
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env python3
2
+ # coding=utf-8
3
+
4
+ import inkex
5
+
6
+ import daijimaps
7
+
8
+
9
+ class FixSymbolLinks(daijimaps.AddressTree):
10
+ # XXX Find Content/Facilities
11
+ # XXX Find Toilets
12
+ # XXX Iterate children
13
+ # XXX Check if child has transform="translate()"
14
+ # XXX Check if child is <use/> or <g>
15
+ # XXX If not correct, regen <use/> with the correct href
16
+
17
+ def _make_use(self, kind, target):
18
+ x = inkex.Use()
19
+ x.label = target.label
20
+ x.attrib["href"] = f"X{kind}"
21
+ x.attrib["transform"] = target.atrib["transform"]
22
+ return x
23
+
24
+ def _is_good_use(self, child, kind):
25
+ if isinstance(child, inkex.Use):
26
+ if "transform" in child.attrib:
27
+ if "href" in child.attrib:
28
+ if child.attrib["href"] == f"X{kind}":
29
+ return True
30
+ return False
31
+
32
+ def _find_group(self, layer, label) -> inkex.Group | None:
33
+ for child in list(layer):
34
+ if not isinstance(child, inkex.Group):
35
+ continue
36
+ if child.label is None or child.label != label:
37
+ continue
38
+ return child
39
+ return None
40
+
41
+ def _process_addresses(self, node):
42
+ content: inkex.Group | None = self._find_group(node, "Content")
43
+ if content is None:
44
+ return False
45
+ facilities: inkex.Group | None = self._find_group(content, "Facilities")
46
+ if facilities is None:
47
+ return False
48
+ for facility in list(facilities):
49
+ if not isinstance(facility, inkex.Group):
50
+ continue
51
+ # e.g. kind == Toilets
52
+ kind = facility.label
53
+ if kind is None:
54
+ continue
55
+ if self.svg.getElementById(f"X{kind}") is None:
56
+ self.msg(f"unknown facility kind: {kind}")
57
+ continue
58
+ for child in list(facility):
59
+ # XXX style => attribute
60
+ if self._is_good_use(child, kind):
61
+ # good - nothing to do
62
+ continue
63
+ # fixup
64
+ self.msg(f"fixup use: {facility}: {kind}")
65
+ x = self._make_use(kind, child)
66
+ facility.remove(child)
67
+ facility.append(x)
68
+
69
+
70
+ if __name__ == "__main__":
71
+ FixSymbolLinks().run()
@@ -0,0 +1,17 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
3
+ <name>Flatten Style</name>
4
+ <id>daijimaps.flatten_style</id>
5
+ <label>Flatteen tree by merging styles into leaves.</label>
6
+ <effect needs-live-preview="false">
7
+ <object-type>all</object-type>
8
+ <effects-menu>
9
+ <submenu name="Daiji Maps">
10
+ <submenu name="Fixup" />
11
+ </submenu>
12
+ </effects-menu>
13
+ </effect>
14
+ <script>
15
+ <command location="inx" interpreter="python">flatten_style.py</command>
16
+ </script>
17
+ </inkscape-extension>
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env python3
2
+ # coding=utf-8
3
+
4
+ import inkex
5
+
6
+
7
+ group_styles = {"display"}
8
+
9
+
10
+ class FlattenStyle(inkex.EffectExtension):
11
+ def _flatten_style(self, node):
12
+ if isinstance(node, inkex.Group):
13
+ ss = {}
14
+ for y in group_styles:
15
+ if y in node.style:
16
+ ss[y] = node.style[y]
17
+ for child in list(node):
18
+ child.style.add_inherited(node.style)
19
+ node.style = ss
20
+ for child in list(node):
21
+ self._flatten_style(child)
22
+ return True
23
+
24
+ def effect(self):
25
+ if self.svg.selection:
26
+ for node in self.svg.selection.values():
27
+ self._flatten_style(node)
28
+
29
+
30
+ if __name__ == "__main__":
31
+ FlattenStyle().run()
@@ -0,0 +1,17 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
3
+ <name>Load Markers</name>
4
+ <id>daijimaps.load_markers</id>
5
+ <label>Load markers under Assets.</label>
6
+ <effect needs-live-preview="false">
7
+ <object-type>all</object-type>
8
+ <effects-menu>
9
+ <submenu name="Daiji Maps">
10
+ <submenu name="Assets" />
11
+ </submenu>
12
+ </effects-menu>
13
+ </effect>
14
+ <script>
15
+ <command location="inx" interpreter="python">load_markers.py</command>
16
+ </script>
17
+ </inkscape-extension>
@@ -0,0 +1,117 @@
1
+ #!/usr/bin/env python3
2
+ # coding=utf-8
3
+
4
+ import copy
5
+ import csv
6
+ import os
7
+ import re
8
+
9
+ import inkex
10
+
11
+
12
+ class LoadMarkers(inkex.EffectExtension):
13
+ # (Assets)/(Markers)
14
+ _assets = None
15
+ _markers = None
16
+ _markers_csv = None
17
+
18
+ def _find_group(self, group):
19
+ assert isinstance(self._markers, inkex.Group)
20
+ for node in list(self._markers):
21
+ if node.label == group:
22
+ return node
23
+ return None
24
+
25
+ def _install_marker(self, v, node):
26
+ g = inkex.Group()
27
+ g.label = v["name"] # 'Triangle'
28
+ g.append(node)
29
+ prev = None
30
+ assert isinstance(self._markers, inkex.Group)
31
+ for node in list(self._markers):
32
+ if node.label == v["name"]:
33
+ prev = node
34
+ if prev is not None:
35
+ self._markers.remove(prev)
36
+ self._markers.append(g)
37
+ node.set("id", v["name"]) # 'Triangle'
38
+ return True
39
+
40
+ def _load_marker(self, v):
41
+ svg_path = self.svg_path()
42
+ assert isinstance(svg_path, str)
43
+ file = os.path.join(svg_path, v["file"])
44
+ f = inkex.load_svg(file)
45
+ r = f.getroot()
46
+ assert isinstance(r, inkex.SvgDocumentElement)
47
+ node = r.getElementById(v["id"])
48
+ return copy.deepcopy(node)
49
+
50
+ def _handle_entry(self, v):
51
+ # name,file,id
52
+ if v["name"] == "":
53
+ return False
54
+ self.msg(f"- {v['name']}")
55
+ if re.match("^#.*$", v["name"]) is not None:
56
+ return False
57
+ node = self._load_marker(v)
58
+ if node is None:
59
+ return False
60
+ self._install_marker(v, node)
61
+ return True
62
+
63
+ def _parse_markers_csv(self):
64
+ svg_path = self.svg_path()
65
+ assert isinstance(svg_path, str)
66
+ self._markers_csv = os.path.join(svg_path, "markers.csv")
67
+ with open(self._markers_csv, "r", encoding="utf-8") as fh:
68
+ reader = csv.DictReader(fh)
69
+ values = [line for line in reader]
70
+ for v in values:
71
+ self._handle_entry(v)
72
+
73
+ def _find_assets_markers(self):
74
+ assert isinstance(self._assets, inkex.Group)
75
+ for child in list(self._assets):
76
+ if isinstance(child, inkex.Group) and child.label == "(Markers)":
77
+ self._markers = child
78
+
79
+ def _find_assets(self):
80
+ assert isinstance(self.document, inkex.SvgDocumentElement)
81
+ res = [
82
+ node
83
+ for node in self.document.getroot()
84
+ if isinstance(node, inkex.Group)
85
+ if isinstance(node.label, str)
86
+ if re.match("^[(]Assets[)]$", node.label) is not None
87
+ ]
88
+ if len(res) != 1:
89
+ return None
90
+ else:
91
+ return res[0]
92
+
93
+ def _load_markers(self):
94
+ self.msg("=== load markers: start")
95
+ self._assets = self._find_assets()
96
+ if self._assets is None:
97
+ self.msg("(Assets) not found!")
98
+ return False
99
+ self._find_assets_markers()
100
+ if self._markers is None:
101
+ self.msg("(Assets)/(Markers) not found!")
102
+ return False
103
+ self._parse_markers_csv()
104
+ self.msg("=== load markers: end")
105
+
106
+ def _remove_defs_markers(self):
107
+ for child in list(self.svg.defs):
108
+ if isinstance(child, inkex.Marker):
109
+ self.svg.defs.remove(child)
110
+
111
+ def effect(self):
112
+ self._remove_defs_markers()
113
+ self._load_markers()
114
+
115
+
116
+ if __name__ == "__main__":
117
+ LoadMarkers().run()
@@ -0,0 +1,17 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
3
+ <name>Load Patterns</name>
4
+ <id>daijimaps.load_patterns</id>
5
+ <label>Load patterns under Assets.</label>
6
+ <effect needs-live-preview="false">
7
+ <object-type>all</object-type>
8
+ <effects-menu>
9
+ <submenu name="Daiji Maps">
10
+ <submenu name="Assets" />
11
+ </submenu>
12
+ </effects-menu>
13
+ </effect>
14
+ <script>
15
+ <command location="inx" interpreter="python">load_patterns.py</command>
16
+ </script>
17
+ </inkscape-extension>
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env python3
2
+ # coding=utf-8
3
+
4
+ import copy
5
+ import csv
6
+ import os
7
+ import re
8
+
9
+ from lxml import etree
10
+
11
+ import inkex
12
+
13
+
14
+ class LoadPatterns(inkex.EffectExtension):
15
+ # (Assets)/(Patterns)
16
+ _assets = None
17
+ _patterns = None
18
+ _patterns_csv = None
19
+
20
+ def _find_group(self, group):
21
+ assert isinstance(self._patterns, inkex.Group)
22
+ for node in list(self._patterns):
23
+ if node.label == group:
24
+ return node
25
+ return None
26
+
27
+ def _install_pattern(self, v, node):
28
+ prev = None
29
+ assert isinstance(self._patterns, inkex.Group)
30
+ for child in list(self._patterns):
31
+ if child.get("id") == v["name"]:
32
+ prev = child
33
+ if prev is not None:
34
+ self._patterns.remove(prev)
35
+ self._patterns.append(node)
36
+ node.set("id", v["name"]) # 'StairsH'
37
+ return True
38
+
39
+ def _load_pattern(self, v):
40
+ svg_path = self.svg_path()
41
+ assert isinstance(svg_path, str)
42
+ file = os.path.join(svg_path, v["file"])
43
+ f = inkex.load_svg(file)
44
+ r = f.getroot()
45
+ assert isinstance(r, inkex.SvgDocumentElement)
46
+ node = r.getElementById(v["id"])
47
+ return copy.deepcopy(node)
48
+
49
+ def _handle_entry(self, v):
50
+ # name,file,id
51
+ if v["name"] == "":
52
+ return False
53
+ self.msg(f"- {v['name']}")
54
+ if re.match("^#.*$", v["name"]) is not None:
55
+ return False
56
+ node = self._load_pattern(v)
57
+ if node is None:
58
+ return False
59
+ self._install_pattern(v, node)
60
+ return True
61
+
62
+ def _parse_patterns_csv(self):
63
+ svg_path = self.svg_path()
64
+ assert isinstance(svg_path, str)
65
+ self._patterns_csv = os.path.join(svg_path, "patterns.csv")
66
+ with open(self._patterns_csv, "r", encoding="utf-8") as fh:
67
+ reader = csv.DictReader(fh)
68
+ values = [line for line in reader]
69
+ for v in values:
70
+ self._handle_entry(v)
71
+
72
+ def _find_assets_patterns(self):
73
+ assert isinstance(self._assets, inkex.Group)
74
+ for child in list(self._assets):
75
+ if isinstance(child, inkex.Group) and child.label == "(Patterns)":
76
+ self._patterns = child
77
+
78
+ def _find_assets(self):
79
+ assert isinstance(self.document, etree._ElementTree)
80
+ res = [
81
+ node
82
+ for node in self.document.getroot()
83
+ if isinstance(node, inkex.Group)
84
+ if isinstance(node.label, str)
85
+ if re.match("^[(]Assets[)]$", node.label) is not None
86
+ ]
87
+ if len(res) != 1:
88
+ return None
89
+ else:
90
+ return res[0]
91
+
92
+ def _load_patterns(self):
93
+ self.msg("=== load patterns: start")
94
+ self._assets = self._find_assets()
95
+ if self._assets is None:
96
+ self.msg("(Assets) not found!")
97
+ return False
98
+ self._find_assets_patterns()
99
+ if self._patterns is None:
100
+ self.msg("(Assets)/(Patterns) not found!")
101
+ return False
102
+ self._parse_patterns_csv()
103
+ self.msg("=== load patterns: end")
104
+
105
+ def _remove_defs_patterns(self):
106
+ for child in list(self.svg.defs):
107
+ if isinstance(child, inkex.Pattern):
108
+ self.svg.defs.remove(child)
109
+
110
+ def effect(self):
111
+ self._remove_defs_patterns()
112
+ self._load_patterns()
113
+
114
+
115
+ if __name__ == "__main__":
116
+ LoadPatterns().run()
@@ -0,0 +1,17 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
3
+ <name>Load Symbols</name>
4
+ <id>daijimaps.load_symbols</id>
5
+ <label>Load symbols under Assets.</label>
6
+ <effect needs-live-preview="false">
7
+ <object-type>all</object-type>
8
+ <effects-menu>
9
+ <submenu name="Daiji Maps">
10
+ <submenu name="Assets" />
11
+ </submenu>
12
+ </effects-menu>
13
+ </effect>
14
+ <script>
15
+ <command location="inx" interpreter="python">load_symbols.py</command>
16
+ </script>
17
+ </inkscape-extension>
@@ -0,0 +1,164 @@
1
+ #!/usr/bin/env python3
2
+ # coding=utf-8
3
+
4
+ import csv
5
+ import os
6
+ import re
7
+
8
+ from lxml import etree
9
+
10
+ import inkex
11
+
12
+
13
+ class LoadSymbols(inkex.EffectExtension):
14
+ # (Assets)/(Symbols)
15
+ _assets = None
16
+ _symbols = None
17
+ _symbols_csv = None
18
+
19
+ def _find_group(self, group):
20
+ assert isinstance(self._symbols, inkex.Group)
21
+ for node in list(self._symbols):
22
+ if node.label == group:
23
+ return node
24
+ return None
25
+
26
+ def _install_symbol(self, v, node):
27
+ g = self._find_group(v["group"])
28
+ assert isinstance(self._symbols, inkex.Group)
29
+ if g is None:
30
+ g = inkex.Group()
31
+ g.label = v["group"] # '(Facilities)'
32
+ self._symbols.append(g)
33
+ s = inkex.Group()
34
+ s.label = v["name"] # 'Toilets'
35
+ x = inkex.Group()
36
+ x.label = "X" + v["name"] # 'XToilets'
37
+ x.set("id", x.label) # 'XToilets'
38
+ x.set("transform", f"scale({v['scale']}) translate({v['dx']}, {v['dy']})")
39
+ for c in list(node):
40
+ x.append(c)
41
+ s.append(x)
42
+ prev = None
43
+ for node in list(g):
44
+ if node.label == v["name"]:
45
+ prev = node
46
+ g.append(s)
47
+ if prev is not None:
48
+ g.remove(prev)
49
+ return True
50
+
51
+ # AigaSymbols.svg#Elevator_Inv defines '#person2' (and uses it)
52
+ # Rename '#person2' to '#_person2' so it will not be trimmed
53
+ # by map-extract-floors.py:fixupElement()
54
+ def _fixup_symbol_ids(self, tree):
55
+ if tree is None:
56
+ return
57
+ href_ids = {}
58
+ for e in tree.iter():
59
+ href = e.get("href") or e.get("xlink:href")
60
+ if href is not None:
61
+ href_id = re.sub(r"#", "", href)
62
+ href_ids[href_id] = True
63
+ for e in tree.iter():
64
+ _id = e.get("id")
65
+ if _id in href_ids:
66
+ self.msg(f"fixing id: {_id} -> _{_id}")
67
+ e.set("id", f"_{_id}")
68
+ href = e.get("xlink:href")
69
+ if href is not None:
70
+ href_id = re.sub(r"#", "", href)
71
+ if href_id in href_ids:
72
+ self.msg(f"fixing href: #{href_id} -> #_{href_id}")
73
+ e.set("xlink:href", f"#_{href_id}")
74
+
75
+ def _fixup_symbol_titles(self, node):
76
+ if node is None:
77
+ return
78
+ for e in node.iter():
79
+ if isinstance(e.tag, str) and re.match("^.*title.*$", e.tag) is not None:
80
+ self.msg(f"deleting title: {e}")
81
+ p = e.getparent()
82
+ p.remove(e)
83
+ elif isinstance(e, etree._Comment):
84
+ self.msg(f"deleting comment: {e}")
85
+ p = e.getparent()
86
+ if p:
87
+ p.remove(e)
88
+
89
+ def _fixup_symbol(self, node):
90
+ self._fixup_symbol_ids(node)
91
+ self._fixup_symbol_titles(node)
92
+
93
+ def _load_symbol(self, v):
94
+ svg_path = self.svg_path()
95
+ assert isinstance(svg_path, str)
96
+ file = os.path.join(svg_path, v["file"])
97
+ f = inkex.load_svg(file)
98
+ r = f.getroot()
99
+ assert isinstance(r, inkex.SvgDocumentElement)
100
+ node = r.getElementById(v["id"])
101
+ self._fixup_symbol(node)
102
+ return node
103
+
104
+ def _handle_entry(self, v):
105
+ # group,name,file,id,dx,dy,scale
106
+ if v["group"] == "":
107
+ return False
108
+ if re.match("^#.*$", v["group"]) is not None:
109
+ return False
110
+ node = self._load_symbol(v)
111
+ if node is None:
112
+ self.msg(f"symbol not found: {v}")
113
+ return False
114
+ self._install_symbol(v, node)
115
+ return True
116
+
117
+ def _parse_symbols_csv(self):
118
+ svg_path = self.svg_path()
119
+ assert isinstance(svg_path, str)
120
+ self._symbols_csv = os.path.join(svg_path, "symbols.csv")
121
+ with open(self._symbols_csv, "r", encoding="utf-8") as fh:
122
+ reader = csv.DictReader(fh)
123
+ _header = next(reader)
124
+ values = [line for line in reader]
125
+ for v in values:
126
+ self._handle_entry(v)
127
+
128
+ def _find_assets_symbols(self):
129
+ assert isinstance(self._assets, inkex.Group)
130
+ for child in list(self._assets):
131
+ if isinstance(child, inkex.Group) and child.label == "(Symbols)":
132
+ self._symbols = child
133
+
134
+ def _find_assets(self):
135
+ assert isinstance(self.document, etree._ElementTree)
136
+ res = [
137
+ node
138
+ for node in self.document.getroot()
139
+ if isinstance(node, inkex.Group)
140
+ if isinstance(node.label, str)
141
+ if re.match("^[(]Assets[)]$", node.label) is not None
142
+ ]
143
+ if len(res) != 1:
144
+ return None
145
+ else:
146
+ return res[0]
147
+
148
+ def _load_symbols(self):
149
+ self.msg("=== load symbols: start")
150
+ self._assets = self._find_assets()
151
+ if self._assets is None:
152
+ return False
153
+ self._find_assets_symbols()
154
+ if self._symbols is None:
155
+ return False
156
+ self._parse_symbols_csv()
157
+ self.msg("=== load symbols: end")
158
+
159
+ def effect(self):
160
+ self._load_symbols()
161
+
162
+
163
+ if __name__ == "__main__":
164
+ LoadSymbols().run()
@@ -0,0 +1,24 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
3
+ <name>Renumber (Tree)</name>
4
+ <id>daijimaps.renumber_tree</id>
5
+ <label>Renumber groups under the selected tree.</label>
6
+ <param name="tab" type="notebook">
7
+ <page name="Options" gui-text="Options">
8
+ <param name="floor" type="string" gui-text="Target floor (regular expression)">.</param>
9
+ </page>
10
+ </param>
11
+ <effect needs-live-preview="false">
12
+ <object-type>all</object-type>
13
+ <effects-menu>
14
+ <submenu name="Daiji Maps">
15
+ <submenu name="Addressess">
16
+ <submenu name="Renumber" />
17
+ </submenu>
18
+ </submenu>
19
+ </effects-menu>
20
+ </effect>
21
+ <script>
22
+ <command location="inx" interpreter="python">renumber_tree.py</command>
23
+ </script>
24
+ </inkscape-extension>