summaryrefslogtreecommitdiff
path: root/tools/parse-layout.js
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2025-02-23 18:37:17 +0100
committerTor Andersson <tor@ccxvii.net>2025-03-08 16:32:19 +0100
commitfe2bc3961ec3b3164786074b37e36581b81fa68c (patch)
treebfc80bc4fb161e83f290da6294f0bffe9116500b /tools/parse-layout.js
parenta4c2b8458d1059c373c4a714bce0b5f68a3ce20f (diff)
downloadland-and-freedom-fe2bc3961ec3b3164786074b37e36581b81fa68c.tar.gz
New client and client data processing tools.
Diffstat (limited to 'tools/parse-layout.js')
-rw-r--r--tools/parse-layout.js167
1 files changed, 167 insertions, 0 deletions
diff --git a/tools/parse-layout.js b/tools/parse-layout.js
new file mode 100644
index 0000000..5dcf4f8
--- /dev/null
+++ b/tools/parse-layout.js
@@ -0,0 +1,167 @@
+const fs = require("fs")
+
+const { round, floor, ceil } = Math
+
+let boxes = {}
+let nodes = []
+let edges = []
+let mode, name, x, y, w, h, cx, cy, rx, ry, x2, y2
+let scale = 1
+
+function flush() {
+ if (mode === 'path') {
+ edges.push({ x1: x, y1: y, x2, y2 })
+ }
+ if (mode === 'rect') {
+ boxes[name] = [ x * scale |0, y * scale |0, w * scale |0, h * scale |0 ]
+ nodes.push({ name, x: x + w/2, y: y + h/2 })
+ }
+ if (mode === 'circle') {
+ x = cx - rx
+ y = cy - ry
+ w = rx * 2
+ h = ry * 2
+ boxes[name] = [ x * scale |0, y * scale |0, w * scale |0, h * scale |0 ]
+ nodes.push({ name, x: cx, y: cy })
+ }
+ x = y = x2 = y2 = w = h = cx = cy = rx = ry = 0
+ name = null
+}
+
+function parse_path_data(path) {
+ let cx = 0
+ let cy = 0
+ let abs = 0
+ for (let i = 0; i < path.length;) {
+ switch (path[i]) {
+ case 'M':
+ x = cx = Number(path[i+1])
+ y = cy = Number(path[i+2])
+ i += 3
+ abs = true
+ break
+ case 'm':
+ x = cx = cx + Number(path[i+1])
+ y = cy = cy + Number(path[i+2])
+ i += 3
+ abs = false
+ break
+ case 'C':
+ x2 = cx = Number(path[i+5])
+ y2 = cy = Number(path[i+6])
+ i += 7
+ abs = true
+ break
+ case 'L':
+ i += 1
+ abs = true
+ break
+ case 'H':
+ x2 = cx = Number(path[i+1])
+ i += 2
+ abs = true
+ break
+ case 'V':
+ y2 = cy = Number(path[i+1])
+ i += 2
+ abs = true
+ break
+ case 'c':
+ x2 = cx = cx + Number(path[i+5])
+ y2 = cy = cy + Number(path[i+6])
+ i += 7
+ break
+ case 'l':
+ i += 1
+ abs = false
+ break
+ case 'h':
+ x2 = cx = cx + Number(path[i+1])
+ i += 2
+ abs = false
+ break
+ case 'v':
+ y2 = cy = cy + Number(path[i+1])
+ i += 2
+ abs = false
+ break
+ default:
+ if (abs) {
+ x2 = cx = Number(path[i+0])
+ y2 = cy = Number(path[i+1])
+ } else {
+ x2 = cx = cx + Number(path[i+0])
+ y2 = cy = cy + Number(path[i+1])
+ }
+ i += 2
+ break
+ }
+ }
+}
+
+for (let line of fs.readFileSync("tools/layout.svg", "utf-8").split("\n")) {
+ line = line.trim()
+ if (line.startsWith("<rect")) {
+ flush()
+ mode = "rect"
+ x = y = w = h = 0
+ } else if (line.startsWith("<ellipse") || line.startsWith("<circle")) {
+ flush()
+ mode = "circle"
+ cx = cy = rx = ry = 0
+ } else if (line.startsWith("<path")) {
+ flush()
+ mode = "path"
+ } else if (line.startsWith('x="'))
+ x = round(Number(line.split('"')[1]))
+ else if (line.startsWith('y="'))
+ y = round(Number(line.split('"')[1]))
+ else if (line.startsWith('width="'))
+ w = round(Number(line.split('"')[1]))
+ else if (line.startsWith('height="'))
+ h = round(Number(line.split('"')[1]))
+ else if (line.startsWith('cx="'))
+ cx = round(Number(line.split('"')[1]))
+ else if (line.startsWith('cy="'))
+ cy = round(Number(line.split('"')[1]))
+ else if (line.startsWith('r="'))
+ rx = ry = round(Number(line.split('"')[1]))
+ else if (line.startsWith('rx="'))
+ rx = round(Number(line.split('"')[1]))
+ else if (line.startsWith('ry="'))
+ ry = round(Number(line.split('"')[1]))
+ else if (line.startsWith('inkscape:label="'))
+ name = line.split('"')[1]
+ else if (line.startsWith('d="'))
+ parse_path_data(line.split('"')[1].split(/[ ,]/))
+}
+
+flush()
+
+console.log("const boxes = {")
+for (let key in boxes)
+ console.log("\t\"" + key + "\": " + JSON.stringify(boxes[key]) + ",")
+console.log("}")
+
+function find_closest_node(x, y) {
+ let nd = Infinity, nn = null
+
+ for (let n of nodes) {
+ let d = Math.hypot(n.x - x, n.y - y)
+ if (d < nd) {
+ nd = d
+ nn = n.name
+ }
+ }
+
+ if (!nn)
+ console.log("NOT FOUND", x, y)
+
+ return nn
+}
+
+for (let e of edges) {
+ let n1 = find_closest_node(e.x1, e.y1)
+ let n2 = find_closest_node(e.x2, e.y2)
+ console.log(`edge("${n1}", "${n2}", ${e.x1|0}, ${e.y1|0}, ${e.x2|0}, ${e.y2|0})`)
+}