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.
- package/LICENSE +15 -0
- package/inkscape/extensions/Attic/fix_guides.inx +17 -0
- package/inkscape/extensions/Attic/fix_guides.py +30 -0
- package/inkscape/extensions/Attic/fix_symbol_links.inx +17 -0
- package/inkscape/extensions/Attic/fix_symbol_links.py +71 -0
- package/inkscape/extensions/Attic/flatten_style.inx +17 -0
- package/inkscape/extensions/Attic/flatten_style.py +31 -0
- package/inkscape/extensions/Attic/load_markers.inx +17 -0
- package/inkscape/extensions/Attic/load_markers.py +117 -0
- package/inkscape/extensions/Attic/load_patterns.inx +17 -0
- package/inkscape/extensions/Attic/load_patterns.py +116 -0
- package/inkscape/extensions/Attic/load_symbols.inx +17 -0
- package/inkscape/extensions/Attic/load_symbols.py +164 -0
- package/inkscape/extensions/Attic/renumber_tree.inx +24 -0
- package/inkscape/extensions/Attic/renumber_tree.py +39 -0
- package/inkscape/extensions/Attic/repeat_path.inx +17 -0
- package/inkscape/extensions/Attic/repeat_path.py +58 -0
- package/inkscape/extensions/Attic/resolve_facility_links.inx +19 -0
- package/inkscape/extensions/Attic/resolve_facility_links.py +16 -0
- package/inkscape/extensions/Attic/sort_symbols.inx +17 -0
- package/inkscape/extensions/Attic/sort_symbols.py +48 -0
- package/inkscape/extensions/Attic/symbol_load.inx +17 -0
- package/inkscape/extensions/Attic/symbol_load.py +99 -0
- package/inkscape/extensions/Attic/tidy_tree.inx +22 -0
- package/inkscape/extensions/Attic/tidy_tree.py +178 -0
- package/inkscape/extensions/Attic/use_shop.inx +22 -0
- package/inkscape/extensions/Attic/use_shop.py +26 -0
- package/inkscape/extensions/README.md +34 -0
- package/inkscape/extensions/daijimaps/__init__.py +72 -0
- package/inkscape/extensions/daijimaps/address_tree.py +231 -0
- package/inkscape/extensions/daijimaps/common.py +49 -0
- package/inkscape/extensions/daijimaps/generate_addresses.py +41 -0
- package/inkscape/extensions/daijimaps/guards.py +47 -0
- package/inkscape/extensions/daijimaps/map_layer.py +47 -0
- package/inkscape/extensions/daijimaps/name.py +167 -0
- package/inkscape/extensions/daijimaps/renumber.py +38 -0
- package/inkscape/extensions/daijimaps/resolve_labels.py +65 -0
- package/inkscape/extensions/daijimaps/resolve_names.py +170 -0
- package/inkscape/extensions/daijimaps/save_addresses.py +274 -0
- package/inkscape/extensions/daijimaps/types.py +128 -0
- package/inkscape/extensions/daijimaps/visit_parents.py +37 -0
- package/inkscape/extensions/extract_labels.py +79 -0
- package/inkscape/extensions/fixup_floor_svg.py +28 -0
- package/inkscape/extensions/fixup_texts.inx +15 -0
- package/inkscape/extensions/fixup_texts.py +110 -0
- package/inkscape/extensions/fixup_tree.inx +15 -0
- package/inkscape/extensions/fixup_tree.py +17 -0
- package/inkscape/extensions/flatten_transform.inx +17 -0
- package/inkscape/extensions/flatten_transform.py +63 -0
- package/inkscape/extensions/import_labels.inx +20 -0
- package/inkscape/extensions/import_labels.py +52 -0
- package/inkscape/extensions/import_shops.inx +20 -0
- package/inkscape/extensions/import_shops.py +47 -0
- package/inkscape/extensions/install.sh +14 -0
- package/inkscape/extensions/load_shops.inx +20 -0
- package/inkscape/extensions/load_shops.py +86 -0
- package/inkscape/extensions/renumber_group.inx +15 -0
- package/inkscape/extensions/renumber_group.py +17 -0
- package/inkscape/extensions/resolve_labels.inx +20 -0
- package/inkscape/extensions/resolve_labels.py +142 -0
- package/inkscape/extensions/resolve_shops.inx +20 -0
- package/inkscape/extensions/resolve_shops.py +73 -0
- package/inkscape/extensions/unresolve_labels.inx +20 -0
- package/inkscape/extensions/unresolve_labels.py +53 -0
- package/inkscape/extensions/unresolve_shops.inx +20 -0
- package/inkscape/extensions/unresolve_shops.py +56 -0
- package/inkscape/templates/floors.svg +665 -0
- package/map-extract-floors.js +821 -0
- package/package.json +19 -0
- package/pyproject.toml +20 -0
- package/scripts/inkex-inkscape +14 -0
- package/scripts/inkex-python +14 -0
- package/scripts/inkex-setup +6 -0
- package/scripts/labels.sh +18 -0
- package/scripts/regen.py +77 -0
- package/scripts/regen.sh +24 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
from .address_tree import AddressTree
|
|
2
|
+
|
|
3
|
+
from .generate_addresses import GenerateAddresses
|
|
4
|
+
|
|
5
|
+
from .guards import (
|
|
6
|
+
isBaseElement,
|
|
7
|
+
isCircle,
|
|
8
|
+
isEllipse,
|
|
9
|
+
isGroup,
|
|
10
|
+
isRectangle,
|
|
11
|
+
isTextElement,
|
|
12
|
+
isUse,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
from .name import draw_label, draw_name, move_name, preferInt, read_name, redraw_name
|
|
16
|
+
|
|
17
|
+
from .renumber import renumber_group
|
|
18
|
+
|
|
19
|
+
from .resolve_names import ResolveNames
|
|
20
|
+
|
|
21
|
+
from .save_addresses import SaveAddresses
|
|
22
|
+
|
|
23
|
+
from .types import (
|
|
24
|
+
Address,
|
|
25
|
+
AddressNames,
|
|
26
|
+
AddressString,
|
|
27
|
+
Addresses,
|
|
28
|
+
Name,
|
|
29
|
+
NameAddresses,
|
|
30
|
+
NameString,
|
|
31
|
+
Names,
|
|
32
|
+
XY,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
__all__ = [
|
|
37
|
+
# .address_tree
|
|
38
|
+
AddressTree,
|
|
39
|
+
# .generate_addresses
|
|
40
|
+
GenerateAddresses,
|
|
41
|
+
# .guards
|
|
42
|
+
isBaseElement,
|
|
43
|
+
isCircle,
|
|
44
|
+
isEllipse,
|
|
45
|
+
isGroup,
|
|
46
|
+
isRectangle,
|
|
47
|
+
isTextElement,
|
|
48
|
+
isUse,
|
|
49
|
+
# .name
|
|
50
|
+
draw_label,
|
|
51
|
+
draw_name,
|
|
52
|
+
move_name,
|
|
53
|
+
preferInt,
|
|
54
|
+
read_name,
|
|
55
|
+
redraw_name,
|
|
56
|
+
# .renumber
|
|
57
|
+
renumber_group,
|
|
58
|
+
# .resolve_names
|
|
59
|
+
ResolveNames,
|
|
60
|
+
# .save_addresses
|
|
61
|
+
SaveAddresses,
|
|
62
|
+
# .types
|
|
63
|
+
Address,
|
|
64
|
+
AddressNames,
|
|
65
|
+
AddressString,
|
|
66
|
+
Addresses,
|
|
67
|
+
Name,
|
|
68
|
+
NameAddresses,
|
|
69
|
+
NameString,
|
|
70
|
+
Names,
|
|
71
|
+
XY,
|
|
72
|
+
]
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# coding=utf-8
|
|
3
|
+
|
|
4
|
+
from argparse import ArgumentParser
|
|
5
|
+
import inkex
|
|
6
|
+
import re
|
|
7
|
+
import os
|
|
8
|
+
from lxml import etree
|
|
9
|
+
from .visit_parents import _visit_parents, CONT, SKIP, Visit, Tree, Parents
|
|
10
|
+
from .types import AddressPos, JsonGlobalPaths, JsonLayerPaths, Links, PosAddress
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class AddressTree(inkex.EffectExtension):
|
|
14
|
+
_layers: list[inkex.Group] = []
|
|
15
|
+
|
|
16
|
+
_addresses: AddressPos = {}
|
|
17
|
+
_all_addresses: AddressPos = {}
|
|
18
|
+
_points: PosAddress = {}
|
|
19
|
+
_all_points: PosAddress = {}
|
|
20
|
+
_links: Links = {}
|
|
21
|
+
|
|
22
|
+
# XXX address <g> id
|
|
23
|
+
# XXX (A)ddress
|
|
24
|
+
# e.g. `A1F-Shops-1-1`
|
|
25
|
+
_global_prefix = "A"
|
|
26
|
+
|
|
27
|
+
# e.g. `(Contents)`
|
|
28
|
+
_ignore_pattern = "^[(].*[)]$"
|
|
29
|
+
|
|
30
|
+
_layerPaths: JsonLayerPaths
|
|
31
|
+
_paths: JsonGlobalPaths
|
|
32
|
+
|
|
33
|
+
_find_layers_opts = {"skip_ignoring": True}
|
|
34
|
+
|
|
35
|
+
def _get_path(self, layer_name: str, prefix: str, suffix: str) -> str | None:
|
|
36
|
+
assert isinstance(layer_name, str)
|
|
37
|
+
ps = [
|
|
38
|
+
f"floors/{layer_name}/{prefix}.{suffix}",
|
|
39
|
+
f"floors/{prefix}/{layer_name}.{suffix}",
|
|
40
|
+
f"floors/{layer_name}-{prefix}.{suffix}",
|
|
41
|
+
f"floors/{prefix}-{layer_name}.{suffix}",
|
|
42
|
+
f"{layer_name}/{prefix}.{suffix}",
|
|
43
|
+
f"{prefix}/{layer_name}.{suffix}",
|
|
44
|
+
f"{layer_name}-{prefix}.{suffix}",
|
|
45
|
+
f"{prefix}-{layer_name}.{suffix}",
|
|
46
|
+
]
|
|
47
|
+
svg_path: str = self.svg_path()
|
|
48
|
+
assert isinstance(svg_path, str)
|
|
49
|
+
for p in ps:
|
|
50
|
+
path: str = os.path.join(svg_path, p)
|
|
51
|
+
self.msg(f"_get_path: {path}")
|
|
52
|
+
if os.access(path, os.R_OK):
|
|
53
|
+
self.msg(f"_get_path: found: {path}")
|
|
54
|
+
return path
|
|
55
|
+
self.msg(f"_get_path: not found: {prefix}, {suffix}")
|
|
56
|
+
return None
|
|
57
|
+
|
|
58
|
+
def _ignoring(self, node):
|
|
59
|
+
return re.match(self._ignore_pattern, node.label) is not None
|
|
60
|
+
|
|
61
|
+
def _visitor_node_branch(self, node: Tree, parents: Parents) -> None:
|
|
62
|
+
pass
|
|
63
|
+
|
|
64
|
+
def _visitor_node_leaf(self, node: Tree, parents: Parents) -> None:
|
|
65
|
+
pass
|
|
66
|
+
|
|
67
|
+
def _visitor(self, node: Tree, parents: Parents) -> Visit:
|
|
68
|
+
if not isinstance(node, inkex.Group):
|
|
69
|
+
return SKIP
|
|
70
|
+
if node.label and self._ignoring(node):
|
|
71
|
+
return SKIP
|
|
72
|
+
|
|
73
|
+
# (T) Leaf (terminal) node?
|
|
74
|
+
# leaves MUST be <use> and define transform!
|
|
75
|
+
# XXX why `is not None` doesn't work?
|
|
76
|
+
leaf = isinstance(node, inkex.Use) and node.transform
|
|
77
|
+
|
|
78
|
+
if leaf:
|
|
79
|
+
self._visitor_node_leaf(node, parents)
|
|
80
|
+
return SKIP
|
|
81
|
+
else:
|
|
82
|
+
self._visitor_node_branch(node, parents)
|
|
83
|
+
return CONT
|
|
84
|
+
|
|
85
|
+
def _pre_collect_addresses(self, node) -> None:
|
|
86
|
+
pass
|
|
87
|
+
|
|
88
|
+
def _collect_addresses(self, node) -> None:
|
|
89
|
+
self.msg("=== _collect_addresses@AddressTree")
|
|
90
|
+
self._addresses = {}
|
|
91
|
+
self._points = {}
|
|
92
|
+
|
|
93
|
+
_visit_parents(node, self._visitor)
|
|
94
|
+
|
|
95
|
+
def _post_collect_addresses(self, node: inkex.Group) -> None:
|
|
96
|
+
pass
|
|
97
|
+
|
|
98
|
+
def _pre_process_addresses(self, node: inkex.Group) -> None:
|
|
99
|
+
pass
|
|
100
|
+
|
|
101
|
+
def _process_addresses(self, node: inkex.Group) -> None:
|
|
102
|
+
pass
|
|
103
|
+
|
|
104
|
+
def _post_process_addresses(self, node: inkex.Group) -> None:
|
|
105
|
+
pass
|
|
106
|
+
|
|
107
|
+
def _pre_layers(self) -> None:
|
|
108
|
+
pass
|
|
109
|
+
|
|
110
|
+
def _post_layers(self) -> None:
|
|
111
|
+
pass
|
|
112
|
+
|
|
113
|
+
def _find_group(self, layer, label) -> inkex.Group | None:
|
|
114
|
+
for child in list(layer):
|
|
115
|
+
if "label" in child:
|
|
116
|
+
self.msg(f"_find_group: {child.label}")
|
|
117
|
+
if not isinstance(child, inkex.Group):
|
|
118
|
+
# XXX msg
|
|
119
|
+
continue
|
|
120
|
+
if child.label is None or child.label != label:
|
|
121
|
+
# XXX msg
|
|
122
|
+
continue
|
|
123
|
+
self.msg(f"_find_group: found: {child.label}")
|
|
124
|
+
return child
|
|
125
|
+
return None
|
|
126
|
+
|
|
127
|
+
def _find_or_make_group(self, layer, label) -> inkex.Layer:
|
|
128
|
+
group = self._find_group(layer, label)
|
|
129
|
+
if group is None:
|
|
130
|
+
group = inkex.Layer()
|
|
131
|
+
group.label = label
|
|
132
|
+
layer.append(group)
|
|
133
|
+
return group
|
|
134
|
+
|
|
135
|
+
def _find_layers(self) -> None:
|
|
136
|
+
self.msg("=== _find_layers")
|
|
137
|
+
floor_pattern: str = self.options.floor
|
|
138
|
+
|
|
139
|
+
assert isinstance(self.document, etree._ElementTree)
|
|
140
|
+
assert isinstance(floor_pattern, str | None)
|
|
141
|
+
self._layers: list[inkex.Group] = [
|
|
142
|
+
node
|
|
143
|
+
for node in self.document.getroot()
|
|
144
|
+
if isinstance(node, inkex.Group)
|
|
145
|
+
if not (
|
|
146
|
+
node.label
|
|
147
|
+
and (self._find_layers_opts["skip_ignoring"] and self._ignoring(node))
|
|
148
|
+
)
|
|
149
|
+
if (
|
|
150
|
+
floor_pattern is None
|
|
151
|
+
or not isinstance(node.label, str)
|
|
152
|
+
or re.match(floor_pattern, node.label) is not None
|
|
153
|
+
)
|
|
154
|
+
]
|
|
155
|
+
self.msg(f"=== _find_layers: {self._layers}")
|
|
156
|
+
|
|
157
|
+
def _find_assets(self) -> inkex.Group | None:
|
|
158
|
+
assert isinstance(self.document, etree._ElementTree), ""
|
|
159
|
+
res: list[inkex.Group] = [
|
|
160
|
+
node
|
|
161
|
+
for node in self.document.getroot()
|
|
162
|
+
if isinstance(node, inkex.Group)
|
|
163
|
+
if not (node.label and self._ignoring(node))
|
|
164
|
+
if isinstance(node.label, str)
|
|
165
|
+
and re.match("^(Assets)$", node.label) is not None
|
|
166
|
+
]
|
|
167
|
+
if len(res) != 1:
|
|
168
|
+
return None
|
|
169
|
+
else:
|
|
170
|
+
return res[0]
|
|
171
|
+
|
|
172
|
+
def _set_paths(self, layer_name: str):
|
|
173
|
+
p = self.svg_path()
|
|
174
|
+
assert isinstance(p, str)
|
|
175
|
+
|
|
176
|
+
j = os.path.join
|
|
177
|
+
ln = layer_name
|
|
178
|
+
|
|
179
|
+
self._layerPaths = {
|
|
180
|
+
"addresses": j(p, f"addresses/{ln}.json"),
|
|
181
|
+
"unresolvedNames": j(p, f"unresolved_names/{ln}.json"),
|
|
182
|
+
"resolvedNames": j(p, f"resolved_names/{ln}.json"),
|
|
183
|
+
"tmpUnresolvedNames": j("/tmp", f"tmp_unresolved_names_{ln}.json"),
|
|
184
|
+
"tmpResolvedNames": j("/tmp", f"tmp_resolved_names_{ln}.json"),
|
|
185
|
+
"floorsAddresses": j(p, f"floors-addresses-{ln}.json"),
|
|
186
|
+
"floorsNames": j(p, f"floors-names-{ln}.json"),
|
|
187
|
+
}
|
|
188
|
+
self._paths = {
|
|
189
|
+
"bbox": j(p, "bbox.json"),
|
|
190
|
+
"facilities": j(p, "facilities.json"),
|
|
191
|
+
"floors": j(p, "floors.json"),
|
|
192
|
+
"origin": j(p, "origin.json"),
|
|
193
|
+
"viewbox": j(p, "viewbox.json"),
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
def _handle_layer(self, layer: inkex.Group, layer_name: str) -> None:
|
|
197
|
+
# XXX set .json paths
|
|
198
|
+
# input
|
|
199
|
+
# self._locs_json = os.path.join(self.svg_path(), "build", f"locs_{layer_name}.json")
|
|
200
|
+
# self._locs_json = os.path.join(self.svg_path(), f"locs.json")
|
|
201
|
+
|
|
202
|
+
self._set_paths(layer_name)
|
|
203
|
+
|
|
204
|
+
self._pre_collect_addresses(layer)
|
|
205
|
+
self._collect_addresses(layer)
|
|
206
|
+
self._post_collect_addresses(layer)
|
|
207
|
+
self._pre_process_addresses(layer)
|
|
208
|
+
self._process_addresses(layer)
|
|
209
|
+
self._post_process_addresses(layer)
|
|
210
|
+
|
|
211
|
+
def add_arguments(self, pars: ArgumentParser) -> None:
|
|
212
|
+
pars.add_argument("--tab", type=str, dest="tab")
|
|
213
|
+
pars.add_argument("--floor", type=str, default=".")
|
|
214
|
+
return super().add_arguments(pars)
|
|
215
|
+
|
|
216
|
+
def effect(self) -> None:
|
|
217
|
+
self.msg("==== AddressTree: start")
|
|
218
|
+
self._find_layers()
|
|
219
|
+
self._pre_layers()
|
|
220
|
+
for layer in self._layers:
|
|
221
|
+
layer_name = layer.label
|
|
222
|
+
if not isinstance(layer_name, str):
|
|
223
|
+
continue
|
|
224
|
+
self._handle_layer(layer, layer_name)
|
|
225
|
+
self._post_layers()
|
|
226
|
+
self.msg("==== AddressTree: end")
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
__all__ = [
|
|
230
|
+
AddressTree,
|
|
231
|
+
]
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from .types import Address, AddressString, V
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
# XXX prefer 1 to 1.0
|
|
7
|
+
def unround(n: float) -> float:
|
|
8
|
+
f: float = round(n, ndigits=3)
|
|
9
|
+
i: float = round(f)
|
|
10
|
+
return f if f != i else i
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def xy2v(x, y) -> V:
|
|
14
|
+
return {
|
|
15
|
+
"x": unround(x),
|
|
16
|
+
"y": unround(y),
|
|
17
|
+
#'w': r3w if r3w != rw else rw,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def a2astr(axy: Address) -> AddressString | None:
|
|
22
|
+
(astr, _xy) = axy
|
|
23
|
+
return astr
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def a2v(axy: Address) -> V:
|
|
27
|
+
(_a, (x, y)) = axy
|
|
28
|
+
return xy2v(x, y)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def find_layer_file(dir: str, layer: str, prefix: str, suffix: str) -> str | None:
|
|
32
|
+
ps: list[str] = [
|
|
33
|
+
f"floors/{layer}/{prefix}.{suffix}",
|
|
34
|
+
f"floors/{prefix}/{layer}.{suffix}",
|
|
35
|
+
f"floors/{layer}-{prefix}.{suffix}",
|
|
36
|
+
f"floors/{prefix}-{layer}.{suffix}",
|
|
37
|
+
f"{layer}/{prefix}.{suffix}",
|
|
38
|
+
f"{prefix}/{layer}.{suffix}",
|
|
39
|
+
f"{layer}-{prefix}.{suffix}",
|
|
40
|
+
f"{prefix}-{layer}.{suffix}",
|
|
41
|
+
]
|
|
42
|
+
for p in ps:
|
|
43
|
+
path: str = os.path.join(dir, p)
|
|
44
|
+
if os.access(path, mode=os.R_OK):
|
|
45
|
+
return path
|
|
46
|
+
return None
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
__all__ = [a2astr, a2v, xy2v]
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import inkex
|
|
2
|
+
|
|
3
|
+
from .save_addresses import SaveAddresses
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class GenerateAddresses(SaveAddresses):
|
|
7
|
+
_group_label = "(Addresses)"
|
|
8
|
+
|
|
9
|
+
def _cleanup_addresses(self, layer) -> None:
|
|
10
|
+
for child in list(layer):
|
|
11
|
+
if "label" in child and child.label == self._group_label:
|
|
12
|
+
child.delete()
|
|
13
|
+
|
|
14
|
+
def _generate_addresses_address(self, aparent, k, x, y, bb, href) -> None:
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
def _generate_addresses(self, layer, layer_name: str) -> None:
|
|
18
|
+
self.msg("=== GenerateAddresses: _generate_addresses")
|
|
19
|
+
if len(self._addresses.items()) == 0:
|
|
20
|
+
self.msg("_generate_addresses: no items found!")
|
|
21
|
+
return
|
|
22
|
+
|
|
23
|
+
aparent = inkex.Group()
|
|
24
|
+
aparent.label = self._group_label
|
|
25
|
+
for k, ((x, y), bb, href) in self._addresses.items():
|
|
26
|
+
self._generate_addresses_address(aparent, k, x, y, bb, href)
|
|
27
|
+
layer.append(aparent)
|
|
28
|
+
|
|
29
|
+
def _pre_process_addresses(self, node: inkex.Group) -> None:
|
|
30
|
+
super()._pre_process_addresses(node)
|
|
31
|
+
self._cleanup_addresses(node)
|
|
32
|
+
|
|
33
|
+
def _process_addresses(self, node: inkex.Group) -> None:
|
|
34
|
+
self.msg("=== GenerateAddresses: _process_addresses")
|
|
35
|
+
super()._process_addresses(node)
|
|
36
|
+
name = node.label
|
|
37
|
+
if isinstance(name, str):
|
|
38
|
+
self._generate_addresses(node, name)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
__all__ = [GenerateAddresses]
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from typing import Any, TypeGuard
|
|
2
|
+
|
|
3
|
+
import inkex
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def isBaseElement(x: Any) -> TypeGuard[inkex.BaseElement]:
|
|
7
|
+
return isinstance(x, inkex.BaseElement)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def isCircle(x: Any) -> TypeGuard[inkex.Circle]:
|
|
11
|
+
return isinstance(x, inkex.Circle)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def isEllipse(x: Any) -> TypeGuard[inkex.Ellipse]:
|
|
15
|
+
return isinstance(x, inkex.Ellipse)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def isGroup(x: Any) -> TypeGuard[inkex.Group]:
|
|
19
|
+
return isinstance(x, inkex.Group)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def isRectangle(x: Any) -> TypeGuard[inkex.Rectangle]:
|
|
23
|
+
return isinstance(x, inkex.Rectangle)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def isTextElement(x: Any) -> TypeGuard[inkex.TextElement]:
|
|
27
|
+
return isinstance(x, inkex.TextElement)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def isTspan(x: Any) -> TypeGuard[inkex.Tspan]:
|
|
31
|
+
return isinstance(x, inkex.Tspan)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def isUse(x: Any) -> TypeGuard[inkex.Use]:
|
|
35
|
+
return isinstance(x, inkex.Use)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
__all__ = [
|
|
39
|
+
isBaseElement,
|
|
40
|
+
isCircle,
|
|
41
|
+
isEllipse,
|
|
42
|
+
isGroup,
|
|
43
|
+
isRectangle,
|
|
44
|
+
isTextElement,
|
|
45
|
+
isTspan,
|
|
46
|
+
isUse,
|
|
47
|
+
]
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import inkex
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def fixup_tree_layer(group: inkex.Group) -> None:
|
|
5
|
+
layer_names = [
|
|
6
|
+
"(Names)",
|
|
7
|
+
"(Unresolved Names)",
|
|
8
|
+
"(Labels)",
|
|
9
|
+
"(Unresolved Labels)",
|
|
10
|
+
"Content",
|
|
11
|
+
"(Background)",
|
|
12
|
+
]
|
|
13
|
+
for layer_name in layer_names:
|
|
14
|
+
find_layer_and_change_to_layer(group, layer_name)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def fixup_tree_layer_content(group: inkex.Group) -> None:
|
|
18
|
+
layer_names: list[str] = [
|
|
19
|
+
"(Labels)",
|
|
20
|
+
"(Unresolved Labels)",
|
|
21
|
+
"(Facilities)",
|
|
22
|
+
"(Shops)",
|
|
23
|
+
"Facilities",
|
|
24
|
+
"Shops",
|
|
25
|
+
"(Barriers)",
|
|
26
|
+
"(Spaces)",
|
|
27
|
+
"(Backgrounds)",
|
|
28
|
+
"(Background)",
|
|
29
|
+
]
|
|
30
|
+
for layer_name in layer_names:
|
|
31
|
+
find_layer_and_change_to_layer(group, layer_name)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def find_layer_and_change_to_layer(group: inkex.Group, name: str) -> None:
|
|
35
|
+
for child in list(group):
|
|
36
|
+
if isinstance(child, inkex.Group) and child.label == name:
|
|
37
|
+
group_to_layer(child)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def group_to_layer(group: inkex.Group) -> inkex.Layer:
|
|
41
|
+
group_mode = group.get("inkscape:groupmode", None)
|
|
42
|
+
if group_mode != "layer":
|
|
43
|
+
group.set("inkscape:groupmode", "layer")
|
|
44
|
+
return group
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
__all__: list[str] = ["fixup_tree_layer", "fixup_tree_layer_content"]
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# coding=utf-8
|
|
3
|
+
|
|
4
|
+
import inkex
|
|
5
|
+
|
|
6
|
+
from .types import AddressString, NameString, XY
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def preferInt(n: float) -> float | int:
|
|
10
|
+
r: float = round(n)
|
|
11
|
+
return r if r == n else int(n)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def draw_label(text: str, size: float, x: float = 0, y: float = 0) -> inkex.TextElement:
|
|
15
|
+
t = inkex.TextElement()
|
|
16
|
+
t.label = text
|
|
17
|
+
t.update(
|
|
18
|
+
**{
|
|
19
|
+
"font-family": "'Noto Sans'",
|
|
20
|
+
# "-inkscape-font-specification": "'Noto Sans Ultra-Light'",
|
|
21
|
+
"font-size": f"{size}",
|
|
22
|
+
"font-weight": "200",
|
|
23
|
+
"line-height": "1.5",
|
|
24
|
+
"text-anchor": "middle",
|
|
25
|
+
"text-align": "center",
|
|
26
|
+
"writing-mode": "lr-tb",
|
|
27
|
+
"direction": "ltr",
|
|
28
|
+
"fill": "#000000",
|
|
29
|
+
"stroke": "none",
|
|
30
|
+
}
|
|
31
|
+
)
|
|
32
|
+
txts: list[str] = text.split()
|
|
33
|
+
for txt in txts:
|
|
34
|
+
ts = inkex.Tspan()
|
|
35
|
+
ts.text = txt
|
|
36
|
+
ts.update(
|
|
37
|
+
**{
|
|
38
|
+
"dy": 0,
|
|
39
|
+
"sodipodi:role": "line",
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
t.append(ts)
|
|
43
|
+
return t
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def draw_name(text: str, x: float = 0, y: float = 0) -> inkex.TextElement:
|
|
47
|
+
t = inkex.TextElement()
|
|
48
|
+
t.label = text
|
|
49
|
+
t.update(
|
|
50
|
+
**{
|
|
51
|
+
"x": round(x),
|
|
52
|
+
"y": round(y),
|
|
53
|
+
"font-size": "2px",
|
|
54
|
+
"text-anchor": "middle",
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
ts = inkex.Tspan()
|
|
58
|
+
ts.text = text
|
|
59
|
+
t.append(ts)
|
|
60
|
+
return t
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def redraw_name(
|
|
64
|
+
t: inkex.TextElement, text: str, x: float = 0, y: float = 0
|
|
65
|
+
) -> inkex.TextElement:
|
|
66
|
+
t.label = text
|
|
67
|
+
t.update(
|
|
68
|
+
**{
|
|
69
|
+
"x": round(x),
|
|
70
|
+
"y": round(y),
|
|
71
|
+
"font-size": "2px",
|
|
72
|
+
"text-anchor": "middle",
|
|
73
|
+
}
|
|
74
|
+
)
|
|
75
|
+
first = None
|
|
76
|
+
for ts in t:
|
|
77
|
+
if first is None:
|
|
78
|
+
first = ts
|
|
79
|
+
else:
|
|
80
|
+
t.remove(ts)
|
|
81
|
+
if first is not None:
|
|
82
|
+
first.text = text
|
|
83
|
+
else:
|
|
84
|
+
ts = inkex.Tspan()
|
|
85
|
+
ts.text = text
|
|
86
|
+
t.append(ts)
|
|
87
|
+
return t
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def remove_children_by_label(
|
|
91
|
+
group: inkex.Group, label: str
|
|
92
|
+
) -> inkex.TextElement | None:
|
|
93
|
+
for child in group:
|
|
94
|
+
if not isinstance(child, inkex.TextElement):
|
|
95
|
+
# XXX msg
|
|
96
|
+
continue
|
|
97
|
+
if child.label == label:
|
|
98
|
+
group.remove(child)
|
|
99
|
+
return child
|
|
100
|
+
return None
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def move_name(
|
|
104
|
+
old_group: inkex.Group,
|
|
105
|
+
new_group: inkex.Group,
|
|
106
|
+
old_name: str,
|
|
107
|
+
new_name: str,
|
|
108
|
+
x: float,
|
|
109
|
+
y: float,
|
|
110
|
+
) -> inkex.Group | None:
|
|
111
|
+
remove_children_by_label(new_group, new_name)
|
|
112
|
+
child = remove_children_by_label(old_group, old_name)
|
|
113
|
+
t = (
|
|
114
|
+
draw_name(new_name, x, y)
|
|
115
|
+
if child is None or not isinstance(child, inkex.TextElement)
|
|
116
|
+
else redraw_name(child, new_name, x, y)
|
|
117
|
+
)
|
|
118
|
+
new_group.append(t)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
type NameEntry = tuple[None | AddressString, NameString, XY]
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def read_name(node: inkex.BaseElement) -> None | NameEntry:
|
|
125
|
+
if not isinstance(node, inkex.TextElement):
|
|
126
|
+
return None
|
|
127
|
+
assert isinstance(node.label, str)
|
|
128
|
+
name_and_address: list[str] = node.label.split(" @ ")
|
|
129
|
+
name: str = name_and_address[0]
|
|
130
|
+
if len(name_and_address) == 1:
|
|
131
|
+
address = None
|
|
132
|
+
else:
|
|
133
|
+
address: str = name_and_address[1]
|
|
134
|
+
|
|
135
|
+
# check "unmoved" node (x == 0 and y == 0 and transform is None)
|
|
136
|
+
(x, y) = (node.x, node.y)
|
|
137
|
+
tx = node.transform
|
|
138
|
+
p = (
|
|
139
|
+
inkex.Vector2d(0, 0)
|
|
140
|
+
if (x == 0 and y == 0 and tx is None)
|
|
141
|
+
else inkex.Vector2d(x, y)
|
|
142
|
+
if tx is None
|
|
143
|
+
else tx.apply_to_point(inkex.Vector2d(x, y))
|
|
144
|
+
)
|
|
145
|
+
return (address, name, (round(p.x), round(p.y)))
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def move_label(
|
|
149
|
+
old_group: inkex.Group,
|
|
150
|
+
new_group: inkex.Group,
|
|
151
|
+
old_name: str,
|
|
152
|
+
new_name: str,
|
|
153
|
+
x: None | float = None,
|
|
154
|
+
y: None | float = None,
|
|
155
|
+
) -> inkex.Group | None:
|
|
156
|
+
remove_children_by_label(new_group, new_name)
|
|
157
|
+
child = remove_children_by_label(old_group, old_name)
|
|
158
|
+
if child is None:
|
|
159
|
+
return
|
|
160
|
+
child.label = new_name
|
|
161
|
+
child.transform = None
|
|
162
|
+
child.set("x", None)
|
|
163
|
+
child.set("y", None)
|
|
164
|
+
new_group.append(child)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
__all__ = [draw_label, draw_name, move_name, read_name, redraw_name, move_label]
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
import inkex
|
|
4
|
+
|
|
5
|
+
import daijimaps
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# XXX show log?
|
|
9
|
+
def renumber_group(node: inkex.Group):
|
|
10
|
+
ngroups = 0
|
|
11
|
+
nnongroups = 0
|
|
12
|
+
nnames = 0
|
|
13
|
+
m = re.compile("^[A-Z].*$")
|
|
14
|
+
for child in list(node):
|
|
15
|
+
if not daijimaps.isBaseElement(child):
|
|
16
|
+
continue
|
|
17
|
+
if isinstance(child, inkex.Group):
|
|
18
|
+
ngroups = ngroups + 1
|
|
19
|
+
else:
|
|
20
|
+
nnongroups = nnongroups + 1
|
|
21
|
+
label = child.label
|
|
22
|
+
if label is not None and m.match(label):
|
|
23
|
+
nnames = nnames + 1
|
|
24
|
+
# non-mixed children => renumber children
|
|
25
|
+
if (ngroups == 0 and nnames == 0) or (nnongroups == 0 and nnames == 0):
|
|
26
|
+
for idx, child in enumerate(list(node)):
|
|
27
|
+
if not daijimaps.isBaseElement(child):
|
|
28
|
+
continue
|
|
29
|
+
child.label = idx + 1
|
|
30
|
+
# all children are group => recurse into children
|
|
31
|
+
if nnongroups == 0:
|
|
32
|
+
for child in list(node):
|
|
33
|
+
if not daijimaps.isGroup(child):
|
|
34
|
+
continue
|
|
35
|
+
renumber_group(child)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
__all__ = [renumber_group]
|