@pascal-app/core 1.0.0-beta.5 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (417) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +23 -0
  3. package/dist/capture/index.d.ts +3 -0
  4. package/dist/capture/index.d.ts.map +1 -0
  5. package/dist/capture/index.js +2 -0
  6. package/dist/capture/schema.d.ts +417 -0
  7. package/dist/capture/schema.d.ts.map +1 -0
  8. package/dist/capture/schema.js +350 -0
  9. package/dist/capture/source.d.ts +60 -0
  10. package/dist/capture/source.d.ts.map +1 -0
  11. package/dist/capture/source.js +254 -0
  12. package/dist/events/bus.d.ts +58 -7
  13. package/dist/events/bus.d.ts.map +1 -1
  14. package/dist/events/hidden-wall-pointer-hold.d.ts +28 -0
  15. package/dist/events/hidden-wall-pointer-hold.d.ts.map +1 -0
  16. package/dist/events/hidden-wall-pointer-hold.js +37 -0
  17. package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts +4 -4
  18. package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts.map +1 -1
  19. package/dist/hooks/spatial-grid/floor-placed-elevation.js +7 -12
  20. package/dist/hooks/spatial-grid/floor-placed-footprints.d.ts +4 -0
  21. package/dist/hooks/spatial-grid/floor-placed-footprints.d.ts.map +1 -0
  22. package/dist/hooks/spatial-grid/floor-placed-footprints.js +7 -0
  23. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts +5 -8
  24. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts.map +1 -1
  25. package/dist/hooks/spatial-grid/spatial-grid-manager.js +23 -106
  26. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts +2931 -2
  27. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts.map +1 -1
  28. package/dist/hooks/spatial-grid/spatial-grid-sync.js +207 -30
  29. package/dist/hooks/spatial-grid/support-host-patch.d.ts +45 -1
  30. package/dist/hooks/spatial-grid/support-host-patch.d.ts.map +1 -1
  31. package/dist/hooks/spatial-grid/support-host-patch.js +174 -9
  32. package/dist/hooks/spatial-grid/use-spatial-query.d.ts +1 -1
  33. package/dist/hooks/spatial-grid/use-spatial-query.js +1 -1
  34. package/dist/index.d.ts +74 -64
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +74 -61
  37. package/dist/lib/asset-storage.d.ts.map +1 -1
  38. package/dist/lib/asset-storage.js +4 -1
  39. package/dist/lib/door-operation.d.ts +1 -1
  40. package/dist/lib/item-polygon-overlap.d.ts +6 -0
  41. package/dist/lib/item-polygon-overlap.d.ts.map +1 -0
  42. package/dist/lib/item-polygon-overlap.js +67 -0
  43. package/dist/lib/level-name.d.ts +1 -1
  44. package/dist/lib/measurement-geometry.d.ts +4 -4
  45. package/dist/lib/plan-footprint.d.ts +41 -0
  46. package/dist/lib/plan-footprint.d.ts.map +1 -0
  47. package/dist/lib/plan-footprint.js +58 -0
  48. package/dist/lib/polygon-union.d.ts +4 -0
  49. package/dist/lib/polygon-union.d.ts.map +1 -0
  50. package/dist/lib/polygon-union.js +306 -0
  51. package/dist/lib/roof-overlap.d.ts +32 -0
  52. package/dist/lib/roof-overlap.d.ts.map +1 -0
  53. package/dist/lib/roof-overlap.js +72 -0
  54. package/dist/lib/room-topology-index.d.ts +1 -1
  55. package/dist/lib/room-topology-index.js +1 -1
  56. package/dist/lib/selection-proxy.d.ts +1 -1
  57. package/dist/lib/slab-polygon.d.ts +36 -3
  58. package/dist/lib/slab-polygon.d.ts.map +1 -1
  59. package/dist/lib/slab-polygon.js +135 -29
  60. package/dist/lib/space-detection.d.ts +12 -1
  61. package/dist/lib/space-detection.d.ts.map +1 -1
  62. package/dist/lib/space-detection.js +58 -25
  63. package/dist/lib/terrain-brush.d.ts +1 -1
  64. package/dist/lib/terrain-brush.js +1 -1
  65. package/dist/lib/terrain-codec.d.ts +2 -2
  66. package/dist/lib/terrain-codec.js +1 -1
  67. package/dist/lib/terrain-raycast.d.ts +1 -1
  68. package/dist/lib/terrain-raycast.js +1 -1
  69. package/dist/lib/terrain-source.d.ts +3 -3
  70. package/dist/lib/terrain-source.js +3 -3
  71. package/dist/lib/terrain-support.d.ts +1 -1
  72. package/dist/lib/terrain-support.js +3 -3
  73. package/dist/lib/unit-containment.d.ts +19 -0
  74. package/dist/lib/unit-containment.d.ts.map +1 -0
  75. package/dist/lib/unit-containment.js +158 -0
  76. package/dist/lib/unit-report.d.ts +19 -0
  77. package/dist/lib/unit-report.d.ts.map +1 -0
  78. package/dist/lib/unit-report.js +36 -0
  79. package/dist/lib/wall-distance.d.ts +2 -2
  80. package/dist/lib/wall-distance.js +1 -1
  81. package/dist/lib/zone-quantities.d.ts +1 -1
  82. package/dist/lib/zone-quantities.js +7 -7
  83. package/dist/material-library.d.ts +1 -1
  84. package/dist/material-library.js +1 -1
  85. package/dist/procedural-items/fixtures.d.ts +261 -0
  86. package/dist/procedural-items/fixtures.d.ts.map +1 -0
  87. package/dist/procedural-items/fixtures.js +349 -0
  88. package/dist/procedural-items/index.d.ts +10 -0
  89. package/dist/procedural-items/index.d.ts.map +1 -0
  90. package/dist/procedural-items/index.js +9 -0
  91. package/dist/procedural-items/integration.d.ts +92 -0
  92. package/dist/procedural-items/integration.d.ts.map +1 -0
  93. package/dist/procedural-items/integration.js +19 -0
  94. package/dist/procedural-items/library-colors.d.ts +56 -0
  95. package/dist/procedural-items/library-colors.d.ts.map +1 -0
  96. package/dist/procedural-items/library-colors.js +84 -0
  97. package/dist/procedural-items/materials.d.ts +5 -0
  98. package/dist/procedural-items/materials.d.ts.map +1 -0
  99. package/dist/procedural-items/materials.js +47 -0
  100. package/dist/procedural-items/node.d.ts +280 -0
  101. package/dist/procedural-items/node.d.ts.map +1 -0
  102. package/dist/procedural-items/node.js +71 -0
  103. package/dist/procedural-items/placement.d.ts +7 -0
  104. package/dist/procedural-items/placement.d.ts.map +1 -0
  105. package/dist/procedural-items/placement.js +48 -0
  106. package/dist/procedural-items/query.d.ts +50 -0
  107. package/dist/procedural-items/query.d.ts.map +1 -0
  108. package/dist/procedural-items/query.js +298 -0
  109. package/dist/procedural-items/recipe.d.ts +144 -0
  110. package/dist/procedural-items/recipe.d.ts.map +1 -0
  111. package/dist/procedural-items/recipe.js +372 -0
  112. package/dist/procedural-items/spatial.d.ts +19 -0
  113. package/dist/procedural-items/spatial.d.ts.map +1 -0
  114. package/dist/procedural-items/spatial.js +39 -0
  115. package/dist/registry/__bench__/relations-resolver.bench.js +2 -2
  116. package/dist/registry/handles.d.ts +36 -7
  117. package/dist/registry/handles.d.ts.map +1 -1
  118. package/dist/registry/index.d.ts +6 -7
  119. package/dist/registry/index.d.ts.map +1 -1
  120. package/dist/registry/index.js +4 -5
  121. package/dist/registry/registry.d.ts +13 -6
  122. package/dist/registry/registry.d.ts.map +1 -1
  123. package/dist/registry/registry.js +37 -4
  124. package/dist/registry/relations-resolver.d.ts +2 -2
  125. package/dist/registry/relations-resolver.js +1 -1
  126. package/dist/registry/scene-api.d.ts +18 -2
  127. package/dist/registry/scene-api.d.ts.map +1 -1
  128. package/dist/registry/scene-api.js +50 -2
  129. package/dist/registry/subtree.d.ts +1 -1
  130. package/dist/registry/subtree.js +2 -2
  131. package/dist/registry/types.d.ts +246 -21
  132. package/dist/registry/types.d.ts.map +1 -1
  133. package/dist/registry/use-registry-version.js +1 -1
  134. package/dist/registry/validate-relations.d.ts +4 -0
  135. package/dist/registry/validate-relations.d.ts.map +1 -0
  136. package/dist/registry/validate-relations.js +22 -0
  137. package/dist/schema/__bench__/node-parsers.bench.d.ts +24 -0
  138. package/dist/schema/__bench__/node-parsers.bench.d.ts.map +1 -0
  139. package/dist/schema/__bench__/node-parsers.bench.js +314 -0
  140. package/dist/schema/__fixtures__/node-fixtures.d.ts +28 -0
  141. package/dist/schema/__fixtures__/node-fixtures.d.ts.map +1 -0
  142. package/dist/schema/__fixtures__/node-fixtures.js +127 -0
  143. package/dist/schema/base.d.ts +1 -1
  144. package/dist/schema/base.d.ts.map +1 -1
  145. package/dist/schema/base.js +9 -2
  146. package/dist/schema/collections.d.ts +1 -1
  147. package/dist/schema/collections.js +1 -1
  148. package/dist/schema/compiled-node-parsers.d.ts +40 -0
  149. package/dist/schema/compiled-node-parsers.d.ts.map +1 -0
  150. package/dist/schema/compiled-node-parsers.js +95 -0
  151. package/dist/schema/index.d.ts +73 -66
  152. package/dist/schema/index.d.ts.map +1 -1
  153. package/dist/schema/index.js +65 -57
  154. package/dist/schema/material.d.ts +1 -0
  155. package/dist/schema/material.d.ts.map +1 -1
  156. package/dist/schema/material.js +2 -1
  157. package/dist/schema/nodes/automatic-downspout.d.ts +17 -0
  158. package/dist/schema/nodes/automatic-downspout.d.ts.map +1 -0
  159. package/dist/schema/nodes/automatic-downspout.js +237 -0
  160. package/dist/schema/nodes/block.d.ts +107 -0
  161. package/dist/schema/nodes/block.d.ts.map +1 -0
  162. package/dist/schema/nodes/block.js +206 -0
  163. package/dist/schema/nodes/box-vent.d.ts +8 -2
  164. package/dist/schema/nodes/box-vent.d.ts.map +1 -1
  165. package/dist/schema/nodes/box-vent.js +4 -2
  166. package/dist/schema/nodes/building.d.ts +2 -2
  167. package/dist/schema/nodes/building.d.ts.map +1 -1
  168. package/dist/schema/nodes/building.js +8 -5
  169. package/dist/schema/nodes/cabinet.d.ts +26 -4
  170. package/dist/schema/nodes/cabinet.d.ts.map +1 -1
  171. package/dist/schema/nodes/cabinet.js +29 -8
  172. package/dist/schema/nodes/ceiling.d.ts +2 -2
  173. package/dist/schema/nodes/ceiling.js +5 -5
  174. package/dist/schema/nodes/chimney.d.ts +2 -2
  175. package/dist/schema/nodes/chimney.js +2 -2
  176. package/dist/schema/nodes/column.d.ts +7 -6
  177. package/dist/schema/nodes/column.d.ts.map +1 -1
  178. package/dist/schema/nodes/column.js +3 -2
  179. package/dist/schema/nodes/construction-dimension.d.ts +1 -1
  180. package/dist/schema/nodes/construction-dimension.js +2 -2
  181. package/dist/schema/nodes/cupola.d.ts +9 -1
  182. package/dist/schema/nodes/cupola.d.ts.map +1 -1
  183. package/dist/schema/nodes/cupola.js +4 -2
  184. package/dist/schema/nodes/door.d.ts +1 -1
  185. package/dist/schema/nodes/door.js +2 -2
  186. package/dist/schema/nodes/dormer.d.ts +45 -2
  187. package/dist/schema/nodes/dormer.d.ts.map +1 -1
  188. package/dist/schema/nodes/dormer.js +133 -9
  189. package/dist/schema/nodes/downspout.d.ts +11 -1
  190. package/dist/schema/nodes/downspout.d.ts.map +1 -1
  191. package/dist/schema/nodes/downspout.js +26 -2
  192. package/dist/schema/nodes/duct-fitting.d.ts +18 -1
  193. package/dist/schema/nodes/duct-fitting.d.ts.map +1 -1
  194. package/dist/schema/nodes/duct-fitting.js +26 -5
  195. package/dist/schema/nodes/duct-segment.d.ts +23 -1
  196. package/dist/schema/nodes/duct-segment.d.ts.map +1 -1
  197. package/dist/schema/nodes/duct-segment.js +21 -1
  198. package/dist/schema/nodes/duct-terminal.d.ts +1 -1
  199. package/dist/schema/nodes/duct-terminal.js +1 -1
  200. package/dist/schema/nodes/elevator.d.ts +1 -1
  201. package/dist/schema/nodes/elevator.js +2 -2
  202. package/dist/schema/nodes/eyebrow-vent.d.ts +8 -2
  203. package/dist/schema/nodes/eyebrow-vent.d.ts.map +1 -1
  204. package/dist/schema/nodes/eyebrow-vent.js +4 -2
  205. package/dist/schema/nodes/fence.d.ts +1 -1
  206. package/dist/schema/nodes/fence.js +2 -2
  207. package/dist/schema/nodes/guide.d.ts +1 -1
  208. package/dist/schema/nodes/guide.js +2 -2
  209. package/dist/schema/nodes/gutter.d.ts +36 -2
  210. package/dist/schema/nodes/gutter.d.ts.map +1 -1
  211. package/dist/schema/nodes/gutter.js +310 -3
  212. package/dist/schema/nodes/hanger-overrides.d.ts +7 -0
  213. package/dist/schema/nodes/hanger-overrides.d.ts.map +1 -0
  214. package/dist/schema/nodes/hanger-overrides.js +6 -0
  215. package/dist/schema/nodes/hvac-equipment.d.ts +1 -1
  216. package/dist/schema/nodes/hvac-equipment.js +1 -1
  217. package/dist/schema/nodes/imported-mesh.d.ts +40 -0
  218. package/dist/schema/nodes/imported-mesh.d.ts.map +1 -0
  219. package/dist/schema/nodes/imported-mesh.js +27 -0
  220. package/dist/schema/nodes/item.d.ts +3 -2
  221. package/dist/schema/nodes/item.d.ts.map +1 -1
  222. package/dist/schema/nodes/item.js +8 -3
  223. package/dist/schema/nodes/lean-to-extension.d.ts +212 -0
  224. package/dist/schema/nodes/lean-to-extension.d.ts.map +1 -0
  225. package/dist/schema/nodes/lean-to-extension.js +114 -0
  226. package/dist/schema/nodes/level.d.ts +2 -2
  227. package/dist/schema/nodes/level.d.ts.map +1 -1
  228. package/dist/schema/nodes/level.js +1 -1
  229. package/dist/schema/nodes/lineset.d.ts +1 -1
  230. package/dist/schema/nodes/lineset.js +1 -1
  231. package/dist/schema/nodes/liquid-line.d.ts +1 -1
  232. package/dist/schema/nodes/liquid-line.js +1 -1
  233. package/dist/schema/nodes/measurement.d.ts +1 -1
  234. package/dist/schema/nodes/measurement.js +2 -2
  235. package/dist/schema/nodes/pipe-fitting.d.ts +10 -2
  236. package/dist/schema/nodes/pipe-fitting.d.ts.map +1 -1
  237. package/dist/schema/nodes/pipe-fitting.js +7 -3
  238. package/dist/schema/nodes/pipe-segment.d.ts +24 -2
  239. package/dist/schema/nodes/pipe-segment.d.ts.map +1 -1
  240. package/dist/schema/nodes/pipe-segment.js +21 -1
  241. package/dist/schema/nodes/pipe-trap.d.ts +2 -2
  242. package/dist/schema/nodes/pipe-trap.js +1 -1
  243. package/dist/schema/nodes/ridge-vent.d.ts +2 -2
  244. package/dist/schema/nodes/ridge-vent.d.ts.map +1 -1
  245. package/dist/schema/nodes/ridge-vent.js +7 -4
  246. package/dist/schema/nodes/roof-segment-shape.d.ts +5 -1
  247. package/dist/schema/nodes/roof-segment-shape.d.ts.map +1 -1
  248. package/dist/schema/nodes/roof-segment-shape.js +65 -2
  249. package/dist/schema/nodes/roof-segment-walls.d.ts +4 -2
  250. package/dist/schema/nodes/roof-segment-walls.d.ts.map +1 -1
  251. package/dist/schema/nodes/roof-segment-walls.js +2 -2
  252. package/dist/schema/nodes/roof-segment.d.ts +42 -2
  253. package/dist/schema/nodes/roof-segment.d.ts.map +1 -1
  254. package/dist/schema/nodes/roof-segment.js +81 -4
  255. package/dist/schema/nodes/roof.d.ts +23 -2
  256. package/dist/schema/nodes/roof.d.ts.map +1 -1
  257. package/dist/schema/nodes/roof.js +17 -3
  258. package/dist/schema/nodes/scan.d.ts +19 -2
  259. package/dist/schema/nodes/scan.d.ts.map +1 -1
  260. package/dist/schema/nodes/scan.js +13 -3
  261. package/dist/schema/nodes/shelf.d.ts +3 -3
  262. package/dist/schema/nodes/shelf.d.ts.map +1 -1
  263. package/dist/schema/nodes/shelf.js +3 -4
  264. package/dist/schema/nodes/site.d.ts +1 -1
  265. package/dist/schema/nodes/site.js +2 -2
  266. package/dist/schema/nodes/skylight.d.ts +5 -5
  267. package/dist/schema/nodes/skylight.js +2 -2
  268. package/dist/schema/nodes/slab.d.ts +1 -1
  269. package/dist/schema/nodes/slab.js +3 -3
  270. package/dist/schema/nodes/solar-panel.d.ts +1 -1
  271. package/dist/schema/nodes/solar-panel.js +3 -3
  272. package/dist/schema/nodes/spawn.d.ts +1 -1
  273. package/dist/schema/nodes/spawn.js +1 -1
  274. package/dist/schema/nodes/stair-segment.d.ts +1 -1
  275. package/dist/schema/nodes/stair-segment.js +2 -2
  276. package/dist/schema/nodes/stair.d.ts +2 -2
  277. package/dist/schema/nodes/stair.js +3 -3
  278. package/dist/schema/nodes/structural-grid.d.ts +1 -1
  279. package/dist/schema/nodes/structural-grid.js +1 -1
  280. package/dist/schema/nodes/turbine-vent.d.ts +8 -2
  281. package/dist/schema/nodes/turbine-vent.d.ts.map +1 -1
  282. package/dist/schema/nodes/turbine-vent.js +4 -2
  283. package/dist/schema/nodes/unit.d.ts +33 -0
  284. package/dist/schema/nodes/unit.d.ts.map +1 -0
  285. package/dist/schema/nodes/unit.js +13 -0
  286. package/dist/schema/nodes/wall.d.ts +5 -5
  287. package/dist/schema/nodes/wall.d.ts.map +1 -1
  288. package/dist/schema/nodes/wall.js +13 -6
  289. package/dist/schema/nodes/window.d.ts +10 -3
  290. package/dist/schema/nodes/window.d.ts.map +1 -1
  291. package/dist/schema/nodes/window.js +6 -2
  292. package/dist/schema/nodes/zone.d.ts +2 -2
  293. package/dist/schema/nodes/zone.js +2 -2
  294. package/dist/schema/scene-material.js +2 -2
  295. package/dist/schema/types.d.ts +815 -118
  296. package/dist/schema/types.d.ts.map +1 -1
  297. package/dist/schema/types.js +79 -46
  298. package/dist/services/alignment-anchors.d.ts +6 -11
  299. package/dist/services/alignment-anchors.d.ts.map +1 -1
  300. package/dist/services/alignment-anchors.js +7 -34
  301. package/dist/services/drag-session.d.ts +4 -4
  302. package/dist/services/drag-session.js +1 -1
  303. package/dist/services/hosting.d.ts +4 -10
  304. package/dist/services/hosting.d.ts.map +1 -1
  305. package/dist/services/hosting.js +6 -16
  306. package/dist/services/index.d.ts +16 -13
  307. package/dist/services/index.d.ts.map +1 -1
  308. package/dist/services/index.js +16 -13
  309. package/dist/services/level-height.d.ts +2 -2
  310. package/dist/services/level-height.js +3 -3
  311. package/dist/services/movement.d.ts +3 -3
  312. package/dist/services/movement.js +2 -2
  313. package/dist/services/port-connectivity.d.ts +1 -1
  314. package/dist/services/port-connectivity.js +1 -1
  315. package/dist/services/riser-diagram.d.ts +1 -1
  316. package/dist/services/shelf-board.d.ts +5 -0
  317. package/dist/services/shelf-board.d.ts.map +1 -0
  318. package/dist/services/shelf-board.js +15 -0
  319. package/dist/services/storey.d.ts +2 -2
  320. package/dist/services/storey.js +2 -2
  321. package/dist/services/surface-hosting-procedural-parity.fixtures.d.ts +13 -0
  322. package/dist/services/surface-hosting-procedural-parity.fixtures.d.ts.map +1 -0
  323. package/dist/services/surface-hosting-procedural-parity.fixtures.js +4691 -0
  324. package/dist/services/surface-hosting-shelf-parity.fixtures.d.ts +1060 -0
  325. package/dist/services/surface-hosting-shelf-parity.fixtures.d.ts.map +1 -0
  326. package/dist/services/surface-hosting-shelf-parity.fixtures.js +3127 -0
  327. package/dist/services/surface-hosting.d.ts +88 -0
  328. package/dist/services/surface-hosting.d.ts.map +1 -0
  329. package/dist/services/surface-hosting.js +268 -0
  330. package/dist/services/surface-region.d.ts +8 -0
  331. package/dist/services/surface-region.d.ts.map +1 -0
  332. package/dist/services/surface-region.js +44 -0
  333. package/dist/services/system-graph.d.ts +12 -1
  334. package/dist/services/system-graph.d.ts.map +1 -1
  335. package/dist/services/system-graph.js +36 -6
  336. package/dist/services/validate-dwv.d.ts +1 -1
  337. package/dist/services/validate-dwv.js +1 -1
  338. package/dist/store/actions/node-actions.d.ts +9 -2
  339. package/dist/store/actions/node-actions.d.ts.map +1 -1
  340. package/dist/store/actions/node-actions.js +475 -24
  341. package/dist/store/history-control.d.ts +3 -3
  342. package/dist/store/history-invalidation.d.ts +3 -0
  343. package/dist/store/history-invalidation.d.ts.map +1 -0
  344. package/dist/store/history-invalidation.js +72 -0
  345. package/dist/store/scene-hydration.d.ts +5 -0
  346. package/dist/store/scene-hydration.d.ts.map +1 -0
  347. package/dist/store/scene-hydration.js +57 -0
  348. package/dist/store/use-interactive.d.ts +2 -2
  349. package/dist/store/use-live-terrain.d.ts +1 -1
  350. package/dist/store/use-scene.d.ts +7 -4
  351. package/dist/store/use-scene.d.ts.map +1 -1
  352. package/dist/store/use-scene.js +361 -87
  353. package/dist/systems/elevator/elevator-dispatch.d.ts +2 -2
  354. package/dist/systems/elevator/elevator-dispatch.js +1 -1
  355. package/dist/systems/elevator/elevator-geometry.d.ts +1 -1
  356. package/dist/systems/elevator/elevator-opening-sync.d.ts +1 -1
  357. package/dist/systems/elevator/elevator-opening-sync.js +2 -2
  358. package/dist/systems/elevator/elevator-opening-system.js +3 -3
  359. package/dist/systems/elevator/elevator-runtime.d.ts +3 -3
  360. package/dist/systems/elevator/elevator-runtime.js +3 -3
  361. package/dist/systems/elevator/elevator-service.d.ts +1 -1
  362. package/dist/systems/elevator/elevator-service.js +1 -1
  363. package/dist/systems/fence/fence-centerline.d.ts +2 -2
  364. package/dist/systems/fence/fence-centerline.js +2 -2
  365. package/dist/systems/fence/fence-spline.d.ts +2 -2
  366. package/dist/systems/roof/roof-elevation-system.d.ts +3 -0
  367. package/dist/systems/roof/roof-elevation-system.d.ts.map +1 -0
  368. package/dist/systems/roof/roof-elevation-system.js +94 -0
  369. package/dist/systems/roof/roof-elevation.d.ts +4 -0
  370. package/dist/systems/roof/roof-elevation.d.ts.map +1 -0
  371. package/dist/systems/roof/roof-elevation.js +95 -0
  372. package/dist/systems/roof/roof-footprint.d.ts +17 -0
  373. package/dist/systems/roof/roof-footprint.d.ts.map +1 -0
  374. package/dist/systems/roof/roof-footprint.js +83 -0
  375. package/dist/systems/slab/slab-placement.d.ts +1 -1
  376. package/dist/systems/slab/slab-support.d.ts +1 -1
  377. package/dist/systems/slab/slab-support.js +4 -4
  378. package/dist/systems/stair/stair-flight.d.ts +17 -0
  379. package/dist/systems/stair/stair-flight.d.ts.map +1 -0
  380. package/dist/systems/stair/stair-flight.js +27 -0
  381. package/dist/systems/stair/stair-footprint.d.ts +1 -1
  382. package/dist/systems/stair/stair-opening-preview.d.ts +1621 -1267
  383. package/dist/systems/stair/stair-opening-preview.d.ts.map +1 -1
  384. package/dist/systems/stair/stair-opening-preview.js +2 -2
  385. package/dist/systems/stair/stair-opening-sync.d.ts +1 -1
  386. package/dist/systems/stair/stair-opening-sync.js +6 -6
  387. package/dist/systems/stair/stair-opening-system.d.ts +1 -0
  388. package/dist/systems/stair/stair-opening-system.d.ts.map +1 -1
  389. package/dist/systems/stair/stair-opening-system.js +100 -103
  390. package/dist/systems/stair/stair-rise.d.ts +1 -1
  391. package/dist/systems/stair/stair-rise.d.ts.map +1 -1
  392. package/dist/systems/stair/stair-rise.js +23 -24
  393. package/dist/systems/wall/wall-curve.d.ts +3 -2
  394. package/dist/systems/wall/wall-curve.d.ts.map +1 -1
  395. package/dist/systems/wall/wall-curve.js +73 -0
  396. package/dist/systems/wall/wall-footprint.d.ts +3 -2
  397. package/dist/systems/wall/wall-footprint.d.ts.map +1 -1
  398. package/dist/systems/wall/wall-footprint.js +3 -2
  399. package/dist/systems/wall/wall-mitering.d.ts +1 -1
  400. package/dist/systems/wall/wall-mitering.js +1 -1
  401. package/dist/systems/wall/wall-move.d.ts +1 -1
  402. package/dist/systems/wall/wall-top.d.ts +1 -1
  403. package/dist/systems/wall/wall-topology.d.ts +2 -2
  404. package/dist/systems/wall/wall-topology.js +4 -4
  405. package/dist/utils/clone-scene-graph.d.ts +3 -3
  406. package/dist/utils/clone-scene-graph.d.ts.map +1 -1
  407. package/dist/utils/clone-scene-graph.js +35 -3
  408. package/dist/utils/scene-migrations.d.ts +3 -3
  409. package/dist/utils/scene-migrations.js +3 -3
  410. package/dist/utils/vertical-scene-migration.js +5 -5
  411. package/dist/validation/validate-build-json.d.ts +7 -1
  412. package/dist/validation/validate-build-json.d.ts.map +1 -1
  413. package/dist/validation/validate-build-json.js +92 -4
  414. package/package.json +23 -5
  415. package/dist/systems/elevator/elevator-runtime-system.d.ts +0 -2
  416. package/dist/systems/elevator/elevator-runtime-system.d.ts.map +0 -1
  417. package/dist/systems/elevator/elevator-runtime-system.js +0 -8
@@ -1,5 +1,5 @@
1
- import { isCurvedWall, sampleWallCenterline } from '../systems/wall/wall-curve';
2
- import { getWallThickness } from '../systems/wall/wall-footprint';
1
+ import { isCurvedWall, sampleWallCenterline } from '../systems/wall/wall-curve.js';
2
+ import { getWallThickness } from '../systems/wall/wall-footprint.js';
3
3
  /**
4
4
  * Render-time slab polygon rules.
5
5
  *
@@ -114,16 +114,24 @@ function polygonWindingSign(polygon) {
114
114
  export function slabPolygonContextFromGeometry(ctx) {
115
115
  if (!ctx)
116
116
  return { walls: [], siblingSlabs: [] };
117
- const siblingSlabs = ctx.siblings.filter((node) => node.type === 'slab');
117
+ return {
118
+ ...slabPolygonContextForLevel(ctx.parent, ctx.resolve),
119
+ siblingSlabs: ctx.siblings.filter((node) => node.type === 'slab'),
120
+ };
121
+ }
122
+ export function slabPolygonContextForLevel(parent, resolve, fallbackSlabs = []) {
118
123
  const walls = [];
119
- const parentChildIds = ctx.parent?.children;
120
- if (Array.isArray(parentChildIds)) {
121
- for (const childId of parentChildIds) {
122
- const child = ctx.resolve(childId);
123
- if (child?.type === 'wall') {
124
- walls.push(child);
125
- }
126
- }
124
+ const siblingSlabs = [];
125
+ const childIds = parent?.children;
126
+ if (!Array.isArray(childIds)) {
127
+ return { walls, siblingSlabs: parent ? fallbackSlabs : [] };
128
+ }
129
+ for (const id of childIds) {
130
+ const child = resolve(id);
131
+ if (child?.type === 'wall')
132
+ walls.push(child);
133
+ else if (child?.type === 'slab')
134
+ siblingSlabs.push(child);
127
135
  }
128
136
  return { walls, siblingSlabs };
129
137
  }
@@ -132,7 +140,7 @@ export function getRenderableSlabPolygon(slabNode, context) {
132
140
  if (polygon.length < 3 || isFloatingSlab(slabNode)) {
133
141
  return polygon.map(([x, z]) => [x, z]);
134
142
  }
135
- const subSpans = computeEdgeSubSpans(polygon, slabNode.elevation ?? DEFAULT_SLAB_ELEVATION, context);
143
+ const subSpans = computeEdgeSubSpans(polygon, slabNode.elevation ?? DEFAULT_SLAB_ELEVATION, 'wallCandidates' in context ? context : prepareSlabPolygonContext(context), slabNode.id);
136
144
  if (subSpans.every((spans) => spans.length === 1 && spans[0].offset === 0)) {
137
145
  return polygon.map(([x, z]) => [x, z]);
138
146
  }
@@ -254,17 +262,71 @@ export function snapSlabEdgeToWallBand(a, b, walls, options) {
254
262
  ],
255
263
  };
256
264
  }
257
- /**
258
- * Split every polygon edge at candidate span boundaries and classify
259
- * each sub-span independently. Returns one non-empty span list per
260
- * edge, covering [0, edgeLength] without gaps.
261
- */
262
- function computeEdgeSubSpans(polygon, selfElevation, context) {
263
- const n = polygon.length;
264
- // Winding sign: the outward normal of an edge with direction `dir` is
265
- // `s * (dirZ, -dirX)`, so a target lateral `L` measured along
266
- // `(dirZ, -dirX)` is `s * L` along the outward normal.
267
- const s = polygonWindingSign(polygon);
265
+ function polygonBounds(polygon) {
266
+ const bounds = [Infinity, Infinity, -Infinity, -Infinity];
267
+ for (const [x, z] of polygon) {
268
+ bounds[0] = Math.min(bounds[0], x);
269
+ bounds[1] = Math.min(bounds[1], z);
270
+ bounds[2] = Math.max(bounds[2], x);
271
+ bounds[3] = Math.max(bounds[3], z);
272
+ }
273
+ return bounds;
274
+ }
275
+ function boundsOverlap(a, b, padding) {
276
+ return (a[0] <= b[2] + padding &&
277
+ a[2] >= b[0] - padding &&
278
+ a[1] <= b[3] + padding &&
279
+ a[3] >= b[1] - padding);
280
+ }
281
+ export function scopeSlabPolygonContext(slab, context) {
282
+ const bounds = polygonBounds(slab.polygon);
283
+ const wallCandidates = context.wallCandidates.filter((candidate) => boundsOverlap(bounds, candidate.bounds, candidate.halfThickness + WALL_ADOPTION_TOLERANCE));
284
+ // Keep the level-wide tolerance: even an unadopted wall can widen sibling
285
+ // breakpoint collection, which may affect short-span fusion.
286
+ const neighborSegments = context.neighborSegments.filter((neighbor) => neighbor.slab.id !== slab.id &&
287
+ boundsOverlap(bounds, neighbor.bounds, context.siblingBreakTolerance));
288
+ return {
289
+ ...context,
290
+ walls: wallCandidates.map((candidate) => candidate.wall),
291
+ siblingSlabs: [...new Set(neighborSegments.map((neighbor) => neighbor.slab))],
292
+ wallCandidates,
293
+ neighborSegments,
294
+ siblingBreakTolerance: context.siblingBreakTolerance,
295
+ };
296
+ }
297
+ export function slabPolygonContextChanges(before, after) {
298
+ if (before.siblingBreakTolerance !== after.siblingBreakTolerance)
299
+ return () => true;
300
+ const changedWalls = new Set();
301
+ const changedSlabs = new Set();
302
+ for (let i = 0; i < Math.max(before.walls.length, after.walls.length); i++) {
303
+ if (before.walls[i] === after.walls[i])
304
+ continue;
305
+ if (before.walls[i])
306
+ changedWalls.add(before.walls[i]);
307
+ if (after.walls[i])
308
+ changedWalls.add(after.walls[i]);
309
+ }
310
+ for (let i = 0; i < Math.max(before.siblingSlabs.length, after.siblingSlabs.length); i++) {
311
+ if (before.siblingSlabs[i] === after.siblingSlabs[i])
312
+ continue;
313
+ if (before.siblingSlabs[i])
314
+ changedSlabs.add(before.siblingSlabs[i]);
315
+ if (after.siblingSlabs[i])
316
+ changedSlabs.add(after.siblingSlabs[i]);
317
+ }
318
+ const walls = [...before.wallCandidates, ...after.wallCandidates].filter((candidate) => changedWalls.has(candidate.wall));
319
+ const neighbors = [...before.neighborSegments, ...after.neighborSegments].filter((neighbor) => changedSlabs.has(neighbor.slab));
320
+ return (slab) => {
321
+ const bounds = polygonBounds(slab.polygon);
322
+ return (walls.some((candidate) => boundsOverlap(bounds, candidate.bounds, candidate.halfThickness + WALL_ADOPTION_TOLERANCE)) ||
323
+ neighbors.some((neighbor) => neighbor.slab.id !== slab.id &&
324
+ boundsOverlap(bounds, neighbor.bounds, after.siblingBreakTolerance)));
325
+ };
326
+ }
327
+ export function prepareSlabPolygonContext(context, previous) {
328
+ const wallCache = previous?.wallCache ?? new WeakMap();
329
+ const neighborCache = previous?.neighborCache ?? new WeakMap();
268
330
  const neighborSegments = [];
269
331
  for (const sibling of context.siblingSlabs) {
270
332
  // A floating deck keeps its drawn polygon, so it can't be a seam
@@ -273,6 +335,12 @@ function computeEdgeSubSpans(polygon, selfElevation, context) {
273
335
  // only describe room floors meeting under a wall.
274
336
  if (isFloatingSlab(sibling))
275
337
  continue;
338
+ const cached = neighborCache.get(sibling);
339
+ if (cached) {
340
+ neighborSegments.push(...cached);
341
+ continue;
342
+ }
343
+ const segments = [];
276
344
  const siblingPolygon = sibling.polygon;
277
345
  if (siblingPolygon.length < 2)
278
346
  continue;
@@ -286,19 +354,35 @@ function computeEdgeSubSpans(polygon, selfElevation, context) {
286
354
  const length = Math.hypot(dx, dz);
287
355
  if (length < 1e-9)
288
356
  continue;
289
- neighborSegments.push({
357
+ segments.push({
358
+ slab: sibling,
359
+ bounds: polygonBounds([from, to]),
290
360
  segment: [from[0], from[1], to[0], to[1]],
291
361
  elevation,
292
362
  inwardX: (-siblingWinding * dz) / length,
293
363
  inwardZ: (siblingWinding * dx) / length,
294
364
  });
295
365
  }
366
+ neighborCache.set(sibling, segments);
367
+ neighborSegments.push(...segments);
296
368
  }
297
- const wallCandidates = context.walls.map((wall) => ({
298
- wall,
299
- segments: wallCenterlineSegments(wall),
300
- halfThickness: getWallThickness(wall) / 2,
301
- }));
369
+ const wallCandidates = context.walls.map((wall) => {
370
+ const cached = wallCache.get(wall);
371
+ if (cached)
372
+ return cached;
373
+ const segments = wallCenterlineSegments(wall);
374
+ const candidate = {
375
+ wall,
376
+ segments,
377
+ halfThickness: getWallThickness(wall) / 2,
378
+ bounds: polygonBounds(segments.flatMap(([ax, az, bx, bz]) => [
379
+ [ax, az],
380
+ [bx, bz],
381
+ ])),
382
+ };
383
+ wallCache.set(wall, candidate);
384
+ return candidate;
385
+ });
302
386
  // Sibling breakpoints also matter for legacy face-aligned polygons up
303
387
  // to a full wall band away from the edge (the band-sibling interior
304
388
  // rule in classifySpan), so clip them with the widest band reach any
@@ -308,6 +392,28 @@ function computeEdgeSubSpans(polygon, selfElevation, context) {
308
392
  for (const candidate of wallCandidates) {
309
393
  siblingBreakTolerance = Math.max(siblingBreakTolerance, 2 * (candidate.halfThickness + WALL_ADOPTION_TOLERANCE));
310
394
  }
395
+ return {
396
+ ...context,
397
+ wallCache,
398
+ neighborCache,
399
+ wallCandidates,
400
+ neighborSegments,
401
+ siblingBreakTolerance,
402
+ };
403
+ }
404
+ /**
405
+ * Split every polygon edge at candidate span boundaries and classify
406
+ * each sub-span independently. Returns one non-empty span list per
407
+ * edge, covering [0, edgeLength] without gaps.
408
+ */
409
+ function computeEdgeSubSpans(polygon, selfElevation, context, slabId) {
410
+ const n = polygon.length;
411
+ // Winding sign: the outward normal of an edge with direction `dir` is
412
+ // `s * (dirZ, -dirX)`, so a target lateral `L` measured along
413
+ // `(dirZ, -dirX)` is `s * L` along the outward normal.
414
+ const s = polygonWindingSign(polygon);
415
+ const { wallCandidates, siblingBreakTolerance } = context;
416
+ const neighborSegments = context.neighborSegments.filter((segment) => segment.slab.id !== slabId);
311
417
  const subSpans = [];
312
418
  for (let index = 0; index < n; index += 1) {
313
419
  const a = polygon[index];
@@ -1,4 +1,4 @@
1
- import { type AnyNodeId, type CeilingNode as CeilingNodeType, type SlabNode as SlabNodeType, type WallNode, type ZoneNode as ZoneNodeType } from '../schema';
1
+ import { type AnyNodeId, type CeilingNode as CeilingNodeType, type SlabNode as SlabNodeType, type WallNode, type ZoneNode as ZoneNodeType } from '../schema/index.js';
2
2
  type Point2D = {
3
3
  x: number;
4
4
  y: number;
@@ -80,6 +80,12 @@ export type AutoCeilingPlanningContext = {
80
80
  previousHeightForRoom?: (polygon: Array<[number, number]>) => number | undefined;
81
81
  childPosition?: (childId: AnyNodeId) => [number, number] | undefined;
82
82
  };
83
+ declare function bboxOf(points: Point2D[]): {
84
+ minX: number;
85
+ minY: number;
86
+ maxX: number;
87
+ maxY: number;
88
+ };
83
89
  /**
84
90
  * True when `wall` lies on the boundary of a room enclosed by `walls`, using the
85
91
  * same planar room graph the auto slab/ceiling sync uses. The wall builder's
@@ -90,6 +96,11 @@ export type AutoCeilingPlanningContext = {
90
96
  */
91
97
  export declare function wallClosesRoom(walls: WallNode[], wall: WallNode): boolean;
92
98
  export declare function resolveWallSurfaceSides(wall: Pick<WallNode, 'start' | 'end' | 'thickness' | 'frontSide' | 'backSide'>, roomPolygons: Point2D[][]): Pick<WallSideUpdate, 'frontSide' | 'backSide'>;
99
+ type BoundedPolygon = {
100
+ polygon: Point2D[];
101
+ bbox: ReturnType<typeof bboxOf>;
102
+ };
103
+ export declare function surfaceTouchesRooms(surface: BoundedPolygon, rooms: BoundedPolygon[]): boolean;
93
104
  export declare function planAutoZonesForLevel(spaces: readonly Space[], existingZones: readonly ZoneNodeType[]): AutoZoneSyncPlan;
94
105
  export declare function resolveAutoZonePolygon(zone: Pick<ZoneNodeType, 'autoFromWalls' | 'boundaryWallIds' | 'polygon'>, resolve: (id: AnyNodeId) => unknown): ZoneNodeType['polygon'];
95
106
  export declare function planAutoSlabsForLevel(roomPolygons: Point2D[][], existingSlabs: SlabNodeType[], context?: AutoSlabPlanningContext, namingSlabs?: Array<{
@@ -1 +1 @@
1
- {"version":3,"file":"space-detection.d.ts","sourceRoot":"","sources":["../../src/lib/space-detection.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,SAAS,EAEd,KAAK,WAAW,IAAI,eAAe,EAGnC,KAAK,QAAQ,IAAI,YAAY,EAC7B,KAAK,QAAQ,EAEb,KAAK,QAAQ,IAAI,YAAY,EAC9B,MAAM,WAAW,CAAA;AAgClB,KAAK,OAAO,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAEvC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAA;IACtB,IAAI,EAAE,OAAO,GAAG,MAAM,CAAA;IACtB,MAAM,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAChC,CAAA;AAED,MAAM,MAAM,KAAK,GAAG;IAClB,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAChC,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAA;IAC9B,aAAa,EAAE,iBAAiB,EAAE,CAAA;IAClC,UAAU,EAAE,OAAO,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,2BAA2B,GAAG;IACxC,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,SAAS,GAAG,UAAU,CAAA;IAChC,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,uBAAuB,EAAE,MAAM,CAAA;IAC/B,wBAAwB,EAAE,MAAM,CAAA;CACjC,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,2BAA2B,KAAK,IAAI,CAAA;CACnE,CAAA;AAED,KAAK,aAAa,GAAG;IACnB,OAAO,EAAE,OAAO,EAAE,CAAA;IAClB,aAAa,EAAE,iBAAiB,EAAE,CAAA;CACnC,CAAA;AAED,KAAK,cAAc,GAAG;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAAA;IAC9C,QAAQ,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAAA;CAC9C,CAAA;AAUD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,YAAY,EAAE,CAAA;IACtB,MAAM,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC,YAAY,CAAC,CAAA;KAAE,CAAC,CAAA;IACtE,MAAM,EAAE,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAA;CAClC,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KAAK,MAAM,GAAG,SAAS,CAAA;IAC3E,wBAAwB,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KAAK,MAAM,GAAG,SAAS,CAAA;CACpF,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,eAAe,EAAE,CAAA;IACzB,MAAM,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,eAAe,CAAC,IAAI,CAAC,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC,eAAe,CAAC,CAAA;KAAE,CAAC,CAAA;IAC5E,MAAM,EAAE,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAA;IACpC,QAAQ,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,SAAS,CAAC;QAAC,QAAQ,EAAE,eAAe,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC,CAAA;CACpE,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC,YAAY,CAAC,CAAA;KAAE,CAAC,CAAA;CACvE,CAAA;AAyBD,MAAM,MAAM,0BAA0B,GAAG;IACvC,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KAAK,MAAM,CAAA;IAChE,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KAAK,MAAM,GAAG,SAAS,CAAA;IACxE,qBAAqB,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KAAK,MAAM,GAAG,SAAS,CAAA;IAChF,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,SAAS,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAA;CACrE,CAAA;AAopBD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAIzE;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,OAAO,GAAG,KAAK,GAAG,WAAW,GAAG,WAAW,GAAG,UAAU,CAAC,EAC9E,YAAY,EAAE,OAAO,EAAE,EAAE,GACxB,IAAI,CAAC,cAAc,EAAE,WAAW,GAAG,UAAU,CAAC,CA4ChD;AA4xBD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,KAAK,EAAE,EACxB,aAAa,EAAE,SAAS,YAAY,EAAE,GACrC,gBAAgB,CAyBlB;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,eAAe,GAAG,iBAAiB,GAAG,SAAS,CAAC,EACzE,OAAO,EAAE,CAAC,EAAE,EAAE,SAAS,KAAK,OAAO,GAClC,YAAY,CAAC,SAAS,CAAC,CAgBzB;AAED,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,OAAO,EAAE,EAAE,EACzB,aAAa,EAAE,YAAY,EAAE,EAC7B,OAAO,GAAE,uBAA4B,EACrC,WAAW,GAAE,KAAK,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAiB,GACpD,gBAAgB,CAiHlB;AA2BD,wBAAgB,wBAAwB,CACtC,YAAY,EAAE,OAAO,EAAE,EAAE,EACzB,gBAAgB,EAAE,eAAe,EAAE,EACnC,OAAO,GAAE,0BAA+B,EACxC,cAAc,GAAE,KAAK,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAoB,GAC1D,mBAAmB,CAkKrB;AAkDD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE;;;;;EAEtE;AAiSD,mGAAmG;AACnG,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAED,oFAAoF;AACpF,wBAAgB,oBAAoB,IAAI,IAAI,CAG3C;AAED,2EAA2E;AAC3E,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD;AAED,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,GAAG,EACf,WAAW,EAAE,GAAG,EAChB,OAAO,GAAE,yBAA8B,GACtC,MAAM,IAAI,CA8JZ;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,OAAO,CAiBjF"}
1
+ {"version":3,"file":"space-detection.d.ts","sourceRoot":"","sources":["../../src/lib/space-detection.ts"],"names":[],"mappings":"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"}
@@ -1,14 +1,14 @@
1
- import { GROUND_SUPPORT_ID } from '../hooks/spatial-grid/support-host-id';
2
- import { CeilingNode, SlabNode, ZoneNode, } from '../schema';
3
- import { DEFAULT_LEVEL_HEIGHT } from '../services/level-height';
4
- import { CEILING_CLAMP_MARGIN, findLevelAboveId, getCeilingClampBound, getLevelBelow, getLevelElevations, getStoredLevelHeight, } from '../services/storey';
5
- import { activeSceneCommitNodeIds, getSceneHistoryPauseDepth, pauseSceneHistory, resumeSceneHistory, subscribeSceneCommits, } from '../store/history-control';
6
- import { computeWallSlabSupport } from '../systems/slab/slab-support';
7
- import { getClampedWallCurveOffset, getWallCurveFrameAt, isCurvedWall, } from '../systems/wall/wall-curve';
8
- import { resolveWallTop } from '../systems/wall/wall-top';
9
- import { simplifyClosedPolygon } from './polygon-geometry';
10
- import { distanceToSegment, RoomTopologyIndex, } from './room-topology-index';
11
- import { levelBaseElevationAt } from './terrain-support';
1
+ import { GROUND_SUPPORT_ID } from '../hooks/spatial-grid/support-host-id.js';
2
+ import { CeilingNode, SlabNode, ZoneNode, } from '../schema/index.js';
3
+ import { DEFAULT_LEVEL_HEIGHT } from '../services/level-height.js';
4
+ import { CEILING_CLAMP_MARGIN, findLevelAboveId, getCeilingClampBound, getLevelBelow, getLevelElevations, getStoredLevelHeight, } from '../services/storey.js';
5
+ import { activeSceneCommitNodeIds, getSceneHistoryPauseDepth, pauseSceneHistory, resumeSceneHistory, subscribeSceneCommits, } from '../store/history-control.js';
6
+ import { computeWallSlabSupport } from '../systems/slab/slab-support.js';
7
+ import { getClampedWallCurveOffset, getWallCurveFrameAt, isCurvedWall, } from '../systems/wall/wall-curve.js';
8
+ import { resolveWallTop } from '../systems/wall/wall-top.js';
9
+ import { simplifyClosedPolygon } from './polygon-geometry.js';
10
+ import { distanceToSegment, RoomTopologyIndex, } from './room-topology-index.js';
11
+ import { levelBaseElevationAt } from './terrain-support.js';
12
12
  const DEFAULT_AUTO_SLAB_ELEVATION = 0.05;
13
13
  const CEILING_HEIGHT_EPSILON = 1e-6;
14
14
  const ROOM_CURVE_TOLERANCE = 0.04;
@@ -139,10 +139,10 @@ function bboxOverlapArea(a, b) {
139
139
  // sampling a grid of cell centers over the subject's bbox. Cheap and robust
140
140
  // enough for the merge-vs-demote decision; exact polygon clipping would be a
141
141
  // heavy dependency for a 60% threshold.
142
- function polygonCoverageRatio(subject, covers) {
142
+ function polygonCoverageRatio(subject, covers, subjectBounds) {
143
143
  if (subject.length < 3 || covers.length === 0)
144
144
  return 0;
145
- const bbox = bboxOf(subject);
145
+ const bbox = subjectBounds ?? bboxOf(subject);
146
146
  const width = bbox.maxX - bbox.minX;
147
147
  const height = bbox.maxY - bbox.minY;
148
148
  let inside = 0;
@@ -646,6 +646,17 @@ function sameTuplePolygon(current, next) {
646
646
  return (current.length === next.length &&
647
647
  current.every((point, index) => point[0] === next[index]?.[0] && point[1] === next[index]?.[1]));
648
648
  }
649
+ function sameTuplePolygonRotation(current, next) {
650
+ if (sameTuplePolygon(current, next))
651
+ return true;
652
+ if (current.length !== next.length)
653
+ return false;
654
+ // Preserve the stored ring when extraction only changes its starting vertex.
655
+ return next.some((_, offset) => current.every((point, index) => {
656
+ const candidate = next[(index + offset) % next.length];
657
+ return point[0] === candidate[0] && point[1] === candidate[1];
658
+ }));
659
+ }
649
660
  function sameTuplePolygons(current, next) {
650
661
  return (current.length === next.length &&
651
662
  current.every((polygon, index) => {
@@ -1000,10 +1011,18 @@ function buildSpace(levelId, room) {
1000
1011
  isExterior: false,
1001
1012
  };
1002
1013
  }
1003
- function surfaceTouchesRooms(surface, rooms) {
1004
- const polygon = surface.polygon.map(pointFromTuple);
1005
- return rooms.some((room) => polygonCoverageRatio(polygon, [room.polygon]) > 0 ||
1006
- polygonCoverageRatio(room.polygon, [polygon]) > 0);
1014
+ export function surfaceTouchesRooms(surface, rooms) {
1015
+ const { polygon, bbox } = surface;
1016
+ return rooms.some((room) => {
1017
+ if (bbox.maxX < room.bbox.minX ||
1018
+ room.bbox.maxX < bbox.minX ||
1019
+ bbox.maxY < room.bbox.minY ||
1020
+ room.bbox.maxY < bbox.minY) {
1021
+ return false;
1022
+ }
1023
+ return (polygonCoverageRatio(polygon, [room.polygon], bbox) > 0 ||
1024
+ polygonCoverageRatio(room.polygon, [polygon], room.bbox) > 0);
1025
+ });
1007
1026
  }
1008
1027
  function roomsAreRelated(beforeRoom, currentRoom) {
1009
1028
  const beforeIds = new Set(beforeRoom.boundaryFaces.map((boundary) => boundary.wallId));
@@ -1365,7 +1384,7 @@ export function planAutoSlabsForLevel(roomPolygons, existingSlabs, context = {},
1365
1384
  holeMetadata: [],
1366
1385
  });
1367
1386
  const data = {};
1368
- if (!sameTuplePolygon(slab.polygon, update.polygon))
1387
+ if (!sameTuplePolygonRotation(slab.polygon, update.polygon))
1369
1388
  data.polygon = update.polygon;
1370
1389
  if (!sameTuplePolygons(slab.holes, openings.holes))
1371
1390
  data.holes = openings.holes;
@@ -1496,7 +1515,7 @@ export function planAutoCeilingsForLevel(roomPolygons, existingCeilings, context
1496
1515
  holeMetadata: [],
1497
1516
  });
1498
1517
  const data = {};
1499
- if (!sameTuplePolygon(ceiling.polygon, update.polygon))
1518
+ if (!sameTuplePolygonRotation(ceiling.polygon, update.polygon))
1500
1519
  data.polygon = update.polygon;
1501
1520
  if (!sameTuplePolygons(ceiling.holes, openings.holes))
1502
1521
  data.holes = openings.holes;
@@ -1707,9 +1726,14 @@ function runIndexedSpaceDetection(levelId, topologyDelta, sceneStore, editorStor
1707
1726
  data: { frontSide: update.frontSide, backSide: update.backSide },
1708
1727
  })));
1709
1728
  }
1710
- const scopedRooms = [...topologyDelta.beforeRooms, ...topologyDelta.currentRooms];
1729
+ const scopedRooms = [...topologyDelta.beforeRooms, ...topologyDelta.currentRooms].map((room) => ({
1730
+ polygon: room.polygon,
1731
+ bbox: bboxOf(room.polygon),
1732
+ }));
1711
1733
  if (scopedRooms.length > 0) {
1712
- const unaffectedRooms = topologyDelta.allCurrentRooms.filter((room) => !topologyDelta.currentRooms.includes(room));
1734
+ const unaffectedRooms = topologyDelta.allCurrentRooms
1735
+ .filter((room) => !topologyDelta.currentRooms.includes(room))
1736
+ .map((room) => ({ polygon: room.polygon, bbox: bboxOf(room.polygon) }));
1713
1737
  const currentChildren = levelChildren(nodes, levelId);
1714
1738
  const allSlabs = currentChildren
1715
1739
  .filter((node) => node.type === 'slab')
@@ -1717,10 +1741,14 @@ function runIndexedSpaceDetection(levelId, topologyDelta, sceneStore, editorStor
1717
1741
  const allCeilings = currentChildren
1718
1742
  .filter((node) => node.type === 'ceiling')
1719
1743
  .map((ceiling) => CeilingNode.parse(ceiling));
1720
- const slabs = allSlabs.filter((slab) => surfaceTouchesRooms(slab, scopedRooms) &&
1721
- (!slab.autoFromWalls || !surfaceTouchesRooms(slab, unaffectedRooms)));
1722
- const ceilings = allCeilings.filter((ceiling) => surfaceTouchesRooms(ceiling, scopedRooms) &&
1723
- (!ceiling.autoFromWalls || !surfaceTouchesRooms(ceiling, unaffectedRooms)));
1744
+ const touchesScopedRooms = (surface) => {
1745
+ const polygon = surface.polygon.map(pointFromTuple);
1746
+ const bounded = { polygon, bbox: bboxOf(polygon) };
1747
+ return (surfaceTouchesRooms(bounded, scopedRooms) &&
1748
+ (!surface.autoFromWalls || !surfaceTouchesRooms(bounded, unaffectedRooms)));
1749
+ };
1750
+ const slabs = allSlabs.filter(touchesScopedRooms);
1751
+ const ceilings = allCeilings.filter(touchesScopedRooms);
1724
1752
  const slabRooms = roomsEligibleForAutoSurface(topologyDelta.beforeRooms, topologyDelta.currentRooms, slabs);
1725
1753
  const ceilingRooms = roomsEligibleForAutoSurface(topologyDelta.beforeRooms, topologyDelta.currentRooms, ceilings);
1726
1754
  const levelNode = nodes[levelId];
@@ -1830,6 +1858,11 @@ export function initSpaceDetectionSync(sceneStore, editorStore, options = {}) {
1830
1858
  return;
1831
1859
  adoptSceneBaseline(commit.current.nodes);
1832
1860
  });
1861
+ // Keep reconciliation in this synchronous store subscription. Zundo emits
1862
+ // the originating local SceneCommit only after subscribers return, so the
1863
+ // history-paused derived writes below join that commit's current snapshot
1864
+ // and undo step. Running from subscribeSceneCommits would cross the snapshot
1865
+ // boundary, and the paused writes would emit no replacement commit.
1833
1866
  const unsubscribe = sceneStore.subscribe((state) => {
1834
1867
  if (isProcessing)
1835
1868
  return;
@@ -30,7 +30,7 @@
30
30
  * one in-flight gesture and dies with it, which is cheaper and clearer than
31
31
  * rebuilding a coverage map per pointer-move.
32
32
  */
33
- import { type HeightPatch, type TerrainField } from './terrain-field';
33
+ import { type HeightPatch, type TerrainField } from './terrain-field.js';
34
34
  export type BrushShape = 'round' | 'square';
35
35
  /**
36
36
  * `raise`/`lower` are one verb with an inverted sign at the call site, matching
@@ -30,7 +30,7 @@
30
30
  * one in-flight gesture and dies with it, which is cheaper and clearer than
31
31
  * rebuilding a coverage map per pointer-move.
32
32
  */
33
- import { heightAt, heightAtSample, quantize, } from './terrain-field';
33
+ import { heightAt, heightAtSample, quantize, } from './terrain-field.js';
34
34
  export const DEFAULT_BRUSH_SETTINGS = {
35
35
  radius: 2,
36
36
  strength: 0.6,
@@ -24,8 +24,8 @@
24
24
  * the wire format must not depend on that being true of the machine that saved
25
25
  * the scene.
26
26
  */
27
- import { type TerrainData } from '../schema/terrain';
28
- import type { HeightPatch, TerrainField } from './terrain-field';
27
+ import { type TerrainData } from '../schema/terrain.js';
28
+ import type { HeightPatch, TerrainField } from './terrain-field.js';
29
29
  export type EncodedHeightPatch = Omit<HeightPatch, 'heights'> & {
30
30
  heights: string;
31
31
  };
@@ -24,7 +24,7 @@
24
24
  * the wire format must not depend on that being true of the machine that saved
25
25
  * the scene.
26
26
  */
27
- import { MAX_TERRAIN_SIDE } from '../schema/terrain';
27
+ import { MAX_TERRAIN_SIDE } from '../schema/terrain.js';
28
28
  const BASE64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
29
29
  function encodeBase64(bytes) {
30
30
  let out = '';
@@ -20,7 +20,7 @@
20
20
  * ladder, so the returned point is on the same rendered triangle plane
21
21
  * `heightAt` reports.
22
22
  */
23
- import { type TerrainField } from './terrain-field';
23
+ import { type TerrainField } from './terrain-field.js';
24
24
  export type TerrainHit = {
25
25
  /** Distance along the (unnormalized) direction vector. */
26
26
  readonly t: number;
@@ -20,7 +20,7 @@
20
20
  * ladder, so the returned point is on the same rendered triangle plane
21
21
  * `heightAt` reports.
22
22
  */
23
- import { heightAt } from './terrain-field';
23
+ import { heightAt } from './terrain-field.js';
24
24
  /** Bisection depth. 20 halvings of one cell is sub-micrometre at any sane spacing. */
25
25
  const REFINE_ITERATIONS = 20;
26
26
  /**
@@ -17,9 +17,9 @@
17
17
  * the commit, the next read is a cache hit, so a stroke never decodes base64 even
18
18
  * once, let alone per dab.
19
19
  */
20
- import type { SiteNode } from '../schema/nodes/site';
21
- import type { TerrainData } from '../schema/terrain';
22
- import { createTerrainField, type TerrainField } from './terrain-field';
20
+ import type { SiteNode } from '../schema/nodes/site.js';
21
+ import type { TerrainData } from '../schema/terrain.js';
22
+ import { createTerrainField, type TerrainField } from './terrain-field.js';
23
23
  /**
24
24
  * The terrain field for a site, or `null` when the site has no sculpted terrain.
25
25
  *
@@ -17,9 +17,9 @@
17
17
  * the commit, the next read is a cache hit, so a stroke never decodes base64 even
18
18
  * once, let alone per dab.
19
19
  */
20
- import useLiveTerrain from '../store/use-live-terrain';
21
- import { decodeTerrainField, encodeTerrainField } from './terrain-codec';
22
- import { createTerrainField } from './terrain-field';
20
+ import useLiveTerrain from '../store/use-live-terrain.js';
21
+ import { decodeTerrainField, encodeTerrainField } from './terrain-codec.js';
22
+ import { createTerrainField } from './terrain-field.js';
23
23
  const fieldCache = new WeakMap();
24
24
  /**
25
25
  * Sites whose `terrain` failed to decode. Prevents re-attempting a doomed decode
@@ -11,7 +11,7 @@
11
11
  * The whole file is pure — nodes in, metres out — which is what lets the stacking
12
12
  * matrix be tested per kind without a canvas.
13
13
  */
14
- import type { AnyNode } from '../schema';
14
+ import type { AnyNode } from '../schema/index.js';
15
15
  /**
16
16
  * World Y of the site datum — the plane terrain heights are measured from.
17
17
  *
@@ -11,9 +11,9 @@
11
11
  * The whole file is pure — nodes in, metres out — which is what lets the stacking
12
12
  * matrix be tested per kind without a canvas.
13
13
  */
14
- import { getLevelElevations } from '../services/storey';
15
- import { heightAt } from './terrain-field';
16
- import { terrainFieldOf } from './terrain-source';
14
+ import { getLevelElevations } from '../services/storey.js';
15
+ import { heightAt } from './terrain-field.js';
16
+ import { terrainFieldOf } from './terrain-source.js';
17
17
  /**
18
18
  * World Y of the site datum — the plane terrain heights are measured from.
19
19
  *
@@ -0,0 +1,19 @@
1
+ import type { AnyNode, AnyNodeId, BuildingNode, LevelNode, UnitNode, WallNode, ZoneNode } from '../schema/index.js';
2
+ export type UnitDerivation = {
3
+ unitId: UnitNode['id'];
4
+ memberZoneIds: ZoneNode['id'][];
5
+ levelIds: LevelNode['id'][];
6
+ containedNodeIds: AnyNodeId[];
7
+ boundaryWallIds: WallNode['id'][];
8
+ supportIds: AnyNodeId[];
9
+ visibleNodeIds: AnyNodeId[];
10
+ };
11
+ type Nodes = Readonly<Record<AnyNodeId, AnyNode>>;
12
+ export declare function deriveUnit(unit: UnitNode, nodes: Nodes): UnitDerivation;
13
+ export declare function unitsForZone(zoneId: ZoneNode['id'], nodes: Nodes): UnitNode[];
14
+ export declare function unassignedZoneIds(buildingId: BuildingNode['id'], nodes: Nodes): ZoneNode['id'][];
15
+ export declare function unitWarnings(unit: UnitNode, nodes: Nodes): Array<{
16
+ code: 'empty' | 'non-adjacent-levels';
17
+ }>;
18
+ export {};
19
+ //# sourceMappingURL=unit-containment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unit-containment.d.ts","sourceRoot":"","sources":["../../src/lib/unit-containment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,SAAS,EACT,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,QAAQ,EACT,MAAM,WAAW,CAAA;AAMlB,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAA;IACtB,aAAa,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAA;IAC/B,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,CAAA;IAC3B,gBAAgB,EAAE,SAAS,EAAE,CAAA;IAC7B,eAAe,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAA;IACjC,UAAU,EAAE,SAAS,EAAE,CAAA;IACvB,cAAc,EAAE,SAAS,EAAE,CAAA;CAC5B,CAAA;AAED,KAAK,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAA;AA8CjD,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,GAAG,cAAc,CAuFvE;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,QAAQ,EAAE,CAI7E;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAqBhG;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,KAAK,GACX,KAAK,CAAC;IACP,IAAI,EAAE,OAAO,GAAG,qBAAqB,CAAA;CACtC,CAAC,CAiBD"}