@kerros/schema 0.0.0-stage → 0.1.0-rc.2

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../../node_modules/splaytree/dist/splaytree.js","../../../node_modules/robust-predicates/esm/util.js","../../../node_modules/robust-predicates/esm/orient2d.js","../../../node_modules/polygon-clipping/dist/polygon-clipping.esm.js","../../../src/model/types.ts","../../../src/model/portals.ts","../../../src/model/ontology.ts","../../../src/model/passages.ts","../../../src/model/topology.ts","../../../src/model/vertical.ts","../../../src/model/routeClearance.ts","../../../src/model/navigation.ts","../../../src/model/materials.ts","../../../src/model/precision.ts","../../../src/model/validate.ts","../../../src/model/boundaries.ts","../../../src/model/geometry.ts","../../../src/model/spaces.ts","../../../src/model/inference.ts","../../../src/model/factory.ts","../../../src/model/coverage.ts","../../../src/model/project.ts","../../../src/model/document.ts","../../../src/model/authoring.ts","../../../src/model/mutations.ts","../../../src/model/roomNavigation.ts"],"sourcesContent":["class f {\n constructor(t, e) {\n this.next = null, this.key = t, this.data = e, this.left = null, this.right = null;\n }\n}\nfunction d(n, t) {\n return n > t ? 1 : n < t ? -1 : 0;\n}\nfunction u(n, t, e) {\n const r = new f(null, null);\n let l = r, i = r;\n for (; ; ) {\n const o = e(n, t.key);\n if (o < 0) {\n if (t.left === null) break;\n if (e(n, t.left.key) < 0) {\n const s = t.left;\n if (t.left = s.right, s.right = t, t = s, t.left === null) break;\n }\n i.left = t, i = t, t = t.left;\n } else if (o > 0) {\n if (t.right === null) break;\n if (e(n, t.right.key) > 0) {\n const s = t.right;\n if (t.right = s.left, s.left = t, t = s, t.right === null) break;\n }\n l.right = t, l = t, t = t.right;\n } else break;\n }\n return l.right = t.left, i.left = t.right, t.left = r.right, t.right = r.left, t;\n}\nfunction c(n, t, e, r) {\n const l = new f(n, t);\n if (e === null)\n return l.left = l.right = null, l;\n e = u(n, e, r);\n const i = r(n, e.key);\n return i < 0 ? (l.left = e.left, l.right = e, e.left = null) : i >= 0 && (l.right = e.right, l.left = e, e.right = null), l;\n}\nfunction m(n, t, e) {\n let r = null, l = null;\n if (t) {\n t = u(n, t, e);\n const i = e(t.key, n);\n i === 0 ? (r = t.left, l = t.right) : i < 0 ? (l = t.right, t.right = null, r = t) : (r = t.left, t.left = null, l = t);\n }\n return { left: r, right: l };\n}\nfunction w(n, t, e) {\n return t === null ? n : (n === null || (t = u(n.key, t, e), t.left = n), t);\n}\nfunction _(n, t, e, r, l) {\n if (n) {\n r(`${t}${e ? \"└── \" : \"├── \"}${l(n)}\n`);\n const i = t + (e ? \" \" : \"│ \");\n n.left && _(n.left, i, !1, r, l), n.right && _(n.right, i, !0, r, l);\n }\n}\nclass z {\n constructor(t = d) {\n this._root = null, this._size = 0, this._comparator = t;\n }\n /**\n * Inserts a key, allows duplicates\n */\n insert(t, e) {\n return this._size++, this._root = c(t, e, this._root, this._comparator);\n }\n /**\n * Adds a key, if it is not present in the tree\n */\n add(t, e) {\n const r = new f(t, e);\n this._root === null && (r.left = r.right = null, this._size++, this._root = r);\n const l = this._comparator, i = u(t, this._root, l), o = l(t, i.key);\n return o === 0 ? this._root = i : (o < 0 ? (r.left = i.left, r.right = i, i.left = null) : o > 0 && (r.right = i.right, r.left = i, i.right = null), this._size++, this._root = r), this._root;\n }\n /**\n * @param {Key} key\n * @return {Node|null}\n */\n remove(t) {\n this._root = this._remove(t, this._root, this._comparator);\n }\n /**\n * Deletes i from the tree if it's there\n */\n _remove(t, e, r) {\n let l;\n return e === null ? null : (e = u(t, e, r), r(t, e.key) === 0 ? (e.left === null ? l = e.right : (l = u(t, e.left, r), l.right = e.right), this._size--, l) : e);\n }\n /**\n * Removes and returns the node with smallest key\n */\n pop() {\n let t = this._root;\n if (t) {\n for (; t.left; ) t = t.left;\n return this._root = u(t.key, this._root, this._comparator), this._root = this._remove(t.key, this._root, this._comparator), { key: t.key, data: t.data };\n }\n return null;\n }\n /**\n * Find without splaying\n */\n findStatic(t) {\n let e = this._root;\n const r = this._comparator;\n for (; e; ) {\n const l = r(t, e.key);\n if (l === 0) return e;\n l < 0 ? e = e.left : e = e.right;\n }\n return null;\n }\n find(t) {\n return this._root && (this._root = u(t, this._root, this._comparator), this._comparator(t, this._root.key) !== 0) ? null : this._root;\n }\n contains(t) {\n let e = this._root;\n const r = this._comparator;\n for (; e; ) {\n const l = r(t, e.key);\n if (l === 0) return !0;\n l < 0 ? e = e.left : e = e.right;\n }\n return !1;\n }\n forEach(t, e) {\n let r = this._root;\n const l = [];\n let i = !1;\n for (; !i; )\n r !== null ? (l.push(r), r = r.left) : l.length !== 0 ? (r = l.pop(), t.call(e, r), r = r.right) : i = !0;\n return this;\n }\n /**\n * Walk key range from `low` to `high`. Stops if `fn` returns a value.\n */\n range(t, e, r, l) {\n const i = [], o = this._comparator;\n let s = this._root, h;\n for (; i.length !== 0 || s; )\n if (s)\n i.push(s), s = s.left;\n else {\n if (s = i.pop(), h = o(s.key, e), h > 0)\n break;\n if (o(s.key, t) >= 0 && r.call(l, s))\n return this;\n s = s.right;\n }\n return this;\n }\n /**\n * Returns array of keys\n */\n keys() {\n const t = [];\n return this.forEach(({ key: e }) => {\n t.push(e);\n }), t;\n }\n /**\n * Returns array of all the data in the nodes\n */\n values() {\n const t = [];\n return this.forEach(({ data: e }) => {\n t.push(e);\n }), t;\n }\n min() {\n return this._root ? this.minNode(this._root).key : null;\n }\n max() {\n return this._root ? this.maxNode(this._root).key : null;\n }\n minNode(t = this._root) {\n if (t) for (; t.left; ) t = t.left;\n return t;\n }\n maxNode(t = this._root) {\n if (t) for (; t.right; ) t = t.right;\n return t;\n }\n /**\n * Returns node at given index\n */\n at(t) {\n let e = this._root, r = !1, l = 0;\n const i = [];\n for (; !r; )\n if (e)\n i.push(e), e = e.left;\n else if (i.length > 0) {\n if (e = i.pop(), l === t) return e;\n l++, e = e.right;\n } else r = !0;\n return null;\n }\n next(t) {\n let e = this._root, r = null;\n if (t.right) {\n for (r = t.right; r.left; ) r = r.left;\n return r;\n }\n const l = this._comparator;\n for (; e; ) {\n const i = l(t.key, e.key);\n if (i === 0) break;\n i < 0 ? (r = e, e = e.left) : e = e.right;\n }\n return r;\n }\n prev(t) {\n let e = this._root, r = null;\n if (t.left !== null) {\n for (r = t.left; r.right; ) r = r.right;\n return r;\n }\n const l = this._comparator;\n for (; e; ) {\n const i = l(t.key, e.key);\n if (i === 0) break;\n i < 0 ? e = e.left : (r = e, e = e.right);\n }\n return r;\n }\n clear() {\n return this._root = null, this._size = 0, this;\n }\n toList() {\n return k(this._root);\n }\n /**\n * Bulk-load items. Both array have to be same size\n */\n load(t, e = [], r = !1) {\n let l = t.length;\n const i = this._comparator;\n if (r && g(t, e, 0, l - 1, i), this._root === null)\n this._root = a(t, e, 0, l), this._size = l;\n else {\n const o = y(\n this.toList(),\n x(t, e),\n i\n );\n l = this._size + l, this._root = p({ head: o }, 0, l);\n }\n return this;\n }\n isEmpty() {\n return this._root === null;\n }\n get size() {\n return this._size;\n }\n get root() {\n return this._root;\n }\n toString(t = (e) => String(e.key)) {\n const e = [];\n return _(this._root, \"\", !0, (r) => e.push(r), t), e.join(\"\");\n }\n update(t, e, r) {\n const l = this._comparator;\n let { left: i, right: o } = m(t, this._root, l);\n l(t, e) < 0 ? o = c(e, r, o, l) : i = c(e, r, i, l), this._root = w(i, o, l);\n }\n split(t) {\n return m(t, this._root, this._comparator);\n }\n *[Symbol.iterator]() {\n let t = this._root;\n const e = [];\n let r = !1;\n for (; !r; )\n t !== null ? (e.push(t), t = t.left) : e.length !== 0 ? (t = e.pop(), yield t, t = t.right) : r = !0;\n }\n}\nfunction a(n, t, e, r) {\n const l = r - e;\n if (l > 0) {\n const i = e + Math.floor(l / 2), o = n[i], s = t[i], h = new f(o, s);\n return h.left = a(n, t, e, i), h.right = a(n, t, i + 1, r), h;\n }\n return null;\n}\nfunction x(n, t) {\n const e = new f(null, null);\n let r = e;\n for (let l = 0; l < n.length; l++)\n r = r.next = new f(n[l], t[l]);\n return r.next = null, e.next;\n}\nfunction k(n) {\n let t = n;\n const e = [];\n let r = !1;\n const l = new f(null, null);\n let i = l;\n for (; !r; )\n t ? (e.push(t), t = t.left) : e.length > 0 ? (t = i = i.next = e.pop(), t = t.right) : r = !0;\n return i.next = null, l.next;\n}\nfunction p(n, t, e) {\n const r = e - t;\n if (r > 0) {\n const l = t + Math.floor(r / 2), i = p(n, t, l), o = n.head;\n return o.left = i, n.head = n.head.next, o.right = p(n, l + 1, e), o;\n }\n return null;\n}\nfunction y(n, t, e) {\n const r = new f(null, null);\n let l = r, i = n, o = t;\n for (; i !== null && o !== null; )\n e(i.key, o.key) < 0 ? (l.next = i, i = i.next) : (l.next = o, o = o.next), l = l.next;\n return i !== null ? l.next = i : o !== null && (l.next = o), r.next;\n}\nfunction g(n, t, e, r, l) {\n if (e >= r) return;\n const i = n[e + r >> 1];\n let o = e - 1, s = r + 1;\n for (; ; ) {\n do\n o++;\n while (l(n[o], i) < 0);\n do\n s--;\n while (l(n[s], i) > 0);\n if (o >= s) break;\n let h = n[o];\n n[o] = n[s], n[s] = h, h = t[o], t[o] = t[s], t[s] = h;\n }\n g(n, t, e, s, l), g(n, t, s + 1, r, l);\n}\nexport {\n z as default\n};\n//# sourceMappingURL=splaytree.js.map\n","export const epsilon = 1.1102230246251565e-16;\nexport const splitter = 134217729;\nexport const resulterrbound = (3 + 8 * epsilon) * epsilon;\n\n// fast_expansion_sum_zeroelim routine from original code\nexport function sum(elen, e, flen, f, h) {\n let Q, Qnew, hh, bvirt;\n let enow = e[0];\n let fnow = f[0];\n let eindex = 0;\n let findex = 0;\n if ((fnow > enow) === (fnow > -enow)) {\n Q = enow;\n enow = e[++eindex];\n } else {\n Q = fnow;\n fnow = f[++findex];\n }\n let hindex = 0;\n if (eindex < elen && findex < flen) {\n if ((fnow > enow) === (fnow > -enow)) {\n Qnew = enow + Q;\n hh = Q - (Qnew - enow);\n enow = e[++eindex];\n } else {\n Qnew = fnow + Q;\n hh = Q - (Qnew - fnow);\n fnow = f[++findex];\n }\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n while (eindex < elen && findex < flen) {\n if ((fnow > enow) === (fnow > -enow)) {\n Qnew = Q + enow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (enow - bvirt);\n enow = e[++eindex];\n } else {\n Qnew = Q + fnow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (fnow - bvirt);\n fnow = f[++findex];\n }\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n }\n while (eindex < elen) {\n Qnew = Q + enow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (enow - bvirt);\n enow = e[++eindex];\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n while (findex < flen) {\n Qnew = Q + fnow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (fnow - bvirt);\n fnow = f[++findex];\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n if (Q !== 0 || hindex === 0) {\n h[hindex++] = Q;\n }\n return hindex;\n}\n\nexport function sum_three(alen, a, blen, b, clen, c, tmp, out) {\n return sum(sum(alen, a, blen, b, tmp), tmp, clen, c, out);\n}\n\n// scale_expansion_zeroelim routine from oritinal code\nexport function scale(elen, e, b, h) {\n let Q, sum, hh, product1, product0;\n let bvirt, c, ahi, alo, bhi, blo;\n\n c = splitter * b;\n bhi = c - (c - b);\n blo = b - bhi;\n let enow = e[0];\n Q = enow * b;\n c = splitter * enow;\n ahi = c - (c - enow);\n alo = enow - ahi;\n hh = alo * blo - (Q - ahi * bhi - alo * bhi - ahi * blo);\n let hindex = 0;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n for (let i = 1; i < elen; i++) {\n enow = e[i];\n product1 = enow * b;\n c = splitter * enow;\n ahi = c - (c - enow);\n alo = enow - ahi;\n product0 = alo * blo - (product1 - ahi * bhi - alo * bhi - ahi * blo);\n sum = Q + product0;\n bvirt = sum - Q;\n hh = Q - (sum - bvirt) + (product0 - bvirt);\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n Q = product1 + sum;\n hh = sum - (Q - product1);\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n if (Q !== 0 || hindex === 0) {\n h[hindex++] = Q;\n }\n return hindex;\n}\n\nexport function negate(elen, e) {\n for (let i = 0; i < elen; i++) e[i] = -e[i];\n return elen;\n}\n\nexport function estimate(elen, e) {\n let Q = e[0];\n for (let i = 1; i < elen; i++) Q += e[i];\n return Q;\n}\n\nexport function vec(n) {\n return new Float64Array(n);\n}\n","import {epsilon, splitter, resulterrbound, estimate, vec, sum} from './util.js';\n\nconst ccwerrboundA = (3 + 16 * epsilon) * epsilon;\nconst ccwerrboundB = (2 + 12 * epsilon) * epsilon;\nconst ccwerrboundC = (9 + 64 * epsilon) * epsilon * epsilon;\n\nconst B = vec(4);\nconst C1 = vec(8);\nconst C2 = vec(12);\nconst D = vec(16);\nconst u = vec(4);\n\nfunction orient2dadapt(ax, ay, bx, by, cx, cy, detsum) {\n let acxtail, acytail, bcxtail, bcytail;\n let bvirt, c, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t1, t0, u3;\n\n const acx = ax - cx;\n const bcx = bx - cx;\n const acy = ay - cy;\n const bcy = by - cy;\n\n s1 = acx * bcy;\n c = splitter * acx;\n ahi = c - (c - acx);\n alo = acx - ahi;\n c = splitter * bcy;\n bhi = c - (c - bcy);\n blo = bcy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = acy * bcx;\n c = splitter * acy;\n ahi = c - (c - acy);\n alo = acy - ahi;\n c = splitter * bcx;\n bhi = c - (c - bcx);\n blo = bcx - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n B[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n B[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n B[2] = _j - (u3 - bvirt) + (_i - bvirt);\n B[3] = u3;\n\n let det = estimate(4, B);\n let errbound = ccwerrboundB * detsum;\n if (det >= errbound || -det >= errbound) {\n return det;\n }\n\n bvirt = ax - acx;\n acxtail = ax - (acx + bvirt) + (bvirt - cx);\n bvirt = bx - bcx;\n bcxtail = bx - (bcx + bvirt) + (bvirt - cx);\n bvirt = ay - acy;\n acytail = ay - (acy + bvirt) + (bvirt - cy);\n bvirt = by - bcy;\n bcytail = by - (bcy + bvirt) + (bvirt - cy);\n\n if (acxtail === 0 && acytail === 0 && bcxtail === 0 && bcytail === 0) {\n return det;\n }\n\n errbound = ccwerrboundC * detsum + resulterrbound * Math.abs(det);\n det += (acx * bcytail + bcy * acxtail) - (acy * bcxtail + bcx * acytail);\n if (det >= errbound || -det >= errbound) return det;\n\n s1 = acxtail * bcy;\n c = splitter * acxtail;\n ahi = c - (c - acxtail);\n alo = acxtail - ahi;\n c = splitter * bcy;\n bhi = c - (c - bcy);\n blo = bcy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = acytail * bcx;\n c = splitter * acytail;\n ahi = c - (c - acytail);\n alo = acytail - ahi;\n c = splitter * bcx;\n bhi = c - (c - bcx);\n blo = bcx - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n u[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n u[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n u[2] = _j - (u3 - bvirt) + (_i - bvirt);\n u[3] = u3;\n const C1len = sum(4, B, 4, u, C1);\n\n s1 = acx * bcytail;\n c = splitter * acx;\n ahi = c - (c - acx);\n alo = acx - ahi;\n c = splitter * bcytail;\n bhi = c - (c - bcytail);\n blo = bcytail - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = acy * bcxtail;\n c = splitter * acy;\n ahi = c - (c - acy);\n alo = acy - ahi;\n c = splitter * bcxtail;\n bhi = c - (c - bcxtail);\n blo = bcxtail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n u[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n u[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n u[2] = _j - (u3 - bvirt) + (_i - bvirt);\n u[3] = u3;\n const C2len = sum(C1len, C1, 4, u, C2);\n\n s1 = acxtail * bcytail;\n c = splitter * acxtail;\n ahi = c - (c - acxtail);\n alo = acxtail - ahi;\n c = splitter * bcytail;\n bhi = c - (c - bcytail);\n blo = bcytail - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = acytail * bcxtail;\n c = splitter * acytail;\n ahi = c - (c - acytail);\n alo = acytail - ahi;\n c = splitter * bcxtail;\n bhi = c - (c - bcxtail);\n blo = bcxtail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n u[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n u[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n u[2] = _j - (u3 - bvirt) + (_i - bvirt);\n u[3] = u3;\n const Dlen = sum(C2len, C2, 4, u, D);\n\n return D[Dlen - 1];\n}\n\nexport function orient2d(ax, ay, bx, by, cx, cy) {\n const detleft = (ay - cy) * (bx - cx);\n const detright = (ax - cx) * (by - cy);\n const det = detleft - detright;\n\n const detsum = Math.abs(detleft + detright);\n if (Math.abs(det) >= ccwerrboundA * detsum) return det;\n\n return -orient2dadapt(ax, ay, bx, by, cx, cy, detsum);\n}\n\nexport function orient2dfast(ax, ay, bx, by, cx, cy) {\n return (ay - cy) * (bx - cx) - (ax - cx) * (by - cy);\n}\n","import SplayTree from 'splaytree';\nimport { orient2d } from 'robust-predicates';\n\n/**\n * A bounding box has the format:\n *\n * { ll: { x: xmin, y: ymin }, ur: { x: xmax, y: ymax } }\n *\n */\n\nconst isInBbox = (bbox, point) => {\n return bbox.ll.x <= point.x && point.x <= bbox.ur.x && bbox.ll.y <= point.y && point.y <= bbox.ur.y;\n};\n\n/* Returns either null, or a bbox (aka an ordered pair of points)\n * If there is only one point of overlap, a bbox with identical points\n * will be returned */\nconst getBboxOverlap = (b1, b2) => {\n // check if the bboxes overlap at all\n if (b2.ur.x < b1.ll.x || b1.ur.x < b2.ll.x || b2.ur.y < b1.ll.y || b1.ur.y < b2.ll.y) return null;\n\n // find the middle two X values\n const lowerX = b1.ll.x < b2.ll.x ? b2.ll.x : b1.ll.x;\n const upperX = b1.ur.x < b2.ur.x ? b1.ur.x : b2.ur.x;\n\n // find the middle two Y values\n const lowerY = b1.ll.y < b2.ll.y ? b2.ll.y : b1.ll.y;\n const upperY = b1.ur.y < b2.ur.y ? b1.ur.y : b2.ur.y;\n\n // put those middle values together to get the overlap\n return {\n ll: {\n x: lowerX,\n y: lowerY\n },\n ur: {\n x: upperX,\n y: upperY\n }\n };\n};\n\n/* Javascript doesn't do integer math. Everything is\n * floating point with percision Number.EPSILON.\n *\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON\n */\n\nlet epsilon = Number.EPSILON;\n\n// IE Polyfill\nif (epsilon === undefined) epsilon = Math.pow(2, -52);\nconst EPSILON_SQ = epsilon * epsilon;\n\n/* FLP comparator */\nconst cmp = (a, b) => {\n // check if they're both 0\n if (-epsilon < a && a < epsilon) {\n if (-epsilon < b && b < epsilon) {\n return 0;\n }\n }\n\n // check if they're flp equal\n const ab = a - b;\n if (ab * ab < EPSILON_SQ * a * b) {\n return 0;\n }\n\n // normal comparison\n return a < b ? -1 : 1;\n};\n\n/**\n * This class rounds incoming values sufficiently so that\n * floating points problems are, for the most part, avoided.\n *\n * Incoming points are have their x & y values tested against\n * all previously seen x & y values. If either is 'too close'\n * to a previously seen value, it's value is 'snapped' to the\n * previously seen value.\n *\n * All points should be rounded by this class before being\n * stored in any data structures in the rest of this algorithm.\n */\n\nclass PtRounder {\n constructor() {\n this.reset();\n }\n reset() {\n this.xRounder = new CoordRounder();\n this.yRounder = new CoordRounder();\n }\n round(x, y) {\n return {\n x: this.xRounder.round(x),\n y: this.yRounder.round(y)\n };\n }\n}\nclass CoordRounder {\n constructor() {\n this.tree = new SplayTree();\n // preseed with 0 so we don't end up with values < Number.EPSILON\n this.round(0);\n }\n\n // Note: this can rounds input values backwards or forwards.\n // You might ask, why not restrict this to just rounding\n // forwards? Wouldn't that allow left endpoints to always\n // remain left endpoints during splitting (never change to\n // right). No - it wouldn't, because we snap intersections\n // to endpoints (to establish independence from the segment\n // angle for t-intersections).\n round(coord) {\n const node = this.tree.add(coord);\n const prevNode = this.tree.prev(node);\n if (prevNode !== null && cmp(node.key, prevNode.key) === 0) {\n this.tree.remove(coord);\n return prevNode.key;\n }\n const nextNode = this.tree.next(node);\n if (nextNode !== null && cmp(node.key, nextNode.key) === 0) {\n this.tree.remove(coord);\n return nextNode.key;\n }\n return coord;\n }\n}\n\n// singleton available by import\nconst rounder = new PtRounder();\n\n/* Cross Product of two vectors with first point at origin */\nconst crossProduct = (a, b) => a.x * b.y - a.y * b.x;\n\n/* Dot Product of two vectors with first point at origin */\nconst dotProduct = (a, b) => a.x * b.x + a.y * b.y;\n\n/* Comparator for two vectors with same starting point */\nconst compareVectorAngles = (basePt, endPt1, endPt2) => {\n const res = orient2d(basePt.x, basePt.y, endPt1.x, endPt1.y, endPt2.x, endPt2.y);\n if (res > 0) return -1;\n if (res < 0) return 1;\n return 0;\n};\nconst length = v => Math.sqrt(dotProduct(v, v));\n\n/* Get the sine of the angle from pShared -> pAngle to pShaed -> pBase */\nconst sineOfAngle = (pShared, pBase, pAngle) => {\n const vBase = {\n x: pBase.x - pShared.x,\n y: pBase.y - pShared.y\n };\n const vAngle = {\n x: pAngle.x - pShared.x,\n y: pAngle.y - pShared.y\n };\n return crossProduct(vAngle, vBase) / length(vAngle) / length(vBase);\n};\n\n/* Get the cosine of the angle from pShared -> pAngle to pShaed -> pBase */\nconst cosineOfAngle = (pShared, pBase, pAngle) => {\n const vBase = {\n x: pBase.x - pShared.x,\n y: pBase.y - pShared.y\n };\n const vAngle = {\n x: pAngle.x - pShared.x,\n y: pAngle.y - pShared.y\n };\n return dotProduct(vAngle, vBase) / length(vAngle) / length(vBase);\n};\n\n/* Get the x coordinate where the given line (defined by a point and vector)\n * crosses the horizontal line with the given y coordiante.\n * In the case of parrallel lines (including overlapping ones) returns null. */\nconst horizontalIntersection = (pt, v, y) => {\n if (v.y === 0) return null;\n return {\n x: pt.x + v.x / v.y * (y - pt.y),\n y: y\n };\n};\n\n/* Get the y coordinate where the given line (defined by a point and vector)\n * crosses the vertical line with the given x coordiante.\n * In the case of parrallel lines (including overlapping ones) returns null. */\nconst verticalIntersection = (pt, v, x) => {\n if (v.x === 0) return null;\n return {\n x: x,\n y: pt.y + v.y / v.x * (x - pt.x)\n };\n};\n\n/* Get the intersection of two lines, each defined by a base point and a vector.\n * In the case of parrallel lines (including overlapping ones) returns null. */\nconst intersection$1 = (pt1, v1, pt2, v2) => {\n // take some shortcuts for vertical and horizontal lines\n // this also ensures we don't calculate an intersection and then discover\n // it's actually outside the bounding box of the line\n if (v1.x === 0) return verticalIntersection(pt2, v2, pt1.x);\n if (v2.x === 0) return verticalIntersection(pt1, v1, pt2.x);\n if (v1.y === 0) return horizontalIntersection(pt2, v2, pt1.y);\n if (v2.y === 0) return horizontalIntersection(pt1, v1, pt2.y);\n\n // General case for non-overlapping segments.\n // This algorithm is based on Schneider and Eberly.\n // http://www.cimec.org.ar/~ncalvo/Schneider_Eberly.pdf - pg 244\n\n const kross = crossProduct(v1, v2);\n if (kross == 0) return null;\n const ve = {\n x: pt2.x - pt1.x,\n y: pt2.y - pt1.y\n };\n const d1 = crossProduct(ve, v1) / kross;\n const d2 = crossProduct(ve, v2) / kross;\n\n // take the average of the two calculations to minimize rounding error\n const x1 = pt1.x + d2 * v1.x,\n x2 = pt2.x + d1 * v2.x;\n const y1 = pt1.y + d2 * v1.y,\n y2 = pt2.y + d1 * v2.y;\n const x = (x1 + x2) / 2;\n const y = (y1 + y2) / 2;\n return {\n x: x,\n y: y\n };\n};\n\nclass SweepEvent {\n // for ordering sweep events in the sweep event queue\n static compare(a, b) {\n // favor event with a point that the sweep line hits first\n const ptCmp = SweepEvent.comparePoints(a.point, b.point);\n if (ptCmp !== 0) return ptCmp;\n\n // the points are the same, so link them if needed\n if (a.point !== b.point) a.link(b);\n\n // favor right events over left\n if (a.isLeft !== b.isLeft) return a.isLeft ? 1 : -1;\n\n // we have two matching left or right endpoints\n // ordering of this case is the same as for their segments\n return Segment.compare(a.segment, b.segment);\n }\n\n // for ordering points in sweep line order\n static comparePoints(aPt, bPt) {\n if (aPt.x < bPt.x) return -1;\n if (aPt.x > bPt.x) return 1;\n if (aPt.y < bPt.y) return -1;\n if (aPt.y > bPt.y) return 1;\n return 0;\n }\n\n // Warning: 'point' input will be modified and re-used (for performance)\n constructor(point, isLeft) {\n if (point.events === undefined) point.events = [this];else point.events.push(this);\n this.point = point;\n this.isLeft = isLeft;\n // this.segment, this.otherSE set by factory\n }\n link(other) {\n if (other.point === this.point) {\n throw new Error(\"Tried to link already linked events\");\n }\n const otherEvents = other.point.events;\n for (let i = 0, iMax = otherEvents.length; i < iMax; i++) {\n const evt = otherEvents[i];\n this.point.events.push(evt);\n evt.point = this.point;\n }\n this.checkForConsuming();\n }\n\n /* Do a pass over our linked events and check to see if any pair\n * of segments match, and should be consumed. */\n checkForConsuming() {\n // FIXME: The loops in this method run O(n^2) => no good.\n // Maintain little ordered sweep event trees?\n // Can we maintaining an ordering that avoids the need\n // for the re-sorting with getLeftmostComparator in geom-out?\n\n // Compare each pair of events to see if other events also match\n const numEvents = this.point.events.length;\n for (let i = 0; i < numEvents; i++) {\n const evt1 = this.point.events[i];\n if (evt1.segment.consumedBy !== undefined) continue;\n for (let j = i + 1; j < numEvents; j++) {\n const evt2 = this.point.events[j];\n if (evt2.consumedBy !== undefined) continue;\n if (evt1.otherSE.point.events !== evt2.otherSE.point.events) continue;\n evt1.segment.consume(evt2.segment);\n }\n }\n }\n getAvailableLinkedEvents() {\n // point.events is always of length 2 or greater\n const events = [];\n for (let i = 0, iMax = this.point.events.length; i < iMax; i++) {\n const evt = this.point.events[i];\n if (evt !== this && !evt.segment.ringOut && evt.segment.isInResult()) {\n events.push(evt);\n }\n }\n return events;\n }\n\n /**\n * Returns a comparator function for sorting linked events that will\n * favor the event that will give us the smallest left-side angle.\n * All ring construction starts as low as possible heading to the right,\n * so by always turning left as sharp as possible we'll get polygons\n * without uncessary loops & holes.\n *\n * The comparator function has a compute cache such that it avoids\n * re-computing already-computed values.\n */\n getLeftmostComparator(baseEvent) {\n const cache = new Map();\n const fillCache = linkedEvent => {\n const nextEvent = linkedEvent.otherSE;\n cache.set(linkedEvent, {\n sine: sineOfAngle(this.point, baseEvent.point, nextEvent.point),\n cosine: cosineOfAngle(this.point, baseEvent.point, nextEvent.point)\n });\n };\n return (a, b) => {\n if (!cache.has(a)) fillCache(a);\n if (!cache.has(b)) fillCache(b);\n const {\n sine: asine,\n cosine: acosine\n } = cache.get(a);\n const {\n sine: bsine,\n cosine: bcosine\n } = cache.get(b);\n\n // both on or above x-axis\n if (asine >= 0 && bsine >= 0) {\n if (acosine < bcosine) return 1;\n if (acosine > bcosine) return -1;\n return 0;\n }\n\n // both below x-axis\n if (asine < 0 && bsine < 0) {\n if (acosine < bcosine) return -1;\n if (acosine > bcosine) return 1;\n return 0;\n }\n\n // one above x-axis, one below\n if (bsine < asine) return -1;\n if (bsine > asine) return 1;\n return 0;\n };\n }\n}\n\n// Give segments unique ID's to get consistent sorting of\n// segments and sweep events when all else is identical\nlet segmentId = 0;\nclass Segment {\n /* This compare() function is for ordering segments in the sweep\n * line tree, and does so according to the following criteria:\n *\n * Consider the vertical line that lies an infinestimal step to the\n * right of the right-more of the two left endpoints of the input\n * segments. Imagine slowly moving a point up from negative infinity\n * in the increasing y direction. Which of the two segments will that\n * point intersect first? That segment comes 'before' the other one.\n *\n * If neither segment would be intersected by such a line, (if one\n * or more of the segments are vertical) then the line to be considered\n * is directly on the right-more of the two left inputs.\n */\n static compare(a, b) {\n const alx = a.leftSE.point.x;\n const blx = b.leftSE.point.x;\n const arx = a.rightSE.point.x;\n const brx = b.rightSE.point.x;\n\n // check if they're even in the same vertical plane\n if (brx < alx) return 1;\n if (arx < blx) return -1;\n const aly = a.leftSE.point.y;\n const bly = b.leftSE.point.y;\n const ary = a.rightSE.point.y;\n const bry = b.rightSE.point.y;\n\n // is left endpoint of segment B the right-more?\n if (alx < blx) {\n // are the two segments in the same horizontal plane?\n if (bly < aly && bly < ary) return 1;\n if (bly > aly && bly > ary) return -1;\n\n // is the B left endpoint colinear to segment A?\n const aCmpBLeft = a.comparePoint(b.leftSE.point);\n if (aCmpBLeft < 0) return 1;\n if (aCmpBLeft > 0) return -1;\n\n // is the A right endpoint colinear to segment B ?\n const bCmpARight = b.comparePoint(a.rightSE.point);\n if (bCmpARight !== 0) return bCmpARight;\n\n // colinear segments, consider the one with left-more\n // left endpoint to be first (arbitrary?)\n return -1;\n }\n\n // is left endpoint of segment A the right-more?\n if (alx > blx) {\n if (aly < bly && aly < bry) return -1;\n if (aly > bly && aly > bry) return 1;\n\n // is the A left endpoint colinear to segment B?\n const bCmpALeft = b.comparePoint(a.leftSE.point);\n if (bCmpALeft !== 0) return bCmpALeft;\n\n // is the B right endpoint colinear to segment A?\n const aCmpBRight = a.comparePoint(b.rightSE.point);\n if (aCmpBRight < 0) return 1;\n if (aCmpBRight > 0) return -1;\n\n // colinear segments, consider the one with left-more\n // left endpoint to be first (arbitrary?)\n return 1;\n }\n\n // if we get here, the two left endpoints are in the same\n // vertical plane, ie alx === blx\n\n // consider the lower left-endpoint to come first\n if (aly < bly) return -1;\n if (aly > bly) return 1;\n\n // left endpoints are identical\n // check for colinearity by using the left-more right endpoint\n\n // is the A right endpoint more left-more?\n if (arx < brx) {\n const bCmpARight = b.comparePoint(a.rightSE.point);\n if (bCmpARight !== 0) return bCmpARight;\n }\n\n // is the B right endpoint more left-more?\n if (arx > brx) {\n const aCmpBRight = a.comparePoint(b.rightSE.point);\n if (aCmpBRight < 0) return 1;\n if (aCmpBRight > 0) return -1;\n }\n if (arx !== brx) {\n // are these two [almost] vertical segments with opposite orientation?\n // if so, the one with the lower right endpoint comes first\n const ay = ary - aly;\n const ax = arx - alx;\n const by = bry - bly;\n const bx = brx - blx;\n if (ay > ax && by < bx) return 1;\n if (ay < ax && by > bx) return -1;\n }\n\n // we have colinear segments with matching orientation\n // consider the one with more left-more right endpoint to be first\n if (arx > brx) return 1;\n if (arx < brx) return -1;\n\n // if we get here, two two right endpoints are in the same\n // vertical plane, ie arx === brx\n\n // consider the lower right-endpoint to come first\n if (ary < bry) return -1;\n if (ary > bry) return 1;\n\n // right endpoints identical as well, so the segments are idential\n // fall back on creation order as consistent tie-breaker\n if (a.id < b.id) return -1;\n if (a.id > b.id) return 1;\n\n // identical segment, ie a === b\n return 0;\n }\n\n /* Warning: a reference to ringWindings input will be stored,\n * and possibly will be later modified */\n constructor(leftSE, rightSE, rings, windings) {\n this.id = ++segmentId;\n this.leftSE = leftSE;\n leftSE.segment = this;\n leftSE.otherSE = rightSE;\n this.rightSE = rightSE;\n rightSE.segment = this;\n rightSE.otherSE = leftSE;\n this.rings = rings;\n this.windings = windings;\n // left unset for performance, set later in algorithm\n // this.ringOut, this.consumedBy, this.prev\n }\n static fromRing(pt1, pt2, ring) {\n let leftPt, rightPt, winding;\n\n // ordering the two points according to sweep line ordering\n const cmpPts = SweepEvent.comparePoints(pt1, pt2);\n if (cmpPts < 0) {\n leftPt = pt1;\n rightPt = pt2;\n winding = 1;\n } else if (cmpPts > 0) {\n leftPt = pt2;\n rightPt = pt1;\n winding = -1;\n } else throw new Error(`Tried to create degenerate segment at [${pt1.x}, ${pt1.y}]`);\n const leftSE = new SweepEvent(leftPt, true);\n const rightSE = new SweepEvent(rightPt, false);\n return new Segment(leftSE, rightSE, [ring], [winding]);\n }\n\n /* When a segment is split, the rightSE is replaced with a new sweep event */\n replaceRightSE(newRightSE) {\n this.rightSE = newRightSE;\n this.rightSE.segment = this;\n this.rightSE.otherSE = this.leftSE;\n this.leftSE.otherSE = this.rightSE;\n }\n bbox() {\n const y1 = this.leftSE.point.y;\n const y2 = this.rightSE.point.y;\n return {\n ll: {\n x: this.leftSE.point.x,\n y: y1 < y2 ? y1 : y2\n },\n ur: {\n x: this.rightSE.point.x,\n y: y1 > y2 ? y1 : y2\n }\n };\n }\n\n /* A vector from the left point to the right */\n vector() {\n return {\n x: this.rightSE.point.x - this.leftSE.point.x,\n y: this.rightSE.point.y - this.leftSE.point.y\n };\n }\n isAnEndpoint(pt) {\n return pt.x === this.leftSE.point.x && pt.y === this.leftSE.point.y || pt.x === this.rightSE.point.x && pt.y === this.rightSE.point.y;\n }\n\n /* Compare this segment with a point.\n *\n * A point P is considered to be colinear to a segment if there\n * exists a distance D such that if we travel along the segment\n * from one * endpoint towards the other a distance D, we find\n * ourselves at point P.\n *\n * Return value indicates:\n *\n * 1: point lies above the segment (to the left of vertical)\n * 0: point is colinear to segment\n * -1: point lies below the segment (to the right of vertical)\n */\n comparePoint(point) {\n if (this.isAnEndpoint(point)) return 0;\n const lPt = this.leftSE.point;\n const rPt = this.rightSE.point;\n const v = this.vector();\n\n // Exactly vertical segments.\n if (lPt.x === rPt.x) {\n if (point.x === lPt.x) return 0;\n return point.x < lPt.x ? 1 : -1;\n }\n\n // Nearly vertical segments with an intersection.\n // Check to see where a point on the line with matching Y coordinate is.\n const yDist = (point.y - lPt.y) / v.y;\n const xFromYDist = lPt.x + yDist * v.x;\n if (point.x === xFromYDist) return 0;\n\n // General case.\n // Check to see where a point on the line with matching X coordinate is.\n const xDist = (point.x - lPt.x) / v.x;\n const yFromXDist = lPt.y + xDist * v.y;\n if (point.y === yFromXDist) return 0;\n return point.y < yFromXDist ? -1 : 1;\n }\n\n /**\n * Given another segment, returns the first non-trivial intersection\n * between the two segments (in terms of sweep line ordering), if it exists.\n *\n * A 'non-trivial' intersection is one that will cause one or both of the\n * segments to be split(). As such, 'trivial' vs. 'non-trivial' intersection:\n *\n * * endpoint of segA with endpoint of segB --> trivial\n * * endpoint of segA with point along segB --> non-trivial\n * * endpoint of segB with point along segA --> non-trivial\n * * point along segA with point along segB --> non-trivial\n *\n * If no non-trivial intersection exists, return null\n * Else, return null.\n */\n getIntersection(other) {\n // If bboxes don't overlap, there can't be any intersections\n const tBbox = this.bbox();\n const oBbox = other.bbox();\n const bboxOverlap = getBboxOverlap(tBbox, oBbox);\n if (bboxOverlap === null) return null;\n\n // We first check to see if the endpoints can be considered intersections.\n // This will 'snap' intersections to endpoints if possible, and will\n // handle cases of colinearity.\n\n const tlp = this.leftSE.point;\n const trp = this.rightSE.point;\n const olp = other.leftSE.point;\n const orp = other.rightSE.point;\n\n // does each endpoint touch the other segment?\n // note that we restrict the 'touching' definition to only allow segments\n // to touch endpoints that lie forward from where we are in the sweep line pass\n const touchesOtherLSE = isInBbox(tBbox, olp) && this.comparePoint(olp) === 0;\n const touchesThisLSE = isInBbox(oBbox, tlp) && other.comparePoint(tlp) === 0;\n const touchesOtherRSE = isInBbox(tBbox, orp) && this.comparePoint(orp) === 0;\n const touchesThisRSE = isInBbox(oBbox, trp) && other.comparePoint(trp) === 0;\n\n // do left endpoints match?\n if (touchesThisLSE && touchesOtherLSE) {\n // these two cases are for colinear segments with matching left\n // endpoints, and one segment being longer than the other\n if (touchesThisRSE && !touchesOtherRSE) return trp;\n if (!touchesThisRSE && touchesOtherRSE) return orp;\n // either the two segments match exactly (two trival intersections)\n // or just on their left endpoint (one trivial intersection\n return null;\n }\n\n // does this left endpoint matches (other doesn't)\n if (touchesThisLSE) {\n // check for segments that just intersect on opposing endpoints\n if (touchesOtherRSE) {\n if (tlp.x === orp.x && tlp.y === orp.y) return null;\n }\n // t-intersection on left endpoint\n return tlp;\n }\n\n // does other left endpoint matches (this doesn't)\n if (touchesOtherLSE) {\n // check for segments that just intersect on opposing endpoints\n if (touchesThisRSE) {\n if (trp.x === olp.x && trp.y === olp.y) return null;\n }\n // t-intersection on left endpoint\n return olp;\n }\n\n // trivial intersection on right endpoints\n if (touchesThisRSE && touchesOtherRSE) return null;\n\n // t-intersections on just one right endpoint\n if (touchesThisRSE) return trp;\n if (touchesOtherRSE) return orp;\n\n // None of our endpoints intersect. Look for a general intersection between\n // infinite lines laid over the segments\n const pt = intersection$1(tlp, this.vector(), olp, other.vector());\n\n // are the segments parrallel? Note that if they were colinear with overlap,\n // they would have an endpoint intersection and that case was already handled above\n if (pt === null) return null;\n\n // is the intersection found between the lines not on the segments?\n if (!isInBbox(bboxOverlap, pt)) return null;\n\n // round the the computed point if needed\n return rounder.round(pt.x, pt.y);\n }\n\n /**\n * Split the given segment into multiple segments on the given points.\n * * Each existing segment will retain its leftSE and a new rightSE will be\n * generated for it.\n * * A new segment will be generated which will adopt the original segment's\n * rightSE, and a new leftSE will be generated for it.\n * * If there are more than two points given to split on, new segments\n * in the middle will be generated with new leftSE and rightSE's.\n * * An array of the newly generated SweepEvents will be returned.\n *\n * Warning: input array of points is modified\n */\n split(point) {\n const newEvents = [];\n const alreadyLinked = point.events !== undefined;\n const newLeftSE = new SweepEvent(point, true);\n const newRightSE = new SweepEvent(point, false);\n const oldRightSE = this.rightSE;\n this.replaceRightSE(newRightSE);\n newEvents.push(newRightSE);\n newEvents.push(newLeftSE);\n const newSeg = new Segment(newLeftSE, oldRightSE, this.rings.slice(), this.windings.slice());\n\n // when splitting a nearly vertical downward-facing segment,\n // sometimes one of the resulting new segments is vertical, in which\n // case its left and right events may need to be swapped\n if (SweepEvent.comparePoints(newSeg.leftSE.point, newSeg.rightSE.point) > 0) {\n newSeg.swapEvents();\n }\n if (SweepEvent.comparePoints(this.leftSE.point, this.rightSE.point) > 0) {\n this.swapEvents();\n }\n\n // in the point we just used to create new sweep events with was already\n // linked to other events, we need to check if either of the affected\n // segments should be consumed\n if (alreadyLinked) {\n newLeftSE.checkForConsuming();\n newRightSE.checkForConsuming();\n }\n return newEvents;\n }\n\n /* Swap which event is left and right */\n swapEvents() {\n const tmpEvt = this.rightSE;\n this.rightSE = this.leftSE;\n this.leftSE = tmpEvt;\n this.leftSE.isLeft = true;\n this.rightSE.isLeft = false;\n for (let i = 0, iMax = this.windings.length; i < iMax; i++) {\n this.windings[i] *= -1;\n }\n }\n\n /* Consume another segment. We take their rings under our wing\n * and mark them as consumed. Use for perfectly overlapping segments */\n consume(other) {\n let consumer = this;\n let consumee = other;\n while (consumer.consumedBy) consumer = consumer.consumedBy;\n while (consumee.consumedBy) consumee = consumee.consumedBy;\n const cmp = Segment.compare(consumer, consumee);\n if (cmp === 0) return; // already consumed\n // the winner of the consumption is the earlier segment\n // according to sweep line ordering\n if (cmp > 0) {\n const tmp = consumer;\n consumer = consumee;\n consumee = tmp;\n }\n\n // make sure a segment doesn't consume it's prev\n if (consumer.prev === consumee) {\n const tmp = consumer;\n consumer = consumee;\n consumee = tmp;\n }\n for (let i = 0, iMax = consumee.rings.length; i < iMax; i++) {\n const ring = consumee.rings[i];\n const winding = consumee.windings[i];\n const index = consumer.rings.indexOf(ring);\n if (index === -1) {\n consumer.rings.push(ring);\n consumer.windings.push(winding);\n } else consumer.windings[index] += winding;\n }\n consumee.rings = null;\n consumee.windings = null;\n consumee.consumedBy = consumer;\n\n // mark sweep events consumed as to maintain ordering in sweep event queue\n consumee.leftSE.consumedBy = consumer.leftSE;\n consumee.rightSE.consumedBy = consumer.rightSE;\n }\n\n /* The first segment previous segment chain that is in the result */\n prevInResult() {\n if (this._prevInResult !== undefined) return this._prevInResult;\n if (!this.prev) this._prevInResult = null;else if (this.prev.isInResult()) this._prevInResult = this.prev;else this._prevInResult = this.prev.prevInResult();\n return this._prevInResult;\n }\n beforeState() {\n if (this._beforeState !== undefined) return this._beforeState;\n if (!this.prev) this._beforeState = {\n rings: [],\n windings: [],\n multiPolys: []\n };else {\n const seg = this.prev.consumedBy || this.prev;\n this._beforeState = seg.afterState();\n }\n return this._beforeState;\n }\n afterState() {\n if (this._afterState !== undefined) return this._afterState;\n const beforeState = this.beforeState();\n this._afterState = {\n rings: beforeState.rings.slice(0),\n windings: beforeState.windings.slice(0),\n multiPolys: []\n };\n const ringsAfter = this._afterState.rings;\n const windingsAfter = this._afterState.windings;\n const mpsAfter = this._afterState.multiPolys;\n\n // calculate ringsAfter, windingsAfter\n for (let i = 0, iMax = this.rings.length; i < iMax; i++) {\n const ring = this.rings[i];\n const winding = this.windings[i];\n const index = ringsAfter.indexOf(ring);\n if (index === -1) {\n ringsAfter.push(ring);\n windingsAfter.push(winding);\n } else windingsAfter[index] += winding;\n }\n\n // calcualte polysAfter\n const polysAfter = [];\n const polysExclude = [];\n for (let i = 0, iMax = ringsAfter.length; i < iMax; i++) {\n if (windingsAfter[i] === 0) continue; // non-zero rule\n const ring = ringsAfter[i];\n const poly = ring.poly;\n if (polysExclude.indexOf(poly) !== -1) continue;\n if (ring.isExterior) polysAfter.push(poly);else {\n if (polysExclude.indexOf(poly) === -1) polysExclude.push(poly);\n const index = polysAfter.indexOf(ring.poly);\n if (index !== -1) polysAfter.splice(index, 1);\n }\n }\n\n // calculate multiPolysAfter\n for (let i = 0, iMax = polysAfter.length; i < iMax; i++) {\n const mp = polysAfter[i].multiPoly;\n if (mpsAfter.indexOf(mp) === -1) mpsAfter.push(mp);\n }\n return this._afterState;\n }\n\n /* Is this segment part of the final result? */\n isInResult() {\n // if we've been consumed, we're not in the result\n if (this.consumedBy) return false;\n if (this._isInResult !== undefined) return this._isInResult;\n const mpsBefore = this.beforeState().multiPolys;\n const mpsAfter = this.afterState().multiPolys;\n switch (operation.type) {\n case \"union\":\n {\n // UNION - included iff:\n // * On one side of us there is 0 poly interiors AND\n // * On the other side there is 1 or more.\n const noBefores = mpsBefore.length === 0;\n const noAfters = mpsAfter.length === 0;\n this._isInResult = noBefores !== noAfters;\n break;\n }\n case \"intersection\":\n {\n // INTERSECTION - included iff:\n // * on one side of us all multipolys are rep. with poly interiors AND\n // * on the other side of us, not all multipolys are repsented\n // with poly interiors\n let least;\n let most;\n if (mpsBefore.length < mpsAfter.length) {\n least = mpsBefore.length;\n most = mpsAfter.length;\n } else {\n least = mpsAfter.length;\n most = mpsBefore.length;\n }\n this._isInResult = most === operation.numMultiPolys && least < most;\n break;\n }\n case \"xor\":\n {\n // XOR - included iff:\n // * the difference between the number of multipolys represented\n // with poly interiors on our two sides is an odd number\n const diff = Math.abs(mpsBefore.length - mpsAfter.length);\n this._isInResult = diff % 2 === 1;\n break;\n }\n case \"difference\":\n {\n // DIFFERENCE included iff:\n // * on exactly one side, we have just the subject\n const isJustSubject = mps => mps.length === 1 && mps[0].isSubject;\n this._isInResult = isJustSubject(mpsBefore) !== isJustSubject(mpsAfter);\n break;\n }\n default:\n throw new Error(`Unrecognized operation type found ${operation.type}`);\n }\n return this._isInResult;\n }\n}\n\nclass RingIn {\n constructor(geomRing, poly, isExterior) {\n if (!Array.isArray(geomRing) || geomRing.length === 0) {\n throw new Error(\"Input geometry is not a valid Polygon or MultiPolygon\");\n }\n this.poly = poly;\n this.isExterior = isExterior;\n this.segments = [];\n if (typeof geomRing[0][0] !== \"number\" || typeof geomRing[0][1] !== \"number\") {\n throw new Error(\"Input geometry is not a valid Polygon or MultiPolygon\");\n }\n const firstPoint = rounder.round(geomRing[0][0], geomRing[0][1]);\n this.bbox = {\n ll: {\n x: firstPoint.x,\n y: firstPoint.y\n },\n ur: {\n x: firstPoint.x,\n y: firstPoint.y\n }\n };\n let prevPoint = firstPoint;\n for (let i = 1, iMax = geomRing.length; i < iMax; i++) {\n if (typeof geomRing[i][0] !== \"number\" || typeof geomRing[i][1] !== \"number\") {\n throw new Error(\"Input geometry is not a valid Polygon or MultiPolygon\");\n }\n let point = rounder.round(geomRing[i][0], geomRing[i][1]);\n // skip repeated points\n if (point.x === prevPoint.x && point.y === prevPoint.y) continue;\n this.segments.push(Segment.fromRing(prevPoint, point, this));\n if (point.x < this.bbox.ll.x) this.bbox.ll.x = point.x;\n if (point.y < this.bbox.ll.y) this.bbox.ll.y = point.y;\n if (point.x > this.bbox.ur.x) this.bbox.ur.x = point.x;\n if (point.y > this.bbox.ur.y) this.bbox.ur.y = point.y;\n prevPoint = point;\n }\n // add segment from last to first if last is not the same as first\n if (firstPoint.x !== prevPoint.x || firstPoint.y !== prevPoint.y) {\n this.segments.push(Segment.fromRing(prevPoint, firstPoint, this));\n }\n }\n getSweepEvents() {\n const sweepEvents = [];\n for (let i = 0, iMax = this.segments.length; i < iMax; i++) {\n const segment = this.segments[i];\n sweepEvents.push(segment.leftSE);\n sweepEvents.push(segment.rightSE);\n }\n return sweepEvents;\n }\n}\nclass PolyIn {\n constructor(geomPoly, multiPoly) {\n if (!Array.isArray(geomPoly)) {\n throw new Error(\"Input geometry is not a valid Polygon or MultiPolygon\");\n }\n this.exteriorRing = new RingIn(geomPoly[0], this, true);\n // copy by value\n this.bbox = {\n ll: {\n x: this.exteriorRing.bbox.ll.x,\n y: this.exteriorRing.bbox.ll.y\n },\n ur: {\n x: this.exteriorRing.bbox.ur.x,\n y: this.exteriorRing.bbox.ur.y\n }\n };\n this.interiorRings = [];\n for (let i = 1, iMax = geomPoly.length; i < iMax; i++) {\n const ring = new RingIn(geomPoly[i], this, false);\n if (ring.bbox.ll.x < this.bbox.ll.x) this.bbox.ll.x = ring.bbox.ll.x;\n if (ring.bbox.ll.y < this.bbox.ll.y) this.bbox.ll.y = ring.bbox.ll.y;\n if (ring.bbox.ur.x > this.bbox.ur.x) this.bbox.ur.x = ring.bbox.ur.x;\n if (ring.bbox.ur.y > this.bbox.ur.y) this.bbox.ur.y = ring.bbox.ur.y;\n this.interiorRings.push(ring);\n }\n this.multiPoly = multiPoly;\n }\n getSweepEvents() {\n const sweepEvents = this.exteriorRing.getSweepEvents();\n for (let i = 0, iMax = this.interiorRings.length; i < iMax; i++) {\n const ringSweepEvents = this.interiorRings[i].getSweepEvents();\n for (let j = 0, jMax = ringSweepEvents.length; j < jMax; j++) {\n sweepEvents.push(ringSweepEvents[j]);\n }\n }\n return sweepEvents;\n }\n}\nclass MultiPolyIn {\n constructor(geom, isSubject) {\n if (!Array.isArray(geom)) {\n throw new Error(\"Input geometry is not a valid Polygon or MultiPolygon\");\n }\n try {\n // if the input looks like a polygon, convert it to a multipolygon\n if (typeof geom[0][0][0] === \"number\") geom = [geom];\n } catch (ex) {\n // The input is either malformed or has empty arrays.\n // In either case, it will be handled later on.\n }\n this.polys = [];\n this.bbox = {\n ll: {\n x: Number.POSITIVE_INFINITY,\n y: Number.POSITIVE_INFINITY\n },\n ur: {\n x: Number.NEGATIVE_INFINITY,\n y: Number.NEGATIVE_INFINITY\n }\n };\n for (let i = 0, iMax = geom.length; i < iMax; i++) {\n const poly = new PolyIn(geom[i], this);\n if (poly.bbox.ll.x < this.bbox.ll.x) this.bbox.ll.x = poly.bbox.ll.x;\n if (poly.bbox.ll.y < this.bbox.ll.y) this.bbox.ll.y = poly.bbox.ll.y;\n if (poly.bbox.ur.x > this.bbox.ur.x) this.bbox.ur.x = poly.bbox.ur.x;\n if (poly.bbox.ur.y > this.bbox.ur.y) this.bbox.ur.y = poly.bbox.ur.y;\n this.polys.push(poly);\n }\n this.isSubject = isSubject;\n }\n getSweepEvents() {\n const sweepEvents = [];\n for (let i = 0, iMax = this.polys.length; i < iMax; i++) {\n const polySweepEvents = this.polys[i].getSweepEvents();\n for (let j = 0, jMax = polySweepEvents.length; j < jMax; j++) {\n sweepEvents.push(polySweepEvents[j]);\n }\n }\n return sweepEvents;\n }\n}\n\nclass RingOut {\n /* Given the segments from the sweep line pass, compute & return a series\n * of closed rings from all the segments marked to be part of the result */\n static factory(allSegments) {\n const ringsOut = [];\n for (let i = 0, iMax = allSegments.length; i < iMax; i++) {\n const segment = allSegments[i];\n if (!segment.isInResult() || segment.ringOut) continue;\n let prevEvent = null;\n let event = segment.leftSE;\n let nextEvent = segment.rightSE;\n const events = [event];\n const startingPoint = event.point;\n const intersectionLEs = [];\n\n /* Walk the chain of linked events to form a closed ring */\n while (true) {\n prevEvent = event;\n event = nextEvent;\n events.push(event);\n\n /* Is the ring complete? */\n if (event.point === startingPoint) break;\n while (true) {\n const availableLEs = event.getAvailableLinkedEvents();\n\n /* Did we hit a dead end? This shouldn't happen.\n * Indicates some earlier part of the algorithm malfunctioned. */\n if (availableLEs.length === 0) {\n const firstPt = events[0].point;\n const lastPt = events[events.length - 1].point;\n throw new Error(`Unable to complete output ring starting at [${firstPt.x},` + ` ${firstPt.y}]. Last matching segment found ends at` + ` [${lastPt.x}, ${lastPt.y}].`);\n }\n\n /* Only one way to go, so cotinue on the path */\n if (availableLEs.length === 1) {\n nextEvent = availableLEs[0].otherSE;\n break;\n }\n\n /* We must have an intersection. Check for a completed loop */\n let indexLE = null;\n for (let j = 0, jMax = intersectionLEs.length; j < jMax; j++) {\n if (intersectionLEs[j].point === event.point) {\n indexLE = j;\n break;\n }\n }\n /* Found a completed loop. Cut that off and make a ring */\n if (indexLE !== null) {\n const intersectionLE = intersectionLEs.splice(indexLE)[0];\n const ringEvents = events.splice(intersectionLE.index);\n ringEvents.unshift(ringEvents[0].otherSE);\n ringsOut.push(new RingOut(ringEvents.reverse()));\n continue;\n }\n /* register the intersection */\n intersectionLEs.push({\n index: events.length,\n point: event.point\n });\n /* Choose the left-most option to continue the walk */\n const comparator = event.getLeftmostComparator(prevEvent);\n nextEvent = availableLEs.sort(comparator)[0].otherSE;\n break;\n }\n }\n ringsOut.push(new RingOut(events));\n }\n return ringsOut;\n }\n constructor(events) {\n this.events = events;\n for (let i = 0, iMax = events.length; i < iMax; i++) {\n events[i].segment.ringOut = this;\n }\n this.poly = null;\n }\n getGeom() {\n // Remove superfluous points (ie extra points along a straight line),\n let prevPt = this.events[0].point;\n const points = [prevPt];\n for (let i = 1, iMax = this.events.length - 1; i < iMax; i++) {\n const pt = this.events[i].point;\n const nextPt = this.events[i + 1].point;\n if (compareVectorAngles(pt, prevPt, nextPt) === 0) continue;\n points.push(pt);\n prevPt = pt;\n }\n\n // ring was all (within rounding error of angle calc) colinear points\n if (points.length === 1) return null;\n\n // check if the starting point is necessary\n const pt = points[0];\n const nextPt = points[1];\n if (compareVectorAngles(pt, prevPt, nextPt) === 0) points.shift();\n points.push(points[0]);\n const step = this.isExteriorRing() ? 1 : -1;\n const iStart = this.isExteriorRing() ? 0 : points.length - 1;\n const iEnd = this.isExteriorRing() ? points.length : -1;\n const orderedPoints = [];\n for (let i = iStart; i != iEnd; i += step) orderedPoints.push([points[i].x, points[i].y]);\n return orderedPoints;\n }\n isExteriorRing() {\n if (this._isExteriorRing === undefined) {\n const enclosing = this.enclosingRing();\n this._isExteriorRing = enclosing ? !enclosing.isExteriorRing() : true;\n }\n return this._isExteriorRing;\n }\n enclosingRing() {\n if (this._enclosingRing === undefined) {\n this._enclosingRing = this._calcEnclosingRing();\n }\n return this._enclosingRing;\n }\n\n /* Returns the ring that encloses this one, if any */\n _calcEnclosingRing() {\n // start with the ealier sweep line event so that the prevSeg\n // chain doesn't lead us inside of a loop of ours\n let leftMostEvt = this.events[0];\n for (let i = 1, iMax = this.events.length; i < iMax; i++) {\n const evt = this.events[i];\n if (SweepEvent.compare(leftMostEvt, evt) > 0) leftMostEvt = evt;\n }\n let prevSeg = leftMostEvt.segment.prevInResult();\n let prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null;\n while (true) {\n // no segment found, thus no ring can enclose us\n if (!prevSeg) return null;\n\n // no segments below prev segment found, thus the ring of the prev\n // segment must loop back around and enclose us\n if (!prevPrevSeg) return prevSeg.ringOut;\n\n // if the two segments are of different rings, the ring of the prev\n // segment must either loop around us or the ring of the prev prev\n // seg, which would make us and the ring of the prev peers\n if (prevPrevSeg.ringOut !== prevSeg.ringOut) {\n if (prevPrevSeg.ringOut.enclosingRing() !== prevSeg.ringOut) {\n return prevSeg.ringOut;\n } else return prevSeg.ringOut.enclosingRing();\n }\n\n // two segments are from the same ring, so this was a penisula\n // of that ring. iterate downward, keep searching\n prevSeg = prevPrevSeg.prevInResult();\n prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null;\n }\n }\n}\nclass PolyOut {\n constructor(exteriorRing) {\n this.exteriorRing = exteriorRing;\n exteriorRing.poly = this;\n this.interiorRings = [];\n }\n addInterior(ring) {\n this.interiorRings.push(ring);\n ring.poly = this;\n }\n getGeom() {\n const geom = [this.exteriorRing.getGeom()];\n // exterior ring was all (within rounding error of angle calc) colinear points\n if (geom[0] === null) return null;\n for (let i = 0, iMax = this.interiorRings.length; i < iMax; i++) {\n const ringGeom = this.interiorRings[i].getGeom();\n // interior ring was all (within rounding error of angle calc) colinear points\n if (ringGeom === null) continue;\n geom.push(ringGeom);\n }\n return geom;\n }\n}\nclass MultiPolyOut {\n constructor(rings) {\n this.rings = rings;\n this.polys = this._composePolys(rings);\n }\n getGeom() {\n const geom = [];\n for (let i = 0, iMax = this.polys.length; i < iMax; i++) {\n const polyGeom = this.polys[i].getGeom();\n // exterior ring was all (within rounding error of angle calc) colinear points\n if (polyGeom === null) continue;\n geom.push(polyGeom);\n }\n return geom;\n }\n _composePolys(rings) {\n const polys = [];\n for (let i = 0, iMax = rings.length; i < iMax; i++) {\n const ring = rings[i];\n if (ring.poly) continue;\n if (ring.isExteriorRing()) polys.push(new PolyOut(ring));else {\n const enclosingRing = ring.enclosingRing();\n if (!enclosingRing.poly) polys.push(new PolyOut(enclosingRing));\n enclosingRing.poly.addInterior(ring);\n }\n }\n return polys;\n }\n}\n\n/**\n * NOTE: We must be careful not to change any segments while\n * they are in the SplayTree. AFAIK, there's no way to tell\n * the tree to rebalance itself - thus before splitting\n * a segment that's in the tree, we remove it from the tree,\n * do the split, then re-insert it. (Even though splitting a\n * segment *shouldn't* change its correct position in the\n * sweep line tree, the reality is because of rounding errors,\n * it sometimes does.)\n */\n\nclass SweepLine {\n constructor(queue) {\n let comparator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Segment.compare;\n this.queue = queue;\n this.tree = new SplayTree(comparator);\n this.segments = [];\n }\n process(event) {\n const segment = event.segment;\n const newEvents = [];\n\n // if we've already been consumed by another segment,\n // clean up our body parts and get out\n if (event.consumedBy) {\n if (event.isLeft) this.queue.remove(event.otherSE);else this.tree.remove(segment);\n return newEvents;\n }\n const node = event.isLeft ? this.tree.add(segment) : this.tree.find(segment);\n if (!node) throw new Error(`Unable to find segment #${segment.id} ` + `[${segment.leftSE.point.x}, ${segment.leftSE.point.y}] -> ` + `[${segment.rightSE.point.x}, ${segment.rightSE.point.y}] ` + \"in SweepLine tree.\");\n let prevNode = node;\n let nextNode = node;\n let prevSeg = undefined;\n let nextSeg = undefined;\n\n // skip consumed segments still in tree\n while (prevSeg === undefined) {\n prevNode = this.tree.prev(prevNode);\n if (prevNode === null) prevSeg = null;else if (prevNode.key.consumedBy === undefined) prevSeg = prevNode.key;\n }\n\n // skip consumed segments still in tree\n while (nextSeg === undefined) {\n nextNode = this.tree.next(nextNode);\n if (nextNode === null) nextSeg = null;else if (nextNode.key.consumedBy === undefined) nextSeg = nextNode.key;\n }\n if (event.isLeft) {\n // Check for intersections against the previous segment in the sweep line\n let prevMySplitter = null;\n if (prevSeg) {\n const prevInter = prevSeg.getIntersection(segment);\n if (prevInter !== null) {\n if (!segment.isAnEndpoint(prevInter)) prevMySplitter = prevInter;\n if (!prevSeg.isAnEndpoint(prevInter)) {\n const newEventsFromSplit = this._splitSafely(prevSeg, prevInter);\n for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {\n newEvents.push(newEventsFromSplit[i]);\n }\n }\n }\n }\n\n // Check for intersections against the next segment in the sweep line\n let nextMySplitter = null;\n if (nextSeg) {\n const nextInter = nextSeg.getIntersection(segment);\n if (nextInter !== null) {\n if (!segment.isAnEndpoint(nextInter)) nextMySplitter = nextInter;\n if (!nextSeg.isAnEndpoint(nextInter)) {\n const newEventsFromSplit = this._splitSafely(nextSeg, nextInter);\n for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {\n newEvents.push(newEventsFromSplit[i]);\n }\n }\n }\n }\n\n // For simplicity, even if we find more than one intersection we only\n // spilt on the 'earliest' (sweep-line style) of the intersections.\n // The other intersection will be handled in a future process().\n if (prevMySplitter !== null || nextMySplitter !== null) {\n let mySplitter = null;\n if (prevMySplitter === null) mySplitter = nextMySplitter;else if (nextMySplitter === null) mySplitter = prevMySplitter;else {\n const cmpSplitters = SweepEvent.comparePoints(prevMySplitter, nextMySplitter);\n mySplitter = cmpSplitters <= 0 ? prevMySplitter : nextMySplitter;\n }\n\n // Rounding errors can cause changes in ordering,\n // so remove afected segments and right sweep events before splitting\n this.queue.remove(segment.rightSE);\n newEvents.push(segment.rightSE);\n const newEventsFromSplit = segment.split(mySplitter);\n for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {\n newEvents.push(newEventsFromSplit[i]);\n }\n }\n if (newEvents.length > 0) {\n // We found some intersections, so re-do the current event to\n // make sure sweep line ordering is totally consistent for later\n // use with the segment 'prev' pointers\n this.tree.remove(segment);\n newEvents.push(event);\n } else {\n // done with left event\n this.segments.push(segment);\n segment.prev = prevSeg;\n }\n } else {\n // event.isRight\n\n // since we're about to be removed from the sweep line, check for\n // intersections between our previous and next segments\n if (prevSeg && nextSeg) {\n const inter = prevSeg.getIntersection(nextSeg);\n if (inter !== null) {\n if (!prevSeg.isAnEndpoint(inter)) {\n const newEventsFromSplit = this._splitSafely(prevSeg, inter);\n for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {\n newEvents.push(newEventsFromSplit[i]);\n }\n }\n if (!nextSeg.isAnEndpoint(inter)) {\n const newEventsFromSplit = this._splitSafely(nextSeg, inter);\n for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {\n newEvents.push(newEventsFromSplit[i]);\n }\n }\n }\n }\n this.tree.remove(segment);\n }\n return newEvents;\n }\n\n /* Safely split a segment that is currently in the datastructures\n * IE - a segment other than the one that is currently being processed. */\n _splitSafely(seg, pt) {\n // Rounding errors can cause changes in ordering,\n // so remove afected segments and right sweep events before splitting\n // removeNode() doesn't work, so have re-find the seg\n // https://github.com/w8r/splay-tree/pull/5\n this.tree.remove(seg);\n const rightSE = seg.rightSE;\n this.queue.remove(rightSE);\n const newEvents = seg.split(pt);\n newEvents.push(rightSE);\n // splitting can trigger consumption\n if (seg.consumedBy === undefined) this.tree.add(seg);\n return newEvents;\n }\n}\n\n// Limits on iterative processes to prevent infinite loops - usually caused by floating-point math round-off errors.\nconst POLYGON_CLIPPING_MAX_QUEUE_SIZE = typeof process !== \"undefined\" && process.env.POLYGON_CLIPPING_MAX_QUEUE_SIZE || 1000000;\nconst POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS = typeof process !== \"undefined\" && process.env.POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS || 1000000;\nclass Operation {\n run(type, geom, moreGeoms) {\n operation.type = type;\n rounder.reset();\n\n /* Convert inputs to MultiPoly objects */\n const multipolys = [new MultiPolyIn(geom, true)];\n for (let i = 0, iMax = moreGeoms.length; i < iMax; i++) {\n multipolys.push(new MultiPolyIn(moreGeoms[i], false));\n }\n operation.numMultiPolys = multipolys.length;\n\n /* BBox optimization for difference operation\n * If the bbox of a multipolygon that's part of the clipping doesn't\n * intersect the bbox of the subject at all, we can just drop that\n * multiploygon. */\n if (operation.type === \"difference\") {\n // in place removal\n const subject = multipolys[0];\n let i = 1;\n while (i < multipolys.length) {\n if (getBboxOverlap(multipolys[i].bbox, subject.bbox) !== null) i++;else multipolys.splice(i, 1);\n }\n }\n\n /* BBox optimization for intersection operation\n * If we can find any pair of multipolygons whose bbox does not overlap,\n * then the result will be empty. */\n if (operation.type === \"intersection\") {\n // TODO: this is O(n^2) in number of polygons. By sorting the bboxes,\n // it could be optimized to O(n * ln(n))\n for (let i = 0, iMax = multipolys.length; i < iMax; i++) {\n const mpA = multipolys[i];\n for (let j = i + 1, jMax = multipolys.length; j < jMax; j++) {\n if (getBboxOverlap(mpA.bbox, multipolys[j].bbox) === null) return [];\n }\n }\n }\n\n /* Put segment endpoints in a priority queue */\n const queue = new SplayTree(SweepEvent.compare);\n for (let i = 0, iMax = multipolys.length; i < iMax; i++) {\n const sweepEvents = multipolys[i].getSweepEvents();\n for (let j = 0, jMax = sweepEvents.length; j < jMax; j++) {\n queue.insert(sweepEvents[j]);\n if (queue.size > POLYGON_CLIPPING_MAX_QUEUE_SIZE) {\n // prevents an infinite loop, an otherwise common manifestation of bugs\n throw new Error(\"Infinite loop when putting segment endpoints in a priority queue \" + \"(queue size too big).\");\n }\n }\n }\n\n /* Pass the sweep line over those endpoints */\n const sweepLine = new SweepLine(queue);\n let prevQueueSize = queue.size;\n let node = queue.pop();\n while (node) {\n const evt = node.key;\n if (queue.size === prevQueueSize) {\n // prevents an infinite loop, an otherwise common manifestation of bugs\n const seg = evt.segment;\n throw new Error(`Unable to pop() ${evt.isLeft ? \"left\" : \"right\"} SweepEvent ` + `[${evt.point.x}, ${evt.point.y}] from segment #${seg.id} ` + `[${seg.leftSE.point.x}, ${seg.leftSE.point.y}] -> ` + `[${seg.rightSE.point.x}, ${seg.rightSE.point.y}] from queue.`);\n }\n if (queue.size > POLYGON_CLIPPING_MAX_QUEUE_SIZE) {\n // prevents an infinite loop, an otherwise common manifestation of bugs\n throw new Error(\"Infinite loop when passing sweep line over endpoints \" + \"(queue size too big).\");\n }\n if (sweepLine.segments.length > POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS) {\n // prevents an infinite loop, an otherwise common manifestation of bugs\n throw new Error(\"Infinite loop when passing sweep line over endpoints \" + \"(too many sweep line segments).\");\n }\n const newEvents = sweepLine.process(evt);\n for (let i = 0, iMax = newEvents.length; i < iMax; i++) {\n const evt = newEvents[i];\n if (evt.consumedBy === undefined) queue.insert(evt);\n }\n prevQueueSize = queue.size;\n node = queue.pop();\n }\n\n // free some memory we don't need anymore\n rounder.reset();\n\n /* Collect and compile segments we're keeping into a multipolygon */\n const ringsOut = RingOut.factory(sweepLine.segments);\n const result = new MultiPolyOut(ringsOut);\n return result.getGeom();\n }\n}\n\n// singleton available by import\nconst operation = new Operation();\n\nconst union = function (geom) {\n for (var _len = arguments.length, moreGeoms = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n moreGeoms[_key - 1] = arguments[_key];\n }\n return operation.run(\"union\", geom, moreGeoms);\n};\nconst intersection = function (geom) {\n for (var _len2 = arguments.length, moreGeoms = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n moreGeoms[_key2 - 1] = arguments[_key2];\n }\n return operation.run(\"intersection\", geom, moreGeoms);\n};\nconst xor = function (geom) {\n for (var _len3 = arguments.length, moreGeoms = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {\n moreGeoms[_key3 - 1] = arguments[_key3];\n }\n return operation.run(\"xor\", geom, moreGeoms);\n};\nconst difference = function (subjectGeom) {\n for (var _len4 = arguments.length, clippingGeoms = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {\n clippingGeoms[_key4 - 1] = arguments[_key4];\n }\n return operation.run(\"difference\", subjectGeom, clippingGeoms);\n};\nvar index = {\n union: union,\n intersection: intersection,\n xor: xor,\n difference: difference\n};\n\nexport { index as default };\n","import type { ExteriorPreset } from './materials';\n\nexport type Point = [number, number];\n/** Geographic anchor of the local tangent frame — [lng, lat] in WGS84 degrees; an optional third\n * element rotates the site clockwise from true north (degrees). */\nexport type Origin = [number, number] | [number, number, number];\nexport type Ring = Point[];\n/** The built-in taxonomy of drawable things, spanning the toolkit's use-cases (spaces, openings,\n * devices, logistics, safety). It is intentionally broad rather than tied to one domain; model\n * host-specific subtypes (e.g. a turnstile variety, a sensor class) as `category`/`metadata` on the\n * object rather than by extending this union. Runtime tuple so the type and the document validator\n * share one source of truth. */\nexport const OBJECT_KINDS = [\n 'zone',\n 'room',\n 'parcel',\n 'building',\n 'office',\n 'container',\n 'storage',\n 'door',\n 'window',\n 'gate',\n 'turnstile',\n 'reader',\n 'camera',\n 'elevator',\n 'stairs',\n 'poi',\n 'fixture',\n 'light',\n 'landscape',\n 'sensor',\n 'alarm',\n 'equipment',\n 'evacuation',\n] as const;\nexport type ObjectKind = (typeof OBJECT_KINDS)[number];\nexport type MaterialKind =\n | 'brick'\n | 'stone'\n | 'plaster'\n | 'timber'\n | 'oak'\n | 'tile'\n | 'terrazzo'\n | 'grass'\n | 'paving'\n | 'carpet'\n | 'wallpaper';\nexport type ModelKind =\n | 'bed'\n | 'sofa'\n | 'dining'\n | 'cabinet'\n | 'counter'\n | 'toilet'\n | 'basin'\n | 'shower'\n | 'sauna'\n | 'tree'\n | 'shrub'\n | 'lamp'\n | 'car'\n | 'chimney'\n | 'vent'\n | 'post';\nexport interface RoofSection {\n footprint: Ring;\n ridge: [Point, Point];\n eave: number;\n peak: number;\n}\nexport interface BuildingRoof {\n floorId: string;\n color: string;\n sections: RoofSection[];\n}\n/** mezzanine marks an intermediate (entresol) level: the plan draws it in context of the levels around it. */\nexport interface Floor {\n id: string;\n buildingId: string;\n name: string;\n elevation: number;\n height: number;\n mezzanine?: boolean;\n code?: string;\n /** The artificial light this level burns — colour temperature and how brightly. Absent means a\n * fluorescent ceiling at working brightness, which is what is actually overhead in most of the\n * buildings anyone draws. A building's own lighting does not follow the sun, so this is what\n * keeps a storey legible in a plan opened after dark. */\n light?: InteriorLight;\n /** What this level sounds like from inside it — the default for every space on it that does not\n * say otherwise. Absent is silence. */\n ambience?: Ambience;\n}\n/** The sound of a space, heard at eye level: a named soundscape or musical preset,\n * and how loud, 0 to 1 (absent is 1). Kept in\n * the document rather than the renderer for the same reason light is: what a room sounds like\n * describes the room. */\nexport interface Ambience {\n preset: AmbiencePreset;\n level?: number;\n}\nexport type AmbiencePreset = 'silent' | 'office' | 'backrooms' | 'plant' | 'baths' | 'elevator';\nexport const AMBIENCE_PRESETS: AmbiencePreset[] = ['silent', 'office', 'backrooms', 'plant', 'baths', 'elevator'];\n/** Colour temperature in kelvin (2700 tungsten, 4000 fluorescent, 6500 daylight) and how brightly,\n * 0 to 1. Kept here rather than in the renderer: what a space is lit by describes the space. */\nexport interface InteriorLight {\n kelvin: number;\n level: number;\n /** Optional colour cast from the fittings or reflected surroundings. */\n tint?: string;\n}\n/** A ceiling luminaire. Object height is the mounting height above the floor, intensity is candela,\n * range is metres, and flicker is the optional 0..1 depth of intermittent ballast dimming. */\nexport interface LightFixture {\n /** Optional mounting elevation above the floor; negative values place a lamp inside a pool. */\n mountHeight?: number;\n kelvin: number;\n intensity: number;\n range: number;\n flicker?: number;\n}\nexport interface Building {\n id: string;\n name: string;\n roof?: BuildingRoof;\n /** Provenance id of the basemap footprint a building was adopted from — the value of the host's\n * configured footprints.idField (a string or number, depending on the tile source); absent for\n * hand-drawn buildings. */\n sourceId?: string | number;\n exteriorPreset?: ExteriorPreset;\n}\nexport interface Junction {\n id: string;\n floorId: string | null;\n position: Point;\n}\n/** An unwalled space boundary. Physical boundaries use Barrier IDs and endpoints directly. */\nexport interface VirtualBoundary {\n id: string;\n floorId: string | null;\n startId: string;\n endId: string;\n}\nexport interface BoundaryUse {\n edgeId: string;\n /** Traverse from endId to startId. Absent means startId to endId. */\n reversed?: boolean;\n}\nexport type SpaceGeometry = { mode: 'independent' } | { mode: 'boundaries'; loops: BoundaryUse[][] };\nexport interface Barrier {\n id: string;\n floorId: string | null;\n startId: string;\n endId: string;\n kind: 'wall' | 'fence';\n thickness: number;\n height: number;\n name: string;\n color?: string;\n material?: MaterialKind;\n category?: string;\n metadata?: Record<string, unknown>;\n}\n/** A sloped area: the footprint falls linearly from `high` at `axis[0]` to `low` at `axis[1]`, and\n * stays flat beyond either end — so a footprint longer than its axis keeps level aprons where it\n * meets the decks it joins. Elevations are absolute metres in the same frame as Floor.elevation, so a\n * ramp can span floors (a garage ramp, a loading incline, a sloped plaza). Any area object may carry\n * one; without it an area is flat. The axis always runs downhill: `high` >= `low`. */\nexport interface Slope {\n axis: [Point, Point];\n high: number;\n low: number;\n}\nexport interface SiteObject {\n id: string;\n kind: ObjectKind;\n floorId: string | null;\n name: string;\n position: Point;\n rotation: number;\n rings?: Ring[];\n /** Boundary-driven spaces keep rings and dimensions as a validated, generated cache.\n * Absent is an independent outline, preserving existing/imported projects without guessing. */\n geometry?: SpaceGeometry;\n /** Makes this area a sloped plane rather than a flat plate; see Slope. */\n slope?: Slope;\n /** Clear ceiling height above this floor's datum; omitted uses the storey height.\n * A room spanning storeys uses this with holes in the plates above it. */\n ceilingHeight?: number;\n /** A basin below this area's walking surface, filled with clear water. */\n water?: { depth: number; ripple?: number };\n /** Open water-slide centreline, in metres relative to the object's position and rotation.\n * The third coordinate is height above its floor. */\n slide?: { path: [number, number, number][]; radius: number };\n /** Bottom of a raised fixture, metres above the floor surface (e.g. a doorway lintel). */\n baseHeight?: number;\n width: number;\n depth: number;\n height: number;\n parentId?: string;\n barrierId?: string;\n offset?: number;\n /** Door hinge at the wall start (left, default) or end (right). */\n doorHinge?: 'left' | 'right';\n /** Door mechanism. Omitted means a conventional single hinged leaf. */\n doorType?: 'hinged' | 'sliding' | 'double';\n /** Door opens to the left (+1, default) or right (-1) of the directed wall. */\n doorSwing?: 1 | -1;\n feedId?: string;\n symbol?:\n | 'personnel'\n | 'service'\n | 'driveway'\n | 'parking'\n | 'assembly'\n | 'info'\n | 'aed'\n | 'extinguisher'\n | 'firstaid'\n | 'exit'\n | 'firealarm';\n servedFloorIds?: string[];\n /** Stairs only: which geometry this climb has.\n *\n * `straight` is one run. `switchback` turns back on itself around a half-landing — the half-turn\n * stair that fits a storey into a short core box, and what most building stairs actually are.\n * `dogleg` turns a quarter at its landing, for a stair in the corner of a plan. `spiral` winds\n * around a pole and can land on every level it passes. `escalator` is a machine: a fixed 30° pitch\n * and a flat comb plate at each end.\n *\n * All of them connect the same floors and route identically, which is why this is one field rather\n * than five kinds — the difference is what it looks like and how much run it needs. Absent picks\n * the shape that fits: a straight run where the footprint allows a civil pitch, a switchback where\n * it does not, since a plan that gives a 4.5 m box to a 4.4 m storey means a stair that turns, not\n * a ladder. */\n stairModel?: 'straight' | 'switchback' | 'dogleg' | 'spiral' | 'escalator';\n /** Stairs with the same group on a level share one rectangular floor/ceiling opening. */\n wellGroup?: string;\n /** Escalators only: which way the machine carries you.\n *\n * It is a property of the machine, not of the drawing and not of its name: an escalator runs one\n * way, a bank of them runs alternate ways, and which way this one runs is the first thing anyone\n * asks of it. The same vocabulary as `Zone.connects`, so the described layer and the object never\n * need translating between them. Absent means up, which is what a lone escalator nearly always\n * does. A stair that is not an escalator ignores it — a stair carries you both ways.\n *\n * An imported escalator arrives once per storey it is drawn on; the twin standing lowest is the\n * one the model draws and routes from, so that is the one to author. */\n travel?: 'up' | 'down';\n /** Elevators only: which faces of the car open, relative to the object's own rotation. A through-car\n * opens front and back; a corner lobby car opens front and one side. Absent means the front alone,\n * which is what almost every lift does. Which FLOORS it opens on is `servedFloorIds` — a level the\n * shaft passes without serving has no doors on any side. */\n doorSides?: ('front' | 'back' | 'left' | 'right')[];\n coverageAngle?: number;\n coverageRange?: number;\n color?: string;\n /** Camera: ids of the doors, rooms and elevators this camera observes (event footage lookup). */\n watchedIds?: string[];\n material?: MaterialKind;\n model?: ModelKind;\n light?: LightFixture;\n /** A space's own sound, overriding its floor's. See Floor.ambience. */\n ambience?: Ambience;\n /** Host-defined subtype/category (e.g. 'meeting-room', 'speedgate', 'cold-store') for styling, filtering and event handlers. */\n category?: string;\n /** Arbitrary host metadata; ignored by the core, available to style hooks and event handlers. */\n metadata?: Record<string, unknown>;\n}\nexport interface Drawing {\n id: string;\n floorId: string | null;\n assetId: string;\n name: string;\n width: number;\n height: number;\n origin: Point;\n scale: number;\n rotation: number;\n opacity: number;\n visible: boolean;\n locked: boolean;\n}\n/** A named set of spaces — the area objects listed in `spaceIds`.\n *\n * A zone is a *membership*, not a shape: it has no geometry of its own, which is exactly what lets it\n * span floors, skip buildings, and overlap other zones freely. (Contrast `SiteObject.parentId`, which\n * is the strict single-parent, same-floor, geometrically-contained tree.) A lift shaft is a zone of\n * its per-floor lift spaces; a security area is a zone of the rooms inside it. */\nexport interface Zone {\n id: string;\n name: string;\n spaceIds: string[];\n /** Zones may contain zones: a DAG, not a tree. Cycles are rejected; several parents are fine.\n * Membership does NOT imply access inheritance — that is policy, and policy is the host's. */\n childZoneIds?: string[];\n /** How the spaces within this zone reach each other, when they are not joined by portals.\n * 'all' — every space mutually reachable: a lift serving all of its landings.\n * 'adjacent' — reachable in elevation order, both ways: a stair, passing each level in turn.\n * 'up'/'down'— adjacent but one-way: an escalator, which carries you in a single direction.\n * omitted — no implied connectivity; the zone is a grouping only. */\n connects?: 'all' | 'adjacent' | 'up' | 'down';\n /** Host vocabulary ('security', 'evacuation', 'hvac', …). The core never interprets it. */\n purpose?: string;\n metadata?: Record<string, unknown>;\n}\n/** A traversable connection between exactly two spaces.\n *\n * Direction is deliberately not baked in: a door's entry and exit sides are relative to whichever\n * area you are asking about, so the two sides are stored symmetrically and direction is derived\n * (see `entryInto`). Applications that attach a rule per direction of travel split a two-way door into\n * two objects; that is the right shape for an application layer and the wrong shape for a topology one. */\nexport interface Portal {\n id: string;\n /** The opening object (door/gate/turnstile) crossed here; absent for a virtual portal — an open\n * boundary between two spaces with no physical separator, which malls and open-plan floors need.\n * Kept as a reference rather than folded in, so two portals can be known to share one door leaf. */\n openingId?: string;\n /** The two sides. Order is storage, not meaning — ask `entryInto` rather than reading it. */\n a: string;\n b: string;\n /** Which way passage is possible at all. Default 'both'. */\n passage?: 'both' | 'a-to-b' | 'b-to-a' | 'none';\n /** How far a crossing here can be trusted to have actually happened.\n * 'confirmed' — a sensor saw it (a door monitor opening and closing).\n * 'assumed' — inferred from a grant; nobody watched. The default for a plain door.\n * 'none' — the crossing is a *request*, not an event: a lift floor button, where the\n * passenger may go anywhere. Anything counting crossings must ignore these. */\n attests?: 'confirmed' | 'assumed' | 'none';\n name?: string;\n metadata?: Record<string, unknown>;\n}\n/** An explicit set of portals, for sets that are not a zone boundary — \"all loading-bay shutters\",\n * \"every door with a reader\". Where a set *is* a zone boundary, derive it instead: see `perimeter`. */\nexport interface PortalGroup {\n id: string;\n name: string;\n portalIds: string[];\n metadata?: Record<string, unknown>;\n}\n/** Authored route-graph node for indoor navigation. objectId binds it to a SiteObject (door, elevator, stairs, room, poi) so routing can anchor at that object and instructions can name it. */\nexport interface NavNode {\n id: string;\n floorId: string | null;\n position: Point;\n objectId?: string;\n}\nexport type NavEdgeKind = 'walk' | 'door' | 'stairs' | 'elevator';\n/** Undirected route-graph edge. walk stays on one floor; door stays on one floor or steps outside (one end floorId null); stairs/elevator join different floors and bind the serving object via objectId. weight overrides the derived metres-equivalent cost. */\nexport interface NavEdge {\n id: string;\n kind: NavEdgeKind;\n aId: string;\n bId: string;\n /** Passable from `aId` to `bId` only. Escalators and one-way doors; absent means both ways. */\n directed?: boolean;\n objectId?: string;\n weight?: number;\n}\nexport interface ProjectDocument {\n schemaVersion: 1;\n id: string;\n name: string;\n description: string;\n updatedAt: string;\n origin: Origin;\n datum: string;\n buildings: Building[];\n floors: Floor[];\n junctions: Junction[];\n barriers: Barrier[];\n virtualBoundaries?: VirtualBoundary[];\n objects: SiteObject[];\n drawings: Drawing[];\n referenceNote?: string;\n /** The floor a viewer should open on — the document's own front door, so a project that is really\n * about its offices does not always land on the street. `null` means the outdoor site; omit it\n * entirely to let the viewer pick (ground floor, else the lowest). Hosts can still override per\n * session via ViewState.floor / FloorViewer's `floorId`. */\n initialFloorId?: string | null;\n /** The spatial ontology layered over the geometry: which spaces group together, and what connects\n * to what. Spaces themselves are the ringed area objects in `objects` — nothing is duplicated. */\n zones?: Zone[];\n portals?: Portal[];\n portalGroups?: PortalGroup[];\n /** Optional authored navigation graph. When absent, the graph is derived from spaces and portals\n * (see model/topology.ts) — the plan is then the single source of truth and cannot drift out of\n * step with a hand-kept copy of itself. */\n navNodes?: NavNode[];\n navEdges?: NavEdge[];\n}\nexport interface ProjectSummary {\n id: string;\n name: string;\n updatedAt: string;\n}\nexport interface ProjectRepository {\n list(): Promise<ProjectSummary[]>;\n load(id: string): Promise<ProjectDocument | null>;\n save(project: ProjectDocument): Promise<void>;\n delete(id: string): Promise<void>;\n}\nexport interface AssetRepository {\n get(id: string): Promise<Blob | undefined>;\n put(id: string, asset: Blob): Promise<void>;\n delete(id: string): Promise<void>;\n}\nexport type Tool =\n | 'select'\n | 'pan'\n | 'wall'\n | 'boundary'\n | 'partition'\n | 'fence'\n | 'zone'\n | 'room'\n | 'rectangle'\n | 'enclose'\n | 'hole'\n | 'door'\n | 'window'\n | 'gate'\n | 'turnstile'\n | 'reader'\n | 'camera'\n | 'elevator'\n | 'stairs'\n | 'office'\n | 'container'\n | 'storage'\n | 'poi'\n | 'measure'\n | 'adopt'\n | 'split'\n | 'route'\n | 'sensor'\n | 'light'\n | 'alarm'\n | 'equipment'\n | 'evacuation';\n/** A fresh entity id. A bare UUIDv4 (no type prefix) so ids drop straight into a database `uuid`\n * column and validate there; the entity's type is already given by which collection it lives in. */\nexport const uid = () => crypto.randomUUID();\nexport const isArea = (kind: ObjectKind) =>\n ['zone', 'room', 'parcel', 'building', 'office', 'container', 'storage', 'evacuation'].includes(kind);\nexport const isDevice = (kind: ObjectKind) =>\n ['door', 'gate', 'turnstile', 'reader', 'camera', 'elevator', 'sensor', 'alarm', 'equipment'].includes(kind);\nexport const isOpening = (kind: ObjectKind) => kind === 'door' || kind === 'window' || kind === 'gate';\n/** A *space* is somewhere you can stand — the unit the ontology groups and connects. Areas qualify,\n * and so do lifts and stairs: the inside of a car is as much a place as the lobby it opens onto, and\n * the through-car case depends on being able to say so. */\nexport const isSpace = (kind: ObjectKind) => isArea(kind) || kind === 'elevator' || kind === 'stairs';\n","import { isSpace, type Portal, type ProjectDocument } from './types';\n\nconst pairKey = (a: string, b: string) => JSON.stringify([a, b].sort());\n\n/** A shared virtual edge explicitly declares an unwalled connection. Read its two sides directly;\n * sampling inset room outlines loses narrow openings near the ends of adjoining walls. */\nexport function sharedBoundaryPortals(project: ProjectDocument): Portal[] {\n const edges = new Map((project.virtualBoundaries ?? []).map(edge => [edge.id, edge]));\n if (!edges.size) return [];\n const sides = new Map<string, { id: string; reversed: boolean }[]>();\n for (const space of project.objects) {\n if (!isSpace(space.kind) || space.geometry?.mode !== 'boundaries') continue;\n for (const loop of space.geometry.loops)\n for (const use of loop) {\n const edge = edges.get(use.edgeId);\n if (!edge || edge.floorId !== space.floorId) continue;\n const owners = sides.get(edge.id) ?? [];\n if (!owners.some(owner => owner.id === space.id)) owners.push({ id: space.id, reversed: !!use.reversed });\n sides.set(edge.id, owners);\n }\n }\n const out = new Map<string, Portal>();\n for (const owners of sides.values())\n for (let i = 0; i < owners.length; i++)\n for (let j = i + 1; j < owners.length; j++) {\n if (owners[i].reversed === owners[j].reversed) continue;\n const [a, b] = [owners[i].id, owners[j].id].sort();\n out.set(pairKey(a, b), { id: `open:${a}:${b}`, a, b, attests: 'none' });\n }\n return [...out.values()];\n}\n\n/** The readable portal layer, including explicit shared openings in older saved plans. A stored\n * portal takes precedence, including sealed and one-way passage. No document mutation is needed.\n * Once both spaces use shared boundaries, an inferred open connection also disappears when its\n * virtual edge is replaced by a wall. Legacy independent outlines retain their inferred portals. */\nexport function effectivePortals(project: ProjectDocument): Portal[] {\n const shared = sharedBoundaryPortals(project);\n const pairs = new Set(shared.map(p => pairKey(p.a, p.b)));\n const bound = new Set(project.objects.filter(o => o.geometry?.mode === 'boundaries').map(o => o.id));\n const stored = (project.portals ?? []).filter(\n p => !p.id.startsWith('open:') || !bound.has(p.a) || !bound.has(p.b) || pairs.has(pairKey(p.a, p.b)),\n );\n const authoredPairs = new Set(\n stored.filter(p => !p.id.startsWith('open:') && !p.id.startsWith('inferred:')).map(p => pairKey(p.a, p.b)),\n );\n const retained = stored.filter(p => !p.id.startsWith('open:') || !authoredPairs.has(pairKey(p.a, p.b)));\n const held = new Set(retained.map(p => pairKey(p.a, p.b)));\n return [...retained, ...shared.filter(p => !held.has(pairKey(p.a, p.b)))];\n}\n","// The described layer: zones, portals and portal groups — what groups with what, what connects to\n// what, in which direction, and how far a crossing can be trusted. Everything here is semantics over\n// ids; no geometry is read. Reading the plan itself (inferring portals, dividing spaces) lives in\n// inference.ts, and turning this description into a routing graph lives in topology.ts.\nimport { isSpace, uid, type Portal, type PortalGroup, type ProjectDocument, type Zone } from './types';\nimport { effectivePortals } from './portals';\n\n/** Which way you must cross `portal` to arrive in `spaceId`, or null if you cannot get there that way.\n * Direction is asked, never stored: a door's entry side is relative to the area you mean. */\nexport function entryInto(portal: Portal, spaceId: string): 'a-to-b' | 'b-to-a' | null {\n const passage = portal.passage ?? 'both';\n if (passage === 'none') return null;\n if (portal.b === spaceId && passage !== 'b-to-a') return 'a-to-b';\n if (portal.a === spaceId && passage !== 'a-to-b') return 'b-to-a';\n return null;\n}\n\nconst memberSet = (project: ProjectDocument, zone: Zone, seen = new Set<string>()): Set<string> => {\n if (seen.has(zone.id)) return new Set(); // zones nest as a DAG; a cycle is a bug, not a hang\n seen.add(zone.id);\n const out = new Set(zone.spaceIds);\n for (const childId of zone.childZoneIds ?? []) {\n const child = project.zones?.find(z => z.id === childId);\n if (child) for (const id of memberSet(project, child, seen)) out.add(id);\n }\n return out;\n};\n/** Every space in `zone`, including those reached through nested zones. */\nexport const zoneSpaces = (project: ProjectDocument, zone: Zone): string[] => [...memberSet(project, zone)];\n\n/** Portals on the boundary of `zone` — one side in, one side out. These are the ways in, and the\n * thing software without a floor plan to ask makes you enumerate by hand. Derived, so it cannot go\n * stale when the building is redrawn. */\nexport function perimeter(project: ProjectDocument, zone: Zone): Portal[] {\n const inside = memberSet(project, zone);\n return effectivePortals(project).filter(p => inside.has(p.a) !== inside.has(p.b));\n}\n/** Portals wholly inside `zone`. Not decorative: anything tracking where somebody ended up needs to\n * know that crossing one of these does not change which zone you are in. */\nexport function captive(project: ProjectDocument, zone: Zone): Portal[] {\n const inside = memberSet(project, zone);\n return effectivePortals(project).filter(p => inside.has(p.a) && inside.has(p.b));\n}\n\n// ——— Authoring. Zones are the part a person actually writes: portals are read off the plan, but\n// what counts as \"Finance\" or \"the secure floor\" is a decision nobody can derive.\n\n/** Create a zone over the given spaces. Ids that are not spaces are dropped rather than rejected —\n * a selection usually contains a door or a fixture alongside the rooms, and losing the whole gesture\n * over that would be tiresome. */\nexport function addZone(project: ProjectDocument, name: string, spaceIds: string[], purpose?: string): Zone {\n const zone: Zone = {\n id: uid(),\n name,\n spaceIds: [...new Set(spaceIds)].filter(id => project.objects.some(o => o.id === id && isSpace(o.kind))),\n };\n if (purpose) zone.purpose = purpose;\n (project.zones ??= []).push(zone);\n return zone;\n}\n/** Remove a zone, and any nesting reference to it. A dangling childZoneIds entry fails validation. */\nexport function removeZone(project: ProjectDocument, zoneId: string) {\n project.zones = (project.zones ?? []).filter(z => z.id !== zoneId);\n for (const z of project.zones)\n if (z.childZoneIds?.includes(zoneId)) z.childZoneIds = z.childZoneIds.filter(id => id !== zoneId);\n}\n/** Add or remove spaces on a zone. Membership is a set: adding twice is not an error, and neither is\n * removing something that was never there. */\nexport function setZoneMembers(project: ProjectDocument, zoneId: string, spaceIds: string[], member: boolean) {\n const zone = project.zones?.find(z => z.id === zoneId);\n if (!zone) return;\n const eligible = spaceIds.filter(id => project.objects.some(o => o.id === id && isSpace(o.kind)));\n const next = new Set(zone.spaceIds);\n for (const id of eligible)\n if (member) next.add(id);\n else next.delete(id);\n zone.spaceIds = [...next];\n}\n/** Nest one zone inside another, refusing anything that would make a cycle. Zones form a DAG, and a\n * cycle is the one shape the validator will not accept. */\nexport function nestZone(project: ProjectDocument, parentId: string, childId: string): boolean {\n const parent = project.zones?.find(z => z.id === parentId);\n if (!parent || parentId === childId || !project.zones?.some(z => z.id === childId)) return false;\n const reaches = (from: string, target: string, seen = new Set<string>()): boolean => {\n if (from === target) return true;\n if (seen.has(from)) return false;\n seen.add(from);\n return (project.zones?.find(z => z.id === from)?.childZoneIds ?? []).some(id => reaches(id, target, seen));\n };\n if (reaches(childId, parentId)) return false; // the child already contains us\n parent.childZoneIds = [...new Set([...(parent.childZoneIds ?? []), childId])];\n return true;\n}\n\n/** Create a portal group over the given portals. The escape hatch for sets that are not a zone\n * boundary — \"all loading-bay shutters\", \"every door on the night circuit\". Where a set *is* a zone\n * boundary, derive it with `perimeter` instead; a derived list cannot go stale. Ids that are not\n * portals are dropped rather than rejected, mirroring addZone. */\nexport function addPortalGroup(project: ProjectDocument, name: string, portalIds: string[]): PortalGroup {\n project.portals = effectivePortals(project);\n const group: PortalGroup = {\n id: uid(),\n name,\n portalIds: [...new Set(portalIds)].filter(id => (project.portals ?? []).some(p => p.id === id)),\n };\n (project.portalGroups ??= []).push(group);\n return group;\n}\n/** Remove a portal group. Nothing references groups, so nothing needs cleaning up after one. */\nexport function removePortalGroup(project: ProjectDocument, groupId: string) {\n project.portalGroups = (project.portalGroups ?? []).filter(g => g.id !== groupId);\n}\n/** Add or remove portals on a group. Membership is a set, exactly as setZoneMembers. */\nexport function setPortalGroupMembers(project: ProjectDocument, groupId: string, portalIds: string[], member: boolean) {\n const group = project.portalGroups?.find(g => g.id === groupId);\n if (!group) return;\n project.portals = effectivePortals(project);\n const eligible = portalIds.filter(id => (project.portals ?? []).some(p => p.id === id));\n const next = new Set(group.portalIds);\n for (const id of eligible)\n if (member) next.add(id);\n else next.delete(id);\n group.portalIds = [...next];\n}\n\n/** Drop ontology references to things that no longer exist.\n *\n * Every reference here is validated, so a delete that skips this step produces an invalid document\n * and gets refused — from the outside that looks like the delete silently doing nothing, which is\n * the worst way for a bug to present. Call it after removing objects, from every path that can.\n *\n * A portal whose opening is gone goes with it: the door was the way through, and keeping a portal\n * that no longer has one would quietly turn a closed doorway into an open boundary. */\nexport function pruneOntology(project: ProjectDocument) {\n const alive = new Set(project.objects.map(o => o.id));\n const spaceIds = new Set(project.objects.filter(o => isSpace(o.kind)).map(o => o.id));\n if (project.portals)\n project.portals = project.portals.filter(\n p => spaceIds.has(p.a) && spaceIds.has(p.b) && (!p.openingId || alive.has(p.openingId)),\n );\n const portalIds = new Set((project.portals ?? []).map(p => p.id));\n if (project.zones) {\n const zoneIds = new Set(project.zones.map(z => z.id));\n for (const zone of project.zones) {\n zone.spaceIds = zone.spaceIds.filter(id => spaceIds.has(id));\n if (zone.childZoneIds) zone.childZoneIds = zone.childZoneIds.filter(id => zoneIds.has(id));\n }\n }\n if (project.portalGroups)\n for (const group of project.portalGroups) group.portalIds = group.portalIds.filter(id => portalIds.has(id));\n}\n","/** Openings a person can cross. Windows are openings, but never walkable portals. */\nexport const TRAVERSABLE = new Set<string>(['door', 'gate', 'turnstile']);\n","// The navigation graph as a *derived dual* of the plan: spaces are nodes, portals are edges, and a\n// zone's `connects` supplies the vertical ones. This is IndoorGML's Poincaré duality — a k-dimensional\n// object in primal space maps to an (N−k)-dimensional one in dual space, so rooms become points and\n// the surfaces between them become lines.\n//\n// Nothing here is authored or stored. It is recomputed from the geometry, which is the whole point: a\n// hand-kept graph is a second description of what connects to what, and two descriptions drift.\nimport { distance } from './geometry';\nimport { isSpace, type NavEdge, type NavEdgeKind, type NavNode } from './types';\nimport type { Floor, ProjectDocument, SiteObject } from './types';\nimport { spacePoint } from './spaces';\nimport { zoneSpaces } from './ontology';\nimport { TRAVERSABLE } from './passages';\nimport { effectivePortals } from './portals';\n\n/** Node id for a space. Prefixed so a derived graph can never collide with an authored entity id. */\nexport const spaceNodeId = (spaceId: string) => `space:${spaceId}`;\n\n/** A portal's edge kind.\n *\n * Two different floors is a vertical move. Outdoors is *not* a floor, though — it is `null` — so a\n * front door joins two different `floorId`s while being the least vertical thing in the building.\n * Missing that turns every entrance into a flight of stairs. */\nfunction portalKind(a: SiteObject, b: SiteObject, opening?: SiteObject): NavEdgeKind {\n const sameFloor = a.floorId === b.floorId;\n if (!sameFloor && a.floorId !== null && b.floorId !== null)\n return a.kind === 'elevator' || b.kind === 'elevator' ? 'elevator' : 'stairs';\n // Stepping outside: a threshold, which is what door edges are allowed to be even without a leaf.\n if (!sameFloor) return 'door';\n return opening && TRAVERSABLE.has(opening.kind) ? 'door' : 'walk';\n}\n\nexport function derivedGraph(project: ProjectDocument): { nodes: NavNode[]; edges: NavEdge[] } {\n const objects = new Map(project.objects.map(o => [o.id, o]));\n const floors = new Map<string, Floor>(project.floors.map(f => [f.id, f]));\n const nodes = new Map<string, NavNode>();\n const node = (space: SiteObject): NavNode => {\n const id = spaceNodeId(space.id);\n const existing = nodes.get(id);\n if (existing) return existing;\n const made: NavNode = { id, floorId: space.floorId, position: spacePoint(project, space), objectId: space.id };\n nodes.set(id, made);\n return made;\n };\n // Every space gets a node, whether or not anything connects to it. Creating them only as edges\n // demand them makes an unconnected space vanish from the graph entirely — and routing anchors an\n // object with no footprint (a POI, a door) to the *nearest node*, so a missing node is not merely a\n // gap in the graph, it is an entrance that can never be departed from.\n for (const space of project.objects) if (isSpace(space.kind)) node(space);\n const edges: NavEdge[] = [];\n const join = (id: string, kind: NavEdgeKind, a: SiteObject, b: SiteObject, objectId?: string, directed = false) => {\n if (a.id === b.id) return;\n const edge: NavEdge = { id, kind, aId: node(a).id, bId: node(b).id };\n if (objectId) edge.objectId = objectId;\n if (directed) edge.directed = true;\n edges.push(edge);\n };\n\n for (const portal of effectivePortals(project)) {\n if ((portal.passage ?? 'both') === 'none') continue;\n const a = objects.get(portal.a),\n b = objects.get(portal.b);\n if (!a || !b) continue;\n const opening = portal.openingId ? objects.get(portal.openingId) : undefined;\n const kind = portalKind(a, b, opening);\n // The edge names the opening it crosses only when the two agree: a door on a door edge, a lift\n // on a lift edge. A cross-floor portal may still carry a door — a landing door at a half level —\n // but a vertical edge claiming a door as its stairs would make the document invalid, so a\n // mismatched opening is simply not named and the edge stands on its own.\n const bindable =\n opening && (kind === 'door' ? TRAVERSABLE.has(opening.kind) : kind === 'walk' ? false : opening.kind === kind);\n // A one-way portal becomes a one-way edge. Emitting it undirected would let a route come back\n // through a fire exit, which is the whole thing `passage` exists to forbid.\n const passage = portal.passage ?? 'both';\n const [from, to] = passage === 'b-to-a' ? [b, a] : [a, b];\n join(`portal:${portal.id}`, kind, from, to, bindable ? opening.id : undefined, passage !== 'both');\n }\n\n // A zone that declares its own internal connectivity generates the edges its members imply — which\n // is how a 17-storey lift is one line of authoring rather than 136 portals.\n for (const zone of project.zones ?? []) {\n if (!zone.connects) continue;\n const members = zoneSpaces(project, zone)\n .map(id => objects.get(id))\n .filter((o): o is SiteObject => !!o && o.floorId !== null)\n .sort((x, y) => (floors.get(x.floorId!)?.elevation ?? 0) - (floors.get(y.floorId!)?.elevation ?? 0));\n const kind: NavEdgeKind = members.some(m => m.kind === 'elevator') ? 'elevator' : 'stairs';\n // An escalator carries you one way. Members are sorted upwards, so 'up' runs lower → higher and\n // 'down' is the same pairs reversed; both are directed, which is what makes them escalators\n // rather than stairs that happen to be named after a direction.\n const oneWay = zone.connects === 'up' || zone.connects === 'down';\n for (let i = 1; i < members.length; i++)\n for (let j = zone.connects === 'all' ? 0 : i - 1; j < i; j++)\n if (members[j].floorId !== members[i].floorId)\n // The edge only names the object it rides when that object really is the lift or stair.\n // A zone may connect plain rooms — a split-level atrium, a ramp between decks — and\n // claiming a room is an elevator would make the document invalid, not merely untidy.\n join(\n `zone:${zone.id}:${j}:${i}`,\n kind,\n zone.connects === 'down' ? members[i] : members[j],\n zone.connects === 'down' ? members[j] : members[i],\n members[i].kind === kind ? members[i].id : undefined,\n oneWay,\n );\n }\n return { nodes: [...nodes.values()], edges };\n}\n\n// Recomputed on every routing query otherwise, and routing runs per keystroke in the navigate panel.\n// Documents are replaced rather than mutated, so a WeakMap entry retires with the document it\n// describes — the same bargain exteriorWalls strikes.\nconst cache = new WeakMap<ProjectDocument, { nodes: NavNode[]; edges: NavEdge[] }>();\nexport function topology(project: ProjectDocument): { nodes: NavNode[]; edges: NavEdge[] } {\n const hit = cache.get(project);\n if (hit) return hit;\n const built = derivedGraph(project);\n cache.set(project, built);\n return built;\n}\n\n/** Straight-line length of a derived edge, for cost comparisons against an authored graph. */\nexport const edgeSpan = (nodes: Map<string, NavNode>, edge: NavEdge): number => {\n const a = nodes.get(edge.aId),\n b = nodes.get(edge.bId);\n return a && b ? distance(a.position, b.position) : 0;\n};\n","// Vertical circulation: which levels a stair, escalator or lift actually reaches, and what it has to\n// climb between them.\n//\n// A shaft is the one object that is not on a floor so much as *between* floors, and the document has\n// always said so — `servedFloorIds` is authored in the inspector, seeded by the factory, threaded by\n// routing and enforced by validation. Nothing else read it. The renderer guessed instead, taking\n// \"the next floor up in the same building\" as the rise and drawing the object only on the storey it\n// was filed under, which is why a flight arriving at a level was invisible from that level and why a\n// lift serving eight floors was a box you could see over.\n//\n// This is where that question gets answered once, so the plan, the route and the model agree about\n// where a stair goes.\nimport { closeRing, footprint, objectPosition, objectRotation, rectangle, rotate } from './geometry';\nimport type { Floor, Point, ProjectDocument, Ring, SiteObject } from './types';\n\n/** True for the kinds that connect levels. */\nexport const isVertical = (kind: string) => kind === 'stairs' || kind === 'elevator';\n\n/** Which shaft this object is part of.\n *\n * A shaft is one thing standing in one place reaching several levels, and that is how the document\n * can describe it: one object, one position, one `servedFloorIds`. Older documents — the demo among\n * them — instead repeat the object on every storey it serves, because that is what you had to do\n * before anything read the served list. Both must draw as one lift, so a shaft is identified by what\n * makes it the same shaft: its kind, its name, and where it stands. */\nexport const shaftKey = (object: SiteObject) =>\n `${object.kind}|${object.name}|${object.position[0].toFixed(2)}|${object.position[1].toFixed(2)}`;\n\n/** Every level this shaft reaches, lowest first.\n *\n * `servedFloorIds` when it is authored — that is the document's own statement and outranks any\n * inference. A shaft that declares nothing serves the floor it stands on and no other: better to\n * draw a stair going nowhere, which is visibly wrong and easy to fix, than to invent a connection\n * that routing would then happily send someone through. */\nexport function servedFloors(project: ProjectDocument, object: SiteObject): Floor[] {\n // Every twin's reach, not just this one's. A plan sheet only says what is on its own storey, so an\n // import gives the same stair once per floor it is drawn on, each claiming only that floor. Read\n // together they say what the stair actually connects — which is the question being asked, and the\n // reason a stair imported from three sheets is one flight and not three plates.\n const key = shaftKey(object);\n const ids = project.objects\n .filter(o => isVertical(o.kind) && shaftKey(o) === key)\n .flatMap(o => (o.servedFloorIds?.length ? o.servedFloorIds : o.floorId ? [o.floorId] : []));\n return [...new Set(ids.length ? ids : object.floorId ? [object.floorId] : [])]\n .map(id => project.floors.find(f => f.id === id))\n .filter((f): f is Floor => !!f)\n .sort((a, b) => a.elevation - b.elevation);\n}\n\n/** One climb between two levels the shaft serves. */\nexport interface Flight {\n from: Floor;\n to: Floor;\n /** Metres climbed, always positive. */\n rise: number;\n}\n\n/** The climbs this shaft makes, bottom first.\n *\n * Consecutive served levels, so a stair serving 0-1-2 makes two flights and a lift serving the same\n * three makes two hops of shaft. A level in between that the shaft passes without stopping is simply\n * not in the list, and the flight spanning it is the taller for it — which is the right picture: an\n * express lift's shaft does pass those floors, and a spiral stair's helix does wind past a mezzanine\n * it has no landing on. */\nexport function flights(project: ProjectDocument, object: SiteObject): Flight[] {\n const levels = servedFloors(project, object);\n const out: Flight[] = [];\n for (let i = 1; i < levels.length; i++)\n out.push({ from: levels[i - 1], to: levels[i], rise: levels[i].elevation - levels[i - 1].elevation });\n return out;\n}\n\n/** Does this shaft reach the given level? Includes the floor it is filed under. */\nexport const reaches = (project: ProjectDocument, object: SiteObject, floorId: string | null): boolean =>\n floorId !== null && (object.floorId === floorId || servedFloors(project, object).some(f => f.id === floorId));\n\n/** The flight arriving at a level from below, and the one leaving it upward — what you would see\n * standing on that level. Either may be absent at the ends of the run. */\nexport function flightsAt(\n project: ProjectDocument,\n object: SiteObject,\n floorId: string | null,\n): { up?: Flight; down?: Flight } {\n const all = flights(project, object);\n return {\n up: all.find(f => f.from.id === floorId),\n down: all.find(f => f.to.id === floorId),\n };\n}\n\n/** How far a shaft's body runs, as absolute elevations: the lowest level it serves to the highest.\n * Null when it serves fewer than two levels and so has no body to speak of. */\nexport function span(project: ProjectDocument, object: SiteObject): { bottom: number; top: number } | null {\n const levels = servedFloors(project, object);\n if (levels.length < 2) return null;\n return { bottom: levels[0].elevation, top: levels[levels.length - 1].elevation };\n}\n\n/** The angle a flight of this kind wants to climb at, in degrees from horizontal.\n *\n * An escalator is a machine built to one geometry: 30°, the world over. A stair is free-er but a\n * comfortable flight is around 32°, and anything past about 42° is a ladder. These are what the\n * plan should be *checked against* — the footprint stays the truth of where the thing is — so a run\n * too short for its rise reads as the steep slope it would really be. */\nexport const PITCH = { escalator: 30, stairs: 32 } as const;\n\n/** The run a flight of this rise needs to climb at its natural pitch. Use it to size a shaft the\n * drawing has not sized, and to tell whether one it has sized is plausible. */\nexport const runFor = (rise: number, pitch: number = PITCH.stairs) => rise / Math.tan((pitch * Math.PI) / 180);\n\n/** The pitch a flight actually climbs at, given the run the plan gives it. */\nexport const pitchOf = (rise: number, run: number) => (run > 0 ? (Math.atan(rise / run) * 180) / Math.PI : 90);\n\n/** The deepest tread that is still a tread. Past about a third of a metre a flight stops being a\n * stair: the going grows with the box while the rise per step does not, and what you get is a ramp\n * with slabs laid on it. A box longer than the climb needs keeps its length — the surplus is\n * landing, which is what that spare floor really is. */\nexport const MAX_GOING = 0.32;\n/** A comfortable domestic riser, and close to code everywhere. */\nconst RISER = 0.175;\n/** Head clearance under a flight, and so the reach of the hole one needs in the plate it climbs\n * through: everything above the plate, plus the stretch below it where a person standing on the\n * plate would still be under the soffit. */\nconst HEADROOM = 2.1;\n\n/** The treads one flight of this rise gets, and how deep each is in a run of this length. Capped\n * both ways: a handful of boxes reads as a stair, two hundred reads as a stair and costs a level. */\nexport function treads(rise: number, run: number): { steps: number; going: number } {\n const steps = Math.max(2, Math.min(24, Math.round(rise / RISER)));\n return { steps, going: Math.min(MAX_GOING, run / steps) };\n}\n\nexport type StairModel = NonNullable<SiteObject['stairModel']>;\n\n/** How a shaft is built — as the document says, or as its own footprint implies.\n *\n * A footprint that cannot take the rise at a civil pitch is describing a stair that turns, which is\n * what a short wide core box always is. Both the renderer and the plate it cuts its hole in have to\n * agree about that, so the reading lives here rather than in either of them. */\nexport function stairModel(project: ProjectDocument, object: SiteObject): StairModel {\n if (object.stairModel) return object.stairModel;\n const first = flights(project, object)[0];\n return first && pitchOf(first.rise, Math.max(0.6, object.depth)) > 38 ? 'switchback' : 'straight';\n}\n\n/** A bank of escalators is stacked criss-cross: every other flight runs the other way, so you step\n * off one and turn to step onto the next. Which way round a given flight is decides which end of\n * the footprint it arrives at, and so which end of it the floor above has to be open. */\nexport const flightReversed = (model: StairModel, index: number) => model === 'escalator' && index % 2 === 1;\n\n/** Where one flight's sloping part actually lies inside the box the plan drew.\n *\n * The plan gives a footprint; the climb is what has to fit in it. An escalator keeps a metre of flat\n * comb plate at each end and then climbs at the machine's own 30°, so a box with run to spare gets a\n * longer landing at its foot instead of a shallower ramp — a 1.6 m rise in a 12 m box is a stair with\n * a lot of floor round it, not a slide. A stair's treads are capped at MAX_GOING for the same reason.\n * A box too short for its rise is left alone: it really is that steep and the picture should say so.\n *\n * `t` runs along the object's depth axis from its centre. The foot of a flight is at +depth/2 and its\n * head at -depth/2, which is how the renderer has always laid one out; the surplus goes to whichever\n * end that leaves free — the foot of an escalator, whose comb plates must stay at the ends the plan\n * drew them at, and the head of a stair, which has none. */\nexport interface FlightRun {\n /** The rotation this flight is drawn at — see flightReversed. */\n rotation: number;\n /** A point t metres along the run from the object's centre. */\n at: (t: number) => Point;\n /** How long the box is along that axis, and half of it. */\n length: number;\n half: number;\n /** The flat plate at each end of an escalator; zero for a stair. */\n pad: number;\n /** The sloping part: how long it is, and where it starts and ends along the run. */\n incline: number;\n topT: number;\n footT: number;\n}\nexport function flightRun(\n project: ProjectDocument,\n object: SiteObject,\n rise: number,\n model: StairModel,\n index = 0,\n): FlightRun {\n const position = objectPosition(project, object);\n const rotation = objectRotation(project, object) + (flightReversed(model, index) ? 180 : 0);\n const rad = (rotation * Math.PI) / 180;\n const ux = Math.sin(rad),\n uy = -Math.cos(rad);\n const at = (t: number): Point => [position[0] + ux * t, position[1] + uy * t];\n const length = Math.max(0.6, object.depth),\n half = length / 2;\n if (model === 'escalator') {\n const pad = Math.min(1, length / 4);\n const incline = Math.min(length - pad * 2, Math.max(0.4, runFor(rise, PITCH.escalator)));\n return { rotation, at, length, half, pad, incline, topT: -half + pad, footT: -half + pad + incline };\n }\n const { steps, going } = treads(rise, length);\n const incline = Math.min(length, steps * going);\n return { rotation, at, length, half, pad: 0, incline, topT: half - incline, footT: half };\n}\n\n/** The hole one flight needs in a plate standing `height` metres above its foot.\n *\n * Not the flight's whole footprint. Everything from the head of the run down to where the flight\n * pierces the plate has to be open, because the flight is above the plate there; so does the stretch\n * below it where the soffit is still within head height. Past that the flight is under the floor,\n * which is where the cupboard under the stairs comes from — and why punching the whole of an\n * eight-metre escalator through every storey it passes opened a trench in each of them. */\nfunction headroomBand(run: FlightRun, rise: number, height: number, width: number): Ring {\n const steep = rise > 0.01 ? run.incline / rise : run.incline;\n const end = Math.min(run.footT, Math.max(run.topT + 0.6, run.footT - height * steep + HEADROOM * steep));\n const depth = end - run.topT;\n return closeRing(rectangle(run.at(run.topT + depth / 2), width, depth, run.rotation));\n}\n\n/** The one twin that stands for the shaft: the lowest, so the flights count upward from the bottom.\n * A shaft described the modern way — one object — is trivially its own primary. */\nexport function primaryShafts(project: ProjectDocument): Set<string> {\n const lowest = new Map<string, SiteObject>();\n for (const o of project.objects) {\n if (!isVertical(o.kind)) continue;\n const key = shaftKey(o);\n const rival = lowest.get(key);\n const at = (x: SiteObject) => project.floors.find(f => f.id === x.floorId)?.elevation ?? 0;\n if (!rival || at(o) < at(rival)) lowest.set(key, o);\n }\n return new Set([...lowest.values()].map(o => o.id));\n}\n\n/** Does something come up through this level's floor? The shaft starts below it and reaches it or\n * goes past — so a flight arrives here and the plate it arrives through has to be open.\n *\n * This is one half of what `passesThrough` used to answer for both. Requiring a served level above\n * as well meant the flight arriving at the top of a run was drawn under an uncut slab: on Stockmann's\n * ninth floor all twelve shafts arrive and not one of them cut a hole, so the last flight of every\n * stair in the building was invisible from the storey it lands on. */\nexport function arrivesAt(project: ProjectDocument, object: SiteObject, floorId: string): boolean {\n const level = project.floors.find(f => f.id === floorId);\n if (!level) return false;\n const levels = servedFloors(project, object);\n return (\n levels.some(f => f.elevation < level.elevation - 0.01) && levels.some(f => f.elevation >= level.elevation - 0.01)\n );\n}\n\n/** The other half: does something climb out through this level's ceiling? The shaft stands on this\n * level or lower and carries on above it, so the lid a walked storey gets has to be open over it —\n * which the bottom of a run needs just as much as the middle of one. */\nexport function departsFrom(project: ProjectDocument, object: SiteObject, floorId: string): boolean {\n const level = project.floors.find(f => f.id === floorId);\n if (!level) return false;\n const levels = servedFloors(project, object);\n return (\n levels.some(f => f.elevation <= level.elevation + 0.01) && levels.some(f => f.elevation > level.elevation + 0.01)\n );\n}\n\n/** Does this shaft pass THROUGH a level — arriving from below and carrying on above? Both halves at\n * once, which is the question a level in the middle of a run answers yes to and no end of one does. */\nexport const passesThrough = (project: ProjectDocument, object: SiteObject, floorId: string): boolean =>\n arrivesAt(project, object, floorId) && departsFrom(project, object, floorId);\n\nexport interface VoidOptions {\n /** `floor` (the default) cuts what arrives from below; `ceiling` cuts what departs upward. */\n through?: 'floor' | 'ceiling';\n /** Ignore flights that set off below this elevation. An above-ground view draws nothing under\n * grade, and a hole with nothing beneath it is worse than no hole at all. */\n lowest?: number;\n}\n\n/** What to cut out of a level's floor plate, or out of the lid over a walked storey.\n *\n * A stairwell is a hole. Drawing the slab whole and the stair beneath it puts a lid over the flight,\n * so from the landing above you see a plate where the opening should be and the stair appears to\n * climb into the ceiling. The hole is only as big as the flight needs, though: a lift or a turning\n * core is a shaft and takes its whole footprint, but a straight flight or an escalator lies under\n * the floor for most of its length and wants opening only where it comes up — see headroomBand. */\nexport function shaftVoids(\n project: ProjectDocument,\n floorId: string,\n primary?: Set<string>,\n options: VoidOptions = {},\n): Ring[] {\n const level = project.floors.find(f => f.id === floorId);\n if (!level) return [];\n const ceiling = options.through === 'ceiling';\n const lowest = options.lowest ?? -Infinity;\n const out: Ring[] = [];\n const groups = new Map<string, SiteObject[]>();\n for (const o of project.objects) {\n if (!isVertical(o.kind) || (primary && !primary.has(o.id))) continue;\n const all = flights(project, o);\n // The one climb this plate is in the way of: the flight arriving through it, or the flight\n // setting off up through it. They are different flights on a level in the middle of a run, and\n // on a criss-cross bank they arrive at opposite ends of the same box.\n const index = ceiling\n ? all.findIndex(f => f.from.elevation <= level.elevation + 0.01 && f.to.elevation > level.elevation + 0.01)\n : all.findIndex(f => f.from.elevation < level.elevation - 0.01 && f.to.elevation >= level.elevation - 0.01);\n if (index < 0) continue;\n const flight = all[index];\n if (flight.from.elevation < lowest) continue;\n if (o.kind === 'stairs' && o.wellGroup) {\n const members = groups.get(o.wellGroup) ?? [];\n members.push(o);\n groups.set(o.wellGroup, members);\n continue;\n }\n const model = stairModel(project, o);\n if (o.kind === 'stairs' && (model === 'straight' || model === 'escalator')) {\n const run = flightRun(project, o, flight.rise, model, index);\n const height = level.elevation + (ceiling ? level.height : 0) - flight.from.elevation;\n out.push(headroomBand(run, flight.rise, height, o.width));\n continue;\n }\n const ring = footprint(o)[0];\n // A touch proud of the shaft itself, so the slab does not leave a hairline of itself behind.\n if (ring?.length) out.push(closeRing(ring.map(p => [p[0], p[1]] as Point)));\n }\n for (const members of groups.values()) {\n const rotation = objectRotation(project, members[0]);\n const points = members.flatMap(o => footprint(o)[0]).map(p => rotate(p, -rotation));\n const xs = points.map(p => p[0]),\n ys = points.map(p => p[1]);\n const loX = Math.min(...xs),\n hiX = Math.max(...xs),\n loY = Math.min(...ys),\n hiY = Math.max(...ys);\n out.push(rectangle(rotate([(loX + hiX) / 2, (loY + hiY) / 2], rotation), hiX - loX, hiY - loY, rotation));\n }\n return out;\n}\n","import { distance, footprint, intersects, openRing, pointInRing, segmentProjection } from './geometry';\nimport type { Point, ProjectDocument, Ring } from './types';\n\n/** Extra room for shoulders and for the route marking, in plan metres. */\nexport const ROUTE_CLEARANCE = 0.4;\ntype Bounds = [number, number, number, number];\nexport const routeBounds = (points: Point[], pad = 0): Bounds => [\n Math.min(...points.map(p => p[0])) - pad,\n Math.min(...points.map(p => p[1])) - pad,\n Math.max(...points.map(p => p[0])) + pad,\n Math.max(...points.map(p => p[1])) + pad,\n];\nconst overlaps = (a: Bounds, b: Bounds) => a[0] <= b[2] && a[2] >= b[0] && a[1] <= b[3] && a[3] >= b[1];\nconst gap = (a: Point, b: Point, c: Point, d: Point) =>\n intersects(a, b, c, d)\n ? 0\n : Math.min(\n segmentProjection(a, c, d).distance,\n segmentProjection(b, c, d).distance,\n segmentProjection(c, a, b).distance,\n segmentProjection(d, a, b).distance,\n );\n\n/** A geometric guard for walking connections. It checks the whole segment, not samples along it.\n * Walls retain their thickness; doors/gates cut their actual apertures. Pools and floor holes are\n * obstacles even when a containing room's outer ring includes them. Build once for a document. */\nexport function createRouteClearance(project: ProjectDocument) {\n const junctions = new Map(project.junctions.map(j => [j.id, j.position]));\n const openings = new Map<string, [number, number][]>();\n for (const o of project.objects) {\n if (!o.barrierId || (o.kind !== 'door' && o.kind !== 'gate')) continue;\n const ranges = openings.get(o.barrierId) ?? [];\n ranges.push([(o.offset ?? 0) - o.width / 2, (o.offset ?? 0) + o.width / 2]);\n openings.set(o.barrierId, ranges);\n }\n const walls = new Map<string | null, { ring: Ring; bounds: Bounds }[]>();\n for (const wall of project.barriers) {\n const a = junctions.get(wall.startId),\n b = junctions.get(wall.endId);\n if (!a || !b) continue;\n const length = distance(a, b);\n if (!length) continue;\n const at = (d: number): Point => [a[0] + ((b[0] - a[0]) * d) / length, a[1] + ((b[1] - a[1]) * d) / length];\n const parts = walls.get(wall.floorId) ?? [];\n const nx = (((a[1] - b[1]) / length) * wall.thickness) / 2;\n const ny = (((b[0] - a[0]) / length) * wall.thickness) / 2;\n const add = (from: number, to: number) => {\n if (to <= from) return;\n const start = at(from),\n end = at(to);\n const ring: Ring = [\n [start[0] + nx, start[1] + ny],\n [end[0] + nx, end[1] + ny],\n [end[0] - nx, end[1] - ny],\n [start[0] - nx, start[1] - ny],\n ];\n parts.push({ ring, bounds: routeBounds(ring, ROUTE_CLEARANCE) });\n };\n let cursor = 0;\n for (const [from, to] of (openings.get(wall.id) ?? []).sort((a, b) => a[0] - b[0])) {\n add(cursor, Math.min(length, Math.max(0, from)));\n cursor = Math.max(cursor, Math.min(length, to));\n }\n add(cursor, length);\n walls.set(wall.floorId, parts);\n }\n const holes = new Map<string | null, { ring: Ring; bounds: Bounds }[]>();\n for (const o of project.objects) {\n const rings = o.water\n ? footprint(o).slice(0, 1)\n : o.kind === 'room' || o.kind === 'zone'\n ? footprint(o).slice(1)\n : [];\n const parts = holes.get(o.floorId) ?? [];\n for (const ring of rings) parts.push({ ring: openRing(ring), bounds: routeBounds(ring, ROUTE_CLEARANCE) });\n holes.set(o.floorId, parts);\n }\n /** Restrict the obstacle list once per room or query, so graph construction stays local. */\n return (floorId: string | null, extent?: Bounds) => {\n const localWalls = (walls.get(floorId) ?? []).filter(w => !extent || overlaps(extent, w.bounds));\n const localHoles = (holes.get(floorId) ?? []).filter(h => !extent || overlaps(extent, h.bounds));\n const obstacles = [...localWalls, ...localHoles];\n return (a: Point, b: Point): boolean => {\n const bounds = routeBounds([a, b]);\n for (const h of obstacles) {\n if (!overlaps(bounds, h.bounds)) continue;\n if (pointInRing(a, h.ring) || pointInRing(b, h.ring)) return false;\n for (let i = 0; i < h.ring.length; i++)\n if (gap(a, b, h.ring[i], h.ring[(i + 1) % h.ring.length]) < ROUTE_CLEARANCE - 1e-7) return false;\n }\n return true;\n };\n };\n}\n\nconst cache = new WeakMap<ProjectDocument, ReturnType<typeof createRouteClearance>>();\nexport function routeClearance(project: ProjectDocument) {\n let check = cache.get(project);\n if (!check) {\n check = createRouteClearance(project);\n cache.set(project, check);\n }\n return check;\n}\n","// Indoor-navigation graph: authoring helpers, A-to-B routing (Dijkstra) and human step\n// instructions (graph validation lives in validate.ts). Pure model code — no React, no MapLibre; all geometry stays in the\n// local metric frame, and floor elevations are the real model values (presentation compression of\n// buried floors is a map concern, see src/map/underground.ts).\nimport type { Floor, NavEdge, NavEdgeKind, NavNode, Point, ProjectDocument, SiteObject } from './types';\nimport { uid } from './types';\nimport { distance, objectPosition, pointInRing } from './geometry';\nimport { topology } from './topology';\nimport { servedFloors, shaftKey } from './vertical';\nimport { inSpace, spaceAt } from './spaces';\nimport { routeClearance } from './routeClearance';\nimport type { StatusReading } from './live';\n\n// Cost model in metres-equivalent, exported so editors and play mode price edges identically: a\n// lift ride costs a flat call-and-wait plus a little per metre of rise, stairs cost their run plus\n// a climb penalty — so one storey favours the stairs and a tower ride favours the lift.\nexport const ELEVATOR_BASE = 25,\n ELEVATOR_PER_METRE = 1,\n STAIR_CLIMB_FACTOR = 5,\n DOOR_COST = 1.5;\n/** addNavNode welds onto any existing node within this range (mirrors joinAt's junction reuse). */\nexport const NAV_WELD = 0.25;\n\n// Authored graph wins where a document has one; otherwise the graph is derived from spaces and\n// portals. Routing, the journey player and the route overlay all read through these two accessors,\n// so they need no knowledge of which kind of document they are looking at.\nexport const navNodes = (p: ProjectDocument): NavNode[] => p.navNodes ?? topology(p).nodes;\nexport const navEdges = (p: ProjectDocument): NavEdge[] => p.navEdges ?? topology(p).edges;\nconst floorOf = (p: ProjectDocument, id: string | null): Floor | null =>\n id === null ? null : (p.floors.find(f => f.id === id) ?? null);\nconst elevation = (p: ProjectDocument, id: string | null) => floorOf(p, id)?.elevation ?? 0;\n// Graph validation moved to validate.ts — the validity layer stands on its own.\n\n// ——— Authoring helpers (used by the editor tool and the demo generators).\n/** Find-or-create a route node at a point on a floor, welding onto any node within NAV_WELD. */\nexport function addNavNode(p: ProjectDocument, floorId: string | null, position: Point, objectId?: string): NavNode {\n p.navNodes ??= [];\n const existing = p.navNodes.find(n => n.floorId === floorId && distance(n.position, position) < NAV_WELD);\n if (existing) {\n if (objectId && !existing.objectId) existing.objectId = objectId;\n return existing;\n }\n const node: NavNode = { id: uid(), floorId, position: [position[0], position[1]] };\n if (objectId) node.objectId = objectId;\n p.navNodes.push(node);\n return node;\n}\n/** Connect two nodes, reusing an existing edge of the same kind between the same pair. */\nexport function addNavEdge(p: ProjectDocument, kind: NavEdgeKind, a: NavNode, b: NavNode, objectId?: string): NavEdge {\n p.navEdges ??= [];\n const existing = p.navEdges.find(\n e => e.kind === kind && ((e.aId === a.id && e.bId === b.id) || (e.aId === b.id && e.bId === a.id)),\n );\n if (existing) {\n if (objectId && !existing.objectId) existing.objectId = objectId;\n return existing;\n }\n const edge: NavEdge = { id: uid(), kind, aId: a.id, bId: b.id };\n if (objectId) edge.objectId = objectId;\n p.navEdges.push(edge);\n return edge;\n}\n/** Draw a chain of walk edges through the given points, welding onto existing nodes en route. */\nexport function navPath(p: ProjectDocument, floorId: string | null, points: Point[]): NavNode[] {\n const out = points.map(pt => addNavNode(p, floorId, pt));\n for (let i = 1; i < out.length; i++) if (out[i - 1].id !== out[i].id) addNavEdge(p, 'walk', out[i - 1], out[i]);\n return out;\n}\n/** Thread a vertical connection through an elevator/stairs object: one node per served floor at the object's position. Stairs chain adjacent served floors (you pass every level); an elevator gets an edge per floor pair (a ride is direct, so ELEVATOR_BASE is paid once). Per-floor twin objects share a name (see the demo lifts); pass any one of them and each edge binds the twin on its upper floor. */\nexport function chainVertical(p: ProjectDocument, object: SiteObject): NavNode[] {\n const kind: NavEdgeKind = object.kind === 'elevator' ? 'elevator' : 'stairs';\n // An escalator carries you one way, so the edges it threads are one-way: a route may ride it in\n // the direction it runs and must walk round to come back. A stair has no direction to run in.\n const travel = object.stairModel === 'escalator' ? (object.travel ?? 'up') : null;\n const floors = servedFloors(p, object);\n const key = shaftKey(object);\n const twins = new Map<string | null, SiteObject>();\n for (const o of p.objects)\n if (o.kind === object.kind && shaftKey(o) === key && !twins.has(o.floorId)) twins.set(o.floorId, o);\n const twin = (floorId: string) => twins.get(floorId) ?? object;\n const out = floors.map(f => {\n const t = twin(f.id);\n return addNavNode(p, f.id, objectPosition(p, t), t.id);\n });\n for (let i = 1; i < out.length; i++)\n for (let j = kind === 'elevator' ? 0 : i - 1; j < i; j++) {\n if (out[j].id === out[i].id) continue;\n // Nodes come sorted upwards, so `out[j]` is the lower landing. An escalator running down is\n // the same pair the other way about.\n const [from, to] = travel === 'down' ? [out[i], out[j]] : [out[j], out[i]];\n const edge = addNavEdge(p, kind, from, to, twin(out[i].floorId!).id);\n if (travel) edge.directed = true;\n }\n return out;\n}\n\n// ——— Routing.\nexport interface RouteLeg {\n edge: NavEdge;\n from: NavNode;\n to: NavNode;\n cost: number;\n}\nexport interface RouteStep {\n kind: 'depart' | 'walk' | 'door' | 'stairs' | 'elevator' | 'arrive';\n text: string;\n floorId: string | null;\n nodeIds: string[];\n objectId?: string;\n distance?: number;\n}\n/** Either end of a route: an object in the document by id, or a point on a floor — where the\n * walker is standing, which is the start most people want and no object describes. */\nexport type RouteEnd = string | { name?: string; floorId: string | null; position: Point };\n/** What a route knows about its ends: enough to name them and place them, whether they came from\n * an object or a point. */\nexport type RoutePlace = Pick<SiteObject, 'id' | 'kind' | 'name' | 'floorId' | 'position'>;\n/** The id a host uses for \"where the walker is\" in a picker; findRoute() never sees it. */\nexport const HERE = '@here';\nexport interface Route {\n from: RoutePlace;\n to: RoutePlace;\n nodes: NavNode[];\n legs: RouteLeg[];\n steps: RouteStep[];\n distance: number;\n cost: number;\n}\n\n/** Metres-equivalent cost of traversing an edge; authored weight wins over the derived cost. */\nexport function edgeCost(p: ProjectDocument, edge: NavEdge, a: NavNode, b: NavNode): number {\n if (edge.weight !== undefined) return edge.weight;\n const run = distance(a.position, b.position),\n rise = Math.abs(elevation(p, a.floorId) - elevation(p, b.floorId));\n if (edge.kind === 'elevator') return ELEVATOR_BASE + rise * ELEVATOR_PER_METRE;\n if (edge.kind === 'stairs') return run + rise * STAIR_CLIMB_FACTOR;\n return run + (edge.kind === 'door' ? DOOR_COST : 0);\n}\n/** Walking metres of an edge (horizontal run, plus the rise on vertical edges) — for display, not costing. */\nexport function edgeLength(p: ProjectDocument, edge: NavEdge, a: NavNode, b: NavNode): number {\n const rise =\n edge.kind === 'stairs' || edge.kind === 'elevator'\n ? Math.abs(elevation(p, a.floorId) - elevation(p, b.floorId))\n : 0;\n return distance(a.position, b.position) + rise;\n}\n\n/** Candidate graph entry points for a room/door/poi: nodes bound to the object at cost 0, else nodes inside an area's outer ring, else the nearest node on the object's floor. Cost is the straight-line approach in metres. */\nexport function routeAnchors(p: ProjectDocument, object: SiteObject): { node: NavNode; cost: number }[] {\n const bound = navNodes(p).filter(n => n.objectId === object.id);\n if (bound.length) return bound.map(node => ({ node, cost: 0 }));\n const anchor = objectPosition(p, object);\n const sameFloor = navNodes(p).filter(n => n.floorId === object.floorId);\n const inside = object.rings\n ? sameFloor.filter(\n n => pointInRing(n.position, object.rings![0]) && !object.rings!.slice(1).some(h => pointInRing(n.position, h)),\n )\n : [];\n if (inside.length) return inside.map(node => ({ node, cost: distance(anchor, node.position) }));\n const nearest = sameFloor\n .map(node => ({ node, cost: distance(anchor, node.position) }))\n .sort((a, b) => a.cost - b.cost)[0];\n return nearest ? [nearest] : [];\n}\n\n/** A route's end resolved against the graph: the place it names, the nodes it can join the graph\n * at and what joining costs, and — for a point — the node and edges that stand in for it. A point\n * is not in the graph, so it is given a node of its own, joined by walk edges to the nodes inside\n * the space it stands in (or the nearest node on its floor, standing in a corridor nobody drew as\n * a space). The route then genuinely starts where the walker is, and the first leg is the walk\n * from there to the drawn network. */\nfunction routeEnd(\n p: ProjectDocument,\n end: RouteEnd,\n tag: string,\n): {\n place: RoutePlace;\n anchors: { node: NavNode; cost: number }[];\n extraNodes: NavNode[];\n extraEdges: NavEdge[];\n} | null {\n if (typeof end === 'string') {\n const object = p.objects.find(o => o.id === end);\n return object ? { place: object, anchors: routeAnchors(p, object), extraNodes: [], extraEdges: [] } : null;\n }\n const here: NavNode = { id: `@${tag}`, floorId: end.floorId, position: end.position };\n const sameFloor = navNodes(p).filter(n => n.floorId === end.floorId);\n const space = spaceAt(p, end.floorId, end.position);\n const clear = routeClearance(p)(end.floorId);\n let joins = space ? sameFloor.filter(n => inSpace(space, n.position) && clear(end.position, n.position)) : [];\n if (!space) {\n const nearest = sameFloor\n .filter(n => clear(end.position, n.position))\n .sort((a, b) => distance(a.position, end.position) - distance(b.position, end.position))[0];\n joins = nearest ? [nearest] : [];\n }\n const extraEdges = joins.map(\n (n, i): NavEdge => ({\n id: `@${tag}-${i}`,\n kind: 'walk',\n aId: here.id,\n bId: n.id,\n weight: distance(end.position, n.position),\n }),\n );\n return {\n place: {\n id: `@${tag}`,\n kind: 'poi',\n name: end.name ?? 'Where you are',\n floorId: end.floorId,\n position: end.position,\n },\n anchors: [{ node: here, cost: 0 }],\n extraNodes: [here],\n extraEdges,\n };\n}\n\n/** Shortest route between two ends — objects (rooms, doors, POIs, …) or points on a floor — over\n * the authored graph, with human step instructions. Returns null when either end has no anchor or\n * no path exists. */\nexport interface RouteOptions {\n statuses?: ReadonlyMap<string, StatusReading>;\n}\nexport function findRoute(\n p: ProjectDocument,\n fromEnd: RouteEnd,\n toEnd: RouteEnd,\n options: RouteOptions = {},\n): Route | null {\n const start = routeEnd(p, fromEnd, 'from'),\n end = routeEnd(p, toEnd, 'to');\n if (!start || !end) return null;\n const from = start.place,\n to = end.place;\n const starts = start.anchors,\n goals = end.anchors;\n if (!starts.length || !goals.length) return null;\n const nodes = [...navNodes(p), ...start.extraNodes, ...end.extraNodes],\n byId = new Map(nodes.map(n => [n.id, n]));\n const adjacency = new Map<string, { edge: NavEdge; other: NavNode }[]>();\n for (const e of [...navEdges(p), ...start.extraEdges, ...end.extraEdges]) {\n const a = byId.get(e.aId),\n b = byId.get(e.bId);\n if (!a || !b) continue;\n const machine =\n e.kind === 'stairs' && e.objectId\n ? p.objects.find(o => o.id === e.objectId && o.stairModel === 'escalator')\n : undefined;\n const reading = machine?.feedId ? options.statuses?.get(machine.feedId) : undefined;\n if (machine && (reading?.travel || reading?.running === false)) {\n const up = elevation(p, b.floorId) > elevation(p, a.floorId);\n const forward = (reading.travel ?? machine.travel ?? 'up') === (up ? 'up' : 'down');\n if (reading.running === false || forward)\n (adjacency.get(a.id) ?? adjacency.set(a.id, []).get(a.id)!).push({ edge: e, other: b });\n if (reading.running === false || !forward)\n (adjacency.get(b.id) ?? adjacency.set(b.id, []).get(b.id)!).push({ edge: e, other: a });\n continue;\n }\n (adjacency.get(a.id) ?? adjacency.set(a.id, []).get(a.id)!).push({ edge: e, other: b });\n // A directed edge is passable one way only — an escalator, or a door you cannot come back\n // through. Adding the return leg anyway is how a one-way route quietly becomes a round trip.\n if (!e.directed) (adjacency.get(b.id) ?? adjacency.set(b.id, []).get(b.id)!).push({ edge: e, other: a });\n }\n const queue = new RouteQueue();\n const dist = new Map<string, number>(),\n prev = new Map<string, { node: NavNode; edge: NavEdge }>(),\n done = new Set<string>();\n for (const s of starts)\n if (s.cost < (dist.get(s.node.id) ?? Infinity)) {\n dist.set(s.node.id, s.cost);\n queue.push(s.node.id, s.cost);\n }\n const goalCosts = new Map(goals.map(g => [g.node.id, g.cost]));\n let bestGoal = Infinity;\n for (;;) {\n // A visibility graph can have thousands of nodes. A heap and an admissible goal bound avoid\n // rescanning every reached node and searching the rest of the building after arrival is known.\n const entry = queue.pop();\n if (!entry || entry.cost > bestGoal) break;\n const { id: current, cost: best } = entry;\n if (done.has(current)) continue;\n done.add(current);\n if (goalCosts.has(current)) bestGoal = Math.min(bestGoal, best + goalCosts.get(current)!);\n const node = byId.get(current)!;\n for (const { edge, other } of adjacency.get(current) ?? []) {\n const next = best + edgeCost(p, edge, node, other);\n if (next < (dist.get(other.id) ?? Infinity)) {\n dist.set(other.id, next);\n prev.set(other.id, { node, edge });\n queue.push(other.id, next);\n }\n }\n }\n const goal = goals\n .map(g => ({ ...g, total: (dist.get(g.node.id) ?? Infinity) + g.cost }))\n .sort((a, b) => a.total - b.total)[0];\n if (!goal || !Number.isFinite(goal.total)) return null;\n const legs: RouteLeg[] = [];\n for (let at = goal.node; ; ) {\n const back = prev.get(at.id);\n if (!back) break;\n legs.unshift({ edge: back.edge, from: back.node, to: at, cost: edgeCost(p, back.edge, back.node, at) });\n at = back.node;\n }\n const path = [legs.length ? legs[0].from : goal.node, ...legs.map(l => l.to)];\n const walked = legs.reduce((sum, l) => sum + edgeLength(p, l.edge, l.from, l.to), 0);\n return {\n from,\n to,\n nodes: path,\n legs,\n steps: routeSteps(p, from, to, path, legs),\n distance: walked,\n cost: goal.total,\n };\n}\n\n/** Stable min-heap: equal-cost paths keep insertion order, so a regenerated plan routes identically. */\nclass RouteQueue {\n private items: { id: string; cost: number; order: number }[] = [];\n private order = 0;\n private before(a: (typeof this.items)[number], b: (typeof this.items)[number]) {\n return a.cost < b.cost || (a.cost === b.cost && a.order < b.order);\n }\n push(id: string, cost: number) {\n const item = { id, cost, order: this.order++ };\n let i = this.items.length;\n this.items.push(item);\n while (i > 0) {\n const parent = (i - 1) >> 1;\n if (!this.before(item, this.items[parent])) break;\n this.items[i] = this.items[parent];\n i = parent;\n }\n this.items[i] = item;\n }\n pop() {\n const first = this.items[0],\n last = this.items.pop();\n if (this.items.length && last) {\n let i = 0;\n while (i * 2 + 1 < this.items.length) {\n let child = i * 2 + 1;\n if (child + 1 < this.items.length && this.before(this.items[child + 1], this.items[child])) child++;\n if (!this.before(this.items[child], last)) break;\n this.items[i] = this.items[child];\n i = child;\n }\n this.items[i] = last;\n }\n return first;\n }\n}\n\n// ——— Step instructions.\n/** Human name of a level: \"Menswear & denim (level 3)\" via Floor.code, \"outside\" for the site level. */\nexport function floorPhrase(p: ProjectDocument, floorId: string | null): string {\n const floor = floorOf(p, floorId);\n return !floor ? 'outside' : floor.code ? `${floor.name} (level ${floor.code})` : floor.name;\n}\nconst legName = (p: ProjectDocument, leg: RouteLeg, fallback: string) =>\n p.objects.find(o => o.id === leg.edge.objectId)?.name ?? fallback;\n/** Build the human step list: walking grouped per floor, vertical rides merged per lift/stair name, doors called out — \"Exit through Aleksanterinkatu entrance\", \"Take Lift A to Offices · buying & admin (level 8)\". */\nexport function routeSteps(\n p: ProjectDocument,\n from: RoutePlace,\n to: RoutePlace,\n path: NavNode[],\n legs: RouteLeg[],\n): RouteStep[] {\n const steps: RouteStep[] = [\n {\n kind: 'depart',\n text: `Start at ${from.name}${from.floorId !== null ? ` on ${floorPhrase(p, from.floorId)}` : ''}`,\n floorId: from.floorId,\n nodeIds: path.length ? [path[0].id] : [],\n },\n ];\n for (let i = 0; i < legs.length; i++) {\n const leg = legs[i];\n if (leg.edge.kind === 'walk') {\n // Fold consecutive walk legs on one floor into a single stride.\n let d = edgeLength(p, leg.edge, leg.from, leg.to);\n const nodeIds = [leg.from.id, leg.to.id];\n while (i + 1 < legs.length && legs[i + 1].edge.kind === 'walk') {\n i++;\n d += edgeLength(p, legs[i].edge, legs[i].from, legs[i].to);\n nodeIds.push(legs[i].to.id);\n }\n steps.push({\n kind: 'walk',\n text: `Walk ${Math.max(1, Math.round(d))} m ${legs[i].to.floorId === null ? 'outside' : `along ${floorPhrase(p, leg.from.floorId)}`}`,\n floorId: leg.from.floorId,\n nodeIds,\n distance: d,\n });\n } else if (leg.edge.kind === 'door') {\n const name = legName(p, leg, 'the door');\n const text =\n leg.to.floorId === null && leg.from.floorId !== null\n ? `Exit through ${name}`\n : leg.from.floorId === null && leg.to.floorId !== null\n ? `Enter through ${name}`\n : `Go through ${name}`;\n steps.push({\n kind: 'door',\n text,\n floorId: leg.to.floorId,\n nodeIds: [leg.from.id, leg.to.id],\n objectId: leg.edge.objectId,\n distance: edgeLength(p, leg.edge, leg.from, leg.to),\n });\n } else {\n // Merge a consecutive vertical ride on the same lift/stair name into one instruction.\n const kind = leg.edge.kind,\n name = legName(p, leg, kind === 'elevator' ? 'the lift' : 'the stairs');\n const nodeIds = [leg.from.id, leg.to.id];\n const start = leg.from;\n let end = leg.to;\n let objectId = leg.edge.objectId;\n while (i + 1 < legs.length && legs[i + 1].edge.kind === kind && legName(p, legs[i + 1], name) === name) {\n i++;\n end = legs[i].to;\n nodeIds.push(end.id);\n objectId = legs[i].edge.objectId ?? objectId;\n }\n const rise = elevation(p, end.floorId) - elevation(p, start.floorId);\n const direction = kind === 'stairs' && !/\\b(up|down)\\b/i.test(name) ? `${rise > 0 ? 'up ' : 'down '}` : '';\n steps.push({\n kind,\n text: `Take ${name} ${direction}to ${floorPhrase(p, end.floorId)}`,\n floorId: end.floorId,\n nodeIds,\n objectId,\n });\n }\n }\n steps.push({\n kind: 'arrive',\n text: `Arrive at ${to.name}`,\n floorId: to.floorId,\n nodeIds: path.length ? [path[path.length - 1].id] : [],\n });\n return steps;\n}\n","import type { MaterialKind } from './types';\n\nexport const EXTERIOR_PRESETS = {\n limestone: { name: 'Limestone', material: 'stone', color: '#e2e4e6' },\n brick: { name: 'Warm brick', material: 'brick', color: '#9b705b' },\n darkBrick: { name: 'Dark brick', material: 'brick', color: '#7a4636' },\n plaster: { name: 'Ivory render', material: 'plaster', color: '#e0ddd4' },\n timber: { name: 'Cedar cladding', material: 'timber', color: '#ab8b68' },\n} as const satisfies Record<string, { name: string; material: MaterialKind; color: string }>;\n\nexport type ExteriorPreset = keyof typeof EXTERIOR_PRESETS;\n","/** Numerical tolerances are independent of the user's positioning grid. All values are metres. */\nexport const GEOMETRY_EPS = 1e-6;\nexport const JOIN_EPS = 0.001;\nexport const MIN_WALL_LENGTH = 0.01;\nexport const MIN_RING_EDGE = 0.001;\n/** Usable floor area, after subtracting holes and physical walls, in square metres. */\nexport const MIN_SPACE_AREA = 1;\n/** Topological faces and holes may be smaller than a labelled space. Square metres. */\nexport const MIN_FACE_AREA = 1e-8;\n/** Only derived polygon-clipping inputs use this precision; junctions retain their coordinates. */\nexport const CLIP_SCALE = 1e4;\n","// The validity layer, in one place: every rule a Kerros document must satisfy — structural, ontological,\n// geometric, navigational — and the transaction gate that enforces them on every change.\n//\n// The contract the rest of the library leans on: a ProjectDocument in circulation is ALWAYS valid.\n// Loading validates (importProject, parseExport, the repositories), and editing validates through\n// `transact`, which works on a clone and refuses to return a document that fails any rule — so an\n// invalid state is never observable, only reported as the error that would have created it.\nimport { synchronizeGeometry, validateSpaceBoundaries } from './boundaries';\nimport {\n MIN_SEGMENT,\n OPENING_MIN_SEGMENT,\n barrierEnds,\n containedBy,\n distance,\n intersects,\n openRing,\n objectArea,\n pointInRing,\n ringArea,\n} from './geometry';\nimport { navEdges, navNodes } from './navigation';\nimport { EXTERIOR_PRESETS } from './materials';\nimport { AMBIENCE_PRESETS, OBJECT_KINDS, isArea, isOpening, isSpace } from './types';\nimport type { Ambience, Point, ProjectDocument, Ring, SiteObject } from './types';\nimport { MIN_FACE_AREA, MIN_SPACE_AREA } from './precision';\n\n/** How far from the site origin a coordinate may sit, in metres. A guard against corrupt data, not a\n * modelling limit: no site is 100 km across, but a NaN that became 1e15 through arithmetic would\n * otherwise sail through every finite() check and break projection math much later and much worse. */\nexport const COORD_LIMIT = 100_000;\n\nconst finite = (v: unknown): v is number => typeof v === 'number' && Number.isFinite(v);\nconst point = (v: unknown) =>\n Array.isArray(v) && v.length === 2 && v.every(n => finite(n) && Math.abs(n) <= COORD_LIMIT);\nconst object = (v: unknown): v is Record<string, unknown> => !!v && typeof v === 'object' && !Array.isArray(v);\nconst string = (v: unknown): v is string => typeof v === 'string' && v.length > 0;\nconst distinct = (ids: readonly unknown[]) => new Set(ids).size === ids.length;\n\n/** Geometric sanity of an area's rings: a real outer boundary, no self-crossings, holes inside and\n * disjoint. Returns an error message or null. */\nexport function validateRings(rings: Ring[], minEdge = 0.001, minArea = 0.01): string | null {\n if (!rings.length) return 'Draw an outer boundary first.';\n for (const ring of rings) {\n const p = openRing(ring);\n if (p.length < 3 || ringArea(p) < minArea) return 'An area needs at least three vertices and a non-zero area.';\n for (let i = 0; i < p.length; i++) {\n if (distance(p[i], p[(i + 1) % p.length]) < minEdge) return 'Remove duplicate vertices.';\n for (let j = i + 1; j < p.length; j++) {\n if (j === i + 1 || (i === 0 && j === p.length - 1)) continue;\n if (intersects(p[i], p[(i + 1) % p.length], p[j], p[(j + 1) % p.length]))\n return 'Area boundaries cannot cross themselves.';\n }\n }\n }\n for (let i = 1; i < rings.length; i++) {\n if (!rings[i].every(p => pointInRing(p, rings[0]))) return 'A hole must be completely inside the outer boundary.';\n for (let j = 0; j < i; j++) {\n const a = openRing(rings[i]),\n b = openRing(rings[j]);\n for (let k = 0; k < a.length; k++)\n for (let l = 0; l < b.length; l++)\n if (intersects(a[k], a[(k + 1) % a.length], b[l], b[(l + 1) % b.length]))\n return 'Hole boundaries must not touch or overlap.';\n if (j > 0 && (pointInRing(a[0], b) || pointInRing(b[0], a))) return 'Holes cannot overlap.';\n }\n }\n return null;\n}\n\n/** Spatial relationships between entities: ring sanity per object, parent containment without\n * cycles, and openings that actually fit the barriers they sit in. */\nexport function validateRelationships(project: ProjectDocument): string | null {\n // A facade can have thousands of windows. Index attachments once per validation pass rather\n // than searching every object again for every opening; drafts may mutate between passes.\n const objects = new Map(project.objects.map(o => [o.id, o]));\n const barriers = new Map(project.barriers.map(b => [b.id, b]));\n const attachments = new Map<string, SiteObject[]>();\n for (const o of project.objects) {\n if (!o.barrierId) continue;\n const list = attachments.get(o.barrierId) ?? [];\n list.push(o);\n attachments.set(o.barrierId, list);\n }\n // Reject degenerate segments, while allowing real returns and jambs below the drawing-grid size.\n for (const barrier of project.barriers) {\n const [a, b] = barrierEnds(project, barrier);\n if (distance(a, b) < MIN_SEGMENT - 1e-6) return `A wall or fence must be at least ${MIN_SEGMENT} m long.`;\n }\n for (const object of project.objects) {\n if (object.rings) {\n const shared = object.geometry?.mode === 'boundaries';\n const error = validateRings(object.rings, shared ? 1e-6 : 0.001, shared ? MIN_FACE_AREA : 0.01);\n if (error) return error;\n }\n if (object.parentId) {\n const parent = objects.get(object.parentId);\n if (\n !parent?.rings ||\n !object.rings ||\n parent.floorId !== object.floorId ||\n !containedBy(object.rings, parent.rings)\n )\n return 'A nested zone must remain inside its parent on the same floor.';\n const seen = new Set([object.id]);\n let ancestor: SiteObject | undefined = parent;\n while (ancestor) {\n if (seen.has(ancestor.id)) return 'Zone parents cannot form a cycle.';\n seen.add(ancestor.id);\n ancestor = ancestor.parentId ? objects.get(ancestor.parentId) : undefined;\n }\n }\n if (object.barrierId) {\n // Only an opening belongs in a barrier: a camera \"set into\" a wall is a placement bug, and\n // validating it as an opening would let it punch a hole through the rendering.\n if (!isOpening(object.kind)) return 'Only a door, window or gate can sit in a barrier.';\n const barrier = barriers.get(object.barrierId);\n if (!barrier || barrier.floorId !== object.floorId)\n return 'Opening references a missing barrier or a different floor.';\n const [a, b] = barrierEnds(project, barrier);\n // Actual opening width decides the required wall length, including narrow windows and doors.\n if (distance(a, b) < OPENING_MIN_SEGMENT - 1e-6)\n return `A door, window or gate needs a segment at least ${OPENING_MIN_SEGMENT} m long to sit in.`;\n const offset = object.offset ?? 0;\n if (offset - object.width / 2 < -0.001 || offset + object.width / 2 > distance(a, b) + 0.001)\n return `The barrier is too short for its attached opening. Opening \"${object.name || object.id}\" (${object.id}) on barrier ${barrier.id}: width ${object.width.toFixed(2)} m, centre offset ${offset.toFixed(2)} m, segment length ${distance(a, b).toFixed(2)} m. The centre offset must be between ${(object.width / 2).toFixed(2)} and ${(distance(a, b) - object.width / 2).toFixed(2)} m; if that interval is empty, choose a longer host segment.`;\n if (\n attachments\n .get(barrier.id)!\n .some(o => o.id !== object.id && Math.abs((o.offset ?? 0) - offset) < (o.width + object.width) / 2 - 0.001)\n )\n return 'Attached openings cannot overlap.';\n }\n }\n return null;\n}\n\n/** Semantic validation of the navigation graph — authored or derived; structural checks (ids,\n * uniqueness) live in validateProject. Returns an error message or null. */\nexport function validateNavigation(p: ProjectDocument): string | null {\n const nodes = navNodes(p),\n byId = new Map(nodes.map(n => [n.id, n]));\n const objects = new Map(p.objects.map(o => [o.id, o]));\n const floorIds = new Set(p.floors.map(f => f.id));\n for (const n of nodes) {\n if (!point(n.position)) return 'A route node needs a valid position.';\n if (n.floorId !== null && !floorIds.has(n.floorId)) return 'A route node references an unknown floor.';\n if (n.objectId !== undefined && !objects.has(n.objectId)) return 'A route node references a missing object.';\n }\n for (const e of navEdges(p)) {\n if (!['walk', 'door', 'stairs', 'elevator'].includes(e.kind)) return 'Unknown route edge kind.';\n const a = byId.get(e.aId),\n b = byId.get(e.bId);\n if (!a || !b || e.aId === e.bId) return 'A route edge must join two different route nodes.';\n if (e.weight !== undefined && (typeof e.weight !== 'number' || !Number.isFinite(e.weight) || e.weight <= 0))\n return 'A route edge weight must be a positive number.';\n const vertical = e.kind === 'stairs' || e.kind === 'elevator';\n if (vertical && a.floorId === b.floorId) return 'Stairs and elevator edges must join different floors.';\n if (e.kind === 'walk' && a.floorId !== b.floorId) return 'Walk edges must stay on one floor.';\n if (e.kind === 'door' && a.floorId !== b.floorId && a.floorId !== null && b.floorId !== null)\n return 'Door edges must stay on one floor or step outside.';\n if (e.objectId === undefined) continue;\n const object = objects.get(e.objectId);\n if (!object) return 'A route edge references a missing object.';\n if (e.kind === 'door' && !['door', 'gate', 'turnstile'].includes(object.kind))\n return 'A door edge must bind a door, gate or turnstile.';\n if (vertical && object.kind !== e.kind) return 'A vertical edge must bind a matching stairs or elevator object.';\n // Only meaningful when the object declares which floors it serves. A lift whose floors come from\n // a zone's `connects` declares nothing here, and is correct by construction — the edges were\n // generated from that zone's own membership, so there is no second list to disagree with.\n if (\n vertical &&\n object.servedFloorIds &&\n [a, b].some(n => n.floorId !== null && !object.servedFloorIds!.includes(n.floorId))\n )\n return 'A vertical edge joins a floor its stairs or elevator does not serve.';\n }\n return null;\n}\n\n/** Parse and validate an unknown value into a ProjectDocument; throws with a reason on any failure.\n * Every rule the schema has lives behind this one entry point. */\nexport function validateProject(value: unknown): ProjectDocument {\n const fail = (message: string): never => {\n throw new Error(`Invalid project: ${message}`);\n };\n // One version until the first release. The schema is still being cut, so rather than carry\n // migrations for shapes nobody has shipped against, anything else is simply not a Kerros document.\n if (!object(value) || value.schemaVersion !== 1)\n fail(\n 'unsupported schema version (expected 1). The schema is still changing before release — re-create the project.',\n );\n const v = value as Record<string, unknown>;\n // Origin is [lng, lat, bearing?] in WGS84 — the range check also flags pre-v2 projected (metre) origins.\n const origin = (o: unknown) =>\n Array.isArray(o) &&\n (o.length === 2 || o.length === 3) &&\n o.every(finite) &&\n Math.abs(o[0]) <= 180 &&\n Math.abs(o[1]) <= 90;\n if (\n !string(v.id) ||\n !string(v.name) ||\n !origin(v.origin) ||\n typeof v.description !== 'string' ||\n typeof v.datum !== 'string' ||\n !string(v.updatedAt)\n )\n fail('missing project metadata.');\n for (const key of ['buildings', 'floors', 'junctions', 'barriers', 'objects', 'drawings'])\n if (!Array.isArray(v[key]) || (v[key] as unknown[]).some(x => !object(x) || !string(x.id)))\n fail(`malformed ${key}.`);\n for (const key of ['navNodes', 'navEdges', 'zones', 'portals', 'portalGroups', 'virtualBoundaries'] as const)\n if (\n v[key] !== undefined &&\n (!Array.isArray(v[key]) || (v[key] as unknown[]).some(x => !object(x) || !string(x.id)))\n )\n fail(`malformed ${key}.`);\n const p = v as unknown as ProjectDocument;\n const all = [\n ...p.buildings,\n ...p.floors,\n ...p.junctions,\n ...p.barriers,\n ...(p.virtualBoundaries ?? []),\n ...p.objects,\n ...p.drawings,\n ...(p.navNodes ?? []),\n ...(p.navEdges ?? []),\n ...(p.zones ?? []),\n ...(p.portals ?? []),\n ...(p.portalGroups ?? []),\n ];\n if (new Set(all.map(x => x.id)).size !== all.length) fail('duplicate entity IDs.');\n const floorIds = new Set(p.floors.map(f => f.id)),\n buildingIds = new Set(p.buildings.map(b => b.id));\n if (\n !p.buildings.length ||\n p.buildings.some(\n b => !string(b.name) || (b.sourceId !== undefined && !string(b.sourceId) && !finite(b.sourceId)),\n ) ||\n !p.floors.length ||\n p.floors.some(\n f =>\n !buildingIds.has(f.buildingId) || !string(f.name) || !finite(f.elevation) || !finite(f.height) || f.height <= 0,\n )\n )\n fail('invalid buildings or floors.');\n // An escalator runs one way; a stair does not have a way to run. Saying a staircase travels up\n // describes nothing, and something downstream would eventually believe it.\n if (\n p.objects.some(o => o.travel !== undefined && (o.kind !== 'stairs' || (o.travel !== 'up' && o.travel !== 'down')))\n )\n fail('travel belongs to an escalator and must be up or down.');\n // A lamp that exists: a colour temperature inside the range a luminaire is actually made in, and\n // a level between off and fully lit. Absent is the common case and means a fluorescent ceiling.\n if (\n p.floors.some(\n f =>\n f.light !== undefined &&\n (!finite(f.light.kelvin) ||\n f.light.kelvin < 1000 ||\n f.light.kelvin > 12000 ||\n !finite(f.light.level) ||\n f.light.level < 0 ||\n f.light.level > 1 ||\n (f.light.tint !== undefined && (typeof f.light.tint !== 'string' || !/^#[0-9a-f]{6}$/i.test(f.light.tint)))),\n )\n )\n fail('a floor names a light that is not a lamp.');\n const badAmbience = (a: Ambience | undefined) =>\n a !== undefined &&\n (!AMBIENCE_PRESETS.includes(a.preset) ||\n (a.level !== undefined && (!finite(a.level) || a.level < 0 || a.level > 1)));\n if (p.floors.some(f => badAmbience(f.ambience)) || p.objects.some(o => badAmbience(o.ambience)))\n fail('an ambience names a preset that does not exist, or a level outside 0..1.');\n if (p.initialFloorId !== undefined && p.initialFloorId !== null && !p.floors.some(f => f.id === p.initialFloorId))\n fail('initialFloorId names a floor that does not exist.');\n if (p.buildings.some(b => b.exteriorPreset !== undefined && !Object.hasOwn(EXTERIOR_PRESETS, b.exteriorPreset)))\n fail('unknown exterior preset.');\n for (const e of [...p.junctions, ...p.barriers, ...p.objects, ...p.drawings])\n if (e.floorId !== null && !floorIds.has(e.floorId)) fail('unknown floor reference.');\n if (p.junctions.some(j => !point(j.position))) fail('invalid junction coordinates.');\n for (const edge of p.virtualBoundaries ?? []) {\n const a = p.junctions.find(j => j.id === edge.startId),\n b = p.junctions.find(j => j.id === edge.endId);\n if (\n !a ||\n !b ||\n a.floorId !== edge.floorId ||\n b.floorId !== edge.floorId ||\n distance(a.position, b.position) < 0.001 - 1e-6\n )\n fail('invalid virtual boundary.');\n }\n if (\n p.barriers.some(\n b =>\n !['wall', 'fence'].includes(b.kind) ||\n !string(b.name) ||\n !p.junctions.some(j => j.id === b.startId && j.floorId === b.floorId) ||\n !p.junctions.some(j => j.id === b.endId && j.floorId === b.floorId) ||\n b.startId === b.endId ||\n !finite(b.height) ||\n b.height <= 0 ||\n !finite(b.thickness) ||\n b.thickness <= 0,\n )\n )\n fail('invalid barrier.');\n // The drawn areas of each level, gathered once: the served-floor rule below asks what is under a\n // shaft on every level it claims, and a department store asks that a couple of hundred times.\n const areasByFloor = new Map<string, SiteObject[]>();\n for (const o of p.objects)\n if (o.floorId && isArea(o.kind) && Array.isArray(o.rings) && Array.isArray(o.rings[0]))\n areasByFloor.set(o.floorId, [...(areasByFloor.get(o.floorId) ?? []), o]);\n for (const o of p.objects) {\n if (\n !(OBJECT_KINDS as readonly string[]).includes(o.kind) ||\n !string(o.name) ||\n !point(o.position) ||\n !finite(o.rotation) ||\n !finite(o.width) ||\n o.width <= 0 ||\n !finite(o.depth) ||\n o.depth <= 0 ||\n !finite(o.height) ||\n o.height < 0\n )\n fail('invalid object dimensions or type.');\n if (o.rings && (!Array.isArray(o.rings) || o.rings.some(r => !Array.isArray(r) || r.some(p => !point(p)))))\n fail('invalid polygon coordinates.');\n if (o.servedFloorIds && (!Array.isArray(o.servedFloorIds) || o.servedFloorIds.some(id => !floorIds.has(id))))\n fail('unknown served floor.');\n if (o.servedFloorIds && !distinct(o.servedFloorIds)) fail('served floors must be listed once each.');\n // A shaft stands in one place and reaches a list of levels, so the plan has to agree with itself\n // about that place: where the drawn areas of the levels it serves put floor under it, they all\n // have to. One that lands on twelve plates and falls outside the thirteenth is the real case —\n // a lift core beside a mezzanine gallery, its doors opening onto the hall two storeys down, and\n // routing sending someone through them. Judged on outer boundaries only (a hole is exactly where\n // a shaft belongs: a stair in a light well, a lift in an atrium), and only against levels that\n // are drawn at all — a plan whose floors are not areas yet says nothing about any of its shafts,\n // which is why a shaft standing off every one of them is left alone.\n if (o.servedFloorIds && (o.kind === 'stairs' || o.kind === 'elevator')) {\n const drawn = o.servedFloorIds.map(id => areasByFloor.get(id)).filter(areas => !!areas?.length);\n const on = drawn.map(areas => areas!.some(a => pointInRing(o.position, (a.rings as Ring[])[0])));\n if (on.some(Boolean) && !on.every(Boolean))\n fail('a stair or lift serves a level it does not stand on — its landing there opens onto nothing.');\n }\n if (o.doorHinge !== undefined || o.doorSwing !== undefined || o.doorType !== undefined) {\n if (o.kind !== 'door') fail('only doors carry mechanism, hinge and swing settings.');\n if (o.doorType !== undefined && !['hinged', 'sliding', 'double'].includes(o.doorType))\n fail('door type must be hinged, sliding or double.');\n if (o.doorHinge !== undefined && !['left', 'right'].includes(o.doorHinge))\n fail('door hinge must be left or right.');\n if (o.doorSwing !== undefined && o.doorSwing !== 1 && o.doorSwing !== -1) fail('door swing must be 1 or -1.');\n }\n if (o.doorSides !== undefined) {\n if (o.kind !== 'elevator') fail('only an elevator lists door sides.');\n if (\n !Array.isArray(o.doorSides) ||\n !o.doorSides.length ||\n o.doorSides.some(d => !['front', 'back', 'left', 'right'].includes(d as string)) ||\n !distinct(o.doorSides as string[])\n )\n fail('door sides are front, back, left or right, listed once each.');\n }\n if (o.wellGroup !== undefined && (o.kind !== 'stairs' || !string(o.wellGroup) || !o.wellGroup.trim()))\n fail('only stairs carry a non-empty shared well group.');\n if (o.stairModel !== undefined) {\n if (o.kind !== 'stairs') fail('only stairs carry a stair model.');\n if (!['straight', 'switchback', 'dogleg', 'spiral', 'escalator'].includes(o.stairModel as string))\n fail('a stair model is straight, switchback, dogleg, spiral or escalator.');\n }\n if (o.light !== undefined || o.kind === 'light') {\n const lamp = o.light;\n if (\n o.kind !== 'light' ||\n !object(lamp) ||\n (lamp.mountHeight !== undefined &&\n (!finite(lamp.mountHeight) || lamp.mountHeight < -20 || lamp.mountHeight > 100)) ||\n !finite(lamp.kelvin) ||\n lamp.kelvin < 1000 ||\n lamp.kelvin > 12000 ||\n !finite(lamp.intensity) ||\n lamp.intensity < 0 ||\n lamp.intensity > 10000 ||\n !finite(lamp.range) ||\n lamp.range <= 0 ||\n lamp.range > 100 ||\n (lamp.flicker !== undefined && (!finite(lamp.flicker) || lamp.flicker < 0 || lamp.flicker > 1))\n )\n fail('a light needs a valid colour temperature, intensity, range and optional flicker.');\n }\n if (o.watchedIds && (!Array.isArray(o.watchedIds) || o.watchedIds.some(id => !p.objects.some(x => x.id === id))))\n fail('unknown watched object.');\n if (o.watchedIds && !distinct(o.watchedIds)) fail('watched objects must be listed once each.');\n if (\n o.ceilingHeight !== undefined &&\n (!['room', 'zone'].includes(o.kind as string) || !finite(o.ceilingHeight) || o.ceilingHeight <= 0)\n )\n fail('a space ceiling height must be positive.');\n if (\n o.baseHeight !== undefined &&\n (o.kind !== 'fixture' || !finite(o.baseHeight) || o.baseHeight < 0 || o.baseHeight > 100)\n )\n fail('a raised fixture needs a base height between 0 and 100 m.');\n if (o.water !== undefined) {\n const water = o.water;\n if (\n !['room', 'zone'].includes(o.kind as string) ||\n !o.rings ||\n !object(water) ||\n !finite(water.depth) ||\n water.depth <= 0 ||\n water.depth > 20 ||\n (water.ripple !== undefined && (!finite(water.ripple) || water.ripple < 0 || water.ripple > 0.1))\n )\n fail('water needs an area, a depth up to 20 m and ripples up to 10 cm.');\n }\n if (o.slide !== undefined) {\n const slide = o.slide;\n if (\n o.kind !== 'fixture' ||\n !object(slide) ||\n !finite(slide.radius) ||\n slide.radius <= 0 ||\n !Array.isArray(slide.path) ||\n slide.path.length < 2 ||\n slide.path.length > 100 ||\n !slide.path.every(p => Array.isArray(p) && p.length === 3 && p.every(finite) && (p[2] as number) >= 0)\n )\n fail('a water slide needs a positive radius and a finite path above its floor.');\n }\n if (o.slope !== undefined) {\n const s = o.slope;\n if (\n !object(s) ||\n !Array.isArray(s.axis) ||\n s.axis.length !== 2 ||\n !s.axis.every(point) ||\n !finite(s.high) ||\n !finite(s.low) ||\n distance(s.axis[0] as Point, s.axis[1] as Point) < 0.01 ||\n s.high < s.low\n )\n fail('invalid slope: needs a downhill two-point axis (high >= low) of non-zero length.');\n if (!o.rings) fail('a sloped object must be an area with a footprint.');\n }\n if (o.category !== undefined && !string(o.category)) fail('object category must be a string.');\n if (o.metadata !== undefined && !object(o.metadata)) fail('object metadata must be an object.');\n if (o.barrierId && !finite(o.offset)) fail('missing opening offset.');\n if (o.feedId !== undefined && typeof o.feedId !== 'string') fail('invalid feed binding.');\n if (o.coverageRange !== undefined && (!finite(o.coverageRange) || o.coverageRange <= 0))\n fail('invalid camera range.');\n if (o.coverageAngle !== undefined && (!finite(o.coverageAngle) || o.coverageAngle <= 0 || o.coverageAngle > 360))\n fail('invalid camera angle.');\n }\n for (const d of p.drawings)\n if (\n !string(d.assetId) ||\n !string(d.name) ||\n !point(d.origin) ||\n !finite(d.scale) ||\n d.scale <= 0 ||\n !finite(d.width) ||\n d.width <= 0 ||\n !finite(d.height) ||\n d.height <= 0 ||\n !finite(d.rotation) ||\n !finite(d.opacity) ||\n d.opacity < 0 ||\n d.opacity > 1 ||\n typeof d.visible !== 'boolean' ||\n typeof d.locked !== 'boolean'\n )\n fail('invalid reference drawing.');\n // ——— The spatial ontology. Spaces are the ringed area objects; zones and portals only reference\n // them, so every reference has to resolve or the derived graph would quietly lose edges.\n const spaceIds = new Set(p.objects.filter(o => isSpace(o.kind)).map(o => o.id));\n const kindById = new Map(p.objects.map(o => [o.id, o.kind]));\n const zoneIds = new Set((p.zones ?? []).map(z => z.id));\n for (const z of p.zones ?? []) {\n if (!string(z.name) || !Array.isArray(z.spaceIds)) fail('a zone needs a name and a list of spaces.');\n if (z.spaceIds.some(id => !spaceIds.has(id))) fail('a zone lists a space that is not an area object.');\n if (!distinct(z.spaceIds)) fail('a zone must list each space once — membership is a set.');\n if (z.childZoneIds && z.childZoneIds.some(id => !zoneIds.has(id))) fail('a zone nests a zone that does not exist.');\n if (z.childZoneIds && !distinct(z.childZoneIds)) fail('a zone must nest each child once.');\n if (z.connects !== undefined && !['all', 'adjacent', 'up', 'down'].includes(z.connects))\n fail(\"a zone's connects must be 'all', 'adjacent', 'up' or 'down'.\");\n }\n // Zones nest as a DAG. Cycles are tolerated at read time (ontology.ts guards) but are still a\n // malformed document, and saying so here is cheaper than debugging a zone that contains itself.\n const walking = new Set<string>(),\n settled = new Set<string>();\n const cycles = (id: string): boolean => {\n if (settled.has(id)) return false;\n if (walking.has(id)) return true;\n walking.add(id);\n const found = ((p.zones ?? []).find(z => z.id === id)?.childZoneIds ?? []).some(cycles);\n walking.delete(id);\n settled.add(id);\n return found;\n };\n if ([...zoneIds].some(cycles)) fail('zones cannot contain themselves.');\n for (const portal of p.portals ?? []) {\n if (!spaceIds.has(portal.a) || !spaceIds.has(portal.b))\n fail('a portal must join two areas that exist on the plan.');\n if (portal.a === portal.b) fail('a portal must join two different spaces.');\n // A window is an opening but never a portal — you cannot walk through it. Same list as\n // inference's TRAVERSABLE, inlined so the rules depend on nothing that changes at runtime.\n if (portal.openingId && !['door', 'gate', 'turnstile'].includes(kindById.get(portal.openingId) ?? ''))\n fail(\"a portal's opening must be a door, gate or turnstile.\");\n if (portal.passage !== undefined && !['both', 'a-to-b', 'b-to-a', 'none'].includes(portal.passage))\n fail('invalid portal passage direction.');\n if (portal.attests !== undefined && !['confirmed', 'assumed', 'none'].includes(portal.attests))\n fail('invalid portal attestation.');\n }\n const portalIds = new Set((p.portals ?? []).map(x => x.id));\n for (const g of p.portalGroups ?? []) {\n if (!string(g.name) || !Array.isArray(g.portalIds) || g.portalIds.some(id => !portalIds.has(id)))\n fail('a portal group needs a name and must list portals that exist.');\n if (!distinct(g.portalIds)) fail('a portal group must list each portal once.');\n }\n const error = validateRelationships(p);\n if (error) fail(error);\n validateSpaceBoundaries(p);\n const navError = validateNavigation(p);\n if (navError) fail(navError);\n return p;\n}\n\n// ——— The transaction gate.\n\n/** Deep-freeze a document in place and return it. Writes to a frozen document throw (modules run in\n * strict mode), so an out-of-band mutation — one that dodged `transact` — fails at the assignment\n * that would have corrupted the document, not three renders later. */\nexport function freezeProject(project: ProjectDocument): ProjectDocument {\n const walk = (value: unknown) => {\n if (value && typeof value === 'object' && !Object.isFrozen(value)) {\n Object.freeze(value);\n for (const inner of Object.values(value)) walk(inner);\n }\n };\n walk(project);\n return project;\n}\n\nexport type TransactResult = { ok: true; project: ProjectDocument } | { ok: false; error: string };\n\n/** Apply a change atomically: work on a clone, run every rule, and only then hand the result back —\n * frozen, so nothing can edit it except the next transaction. If the change throws, or the outcome\n * breaks any rule, the original is untouched and the reason comes back as `error`; there is no\n * state in which a caller holds a partly-applied or invalid document.\n *\n * `updatedAt` is deliberately not stamped here — that belongs to whoever owns persistence and\n * history (see commitHistory), which also stamps undo and redo. */\nexport function transact(\n project: ProjectDocument,\n change: (draft: ProjectDocument) => void,\n options?: { freeze?: boolean },\n): TransactResult {\n try {\n const draft = structuredClone(project); // clones of frozen objects are mutable: drafts stay editable\n change(draft);\n synchronizeGeometry(project, draft);\n // Older imported outlines remain readable. New or resized areas use the same usable-area\n // minimum as enclosure and splitting; changing a name never invalidates a legacy small area.\n for (const o of draft.objects)\n if (isArea(o.kind) && objectArea(o) < MIN_SPACE_AREA) {\n const old = project.objects.find(previous => previous.id === o.id && isArea(previous.kind));\n if (!old || objectArea(old) !== objectArea(o))\n throw new Error(\n `A space needs at least ${MIN_SPACE_AREA} m² of usable area. \"${o.name || o.id}\" (${o.id}) has ${objectArea(o).toFixed(3)} m².`,\n );\n }\n validateProject(draft);\n return { ok: true, project: options?.freeze === false ? draft : freezeProject(draft) };\n } catch (error) {\n return { ok: false, error: error instanceof Error ? error.message : String(error) };\n }\n}\n","// The shared 2D boundary model. Barriers ARE physical edges; only unwalled edges need another record.\n// Space loops reference these edges. Coordinates in rings are generated compatibility/render caches.\nimport polygonClipping from 'polygon-clipping';\nimport { validateRings } from './validate';\nimport type { Barrier, BoundaryUse, Point, ProjectDocument, Ring, SiteObject, VirtualBoundary } from './types';\nimport { isArea, uid } from './types';\nimport {\n addBarrier,\n centroid,\n closeRing,\n distance,\n footprint,\n openRing,\n pointInRing,\n rectangle,\n removeBarrier,\n ringArea,\n segmentProjection,\n} from './geometry';\nimport {\n CLIP_SCALE,\n GEOMETRY_EPS as EPS,\n MIN_FACE_AREA,\n MIN_RING_EDGE,\n MIN_SPACE_AREA,\n MIN_WALL_LENGTH,\n} from './precision';\n\nexport type BoundaryEdge = Barrier | VirtualBoundary;\nexport interface BoundaryRegion {\n loops: BoundaryUse[][];\n /** Centreline polygon, including holes. Net footprints also subtract the physical wall bodies. */\n rings: Ring[];\n}\nexport const boundaryEdges = (p: ProjectDocument): BoundaryEdge[] => [...p.barriers, ...(p.virtualBoundaries ?? [])];\nexport const followsBoundaries = (o: SiteObject) => o.geometry?.mode === 'boundaries';\nconst ends = (p: ProjectDocument, e: BoundaryEdge): [Point, Point] => {\n const a = p.junctions.find(j => j.id === e.startId),\n b = p.junctions.find(j => j.id === e.endId);\n if (!a || !b) throw new Error('A space boundary references a missing junction.');\n return [a.position, b.position];\n};\nconst reverse = (loop: BoundaryUse[]) => [...loop].reverse().map(u => ({ edgeId: u.edgeId, reversed: !u.reversed }));\nconst signedArea = (ring: Ring) =>\n ring.reduce((s, a, i) => {\n const b = ring[(i + 1) % ring.length];\n return s + a[0] * b[1] - b[0] * a[1];\n }, 0) / 2;\nconst area = (rings: Ring[]) => ringArea(rings[0]) - rings.slice(1).reduce((s, r) => s + ringArea(r), 0);\nconst totalArea = (polys: Ring[][]) => polys.reduce((s, pg) => s + area(pg), 0);\nconst quantize = (rings: Ring[]) =>\n rings.map(r =>\n closeRing(r).map(\n q => [Math.round(q[0] * CLIP_SCALE) / CLIP_SCALE, Math.round(q[1] * CLIP_SCALE) / CLIP_SCALE] as Point,\n ),\n );\n/** Integer input coordinates avoid binary near-duplicates in the clipper's event queue. The\n * output keeps much finer precision so independently computed shared intersections agree. */\nfunction difference(subject: Ring[], ...clips: Ring[][]): Ring[][] {\n const scaled = (rings: Ring[]) =>\n rings.map(r => closeRing(r).map(q => [Math.round(q[0] * CLIP_SCALE), Math.round(q[1] * CLIP_SCALE)] as Point));\n const input = scaled(subject),\n operands = clips.map(scaled);\n let result: Ring[][];\n try {\n result = polygonClipping.difference(input, ...operands) as Ring[][];\n } catch {\n // An equivalent Boolean evaluation avoids a clipper event-queue failure with many nearly\n // coincident wall corners. Do not quantize intermediate results or discard failed polygons.\n result = [input];\n for (const operand of operands) {\n if (!result.length) break;\n result = polygonClipping.difference(result, operand) as Ring[][];\n }\n }\n return result.map(pg =>\n pg.map(r =>\n r.map(\n q => [Math.round((q[0] / CLIP_SCALE) * 1e10) / 1e10, Math.round((q[1] / CLIP_SCALE) * 1e10) / 1e10] as Point,\n ),\n ),\n );\n}\n\n/** Keep every reference correct when a physical/virtual edge is split or replaced. */\nexport function replaceBoundaryUses(p: ProjectDocument, edgeId: string, replacement: BoundaryUse[]) {\n for (const o of p.objects)\n if (o.geometry?.mode === 'boundaries')\n o.geometry.loops = o.geometry.loops.map(loop =>\n loop.flatMap(u => (u.edgeId !== edgeId ? [u] : u.reversed ? reverse(replacement) : replacement)),\n );\n}\n\nexport function boundaryRings(p: ProjectDocument, loops: BoundaryUse[][], floorId: string | null): Ring[] {\n const edges = new Map(boundaryEdges(p).map(e => [e.id, e]));\n return loops.map(loop => {\n if (loop.length < 3) throw new Error('A space boundary must form a closed loop.');\n const ring: Ring = [];\n for (let i = 0; i < loop.length; i++) {\n const u = loop[i],\n next = loop[(i + 1) % loop.length];\n const e = edges.get(u.edgeId),\n n = edges.get(next.edgeId);\n if (!e || !n || e.floorId !== floorId || n.floorId !== floorId)\n throw new Error('A space boundary references a missing edge or another floor.');\n if ((u.reversed ? e.startId : e.endId) !== (next.reversed ? n.endId : n.startId))\n throw new Error('Space boundary edges must share their junctions in order.');\n ring.push(ends(p, e)[u.reversed ? 1 : 0]);\n }\n return closeRing(ring);\n });\n}\n\nfunction splitEdge(p: ProjectDocument, edge: BoundaryEdge, cuts: { t: number; id: string }[]) {\n const [a, b] = ends(p, edge),\n length = distance(a, b);\n const interior = cuts.filter(c => c.t > EPS / length && c.t < 1 - EPS / length).sort((x, y) => x.t - y.t);\n const unique = interior.filter((c, i) => i === 0 || c.id !== interior[i - 1].id);\n if (!unique.length) return;\n const stops = [{ t: 0, id: edge.startId }, ...unique, { t: 1, id: edge.endId }];\n const openings = p.objects.filter(o => o.barrierId === edge.id);\n for (const c of unique)\n for (const o of openings)\n if (Math.abs((o.offset ?? 0) - c.t * length) < o.width / 2 - EPS)\n throw new Error('A junction cannot split an opening.');\n const physical = 'kind' in edge;\n const pieces = stops.slice(1).map((end, i) => {\n const start = stops[i];\n if ((end.t - start.t) * length < (physical ? MIN_WALL_LENGTH : MIN_RING_EDGE) - EPS)\n throw new Error(\n `That crossing would leave a boundary segment too short. \"${'name' in edge ? edge.name : edge.id}\" would be ${((end.t - start.t) * length).toFixed(4)} m long.`,\n );\n return { ...edge, id: i === 0 ? edge.id : uid(), startId: start.id, endId: end.id };\n });\n for (const o of openings) {\n const at = (o.offset ?? 0) / length;\n const i = stops.slice(1).findIndex(s => at <= s.t + EPS);\n o.barrierId = pieces[i].id;\n o.offset = (o.offset ?? 0) - stops[i].t * length;\n }\n replaceBoundaryUses(\n p,\n edge.id,\n pieces.map(e => ({ edgeId: e.id })),\n );\n Object.assign(edge, pieces[0]);\n if (physical) p.barriers.push(...(pieces.slice(1) as Barrier[]));\n else (p.virtualBoundaries ??= []).push(...pieces.slice(1));\n}\n\n/** Planarize a floor: one junction at each intersection, with overlaps represented once.\n * Exact calculated intersections are shared; the input grid is not applied again here. */\nexport function normalizeBoundaries(p: ProjectDocument, floorId: string | null) {\n const edges = boundaryEdges(p).filter(e => e.floorId === floorId);\n const junctions = p.junctions.filter(j => j.floorId === floorId);\n const canonical = new Map<string, string>();\n const representatives: typeof junctions = [];\n for (const j of junctions) {\n const earlier = representatives.find(k => distance(k.position, j.position) <= EPS);\n if (earlier) canonical.set(j.id, earlier.id);\n else representatives.push(j);\n }\n for (const e of edges) {\n e.startId = canonical.get(e.startId) ?? e.startId;\n e.endId = canonical.get(e.endId) ?? e.endId;\n }\n p.junctions = p.junctions.filter(j => !canonical.has(j.id));\n const positions = new Map(p.junctions.map(j => [j.id, j.position]));\n // Resolve endpoints once, before the broad-phase pair scan. Looking each one up in the\n // full junction list inside the nested loop made planarization cubic in floor size.\n const spans = edges.map(e => ({\n points: [positions.get(e.startId)!, positions.get(e.endId)!] as [Point, Point],\n box: bounds([positions.get(e.startId)!, positions.get(e.endId)!]),\n }));\n const cuts = new Map<string, { t: number; id: string }[]>();\n const cut = (e: BoundaryEdge, at: Point) => {\n const [a, b] = ends(p, e),\n hit = segmentProjection(at, a, b);\n let j = p.junctions.find(j => j.floorId === floorId && distance(j.position, at) <= EPS);\n if (!j) {\n j = { id: uid(), floorId, position: at };\n p.junctions.push(j);\n }\n const list = cuts.get(e.id) ?? [];\n list.push({ t: hit.t, id: j.id });\n cuts.set(e.id, list);\n };\n for (let i = 0; i < edges.length; i++)\n for (let k = i + 1; k < edges.length; k++) {\n if (!boundsMeet(spans[i].box, spans[k].box)) continue;\n const one = edges[i],\n two = edges[k],\n [a, b] = spans[i].points,\n [c, d] = spans[k].points;\n const ux = b[0] - a[0],\n uy = b[1] - a[1],\n vx = d[0] - c[0],\n vy = d[1] - c[1];\n const det = ux * vy - uy * vx;\n const sharedEnd =\n one.startId === two.startId ||\n one.startId === two.endId ||\n one.endId === two.startId ||\n one.endId === two.endId;\n // Lines with a shared endpoint already have their intersection. Solving again for almost\n // parallel edges amplifies cancellation and can invent a second, microscopic cut beside it.\n // Still check endpoint projections below: collinear edges can overlap beyond the junction.\n if (!sharedEnd && Math.abs(det) > 1e-12 * Math.hypot(ux, uy) * Math.hypot(vx, vy)) {\n const t = ((c[0] - a[0]) * vy - (c[1] - a[1]) * vx) / det;\n const s = ((c[0] - a[0]) * uy - (c[1] - a[1]) * ux) / det;\n if (\n t >= -EPS / Math.hypot(ux, uy) &&\n t <= 1 + EPS / Math.hypot(ux, uy) &&\n s >= -EPS / Math.hypot(vx, vy) &&\n s <= 1 + EPS / Math.hypot(vx, vy)\n ) {\n const at: Point = [a[0] + Math.max(0, Math.min(1, t)) * ux, a[1] + Math.max(0, Math.min(1, t)) * uy];\n cut(one, at);\n cut(two, at);\n }\n } else {\n for (const at of [a, b])\n if (segmentProjection(at, c, d).distance <= EPS) {\n cut(one, at);\n cut(two, at);\n }\n for (const at of [c, d])\n if (segmentProjection(at, a, b).distance <= EPS) {\n cut(one, at);\n cut(two, at);\n }\n }\n }\n for (const e of edges) splitEdge(p, e, cuts.get(e.id) ?? []);\n // Physical edges precede virtual ones, so drawing a wall on a virtual division builds that wall.\n const byEnds = new Map<string, BoundaryEdge>();\n const removed = new Set<string>();\n for (const e of boundaryEdges(p).filter(e => e.floorId === floorId)) {\n const key = [e.startId, e.endId].sort().join('|'),\n kept = byEnds.get(key);\n if (!kept) {\n byEnds.set(key, e);\n continue;\n }\n const flipped = e.startId !== kept.startId;\n replaceBoundaryUses(p, e.id, [{ edgeId: kept.id, reversed: flipped }]);\n for (const o of p.objects.filter(o => o.barrierId === e.id)) {\n o.barrierId = kept.id;\n if (flipped) {\n o.offset = distance(...ends(p, kept)) - (o.offset ?? 0);\n if (o.kind === 'door') {\n o.doorHinge = o.doorHinge === 'right' ? 'left' : 'right';\n o.doorSwing = o.doorSwing === -1 ? 1 : -1;\n }\n }\n }\n removed.add(e.id);\n }\n p.barriers = p.barriers.filter(e => !removed.has(e.id));\n if (p.virtualBoundaries) p.virtualBoundaries = p.virtualBoundaries.filter(e => !removed.has(e.id));\n const used = new Set(boundaryEdges(p).flatMap(e => [e.startId, e.endId]));\n p.junctions = p.junctions.filter(j => !canonical.has(j.id) || used.has(j.id));\n}\n\n/** Bounded faces of the shared graph. Bridges do not divide a face; nested components form holes. */\nexport function boundaryRegions(p: ProjectDocument, floorId: string | null): BoundaryRegion[] {\n const edges = boundaryEdges(p).filter(e => e.floorId === floorId);\n const outgoing = new Map<string, { edge: BoundaryEdge; to: string }[]>();\n for (const e of edges)\n for (const [a, b] of [\n [e.startId, e.endId],\n [e.endId, e.startId],\n ]) {\n const list = outgoing.get(a) ?? [];\n list.push({ edge: e, to: b });\n outgoing.set(a, list);\n }\n const entered = new Map<string, number>(),\n low = new Map<string, number>(),\n bridges = new Set<string>();\n let time = 0;\n const visit = (at: string, parent?: string) => {\n entered.set(at, ++time);\n low.set(at, time);\n for (const { edge, to } of outgoing.get(at) ?? []) {\n if (edge.id === parent) continue;\n if (!entered.has(to)) {\n visit(to, edge.id);\n low.set(at, Math.min(low.get(at)!, low.get(to)!));\n if (low.get(to)! > entered.get(at)!) bridges.add(edge.id);\n } else low.set(at, Math.min(low.get(at)!, entered.get(to)!));\n }\n };\n for (const at of outgoing.keys()) if (!entered.has(at)) visit(at);\n const positions = new Map(p.junctions.map(j => [j.id, j.position]));\n for (const [at, list] of outgoing) {\n const a = positions.get(at)!;\n outgoing.set(\n at,\n list\n .filter(x => !bridges.has(x.edge.id))\n .sort((x, y) => {\n const b = positions.get(x.to)!,\n c = positions.get(y.to)!;\n return Math.atan2(b[1] - a[1], b[0] - a[0]) - Math.atan2(c[1] - a[1], c[0] - a[0]);\n }),\n );\n }\n const seen = new Set<string>(),\n cycles: { loop: BoundaryUse[]; ring: Ring }[] = [];\n for (const e of edges.filter(e => !bridges.has(e.id)))\n for (const reversed of [false, true]) {\n let use: BoundaryUse = { edgeId: e.id, reversed },\n current = e;\n const first = `${e.id}:${reversed}`,\n loop: BoundaryUse[] = [],\n ring: Ring = [];\n if (seen.has(first)) continue;\n for (let step = 0; step <= edges.length * 2; step++) {\n const key = `${use.edgeId}:${!!use.reversed}`;\n if (seen.has(key)) break;\n seen.add(key);\n loop.push(use);\n const from = use.reversed ? current.endId : current.startId,\n to = use.reversed ? current.startId : current.endId;\n ring.push(positions.get(from)!);\n const list = outgoing.get(to)!;\n const back = list.findIndex(x => x.edge.id === current.id);\n const next = list[(back + list.length - 1) % list.length];\n current = next.edge;\n use = { edgeId: current.id, reversed: current.endId === to };\n if (`${use.edgeId}:${!!use.reversed}` === first) break;\n }\n if (signedArea(ring) >= MIN_FACE_AREA) cycles.push({ loop, ring: closeRing(ring) });\n }\n const parent = cycles.map(\n (child, i) =>\n cycles\n .map((candidate, j) => ({ j, candidate }))\n .filter(\n ({ candidate, j }) =>\n j !== i &&\n ringArea(candidate.ring) > ringArea(child.ring) + EPS &&\n child.ring.every(q => pointInRing(q, candidate.ring)) &&\n !child.loop.some(u => candidate.loop.some(v => v.edgeId === u.edgeId)),\n )\n .sort((a, b) => ringArea(a.candidate.ring) - ringArea(b.candidate.ring))[0]?.j,\n );\n return cycles.map((c, i) => {\n const holes = cycles.filter((_, j) => parent[j] === i);\n return {\n loops: [c.loop, ...holes.map(h => reverse(h.loop))],\n rings: [c.ring, ...holes.map(h => closeRing([...openRing(h.ring)].reverse()))],\n };\n });\n}\n\nfunction wallBodies(p: ProjectDocument, floorId: string | null): Ring[][] {\n // Subdividing a straight wall must not change its swept body through separate rounding at\n // each new endpoint. Reconstitute collinear runs for clipping, retaining the individual IDs.\n const positions = new Map(p.junctions.map(j => [j.id, j.position]));\n const runs = p.barriers\n .filter(b => b.floorId === floorId)\n .map(b => ({\n points: [positions.get(b.startId)!, positions.get(b.endId)!] as [Point, Point],\n thickness: b.thickness,\n }));\n for (let i = 0; i < runs.length; i++) {\n let merged = true;\n while (merged) {\n merged = false;\n for (let k = i + 1; k < runs.length; k++) {\n const one = runs[i],\n two = runs[k];\n if (one.thickness !== two.thickness) continue;\n const [a, b] = one.points,\n [c, d] = two.points;\n const ab = distance(a, b),\n cd = distance(c, d);\n if (Math.abs((b[0] - a[0]) * (d[1] - c[1]) - (b[1] - a[1]) * (d[0] - c[0])) > EPS * ab * cd) continue;\n const pair = [\n [a, c, b, d],\n [a, d, b, c],\n [b, c, a, d],\n [b, d, a, c],\n ].find(([x, y]) => distance(x, y) <= EPS);\n if (!pair) continue;\n one.points = [pair[2], pair[3]];\n runs.splice(k, 1);\n merged = true;\n break;\n }\n }\n }\n return runs.map(({ points: [a, c], thickness }) => {\n // Canonical orientation makes reversed strokes use exactly the same clipping coordinates.\n if (a[0] > c[0] || (a[0] === c[0] && a[1] > c[1])) [a, c] = [c, a];\n const len = distance(a, c);\n return quantize([\n rectangle(\n [(a[0] + c[0]) / 2, (a[1] + c[1]) / 2],\n len + thickness,\n thickness,\n (Math.atan2(c[1] - a[1], c[0] - a[0]) * 180) / Math.PI,\n ),\n ]);\n });\n}\nfunction tidy(ring: Ring): Ring {\n const out: Ring = [];\n for (const q of openRing(ring)) if (!out.length || distance(out.at(-1)!, q) >= EPS) out.push(q);\n if (out.length > 1 && distance(out[0], out.at(-1)!) < EPS) out.pop();\n return closeRing(out);\n}\ntype Bounds = { minX: number; minY: number; maxX: number; maxY: number };\nconst bounds = (ring: Ring): Bounds => {\n let minX = Infinity,\n minY = Infinity,\n maxX = -Infinity,\n maxY = -Infinity;\n for (const [x, y] of ring) {\n minX = Math.min(minX, x);\n minY = Math.min(minY, y);\n maxX = Math.max(maxX, x);\n maxY = Math.max(maxY, y);\n }\n return { minX, minY, maxX, maxY };\n};\nconst boundsMeet = (a: Bounds, b: Bounds) =>\n a.minX <= b.maxX + EPS && a.maxX + EPS >= b.minX && a.minY <= b.maxY + EPS && a.maxY + EPS >= b.minY;\n\n/** Short-lived evaluation scope: coordinates are fixed during one refresh/validation pass. Reuse\n * wall bodies across its spaces, without caching a mutable transaction draft between edits. */\nfunction netEvaluator(p: ProjectDocument) {\n const floors = new Map<string | null, { rings: Ring[]; box: Bounds }[]>();\n return (floorId: string | null, rings: Ring[], allowEmpty = false): Ring[] => {\n let solids = floors.get(floorId);\n if (!solids) {\n solids = wallBodies(p, floorId).map(rings => ({ rings, box: bounds(rings[0]) }));\n floors.set(floorId, solids);\n }\n const box = bounds(rings[0]);\n const nearby = solids.filter(s => boundsMeet(s.box, box)).map(s => s.rings);\n return netRings(rings, nearby, allowEmpty);\n };\n}\nfunction netRings(rings: Ring[], solids: Ring[][], allowEmpty = false): Ring[] {\n const pieces = solids.length ? difference(rings, ...solids) : [quantize(rings)];\n const usable = pieces.filter(pg => area(pg) >= MIN_SPACE_AREA);\n if (!usable.length && allowEmpty) return [];\n if (!usable.length)\n throw new Error(\n `A space needs at least ${MIN_SPACE_AREA} m² of usable area. Largest region after subtracting walls: ${Math.max(0, ...pieces.map(pg => area(pg))).toFixed(3)} m².`,\n );\n if (usable.length !== 1)\n throw new Error(\n `The wall would leave ${usable.length} disconnected usable regions (${usable.map(pg => area(pg).toFixed(2)).join(', ')} m²). Extend it to a boundary to divide the space.`,\n );\n return usable[0].map(tidy);\n}\nexport function derivedSpaceRings(p: ProjectDocument, o: SiteObject): Ring[] {\n if (o.geometry?.mode !== 'boundaries') return footprint(o);\n return netEvaluator(p)(o.floorId, boundaryRings(p, o.geometry.loops, o.floorId));\n}\nfunction cacheRings(o: SiteObject, rings: Ring[]) {\n o.rings = rings;\n o.position = centroid(rings[0]);\n o.rotation = 0;\n const xs = rings[0].map(q => q[0]),\n ys = rings[0].map(q => q[1]);\n o.width = Math.max(...xs) - Math.min(...xs);\n o.depth = Math.max(...ys) - Math.min(...ys);\n}\n\nexport function bindSpaceToRegion(p: ProjectDocument, o: SiteObject, region: BoundaryRegion) {\n if (!isArea(o.kind)) throw new Error('Only a drawn area can use shared boundaries.');\n o.geometry = { mode: 'boundaries', loops: structuredClone(region.loops) };\n cacheRings(o, derivedSpaceRings(p, o));\n}\nexport function boundaryRegionAt(p: ProjectDocument, floorId: string | null, point: Point): BoundaryRegion | null {\n return (\n boundaryRegions(p, floorId)\n .filter(r => pointInRing(point, r.rings[0]) && !r.rings.slice(1).some(h => pointInRing(point, h)))\n .sort((a, b) => area(a.rings) - area(b.rings))[0] ?? null\n );\n}\n\nfunction junctionAt(p: ProjectDocument, floorId: string | null, point: Point): string {\n const existing = p.junctions.find(j => j.floorId === floorId && distance(j.position, point) <= EPS);\n if (existing) return existing.id;\n const id = uid();\n p.junctions.push({ id, floorId, position: point });\n return id;\n}\nexport function addVirtualBoundary(p: ProjectDocument, floorId: string | null, a: Point, b: Point): string {\n if (distance(a, b) < MIN_RING_EDGE) throw new Error('A space boundary is too short.');\n const startId = junctionAt(p, floorId, a),\n endId = junctionAt(p, floorId, b);\n const existing = boundaryEdges(p).find(\n e =>\n e.floorId === floorId &&\n ((e.startId === startId && e.endId === endId) || (e.startId === endId && e.endId === startId)),\n );\n if (existing) return existing.id;\n const id = uid();\n (p.virtualBoundaries ??= []).push({ id, floorId, startId, endId });\n return id;\n}\n\n/** The drawing tool intentionally opens any collinear wall span. Ordinary addVirtualBoundary\n * remains non-destructive for generated space outlines and model normalization. */\nexport function drawVirtualBoundary(p: ProjectDocument, floorId: string | null, a: Point, b: Point): string {\n const length = distance(a, b);\n if (length < MIN_RING_EDGE) throw new Error('A space boundary is too short.');\n const onLine = (q: Point) => Math.abs((b[0] - a[0]) * (q[1] - a[1]) - (b[1] - a[1]) * (q[0] - a[0])) / length <= EPS;\n for (const wall of [...p.barriers].filter(w => w.floorId === floorId)) {\n const [start, end] = ends(p, wall);\n if (!onLine(start) || !onLine(end)) continue;\n const cuts = [a, b].flatMap(q => {\n const hit = segmentProjection(q, start, end);\n return hit.distance <= EPS && hit.t > 0 && hit.t < 1 ? [{ t: hit.t, id: junctionAt(p, floorId, hit.point) }] : [];\n });\n splitEdge(p, wall, cuts);\n }\n for (const wall of [...p.barriers].filter(w => w.floorId === floorId)) {\n if (!ends(p, wall).every(q => segmentProjection(q, a, b).distance <= EPS)) continue;\n // Retain the edge identity and room loops, even when no room has claimed it yet.\n (p.virtualBoundaries ??= []).push({ id: wall.id, floorId, startId: wall.startId, endId: wall.endId });\n removeBarrier(p, wall.id);\n }\n return addVirtualBoundary(p, floorId, a, b);\n}\n\n/** Explicit conversion: retain the drawn shape with shared virtual edges, or adopt its enclosing\n * walls on request. Legacy documents remain independent until this operation is chosen. */\nexport function connectSpace(p: ProjectDocument, objectId: string, source: 'outline' | 'walls' = 'outline') {\n const o = p.objects.find(o => o.id === objectId);\n if (!o || !isArea(o.kind)) throw new Error('Select an area to connect to boundaries.');\n if (source === 'walls') {\n normalizeBoundaries(p, o.floorId);\n // A concave outline's label position can lie outside it. An explicit adoption uses the\n // region containing the greatest part of its footprint, and refuses ambiguous choices.\n const sourceRings = footprint(o),\n sourceArea = area(sourceRings);\n const candidates = boundaryRegions(p, o.floorId)\n .map(region => ({\n region,\n overlap: sourceArea - totalArea(difference(sourceRings, region.rings)),\n }))\n .filter(c => c.overlap > EPS)\n .sort((a, b) => b.overlap - a.overlap);\n if (candidates.length > 1 && Math.abs(candidates[0].overlap - candidates[1].overlap) < EPS)\n throw new Error('More than one region matches this outline. Use Space from walls inside the intended region.');\n const region = candidates[0]?.region;\n if (!region) throw new Error('No closed wall boundary surrounds this space.');\n bindSpaceToRegion(p, o, region);\n return;\n }\n const loops = footprint(o).map((ring, ri) => {\n let points = openRing(ring);\n if (signedArea(points) > 0 !== (ri === 0)) points = [...points].reverse();\n return points.map((a, i) => {\n const b = points[(i + 1) % points.length],\n edgeId = addVirtualBoundary(p, o.floorId, a, b);\n const e = boundaryEdges(p).find(e => e.id === edgeId)!;\n return { edgeId, reversed: distance(ends(p, e)[0], a) > EPS };\n });\n });\n o.geometry = { mode: 'boundaries', loops };\n normalizeBoundaries(p, o.floorId);\n cacheRings(o, derivedSpaceRings(p, o));\n}\nexport function disconnectSpace(p: ProjectDocument, objectId: string) {\n const o = p.objects.find(o => o.id === objectId);\n if (o) o.geometry = { mode: 'independent' };\n}\n\nexport function addBoundaryHole(p: ProjectDocument, o: SiteObject, ring: Ring) {\n if (o.geometry?.mode !== 'boundaries') throw new Error('Select a space with shared boundaries.');\n let points = openRing(ring);\n if (signedArea(points) > 0) points = [...points].reverse();\n const loop = points.map((a, i) => {\n const edgeId = addVirtualBoundary(p, o.floorId, a, points[(i + 1) % points.length]);\n const e = boundaryEdges(p).find(e => e.id === edgeId)!;\n return { edgeId, reversed: distance(ends(p, e)[0], a) > EPS };\n });\n o.geometry.loops.push(loop);\n}\n\nexport function splitBoundarySpace(p: ProjectDocument, o: SiteObject, a: Point, b: Point, wall = true): string {\n if (o.geometry?.mode !== 'boundaries') throw new Error('This space has no shared boundaries.');\n const length = distance(a, b);\n if (length < EPS) throw new Error('Draw a line across the space.');\n const dx = (b[0] - a[0]) / length,\n dy = (b[1] - a[1]) / length;\n const hits: number[] = [];\n for (const closed of boundaryRings(p, o.geometry.loops, o.floorId)) {\n const r = openRing(closed);\n for (let i = 0; i < r.length; i++) {\n const c = r[i],\n d = r[(i + 1) % r.length],\n ex = d[0] - c[0],\n ey = d[1] - c[1];\n const det = dx * ey - dy * ex;\n if (Math.abs(det) < 1e-12) continue;\n const t = ((c[0] - a[0]) * dy - (c[1] - a[1]) * dx) / det;\n if (t >= -EPS && t <= 1 + EPS) hits.push(((c[0] - a[0]) * ey - (c[1] - a[1]) * ex) / det);\n }\n }\n hits.sort((x, y) => x - y);\n const unique = hits.filter((x, i) => i === 0 || x - hits[i - 1] > EPS);\n for (let i = 0; i + 1 < unique.length; i += 2) {\n const start: Point = [a[0] + unique[i] * dx, a[1] + unique[i] * dy];\n const end: Point = [a[0] + unique[i + 1] * dx, a[1] + unique[i + 1] * dy];\n if (wall) {\n const edge = addBarrier(p, start, end, o.floorId, 'wall');\n if (edge) {\n edge.name = 'Partition';\n edge.thickness = 0.18;\n }\n } else addVirtualBoundary(p, o.floorId, start, end);\n }\n normalizeBoundaries(p, o.floorId);\n const created = refreshBoundarySpaces(p);\n if (!created.length) throw new Error('The cut must divide the space into usable regions.');\n return created[0];\n}\n\n/** Join centreline loops before deriving the net footprint, including the former wall's floor area. */\nexport function mergeBoundaryGeometry(p: ProjectDocument, keep: SiteObject, absorbed: SiteObject): boolean {\n if (keep.geometry?.mode !== 'boundaries' || absorbed.geometry?.mode !== 'boundaries')\n throw new Error('Connect both spaces to shared boundaries before merging their boundaries.');\n const a = keep.geometry.loops.flat(),\n b = absorbed.geometry.loops.flat();\n const shared = new Set(\n a.filter(u => b.some(v => v.edgeId === u.edgeId && !!v.reversed !== !!u.reversed)).map(u => u.edgeId),\n );\n if (!shared.size) return false;\n if (p.barriers.some(e => shared.has(e.id))) throw new Error('Remove the dividing wall before merging these spaces.');\n const edges = new Map(boundaryEdges(p).map(e => [e.id, e]));\n const remaining = [...a, ...b].filter(u => !shared.has(u.edgeId));\n const loops: BoundaryUse[][] = [];\n while (remaining.length) {\n const loop = [remaining.shift()!];\n const first = edges.get(loop[0].edgeId)!;\n const start = loop[0].reversed ? first.endId : first.startId;\n let at = loop[0].reversed ? first.startId : first.endId;\n while (at !== start) {\n const index = remaining.findIndex(u => {\n const e = edges.get(u.edgeId)!;\n return (u.reversed ? e.endId : e.startId) === at;\n });\n if (index < 0) throw new Error('The merged space boundary is not closed.');\n const u = remaining.splice(index, 1)[0],\n e = edges.get(u.edgeId)!;\n loop.push(u);\n at = u.reversed ? e.startId : e.endId;\n }\n loops.push(loop);\n }\n loops.sort(\n (a, b) =>\n signedArea(openRing(boundaryRings(p, [b], keep.floorId)[0])) -\n signedArea(openRing(boundaryRings(p, [a], keep.floorId)[0])),\n );\n keep.geometry = { mode: 'boundaries', loops };\n p.virtualBoundaries = (p.virtualBoundaries ?? []).filter(\n e =>\n !shared.has(e.id) ||\n p.objects.some(\n o =>\n o.id !== absorbed.id &&\n o.geometry?.mode === 'boundaries' &&\n o.geometry.loops.some(l => l.some(u => u.edgeId === e.id)),\n ),\n );\n cacheRings(keep, derivedSpaceRings(p, keep));\n return true;\n}\n\n/** A removed wall leaves the semantic division as a virtual boundary. */\nexport function preserveBoundary(p: ProjectDocument, edge: BoundaryEdge) {\n if (\n !p.objects.some(\n o => o.geometry?.mode === 'boundaries' && o.geometry.loops.some(l => l.some(u => u.edgeId === edge.id)),\n )\n )\n return;\n if (!(p.virtualBoundaries ?? []).some(e => e.id === edge.id))\n (p.virtualBoundaries ??= []).push({ id: edge.id, floorId: edge.floorId, startId: edge.startId, endId: edge.endId });\n}\n\n/** Regenerate by explicit loops, subdividing identities only when a new boundary divides a space.\n * No old/new footprint-overlap matching is involved in ordinary wall movements. */\nexport function refreshBoundarySpaces(p: ProjectDocument, topologyChanged?: Set<string | null>): string[] {\n const created: string[] = [],\n regions = new Map<string | null, BoundaryRegion[]>();\n const net = netEvaluator(p);\n for (const o of [...p.objects]) {\n if (o.geometry?.mode !== 'boundaries') continue;\n const envelope = boundaryRings(p, o.geometry.loops, o.floorId);\n // Moving a vertex changes the shape of a face, not its identity. Only a changed edge graph\n // needs face discovery and polygon containment against every other region on the floor.\n if (topologyChanged && !topologyChanged.has(o.floorId)) {\n cacheRings(o, net(o.floorId, envelope));\n continue;\n }\n if (!regions.has(o.floorId)) regions.set(o.floorId, boundaryRegions(p, o.floorId));\n const inside = regions.get(o.floorId)!.filter(r => totalArea(difference(r.rings, envelope)) < EPS);\n if (!inside.length) throw new Error('The space boundaries no longer form a closed region.');\n inside.sort((a, b) => area(b.rings) - area(a.rings));\n // Interior walls can eliminate a tiny region, but a labelled space must never disappear silently.\n const usable = inside\n .map(r => ({ region: r, rings: net(o.floorId, r.rings, inside.length > 1) }))\n .filter(r => r.rings.length)\n .sort((a, b) => area(b.rings) - area(a.rings));\n if (!usable.length) throw new Error('The walls would remove all usable area from this space.');\n for (let i = 0; i < usable.length; i++) {\n const target = i === 0 ? o : { ...structuredClone(o), id: uid(), name: `${o.name} ${i + 1}`, feedId: undefined };\n target.geometry = { mode: 'boundaries', loops: structuredClone(usable[i].region.loops) };\n cacheRings(target, usable[i].rings);\n if (i > 0) {\n p.objects.push(target);\n created.push(target.id);\n for (const z of p.zones ?? []) if (z.spaceIds.includes(o.id)) z.spaceIds.push(target.id);\n }\n }\n }\n return created;\n}\n\n/** One synchronization gate for UI gestures, host mutations, history and persistence. */\nexport function synchronizeGeometry(before: ProjectDocument, p: ProjectDocument) {\n // A host may install the frozen result of another transaction in its draft (e.g. a constrained\n // drag). Thaw those collections before the normalization pass, without touching its input.\n for (const key of ['barriers', 'junctions', 'objects', 'virtualBoundaries', 'zones'] as const) {\n const collection = p[key];\n if (collection && (Object.isFrozen(collection) || collection.some(e => Object.isFrozen(e))))\n Object.assign(p, { [key]: structuredClone(collection) });\n }\n const edges = boundaryEdges(p),\n ids = new Set(edges.map(e => e.id));\n for (const e of boundaryEdges(before))\n if (!ids.has(e.id)) {\n preserveBoundary(p, e);\n if ((p.virtualBoundaries ?? []).some(v => v.id === e.id))\n for (const id of [e.startId, e.endId]) {\n if (!p.junctions.some(j => j.id === id)) {\n const old = before.junctions.find(j => j.id === id);\n if (old) p.junctions.push(structuredClone(old));\n }\n }\n }\n const signature = (doc: ProjectDocument, floor: string | null) =>\n JSON.stringify([\n boundaryEdges(doc)\n .filter(e => e.floorId === floor)\n .map(e => [e.id, e.startId, e.endId]),\n doc.junctions.filter(j => j.floorId === floor).map(j => [j.id, j.position]),\n ]);\n const floors = new Set(boundaryEdges(p).map(e => e.floorId));\n for (const floor of floors) if (signature(before, floor) !== signature(p, floor)) normalizeBoundaries(p, floor);\n const topology = (doc: ProjectDocument, floor: string | null) =>\n JSON.stringify(\n boundaryEdges(doc)\n .filter(e => e.floorId === floor)\n .map(e => [e.id, e.startId, e.endId]),\n );\n const changed = new Set([...floors].filter(floor => topology(before, floor) !== topology(p, floor)));\n refreshBoundarySpaces(p, changed);\n}\n\n/** Validate the explicit topology and its cache. Independent polygons retain their existing rules. */\nexport function validateSpaceBoundaries(p: ProjectDocument) {\n const occupied = new Set<string>();\n const faces = new Map<string | null, Set<string>>();\n const net = netEvaluator(p);\n const loopKey = (loops: BoundaryUse[][]) =>\n loops\n .flat()\n .map(u => `${u.edgeId}:${!!u.reversed}`)\n .sort()\n .join('|');\n for (const o of p.objects) {\n if (o.geometry === undefined) continue;\n if (!o.geometry || !['independent', 'boundaries'].includes(o.geometry.mode))\n throw new Error('Unknown space geometry mode.');\n if (o.geometry.mode === 'independent') continue;\n if (\n !isArea(o.kind) ||\n !Array.isArray(o.geometry.loops) ||\n !o.geometry.loops.length ||\n o.geometry.loops.some(\n l =>\n !Array.isArray(l) ||\n l.some(\n u => !u || typeof u.edgeId !== 'string' || (u.reversed !== undefined && typeof u.reversed !== 'boolean'),\n ),\n )\n )\n throw new Error('Malformed space boundary loops.');\n const rings = boundaryRings(p, o.geometry.loops, o.floorId);\n const issue = validateRings(rings, EPS, MIN_FACE_AREA);\n if (issue) throw new Error(issue);\n if (signedArea(openRing(rings[0])) <= 0 || rings.slice(1).some(r => signedArea(openRing(r)) >= 0))\n throw new Error('Space boundary loops must keep the space on their left.');\n if (!faces.has(o.floorId)) faces.set(o.floorId, new Set(boundaryRegions(p, o.floorId).map(r => loopKey(r.loops))));\n if (!faces.get(o.floorId)!.has(loopKey(o.geometry.loops)))\n throw new Error('A connected space must follow one face of the boundary network.');\n for (const loop of o.geometry.loops)\n for (const u of loop) {\n const key = `${u.edgeId}:${!!u.reversed}`;\n if (occupied.has(key)) throw new Error('Two spaces cannot occupy the same side of a shared boundary.');\n occupied.add(key);\n }\n const calculated = net(o.floorId, rings);\n if (\n !o.rings ||\n calculated.length !== o.rings.length ||\n calculated.some(\n (r, ri) => r.length !== o.rings![ri].length || r.some((q, i) => distance(q, o.rings![ri][i]) > EPS),\n )\n )\n throw new Error('The space footprint is stale. Update it through a geometry transaction.');\n const xs = calculated[0].map(q => q[0]),\n ys = calculated[0].map(q => q[1]);\n if (\n distance(o.position, centroid(calculated[0])) > EPS ||\n Math.abs(o.width - (Math.max(...xs) - Math.min(...xs))) > EPS ||\n Math.abs(o.depth - (Math.max(...ys) - Math.min(...ys))) > EPS ||\n o.rotation !== 0\n )\n throw new Error('A boundary-driven space has stale calculated dimensions.');\n }\n}\n","import polygonClipping from 'polygon-clipping';\nimport type {\n Barrier,\n Drawing,\n Origin,\n Point,\n ProjectDocument,\n Ring,\n SiteObject,\n Slope,\n VirtualBoundary,\n} from './types';\nimport { uid } from './types';\nimport { boundaryEdges, preserveBoundary, replaceBoundaryUses, splitBoundarySpace } from './boundaries';\nimport { GEOMETRY_EPS, JOIN_EPS, MIN_RING_EDGE, MIN_SPACE_AREA, MIN_WALL_LENGTH } from './precision';\n\nexport const distance = (a: Point, b: Point) => Math.hypot(a[0] - b[0], a[1] - b[1]);\nexport const rotate = (p: Point, degrees: number): Point => {\n const r = (degrees * Math.PI) / 180;\n return [p[0] * Math.cos(r) - p[1] * Math.sin(r), p[0] * Math.sin(r) + p[1] * Math.cos(r)];\n};\n// Local planar frame via an ellipsoidal local-tangent-plane around the origin's lng/lat — accurate to\n// sub-centimetre at building scale with no projection library and no region assumption. `origin` is\n// [lng, lat, bearing?]; origin[2] is the site bearing (clockwise from true north), so a plan can align\n// to a real street grid while its coordinates stay simple and axis-aligned.\nconst DEG = Math.PI / 180,\n WGS84_A = 6378137,\n WGS84_E2 = 0.00669437999014;\nconst metresPerDegree = (lat: number) => {\n const s = Math.sin(lat * DEG) ** 2;\n return {\n lng: DEG * (WGS84_A / Math.sqrt(1 - WGS84_E2 * s)) * Math.cos(lat * DEG),\n lat: (DEG * (WGS84_A * (1 - WGS84_E2))) / (1 - WGS84_E2 * s) ** 1.5,\n };\n};\nexport const geoOrigin = (lngLat: Point, bearing = 0): Origin =>\n bearing ? [lngLat[0], lngLat[1], bearing] : [lngLat[0], lngLat[1]];\n/** Shift a site anchor by a distance on the ground, in metres east and north.\n *\n * Nudging a building into place is a thing you do in metres — \"half a metre that way\" — and the\n * anchor is stored in degrees, where the useful step depends on latitude and differs between the\n * two axes. Deliberately NOT rotated by the site bearing: this moves the site across the world,\n * and the directions that make sense for that are the compass ones, not the plan's own grid. */\nexport const moveOrigin = (origin: Origin, east: number, north: number): Origin => {\n const m = metresPerDegree(origin[1]);\n const moved: Origin = [origin[0] + east / m.lng, origin[1] + north / m.lat];\n return origin[2] ? [moved[0], moved[1], origin[2]] : moved;\n};\nexport const toLocal = (lngLat: Point, origin: Origin): Point => {\n const m = metresPerDegree(origin[1]);\n const d: Point = [(lngLat[0] - origin[0]) * m.lng, (lngLat[1] - origin[1]) * m.lat];\n return origin[2] ? rotate(d, origin[2]) : d;\n};\nexport const toLngLat = (p: Point, origin: Origin): Point => {\n const m = metresPerDegree(origin[1]);\n const r = origin[2] ? rotate(p, -origin[2]) : p;\n return [origin[0] + r[0] / m.lng, origin[1] + r[1] / m.lat];\n};\nexport const add = (a: Point, b: Point): Point => [a[0] + b[0], a[1] + b[1]];\nexport const closeRing = (ring: Ring): Ring =>\n !ring.length ? [] : distance(ring[0], ring[ring.length - 1]) < 1e-8 ? ring : [...ring, ring[0]];\nexport const openRing = (ring: Ring): Ring =>\n ring.length > 1 && distance(ring[0], ring[ring.length - 1]) < 1e-8 ? ring.slice(0, -1) : ring;\nexport const ringArea = (ring: Ring) =>\n Math.abs(\n ring.reduce((sum, p, i) => {\n const q = ring[(i + 1) % ring.length];\n return sum + p[0] * q[1] - q[0] * p[1];\n }, 0),\n ) / 2;\nexport const objectArea = (object: SiteObject) =>\n object.rings\n ? ringArea(object.rings[0]) - object.rings.slice(1).reduce((sum, r) => sum + ringArea(r), 0)\n : object.width * object.depth;\nexport const centroid = (ring: Ring): Point => {\n const points = openRing(ring);\n return [points.reduce((s, p) => s + p[0], 0) / points.length, points.reduce((s, p) => s + p[1], 0) / points.length];\n};\nexport const rectangle = (center: Point, width: number, depth: number, rotation = 0): Ring =>\n closeRing(\n (\n [\n [-width / 2, -depth / 2],\n [width / 2, -depth / 2],\n [width / 2, depth / 2],\n [-width / 2, depth / 2],\n ] as Point[]\n ).map(p => add(center, rotate(p, rotation))),\n );\n/** Do the two open segments cross? Used for line of sight: a wall between two points blocks it.\n * Touching at an endpoint does not count — walls meet at shared junctions, and a sightline grazing\n * such a corner is not obstructed by it. */\nexport function segmentsCross(a: Point, b: Point, c: Point, d: Point): boolean {\n const side = (p: Point, q: Point, r: Point) => (q[0] - p[0]) * (r[1] - p[1]) - (q[1] - p[1]) * (r[0] - p[0]);\n const [s1, s2, s3, s4] = [side(a, b, c), side(a, b, d), side(c, d, a), side(c, d, b)];\n const EPS = 1e-9;\n return ((s1 > EPS && s2 < -EPS) || (s1 < -EPS && s2 > EPS)) && ((s3 > EPS && s4 < -EPS) || (s3 < -EPS && s4 > EPS));\n}\nexport function segmentProjection(p: Point, a: Point, b: Point) {\n const length = distance(a, b);\n const t = length\n ? Math.max(0, Math.min(1, ((p[0] - a[0]) * (b[0] - a[0]) + (p[1] - a[1]) * (b[1] - a[1])) / length ** 2))\n : 0;\n const point: Point = [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t];\n return { point, t, distance: distance(p, point), length };\n}\n/** Elevation of a sloped area at a point: project onto the slope axis and lerp high → low. Points\n * beyond either end clamp, so a footprint wider than its axis keeps flat aprons at both ends. */\nexport function slopeElevation(slope: Slope, point: Point): number {\n const { t } = segmentProjection(point, slope.axis[0], slope.axis[1]);\n return slope.high + (slope.low - slope.high) * t;\n}\n/** The ground an object covers. Most areas carry an explicit outline; anything placed by size falls\n * back to the rectangle its width, depth and rotation describe. One definition, so the model and the\n * renderer cannot disagree about where a thing is. */\nexport const footprint = (o: SiteObject): Ring[] => o.rings ?? [rectangle(o.position, o.width, o.depth, o.rotation)];\n// Store array indices, not coordinates: transaction drafts move/replace junctions in place. Verify\n// each hit so same-length splices and reordering cannot leave the rendering or snapping cache stale.\nconst junctionIndices = new WeakMap<ProjectDocument['junctions'], { length: number; ids: Map<string, number> }>();\nfunction indexedJunction(junctions: ProjectDocument['junctions'], id: string) {\n let index = junctionIndices.get(junctions);\n const position = index?.ids.get(id);\n if (!index || index.length !== junctions.length || position === undefined || junctions[position]?.id !== id) {\n const ids = new Map<string, number>();\n junctions.forEach((j, i) => {\n if (!ids.has(j.id)) ids.set(j.id, i);\n });\n index = { length: junctions.length, ids };\n junctionIndices.set(junctions, index);\n }\n const at = index.ids.get(id);\n return at === undefined ? undefined : junctions[at];\n}\nexport function barrierEnds(project: ProjectDocument, barrier: Barrier | VirtualBoundary): [Point, Point] {\n return [\n indexedJunction(project.junctions, barrier.startId)!.position,\n indexedJunction(project.junctions, barrier.endId)!.position,\n ];\n}\nexport function objectPosition(project: ProjectDocument, object: SiteObject): Point {\n const barrier = project.barriers.find(b => b.id === object.barrierId);\n if (!barrier) return object.position;\n const [a, b] = barrierEnds(project, barrier);\n const l = distance(a, b);\n const t = l ? (object.offset ?? l / 2) / l : 0;\n return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t];\n}\nexport function objectRotation(project: ProjectDocument, object: SiteObject) {\n const barrier = project.barriers.find(b => b.id === object.barrierId);\n if (!barrier) return object.rotation;\n const [a, b] = barrierEnds(project, barrier);\n return (Math.atan2(b[1] - a[1], b[0] - a[0]) * 180) / Math.PI;\n}\nexport function pointInRing(point: Point, ring: Ring): boolean {\n let inside = false;\n for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {\n const a = ring[i],\n b = ring[j];\n if (a[1] > point[1] !== b[1] > point[1] && point[0] < ((b[0] - a[0]) * (point[1] - a[1])) / (b[1] - a[1]) + a[0])\n inside = !inside;\n }\n return inside;\n}\nconst cross = (a: Point, b: Point, c: Point) => (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);\n/** Whether segments a–b and c–d cross or touch, endpoints included. */\nexport function intersects(a: Point, b: Point, c: Point, d: Point) {\n const on = (p: Point, x: Point, y: Point) =>\n Math.abs(cross(x, y, p)) < 1e-8 * distance(x, y) &&\n p[0] >= Math.min(x[0], y[0]) - 1e-8 &&\n p[0] <= Math.max(x[0], y[0]) + 1e-8 &&\n p[1] >= Math.min(x[1], y[1]) - 1e-8 &&\n p[1] <= Math.max(x[1], y[1]) + 1e-8;\n return (\n (cross(a, b, c) * cross(a, b, d) < 0 && cross(c, d, a) * cross(c, d, b) < 0) ||\n on(c, a, b) ||\n on(d, a, b) ||\n on(a, c, d) ||\n on(b, c, d)\n );\n}\n// Ring and relationship validation moved to validate.ts — the validity layer stands on its own.\nexport function containedBy(child: Ring[], parent: Ring[]): boolean {\n try {\n return polygonClipping.difference(child, parent).every(p => ringArea(p[0] as Ring) < 0.001);\n } catch {\n return false;\n }\n}\nexport function snapPoint(\n project: ProjectDocument,\n floorId: string | null,\n point: Point,\n tolerance: number,\n previous?: Point,\n grid = true,\n /** Direction the segment from `previous` is held to, with its 15° multiples. Default 0 is the site\n * grid; pass `referenceAxis(...).angle` to hold to the building or to a neighbouring wall instead. */\n axis = 0,\n): { point: Point; label: string } {\n let best = tolerance,\n result: Point | null = null,\n label = '';\n let junctionScore = 1;\n const degrees = new Map<string, number>();\n for (const b of boundaryEdges(project))\n for (const id of [b.startId, b.endId]) degrees.set(id, (degrees.get(id) ?? 0) + 1);\n for (const junction of project.junctions.filter(j => j.floorId === floorId)) {\n const d = distance(point, junction.position);\n const degree = degrees.get(junction.id) ?? 0;\n // A T junction attracts the fourth branch before a projection onto an adjacent wall can\n // create a second, almost coincident T. All four branches reuse the same junction identity.\n const score = d / (tolerance * (degree >= 3 ? 1.5 : 1));\n if (score < junctionScore) {\n junctionScore = score;\n result = junction.position;\n label = degree >= 3 ? 'Junction' : 'Endpoint';\n }\n }\n if (result) return { point: result, label };\n const angleLabel = (quarter: number) => {\n const turn = Math.round(quarter * 45);\n const acute = turn > 90 ? 180 - turn : turn;\n return acute === 0 ? 'Parallel' : acute === 90 ? 'Square' : `${acute}°`;\n };\n const held = previous && holdAngle(previous, point, axis, tolerance);\n if (held && previous) {\n const dx = held.point[0] - previous[0],\n dy = held.point[1] - previous[1];\n for (const barrier of boundaryEdges(project).filter(b => b.floorId === floorId)) {\n const [a, b] = barrierEnds(project, barrier);\n const ex = b[0] - a[0],\n ey = b[1] - a[1];\n const denom = dx * ey - dy * ex;\n if (Math.abs(denom) < 1e-9) continue;\n const ax = a[0] - previous[0],\n ay = a[1] - previous[1];\n const t = (ax * ey - ay * ex) / denom,\n u = (ax * dy - ay * dx) / denom;\n if (t <= 0 || u < 0 || u > 1) continue;\n const hit: Point = [previous[0] + dx * t, previous[1] + dy * t];\n const d = distance(point, hit);\n if (d >= best) continue;\n best = d;\n result = barrierJoinPoint(project, hit, floorId);\n label = distance(result, hit) < 1e-6 ? angleLabel(held.quarter) : 'Endpoint';\n }\n if (result) return { point: result, label };\n }\n for (const barrier of boundaryEdges(project).filter(b => b.floorId === floorId)) {\n const projected = segmentProjection(point, ...barrierEnds(project, barrier));\n if (projected.distance < best) {\n best = projected.distance;\n result = barrierJoinPoint(project, projected.point, floorId);\n label = 'On segment';\n }\n }\n if (result) return { point: result, label };\n let p: Point = grid ? [Math.round(point[0] * 2) / 2, Math.round(point[1] * 2) / 2] : point;\n if (previous) {\n const held = holdAngle(previous, p, axis, tolerance);\n if (held) {\n p = held.point;\n label = angleLabel(held.quarter);\n }\n }\n return { point: p, label: label || (grid ? '0.5 m grid' : '') };\n}\n/** Hold a segment to `axis` and every 15° off it (including 45° and 90°). See\n * `referenceAxis` in ./walls for where a meaningful axis comes from; 0 is the site's own grid.\n *\n * The test is perpendicular distance from the candidate ray, not an angle, so the tolerance stays a\n * constant width on screen: a short wall snaps readily and a long one keeps fine control of its far\n * end, which is the behaviour that makes the constraint feel like help rather than a fight. Null when\n * the pointer is near none of them — an angle nobody asked for is worse than no angle at all. */\nconst zero = (v: number) => (Math.abs(v) < 1e-12 ? 0 : v);\nexport function holdAngle(\n previous: Point,\n point: Point,\n axis: number,\n tolerance: number,\n): { point: Point; degrees: number; quarter: number } | null {\n const vx = point[0] - previous[0],\n vy = point[1] - previous[1];\n if (Math.hypot(vx, vy) < 1e-6) return null;\n let best: { point: Point; degrees: number; quarter: number; offset: number } | null = null;\n for (let k = 0; k < 24; k++) {\n const degrees = axis + k * 15,\n rad = (degrees * Math.PI) / 180,\n // cos(90°) comes back as 6e-17 rather than 0, which would leave a wall a hair off the very axis\n // it was just held to — harmless on screen, but it is what gets written to the document.\n dx = zero(Math.cos(rad)),\n dy = zero(Math.sin(rad)),\n along = vx * dx + vy * dy;\n if (along <= 0) continue; // the opposing ray of a pair already covered by its partner\n const offset = Math.abs(vx * dy - vy * dx);\n if (offset >= tolerance || (best && offset >= best.offset)) continue;\n best = { point: [previous[0] + dx * along, previous[1] + dy * along], degrees, quarter: (k % 12) / 3, offset };\n }\n return best && { point: best.point, degrees: best.degrees, quarter: best.quarter };\n}\n/** One centimetre is the model's degeneracy guard, independent of the drawing grid and zoom.\n * Short returns, jambs and staggered junctions are real geometry; their screen handles spread\n * apart when necessary so they remain editable. */\nexport const MIN_SEGMENT = MIN_WALL_LENGTH;\n/** An opening needs a valid wall AND enough length for its actual width. Kept as an exported\n * base limit for callers; there is no additional one-metre restriction on narrow doors/windows. */\nexport const OPENING_MIN_SEGMENT = MIN_SEGMENT;\n/** Automatic joins only absorb sub-millimetre coordinate noise. Interactive snapping has its\n * own screen-based reach, so a deliberate centimetre-scale feature survives with snapping off. */\n\n/** Weld a connection near the end of a wall to that end. The snap preview and the actual\n * junction use the same rule, so an ordinary T-junction cannot leave an uneditable stub. */\nexport function barrierJoinPoint(project: ProjectDocument, point: Point, floorId: string | null): Point {\n const existing = project.junctions.find(j => j.floorId === floorId && distance(j.position, point) < JOIN_EPS);\n if (existing) return existing.position;\n for (const barrier of project.barriers) {\n if (barrier.floorId !== floorId) continue;\n const [a, b] = barrierEnds(project, barrier);\n const hit = segmentProjection(point, a, b);\n if (hit.distance > JOIN_EPS) continue;\n const nearest = hit.t <= 0.5 ? a : b;\n if (distance(hit.point, nearest) < MIN_SEGMENT - 1e-6) return nearest;\n }\n return point;\n}\n\n/** A preview can check a connection without partially splitting any walls. */\nexport function junctionIssue(project: ProjectDocument, point: Point, floorId: string | null): string | null {\n point = barrierJoinPoint(project, point, floorId);\n if (project.junctions.some(j => j.floorId === floorId && distance(j.position, point) < JOIN_EPS)) return null;\n for (const barrier of project.barriers.filter(b => b.floorId === floorId)) {\n const [a, b] = barrierEnds(project, barrier);\n const hit = segmentProjection(point, a, b);\n if (hit.distance > JOIN_EPS || hit.t <= 0 || hit.t >= 1) continue;\n const cut = distance(a, point);\n for (const o of project.objects.filter(o => o.barrierId === barrier.id)) {\n if (Math.abs((o.offset ?? 0) - cut) < o.width / 2) return 'A junction cannot split an opening.';\n if (((o.offset ?? 0) < cut ? cut : distance(point, b)) < OPENING_MIN_SEGMENT - 1e-6)\n return `Leave at least ${OPENING_MIN_SEGMENT} m of wall around an opening.`;\n }\n }\n return null;\n}\n\n/** Preflight the complete stroke, including openings crossed between its endpoints. */\nexport function barrierStrokeIssue(\n project: ProjectDocument,\n a: Point,\n b: Point,\n floorId: string | null,\n): string | null {\n a = barrierJoinPoint(project, a, floorId);\n b = barrierJoinPoint(project, b, floorId);\n const atStart = junctionIssue(project, a, floorId) ?? junctionIssue(project, b, floorId);\n if (atStart) return atStart;\n const ux = b[0] - a[0],\n uy = b[1] - a[1];\n const length = distance(a, b),\n cuts = [0, length];\n const tooShort = (span: number, minimum: number) => span > GEOMETRY_EPS && span < minimum - GEOMETRY_EPS;\n for (const wall of boundaryEdges(project).filter(w => w.floorId === floorId)) {\n const [c, d] = barrierEnds(project, wall),\n vx = d[0] - c[0],\n vy = d[1] - c[1];\n const det = ux * vy - uy * vx;\n if (Math.abs(det) < 1e-12 * length * distance(c, d)) {\n for (const q of [c, d]) {\n const hit = segmentProjection(q, a, b);\n if (hit.distance <= GEOMETRY_EPS) cuts.push(hit.t * length);\n }\n continue;\n }\n const t = ((c[0] - a[0]) * vy - (c[1] - a[1]) * vx) / det;\n const s = ((c[0] - a[0]) * uy - (c[1] - a[1]) * ux) / det;\n if (t < 0 || t > 1 || s < 0 || s > 1) continue;\n cuts.push(t * length);\n if (tooShort(Math.min(s, 1 - s) * distance(c, d), 'kind' in wall ? MIN_SEGMENT : MIN_RING_EDGE))\n return 'That crossing would leave a boundary segment too short.';\n const issue = junctionIssue(project, [a[0] + t * ux, a[1] + t * uy], floorId);\n if (issue) return issue;\n }\n cuts.sort((x, y) => x - y);\n if (cuts.some((cut, i) => i > 0 && tooShort(cut - cuts[i - 1], MIN_SEGMENT)))\n return 'That crossing would leave a boundary segment too short.';\n return null;\n}\n\nexport function joinAt(project: ProjectDocument, point: Point, floorId: string | null): string {\n point = barrierJoinPoint(project, point, floorId);\n const existing = project.junctions.find(j => j.floorId === floorId && distance(j.position, point) < JOIN_EPS);\n if (existing) return existing.id;\n const issue = junctionIssue(project, point, floorId);\n if (issue) throw new Error(issue);\n const id = uid();\n project.junctions.push({ id, floorId, position: point });\n for (const barrier of [...project.barriers].filter(b => b.floorId === floorId)) {\n const [a, b] = barrierEnds(project, barrier);\n const hit = segmentProjection(point, a, b);\n if (hit.distance > JOIN_EPS || hit.t <= 0 || hit.t >= 1) continue;\n const cut = distance(a, point);\n const attachments = project.objects.filter(o => o.barrierId === barrier.id);\n const newId = uid();\n const oldEnd = barrier.endId;\n barrier.endId = id;\n project.barriers.push({ ...barrier, id: newId, startId: id, endId: oldEnd });\n replaceBoundaryUses(project, barrier.id, [{ edgeId: barrier.id }, { edgeId: newId }]);\n attachments.forEach(o => {\n if ((o.offset ?? 0) > cut) {\n o.barrierId = newId;\n o.offset = (o.offset ?? 0) - cut;\n }\n });\n }\n return id;\n}\n/** Take a wall out of the document, with everything that only existed because it was there.\n *\n * A wall is never alone: doors and windows hang in it, junctions exist to hold its ends, and route\n * nodes may be bound to those openings. Removing the barrier alone leaves each of those pointing at\n * something that is gone, and the document refuses the whole edit — so the delete appears to do\n * nothing at all, which is worse than either outcome. Everything that removes a wall goes through\n * here so that cannot happen in one place and not another.\n *\n * A junction survives if any other wall still ends there; the ontology is pruned by the caller,\n * which knows whether spaces are also being merged. */\nexport function removeBarrier(project: ProjectDocument, barrierId: string) {\n const removed = project.barriers.find(b => b.id === barrierId);\n if (removed) preserveBoundary(project, removed);\n const openings = new Set(project.objects.filter(o => o.barrierId === barrierId).map(o => o.id));\n project.objects = project.objects.filter(o => !openings.has(o.id));\n for (const o of project.objects) if (o.parentId && openings.has(o.parentId)) o.parentId = undefined;\n project.barriers = project.barriers.filter(b => b.id !== barrierId);\n project.junctions = project.junctions.filter(j =>\n boundaryEdges(project).some(b => b.startId === j.id || b.endId === j.id),\n );\n if (project.navNodes?.length) {\n const alive = new Set(project.objects.map(o => o.id));\n project.navNodes = project.navNodes.filter(n => n.objectId === undefined || alive.has(n.objectId));\n const nodes = new Set(project.navNodes.map(n => n.id));\n project.navEdges = (project.navEdges ?? []).filter(\n e => nodes.has(e.aId) && nodes.has(e.bId) && (e.objectId === undefined || alive.has(e.objectId)),\n );\n }\n}\n\nexport function addBarrier(\n project: ProjectDocument,\n a: Point,\n b: Point,\n floorId: string | null,\n kind: 'wall' | 'fence',\n) {\n if (distance(a, b) < MIN_SEGMENT - 1e-6) throw new Error(`A segment must be at least ${MIN_SEGMENT} m long.`);\n a = barrierJoinPoint(project, a, floorId);\n b = barrierJoinPoint(project, b, floorId);\n // Snapping can collapse a stroke back onto its start. Repeated clicks are harmless.\n if (distance(a, b) < MIN_SEGMENT - 1e-6) return;\n const startId = joinAt(project, a, floorId),\n endId = joinAt(project, b, floorId);\n if (\n startId === endId ||\n project.barriers.some(\n w =>\n w.floorId === floorId &&\n w.kind === kind &&\n ((w.startId === startId && w.endId === endId) || (w.startId === endId && w.endId === startId)),\n )\n )\n return;\n const barrier: Barrier = {\n id: uid(),\n floorId,\n startId,\n endId,\n kind,\n name: kind === 'wall' ? 'Wall' : 'Site fence',\n thickness: kind === 'wall' ? 0.3 : 0.1,\n height: kind === 'wall' ? 3.5 : 2,\n };\n project.barriers.push(barrier);\n return barrier;\n}\n// Splits a room/zone along the infinite line drawn through `pa`→`pb`. Because the line is treated as\n// unbounded, the stroke may start and end well past the walls — the room is divided wherever the line\n// actually crosses it, so precise clicks on the walls are not required. Holes are supported: each half\n// keeps the portion of any hole on its side (a hole straddling the cut merges into that half's\n// boundary), and the partition wall is built only across solid spans, skipping courtyards. By\n// convention the original keeps the right-hand side of the pa→pb direction and the twin takes the left\n// (the twin is what the editor selects after the cut).\nexport function splitRoom(\n project: ProjectDocument,\n roomId: string,\n pa: Point,\n pb: Point,\n /** Build the partition wall along the cut. False when a wall already exists there — splitting a\n * space *because* someone drew a wall must not draw a second one on top of it. */\n wall = true,\n): string {\n const o = project.objects.find(x => x.id === roomId);\n if (!o?.rings?.length) throw new Error('Pick a room or zone to split.');\n if (o.geometry?.mode === 'boundaries') return splitBoundarySpace(project, o, pa, pb, wall);\n const len = distance(pa, pb);\n if (len < 1e-6) throw new Error('Draw a line across the room to split it.');\n const dir: Point = [(pb[0] - pa[0]) / len, (pb[1] - pa[1]) / len];\n const normal: Point = [dir[1], -dir[0]]; // unit normal pointing to the right-hand side of travel\n\n // A cut long enough to reach past the whole room, so overshooting the walls is harmless.\n const poly = o.rings.map(closeRing);\n const reach = Math.max(len, ...poly.flat().map(p => distance(pa, p))) * 4 + 10;\n const c0: Point = [pa[0] - dir[0] * reach, pa[1] - dir[1] * reach];\n const c1: Point = [pa[0] + dir[0] * reach, pa[1] + dir[1] * reach];\n const halfPlane = (side: 1 | -1): Ring =>\n closeRing([\n c0,\n c1,\n [c1[0] + normal[0] * reach * side, c1[1] + normal[1] * reach * side],\n [c0[0] + normal[0] * reach * side, c0[1] + normal[1] * reach * side],\n ]);\n // Intersect the room (outer + holes) with a half-plane; keep the largest resulting polygon.\n const clip = (side: 1 | -1): Ring[] => {\n const pieces = polygonClipping.intersection(poly as Ring[], [halfPlane(side)]) as unknown as Ring[][];\n if (!pieces.length) throw new Error('The cut must cross the room from one wall to the opposite wall.');\n const netArea = (pg: Ring[]) => ringArea(pg[0]) - pg.slice(1).reduce((sum, r) => sum + ringArea(r), 0);\n const usable = pieces.filter(pg => netArea(pg) >= MIN_SPACE_AREA).sort((a, b) => netArea(b) - netArea(a));\n if (!usable.length) throw new Error(`Each split space needs at least ${MIN_SPACE_AREA} m² of usable area.`);\n if (usable.length > 1)\n throw new Error('That cut would leave disconnected pieces — draw a single straight line across the room.');\n return usable[0].map(closeRing);\n };\n // Only weld numerical duplicates. Removing a real cut vertex changes the boundary and can\n // lose floor area or erase a small notch; the wall minimum and drawing grid do not govern rings.\n const drawnKey = (p: Point) => `${p[0].toFixed(4)},${p[1].toFixed(4)}`;\n const drawn = new Set(poly.flat().map(drawnKey));\n const weld = (rings: Ring[]): Ring[] =>\n rings.map(closed => {\n const r = openRing(closed);\n const kept = r.filter((p, i) => {\n if (drawn.has(drawnKey(p))) return true;\n const prev = r[(i + r.length - 1) % r.length],\n next = r[(i + 1) % r.length];\n if (drawn.has(drawnKey(prev)) && distance(p, prev) < JOIN_EPS) return false;\n if (drawn.has(drawnKey(next)) && distance(p, next) < JOIN_EPS) return false;\n return true;\n });\n // Removing a cut vertex can connect across a concave notch or reverse a boundary edge.\n // Keep the clipper's valid boundary if that shortcut would cross another edge.\n const crossing = kept.some((p, i) =>\n kept.some(\n (q, j) =>\n j > i + 1 &&\n !(i === 0 && j === kept.length - 1) &&\n intersects(p, kept[(i + 1) % kept.length], q, kept[(j + 1) % kept.length]),\n ),\n );\n return kept.length >= 3 && ringArea(kept) >= 0.01 && !crossing ? closeRing(kept) : closed;\n });\n const right = weld(clip(1)); // original keeps the right-hand side …\n const left = weld(clip(-1)); // … the twin takes the left\n\n const apply = (target: SiteObject, rings: Ring[]) => {\n target.rings = rings;\n target.position = centroid(rings[0]);\n const outer = openRing(rings[0]);\n const xs = outer.map(p => p[0]),\n ys = outer.map(p => p[1]);\n target.width = Math.max(...xs) - Math.min(...xs);\n target.depth = Math.max(...ys) - Math.min(...ys);\n };\n const twin = structuredClone(o);\n twin.id = uid();\n twin.name = `${o.name} 2`;\n twin.feedId = undefined;\n apply(o, right);\n apply(twin, left);\n project.objects.push(twin);\n\n if (!wall) return twin.id;\n // Partition wall: collect every crossing of the cut line with every ring (outer + holes) as a signed\n // distance along `dir` from `pa`, order them, and wall each solid interval (crossings 0-1, 2-3, …).\n // This skips holes and handles concave rooms the line enters and leaves more than once.\n const crossings: number[] = [];\n for (const ring of poly) {\n const r = openRing(ring);\n for (let i = 0; i < r.length; i++) {\n const a = r[i],\n b = r[(i + 1) % r.length];\n const e: Point = [b[0] - a[0], b[1] - a[1]];\n const denom = dir[0] * e[1] - dir[1] * e[0];\n if (Math.abs(denom) < 1e-12) continue; // edge parallel to the cut\n const qp: Point = [a[0] - pa[0], a[1] - pa[1]];\n const u = (qp[0] * dir[1] - qp[1] * dir[0]) / denom; // param along the edge\n if (u < -1e-9 || u > 1 + 1e-9) continue;\n crossings.push((qp[0] * e[1] - qp[1] * e[0]) / denom); // distance along the cut\n }\n }\n crossings.sort((x, y) => x - y);\n const deduped = crossings.filter((t, i) => i === 0 || t - crossings[i - 1] > 1e-4);\n const from = project.barriers.length;\n for (let i = 0; i + 1 < deduped.length; i += 2) {\n const s: Point = [pa[0] + dir[0] * deduped[i], pa[1] + dir[1] * deduped[i]];\n const e: Point = [pa[0] + dir[0] * deduped[i + 1], pa[1] + dir[1] * deduped[i + 1]];\n if (distance(s, e) >= MIN_SEGMENT - 1e-6) addBarrier(project, s, e, o.floorId, 'wall');\n }\n project.barriers.slice(from).forEach(b => {\n b.name = 'Partition';\n b.thickness = 0.18;\n });\n return twin.id;\n}\n// Clones a floor with everything on it, including its slice of the nav graph: node/edge ids are\n// remapped (bindings follow cloned objects), and cross-floor edges (vertical rides, exits) are\n// dropped — re-run chainVertical on the copy to rejoin it to the shafts.\n/** Delete a floor and everything anchored to it. The cascade is the whole job: a floor owns junctions,\n * barriers, objects and drawings, and those are in turn referenced from elsewhere — openings hang off\n * barriers, cameras watch objects, lifts serve floors, nested zones name a parent, the nav graph binds\n * both, a building may roof this level, and the document may open on it. Anything missed here surfaces\n * later as a validation failure on load, so it is all handled up front.\n * Refuses to remove the last floor: a project must always have one. Returns the ids that were removed. */\nexport function removeFloor(project: ProjectDocument, floorId: string): string[] {\n const floor = project.floors.find(f => f.id === floorId);\n if (!floor) throw new Error('That floor is not part of this project.');\n if (project.floors.length <= 1) throw new Error('A project needs at least one floor.');\n\n const goneObjects = new Set(project.objects.filter(o => o.floorId === floorId).map(o => o.id));\n const goneBarriers = new Set(project.barriers.filter(b => b.floorId === floorId).map(b => b.id));\n const removed = [floorId, ...goneObjects, ...goneBarriers];\n\n project.floors = project.floors.filter(f => f.id !== floorId);\n project.junctions = project.junctions.filter(j => j.floorId !== floorId);\n project.barriers = project.barriers.filter(b => b.floorId !== floorId);\n if (project.virtualBoundaries)\n project.virtualBoundaries = project.virtualBoundaries.filter(b => b.floorId !== floorId);\n project.objects = project.objects.filter(o => o.floorId !== floorId);\n project.drawings = project.drawings.filter(d => d.floorId !== floorId);\n\n for (const o of project.objects) {\n // An opening whose wall is gone would float; a nested zone whose parent is gone becomes its own.\n if (o.barrierId && goneBarriers.has(o.barrierId)) {\n o.barrierId = undefined;\n o.offset = undefined;\n }\n if (o.parentId && goneObjects.has(o.parentId)) o.parentId = undefined;\n if (o.watchedIds) {\n o.watchedIds = o.watchedIds.filter(id => !goneObjects.has(id));\n if (!o.watchedIds.length) o.watchedIds = undefined;\n }\n if (o.servedFloorIds) {\n o.servedFloorIds = o.servedFloorIds.filter(id => id !== floorId);\n if (!o.servedFloorIds.length) o.servedFloorIds = undefined;\n }\n }\n // Nav nodes on the floor go, as do nodes bound to a deleted object; then any edge missing an end.\n if (project.navNodes) {\n const goneNodes = new Set(\n project.navNodes.filter(n => n.floorId === floorId || (n.objectId && goneObjects.has(n.objectId))).map(n => n.id),\n );\n project.navNodes = project.navNodes.filter(n => !goneNodes.has(n.id));\n project.navEdges = (project.navEdges ?? []).filter(\n e => !goneNodes.has(e.aId) && !goneNodes.has(e.bId) && !(e.objectId && goneObjects.has(e.objectId)),\n );\n }\n // The ontology references those objects too. Kept inline rather than calling model/topology's\n // pruneOntology, because topology imports this module and the cycle is not worth the reuse.\n if (project.portals)\n project.portals = project.portals.filter(\n p => !goneObjects.has(p.a) && !goneObjects.has(p.b) && !(p.openingId && goneObjects.has(p.openingId)),\n );\n const livePortals = new Set((project.portals ?? []).map(p => p.id));\n for (const zone of project.zones ?? []) zone.spaceIds = zone.spaceIds.filter(id => !goneObjects.has(id));\n for (const group of project.portalGroups ?? []) group.portalIds = group.portalIds.filter(id => livePortals.has(id));\n for (const b of project.buildings) if (b.roof?.floorId === floorId) b.roof = undefined;\n if (project.initialFloorId === floorId) project.initialFloorId = undefined;\n return removed;\n}\nexport function duplicateFloor(project: ProjectDocument, floorId: string): string {\n const floor = project.floors.find(f => f.id === floorId)!;\n const newId = uid();\n const map = new Map<string, string>();\n const cloneId = (id: string) => {\n if (!map.has(id)) map.set(id, uid());\n return map.get(id)!;\n };\n project.floors.push({\n ...floor,\n id: newId,\n name: `${floor.name} copy`,\n elevation: Math.max(\n ...project.floors.filter(f => f.buildingId === floor.buildingId).map(f => f.elevation + f.height),\n ),\n });\n project.junctions\n .filter(j => j.floorId === floorId)\n .forEach(j => project.junctions.push({ ...structuredClone(j), id: cloneId(j.id), floorId: newId }));\n project.barriers\n .filter(b => b.floorId === floorId)\n .forEach(b =>\n project.barriers.push({\n ...b,\n id: cloneId(b.id),\n floorId: newId,\n startId: cloneId(b.startId),\n endId: cloneId(b.endId),\n }),\n );\n project.objects\n .filter(o => o.floorId === floorId)\n .forEach(o =>\n project.objects.push({\n ...structuredClone(o),\n id: cloneId(o.id),\n floorId: newId,\n feedId: undefined,\n parentId: o.parentId ? cloneId(o.parentId) : undefined,\n barrierId: o.barrierId ? cloneId(o.barrierId) : undefined,\n servedFloorIds: o.servedFloorIds?.map(id => (id === floorId ? newId : id)),\n geometry:\n o.geometry?.mode === 'boundaries'\n ? {\n mode: 'boundaries',\n loops: o.geometry.loops.map(l => l.map(u => ({ ...u, edgeId: cloneId(u.edgeId) }))),\n }\n : o.geometry,\n }),\n );\n project.virtualBoundaries\n ?.filter(b => b.floorId === floorId)\n .forEach(b =>\n project.virtualBoundaries!.push({\n ...b,\n id: cloneId(b.id),\n floorId: newId,\n startId: cloneId(b.startId),\n endId: cloneId(b.endId),\n }),\n );\n project.drawings\n .filter(d => d.floorId === floorId)\n .forEach(d => project.drawings.push({ ...d, id: uid(), floorId: newId }));\n project.navNodes\n ?.filter(n => n.floorId === floorId)\n .forEach(n =>\n project.navNodes!.push({\n ...structuredClone(n),\n id: cloneId(n.id),\n floorId: newId,\n objectId: n.objectId && map.has(n.objectId) ? map.get(n.objectId)! : undefined,\n }),\n );\n project.navEdges\n ?.filter(e => map.has(e.aId) && map.has(e.bId))\n .forEach(e =>\n project.navEdges!.push({\n ...e,\n id: cloneId(e.id),\n aId: map.get(e.aId)!,\n bId: map.get(e.bId)!,\n objectId: e.objectId && map.has(e.objectId) ? map.get(e.objectId)! : undefined,\n }),\n );\n return newId;\n}\nexport function alignDrawing(\n imagePoints: [Point, Point],\n mapPoints: [Point, Point],\n): Pick<Drawing, 'origin' | 'scale' | 'rotation'> {\n const flipped: [Point, Point] = imagePoints.map(p => [p[0], -p[1]] as Point) as [Point, Point];\n const dl = distance(...flipped),\n ml = distance(...mapPoints);\n if (dl < 1 || ml < 0.01) throw new Error('Choose two distinct points.');\n const rotation =\n ((Math.atan2(mapPoints[1][1] - mapPoints[0][1], mapPoints[1][0] - mapPoints[0][0]) -\n Math.atan2(flipped[1][1] - flipped[0][1], flipped[1][0] - flipped[0][0])) *\n 180) /\n Math.PI;\n const scale = ml / dl;\n const offset = rotate([flipped[0][0] * scale, flipped[0][1] * scale], rotation);\n return { origin: [mapPoints[0][0] - offset[0], mapPoints[0][1] - offset[1]], scale, rotation };\n}\nexport const drawingCorners = (d: Drawing): Point[] =>\n (\n [\n [0, 0],\n [d.width, 0],\n [d.width, -d.height],\n [0, -d.height],\n ] as Point[]\n ).map(p => add(d.origin, rotate([p[0] * d.scale, p[1] * d.scale], d.rotation)));\n","// Space queries: which objects are places, and which place a point is in. A space is somewhere you\n// can stand — the ringed area objects already on the plan, plus lifts and stairs — and everything\n// the ontology says is said about these, so the questions \"what counts?\" and \"where am I?\" sit\n// here, beneath both the described layer (ontology.ts) and the derived one (topology.ts).\nimport polygonClipping from 'polygon-clipping';\nimport {\n barrierEnds,\n centroid,\n closeRing,\n distance,\n footprint,\n objectArea,\n objectPosition,\n openRing,\n pointInRing,\n rectangle,\n ringArea,\n} from './geometry';\nimport { isSpace, type Point, type ProjectDocument, type Ring, type SiteObject } from './types';\n\n/** The enclosed region a point stands in, read off the walls around it.\n *\n * A floor's open area is its extent minus the bodies of its walls, and that difference falls apart\n * into exactly the regions the walls divide it into — so the room under a click is whichever of\n * those contains the click. No tracing, no flood fill, no tolerance to tune: the walls say where\n * the rooms are, and this reads the answer.\n *\n * Doorways do not leak, because a door is an object ON a continuous wall rather than a hole in the\n * run of it. A doorless passage does leak, and should: the drawing said those two places flow into\n * one another. Returns null when the point is not enclosed — outside the building, or inside a\n * boundary with a gap in it, where the region reaches the edge of the extent. */\nexport function enclosedRegion(project: ProjectDocument, floorId: string | null, point: Point): Ring | null {\n // The SMALLEST region containing the point, as spaceAt picks the smallest space: a walled island\n // — a sauna in a bathroom, a WC off a hall, a lift core in a lobby — sits inside the region around\n // it, and both contain a click in the island. The island is the one that was clicked.\n let best: Ring | null = null;\n for (const ring of enclosedRegions(project, floorId))\n if (pointInRing(point, ring) && (!best || Math.abs(ringArea(ring)) < Math.abs(ringArea(best)))) best = ring;\n return best;\n}\n\n/** Every enclosed region on a floor, largest first.\n *\n * Outer rings only: a region with a walled island inside it comes back with the island filled in,\n * so its area overstates the floor you could stand on by the island's footprint. Carrying the holes\n * through as further rings is the complete answer and changes this signature; until then the island\n * is its own region in the list, and enclosedRegion returns it for a click inside it.\n *\n * The same difference as `enclosedRegion`, read whole rather than probed: one subtraction gives all\n * the rooms the walls describe. Regions touching the extent are open to the outside and dropped,\n * and slivers below `minArea` — the gap between two walls that nearly meet — with them. */\nexport function enclosedRegions(project: ProjectDocument, floorId: string | null, minArea = 1): Ring[] {\n const walls = project.barriers.filter(b => b.floorId === floorId);\n if (!walls.length) return [];\n const corners: Point[] = walls.flatMap(b => barrierEnds(project, b) as unknown as Point[]);\n const pad = 2;\n const x0 = Math.min(...corners.map(p => p[0])) - pad,\n x1 = Math.max(...corners.map(p => p[0])) + pad,\n y0 = Math.min(...corners.map(p => p[1])) - pad,\n y1 = Math.max(...corners.map(p => p[1])) + pad;\n const extent: Ring = [\n [x0, y0],\n [x1, y0],\n [x1, y1],\n [x0, y1],\n [x0, y0],\n ];\n // Each wall as a solid: its centreline swept by its thickness, run on by half a thickness at each\n // end so corners close and no region leaks through the notch between two walls that meet.\n const solids = walls.map(b => {\n const [a, c] = barrierEnds(project, b);\n const len = distance(a, c) || 0.001;\n const angle = (Math.atan2(c[1] - a[1], c[0] - a[0]) * 180) / Math.PI;\n const mid: Point = [(a[0] + c[0]) / 2, (a[1] + c[1]) / 2];\n // Shared corners reached through different rotations differ at floating-point precision.\n // Quantise before clipping (as floorOutline does), or even a closed rectangle can fail\n // polygon-clipping's sweep and appear to enclose no space at all.\n return [\n closeRing(rectangle(mid, len + b.thickness, b.thickness, angle)).map(\n q => [Math.round(q[0] * 1e4) / 1e4, Math.round(q[1] * 1e4) / 1e4] as Point,\n ),\n ];\n });\n let open: Ring[][];\n try {\n open = polygonClipping.difference([extent], ...solids) as unknown as Ring[][];\n } catch {\n return []; // degenerate walls: no answer is better than a wrong one\n }\n const area = (ring: Ring) =>\n Math.abs(\n ring.reduce((sum, q, i) => {\n const r = ring[(i + 1) % ring.length];\n return sum + q[0] * r[1] - r[0] * q[1];\n }, 0) / 2,\n );\n // Clipping leaves vertices the document will not hold: a point repeated where two solids met, and\n // the collinear ones left along a straight edge that was cut and rejoined.\n const tidy = (ring: Ring): Ring => {\n // Use the document's 1 mm minimum edge, including near-duplicates introduced by clipping.\n const EPS = 0.001;\n const out: Ring = [];\n for (const q of ring) if (!out.length || distance(out[out.length - 1], q) > EPS) out.push(q);\n if (out.length > 1 && distance(out[0], out[out.length - 1]) <= EPS) out.pop();\n const straight: Ring = [];\n for (let i = 0; i < out.length; i++) {\n const prev = out[(i + out.length - 1) % out.length],\n here = out[i],\n next = out[(i + 1) % out.length];\n const ax = here[0] - prev[0],\n ay = here[1] - prev[1],\n bx = next[0] - here[0],\n by = next[1] - here[1];\n // The SINE of the turn, not the raw cross product: a cross product scales with the product of\n // the edge lengths, so a fixed threshold on it means something different on a 0.1 m edge than\n // on a 20 m one, and long collinear edges survive a cut-and-rejoin as false corners.\n const sine = Math.abs(ax * by - ay * bx) / (Math.hypot(ax, ay) * Math.hypot(bx, by) || 1);\n if (sine > 1e-4) straight.push(here);\n }\n return straight.length >= 3 ? straight : out;\n };\n return open\n .filter(pg => !pg[0].some(q => q[0] <= x0 + 1e-6 || q[0] >= x1 - 1e-6 || q[1] <= y0 + 1e-6 || q[1] >= y1 - 1e-6))\n .map(pg => tidy(openRing(pg[0])))\n .filter(ring => ring.length >= 3 && area(ring) >= minArea)\n .sort((a, b) => area(b) - area(a));\n}\n\n/** Re-fit the rooms that the walls were defining, after those walls have moved.\n *\n * A room stores its own outline, which is what lets a space exist where no wall does — a zone over\n * an open floor, a parcel, an area someone drew freehand. The cost is that moving a wall used to\n * leave the room it bounded exactly where it was, so the two drifted apart and had to be kept in\n * step by hand.\n *\n * They do not have to be. Pass the regions as they stood BEFORE the edit: a room whose outline was\n * one of them was being defined by the walls, so it takes the region that now stands in its place.\n * A room that matched nothing was drawn rather than enclosed, and is left alone. Identity is never\n * touched — the name, colour, bindings and id are the room; only its shape came from the walls. */\nexport function refitEnclosedRooms(project: ProjectDocument, floorId: string | null, before: Ring[]): number {\n if (!before.length) return 0;\n const after = enclosedRegions(project, floorId);\n // How much two outlines are the same outline. Overlap rather than centroid-in-ring: an L-shaped\n // room has its centroid outside itself, and a containment test quietly fails to match every such\n // room — of which a building with a bay or a wing has several.\n const sameness = (one: Ring, two: Ring) => {\n try {\n const inter = polygonClipping.intersection([closeRing(one)], [closeRing(two)]) as unknown as Ring[][];\n const union = polygonClipping.union([closeRing(one)], [closeRing(two)]) as unknown as Ring[][];\n const sum = (pg: Ring[][]) => pg.reduce((t, poly) => t + Math.abs(ringArea(poly[0])), 0);\n const u = sum(union);\n return u > 0 ? sum(inter) / u : 0;\n } catch {\n return 0;\n }\n };\n const matches = (ring: Ring, pool: Ring[]) => pool.find(r => sameness(ring, r) > 0.95);\n // Work out every room's claim first, then apply only the claims that are unambiguous. Removing a\n // wall merges two regions into one, and both of the rooms it separated then point at that same\n // region: growing both to fill it would draw two rooms over each other. Two claims on one region\n // means the edit changed what the rooms ARE, not merely their shape, and that is a question for\n // whoever made the edit — mergeSpaces, or leaving them be — not for a re-fit to answer.\n const claims: { room: SiteObject; ring: Ring }[] = [];\n for (const room of project.objects) {\n if (room.floorId !== floorId || room.kind !== 'room' || !room.rings?.length || room.geometry !== undefined)\n continue;\n if (!matches(room.rings[0], before)) continue; // drawn, not enclosed — leave it be\n // The region that best stands where this room stood. Best overlap, not containment, for the\n // same concave reason.\n const now = after\n .map(r => ({ r, score: sameness(room.rings![0], r) }))\n .filter(x => x.score > 0.2)\n .sort((a, b) => b.score - a.score)[0]?.r;\n if (!now) continue; // its walls no longer enclose anything; keep the last good shape\n claims.push({ room, ring: now });\n }\n let refitted = 0;\n for (const { room, ring } of claims) {\n if (claims.some(other => other.room !== room && other.ring === ring)) continue; // contested\n // Holes are carried across untouched. A wall that bounded a courtyard rather than the room's\n // outside leaves its hole stale; rare enough to name rather than solve.\n const holes = room.rings!.slice(1);\n room.rings = [closeRing(ring), ...holes];\n room.position = centroid(ring);\n const xs = ring.map(p => p[0]),\n ys = ring.map(p => p[1]);\n room.width = Math.max(...xs) - Math.min(...xs);\n room.depth = Math.max(...ys) - Math.min(...ys);\n refitted++;\n }\n return refitted;\n}\n\n/** Spaces are objects you can stand in — the areas already in the document, plus lifts and stairs.\n * Nothing new is stored for them: a room *is* a space, and zones and portals reference it by id. */\nexport const spaces = (project: ProjectDocument): SiteObject[] => project.objects.filter(o => isSpace(o.kind));\n\n/** Where a space sits for routing. Its footprint's centroid, falling back to its placed position. */\nexport function spacePoint(project: ProjectDocument, space: SiteObject): Point {\n const ring = footprint(space)[0];\n return ring?.length ? centroid(ring) : objectPosition(project, space);\n}\n\n/** True when `point` falls inside a space's footprint — inside its outline and outside its holes. */\nexport function inSpace(space: SiteObject, point: Point): boolean {\n const [outline, ...holes] = footprint(space);\n return !!outline && pointInRing(point, outline) && !holes.some(hole => pointInRing(point, hole));\n}\n\n/** The space a point falls in: the *smallest* one containing it, since a room inside a zone inside a\n * floor plate are all true and only the innermost is useful. */\nexport function spaceAt(project: ProjectDocument, floorId: string | null, point: Point): SiteObject | null {\n let best: SiteObject | null = null,\n bestArea = Number.POSITIVE_INFINITY;\n for (const space of project.objects) {\n if (space.floorId !== floorId || !isSpace(space.kind) || !inSpace(space, point)) continue;\n const area = objectArea(space);\n if (area >= bestArea) continue;\n bestArea = area;\n best = space;\n }\n return best;\n}\n","// Reading the plan: what the geometry already says about connection and separation. Portals are\n// inferred from doors and from open boundaries, and a wall drawn or removed changes which spaces\n// exist at all. Nothing here decides anything — decisions (zones, hand-set passage) live in\n// ontology.ts; this module only reports what is drawn, which is why it may be re-run at any time.\nimport polygonClipping from 'polygon-clipping';\nimport { mergeBoundaryGeometry } from './boundaries';\nimport {\n barrierEnds,\n closeRing,\n distance,\n footprint,\n objectArea,\n objectPosition,\n openRing,\n pointInRing,\n segmentProjection,\n splitRoom,\n} from './geometry';\nimport { isSpace, type Point, type Portal, type ProjectDocument, type SiteObject } from './types';\nimport { inSpace, spaceAt } from './spaces';\nimport { isVertical, servedFloors, shaftKey } from './vertical';\nimport { pruneOntology } from './ontology';\nimport { sharedBoundaryPortals } from './portals';\nimport { TRAVERSABLE } from './passages';\nexport { TRAVERSABLE } from './passages';\n\n/** How far past a wall face to look for the room on that side — enough to clear the leaf and any\n * threshold, small enough to stay in the room rather than reaching into the next one. */\nconst PROBE = 0.35;\n/** Infer the portals a plan already describes: for each opening, the space on either side of the wall\n * it sits in. This is the move software without a plan cannot make — it has to be told which\n * doors bound an area, because none of them has a floor plan to ask.\n *\n * Openings whose sides cannot be resolved are skipped rather than guessed at: an unbounded or\n * open-plan side is a real modelling gap, and inventing a portal there would hide it. */\nexport function inferPortals(project: ProjectDocument): Portal[] {\n const barriers = new Map(project.barriers.map(b => [b.id, b]));\n const out: Portal[] = [];\n for (const opening of project.objects) {\n if (!TRAVERSABLE.has(opening.kind)) continue;\n const at = objectPosition(project, opening);\n // The direction to probe: across the wall it is set into, or across its own facing if it is free.\n let nx: number,\n ny: number,\n clearance = PROBE;\n const barrier = opening.barrierId ? barriers.get(opening.barrierId) : undefined;\n if (barrier) {\n const [a, b] = barrierEnds(project, barrier);\n const len = distance(a, b) || 1;\n nx = (b[1] - a[1]) / len;\n ny = -(b[0] - a[0]) / len;\n clearance += barrier.thickness / 2;\n } else {\n const rad = ((opening.rotation ?? 0) * Math.PI) / 180;\n nx = -Math.sin(rad);\n ny = Math.cos(rad);\n clearance += opening.depth / 2;\n }\n // Look on the opening's own floor first, then outdoors. A front door has a room on one side and\n // the street on the other, and the street is not a floor — it is floorId null. Probing only the\n // door's own level makes every entrance in the building unresolvable, which quietly severs the\n // inside from the outside and leaves no route to a muster point.\n const side = (sign: number): SiteObject | null => {\n const probe: Point = [at[0] + nx * clearance * sign, at[1] + ny * clearance * sign];\n return (\n spaceAt(project, opening.floorId, probe) ?? (opening.floorId === null ? null : spaceAt(project, null, probe))\n );\n };\n const a = side(1),\n b = side(-1);\n if (!a || !b || a.id === b.id) continue;\n out.push({ id: `inferred:${opening.id}`, openingId: opening.id, a: a.id, b: b.id, attests: 'assumed' });\n }\n return out;\n}\n\n/** Sampling step along a space's outline, and how far past it to look for a neighbour. */\nconst WALK = 1,\n REACH = 0.45;\n/** A shared run shorter than this is two rooms brushing at a corner, not a way through. */\nconst MIN_OPENING = 1.2;\n\n/** Infer the portals that have no door in them: two spaces that share a boundary with nothing built\n * across it. Open-plan floors are made of these — a department opening onto a gallery, a lift car\n * onto its lobby — and a model that only knows about door objects cannot see any of them.\n *\n * Shared virtual edges give exact connectivity. For independent outlines, walk the outline and\n * accumulate stretches that can step across into a neighbour without crossing a wall. */\nexport function inferOpenBoundaries(project: ProjectDocument): Portal[] {\n const byFloor = new Map<string, SiteObject[]>();\n const standOn = (space: SiteObject, key: string) => {\n const list = byFloor.get(key);\n if (list) list.push(space);\n else byFloor.set(key, [space]);\n };\n // Which floors already have a landing of each shaft drawn on them. A plan drawn sheet by sheet\n // gives one landing per storey and every one of them meets its own lobby without help.\n const landed = new Map<string, Set<string>>();\n for (const o of project.objects) {\n if (!isVertical(o.kind) || !o.floorId) continue;\n const key = shaftKey(o);\n const floors = landed.get(key);\n if (floors) floors.add(o.floorId);\n else landed.set(key, new Set([o.floorId]));\n }\n for (const space of project.objects) {\n if (!isSpace(space.kind)) continue;\n standOn(space, space.floorId ?? '');\n // A shaft is a column, and it stands on every floor it serves. A plan that draws the core once\n // and lists the floors it serves makes the same claim as a hundred landings do, in one object —\n // and walking only the floor that object happens to be filed under found a ten-storey lift\n // exactly one way in, which reads as a cupboard in the basement rather than as a lift.\n //\n // Only where nothing of this shaft already stands, though. servedFloors unions what every twin\n // declares, so a tower drawn landing by landing has each of its hundred landings claiming all\n // hundred floors: lifting them all onto all of them is the same wall walked ten thousand times\n // for the hundred placements that meant anything, and it took the Silo's inference from under a\n // second to eight.\n if (!isVertical(space.kind)) continue;\n const here = landed.get(shaftKey(space));\n for (const floor of servedFloors(project, space))\n if (floor.id !== space.floorId && !here?.has(floor.id)) standOn(space, floor.id);\n }\n // This index belongs to this inference pass: mutable editor drafts must never reuse stale\n // footprints. Bounds reject distant candidates before polygon tests and wall projections.\n type Bounds = [number, number, number, number];\n const bounds = (points: Point[], pad = 0): Bounds => {\n const box: Bounds = [Infinity, Infinity, -Infinity, -Infinity];\n for (const [x, y] of points) {\n box[0] = Math.min(box[0], x - pad);\n box[1] = Math.min(box[1], y - pad);\n box[2] = Math.max(box[2], x + pad);\n box[3] = Math.max(box[3], y + pad);\n }\n return box;\n };\n const within = (box: Bounds, x: number, y: number) => x >= box[0] && y >= box[1] && x <= box[2] && y <= box[3];\n const shapes = new Map(\n [...byFloor.values()].flat().map(o => {\n const rings = footprint(o);\n return [o.id, { rings, bounds: bounds(rings[0] ?? []) }] as const;\n }),\n );\n const inside = (space: SiteObject, point: Point) => {\n const shape = shapes.get(space.id)!;\n return (\n within(shape.bounds, ...point) &&\n !!shape.rings[0] &&\n pointInRing(point, shape.rings[0]) &&\n !shape.rings.slice(1).some(h => pointInRing(point, h))\n );\n };\n const wallsByFloor = new Map<string, { ends: [Point, Point]; bounds: Bounds }[]>();\n for (const barrier of project.barriers) {\n const key = barrier.floorId ?? '';\n const list = wallsByFloor.get(key);\n const ends = barrierEnds(project, barrier);\n const wall = { ends, bounds: bounds(ends, REACH) };\n if (list) list.push(wall);\n else wallsByFloor.set(key, [wall]);\n }\n const shared = new Map<string, number>();\n for (const [floorKey, onFloor] of byFloor) {\n const walls = wallsByFloor.get(floorKey) ?? [];\n // Smallest-first, so a probe landing in a nested room reports the room and not the plate.\n const ordered = [...onFloor].sort((a, b) => objectArea(a) - objectArea(b));\n for (const space of onFloor) {\n // Every ring, holes included. A courtyard's edge is as much a boundary as the outer wall, and\n // a pavilion standing in that courtyard connects to nothing if only the outline is walked.\n // Probing back into the space itself is skipped below, so a hole over open void costs nothing.\n for (const ringRaw of shapes.get(space.id)!.rings) {\n if (!ringRaw?.length) continue;\n const ring = openRing(ringRaw);\n for (let i = 0; i < ring.length; i++) {\n const a = ring[i],\n b = ring[(i + 1) % ring.length];\n const len = distance(a, b);\n if (len < 0.05) continue;\n const ux = (b[0] - a[0]) / len,\n uy = (b[1] - a[1]) / len,\n nx = uy,\n ny = -ux; // outward-ish normal; both signs are tried below\n const steps = Math.max(1, Math.round(len / WALK));\n for (let s = 0; s < steps; s++) {\n const t = ((s + 0.5) / steps) * len;\n const px = a[0] + ux * t,\n py = a[1] + uy * t;\n // Built across this stretch? Then whatever is beyond it is behind a wall.\n if (walls.some(w => within(w.bounds, px, py) && segmentProjection([px, py], ...w.ends).distance < REACH))\n continue;\n for (const sign of [1, -1]) {\n const probe: Point = [px + nx * REACH * sign, py + ny * REACH * sign];\n if (inside(space, probe)) continue; // still inside ourselves\n const other = ordered.find(o => o.id !== space.id && inside(o, probe));\n if (!other) continue;\n // Shared geometry already says whether these two faces have an open edge. A coarse\n // probe must neither miss a narrow opening nor invent a shortcut at a wall junction.\n if (space.geometry?.mode === 'boundaries' && other.geometry?.mode === 'boundaries') continue;\n const key = space.id < other.id ? `${space.id}|${other.id}` : `${other.id}|${space.id}`;\n shared.set(key, (shared.get(key) ?? 0) + len / steps);\n }\n }\n }\n }\n }\n }\n const out = sharedBoundaryPortals(project);\n for (const [key, run] of shared) {\n if (run < MIN_OPENING) continue;\n const [a, b] = key.split('|');\n out.push({ id: `open:${a}:${b}`, a, b, attests: 'none' });\n }\n return out;\n}\n\n/** An inferred portal's id is deterministic — the opening or the pair of spaces it joins — so a\n * re-inference can recognise the portal it replaces and carry a person's edits across. */\nconst INFERRED = (id: string) => id.startsWith('inferred:') || id.startsWith('open:');\n\n/** Re-read the portals from the plan, keeping what a person has decided.\n *\n * Hand-authored portals (any id inference would not mint) survive wholesale. On re-inferred ones the\n * geometry is the plan's to change — which spaces, through which opening — but the semantic fields a\n * person may have set (`passage`, `attests`, `name`, `metadata`) are carried onto the replacement:\n * sealing a doorway or marking it monitored must survive the plan being redrawn around it. A portal\n * the plan no longer describes goes, and its edits go with it — they were about a way through that\n * no longer exists. */\nexport function refreshPortals(project: ProjectDocument): number {\n const previous = project.portals ?? [];\n const authored = previous.filter(p => !INFERRED(p.id));\n const held = new Set(authored.flatMap(p => (p.openingId ? [p.openingId] : [])));\n const heldPairs = new Set(authored.map(p => JSON.stringify([p.a, p.b].sort())));\n const edited = new Map(previous.filter(p => INFERRED(p.id)).map(p => [p.id, p]));\n const fresh = [...inferPortals(project), ...inferOpenBoundaries(project)]\n .filter(p => !p.openingId || !held.has(p.openingId))\n .filter(p => !p.id.startsWith('open:') || !heldPairs.has(JSON.stringify([p.a, p.b].sort())))\n .map(p => {\n const old = edited.get(p.id);\n if (!old) return p;\n if (old.passage !== undefined) p.passage = old.passage;\n if (old.attests !== undefined) p.attests = old.attests;\n if (old.name !== undefined) p.name = old.name;\n if (old.metadata !== undefined) p.metadata = old.metadata;\n return p;\n });\n project.portals = [...authored, ...fresh];\n return fresh.length;\n}\n\n/** Spaces the segment a→b cuts clean across: it enters and leaves, so the space really is in two\n * pieces. Touching a corner or stopping halfway inside does not divide anything. */\nexport function spacesDividedBy(project: ProjectDocument, floorId: string | null, a: Point, b: Point): SiteObject[] {\n const out: SiteObject[] = [];\n for (const space of project.objects) {\n if (space.floorId !== floorId || !isSpace(space.kind)) continue;\n if (space.geometry?.mode === 'boundaries') continue; // the shared graph handles the subdivision\n // A containing area names the whole floor/department. Split its rooms, keeping their\n // parent intact; cutting the parent first strands children outside their parent polygon.\n if (project.objects.some(o => o.parentId === space.id)) continue;\n const ring = footprint(space)[0];\n if (!ring?.length) continue;\n // Both ends outside, and some part of the run inside. Testing the midpoint alone is not enough:\n // a wall crossing two rooms has its midpoint in the gap between them and would divide neither.\n const interior = (point: Point) =>\n inSpace(space, point) &&\n !footprint(space).some(closed => {\n const r = openRing(closed);\n return r.some((q, i) => segmentProjection(point, q, r[(i + 1) % r.length]).distance < 1e-6);\n });\n if (interior(a) || interior(b)) continue;\n const steps = Math.max(8, Math.min(200, Math.round(distance(a, b) / 0.25)));\n let entered = false;\n for (let i = 1; i < steps && !entered; i++) {\n const t = i / steps;\n entered = inSpace(space, [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t]);\n }\n if (entered) out.push(space);\n }\n return out;\n}\n\n/** Split every space a new wall cuts across, so the plan cannot claim two walled-apart halves are one\n * place. Returns the ids of the pieces created.\n *\n * The wall is assumed to exist already — this is called *because* one was drawn — so no partition is\n * built. splitRoom would otherwise lay a second wall along the first.\n *\n * Splitting is safe in a way that joining is not: one space becomes two and both inherit everything,\n * where merging two spaces would have to destroy one identity — its name, its feed binding, whichever\n * zones it had joined. That asymmetry is why this happens automatically and merging never will. */\nexport function divideSpaces(project: ProjectDocument, floorId: string | null, a: Point, b: Point): string[] {\n const made: string[] = [];\n for (const space of spacesDividedBy(project, floorId, a, b)) {\n try {\n made.push(splitRoom(project, space.id, a, b, false));\n } catch {\n // A cut that produces a sliver, or a shape polygon-clipping will not divide, leaves the space\n // whole. Better one honest space than two broken ones.\n }\n }\n return made;\n}\n\n/** Spaces that a wall was the only thing keeping apart: remove it and they are one room again.\n *\n * Answered before the wall goes, because afterwards the evidence is gone. Two spaces qualify when\n * they share a boundary that this barrier runs along, and nothing else is built across it. */\nexport function spacesRejoinedBy(project: ProjectDocument, barrierId: string): [SiteObject, SiteObject] | null {\n const barrier = project.barriers.find(b => b.id === barrierId);\n if (!barrier) return null;\n const without: ProjectDocument = { ...project, barriers: project.barriers.filter(x => x.id !== barrierId) };\n // The rule is simply: which pair becomes open to each other once this wall is gone? Ask the same\n // inference the rest of the model uses rather than inventing a second notion of adjacency, and\n // compare against what was already open so an unrelated doorway is not mistaken for this wall.\n const already = new Set(inferOpenBoundaries(project).map(p => [p.a, p.b].sort().join('|')));\n for (const portal of inferOpenBoundaries(without)) {\n if (already.has([portal.a, portal.b].sort().join('|'))) continue;\n const one = project.objects.find(o => o.id === portal.a),\n two = project.objects.find(o => o.id === portal.b);\n if (one && two) return [one, two];\n }\n return null;\n}\n/** Merge `absorbed` into `keep`, uniting their footprints. The survivor keeps its own name, colour and\n * bindings; that is the whole reason this is never automatic — something is always discarded. */\nexport function mergeSpaces(project: ProjectDocument, keepId: string, absorbedId: string): boolean {\n const keep = project.objects.find(o => o.id === keepId),\n absorbed = project.objects.find(o => o.id === absorbedId);\n if (!keep || !absorbed || keep.id === absorbed.id) return false;\n if (keep.geometry?.mode === 'boundaries' || absorbed.geometry?.mode === 'boundaries') {\n if (!mergeBoundaryGeometry(project, keep, absorbed)) return false;\n } else {\n const united = polygonClipping.union(footprint(keep).map(closeRing), footprint(absorbed).map(closeRing));\n if (united.length !== 1) return false;\n keep.rings = united[0].map(r => closeRing(r as Point[]));\n }\n project.objects = project.objects.filter(o => o.id !== absorbedId);\n for (const o of project.objects) if (o.parentId === absorbedId) o.parentId = keepId;\n // Anything that pointed at the absorbed space now points at the survivor, then duplicates collapse.\n for (const portal of project.portals ?? []) {\n if (portal.a === absorbedId) portal.a = keepId;\n if (portal.b === absorbedId) portal.b = keepId;\n }\n project.portals = (project.portals ?? []).filter(p => p.a !== p.b);\n for (const zone of project.zones ?? [])\n zone.spaceIds = [...new Set(zone.spaceIds.map(id => (id === absorbedId ? keepId : id)))];\n pruneOntology(project);\n return true;\n}\n","// Core domain factories for building indoor-mapping documents from scratch — no app defaults, no\n// demo data. Part of the schema contract so library users can construct valid projects and objects.\nimport type { ObjectKind, Origin, Point, ProjectDocument, SiteObject } from './types';\n\n/** An empty, valid single-floor project anchored at an explicit EPSG:3067 origin (with optional site bearing). */\nexport function emptyProject(\n origin: Origin,\n name = 'Untitled site',\n datum = 'Site ground level = 0 m',\n): ProjectDocument {\n return {\n schemaVersion: 1,\n id: crypto.randomUUID(),\n name,\n description: name,\n updatedAt: new Date().toISOString(),\n origin,\n datum,\n buildings: [{ id: 'building-main', name: 'Main building' }],\n floors: [{ id: 'floor-ground', buildingId: 'building-main', name: 'Ground floor', elevation: 0, height: 3.5 }],\n junctions: [],\n barriers: [],\n objects: [],\n drawings: [],\n };\n}\n/** Create a site object of the given kind at a position, seeded with sensible default dimensions. */\nexport function createObject(kind: ObjectKind, position: Point, floorId: string | null, name?: string): SiteObject {\n const sizes: Partial<Record<ObjectKind, [number, number, number]>> = {\n door: [1, 0.2, 2.1],\n window: [1.2, 0.15, 1.6],\n gate: [4, 0.15, 2],\n turnstile: [1, 1, 1.1],\n elevator: [2.6, 2.6, 2.5],\n stairs: [2.5, 4.5, 2.7],\n office: [6, 3, 2.6],\n container: [6, 2.4, 2.6],\n storage: [8, 6, 0.1],\n camera: [0.5, 0.5, 2.4],\n sensor: [0.35, 0.35, 0.25],\n light: [1.2, 0.3, 2.8],\n alarm: [0.4, 0.4, 0.4],\n equipment: [1.4, 0.9, 1.4],\n };\n const [width, depth, height] = sizes[kind] ?? [1, 1, 0];\n return {\n id: crypto.randomUUID(),\n kind,\n floorId,\n name: name ?? kind[0].toUpperCase() + kind.slice(1),\n position,\n rotation: 0,\n width,\n depth,\n height,\n symbol: kind === 'poi' ? 'personnel' : undefined,\n coverageAngle: kind === 'camera' ? 70 : undefined,\n coverageRange: kind === 'camera' ? 12 : undefined,\n servedFloorIds: kind === 'stairs' || kind === 'elevator' ? (floorId ? [floorId] : []) : undefined,\n ...(kind === 'light' ? { light: { kelvin: 4000, intensity: 45, range: 12 } } : {}),\n };\n}\n","// What a camera can see, read off the plan.\n//\n// A camera carries a facing, a reach and a field of view, and the plan already says where the walls\n// and the rooms are — so which spaces and doorways fall inside that cone is a computation, not\n// something anyone should be typing in by hand. `watchedIds` is the field it lands in; the library\n// never interprets it, and what a host does with \"this camera covers that door\" is its own business.\n//\n// Deliberately coarse in one respect: a space counts by its centre, so a long corridor whose middle\n// is out of reach does not count even though its near end is visible. Naming the rule is better than\n// a partial-visibility fraction nobody can check by eye.\nimport { barrierEnds, distance, objectPosition, pointInRing, segmentsCross } from './geometry';\nimport { isOpening, isSpace, type ProjectDocument, type SiteObject } from './types';\n\nexport const DEFAULT_RANGE = 12;\nexport const DEFAULT_FOV = 70;\n\n/** Ids of the spaces and openings inside `camera`'s cone with an unobstructed line to it.\n *\n * Sightlines stop at walls, with one exception: the opening being tested is itself a hole in the\n * wall it sits on, so that wall cannot be what hides it. */\nexport function coverageOf(project: ProjectDocument, camera: SiteObject): string[] {\n const range = camera.coverageRange ?? DEFAULT_RANGE;\n const half = (camera.coverageAngle ?? DEFAULT_FOV) / 2;\n const from = objectPosition(project, camera);\n const facing = camera.rotation ?? 0;\n const walls = project.barriers.filter(b => b.floorId === camera.floorId);\n const ends = new Map(walls.map(b => [b.id, barrierEnds(project, b)]));\n const seen: string[] = [];\n for (const o of project.objects) {\n if (o.id === camera.id || o.floorId !== camera.floorId) continue;\n if (!isSpace(o.kind) && !isOpening(o.kind)) continue;\n // The room the camera stands in is covered whatever the cone says — the camera is inside it,\n // and its centre may well be behind the lens.\n if (o.rings?.length && pointInRing(from, o.rings[0])) {\n seen.push(o.id);\n continue;\n }\n const to = objectPosition(project, o);\n const reach = distance(from, to);\n if (reach < 0.01 || reach > range) continue;\n const bearing = (Math.atan2(to[1] - from[1], to[0] - from[0]) * 180) / Math.PI;\n const off = Math.abs(((((bearing - facing) % 360) + 540) % 360) - 180);\n if (off > half) continue;\n const blocked = walls.some(b => {\n if (b.id === o.barrierId) return false; // the opening is the hole in this wall\n const [p, q] = ends.get(b.id)!;\n return segmentsCross(from, to, p, q);\n });\n if (!blocked) seen.push(o.id);\n }\n return seen;\n}\n","import type { ProjectDocument, SiteObject } from './types';\nimport { add, rotate } from './geometry';\n\nexport function copyProject(project: ProjectDocument): ProjectDocument {\n const copy = structuredClone(project);\n copy.id = crypto.randomUUID();\n copy.name = `${project.name} copy`;\n copy.updatedAt = new Date().toISOString();\n copy.objects.forEach(object => {\n delete object.feedId;\n });\n return copy;\n}\n\n/** Apply dimensions in the object's own axes, then rotate and translate its polygon. */\nexport function transformObject(object: SiteObject, patch: Partial<SiteObject>) {\n const oldRotation = object.rotation;\n const target = patch.position ?? object.position;\n if (object.rings) {\n const sx = (patch.width ?? object.width) / object.width;\n const sy = (patch.depth ?? object.depth) / object.depth;\n object.rings = object.rings.map(ring =>\n ring.map(point => {\n const local = rotate([point[0] - object.position[0], point[1] - object.position[1]], -oldRotation);\n return add(target, rotate([local[0] * sx, local[1] * sy], patch.rotation ?? oldRotation));\n }),\n );\n }\n Object.assign(object, patch);\n}\n\n/** The floor a viewer should open on: the document's own `initialFloorId` when it names a floor that\n * still exists, otherwise the ground floor, otherwise the lowest one. An explicit `null` is a real\n * answer — it means the outdoor site — so it is distinguished from the field being absent. */\nexport function openingFloorId(project: ProjectDocument): string | null {\n const preferred = project.initialFloorId;\n if (preferred === null) return null;\n if (preferred !== undefined && project.floors.some(f => f.id === preferred)) return preferred;\n return project.floors.find(f => f.elevation === 0)?.id ?? project.floors[0]?.id ?? null;\n}\n","// Document serialisation: export/import with embedded reference images, and read-only parsing of an\n// export. Import-side-effect-free — no browser storage, no React, no MapLibre; safe for any host\n// (node-side tests, schema consumers). Every path in and out runs the full rule set in validate.ts,\n// so a ProjectDocument obtained here is valid by construction.\nimport type { AssetRepository, ProjectDocument } from './types';\nimport { validateProject } from './validate';\n\nexport async function blobDataUrl(blob: Blob): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(String(reader.result));\n reader.onerror = () => reject(reader.error);\n reader.readAsDataURL(blob);\n });\n}\nexport async function exportProject(project: ProjectDocument, assets: AssetRepository): Promise<string> {\n const embeddedAssets: Record<string, string> = {};\n for (const id of new Set(project.drawings.map(d => d.assetId))) {\n const blob = await assets.get(id);\n if (!blob) throw new Error('A reference drawing is missing. Reattach it or remove its reference before exporting.');\n embeddedAssets[id] = await blobDataUrl(blob);\n }\n return JSON.stringify({ ...project, embeddedAssets }, null, 2);\n}\nexport async function importProject(json: string, assets: AssetRepository): Promise<ProjectDocument> {\n const value: unknown = JSON.parse(json);\n const project = validateProject(value);\n const embedded = (value as { embeddedAssets?: Record<string, unknown> }).embeddedAssets ?? {};\n const decoded: [string, Blob][] = [];\n for (const id of new Set(project.drawings.map(d => d.assetId))) {\n const data = embedded[id];\n if (typeof data !== 'string' || !/^data:image\\/(png|jpeg|webp);base64,/.test(data))\n throw new Error('Project export is missing a supported reference image.');\n const res = await fetch(data);\n decoded.push([id, await res.blob()]);\n }\n const copy = structuredClone(project);\n delete (copy as ProjectDocument & { embeddedAssets?: unknown }).embeddedAssets;\n for (const [id, blob] of decoded) {\n const assetId = crypto.randomUUID();\n await assets.put(assetId, blob);\n copy.drawings\n .filter(d => d.assetId === id)\n .forEach(d => {\n d.assetId = assetId;\n });\n }\n copy.id = crypto.randomUUID();\n copy.updatedAt = new Date().toISOString();\n return copy;\n}\n/** Display semantics: ids and updatedAt untouched, nothing written anywhere — unlike importProject, which rewrites both for import-for-editing. Unsupported embedded entries resolve to undefined at get time rather than throwing. */\nexport function parseExport(json: string): { project: ProjectDocument; assets: AssetRepository } {\n const value: unknown = JSON.parse(json);\n const project = validateProject(value);\n const embedded = (value as { embeddedAssets?: Record<string, unknown> }).embeddedAssets ?? {};\n const copy = structuredClone(project);\n delete (copy as ProjectDocument & { embeddedAssets?: unknown }).embeddedAssets;\n const get = async (id: string): Promise<Blob | undefined> => {\n const data = embedded[id];\n if (typeof data !== 'string' || !/^data:image\\/(png|jpeg|webp);base64,/.test(data)) return undefined;\n return (await fetch(data)).blob();\n };\n return { project: copy, assets: { get, put: async () => {}, delete: async () => {} } };\n}\n","// Geometry gestures shared by the editor and the randomized authoring tests.\nimport {\n addBarrier,\n barrierEnds,\n barrierJoinPoint,\n barrierStrokeIssue,\n centroid,\n closeRing,\n distance,\n intersects,\n objectArea,\n openRing,\n segmentProjection,\n MIN_SEGMENT,\n} from './geometry';\nimport { inSpace } from './spaces';\nimport { createObject } from './factory';\nimport { divideSpaces } from './inference';\nimport type { Point, ProjectDocument, Ring } from './types';\nimport { transact } from './validate';\nimport { GEOMETRY_EPS, JOIN_EPS, MIN_RING_EDGE } from './precision';\nimport {\n bindSpaceToRegion,\n boundaryEdges,\n boundaryRegionAt,\n derivedSpaceRings,\n normalizeBoundaries,\n} from './boundaries';\n\n/** Ignore double-click duplicates; reject a crossing while the last good draft is still editable. */\nexport function appendAreaPoint(draft: Ring, point: Point): { points: Ring; error?: string } {\n if (!draft.length) return { points: [point] };\n if (distance(draft.at(-1)!, point) < 0.001) return { points: draft };\n for (let i = 0; i + 2 < draft.length; i++)\n if (intersects(draft.at(-1)!, point, draft[i], draft[i + 1]))\n return { points: draft, error: 'That edge crosses the outline. Choose another point, or undo the last point.' };\n return { points: [...draft, point] };\n}\n\n/** The wall/partition tool: divide along the endpoints actually used after welding. */\nexport function drawBarrier(\n project: ProjectDocument,\n floorId: string | null,\n a: Point,\n b: Point,\n kind: 'wall' | 'fence' = 'wall',\n) {\n if (distance(a, b) < MIN_SEGMENT - 1e-6) return;\n const issue = barrierStrokeIssue(project, a, b, floorId);\n if (issue) throw new Error(issue);\n const barrier = addBarrier(project, a, b, floorId, kind);\n if (barrier && kind === 'wall') divideSpaces(project, floorId, ...barrierEnds(project, barrier));\n return barrier;\n}\n\n/** A completed stroke stops chaining when its tip meets an existing boundary, including an\n * earlier segment of the same outline. Test before adding the segment: afterwards every tip\n * belongs to a boundary. Use the model's joining tolerance, not the pointer's snap reach. */\nexport function endsBoundaryStroke(\n project: ProjectDocument,\n floorId: string | null,\n a: Point,\n b: Point,\n kind: 'wall' | 'fence' | 'boundary' = 'wall',\n): boolean {\n const physical = kind !== 'boundary';\n const start = physical ? barrierJoinPoint(project, a, floorId) : a;\n const end = physical ? barrierJoinPoint(project, b, floorId) : b;\n if (distance(start, end) < (physical ? MIN_SEGMENT - GEOMETRY_EPS : MIN_RING_EDGE)) return false;\n return boundaryEdges(project).some(edge => {\n if (edge.floorId !== floorId) return false;\n const tolerance = physical && 'kind' in edge ? JOIN_EPS : GEOMETRY_EPS;\n return segmentProjection(end, ...barrierEnds(project, edge)).distance <= tolerance;\n });\n}\n\n/** The enclose tool: creating and re-fitting use exactly the same generated outline. */\nexport function encloseRoom(project: ProjectDocument, floorId: string | null, point: Point) {\n normalizeBoundaries(project, floorId);\n const region = boundaryRegionAt(project, floorId, point);\n if (!region) return null;\n const ring = region.rings[0];\n const existing = project.objects\n .filter(o => o.floorId === floorId && o.kind === 'room' && inSpace(o, point))\n .sort((a, b) => objectArea(a) - objectArea(b))[0];\n const room = existing ?? createObject('room', centroid(ring), floorId, 'Room');\n const probe = { ...room, geometry: { mode: 'boundaries' as const, loops: region.loops } };\n probe.rings = derivedSpaceRings(project, probe);\n if (!inSpace(probe, point)) return null;\n const key = (loops: import('./types').BoundaryUse[][]) =>\n loops\n .flat()\n .map(u => `${u.edgeId}:${!!u.reversed}`)\n .sort()\n .join('|');\n const same = project.objects.find(\n o => o.geometry?.mode === 'boundaries' && key(o.geometry.loops) === key(region.loops),\n );\n if (same) return { room: same, existing: true };\n bindSpaceToRegion(project, room, region);\n if (!existing) project.objects.push(room);\n return { room, existing: !!existing };\n}\n\nexport type GeometryDrag =\n | { kind: 'junction'; id: string; point: Point }\n | { kind: 'barrier'; id: string; point: Point }\n | { kind: 'ring'; id: string; point: Point; ringIndex: number; index: number };\n\n/** Keep ordered openings on a resized wall. Move them only as far as necessary to fit;\n * when their total width cannot fit, validation limits the wall movement instead. */\nfunction fitAttachedOpenings(project: ProjectDocument, changed: Set<string>) {\n for (const barrier of project.barriers) {\n if (!changed.has(barrier.startId) && !changed.has(barrier.endId)) continue;\n const length = distance(...barrierEnds(project, barrier));\n const openings = project.objects\n .filter(o => o.barrierId === barrier.id)\n .sort((a, b) => (a.offset ?? 0) - (b.offset ?? 0));\n let end = length;\n for (const o of [...openings].reverse()) {\n o.offset = Math.min(o.offset ?? 0, end - o.width / 2);\n end = o.offset - o.width / 2;\n }\n let start = 0;\n for (const o of openings) {\n o.offset = Math.max(o.offset ?? 0, start + o.width / 2);\n start = o.offset + o.width / 2;\n }\n }\n}\n\nfunction geometryMutation(project: ProjectDocument, move: GeometryDrag) {\n const deltas = new Map<string, Point>();\n let vertex: Point | undefined;\n if (move.kind === 'junction') {\n const j = project.junctions.find(j => j.id === move.id);\n if (!j) return;\n deltas.set(j.id, [move.point[0] - j.position[0], move.point[1] - j.position[1]]);\n } else if (move.kind === 'barrier') {\n const b = boundaryEdges(project).find(b => b.id === move.id);\n if (!b) return;\n const [a, c] = barrierEnds(project, b);\n const length = distance(a, c);\n const nx = -(c[1] - a[1]) / length,\n ny = (c[0] - a[0]) / length;\n const slide = (move.point[0] - (a[0] + c[0]) / 2) * nx + (move.point[1] - (a[1] + c[1]) / 2) * ny;\n for (const id of [b.startId, b.endId]) deltas.set(id, [nx * slide, ny * slide]);\n } else {\n const ring = project.objects.find(o => o.id === move.id)?.rings?.[move.ringIndex];\n if (project.objects.find(o => o.id === move.id)?.geometry?.mode === 'boundaries') return;\n vertex = ring && openRing(ring)[move.index];\n if (!vertex) return;\n }\n return (draft: ProjectDocument, fraction: number) => {\n for (const j of draft.junctions) {\n const delta = deltas.get(j.id);\n if (delta) j.position = [j.position[0] + delta[0] * fraction, j.position[1] + delta[1] * fraction];\n }\n if (move.kind === 'ring') {\n const o = draft.objects.find(o => o.id === move.id)!;\n const ring = openRing(o.rings![move.ringIndex]);\n ring[move.index] = [\n vertex![0] + (move.point[0] - vertex![0]) * fraction,\n vertex![1] + (move.point[1] - vertex![1]) * fraction,\n ];\n o.rings![move.ringIndex] = closeRing(ring);\n o.position = centroid(o.rings![0]);\n } else {\n fitAttachedOpenings(draft, new Set(deltas.keys()));\n }\n };\n}\n\n/** Apply one requested drop to a transaction draft. The editor previews snapping alone and calls\n * this once on release; transact either accepts the entire move or leaves the original intact. */\nexport function applyGeometryDrag(project: ProjectDocument, move: GeometryDrag) {\n geometryMutation(project, move)?.(project, 1);\n}\n\n/** Optional constrained authoring operation for hosts and scripted drawing: find a valid position\n * along a requested movement. Interactive editor drags use applyGeometryDrag on release instead. */\nexport function dragGeometry(project: ProjectDocument, _floorId: string | null, move: GeometryDrag): ProjectDocument {\n const mutation = geometryMutation(project, move);\n if (!mutation) return project;\n const trial = (fraction: number) => transact(project, draft => mutation(draft, fraction));\n const full = trial(1);\n if (full.ok) return full.project;\n let low = 0,\n high = 1,\n best = project;\n // Eighteen trials resolve even a 100 m gesture to less than a millimetre.\n for (let i = 0; i < 18; i++) {\n const mid = (low + high) / 2;\n const result = trial(mid);\n if (result.ok) {\n low = mid;\n best = result.project;\n } else high = mid;\n }\n return best;\n}\n","// A uniform, serializable representation of change. Every mutation is plain data — a kind and its\n// arguments — executed through the same atomic gate (`transact`): clone, apply, run every rule,\n// commit or refuse. What that buys:\n//\n// - one execution path to reason about, instead of a hand-rolled clone/validate at every call site\n// - mutations can be logged, replayed, table-tested and sent over a wire, because they are data\n// - a sequence is atomic as a whole (`applyMutations`): a migration that fails at step 7 of 12\n// leaves the document exactly as it was, not seven-twelfths changed\n//\n// The vocabulary maps 1:1 onto the authoring functions the modules already export — this file adds\n// no new behaviour, only a data shape for the behaviour that exists. Interactive gestures (dragging\n// a wall, tracing a footprint) stay as plain `transact` callbacks in the editor; a Mutation is for\n// changes worth naming.\nimport type {\n Barrier,\n Building,\n Floor,\n NavEdge,\n NavNode,\n ObjectKind,\n Origin,\n Point,\n Portal,\n PortalGroup,\n ProjectDocument,\n Ring,\n SiteObject,\n Zone,\n} from './types';\nimport { uid } from './types';\nimport { addBarrier, duplicateFloor, removeBarrier, removeFloor, splitRoom } from './geometry';\nimport { applyGeometryDrag, drawBarrier, encloseRoom, type GeometryDrag } from './authoring';\nimport { createObject } from './factory';\nimport {\n addPortalGroup,\n addZone,\n nestZone,\n pruneOntology,\n removePortalGroup,\n removeZone,\n setPortalGroupMembers,\n setZoneMembers,\n} from './ontology';\nimport { divideSpaces, mergeSpaces, refreshPortals } from './inference';\nimport { transact, type TransactResult } from './validate';\nimport { addBoundaryHole, addVirtualBoundary, connectSpace, disconnectSpace, drawVirtualBoundary } from './boundaries';\n\n/** Every mutation the schema can execute, as data. `kind` names the operation; the rest are its\n * arguments, exactly as the underlying authoring function takes them. */\nexport type Mutation =\n | { kind: 'addBuilding'; building: Building }\n | { kind: 'patchBuilding'; buildingId: string; set: Partial<Omit<Building, 'id'>> }\n | { kind: 'addFloor'; floor: Floor }\n | { kind: 'patchFloor'; floorId: string; set: Partial<Omit<Floor, 'id' | 'buildingId'>> }\n | { kind: 'removeFloor'; floorId: string }\n | { kind: 'duplicateFloor'; floorId: string }\n | { kind: 'patchProject'; set: Partial<Pick<ProjectDocument, 'name' | 'description' | 'datum' | 'initialFloorId'>> }\n | { kind: 'patchBarrier'; barrierId: string; set: Partial<Omit<Barrier, 'id' | 'startId' | 'endId' | 'floorId'>> }\n | { kind: 'removeBarrier'; barrierId: string }\n | { kind: 'moveGeometry'; move: GeometryDrag }\n | { kind: 'drawBoundary'; a: Point; b: Point; floorId: string | null }\n | { kind: 'drawBarrier'; a: Point; b: Point; floorId: string | null; barrierKind?: 'wall' | 'fence' }\n | { kind: 'encloseRoom'; floorId: string | null; point: Point; name?: string }\n | { kind: 'addHole'; objectId: string; ring: Ring }\n | { kind: 'patchZone'; zoneId: string; set: Partial<Pick<Zone, 'name' | 'purpose' | 'connects' | 'metadata'>> }\n | { kind: 'addPortal'; portal: Omit<Portal, 'id'> }\n | { kind: 'removePortal'; portalId: string }\n | { kind: 'setNavigation'; nodes: NavNode[]; edges: NavEdge[] }\n | { kind: 'addZone'; name: string; spaceIds: string[]; purpose?: string }\n | { kind: 'removeZone'; zoneId: string }\n | { kind: 'setZoneMembers'; zoneId: string; spaceIds: string[]; member: boolean }\n | { kind: 'nestZone'; parentId: string; childId: string }\n | { kind: 'addPortalGroup'; name: string; portalIds: string[] }\n | { kind: 'removePortalGroup'; groupId: string }\n | { kind: 'setPortalGroupMembers'; groupId: string; portalIds: string[]; member: boolean }\n // patchPortal deliberately cannot touch a/b/openingId — which spaces a portal joins is the\n // plan's to say (inference or an explicit new portal), never a field edit. patchObject is wide\n // open bar id and kind: every field it can set is re-checked by the full rule set on commit.\n | { kind: 'patchPortal'; portalId: string; set: Partial<Omit<Portal, 'id' | 'a' | 'b' | 'openingId'>> }\n | { kind: 'patchObject'; objectId: string; set: Partial<Omit<SiteObject, 'id' | 'kind'>> }\n // addObject seeds with createObject's defaults, then applies the given fields — so a mutation\n // script says only what differs (rings, width, a barrier binding), not every dimension.\n | {\n kind: 'addObject';\n objectKind: ObjectKind;\n name: string;\n position: Point;\n floorId: string | null;\n set?: Partial<Omit<SiteObject, 'id' | 'kind'>>;\n }\n | { kind: 'removeObjects'; ids: string[] }\n | { kind: 'refreshPortals' }\n | { kind: 'pruneOntology' }\n | { kind: 'addBarrier'; a: Point; b: Point; floorId: string | null; barrierKind: 'wall' | 'fence' }\n | { kind: 'addBoundary'; a: Point; b: Point; floorId: string | null }\n | { kind: 'connectSpace'; objectId: string; source?: 'outline' | 'walls' }\n | { kind: 'disconnectSpace'; objectId: string }\n | { kind: 'splitRoom'; roomId: string; a: Point; b: Point; wall?: boolean }\n | { kind: 'divideSpaces'; floorId: string | null; a: Point; b: Point }\n | { kind: 'mergeSpaces'; keepId: string; absorbedId: string }\n /** Move or turn the whole site. The geometry is untouched — local metres stay what they were; only\n * where the frame is pinned and which way it faces change. A plan carries no heading, so this is\n * how an imported one is squared onto the street it actually stands on. */\n | { kind: 'setOrigin'; origin: Origin };\n\n/** What a mutation reports back, beyond the new document: the entity it created, or whether it did\n * anything at all. Read it off the result rather than hunting the document for what changed.\n * Entity outcomes are views INTO the frozen result — read them freely, but editing one throws;\n * the next change goes through the next transaction like every other. */\nexport type MutationOutcome = Zone | PortalGroup | string[] | string | boolean | number | undefined;\n\nconst run = (draft: ProjectDocument, m: Mutation): MutationOutcome => {\n switch (m.kind) {\n case 'addBuilding':\n draft.buildings.push(structuredClone(m.building));\n return m.building.id;\n case 'patchBuilding':\n return patch(draft.buildings, m.buildingId, m.set, ['id']);\n case 'addFloor':\n draft.floors.push(structuredClone(m.floor));\n return m.floor.id;\n case 'patchFloor':\n return patch(draft.floors, m.floorId, m.set, ['id', 'buildingId']);\n case 'removeFloor':\n return removeFloor(draft, m.floorId);\n case 'duplicateFloor':\n if (!draft.floors.some(f => f.id === m.floorId)) throw new Error('No such floor.');\n return duplicateFloor(draft, m.floorId);\n case 'patchProject':\n for (const key of Object.keys(m.set))\n if (!['name', 'description', 'datum', 'initialFloorId'].includes(key))\n throw new Error(`Cannot patch project ${key}.`);\n Object.assign(draft, m.set);\n return draft.id;\n case 'patchBarrier':\n return patch(draft.barriers, m.barrierId, m.set, ['id', 'startId', 'endId', 'floorId']);\n case 'removeBarrier':\n removeBarrier(draft, m.barrierId);\n pruneOntology(draft);\n return undefined;\n case 'moveGeometry':\n applyGeometryDrag(draft, m.move);\n return m.move.id;\n case 'drawBoundary':\n return drawVirtualBoundary(draft, m.floorId, m.a, m.b);\n case 'drawBarrier':\n return drawBarrier(draft, m.floorId, m.a, m.b, m.barrierKind)?.id;\n case 'encloseRoom': {\n const result = encloseRoom(draft, m.floorId, m.point);\n if (!result) throw new Error('No enclosed region at that point. Complete its walls or virtual boundaries first.');\n if (m.name) result.room.name = m.name;\n return result.room.id;\n }\n case 'addHole': {\n const object = draft.objects.find(o => o.id === m.objectId);\n if (!object?.rings?.length) throw new Error('Select an area with a footprint.');\n if (object.geometry?.mode === 'boundaries') addBoundaryHole(draft, object, m.ring);\n else object.rings.push(structuredClone(m.ring));\n return object.id;\n }\n case 'patchZone':\n for (const key of Object.keys(m.set))\n if (!['name', 'purpose', 'connects', 'metadata'].includes(key)) throw new Error(`Cannot patch zone ${key}.`);\n return patch(draft.zones ?? [], m.zoneId, m.set, ['id']);\n case 'addPortal': {\n const id = uid();\n (draft.portals ??= []).push({ ...structuredClone(m.portal), id });\n return id;\n }\n case 'removePortal':\n draft.portals = (draft.portals ?? []).filter(p => p.id !== m.portalId);\n pruneOntology(draft);\n return undefined;\n case 'setNavigation':\n draft.navNodes = structuredClone(m.nodes);\n draft.navEdges = structuredClone(m.edges);\n return undefined;\n case 'addZone':\n return addZone(draft, m.name, m.spaceIds, m.purpose);\n case 'removeZone':\n removeZone(draft, m.zoneId);\n return undefined;\n case 'setZoneMembers':\n setZoneMembers(draft, m.zoneId, m.spaceIds, m.member);\n return undefined;\n case 'nestZone': {\n // A refused nesting (it would cycle) is an error, not a shrug: data-shaped callers cannot\n // check a boolean the way code-shaped callers can, so the refusal must surface as one.\n if (!nestZone(draft, m.parentId, m.childId)) throw new Error('That nesting would make a zone contain itself.');\n return true;\n }\n case 'addPortalGroup':\n return addPortalGroup(draft, m.name, m.portalIds);\n case 'removePortalGroup':\n removePortalGroup(draft, m.groupId);\n return undefined;\n case 'setPortalGroupMembers':\n setPortalGroupMembers(draft, m.groupId, m.portalIds, m.member);\n return undefined;\n case 'patchPortal': {\n return patch(draft.portals ?? [], m.portalId, m.set, ['id', 'a', 'b', 'openingId']);\n }\n case 'patchObject': {\n return patch(draft.objects, m.objectId, m.set, ['id', 'kind']);\n }\n case 'addObject': {\n const object = createObject(m.objectKind, m.position, m.floorId, m.name);\n if (m.set) patch([object], object.id, m.set, ['id', 'kind']);\n draft.objects.push(object);\n return object.id;\n }\n case 'removeObjects': {\n const gone = new Set(m.ids);\n const before = draft.objects.length;\n draft.objects = draft.objects.filter(o => !gone.has(o.id));\n // Everything that pointed at the removed objects follows them out: ontology references via\n // pruneOntology, and any authored graph nodes/edges bound to them — validation refuses\n // dangling references, so leaving them would turn this delete into a refused transaction.\n if (draft.navNodes) {\n const deadNodes = new Set(draft.navNodes.filter(n => n.objectId && gone.has(n.objectId)).map(n => n.id));\n draft.navNodes = draft.navNodes.filter(n => !deadNodes.has(n.id));\n draft.navEdges = (draft.navEdges ?? []).filter(\n e => !deadNodes.has(e.aId) && !deadNodes.has(e.bId) && (!e.objectId || !gone.has(e.objectId)),\n );\n }\n pruneOntology(draft);\n return before - draft.objects.length;\n }\n case 'refreshPortals':\n return refreshPortals(draft);\n case 'pruneOntology':\n pruneOntology(draft);\n return undefined;\n case 'addBarrier':\n return addBarrier(draft, m.a, m.b, m.floorId, m.barrierKind)?.id;\n case 'addBoundary':\n return addVirtualBoundary(draft, m.floorId, m.a, m.b);\n case 'connectSpace':\n connectSpace(draft, m.objectId, m.source);\n return m.objectId;\n case 'disconnectSpace':\n disconnectSpace(draft, m.objectId);\n return m.objectId;\n case 'splitRoom':\n return splitRoom(draft, m.roomId, m.a, m.b, m.wall);\n case 'divideSpaces':\n return divideSpaces(draft, m.floorId, m.a, m.b);\n case 'setOrigin': {\n draft.origin = [...m.origin] as Origin;\n return draft.origin.join(',');\n }\n case 'mergeSpaces': {\n if (!mergeSpaces(draft, m.keepId, m.absorbedId))\n throw new Error('Those spaces do not touch, so there is nothing to merge.');\n return true;\n }\n default:\n throw new Error(`Unknown mutation: ${String((m as { kind?: unknown }).kind)}`);\n }\n};\n\nfunction patch<T extends { id: string }>(items: T[], id: string, set: object, immutable: string[]) {\n const item = items.find(x => x.id === id);\n if (!item) throw new Error(`No such entity: ${id}`);\n for (const key of Object.keys(set))\n if (immutable.includes(key) || ['__proto__', 'constructor', 'prototype'].includes(key))\n throw new Error(`Cannot patch ${key}.`);\n Object.assign(item, structuredClone(set));\n return id;\n}\n\nexport type MutationResult = TransactResult & { outcomes?: MutationOutcome[] };\n\n/** Execute one mutation atomically. Sugar over `applyMutations` with a single step. */\nexport const applyMutation = (project: ProjectDocument, mutation: Mutation): MutationResult =>\n applyMutations(project, [mutation]);\n\n/** Execute a sequence of mutations as ONE transaction: all of them apply and the result passes\n * every rule, or none of them do and `error` says why. `outcomes` reports what each step returned\n * (created zones, split-off ids), in order — present only on success. */\nexport function applyMutations(project: ProjectDocument, mutations: Mutation[]): MutationResult {\n const outcomes: MutationOutcome[] = [];\n const result = transact(project, draft => {\n for (const [index, mutation] of mutations.entries()) {\n try {\n outcomes.push(run(draft, mutation));\n } catch (error) {\n throw new Error(\n `Mutation #${index + 1} (${mutation.kind}): ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n });\n return result.ok ? { ...result, outcomes } : result;\n}\n","import { distance, footprint, openRing, pointInRing, segmentProjection } from './geometry';\nimport { createRouteClearance, routeBounds, ROUTE_CLEARANCE } from './routeClearance';\nimport type { NavEdge, NavNode, Point, ProjectDocument, Ring } from './types';\n\n/** Bind a graph node to the room whose walkable floor it can enter. Use separate nodes on the\n * sides of a controlled portal and join those with a directed/door edge in `graph`. */\nexport interface RoomAccess {\n spaceId: string;\n nodeId: string;\n}\nexport interface RoomNavigationGraph {\n nodes: NavNode[];\n edges: NavEdge[];\n}\nconst GENERATED = '@room-nav:';\nconst winding = (ring: Ring) =>\n Math.sign(\n ring.reduce((sum, p, i) => {\n const q = ring[(i + 1) % ring.length];\n return sum + p[0] * q[1] - q[0] * p[1];\n }, 0),\n ) || 1;\n\n/** Build the geometric walking graph inside rooms. Explicit access points describe connectivity;\n * room outlines, holes, pools and wall thickness describe where a person can walk. The input\n * document/graph are not mutated. Supplied door/vertical/directed edges are kept verbatim. */\nexport function buildRoomNavigation(\n project: ProjectDocument,\n access: readonly RoomAccess[],\n graph: RoomNavigationGraph = { nodes: [], edges: [] },\n): RoomNavigationGraph {\n const rooms = project.objects.filter(o => o.kind === 'room' && footprint(o)[0]?.length);\n const nodes: NavNode[] = graph.nodes\n .filter(n => !n.id.startsWith(GENERATED))\n .map(n => ({ ...n, position: [...n.position] }));\n const edges = graph.edges.filter(e => !e.id.startsWith(GENERATED));\n const byId = new Map(nodes.map(n => [n.id, n]));\n const members = new Map(rooms.map(room => [room.id, [] as NavNode[]]));\n const floors = new Map(rooms.map(room => [room.id, room.floorId]));\n for (const node of nodes)\n if (node.objectId && floors.get(node.objectId) === node.floorId) members.get(node.objectId)?.push(node);\n for (const { spaceId, nodeId } of access) {\n const node = byId.get(nodeId),\n room = members.get(spaceId);\n if (node && room && floors.get(spaceId) === node.floorId && !room.includes(node)) room.push(node);\n }\n const pools = new Map<string, Ring[]>();\n for (const o of project.objects)\n if (o.water && o.parentId) {\n const rings = pools.get(o.parentId) ?? [];\n rings.push(...footprint(o).slice(0, 1));\n pools.set(o.parentId, rings);\n }\n const clearance = createRouteClearance(project);\n for (const room of rooms) {\n const prefix = `${GENERATED}${encodeURIComponent(room.id)}:`;\n const candidates = members.get(room.id)!;\n const [outline, ...holes] = footprint(room);\n const visible = clearance(room.floorId, routeBounds(outline));\n const clear = (a: Point, b: Point) => segmentInRoom(a, b, outline) && visible(a, b);\n const obstacles = [...holes, ...(pools.get(room.id) ?? [])];\n const add = (position: Point) => {\n if (!clear(position, position)) return;\n if (candidates.some(n => distance(n.position, position) < 0.01)) return;\n const node: NavNode = { id: `${prefix}point:${candidates.length}`, floorId: room.floorId, position };\n nodes.push(node);\n candidates.push(node);\n };\n // Polygon offset corners handle concave rooms as well as rectangular halls. Each candidate is\n // still checked against the real geometry; no bounding-box shortcut can cross a notch or hole.\n const corners = (ring: Ring, inset: number) => {\n const points = openRing(ring),\n sign = winding(ring);\n const normal = (a: Point, b: Point): Point => {\n const d = distance(a, b) || 1;\n return [(sign * (a[1] - b[1])) / d, (sign * (b[0] - a[0])) / d];\n };\n for (let i = 0; i < points.length; i++) {\n const at = points[i],\n before = points[(i + points.length - 1) % points.length],\n next = points[(i + 1) % points.length];\n const a = normal(before, at),\n b = normal(at, next),\n divisor = 1 + a[0] * b[0] + a[1] * b[1];\n const turn = sign * ((at[0] - before[0]) * (next[1] - at[1]) - (at[1] - before[1]) * (next[0] - at[0]));\n if (inset > 0 && turn >= 0) continue; // only concave outer corners need waypoints\n if (divisor > 0.05) add([at[0] + (inset * (a[0] + b[0])) / divisor, at[1] + (inset * (a[1] + b[1])) / divisor]);\n if (inset < 0) add([(at[0] + next[0]) / 2 + inset * b[0], (at[1] + next[1]) / 2 + inset * b[1]]);\n }\n };\n corners(outline, ROUTE_CLEARANCE + 0.2);\n for (const obstacle of obstacles) corners(obstacle, -ROUTE_CLEARANCE - 0.1);\n // Optional perpendicular approaches avoid grazing a jamb on an oblique crossing. Aligned\n // access points can still connect directly, without a detour through either approach.\n const ring = openRing(outline),\n sign = winding(outline);\n for (const node of [...candidates])\n for (let i = 0; i < ring.length; i++) {\n const a = ring[i],\n b = ring[(i + 1) % ring.length],\n length = distance(a, b);\n if (length && segmentProjection(node.position, a, b).distance < 0.01)\n add([\n node.position[0] + ((sign * (a[1] - b[1])) / length) * 0.9,\n node.position[1] + ((sign * (b[0] - a[0])) / length) * 0.9,\n ]);\n }\n let anchor = candidates.find(n => n.objectId === room.id);\n if (!anchor) {\n anchor = { id: `${prefix}anchor`, floorId: room.floorId, position: [...room.position], objectId: room.id };\n nodes.push(anchor);\n candidates.push(anchor);\n }\n if (!clear(anchor.position, anchor.position)) {\n const dry = candidates\n .filter(n => clear(n.position, n.position))\n .sort((a, b) => distance(a.position, room.position) - distance(b.position, room.position))[0];\n if (dry) anchor.position = [...dry.position];\n }\n for (let i = 0; i < candidates.length; i++)\n for (let j = i + 1; j < candidates.length; j++) {\n const a = candidates[i],\n b = candidates[j];\n if (clear(a.position, b.position))\n edges.push({ id: `${prefix}edge:${i}:${j}`, kind: 'walk', aId: a.id, bId: b.id });\n }\n }\n return { nodes, edges };\n}\n\n/** Every interval of the segment must stay inside the room, including when it passes exactly\n * through a concave vertex. Testing only the midpoint misses paths that leave and re-enter. */\nfunction segmentInRoom(a: Point, b: Point, outline: Ring): boolean {\n const ring = openRing(outline);\n const inside = (p: Point) =>\n pointInRing(p, ring) || ring.some((q, i) => segmentProjection(p, q, ring[(i + 1) % ring.length]).distance < 1e-7);\n if (!inside(a) || !inside(b)) return false;\n const dx = b[0] - a[0],\n dy = b[1] - a[1],\n length = distance(a, b);\n if (length < 1e-8) return true;\n const cuts = [0, 1];\n for (let i = 0; i < ring.length; i++) {\n const c = ring[i],\n d = ring[(i + 1) % ring.length],\n ex = d[0] - c[0],\n ey = d[1] - c[1],\n cross = dx * ey - dy * ex;\n if (Math.abs(cross) < 1e-9) {\n for (const p of [c, d]) if (segmentProjection(p, a, b).distance < 1e-7) cuts.push(segmentProjection(p, a, b).t);\n } else {\n const t = ((c[0] - a[0]) * ey - (c[1] - a[1]) * ex) / cross;\n const u = ((c[0] - a[0]) * dy - (c[1] - a[1]) * dx) / cross;\n if (t > 0 && t < 1 && u >= 0 && u <= 1) cuts.push(t);\n }\n }\n cuts.sort((a, b) => a - b);\n return cuts.slice(1).every((t, i) => inside([a[0] + (dx * (t + cuts[i])) / 2, a[1] + (dy * (t + cuts[i])) / 2]));\n}\n"],"names":["f","e","d","n","u","r","l","o","s","c","m","w","_","z","h","k","g","a","y","x","p","epsilon","splitter","resulterrbound","sum","elen","flen","Q","Qnew","hh","bvirt","enow","fnow","eindex","findex","hindex","estimate","i","vec","ccwerrboundA","ccwerrboundB","ccwerrboundC","B","C1","C2","D","orient2dadapt","ax","ay","bx","by","cx","cy","detsum","acxtail","acytail","bcxtail","bcytail","ahi","alo","bhi","blo","_i","_j","_0","s1","s0","t1","t0","u3","acx","bcx","acy","bcy","det","errbound","C1len","C2len","Dlen","orient2d","detleft","detright","isInBbox","bbox","point","getBboxOverlap","b1","b2","lowerX","upperX","lowerY","upperY","EPSILON_SQ","cmp","b","ab","PtRounder","CoordRounder","SplayTree","coord","node","prevNode","nextNode","rounder","crossProduct","dotProduct","compareVectorAngles","basePt","endPt1","endPt2","res","length","v","sineOfAngle","pShared","pBase","pAngle","vBase","vAngle","cosineOfAngle","horizontalIntersection","pt","verticalIntersection","intersection$1","pt1","v1","pt2","v2","kross","ve","d1","d2","x1","x2","y1","y2","SweepEvent","ptCmp","Segment","aPt","bPt","isLeft","other","otherEvents","iMax","evt","numEvents","evt1","j","evt2","events","baseEvent","cache","fillCache","linkedEvent","nextEvent","asine","acosine","bsine","bcosine","segmentId","alx","blx","arx","brx","aly","bly","ary","bry","aCmpBLeft","bCmpARight","bCmpALeft","aCmpBRight","leftSE","rightSE","rings","windings","ring","leftPt","rightPt","winding","cmpPts","newRightSE","lPt","rPt","yDist","xFromYDist","xDist","yFromXDist","tBbox","oBbox","bboxOverlap","tlp","trp","olp","orp","touchesOtherLSE","touchesThisLSE","touchesOtherRSE","touchesThisRSE","newEvents","alreadyLinked","newLeftSE","oldRightSE","newSeg","tmpEvt","consumer","consumee","tmp","index","seg","beforeState","ringsAfter","windingsAfter","mpsAfter","polysAfter","polysExclude","poly","mp","mpsBefore","operation","noBefores","noAfters","least","most","diff","isJustSubject","mps","RingIn","geomRing","isExterior","firstPoint","prevPoint","sweepEvents","segment","PolyIn","geomPoly","multiPoly","ringSweepEvents","jMax","MultiPolyIn","geom","isSubject","polySweepEvents","RingOut","allSegments","ringsOut","prevEvent","event","startingPoint","intersectionLEs","availableLEs","firstPt","lastPt","indexLE","intersectionLE","ringEvents","comparator","prevPt","points","nextPt","step","iStart","iEnd","orderedPoints","enclosing","leftMostEvt","prevSeg","prevPrevSeg","PolyOut","exteriorRing","ringGeom","MultiPolyOut","polyGeom","polys","enclosingRing","SweepLine","queue","nextSeg","prevMySplitter","prevInter","newEventsFromSplit","nextMySplitter","nextInter","mySplitter","inter","POLYGON_CLIPPING_MAX_QUEUE_SIZE","POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS","Operation","type","moreGeoms","multipolys","subject","mpA","sweepLine","prevQueueSize","union","_len","_key","intersection","_len2","_key2","xor","_len3","_key3","difference","subjectGeom","_len4","clippingGeoms","_key4","OBJECT_KINDS","AMBIENCE_PRESETS","uid","isArea","kind","isDevice","isOpening","isSpace","pairKey","sharedBoundaryPortals","project","_a","edges","edge","sides","space","loop","use","owners","owner","out","effectivePortals","shared","pairs","bound","stored","authoredPairs","retained","held","entryInto","portal","spaceId","passage","memberSet","zone","seen","childId","child","id","zoneSpaces","perimeter","inside","captive","addZone","name","spaceIds","purpose","removeZone","zoneId","setZoneMembers","member","eligible","next","nestZone","parentId","_b","parent","reaches","from","target","addPortalGroup","portalIds","group","removePortalGroup","groupId","setPortalGroupMembers","pruneOntology","alive","zoneIds","TRAVERSABLE","spaceNodeId","portalKind","opening","sameFloor","derivedGraph","objects","floors","nodes","existing","made","spacePoint","join","objectId","directed","bindable","to","members","oneWay","topology","hit","built","isVertical","shaftKey","object","servedFloors","key","ids","flights","levels","floorId","flightsAt","all","span","PITCH","runFor","rise","pitch","pitchOf","run","MAX_GOING","RISER","HEADROOM","treads","steps","stairModel","first","flightReversed","model","flightRun","position","objectPosition","rotation","objectRotation","rad","ux","uy","at","t","half","pad","incline","going","headroomBand","height","width","steep","depth","closeRing","rectangle","primaryShafts","lowest","rival","arrivesAt","level","departsFrom","passesThrough","shaftVoids","primary","options","ceiling","groups","flight","footprint","rotate","xs","ys","loX","hiX","loY","hiY","ROUTE_CLEARANCE","routeBounds","overlaps","gap","intersects","segmentProjection","createRouteClearance","junctions","openings","ranges","walls","wall","distance","parts","nx","ny","add","start","end","cursor","holes","openRing","extent","localWalls","localHoles","obstacles","bounds","pointInRing","routeClearance","check","ELEVATOR_BASE","ELEVATOR_PER_METRE","STAIR_CLIMB_FACTOR","DOOR_COST","NAV_WELD","navNodes","navEdges","floorOf","elevation","addNavNode","addNavEdge","navPath","chainVertical","travel","twins","twin","HERE","edgeCost","edgeLength","routeAnchors","anchor","nearest","routeEnd","tag","here","spaceAt","clear","joins","inSpace","extraEdges","findRoute","fromEnd","toEnd","starts","goals","byId","adjacency","machine","reading","up","forward","RouteQueue","dist","prev","done","goalCosts","bestGoal","entry","current","best","goal","legs","back","path","walked","routeSteps","__publicField","cost","item","last","floorPhrase","floor","legName","leg","fallback","nodeIds","text","direction","EXTERIOR_PRESETS","GEOMETRY_EPS","JOIN_EPS","MIN_WALL_LENGTH","MIN_RING_EDGE","MIN_SPACE_AREA","MIN_FACE_AREA","CLIP_SCALE","COORD_LIMIT","finite","string","distinct","validateRings","minEdge","minArea","ringArea","validateRelationships","barriers","attachments","list","barrier","barrierEnds","MIN_SEGMENT","error","containedBy","ancestor","OPENING_MIN_SEGMENT","offset","validateNavigation","floorIds","vertical","validateProject","value","fail","message","origin","buildingIds","badAmbience","areasByFloor","on","areas","lamp","water","slide","kindById","walking","settled","cycles","found","validateSpaceBoundaries","navError","freezeProject","walk","inner","transact","change","draft","synchronizeGeometry","objectArea","old","previous","boundaryEdges","followsBoundaries","ends","reverse","signedArea","area","totalArea","pg","quantize","q","clips","scaled","input","operands","result","polygonClipping","operand","replaceBoundaryUses","edgeId","replacement","boundaryRings","loops","splitEdge","cuts","interior","EPS","unique","stops","physical","pieces","normalizeBoundaries","canonical","representatives","earlier","positions","spans","cut","boundsMeet","one","two","vx","vy","byEnds","removed","kept","flipped","used","boundaryRegions","outgoing","entered","low","bridges","time","visit","reversed","candidate","wallBodies","runs","merged","cd","pair","thickness","len","tidy","minX","minY","maxX","maxY","netEvaluator","allowEmpty","solids","box","nearby","netRings","usable","derivedSpaceRings","cacheRings","centroid","bindSpaceToRegion","region","boundaryRegionAt","junctionAt","addVirtualBoundary","startId","endId","drawVirtualBoundary","onLine","removeBarrier","connectSpace","source","sourceRings","sourceArea","candidates","ri","disconnectSpace","addBoundaryHole","splitBoundarySpace","dx","dy","hits","closed","ex","ey","addBarrier","created","refreshBoundarySpaces","mergeBoundaryGeometry","keep","absorbed","remaining","preserveBoundary","topologyChanged","regions","net","envelope","before","collection","signature","doc","changed","occupied","faces","loopKey","issue","calculated","degrees","DEG","WGS84_A","WGS84_E2","metresPerDegree","lat","geoOrigin","lngLat","bearing","moveOrigin","east","north","moved","toLocal","toLngLat","center","segmentsCross","side","s2","s3","s4","slopeElevation","slope","junctionIndices","indexedJunction","cross","barrierJoinPoint","junctionIssue","barrierStrokeIssue","atStart","tooShort","minimum","joinAt","newId","oldEnd","barrierId","splitRoom","roomId","pa","pb","dir","normal","reach","c0","c1","halfPlane","clip","netArea","drawnKey","drawn","weld","crossing","right","left","apply","outer","crossings","denom","qp","deduped","removeFloor","goneObjects","goneBarriers","goneNodes","livePortals","duplicateFloor","_c","map","cloneId","enclosedRegion","enclosedRegions","corners","x0","y0","angle","mid","open","straight","refitEnclosedRooms","after","sameness","matches","pool","claims","room","now","refitted","spaces","outline","hole","bestArea","PROBE","inferPortals","clearance","sign","probe","WALK","REACH","MIN_OPENING","inferOpenBoundaries","byFloor","standOn","landed","within","shapes","shape","wallsByFloor","floorKey","onFloor","ordered","ringRaw","px","py","INFERRED","refreshPortals","authored","heldPairs","edited","fresh","spacesDividedBy","divideSpaces","spacesRejoinedBy","without","already","mergeSpaces","keepId","absorbedId","united","emptyProject","datum","createObject","sizes","DEFAULT_RANGE","DEFAULT_FOV","coverageOf","camera","range","facing","copyProject","copy","openingFloorId","preferred","blobDataUrl","blob","resolve","reject","reader","exportProject","assets","embeddedAssets","importProject","json","embedded","decoded","data","assetId","parseExport","drawBarrier","encloseRoom","same","fitAttachedOpenings","geometryMutation","move","_d","deltas","vertex","fraction","delta","applyGeometryDrag","patch","gone","deadNodes","items","set","immutable","applyMutation","mutation","applyMutations","mutations","outcomes","GENERATED","buildRoomNavigation","access","graph","rooms","nodeId","pools","prefix","visible","segmentInRoom","inset","divisor","turn","obstacle","dry"],"mappings":"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","x_google_ignoreList":[0,1,2,3]}