@pascal-app/core 0.8.0 → 0.9.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.
Files changed (471) hide show
  1. package/dist/events/bus.d.ts +67 -13
  2. package/dist/events/bus.d.ts.map +1 -1
  3. package/dist/hooks/scene-registry/item-clip-registry.d.ts +18 -0
  4. package/dist/hooks/scene-registry/item-clip-registry.d.ts.map +1 -0
  5. package/dist/hooks/scene-registry/item-clip-registry.js +10 -0
  6. package/dist/hooks/scene-registry/scene-registry.d.ts +14 -23
  7. package/dist/hooks/scene-registry/scene-registry.d.ts.map +1 -1
  8. package/dist/hooks/scene-registry/scene-registry.js +59 -26
  9. package/dist/hooks/scene-registry/scene-registry.test.d.ts +2 -0
  10. package/dist/hooks/scene-registry/scene-registry.test.d.ts.map +1 -0
  11. package/dist/hooks/scene-registry/scene-registry.test.js +26 -0
  12. package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts +14 -0
  13. package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts.map +1 -0
  14. package/dist/hooks/spatial-grid/floor-placed-elevation.js +51 -0
  15. package/dist/hooks/spatial-grid/floor-placed-elevation.test.d.ts +2 -0
  16. package/dist/hooks/spatial-grid/floor-placed-elevation.test.d.ts.map +1 -0
  17. package/dist/hooks/spatial-grid/floor-placed-elevation.test.js +366 -0
  18. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts +79 -11
  19. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts.map +1 -1
  20. package/dist/hooks/spatial-grid/spatial-grid-manager.js +508 -141
  21. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts +28 -1
  22. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts.map +1 -1
  23. package/dist/hooks/spatial-grid/spatial-grid-sync.js +109 -18
  24. package/dist/hooks/spatial-grid/wall-slab-overlap.test.d.ts +2 -0
  25. package/dist/hooks/spatial-grid/wall-slab-overlap.test.d.ts.map +1 -0
  26. package/dist/hooks/spatial-grid/wall-slab-overlap.test.js +363 -0
  27. package/dist/index.d.ts +36 -8
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +33 -6
  30. package/dist/lib/level-name.d.ts +4 -0
  31. package/dist/lib/level-name.d.ts.map +1 -0
  32. package/dist/lib/level-name.js +10 -0
  33. package/dist/lib/measurement-geometry.d.ts +19 -0
  34. package/dist/lib/measurement-geometry.d.ts.map +1 -0
  35. package/dist/lib/measurement-geometry.js +232 -0
  36. package/dist/lib/measurement-geometry.test.d.ts +2 -0
  37. package/dist/lib/measurement-geometry.test.d.ts.map +1 -0
  38. package/dist/lib/measurement-geometry.test.js +102 -0
  39. package/dist/lib/polygon-geometry.d.ts +0 -1
  40. package/dist/lib/polygon-geometry.d.ts.map +1 -1
  41. package/dist/lib/polygon-geometry.js +0 -18
  42. package/dist/lib/polygon-relations.d.ts +10 -0
  43. package/dist/lib/polygon-relations.d.ts.map +1 -0
  44. package/dist/lib/polygon-relations.js +73 -0
  45. package/dist/lib/selection-proxy.d.ts +4 -0
  46. package/dist/lib/selection-proxy.d.ts.map +1 -0
  47. package/dist/lib/selection-proxy.js +12 -0
  48. package/dist/lib/slab-polygon.d.ts +31 -2
  49. package/dist/lib/slab-polygon.d.ts.map +1 -1
  50. package/dist/lib/slab-polygon.js +525 -31
  51. package/dist/lib/slab-polygon.test.d.ts +2 -0
  52. package/dist/lib/slab-polygon.test.d.ts.map +1 -0
  53. package/dist/lib/slab-polygon.test.js +635 -0
  54. package/dist/lib/slots.d.ts +14 -0
  55. package/dist/lib/slots.d.ts.map +1 -0
  56. package/dist/lib/slots.js +26 -0
  57. package/dist/lib/space-detection-pause.test.d.ts +2 -0
  58. package/dist/lib/space-detection-pause.test.d.ts.map +1 -0
  59. package/dist/lib/space-detection-pause.test.js +42 -0
  60. package/dist/lib/space-detection.d.ts +54 -2
  61. package/dist/lib/space-detection.d.ts.map +1 -1
  62. package/dist/lib/space-detection.js +599 -124
  63. package/dist/lib/space-detection.test.d.ts +2 -0
  64. package/dist/lib/space-detection.test.d.ts.map +1 -0
  65. package/dist/lib/space-detection.test.js +376 -0
  66. package/dist/lib/wall-distance.d.ts +60 -0
  67. package/dist/lib/wall-distance.d.ts.map +1 -0
  68. package/dist/lib/wall-distance.js +85 -0
  69. package/dist/lib/zone-quantities.d.ts +21 -0
  70. package/dist/lib/zone-quantities.d.ts.map +1 -0
  71. package/dist/lib/zone-quantities.js +183 -0
  72. package/dist/lib/zone-quantities.test.d.ts +2 -0
  73. package/dist/lib/zone-quantities.test.d.ts.map +1 -0
  74. package/dist/lib/zone-quantities.test.js +82 -0
  75. package/dist/material-library.d.ts +20 -1
  76. package/dist/material-library.d.ts.map +1 -1
  77. package/dist/material-library.js +3737 -200
  78. package/dist/registry/__bench__/relations-resolver.bench.d.ts +15 -0
  79. package/dist/registry/__bench__/relations-resolver.bench.d.ts.map +1 -0
  80. package/dist/registry/__bench__/relations-resolver.bench.js +170 -0
  81. package/dist/registry/handles.d.ts +394 -0
  82. package/dist/registry/handles.d.ts.map +1 -0
  83. package/dist/registry/handles.js +24 -0
  84. package/dist/registry/index.d.ts +7 -0
  85. package/dist/registry/index.d.ts.map +1 -0
  86. package/dist/registry/index.js +4 -0
  87. package/dist/registry/registry.d.ts +136 -0
  88. package/dist/registry/registry.d.ts.map +1 -0
  89. package/dist/registry/registry.js +282 -0
  90. package/dist/registry/registry.test.d.ts +2 -0
  91. package/dist/registry/registry.test.d.ts.map +1 -0
  92. package/dist/registry/registry.test.js +196 -0
  93. package/dist/registry/relations-resolver.d.ts +42 -0
  94. package/dist/registry/relations-resolver.d.ts.map +1 -0
  95. package/dist/registry/relations-resolver.js +77 -0
  96. package/dist/registry/relations-resolver.test.d.ts +2 -0
  97. package/dist/registry/relations-resolver.test.d.ts.map +1 -0
  98. package/dist/registry/relations-resolver.test.js +183 -0
  99. package/dist/registry/scene-api.d.ts +44 -0
  100. package/dist/registry/scene-api.d.ts.map +1 -0
  101. package/dist/registry/scene-api.js +111 -0
  102. package/dist/registry/scene-api.test.d.ts +2 -0
  103. package/dist/registry/scene-api.test.d.ts.map +1 -0
  104. package/dist/registry/scene-api.test.js +183 -0
  105. package/dist/registry/subtree.d.ts +67 -0
  106. package/dist/registry/subtree.d.ts.map +1 -0
  107. package/dist/registry/subtree.js +123 -0
  108. package/dist/registry/subtree.test.d.ts +2 -0
  109. package/dist/registry/subtree.test.d.ts.map +1 -0
  110. package/dist/registry/subtree.test.js +163 -0
  111. package/dist/registry/types.d.ts +2099 -0
  112. package/dist/registry/types.d.ts.map +1 -0
  113. package/dist/registry/types.js +1 -0
  114. package/dist/schema/index.d.ts +35 -4
  115. package/dist/schema/index.d.ts.map +1 -1
  116. package/dist/schema/index.js +32 -4
  117. package/dist/schema/material.d.ts +13 -2
  118. package/dist/schema/material.d.ts.map +1 -1
  119. package/dist/schema/material.js +17 -5
  120. package/dist/schema/material.test.d.ts +2 -0
  121. package/dist/schema/material.test.d.ts.map +1 -0
  122. package/dist/schema/material.test.js +43 -0
  123. package/dist/schema/nodes/box-vent.d.ts +74 -0
  124. package/dist/schema/nodes/box-vent.d.ts.map +1 -0
  125. package/dist/schema/nodes/box-vent.js +63 -0
  126. package/dist/schema/nodes/building.d.ts +1 -1
  127. package/dist/schema/nodes/building.d.ts.map +1 -1
  128. package/dist/schema/nodes/building.js +3 -2
  129. package/dist/schema/nodes/cabinet.d.ts +534 -0
  130. package/dist/schema/nodes/cabinet.d.ts.map +1 -0
  131. package/dist/schema/nodes/cabinet.js +137 -0
  132. package/dist/schema/nodes/ceiling.d.ts +5 -2
  133. package/dist/schema/nodes/ceiling.d.ts.map +1 -1
  134. package/dist/schema/nodes/ceiling.js +5 -1
  135. package/dist/schema/nodes/chimney.d.ts +158 -0
  136. package/dist/schema/nodes/chimney.d.ts.map +1 -0
  137. package/dist/schema/nodes/chimney.js +67 -0
  138. package/dist/schema/nodes/column.d.ts +600 -7
  139. package/dist/schema/nodes/column.d.ts.map +1 -1
  140. package/dist/schema/nodes/column.js +589 -6
  141. package/dist/schema/nodes/cupola.d.ts +66 -0
  142. package/dist/schema/nodes/cupola.d.ts.map +1 -0
  143. package/dist/schema/nodes/cupola.js +28 -0
  144. package/dist/schema/nodes/door.d.ts +13 -5
  145. package/dist/schema/nodes/door.d.ts.map +1 -1
  146. package/dist/schema/nodes/door.js +12 -0
  147. package/dist/schema/nodes/dormer.d.ts +228 -0
  148. package/dist/schema/nodes/dormer.d.ts.map +1 -0
  149. package/dist/schema/nodes/dormer.js +119 -0
  150. package/dist/schema/nodes/downspout.d.ts +75 -0
  151. package/dist/schema/nodes/downspout.d.ts.map +1 -0
  152. package/dist/schema/nodes/downspout.js +63 -0
  153. package/dist/schema/nodes/duct-fitting.d.ts +91 -0
  154. package/dist/schema/nodes/duct-fitting.d.ts.map +1 -0
  155. package/dist/schema/nodes/duct-fitting.js +92 -0
  156. package/dist/schema/nodes/duct-segment.d.ts +61 -0
  157. package/dist/schema/nodes/duct-segment.d.ts.map +1 -0
  158. package/dist/schema/nodes/duct-segment.js +73 -0
  159. package/dist/schema/nodes/duct-terminal.d.ts +57 -0
  160. package/dist/schema/nodes/duct-terminal.d.ts.map +1 -0
  161. package/dist/schema/nodes/duct-terminal.js +51 -0
  162. package/dist/schema/nodes/elevator.d.ts +106 -0
  163. package/dist/schema/nodes/elevator.d.ts.map +1 -0
  164. package/dist/schema/nodes/elevator.js +57 -0
  165. package/dist/schema/nodes/eyebrow-vent.d.ts +68 -0
  166. package/dist/schema/nodes/eyebrow-vent.d.ts.map +1 -0
  167. package/dist/schema/nodes/eyebrow-vent.js +40 -0
  168. package/dist/schema/nodes/fence.d.ts +19 -2
  169. package/dist/schema/nodes/fence.d.ts.map +1 -1
  170. package/dist/schema/nodes/fence.js +27 -2
  171. package/dist/schema/nodes/gutter.d.ts +84 -0
  172. package/dist/schema/nodes/gutter.d.ts.map +1 -0
  173. package/dist/schema/nodes/gutter.js +76 -0
  174. package/dist/schema/nodes/hvac-equipment.d.ts +63 -0
  175. package/dist/schema/nodes/hvac-equipment.d.ts.map +1 -0
  176. package/dist/schema/nodes/hvac-equipment.js +55 -0
  177. package/dist/schema/nodes/item.d.ts +12 -0
  178. package/dist/schema/nodes/item.d.ts.map +1 -1
  179. package/dist/schema/nodes/item.js +20 -0
  180. package/dist/schema/nodes/level.d.ts +1 -1
  181. package/dist/schema/nodes/level.d.ts.map +1 -1
  182. package/dist/schema/nodes/level.js +4 -0
  183. package/dist/schema/nodes/lineset.d.ts +42 -0
  184. package/dist/schema/nodes/lineset.d.ts.map +1 -0
  185. package/dist/schema/nodes/lineset.js +38 -0
  186. package/dist/schema/nodes/liquid-line.d.ts +34 -0
  187. package/dist/schema/nodes/liquid-line.d.ts.map +1 -0
  188. package/dist/schema/nodes/liquid-line.js +24 -0
  189. package/dist/schema/nodes/measurement.d.ts +306 -0
  190. package/dist/schema/nodes/measurement.d.ts.map +1 -0
  191. package/dist/schema/nodes/measurement.js +87 -0
  192. package/dist/schema/nodes/measurement.test.d.ts +2 -0
  193. package/dist/schema/nodes/measurement.test.d.ts.map +1 -0
  194. package/dist/schema/nodes/measurement.test.js +139 -0
  195. package/dist/schema/nodes/pipe-fitting.d.ts +56 -0
  196. package/dist/schema/nodes/pipe-fitting.d.ts.map +1 -0
  197. package/dist/schema/nodes/pipe-fitting.js +45 -0
  198. package/dist/schema/nodes/pipe-segment.d.ts +48 -0
  199. package/dist/schema/nodes/pipe-segment.d.ts.map +1 -0
  200. package/dist/schema/nodes/pipe-segment.js +36 -0
  201. package/dist/schema/nodes/pipe-trap.d.ts +43 -0
  202. package/dist/schema/nodes/pipe-trap.d.ts.map +1 -0
  203. package/dist/schema/nodes/pipe-trap.js +36 -0
  204. package/dist/schema/nodes/ridge-vent-defaults.test.d.ts +2 -0
  205. package/dist/schema/nodes/ridge-vent-defaults.test.d.ts.map +1 -0
  206. package/dist/schema/nodes/ridge-vent-defaults.test.js +205 -0
  207. package/dist/schema/nodes/ridge-vent.d.ts +82 -0
  208. package/dist/schema/nodes/ridge-vent.d.ts.map +1 -0
  209. package/dist/schema/nodes/ridge-vent.js +248 -0
  210. package/dist/schema/nodes/roof-segment-shape.d.ts +90 -0
  211. package/dist/schema/nodes/roof-segment-shape.d.ts.map +1 -0
  212. package/dist/schema/nodes/roof-segment-shape.js +318 -0
  213. package/dist/schema/nodes/roof-segment-shape.test.d.ts +2 -0
  214. package/dist/schema/nodes/roof-segment-shape.test.d.ts.map +1 -0
  215. package/dist/schema/nodes/roof-segment-shape.test.js +175 -0
  216. package/dist/schema/nodes/roof-segment-surface.test.d.ts +2 -0
  217. package/dist/schema/nodes/roof-segment-surface.test.d.ts.map +1 -0
  218. package/dist/schema/nodes/roof-segment-surface.test.js +48 -0
  219. package/dist/schema/nodes/roof-segment-trim.test.d.ts +2 -0
  220. package/dist/schema/nodes/roof-segment-trim.test.d.ts.map +1 -0
  221. package/dist/schema/nodes/roof-segment-trim.test.js +107 -0
  222. package/dist/schema/nodes/roof-segment-walls.d.ts +101 -0
  223. package/dist/schema/nodes/roof-segment-walls.d.ts.map +1 -0
  224. package/dist/schema/nodes/roof-segment-walls.js +330 -0
  225. package/dist/schema/nodes/roof-segment-walls.test.d.ts +2 -0
  226. package/dist/schema/nodes/roof-segment-walls.test.d.ts.map +1 -0
  227. package/dist/schema/nodes/roof-segment-walls.test.js +92 -0
  228. package/dist/schema/nodes/roof-segment.d.ts +273 -3
  229. package/dist/schema/nodes/roof-segment.d.ts.map +1 -1
  230. package/dist/schema/nodes/roof-segment.js +539 -3
  231. package/dist/schema/nodes/roof.d.ts +8 -8
  232. package/dist/schema/nodes/roof.d.ts.map +1 -1
  233. package/dist/schema/nodes/roof.js +4 -16
  234. package/dist/schema/nodes/shelf.d.ts +106 -0
  235. package/dist/schema/nodes/shelf.d.ts.map +1 -0
  236. package/dist/schema/nodes/shelf.js +90 -0
  237. package/dist/schema/nodes/site.d.ts +1 -122
  238. package/dist/schema/nodes/site.d.ts.map +1 -1
  239. package/dist/schema/nodes/site.js +2 -6
  240. package/dist/schema/nodes/skylight.d.ts +279 -0
  241. package/dist/schema/nodes/skylight.d.ts.map +1 -0
  242. package/dist/schema/nodes/skylight.js +152 -0
  243. package/dist/schema/nodes/slab.d.ts +5 -2
  244. package/dist/schema/nodes/slab.d.ts.map +1 -1
  245. package/dist/schema/nodes/slab.js +5 -1
  246. package/dist/schema/nodes/solar-panel.d.ts +117 -0
  247. package/dist/schema/nodes/solar-panel.d.ts.map +1 -0
  248. package/dist/schema/nodes/solar-panel.js +47 -0
  249. package/dist/schema/nodes/stair-segment.d.ts +4 -4
  250. package/dist/schema/nodes/stair.d.ts +13 -12
  251. package/dist/schema/nodes/stair.d.ts.map +1 -1
  252. package/dist/schema/nodes/stair.js +3 -0
  253. package/dist/schema/nodes/surface-hole-metadata.d.ts +2 -0
  254. package/dist/schema/nodes/surface-hole-metadata.d.ts.map +1 -1
  255. package/dist/schema/nodes/surface-hole-metadata.js +3 -1
  256. package/dist/schema/nodes/turbine-vent.d.ts +68 -0
  257. package/dist/schema/nodes/turbine-vent.d.ts.map +1 -0
  258. package/dist/schema/nodes/turbine-vent.js +41 -0
  259. package/dist/schema/nodes/wall.d.ts +245 -6
  260. package/dist/schema/nodes/wall.d.ts.map +1 -1
  261. package/dist/schema/nodes/wall.js +257 -0
  262. package/dist/schema/nodes/wall.test.d.ts +2 -0
  263. package/dist/schema/nodes/wall.test.d.ts.map +1 -0
  264. package/dist/schema/nodes/wall.test.js +208 -0
  265. package/dist/schema/nodes/window.d.ts +11 -3
  266. package/dist/schema/nodes/window.d.ts.map +1 -1
  267. package/dist/schema/nodes/window.js +12 -0
  268. package/dist/schema/nodes/zone.d.ts +2 -0
  269. package/dist/schema/nodes/zone.d.ts.map +1 -1
  270. package/dist/schema/nodes/zone.js +6 -0
  271. package/dist/schema/scene-material.d.ts +41 -0
  272. package/dist/schema/scene-material.d.ts.map +1 -0
  273. package/dist/schema/scene-material.js +9 -0
  274. package/dist/schema/types.d.ts +2850 -655
  275. package/dist/schema/types.d.ts.map +1 -1
  276. package/dist/schema/types.js +49 -0
  277. package/dist/services/alignment-anchors.d.ts +100 -0
  278. package/dist/services/alignment-anchors.d.ts.map +1 -0
  279. package/dist/services/alignment-anchors.js +312 -0
  280. package/dist/services/alignment-anchors.test.d.ts +2 -0
  281. package/dist/services/alignment-anchors.test.d.ts.map +1 -0
  282. package/dist/services/alignment-anchors.test.js +383 -0
  283. package/dist/services/alignment.d.ts +131 -0
  284. package/dist/services/alignment.d.ts.map +1 -0
  285. package/dist/services/alignment.js +171 -0
  286. package/dist/services/alignment.test.d.ts +2 -0
  287. package/dist/services/alignment.test.d.ts.map +1 -0
  288. package/dist/services/alignment.test.js +92 -0
  289. package/dist/services/drag-session.d.ts +47 -0
  290. package/dist/services/drag-session.d.ts.map +1 -0
  291. package/dist/services/drag-session.js +100 -0
  292. package/dist/services/drag-session.test.d.ts +2 -0
  293. package/dist/services/drag-session.test.d.ts.map +1 -0
  294. package/dist/services/drag-session.test.js +219 -0
  295. package/dist/services/hosting.d.ts +88 -0
  296. package/dist/services/hosting.d.ts.map +1 -0
  297. package/dist/services/hosting.js +131 -0
  298. package/dist/services/hosting.test.d.ts +2 -0
  299. package/dist/services/hosting.test.d.ts.map +1 -0
  300. package/dist/services/hosting.test.js +230 -0
  301. package/dist/services/index.d.ts +13 -0
  302. package/dist/services/index.d.ts.map +1 -0
  303. package/dist/services/index.js +12 -0
  304. package/dist/services/level-height.d.ts +28 -0
  305. package/dist/services/level-height.d.ts.map +1 -0
  306. package/dist/services/level-height.js +62 -0
  307. package/dist/services/movement.d.ts +48 -0
  308. package/dist/services/movement.d.ts.map +1 -0
  309. package/dist/services/movement.js +65 -0
  310. package/dist/services/movement.test.d.ts +2 -0
  311. package/dist/services/movement.test.d.ts.map +1 -0
  312. package/dist/services/movement.test.js +133 -0
  313. package/dist/services/opening-guides.d.ts +141 -0
  314. package/dist/services/opening-guides.d.ts.map +1 -0
  315. package/dist/services/opening-guides.js +267 -0
  316. package/dist/services/opening-guides.test.d.ts +2 -0
  317. package/dist/services/opening-guides.test.d.ts.map +1 -0
  318. package/dist/services/opening-guides.test.js +208 -0
  319. package/dist/services/port-connectivity.d.ts +115 -0
  320. package/dist/services/port-connectivity.d.ts.map +1 -0
  321. package/dist/services/port-connectivity.js +300 -0
  322. package/dist/services/port-connectivity.test.d.ts +2 -0
  323. package/dist/services/port-connectivity.test.d.ts.map +1 -0
  324. package/dist/services/port-connectivity.test.js +297 -0
  325. package/dist/services/riser-diagram.d.ts +40 -0
  326. package/dist/services/riser-diagram.d.ts.map +1 -0
  327. package/dist/services/riser-diagram.js +110 -0
  328. package/dist/services/riser-diagram.test.d.ts +2 -0
  329. package/dist/services/riser-diagram.test.d.ts.map +1 -0
  330. package/dist/services/riser-diagram.test.js +66 -0
  331. package/dist/services/single-undo-dance.test.d.ts +2 -0
  332. package/dist/services/single-undo-dance.test.d.ts.map +1 -0
  333. package/dist/services/single-undo-dance.test.js +210 -0
  334. package/dist/services/snap.d.ts +80 -0
  335. package/dist/services/snap.d.ts.map +1 -0
  336. package/dist/services/snap.js +140 -0
  337. package/dist/services/snap.test.d.ts +2 -0
  338. package/dist/services/snap.test.d.ts.map +1 -0
  339. package/dist/services/snap.test.js +137 -0
  340. package/dist/services/system-graph.d.ts +30 -0
  341. package/dist/services/system-graph.d.ts.map +1 -0
  342. package/dist/services/system-graph.js +164 -0
  343. package/dist/services/system-graph.test.d.ts +2 -0
  344. package/dist/services/system-graph.test.d.ts.map +1 -0
  345. package/dist/services/system-graph.test.js +138 -0
  346. package/dist/services/validate-dwv.d.ts +32 -0
  347. package/dist/services/validate-dwv.d.ts.map +1 -0
  348. package/dist/services/validate-dwv.js +118 -0
  349. package/dist/services/validate-dwv.test.d.ts +2 -0
  350. package/dist/services/validate-dwv.test.d.ts.map +1 -0
  351. package/dist/services/validate-dwv.test.js +109 -0
  352. package/dist/solar-panel-presets.d.ts +17 -0
  353. package/dist/solar-panel-presets.d.ts.map +1 -0
  354. package/dist/solar-panel-presets.js +43 -0
  355. package/dist/store/actions/node-actions.d.ts +14 -2
  356. package/dist/store/actions/node-actions.d.ts.map +1 -1
  357. package/dist/store/actions/node-actions.js +585 -15
  358. package/dist/store/actions/node-mutation-sanitize.test.d.ts +2 -0
  359. package/dist/store/actions/node-mutation-sanitize.test.d.ts.map +1 -0
  360. package/dist/store/actions/node-mutation-sanitize.test.js +147 -0
  361. package/dist/store/actions/reparent.test.d.ts +2 -0
  362. package/dist/store/actions/reparent.test.d.ts.map +1 -0
  363. package/dist/store/actions/reparent.test.js +212 -0
  364. package/dist/store/actions/ridge-vent-update.test.d.ts +2 -0
  365. package/dist/store/actions/ridge-vent-update.test.d.ts.map +1 -0
  366. package/dist/store/actions/ridge-vent-update.test.js +264 -0
  367. package/dist/store/history-control.d.ts +11 -0
  368. package/dist/store/history-control.d.ts.map +1 -1
  369. package/dist/store/history-control.js +33 -0
  370. package/dist/store/use-interactive.d.ts +39 -0
  371. package/dist/store/use-interactive.d.ts.map +1 -1
  372. package/dist/store/use-interactive.js +75 -0
  373. package/dist/store/use-live-node-overrides.d.ts +22 -0
  374. package/dist/store/use-live-node-overrides.d.ts.map +1 -0
  375. package/dist/store/use-live-node-overrides.js +59 -0
  376. package/dist/store/use-scene-dirty-tracking.test.d.ts +2 -0
  377. package/dist/store/use-scene-dirty-tracking.test.d.ts.map +1 -0
  378. package/dist/store/use-scene-dirty-tracking.test.js +68 -0
  379. package/dist/store/use-scene-elevator-migration.test.d.ts +2 -0
  380. package/dist/store/use-scene-elevator-migration.test.d.ts.map +1 -0
  381. package/dist/store/use-scene-elevator-migration.test.js +109 -0
  382. package/dist/store/use-scene-measurement-roundtrip.test.d.ts +2 -0
  383. package/dist/store/use-scene-measurement-roundtrip.test.d.ts.map +1 -0
  384. package/dist/store/use-scene-measurement-roundtrip.test.js +97 -0
  385. package/dist/store/use-scene-plugins.test.d.ts +2 -0
  386. package/dist/store/use-scene-plugins.test.d.ts.map +1 -0
  387. package/dist/store/use-scene-plugins.test.js +51 -0
  388. package/dist/store/use-scene-wall-slot-migration.test.d.ts +2 -0
  389. package/dist/store/use-scene-wall-slot-migration.test.d.ts.map +1 -0
  390. package/dist/store/use-scene-wall-slot-migration.test.js +210 -0
  391. package/dist/store/use-scene-window-migration.test.d.ts +2 -0
  392. package/dist/store/use-scene-window-migration.test.d.ts.map +1 -0
  393. package/dist/store/use-scene-window-migration.test.js +85 -0
  394. package/dist/store/use-scene.d.ts +28 -2
  395. package/dist/store/use-scene.d.ts.map +1 -1
  396. package/dist/store/use-scene.js +546 -49
  397. package/dist/systems/elevator/elevator-dispatch.d.ts +12 -0
  398. package/dist/systems/elevator/elevator-dispatch.d.ts.map +1 -0
  399. package/dist/systems/elevator/elevator-dispatch.js +57 -0
  400. package/dist/systems/elevator/elevator-geometry.d.ts +15 -0
  401. package/dist/systems/elevator/elevator-geometry.d.ts.map +1 -0
  402. package/dist/systems/elevator/elevator-geometry.js +50 -0
  403. package/dist/systems/elevator/elevator-opening-sync.d.ts +6 -0
  404. package/dist/systems/elevator/elevator-opening-sync.d.ts.map +1 -0
  405. package/dist/systems/elevator/elevator-opening-sync.js +218 -0
  406. package/dist/systems/elevator/elevator-opening-sync.test.d.ts +2 -0
  407. package/dist/systems/elevator/elevator-opening-sync.test.d.ts.map +1 -0
  408. package/dist/systems/elevator/elevator-opening-sync.test.js +146 -0
  409. package/dist/systems/elevator/elevator-opening-system.d.ts +2 -0
  410. package/dist/systems/elevator/elevator-opening-system.d.ts.map +1 -0
  411. package/dist/systems/elevator/elevator-opening-system.js +48 -0
  412. package/dist/systems/elevator/elevator-runtime-system.d.ts +2 -0
  413. package/dist/systems/elevator/elevator-runtime-system.d.ts.map +1 -0
  414. package/dist/systems/elevator/elevator-runtime-system.js +8 -0
  415. package/dist/systems/elevator/elevator-runtime.d.ts +18 -0
  416. package/dist/systems/elevator/elevator-runtime.d.ts.map +1 -0
  417. package/dist/systems/elevator/elevator-runtime.js +225 -0
  418. package/dist/systems/elevator/elevator-runtime.test.d.ts +2 -0
  419. package/dist/systems/elevator/elevator-runtime.test.d.ts.map +1 -0
  420. package/dist/systems/elevator/elevator-runtime.test.js +64 -0
  421. package/dist/systems/elevator/elevator-service.d.ts +19 -0
  422. package/dist/systems/elevator/elevator-service.d.ts.map +1 -0
  423. package/dist/systems/elevator/elevator-service.js +111 -0
  424. package/dist/systems/fence/fence-centerline.d.ts +12 -0
  425. package/dist/systems/fence/fence-centerline.d.ts.map +1 -0
  426. package/dist/systems/fence/fence-centerline.js +37 -0
  427. package/dist/systems/fence/fence-spline.d.ts +39 -0
  428. package/dist/systems/fence/fence-spline.d.ts.map +1 -0
  429. package/dist/systems/fence/fence-spline.js +196 -0
  430. package/dist/systems/fence/fence-spline.test.d.ts +2 -0
  431. package/dist/systems/fence/fence-spline.test.d.ts.map +1 -0
  432. package/dist/systems/fence/fence-spline.test.js +136 -0
  433. package/dist/systems/stair/stair-footprint.d.ts +44 -0
  434. package/dist/systems/stair/stair-footprint.d.ts.map +1 -0
  435. package/dist/systems/stair/stair-footprint.js +178 -0
  436. package/dist/systems/stair/stair-opening-preview.d.ts +2447 -0
  437. package/dist/systems/stair/stair-opening-preview.d.ts.map +1 -0
  438. package/dist/systems/stair/stair-opening-preview.js +93 -0
  439. package/dist/systems/stair/stair-opening-preview.test.d.ts +2 -0
  440. package/dist/systems/stair/stair-opening-preview.test.d.ts.map +1 -0
  441. package/dist/systems/stair/stair-opening-preview.test.js +80 -0
  442. package/dist/systems/stair/stair-opening-sync.d.ts.map +1 -1
  443. package/dist/systems/stair/stair-opening-sync.js +155 -147
  444. package/dist/systems/stair/stair-opening-sync.test.js +424 -2
  445. package/dist/systems/stair/stair-opening-system.d.ts +2 -0
  446. package/dist/systems/stair/stair-opening-system.d.ts.map +1 -0
  447. package/dist/systems/stair/stair-opening-system.js +104 -0
  448. package/dist/systems/wall/wall-mitering.d.ts.map +1 -1
  449. package/dist/systems/wall/wall-mitering.js +38 -2
  450. package/dist/systems/wall/wall-mitering.test.d.ts +2 -0
  451. package/dist/systems/wall/wall-mitering.test.d.ts.map +1 -0
  452. package/dist/systems/wall/wall-mitering.test.js +63 -0
  453. package/dist/systems/wall/wall-move.d.ts +48 -0
  454. package/dist/systems/wall/wall-move.d.ts.map +1 -0
  455. package/dist/systems/wall/wall-move.js +193 -0
  456. package/dist/utils/clone-scene-graph.d.ts +7 -4
  457. package/dist/utils/clone-scene-graph.d.ts.map +1 -1
  458. package/dist/utils/clone-scene-graph.js +29 -7
  459. package/dist/utils/clone-scene-graph.test.d.ts +2 -0
  460. package/dist/utils/clone-scene-graph.test.d.ts.map +1 -0
  461. package/dist/utils/clone-scene-graph.test.js +62 -0
  462. package/dist/utils/heal-scene-graph.d.ts +18 -0
  463. package/dist/utils/heal-scene-graph.d.ts.map +1 -0
  464. package/dist/utils/heal-scene-graph.js +90 -0
  465. package/dist/utils/heal-scene-graph.test.d.ts +2 -0
  466. package/dist/utils/heal-scene-graph.test.d.ts.map +1 -0
  467. package/dist/utils/heal-scene-graph.test.js +88 -0
  468. package/dist/validation/validate-build-json.d.ts +44 -0
  469. package/dist/validation/validate-build-json.d.ts.map +1 -0
  470. package/dist/validation/validate-build-json.js +256 -0
  471. package/package.json +11 -4
@@ -0,0 +1,225 @@
1
+ import { useInteractive } from '../../store/use-interactive';
2
+ import useScene from '../../store/use-scene';
3
+ import { resolveElevatorLevels } from './elevator-service';
4
+ const EPSILON = 0.001;
5
+ function moveToward(current, target, maxDelta) {
6
+ const delta = target - current;
7
+ if (Math.abs(delta) <= maxDelta)
8
+ return target;
9
+ return current + Math.sign(delta) * maxDelta;
10
+ }
11
+ export function createElevatorInteractiveState(levelId, carY) {
12
+ return {
13
+ currentLevelId: levelId,
14
+ targetLevelId: null,
15
+ carY,
16
+ doorOpen: 0,
17
+ phase: 'idle',
18
+ phaseStartedAt: null,
19
+ queue: [],
20
+ requestedStops: [],
21
+ };
22
+ }
23
+ function getInitialElevatorState(elevatorId, nodes) {
24
+ const node = nodes[elevatorId];
25
+ if (node?.type !== 'elevator')
26
+ return null;
27
+ const { defaultEntry } = resolveElevatorLevels(node, nodes);
28
+ if (!defaultEntry)
29
+ return null;
30
+ return createElevatorInteractiveState(defaultEntry.id, defaultEntry.baseY);
31
+ }
32
+ function ensureElevatorState(elevatorId, nodes) {
33
+ const interactive = useInteractive.getState();
34
+ const existing = interactive.elevators[elevatorId];
35
+ if (existing)
36
+ return existing;
37
+ const initial = getInitialElevatorState(elevatorId, nodes);
38
+ if (!initial)
39
+ return null;
40
+ interactive.initElevator(elevatorId, initial.currentLevelId, initial.carY);
41
+ return initial;
42
+ }
43
+ export function queueElevatorRequest(state, levelId) {
44
+ const isAlreadyQueued = state.queue.includes(levelId) || state.targetLevelId === levelId;
45
+ if (isAlreadyQueued)
46
+ return state;
47
+ return {
48
+ ...state,
49
+ queue: [...state.queue, levelId],
50
+ requestedStops: state.requestedStops.includes(levelId)
51
+ ? state.requestedStops
52
+ : [...state.requestedStops, levelId],
53
+ };
54
+ }
55
+ export function openElevatorDoorState(state) {
56
+ if (!state.currentLevelId || state.phase === 'moving')
57
+ return state;
58
+ return {
59
+ ...state,
60
+ phase: 'opening',
61
+ phaseStartedAt: null,
62
+ };
63
+ }
64
+ export function requestElevatorLevel(elevatorId, levelId) {
65
+ const nodes = useScene.getState().nodes;
66
+ const current = ensureElevatorState(elevatorId, nodes);
67
+ if (!current)
68
+ return;
69
+ const next = queueElevatorRequest(current, levelId);
70
+ if (next === current)
71
+ return;
72
+ useInteractive.getState().setElevatorState(elevatorId, next);
73
+ }
74
+ export function openElevatorDoor(elevatorId) {
75
+ const nodes = useScene.getState().nodes;
76
+ const current = ensureElevatorState(elevatorId, nodes);
77
+ if (!current)
78
+ return;
79
+ const next = openElevatorDoorState(current);
80
+ if (next === current)
81
+ return;
82
+ useInteractive.getState().setElevatorState(elevatorId, next);
83
+ }
84
+ export function stepElevatorRuntimeState({ defaultEntry, delta, elevator, entries, now, state, }) {
85
+ const currentEntry = entries.find((entry) => entry.id === state.currentLevelId) ?? defaultEntry;
86
+ if (currentEntry.id !== state.currentLevelId) {
87
+ return {
88
+ ...state,
89
+ currentLevelId: currentEntry.id,
90
+ carY: currentEntry.baseY,
91
+ targetLevelId: null,
92
+ phase: 'idle',
93
+ phaseStartedAt: null,
94
+ queue: [],
95
+ requestedStops: [],
96
+ doorOpen: 0,
97
+ };
98
+ }
99
+ const targetEntry = state.targetLevelId
100
+ ? entries.find((entry) => entry.id === state.targetLevelId)
101
+ : state.queue[0]
102
+ ? entries.find((entry) => entry.id === state.queue[0])
103
+ : null;
104
+ const doorDurationMs = Math.max(elevator.doorDurationMs ?? 900, 1);
105
+ const doorStep = (delta * 1000) / doorDurationMs;
106
+ switch (state.phase) {
107
+ case 'idle': {
108
+ const nextLevelId = state.queue[0] ?? null;
109
+ if (!nextLevelId) {
110
+ if (state.doorOpen > EPSILON) {
111
+ return {
112
+ ...state,
113
+ doorOpen: Math.max(0, state.doorOpen - doorStep),
114
+ };
115
+ }
116
+ if (state.requestedStops.length === 0)
117
+ return state;
118
+ return {
119
+ ...state,
120
+ requestedStops: [],
121
+ };
122
+ }
123
+ return {
124
+ ...state,
125
+ targetLevelId: nextLevelId,
126
+ phase: state.doorOpen > EPSILON
127
+ ? 'closing'
128
+ : nextLevelId === state.currentLevelId
129
+ ? 'opening'
130
+ : 'moving',
131
+ phaseStartedAt: now,
132
+ };
133
+ }
134
+ case 'closing': {
135
+ const doorOpen = Math.max(0, state.doorOpen - doorStep);
136
+ return {
137
+ ...state,
138
+ doorOpen,
139
+ phase: doorOpen <= EPSILON ? (state.targetLevelId ? 'moving' : 'idle') : 'closing',
140
+ phaseStartedAt: doorOpen <= EPSILON ? now : state.phaseStartedAt,
141
+ };
142
+ }
143
+ case 'moving': {
144
+ if (!targetEntry) {
145
+ return {
146
+ ...state,
147
+ targetLevelId: null,
148
+ phase: 'idle',
149
+ queue: [],
150
+ requestedStops: [],
151
+ };
152
+ }
153
+ const speed = Math.max(elevator.speed ?? 2.2, 0.1);
154
+ const nextY = moveToward(state.carY, targetEntry.baseY, speed * delta);
155
+ const arrived = Math.abs(nextY - targetEntry.baseY) <= EPSILON;
156
+ return {
157
+ ...state,
158
+ carY: nextY,
159
+ currentLevelId: arrived ? targetEntry.id : state.currentLevelId,
160
+ phase: arrived ? 'opening' : 'moving',
161
+ phaseStartedAt: arrived ? now : state.phaseStartedAt,
162
+ };
163
+ }
164
+ case 'opening': {
165
+ const doorOpen = Math.min(1, state.doorOpen + doorStep);
166
+ return {
167
+ ...state,
168
+ doorOpen,
169
+ phase: doorOpen >= 1 - EPSILON ? 'open' : 'opening',
170
+ phaseStartedAt: doorOpen >= 1 - EPSILON ? now : state.phaseStartedAt,
171
+ targetLevelId: doorOpen >= 1 - EPSILON ? null : state.targetLevelId,
172
+ queue: doorOpen >= 1 - EPSILON && state.queue[0] === state.currentLevelId
173
+ ? state.queue.slice(1)
174
+ : state.queue,
175
+ };
176
+ }
177
+ case 'open': {
178
+ const elapsed = now - (state.phaseStartedAt ?? now);
179
+ if (elapsed < Math.max(elevator.dwellMs ?? 1400, 0))
180
+ return state;
181
+ return {
182
+ ...state,
183
+ phase: 'closing',
184
+ phaseStartedAt: now,
185
+ targetLevelId: state.queue[0] ?? null,
186
+ };
187
+ }
188
+ }
189
+ }
190
+ export function stepElevatorRuntimes(now, delta) {
191
+ const nodes = useScene.getState().nodes;
192
+ const interactive = useInteractive.getState();
193
+ for (const elevatorId of Object.keys(interactive.elevators)) {
194
+ const typedElevatorId = elevatorId;
195
+ if (nodes[typedElevatorId]?.type !== 'elevator') {
196
+ interactive.removeElevator(typedElevatorId);
197
+ }
198
+ }
199
+ for (const node of Object.values(nodes)) {
200
+ if (node.type !== 'elevator')
201
+ continue;
202
+ const elevatorId = node.id;
203
+ const { entries, defaultEntry } = resolveElevatorLevels(node, nodes);
204
+ if (!defaultEntry)
205
+ continue;
206
+ const state = useInteractive.getState().elevators[elevatorId];
207
+ if (!state) {
208
+ useInteractive
209
+ .getState()
210
+ .initElevator(elevatorId, defaultEntry.id, defaultEntry.baseY);
211
+ continue;
212
+ }
213
+ const next = stepElevatorRuntimeState({
214
+ defaultEntry,
215
+ delta,
216
+ elevator: node,
217
+ entries,
218
+ now,
219
+ state,
220
+ });
221
+ if (next !== state) {
222
+ useInteractive.getState().setElevatorState(elevatorId, next);
223
+ }
224
+ }
225
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=elevator-runtime.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elevator-runtime.test.d.ts","sourceRoot":"","sources":["../../../src/systems/elevator/elevator-runtime.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,64 @@
1
+ import { describe, expect, test } from 'bun:test';
2
+ import { ElevatorNode } from '../../schema';
3
+ import { createElevatorInteractiveState, openElevatorDoorState, queueElevatorRequest, stepElevatorRuntimeState, } from './elevator-runtime';
4
+ const groundLevelId = 'level_ground';
5
+ const upperLevelId = 'level_upper';
6
+ const entries = [
7
+ { id: groundLevelId, label: '0', baseY: 0 },
8
+ { id: upperLevelId, label: '1', baseY: 2.5 },
9
+ ];
10
+ const elevator = ElevatorNode.parse({
11
+ speed: 10,
12
+ doorDurationMs: 100,
13
+ dwellMs: 0,
14
+ });
15
+ describe('elevator runtime helpers', () => {
16
+ test('queues level requests without duplicating the target', () => {
17
+ const state = createElevatorInteractiveState(groundLevelId, 0);
18
+ const queued = queueElevatorRequest(state, upperLevelId);
19
+ const duplicated = queueElevatorRequest(queued, upperLevelId);
20
+ expect(queued.queue).toEqual([upperLevelId]);
21
+ expect(queued.requestedStops).toEqual([upperLevelId]);
22
+ expect(duplicated.queue).toEqual([upperLevelId]);
23
+ expect(duplicated.requestedStops).toEqual([upperLevelId]);
24
+ });
25
+ test('opens doors only when the elevator is not moving', () => {
26
+ const idle = createElevatorInteractiveState(groundLevelId, 0);
27
+ const moving = { ...idle, phase: 'moving' };
28
+ expect(openElevatorDoorState(idle).phase).toBe('opening');
29
+ expect(openElevatorDoorState(moving)).toBe(moving);
30
+ });
31
+ test('moves to a queued level and clears the served request on arrival', () => {
32
+ const queued = queueElevatorRequest(createElevatorInteractiveState(groundLevelId, 0), upperLevelId);
33
+ const moving = stepElevatorRuntimeState({
34
+ defaultEntry: entries[0],
35
+ delta: 0.016,
36
+ elevator,
37
+ entries,
38
+ now: 0,
39
+ state: queued,
40
+ });
41
+ const arrived = stepElevatorRuntimeState({
42
+ defaultEntry: entries[0],
43
+ delta: 1,
44
+ elevator,
45
+ entries,
46
+ now: 100,
47
+ state: moving,
48
+ });
49
+ const open = stepElevatorRuntimeState({
50
+ defaultEntry: entries[0],
51
+ delta: 1,
52
+ elevator,
53
+ entries,
54
+ now: 200,
55
+ state: arrived,
56
+ });
57
+ expect(moving.phase).toBe('moving');
58
+ expect(arrived.currentLevelId).toBe(upperLevelId);
59
+ expect(arrived.phase).toBe('opening');
60
+ expect(open.phase).toBe('open');
61
+ expect(open.queue).toEqual([]);
62
+ expect(open.requestedStops).toEqual([upperLevelId]);
63
+ });
64
+ });
@@ -0,0 +1,19 @@
1
+ import type { AnyNode, ElevatorNode, LevelNode } from '../../schema';
2
+ export declare const DEFAULT_ELEVATOR_LEVEL_HEIGHT = 2.5;
3
+ export type ElevatorLevelEntry = {
4
+ id: LevelNode['id'];
5
+ label: string;
6
+ baseY: number;
7
+ };
8
+ export declare function resolveElevatorBuildingLevels(elevator: ElevatorNode, nodes: Record<string, AnyNode>): LevelNode[];
9
+ export declare function resolveElevatorServiceLevelIds(elevator: ElevatorNode, nodes: Record<string, AnyNode>): string[];
10
+ export declare function resolveElevatorServiceLevels(elevator: ElevatorNode, nodes: Record<string, AnyNode>): LevelNode[];
11
+ export declare function getElevatorLevelHeight(levelId: string, nodes: Record<string, AnyNode>): number;
12
+ export declare function resolveElevatorLevels(elevator: ElevatorNode, nodes: Record<string, AnyNode>): {
13
+ entries: ElevatorLevelEntry[];
14
+ defaultEntry: ElevatorLevelEntry | null;
15
+ shaftBaseY: number;
16
+ shaftTopY: number;
17
+ totalHeight: number;
18
+ };
19
+ //# sourceMappingURL=elevator-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elevator-service.d.ts","sourceRoot":"","sources":["../../../src/systems/elevator/elevator-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EAGP,YAAY,EACZ,SAAS,EAEV,MAAM,cAAc,CAAA;AAErB,eAAO,MAAM,6BAA6B,MAAM,CAAA;AAEhD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,EAAE,EAAE,SAAS,CAAC,IAAI,CAAC,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AA2BD,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,YAAY,EACtB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,SAAS,EAAE,CAEb;AAED,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,YAAY,EACtB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,MAAM,EAAE,CAEV;AAED,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,YAAY,EACtB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,SAAS,EAAE,CAsBb;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAoB9F;AAED,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,YAAY,EACtB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B;IACD,OAAO,EAAE,kBAAkB,EAAE,CAAA;IAC7B,YAAY,EAAE,kBAAkB,GAAG,IAAI,CAAA;IACvC,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;CACpB,CA0CA"}
@@ -0,0 +1,111 @@
1
+ export const DEFAULT_ELEVATOR_LEVEL_HEIGHT = 2.5;
2
+ function getBuildingLevels(elevator, nodes) {
3
+ const building = elevator.parentId && nodes[elevator.parentId]?.type === 'building'
4
+ ? nodes[elevator.parentId]
5
+ : null;
6
+ if (building?.type !== 'building')
7
+ return [];
8
+ return building.children
9
+ .map((childId) => nodes[childId])
10
+ .filter((node) => node?.type === 'level')
11
+ .sort((left, right) => left.level - right.level);
12
+ }
13
+ function findLevelIndex(levels, levelId) {
14
+ if (!levelId)
15
+ return -1;
16
+ return levels.findIndex((level) => level.id === levelId);
17
+ }
18
+ function getDefaultToIndex(levels, fromIndex) {
19
+ if (levels.length === 0)
20
+ return -1;
21
+ if (fromIndex < 0)
22
+ return Math.min(1, levels.length - 1);
23
+ return Math.min(fromIndex + 1, levels.length - 1);
24
+ }
25
+ export function resolveElevatorBuildingLevels(elevator, nodes) {
26
+ return getBuildingLevels(elevator, nodes);
27
+ }
28
+ export function resolveElevatorServiceLevelIds(elevator, nodes) {
29
+ return resolveElevatorServiceLevels(elevator, nodes).map((level) => level.id);
30
+ }
31
+ export function resolveElevatorServiceLevels(elevator, nodes) {
32
+ const levels = getBuildingLevels(elevator, nodes);
33
+ if (levels.length === 0)
34
+ return [];
35
+ const hasServiceBounds = Boolean(elevator.fromLevelId || elevator.toLevelId);
36
+ let legacyServedLevels = [];
37
+ if (!hasServiceBounds && elevator.servedLevelIds && elevator.servedLevelIds.length > 0) {
38
+ const servedIds = new Set(elevator.servedLevelIds);
39
+ legacyServedLevels = levels.filter((level) => servedIds.has(level.id));
40
+ }
41
+ const legacyFromLevelId = legacyServedLevels[0]?.id ?? null;
42
+ const legacyToLevelId = legacyServedLevels[legacyServedLevels.length - 1]?.id ?? null;
43
+ const explicitFromIndex = findLevelIndex(levels, elevator.fromLevelId ?? legacyFromLevelId);
44
+ const defaultFromIndex = findLevelIndex(levels, elevator.defaultLevelId);
45
+ const fromIndex = explicitFromIndex >= 0 ? explicitFromIndex : Math.max(defaultFromIndex, 0);
46
+ const toIndex = findLevelIndex(levels, elevator.toLevelId ?? legacyToLevelId);
47
+ const resolvedToIndex = toIndex >= 0 ? toIndex : getDefaultToIndex(levels, fromIndex);
48
+ const minIndex = Math.min(fromIndex, resolvedToIndex);
49
+ const maxIndex = Math.max(fromIndex, resolvedToIndex);
50
+ return levels.slice(minIndex, maxIndex + 1);
51
+ }
52
+ export function getElevatorLevelHeight(levelId, nodes) {
53
+ const level = nodes[levelId];
54
+ if (level?.type !== 'level')
55
+ return DEFAULT_ELEVATOR_LEVEL_HEIGHT;
56
+ let maxTop = 0;
57
+ for (const childId of level.children) {
58
+ const child = nodes[childId];
59
+ if (!child)
60
+ continue;
61
+ if (child.type === 'ceiling') {
62
+ const height = child.height ?? DEFAULT_ELEVATOR_LEVEL_HEIGHT;
63
+ if (height > maxTop)
64
+ maxTop = height;
65
+ }
66
+ else if (child.type === 'wall') {
67
+ const height = child.height ?? DEFAULT_ELEVATOR_LEVEL_HEIGHT;
68
+ if (height > maxTop)
69
+ maxTop = height;
70
+ }
71
+ }
72
+ return maxTop > 0 ? maxTop : DEFAULT_ELEVATOR_LEVEL_HEIGHT;
73
+ }
74
+ export function resolveElevatorLevels(elevator, nodes) {
75
+ const allLevels = resolveElevatorBuildingLevels(elevator, nodes);
76
+ const baseYByLevelId = new Map();
77
+ let cumulativeY = 0;
78
+ for (const level of allLevels) {
79
+ baseYByLevelId.set(level.id, cumulativeY);
80
+ cumulativeY += getElevatorLevelHeight(level.id, nodes);
81
+ }
82
+ const serviceLevels = resolveElevatorServiceLevels(elevator, nodes);
83
+ const entries = serviceLevels.map((level) => ({
84
+ id: level.id,
85
+ label: String(level.level),
86
+ baseY: baseYByLevelId.get(level.id) ?? 0,
87
+ }));
88
+ const defaultEntry = entries.find((entry) => entry.id === elevator.defaultLevelId) ??
89
+ entries.find((entry) => entry.id === elevator.fromLevelId) ??
90
+ entries[0] ??
91
+ null;
92
+ const firstServedLevel = serviceLevels[0] ?? null;
93
+ const lastServedLevel = serviceLevels[serviceLevels.length - 1] ?? null;
94
+ const shaftBaseY = firstServedLevel ? (baseYByLevelId.get(firstServedLevel.id) ?? 0) : 0;
95
+ const lastServedIndex = lastServedLevel
96
+ ? allLevels.findIndex((level) => level.id === lastServedLevel.id)
97
+ : -1;
98
+ const nextLevel = lastServedIndex >= 0 ? allLevels[lastServedIndex + 1] : null;
99
+ const shaftTopY = nextLevel
100
+ ? (baseYByLevelId.get(nextLevel.id) ?? cumulativeY)
101
+ : lastServedLevel
102
+ ? cumulativeY
103
+ : elevator.cabHeight + 0.3;
104
+ return {
105
+ entries,
106
+ defaultEntry,
107
+ shaftBaseY,
108
+ shaftTopY,
109
+ totalHeight: Math.max(shaftTopY - shaftBaseY, elevator.cabHeight + 0.3),
110
+ };
111
+ }
@@ -0,0 +1,12 @@
1
+ import type { FenceNode } from '../../schema';
2
+ import type { Point2D } from '../wall/wall-mitering';
3
+ type CurveFrame = {
4
+ point: Point2D;
5
+ tangent: Point2D;
6
+ normal: Point2D;
7
+ };
8
+ export declare function getFenceCenterlineFrameAt(fence: FenceNode, t: number): CurveFrame;
9
+ export declare function sampleFenceCenterline(fence: FenceNode, segments?: number): Point2D[];
10
+ export declare function getFenceCenterlineLength(fence: FenceNode, segments?: number): number;
11
+ export {};
12
+ //# sourceMappingURL=fence-centerline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fence-centerline.d.ts","sourceRoot":"","sources":["../../../src/systems/fence/fence-centerline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE7C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAA;AAqBpD,KAAK,UAAU,GAAG;IAChB,KAAK,EAAE,OAAO,CAAA;IACd,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,OAAO,CAAA;CAChB,CAAA;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,GAAG,UAAU,CAKjF;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,SAAS,EAChB,QAAQ,SAA0B,GACjC,OAAO,EAAE,CASX;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,SAAS,EAChB,QAAQ,SAA0B,GACjC,MAAM,CAOR"}
@@ -0,0 +1,37 @@
1
+ import { getWallCurveFrameAt, getWallCurveLength, sampleWallCenterline } from '../wall/wall-curve';
2
+ import { getFenceSplineFrameAt, getFenceSplineLength, isSplineFence, sampleFenceSpline, } from './fence-spline';
3
+ /**
4
+ * Unified fence centerline accessors. A fence is either:
5
+ * - a spline fence (`path` of >= 2 control points) → smooth Catmull-Rom, or
6
+ * - a straight / single-arc fence (`start`/`end` + optional `curveOffset`).
7
+ *
8
+ * These wrappers branch on `isSplineFence` and return the SAME shapes the wall
9
+ * arc helpers return, so every consumer (3D geometry, 2D floor-plan, length,
10
+ * handles) can sample the centerline without caring which kind it is. Wall arc
11
+ * math in `wall-curve.ts` is untouched — walls never carry a `path`.
12
+ */
13
+ const DEFAULT_SAMPLE_SEGMENTS = 96;
14
+ export function getFenceCenterlineFrameAt(fence, t) {
15
+ if (isSplineFence(fence) && fence.path) {
16
+ return getFenceSplineFrameAt(fence.path, t, fence.tangents);
17
+ }
18
+ return getWallCurveFrameAt(fence, t);
19
+ }
20
+ export function sampleFenceCenterline(fence, segments = DEFAULT_SAMPLE_SEGMENTS) {
21
+ if (isSplineFence(fence) && fence.path) {
22
+ // Spread the requested sample budget across the spans so a long path still
23
+ // reads smoothly without exploding the point count.
24
+ const spanCount = Math.max(1, fence.path.length - 1);
25
+ const perSpan = Math.max(2, Math.ceil(segments / spanCount));
26
+ return sampleFenceSpline(fence.path, fence.tangents, perSpan);
27
+ }
28
+ return sampleWallCenterline(fence, segments);
29
+ }
30
+ export function getFenceCenterlineLength(fence, segments = DEFAULT_SAMPLE_SEGMENTS) {
31
+ if (isSplineFence(fence) && fence.path) {
32
+ const spanCount = Math.max(1, fence.path.length - 1);
33
+ const perSpan = Math.max(2, Math.ceil(segments / spanCount));
34
+ return getFenceSplineLength(fence.path, fence.tangents, perSpan);
35
+ }
36
+ return getWallCurveLength(fence, segments);
37
+ }
@@ -0,0 +1,39 @@
1
+ import type { FenceNode } from '../../schema';
2
+ import type { Point2D } from '../wall/wall-mitering';
3
+ type FenceSplineLike = Pick<FenceNode, 'path'>;
4
+ type TangentList = ReadonlyArray<readonly [number, number] | null> | undefined;
5
+ export declare function isSplineFence(fence: FenceSplineLike): boolean;
6
+ type CurveFrame = {
7
+ point: Point2D;
8
+ tangent: Point2D;
9
+ normal: Point2D;
10
+ };
11
+ /**
12
+ * OUT-handle offset vector for control point `index` — the stored tangent if
13
+ * the user has adjusted it, otherwise the automatic distance-aware tangent
14
+ * (endpoints duplicate the neighbour so the ends stay tangent to their single
15
+ * span). The IN handle is the negation of this.
16
+ *
17
+ * Exported so the editing UI can draw the tangent line / handle dots at the
18
+ * right place even before the user has dragged them.
19
+ */
20
+ export declare function getFenceControlHandle(path: ReadonlyArray<readonly [number, number]>, tangents: TangentList, index: number): Point2D;
21
+ export declare function getTwoPointFenceCurveTangents(path: ReadonlyArray<readonly [number, number]>): Array<[number, number] | null> | undefined;
22
+ /**
23
+ * Sample the spline centerline into a polyline. Control points are honored as
24
+ * on-curve anchors; `segmentsPerSpan` controls smoothness between them.
25
+ * Returns `(segmentsPerSpan * spanCount) + 1` points, first == path[0],
26
+ * last == path[-1].
27
+ */
28
+ export declare function sampleFenceSpline(path: ReadonlyArray<readonly [number, number]>, tangents?: TangentList, segmentsPerSpan?: number): Point2D[];
29
+ /**
30
+ * Frame (point + tangent + normal) at parameter `t` in [0, 1] along the spline
31
+ * centerline. Same return shape as `getWallCurveFrameAt` so it is a drop-in for
32
+ * the arc branch. `t` is uniform over the sampled polyline (arc length is not
33
+ * reparameterised — adequate for marching posts / rails and far cheaper).
34
+ */
35
+ export declare function getFenceSplineFrameAt(path: ReadonlyArray<readonly [number, number]>, t: number, tangents?: TangentList, segmentsPerSpan?: number): CurveFrame;
36
+ /** Total polyline length of the sampled spline centerline. */
37
+ export declare function getFenceSplineLength(path: ReadonlyArray<readonly [number, number]>, tangents?: TangentList, segmentsPerSpan?: number): number;
38
+ export {};
39
+ //# sourceMappingURL=fence-spline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fence-spline.d.ts","sourceRoot":"","sources":["../../../src/systems/fence/fence-spline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAA;AA0BpD,KAAK,eAAe,GAAG,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;AAC9C,KAAK,WAAW,GAAG,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,SAAS,CAAA;AAE9E,wBAAgB,aAAa,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAE7D;AAED,KAAK,UAAU,GAAG;IAChB,KAAK,EAAE,OAAO,CAAA;IACd,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,OAAO,CAAA;CAChB,CAAA;AAkBD;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAC9C,QAAQ,EAAE,WAAW,EACrB,KAAK,EAAE,MAAM,GACZ,OAAO,CAiCT;AAED,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAC7C,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,SAAS,CAyB5C;AAkBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAC9C,QAAQ,CAAC,EAAE,WAAW,EACtB,eAAe,SAA4B,GAC1C,OAAO,EAAE,CA0BX;AA4CD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAC9C,CAAC,EAAE,MAAM,EACT,QAAQ,CAAC,EAAE,WAAW,EACtB,eAAe,SAA4B,GAC1C,UAAU,CAEZ;AAED,8DAA8D;AAC9D,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAC9C,QAAQ,CAAC,EAAE,WAAW,EACtB,eAAe,SAA4B,GAC1C,MAAM,CAOR"}