@pascal-app/core 0.9.2 → 1.0.0-beta.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 (339) hide show
  1. package/README.md +17 -10
  2. package/dist/events/bus.d.ts +21 -2
  3. package/dist/events/bus.d.ts.map +1 -1
  4. package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts +17 -1
  5. package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts.map +1 -1
  6. package/dist/hooks/spatial-grid/floor-placed-elevation.js +61 -8
  7. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts +116 -66
  8. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts.map +1 -1
  9. package/dist/hooks/spatial-grid/spatial-grid-manager.js +319 -441
  10. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts +46 -1
  11. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts.map +1 -1
  12. package/dist/hooks/spatial-grid/spatial-grid-sync.js +204 -12
  13. package/dist/hooks/spatial-grid/support-host-id.d.ts +3 -0
  14. package/dist/hooks/spatial-grid/support-host-id.d.ts.map +1 -0
  15. package/dist/hooks/spatial-grid/support-host-id.js +2 -0
  16. package/dist/hooks/spatial-grid/support-host-patch.d.ts +51 -0
  17. package/dist/hooks/spatial-grid/support-host-patch.d.ts.map +1 -0
  18. package/dist/hooks/spatial-grid/support-host-patch.js +164 -0
  19. package/dist/index.d.ts +23 -11
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +22 -10
  22. package/dist/lib/measurement-geometry.d.ts +4 -0
  23. package/dist/lib/measurement-geometry.d.ts.map +1 -1
  24. package/dist/lib/measurement-geometry.js +27 -10
  25. package/dist/lib/slab-polygon.d.ts.map +1 -1
  26. package/dist/lib/slab-polygon.js +33 -1
  27. package/dist/lib/space-detection.d.ts +15 -4
  28. package/dist/lib/space-detection.d.ts.map +1 -1
  29. package/dist/lib/space-detection.js +232 -91
  30. package/dist/lib/terrain-brush.d.ts +163 -0
  31. package/dist/lib/terrain-brush.d.ts.map +1 -0
  32. package/dist/lib/terrain-brush.js +359 -0
  33. package/dist/lib/terrain-codec.d.ts +51 -0
  34. package/dist/lib/terrain-codec.d.ts.map +1 -0
  35. package/dist/lib/terrain-codec.js +167 -0
  36. package/dist/lib/terrain-field.d.ts +150 -0
  37. package/dist/lib/terrain-field.d.ts.map +1 -0
  38. package/dist/lib/terrain-field.js +248 -0
  39. package/dist/lib/terrain-raycast.d.ts +44 -0
  40. package/dist/lib/terrain-raycast.d.ts.map +1 -0
  41. package/dist/lib/terrain-raycast.js +188 -0
  42. package/dist/lib/terrain-source.d.ts +60 -0
  43. package/dist/lib/terrain-source.d.ts.map +1 -0
  44. package/dist/lib/terrain-source.js +90 -0
  45. package/dist/lib/terrain-support.d.ts +85 -0
  46. package/dist/lib/terrain-support.d.ts.map +1 -0
  47. package/dist/lib/terrain-support.js +218 -0
  48. package/dist/lib/zone-quantities.d.ts +1 -1
  49. package/dist/lib/zone-quantities.d.ts.map +1 -1
  50. package/dist/lib/zone-quantities.js +311 -66
  51. package/dist/material-library.d.ts +9 -1
  52. package/dist/material-library.d.ts.map +1 -1
  53. package/dist/material-library.js +56 -4
  54. package/dist/registry/handles.d.ts +16 -1
  55. package/dist/registry/handles.d.ts.map +1 -1
  56. package/dist/registry/index.d.ts +1 -1
  57. package/dist/registry/index.d.ts.map +1 -1
  58. package/dist/registry/subtree.d.ts.map +1 -1
  59. package/dist/registry/subtree.js +5 -2
  60. package/dist/registry/types.d.ts +83 -1
  61. package/dist/registry/types.d.ts.map +1 -1
  62. package/dist/schema/index.d.ts +6 -3
  63. package/dist/schema/index.d.ts.map +1 -1
  64. package/dist/schema/index.js +6 -3
  65. package/dist/schema/nodes/cabinet.d.ts +2 -0
  66. package/dist/schema/nodes/cabinet.d.ts.map +1 -1
  67. package/dist/schema/nodes/cabinet.js +4 -2
  68. package/dist/schema/nodes/ceiling.d.ts +1 -1
  69. package/dist/schema/nodes/ceiling.d.ts.map +1 -1
  70. package/dist/schema/nodes/ceiling.js +7 -1
  71. package/dist/schema/nodes/column.d.ts +1 -0
  72. package/dist/schema/nodes/column.d.ts.map +1 -1
  73. package/dist/schema/nodes/column.js +2 -0
  74. package/dist/schema/nodes/construction-dimension.d.ts +195 -0
  75. package/dist/schema/nodes/construction-dimension.d.ts.map +1 -0
  76. package/dist/schema/nodes/construction-dimension.js +151 -0
  77. package/dist/schema/nodes/door.d.ts +29 -0
  78. package/dist/schema/nodes/door.d.ts.map +1 -1
  79. package/dist/schema/nodes/door.js +20 -0
  80. package/dist/schema/nodes/duct-terminal.d.ts +1 -0
  81. package/dist/schema/nodes/duct-terminal.d.ts.map +1 -1
  82. package/dist/schema/nodes/duct-terminal.js +2 -0
  83. package/dist/schema/nodes/fence.d.ts +2 -0
  84. package/dist/schema/nodes/fence.d.ts.map +1 -1
  85. package/dist/schema/nodes/fence.js +8 -0
  86. package/dist/schema/nodes/hvac-equipment.d.ts +1 -0
  87. package/dist/schema/nodes/hvac-equipment.d.ts.map +1 -1
  88. package/dist/schema/nodes/hvac-equipment.js +2 -0
  89. package/dist/schema/nodes/item.d.ts +1 -0
  90. package/dist/schema/nodes/item.d.ts.map +1 -1
  91. package/dist/schema/nodes/item.js +13 -0
  92. package/dist/schema/nodes/level.d.ts +2 -1
  93. package/dist/schema/nodes/level.d.ts.map +1 -1
  94. package/dist/schema/nodes/level.js +12 -33
  95. package/dist/schema/nodes/shelf.d.ts +1 -0
  96. package/dist/schema/nodes/shelf.d.ts.map +1 -1
  97. package/dist/schema/nodes/shelf.js +2 -0
  98. package/dist/schema/nodes/site.d.ts +9 -0
  99. package/dist/schema/nodes/site.d.ts.map +1 -1
  100. package/dist/schema/nodes/site.js +8 -6
  101. package/dist/schema/nodes/slab.d.ts +5 -0
  102. package/dist/schema/nodes/slab.d.ts.map +1 -1
  103. package/dist/schema/nodes/slab.js +14 -2
  104. package/dist/schema/nodes/spawn.d.ts +1 -0
  105. package/dist/schema/nodes/spawn.d.ts.map +1 -1
  106. package/dist/schema/nodes/spawn.js +2 -0
  107. package/dist/schema/nodes/stair.d.ts +3 -1
  108. package/dist/schema/nodes/stair.d.ts.map +1 -1
  109. package/dist/schema/nodes/stair.js +8 -1
  110. package/dist/schema/nodes/structural-grid.d.ts +27 -0
  111. package/dist/schema/nodes/structural-grid.d.ts.map +1 -0
  112. package/dist/schema/nodes/structural-grid.js +17 -0
  113. package/dist/schema/nodes/wall.d.ts +5 -2
  114. package/dist/schema/nodes/wall.d.ts.map +1 -1
  115. package/dist/schema/nodes/wall.js +13 -4
  116. package/dist/schema/nodes/window.d.ts +29 -0
  117. package/dist/schema/nodes/window.d.ts.map +1 -1
  118. package/dist/schema/nodes/window.js +18 -0
  119. package/dist/schema/nodes/zone.d.ts +20 -0
  120. package/dist/schema/nodes/zone.d.ts.map +1 -1
  121. package/dist/schema/nodes/zone.js +15 -0
  122. package/dist/schema/terrain.d.ts +28 -0
  123. package/dist/schema/terrain.d.ts.map +1 -0
  124. package/dist/schema/terrain.js +30 -0
  125. package/dist/schema/types.d.ts +211 -3
  126. package/dist/schema/types.d.ts.map +1 -1
  127. package/dist/schema/types.js +4 -0
  128. package/dist/services/__fixtures__/wall-plane-top-boundary-repro.d.ts +80 -0
  129. package/dist/services/__fixtures__/wall-plane-top-boundary-repro.d.ts.map +1 -0
  130. package/dist/services/__fixtures__/wall-plane-top-boundary-repro.js +89 -0
  131. package/dist/services/index.d.ts +2 -1
  132. package/dist/services/index.d.ts.map +1 -1
  133. package/dist/services/index.js +2 -1
  134. package/dist/services/level-height.d.ts +8 -9
  135. package/dist/services/level-height.d.ts.map +1 -1
  136. package/dist/services/level-height.js +48 -16
  137. package/dist/services/storey.d.ts +103 -0
  138. package/dist/services/storey.d.ts.map +1 -0
  139. package/dist/services/storey.js +296 -0
  140. package/dist/store/actions/node-actions.d.ts.map +1 -1
  141. package/dist/store/actions/node-actions.js +47 -3
  142. package/dist/store/history-control.d.ts +20 -0
  143. package/dist/store/history-control.d.ts.map +1 -1
  144. package/dist/store/history-control.js +110 -13
  145. package/dist/store/use-live-terrain.d.ts +65 -0
  146. package/dist/store/use-live-terrain.d.ts.map +1 -0
  147. package/dist/store/use-live-terrain.js +31 -0
  148. package/dist/store/use-live-transforms.d.ts +8 -0
  149. package/dist/store/use-live-transforms.d.ts.map +1 -1
  150. package/dist/store/use-scene.d.ts +31 -2
  151. package/dist/store/use-scene.d.ts.map +1 -1
  152. package/dist/store/use-scene.js +638 -8
  153. package/dist/systems/elevator/elevator-opening-system.d.ts +1 -0
  154. package/dist/systems/elevator/elevator-opening-system.d.ts.map +1 -1
  155. package/dist/systems/elevator/elevator-opening-system.js +27 -21
  156. package/dist/systems/elevator/elevator-service.d.ts +0 -2
  157. package/dist/systems/elevator/elevator-service.d.ts.map +1 -1
  158. package/dist/systems/elevator/elevator-service.js +2 -24
  159. package/dist/systems/slab/slab-placement.d.ts +11 -0
  160. package/dist/systems/slab/slab-placement.d.ts.map +1 -0
  161. package/dist/systems/slab/slab-placement.js +14 -0
  162. package/dist/systems/slab/slab-support.d.ts +150 -0
  163. package/dist/systems/slab/slab-support.d.ts.map +1 -0
  164. package/dist/systems/slab/slab-support.js +575 -0
  165. package/dist/systems/stair/stair-opening-preview.d.ts +1060 -935
  166. package/dist/systems/stair/stair-opening-preview.d.ts.map +1 -1
  167. package/dist/systems/stair/stair-opening-sync.d.ts.map +1 -1
  168. package/dist/systems/stair/stair-opening-sync.js +18 -15
  169. package/dist/systems/stair/stair-opening-system.d.ts.map +1 -1
  170. package/dist/systems/stair/stair-opening-system.js +32 -4
  171. package/dist/systems/stair/stair-rise.d.ts +22 -0
  172. package/dist/systems/stair/stair-rise.d.ts.map +1 -0
  173. package/dist/systems/stair/stair-rise.js +79 -0
  174. package/dist/systems/wall/wall-curve.d.ts +10 -0
  175. package/dist/systems/wall/wall-curve.d.ts.map +1 -1
  176. package/dist/systems/wall/wall-curve.js +1 -1
  177. package/dist/systems/wall/wall-mitering.js +6 -6
  178. package/dist/systems/wall/wall-top.d.ts +40 -0
  179. package/dist/systems/wall/wall-top.d.ts.map +1 -0
  180. package/dist/systems/wall/wall-top.js +46 -0
  181. package/dist/utils/clone-scene-graph.d.ts.map +1 -1
  182. package/dist/utils/clone-scene-graph.js +34 -3
  183. package/dist/utils/heal-scene-graph.d.ts +1 -1
  184. package/dist/utils/heal-scene-graph.d.ts.map +1 -1
  185. package/dist/utils/heal-scene-graph.js +25 -9
  186. package/dist/validation/validate-build-json.d.ts +2 -0
  187. package/dist/validation/validate-build-json.d.ts.map +1 -1
  188. package/dist/validation/validate-build-json.js +59 -3
  189. package/package.json +2 -2
  190. package/dist/hooks/scene-registry/scene-registry.test.d.ts +0 -2
  191. package/dist/hooks/scene-registry/scene-registry.test.d.ts.map +0 -1
  192. package/dist/hooks/scene-registry/scene-registry.test.js +0 -26
  193. package/dist/hooks/spatial-grid/floor-placed-elevation.test.d.ts +0 -2
  194. package/dist/hooks/spatial-grid/floor-placed-elevation.test.d.ts.map +0 -1
  195. package/dist/hooks/spatial-grid/floor-placed-elevation.test.js +0 -366
  196. package/dist/hooks/spatial-grid/wall-slab-overlap.test.d.ts +0 -2
  197. package/dist/hooks/spatial-grid/wall-slab-overlap.test.d.ts.map +0 -1
  198. package/dist/hooks/spatial-grid/wall-slab-overlap.test.js +0 -363
  199. package/dist/lib/measurement-geometry.test.d.ts +0 -2
  200. package/dist/lib/measurement-geometry.test.d.ts.map +0 -1
  201. package/dist/lib/measurement-geometry.test.js +0 -102
  202. package/dist/lib/slab-polygon.test.d.ts +0 -2
  203. package/dist/lib/slab-polygon.test.d.ts.map +0 -1
  204. package/dist/lib/slab-polygon.test.js +0 -635
  205. package/dist/lib/space-detection-pause.test.d.ts +0 -2
  206. package/dist/lib/space-detection-pause.test.d.ts.map +0 -1
  207. package/dist/lib/space-detection-pause.test.js +0 -42
  208. package/dist/lib/space-detection.test.d.ts +0 -2
  209. package/dist/lib/space-detection.test.d.ts.map +0 -1
  210. package/dist/lib/space-detection.test.js +0 -376
  211. package/dist/lib/zone-quantities.test.d.ts +0 -2
  212. package/dist/lib/zone-quantities.test.d.ts.map +0 -1
  213. package/dist/lib/zone-quantities.test.js +0 -82
  214. package/dist/registry/registry.test.d.ts +0 -2
  215. package/dist/registry/registry.test.d.ts.map +0 -1
  216. package/dist/registry/registry.test.js +0 -196
  217. package/dist/registry/relations-resolver.test.d.ts +0 -2
  218. package/dist/registry/relations-resolver.test.d.ts.map +0 -1
  219. package/dist/registry/relations-resolver.test.js +0 -183
  220. package/dist/registry/scene-api.test.d.ts +0 -2
  221. package/dist/registry/scene-api.test.d.ts.map +0 -1
  222. package/dist/registry/scene-api.test.js +0 -183
  223. package/dist/registry/subtree.test.d.ts +0 -2
  224. package/dist/registry/subtree.test.d.ts.map +0 -1
  225. package/dist/registry/subtree.test.js +0 -163
  226. package/dist/schema/asset-url.test.d.ts +0 -2
  227. package/dist/schema/asset-url.test.d.ts.map +0 -1
  228. package/dist/schema/asset-url.test.js +0 -134
  229. package/dist/schema/material.test.d.ts +0 -2
  230. package/dist/schema/material.test.d.ts.map +0 -1
  231. package/dist/schema/material.test.js +0 -43
  232. package/dist/schema/nodes/measurement.test.d.ts +0 -2
  233. package/dist/schema/nodes/measurement.test.d.ts.map +0 -1
  234. package/dist/schema/nodes/measurement.test.js +0 -139
  235. package/dist/schema/nodes/ridge-vent-defaults.test.d.ts +0 -2
  236. package/dist/schema/nodes/ridge-vent-defaults.test.d.ts.map +0 -1
  237. package/dist/schema/nodes/ridge-vent-defaults.test.js +0 -205
  238. package/dist/schema/nodes/roof-segment-shape.test.d.ts +0 -2
  239. package/dist/schema/nodes/roof-segment-shape.test.d.ts.map +0 -1
  240. package/dist/schema/nodes/roof-segment-shape.test.js +0 -175
  241. package/dist/schema/nodes/roof-segment-surface.test.d.ts +0 -2
  242. package/dist/schema/nodes/roof-segment-surface.test.d.ts.map +0 -1
  243. package/dist/schema/nodes/roof-segment-surface.test.js +0 -48
  244. package/dist/schema/nodes/roof-segment-trim.test.d.ts +0 -2
  245. package/dist/schema/nodes/roof-segment-trim.test.d.ts.map +0 -1
  246. package/dist/schema/nodes/roof-segment-trim.test.js +0 -107
  247. package/dist/schema/nodes/roof-segment-walls.test.d.ts +0 -2
  248. package/dist/schema/nodes/roof-segment-walls.test.d.ts.map +0 -1
  249. package/dist/schema/nodes/roof-segment-walls.test.js +0 -92
  250. package/dist/schema/nodes/wall.test.d.ts +0 -2
  251. package/dist/schema/nodes/wall.test.d.ts.map +0 -1
  252. package/dist/schema/nodes/wall.test.js +0 -208
  253. package/dist/services/alignment-anchors.test.d.ts +0 -2
  254. package/dist/services/alignment-anchors.test.d.ts.map +0 -1
  255. package/dist/services/alignment-anchors.test.js +0 -383
  256. package/dist/services/alignment.test.d.ts +0 -2
  257. package/dist/services/alignment.test.d.ts.map +0 -1
  258. package/dist/services/alignment.test.js +0 -92
  259. package/dist/services/drag-session.test.d.ts +0 -2
  260. package/dist/services/drag-session.test.d.ts.map +0 -1
  261. package/dist/services/drag-session.test.js +0 -219
  262. package/dist/services/hosting.test.d.ts +0 -2
  263. package/dist/services/hosting.test.d.ts.map +0 -1
  264. package/dist/services/hosting.test.js +0 -230
  265. package/dist/services/movement.test.d.ts +0 -2
  266. package/dist/services/movement.test.d.ts.map +0 -1
  267. package/dist/services/movement.test.js +0 -133
  268. package/dist/services/opening-guides.test.d.ts +0 -2
  269. package/dist/services/opening-guides.test.d.ts.map +0 -1
  270. package/dist/services/opening-guides.test.js +0 -208
  271. package/dist/services/port-connectivity.test.d.ts +0 -2
  272. package/dist/services/port-connectivity.test.d.ts.map +0 -1
  273. package/dist/services/port-connectivity.test.js +0 -297
  274. package/dist/services/riser-diagram.test.d.ts +0 -2
  275. package/dist/services/riser-diagram.test.d.ts.map +0 -1
  276. package/dist/services/riser-diagram.test.js +0 -66
  277. package/dist/services/single-undo-dance.test.d.ts +0 -2
  278. package/dist/services/single-undo-dance.test.d.ts.map +0 -1
  279. package/dist/services/single-undo-dance.test.js +0 -210
  280. package/dist/services/snap.test.d.ts +0 -2
  281. package/dist/services/snap.test.d.ts.map +0 -1
  282. package/dist/services/snap.test.js +0 -137
  283. package/dist/services/system-graph.test.d.ts +0 -2
  284. package/dist/services/system-graph.test.d.ts.map +0 -1
  285. package/dist/services/system-graph.test.js +0 -138
  286. package/dist/services/validate-dwv.test.d.ts +0 -2
  287. package/dist/services/validate-dwv.test.d.ts.map +0 -1
  288. package/dist/services/validate-dwv.test.js +0 -109
  289. package/dist/store/actions/node-mutation-sanitize.test.d.ts +0 -2
  290. package/dist/store/actions/node-mutation-sanitize.test.d.ts.map +0 -1
  291. package/dist/store/actions/node-mutation-sanitize.test.js +0 -147
  292. package/dist/store/actions/reparent.test.d.ts +0 -2
  293. package/dist/store/actions/reparent.test.d.ts.map +0 -1
  294. package/dist/store/actions/reparent.test.js +0 -212
  295. package/dist/store/actions/ridge-vent-update.test.d.ts +0 -2
  296. package/dist/store/actions/ridge-vent-update.test.d.ts.map +0 -1
  297. package/dist/store/actions/ridge-vent-update.test.js +0 -264
  298. package/dist/store/use-scene-dirty-tracking.test.d.ts +0 -2
  299. package/dist/store/use-scene-dirty-tracking.test.d.ts.map +0 -1
  300. package/dist/store/use-scene-dirty-tracking.test.js +0 -68
  301. package/dist/store/use-scene-elevator-migration.test.d.ts +0 -2
  302. package/dist/store/use-scene-elevator-migration.test.d.ts.map +0 -1
  303. package/dist/store/use-scene-elevator-migration.test.js +0 -109
  304. package/dist/store/use-scene-measurement-roundtrip.test.d.ts +0 -2
  305. package/dist/store/use-scene-measurement-roundtrip.test.d.ts.map +0 -1
  306. package/dist/store/use-scene-measurement-roundtrip.test.js +0 -97
  307. package/dist/store/use-scene-plugins.test.d.ts +0 -2
  308. package/dist/store/use-scene-plugins.test.d.ts.map +0 -1
  309. package/dist/store/use-scene-plugins.test.js +0 -51
  310. package/dist/store/use-scene-wall-slot-migration.test.d.ts +0 -2
  311. package/dist/store/use-scene-wall-slot-migration.test.d.ts.map +0 -1
  312. package/dist/store/use-scene-wall-slot-migration.test.js +0 -210
  313. package/dist/store/use-scene-window-migration.test.d.ts +0 -2
  314. package/dist/store/use-scene-window-migration.test.d.ts.map +0 -1
  315. package/dist/store/use-scene-window-migration.test.js +0 -85
  316. package/dist/systems/elevator/elevator-opening-sync.test.d.ts +0 -2
  317. package/dist/systems/elevator/elevator-opening-sync.test.d.ts.map +0 -1
  318. package/dist/systems/elevator/elevator-opening-sync.test.js +0 -146
  319. package/dist/systems/elevator/elevator-runtime.test.d.ts +0 -2
  320. package/dist/systems/elevator/elevator-runtime.test.d.ts.map +0 -1
  321. package/dist/systems/elevator/elevator-runtime.test.js +0 -64
  322. package/dist/systems/fence/fence-spline.test.d.ts +0 -2
  323. package/dist/systems/fence/fence-spline.test.d.ts.map +0 -1
  324. package/dist/systems/fence/fence-spline.test.js +0 -136
  325. package/dist/systems/stair/stair-opening-preview.test.d.ts +0 -2
  326. package/dist/systems/stair/stair-opening-preview.test.d.ts.map +0 -1
  327. package/dist/systems/stair/stair-opening-preview.test.js +0 -80
  328. package/dist/systems/stair/stair-opening-sync.test.d.ts +0 -2
  329. package/dist/systems/stair/stair-opening-sync.test.d.ts.map +0 -1
  330. package/dist/systems/stair/stair-opening-sync.test.js +0 -485
  331. package/dist/systems/wall/wall-mitering.test.d.ts +0 -2
  332. package/dist/systems/wall/wall-mitering.test.d.ts.map +0 -1
  333. package/dist/systems/wall/wall-mitering.test.js +0 -63
  334. package/dist/utils/clone-scene-graph.test.d.ts +0 -2
  335. package/dist/utils/clone-scene-graph.test.d.ts.map +0 -1
  336. package/dist/utils/clone-scene-graph.test.js +0 -62
  337. package/dist/utils/heal-scene-graph.test.d.ts +0 -2
  338. package/dist/utils/heal-scene-graph.test.d.ts.map +0 -1
  339. package/dist/utils/heal-scene-graph.test.js +0 -88
@@ -1,175 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
- import { getDutchEndSlopeFaces, getDutchRoofShapeMetrics, getRoofModuleFaces, getRoofShapeRatios, } from './roof-segment-shape';
3
- describe('roof segment shape', () => {
4
- test('dutch shell is built as one complete non-duplicated face set', () => {
5
- const wh = 3;
6
- const rh = 2;
7
- const faces = getRoofModuleFaces({
8
- type: 'dutch',
9
- w: 8,
10
- d: 6,
11
- wh,
12
- rh,
13
- baseY: 0,
14
- insets: { dutchI: 1.5 },
15
- baseW: 8,
16
- baseD: 6,
17
- tanTheta: 1,
18
- shapeRatios: getRoofShapeRatios({
19
- dutchHipWidthRatio: 0.25,
20
- dutchHipHeightRatio: 0.5,
21
- dutchWaistLengthRatio: 1,
22
- dutchGabletRake: 0.25,
23
- }),
24
- });
25
- const peakY = wh + rh;
26
- const peakFaces = faces.filter((face) => face.some((vertex) => Math.abs(vertex.y - peakY) < 1e-6));
27
- const signatures = new Set(faces.map((face) => face
28
- .map((vertex) => `${vertex.x.toFixed(3)},${vertex.y.toFixed(3)},${vertex.z.toFixed(3)}`)
29
- .sort()
30
- .join('|')));
31
- expect(faces).toHaveLength(13);
32
- expect(peakFaces).toHaveLength(4);
33
- expect(signatures.size).toBe(faces.length);
34
- const lowerRightHip = faces.find((face) => face.some((vertex) => Math.abs(vertex.x - 2.75) < 1e-6 &&
35
- Math.abs(vertex.y - 4) < 1e-6 &&
36
- Math.abs(vertex.z - 1.5) < 1e-6));
37
- const gableTriangle = faces.find((face) => face.length === 3 &&
38
- face.some((vertex) => vertex.x === 2.5 && vertex.y === 5) &&
39
- face.some((vertex) => vertex.x === 2.5 && vertex.z === 1.5));
40
- expect(lowerRightHip).toBeDefined();
41
- expect(gableTriangle?.some((vertex) => vertex.x === 2.75)).toBe(false);
42
- });
43
- test('dutch depth-axis shell rotates the upper gable correctly', () => {
44
- const faces = getRoofModuleFaces({
45
- type: 'dutch',
46
- w: 6,
47
- d: 8,
48
- wh: 3,
49
- rh: 2,
50
- baseY: 0,
51
- insets: { dutchI: 1.5 },
52
- baseW: 6,
53
- baseD: 8,
54
- tanTheta: 1,
55
- shapeRatios: getRoofShapeRatios({
56
- dutchHipWidthRatio: 0.25,
57
- dutchHipHeightRatio: 0.5,
58
- dutchWaistLengthRatio: 1,
59
- dutchGabletRake: 0.25,
60
- }),
61
- });
62
- const peakFaces = faces.filter((face) => face.some((vertex) => vertex.y === 5));
63
- const ridgeOnlyOnZAxis = peakFaces
64
- .flat()
65
- .filter((vertex) => vertex.y === 5)
66
- .every((vertex) => vertex.x === 0);
67
- expect(peakFaces).toHaveLength(4);
68
- expect(ridgeOnlyOnZAxis).toBe(true);
69
- });
70
- test('dutch end hip slope extends inward until it meets the gable triangle', () => {
71
- const ratios = getRoofShapeRatios({
72
- dutchHipWidthRatio: 0.25,
73
- dutchHipHeightRatio: 0.5,
74
- dutchWaistLengthRatio: 1,
75
- dutchGabletRake: 0.75,
76
- });
77
- const metrics = getDutchRoofShapeMetrics({
78
- w: 8,
79
- d: 6,
80
- wh: 3,
81
- rh: 2,
82
- dutchI: 1.5,
83
- baseW: 8,
84
- baseD: 6,
85
- shapeRatios: ratios,
86
- });
87
- const faces = getRoofModuleFaces({
88
- type: 'dutch',
89
- w: 8,
90
- d: 6,
91
- wh: 3,
92
- rh: 2,
93
- baseY: 0,
94
- insets: { dutchI: 1.5 },
95
- baseW: 8,
96
- baseD: 6,
97
- tanTheta: 1,
98
- shapeRatios: ratios,
99
- dutchTopRakeThickness: 0.21,
100
- });
101
- expect(metrics?.innerWaistHalfX).toBe(2.5);
102
- expect(metrics?.outerWaistHalfX).toBe(3.25);
103
- // The end slope now clips against the rake's lower inner edge and is
104
- // reprojected back onto the end-slope plane, so the shorter top edge stays
105
- // planar instead of twisting.
106
- const hipTopFace = faces.find((face) => face.some((vertex) => Math.abs(vertex.x - 4) < 1e-6 &&
107
- Math.abs(vertex.y - 3) < 1e-6 &&
108
- Math.abs(vertex.z - 3) < 1e-6) &&
109
- face.some((vertex) => Math.abs(vertex.x - 3.0325) < 1e-6 &&
110
- Math.abs(vertex.y - 4.29) < 1e-6 &&
111
- Math.abs(vertex.z - 0.75) < 1e-6) &&
112
- face.some((vertex) => Math.abs(vertex.x - 3.0325) < 1e-6 &&
113
- Math.abs(vertex.y - 4.29) < 1e-6 &&
114
- Math.abs(vertex.z + 0.75) < 1e-6));
115
- const gableTriangle = faces.find((face) => face.length === 3 &&
116
- face.some((vertex) => vertex.x === 2.5 && vertex.y === 5) &&
117
- face.some((vertex) => vertex.x === 2.5 && vertex.z === 1.5));
118
- expect(hipTopFace).toBeDefined();
119
- expect(gableTriangle?.some((vertex) => vertex.x === 3.25)).toBe(false);
120
- });
121
- test('excludeDutchEndSlopes pulls the end slopes out into getDutchEndSlopeFaces', () => {
122
- const ratios = getRoofShapeRatios({
123
- dutchHipWidthRatio: 0.25,
124
- dutchHipHeightRatio: 0.5,
125
- dutchWaistLengthRatio: 1,
126
- dutchGabletRake: 0.75,
127
- });
128
- const args = {
129
- type: 'dutch',
130
- w: 8,
131
- d: 6,
132
- wh: 3,
133
- rh: 2,
134
- baseY: 0,
135
- insets: { dutchI: 1.5 },
136
- baseW: 8,
137
- baseD: 6,
138
- tanTheta: 1,
139
- shapeRatios: ratios,
140
- dutchTopRakeThickness: 0.21,
141
- };
142
- const full = getRoofModuleFaces(args);
143
- const shell = getRoofModuleFaces({ ...args, excludeDutchEndSlopes: true });
144
- const endSlopes = getDutchEndSlopeFaces({
145
- w: 8,
146
- d: 6,
147
- wh: 3,
148
- rh: 2,
149
- insets: { dutchI: 1.5 },
150
- baseW: 8,
151
- baseD: 6,
152
- shapeRatios: ratios,
153
- dutchTopRakeThickness: 0.21,
154
- });
155
- // The two end slopes leave the shell and reappear in the standalone set.
156
- expect(shell).toHaveLength(full.length - 2);
157
- expect(endSlopes).toHaveLength(2);
158
- // The standalone end slopes are 6-point polygons whose shorter top edge is
159
- // clipped to the rake's lower inner edge and then kept on the end-slope
160
- // plane.
161
- const endIsEndSlope = endSlopes.every((face) => face.length === 6 &&
162
- face.some((vertex) => Math.abs(Math.abs(vertex.x) - 3.25) < 1e-6) &&
163
- face.some((vertex) => Math.abs(Math.abs(vertex.x) - 3.0325) < 1e-6) &&
164
- face.some((vertex) => Math.abs(Math.abs(vertex.x) - 4) < 1e-6));
165
- expect(endIsEndSlope).toBe(true);
166
- // The removed faces are exactly the end slopes — the shell keeps every
167
- // other face the full module produced.
168
- const signature = (face) => face
169
- .map((vertex) => `${vertex.x.toFixed(3)},${vertex.y.toFixed(3)},${vertex.z.toFixed(3)}`)
170
- .join('|');
171
- const shellSigs = new Set(shell.map(signature));
172
- const removed = full.filter((face) => !shellSigs.has(signature(face)));
173
- expect(removed).toHaveLength(2);
174
- });
175
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=roof-segment-surface.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"roof-segment-surface.test.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/roof-segment-surface.test.ts"],"names":[],"mappings":""}
@@ -1,48 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
- import { getRoofSegmentSurfaceY, ROOF_SHAPE_DEFAULTS, RoofSegmentNode } from './roof-segment';
3
- describe('getRoofSegmentSurfaceY', () => {
4
- test('keeps the Dutch width-axis rake on the upper gable slope', () => {
5
- const segment = RoofSegmentNode.parse({
6
- roofType: 'dutch',
7
- width: 8,
8
- depth: 6,
9
- wallHeight: 3,
10
- pitch: 40,
11
- });
12
- const activeRh = getRoofSegmentSurfaceY(segment, 0, 0) - segment.wallHeight;
13
- const upperRise = activeRh * (1 - segment.dutchHipHeightRatio);
14
- const waistHalfZ = segment.depth / 2 - Math.min(segment.width, segment.depth) * segment.dutchHipWidthRatio;
15
- const availableRake = Math.max(0, segment.width / 2 -
16
- (segment.width / 2 - Math.min(segment.width, segment.depth) * segment.dutchHipWidthRatio) *
17
- segment.dutchWaistLengthRatio);
18
- const rakeReach = Math.min(segment.dutchGabletRake, availableRake * 0.98);
19
- const localX = (segment.width / 2 - Math.min(segment.width, segment.depth) * segment.dutchHipWidthRatio) *
20
- segment.dutchWaistLengthRatio +
21
- rakeReach * 0.5;
22
- const localZ = waistHalfZ * 0.5;
23
- const expected = segment.wallHeight + activeRh - localZ * (upperRise / waistHalfZ);
24
- expect(localX).toBeGreaterThan((segment.width / 2 - Math.min(segment.width, segment.depth) * segment.dutchHipWidthRatio) *
25
- segment.dutchWaistLengthRatio);
26
- expect(getRoofSegmentSurfaceY(segment, localX, localZ)).toBeCloseTo(expected, 6);
27
- });
28
- test('keeps the Dutch depth-axis rake on the upper gable slope', () => {
29
- const segment = RoofSegmentNode.parse({
30
- roofType: 'dutch',
31
- width: 6,
32
- depth: 8,
33
- wallHeight: 3,
34
- pitch: 40,
35
- });
36
- const activeRh = getRoofSegmentSurfaceY(segment, 0, 0) - segment.wallHeight;
37
- const upperRise = activeRh * (1 - segment.dutchHipHeightRatio);
38
- const waistHalfX = segment.width / 2 - Math.min(segment.width, segment.depth) * segment.dutchHipWidthRatio;
39
- const innerWaistHalfZ = (segment.depth / 2 - Math.min(segment.width, segment.depth) * segment.dutchHipWidthRatio) *
40
- segment.dutchWaistLengthRatio;
41
- const rakeReach = Math.min(segment.dutchGabletRake ?? ROOF_SHAPE_DEFAULTS.dutchGabletRake, Math.max(0, segment.depth / 2 - innerWaistHalfZ) * 0.98);
42
- const localX = waistHalfX * 0.5;
43
- const localZ = innerWaistHalfZ + rakeReach * 0.5;
44
- const expected = segment.wallHeight + activeRh - localX * (upperRise / waistHalfX);
45
- expect(localZ).toBeGreaterThan(innerWaistHalfZ);
46
- expect(getRoofSegmentSurfaceY(segment, localX, localZ)).toBeCloseTo(expected, 6);
47
- });
48
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=roof-segment-trim.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"roof-segment-trim.test.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/roof-segment-trim.test.ts"],"names":[],"mappings":""}
@@ -1,107 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
- import { getRoofSegmentVisibleTopBounds, normalizeRoofSegmentTrim, RoofSegmentNode, } from './roof-segment';
3
- describe('roof segment trim', () => {
4
- test('defaults legacy segments to no trim', () => {
5
- const segment = RoofSegmentNode.parse({
6
- id: 'rseg_test',
7
- type: 'roof-segment',
8
- });
9
- expect(segment.trim).toEqual({
10
- left: 0,
11
- right: 0,
12
- front: 0,
13
- back: 0,
14
- frontLeft: 0,
15
- frontRight: 0,
16
- backLeft: 0,
17
- backRight: 0,
18
- frontLeftX: 0,
19
- frontLeftZ: 0,
20
- frontRightX: 0,
21
- frontRightZ: 0,
22
- backLeftX: 0,
23
- backLeftZ: 0,
24
- backRightX: 0,
25
- backRightZ: 0,
26
- });
27
- });
28
- test('normalizes impossible side totals without inverting the footprint', () => {
29
- const trim = normalizeRoofSegmentTrim({
30
- width: 4,
31
- depth: 3,
32
- trim: { left: 3, right: 3, front: 2, back: 2 },
33
- });
34
- expect(trim.left + trim.right).toBeCloseTo(3.9);
35
- expect(trim.front + trim.back).toBeCloseTo(2.9);
36
- });
37
- test('visible top bounds respect asymmetric trims', () => {
38
- const segment = RoofSegmentNode.parse({
39
- id: 'rseg_test',
40
- type: 'roof-segment',
41
- width: 8,
42
- depth: 6,
43
- overhang: 0,
44
- wallThickness: 0,
45
- shingleThickness: 0,
46
- trim: { left: 1, right: 2, front: 0, back: 0 },
47
- });
48
- const bounds = getRoofSegmentVisibleTopBounds(segment);
49
- expect(bounds.minX).toBeCloseTo(-3);
50
- expect(bounds.maxX).toBeCloseTo(2);
51
- expect(bounds.width).toBeCloseTo(5);
52
- });
53
- test('visible top bounds stay finite for legacy partial segments', () => {
54
- const bounds = getRoofSegmentVisibleTopBounds({
55
- id: 'rseg_legacy',
56
- type: 'roof-segment',
57
- roofType: 'gable',
58
- trim: { left: 1 },
59
- });
60
- expect(Number.isFinite(bounds.minX)).toBe(true);
61
- expect(Number.isFinite(bounds.maxX)).toBe(true);
62
- expect(Number.isFinite(bounds.minZ)).toBe(true);
63
- expect(Number.isFinite(bounds.maxZ)).toBe(true);
64
- expect(Number.isFinite(bounds.width)).toBe(true);
65
- expect(Number.isFinite(bounds.depth)).toBe(true);
66
- });
67
- test('diagonal trims can shorten the ridge span', () => {
68
- const segment = RoofSegmentNode.parse({
69
- id: 'rseg_test',
70
- type: 'roof-segment',
71
- width: 8,
72
- depth: 6,
73
- overhang: 0,
74
- wallThickness: 0,
75
- shingleThickness: 0,
76
- trim: { left: 0, right: 0, front: 0, back: 0, frontLeft: 4, backRight: 4 },
77
- });
78
- const bounds = getRoofSegmentVisibleTopBounds(segment);
79
- expect(bounds.minX).toBeCloseTo(-3);
80
- expect(bounds.maxX).toBeCloseTo(3);
81
- expect(bounds.width).toBeCloseTo(6);
82
- });
83
- test('diagonal trims support independent width and depth endpoints', () => {
84
- const segment = RoofSegmentNode.parse({
85
- id: 'rseg_test',
86
- type: 'roof-segment',
87
- width: 8,
88
- depth: 6,
89
- overhang: 0,
90
- wallThickness: 0,
91
- shingleThickness: 0,
92
- trim: {
93
- frontLeftX: 5,
94
- frontLeftZ: 2,
95
- backRightX: 2,
96
- backRightZ: 5,
97
- },
98
- });
99
- const trim = normalizeRoofSegmentTrim(segment);
100
- const bounds = getRoofSegmentVisibleTopBounds(segment);
101
- expect(trim.frontLeft).toBeCloseTo(2);
102
- expect(trim.frontLeftX).toBeCloseTo(5);
103
- expect(trim.frontLeftZ).toBeCloseTo(2);
104
- expect(bounds.maxZ).toBeCloseTo(2.6);
105
- expect(bounds.maxX).toBeCloseTo(3.2);
106
- });
107
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=roof-segment-walls.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"roof-segment-walls.test.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/roof-segment-walls.test.ts"],"names":[],"mappings":""}
@@ -1,92 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
- import { RoofSegmentNode } from './roof-segment';
3
- import { getRoofSegmentWallFace, getRoofSegmentWallFaces, getRoofWallFaceFrame, roofFacePointToSegment, segmentPointToRoofWallFace, } from './roof-segment-walls';
4
- function segment(overrides = {}) {
5
- return RoofSegmentNode.parse({
6
- id: 'rseg_test',
7
- type: 'roof-segment',
8
- roofType: 'gable',
9
- width: 8,
10
- depth: 6,
11
- wallHeight: 2.6,
12
- wallThickness: 0.1,
13
- pitch: 40,
14
- ...overrides,
15
- });
16
- }
17
- describe('roof wall face frames', () => {
18
- test('frame z = 0 lands on the nominal footprint (wall mid-plane)', () => {
19
- const seg = segment();
20
- // front face, u at the face middle, v = 1, mid-plane.
21
- const point = roofFacePointToSegment(seg, 'front', [(8 + 0.1) / 2, 1, 0]);
22
- expect(point[0]).toBeCloseTo(0);
23
- expect(point[1]).toBeCloseTo(1);
24
- expect(point[2]).toBeCloseTo(3); // depth / 2 — the footprint plane
25
- });
26
- test('frame +z is the outward normal on every face', () => {
27
- const seg = segment();
28
- for (const [faceId, axis, sign] of [
29
- ['front', 2, 1],
30
- ['back', 2, -1],
31
- ['right', 0, 1],
32
- ['left', 0, -1],
33
- ]) {
34
- const onPlane = roofFacePointToSegment(seg, faceId, [1, 1, 0]);
35
- const pushed = roofFacePointToSegment(seg, faceId, [1, 1, 0.5]);
36
- expect(pushed[axis] - onPlane[axis]).toBeCloseTo(0.5 * sign);
37
- // The other horizontal axis is unaffected by the push.
38
- const other = axis === 2 ? 0 : 2;
39
- expect(pushed[other] - onPlane[other]).toBeCloseTo(0);
40
- }
41
- });
42
- test('face frame agrees with the hit resolver coordinates', () => {
43
- const seg = segment();
44
- // A point on the outer surface (z = +thickness/2 off the mid-plane)
45
- // must read back with the same u/v and dist ≈ 0 off the outer plane.
46
- const segLocal = roofFacePointToSegment(seg, 'right', [2.5, 1.25, 0.05]);
47
- const { u, v, dist } = segmentPointToRoofWallFace(seg, 'right', segLocal);
48
- expect(u).toBeCloseTo(2.5);
49
- expect(v).toBeCloseTo(1.25);
50
- expect(dist).toBeCloseTo(0);
51
- });
52
- test('resizing the segment moves the frame, not the stored coords', () => {
53
- // The core live-tracking property: the same face-local point maps to
54
- // the new plane after a depth change — children follow by re-render.
55
- const before = roofFacePointToSegment(segment(), 'front', [2, 1, 0]);
56
- const after = roofFacePointToSegment(segment({ depth: 8 }), 'front', [2, 1, 0]);
57
- expect(before[2]).toBeCloseTo(3);
58
- expect(after[2]).toBeCloseTo(4);
59
- expect(after[1]).toBeCloseTo(before[1]);
60
- });
61
- test('frame yaw matches the face descriptor yaw', () => {
62
- const seg = segment();
63
- for (const faceId of ['front', 'back', 'right', 'left']) {
64
- expect(getRoofWallFaceFrame(seg, faceId).yaw).toBe(getRoofSegmentWallFace(seg, faceId).yaw);
65
- }
66
- });
67
- test('dutch width-axis roofs expose hostable gable-end wall profiles on the short ends', () => {
68
- const faces = getRoofSegmentWallFaces(segment({
69
- roofType: 'dutch',
70
- width: 8,
71
- depth: 6,
72
- dutchHipWidthRatio: 0.25,
73
- dutchWaistLengthRatio: 1,
74
- }));
75
- const left = faces.find((face) => face.id === 'left');
76
- const right = faces.find((face) => face.id === 'right');
77
- expect(left?.profile.length).toBeGreaterThan(5);
78
- expect(right?.profile.length).toBeGreaterThan(5);
79
- expect(left?.profile[3]?.[1]).toBeCloseTo(left?.profile[2]?.[1] ?? 0);
80
- });
81
- test('dutch long-side faces stay rectangular while only the gable ends rise above the eave', () => {
82
- const faces = getRoofSegmentWallFaces(segment({
83
- roofType: 'dutch',
84
- width: 8,
85
- depth: 6,
86
- }));
87
- const front = faces.find((face) => face.id === 'front');
88
- const back = faces.find((face) => face.id === 'back');
89
- expect(front?.profile).toHaveLength(4);
90
- expect(back?.profile).toHaveLength(4);
91
- });
92
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=wall.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"wall.test.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/wall.test.ts"],"names":[],"mappings":""}
@@ -1,208 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
- import { buildEnabledWallFaceBandPatch, buildWallFaceBandCountPatch, getWallFaceBandConfig, WALL_CHAIR_RAIL_DEFAULT, WALL_CHAIR_RAIL_SLOT_DEFAULT, WALL_CROWN_DEFAULT, WALL_CROWN_SLOT_DEFAULT, WALL_FACE_BAND_DEFAULT, WALL_FACE_BAND_SOLID_SLOT_DEFAULTS, WALL_SKIRTING_DEFAULT, WALL_SKIRTING_SLOT_DEFAULT, WALL_SURFACE_SLOT_DEFAULTS, WallFaceBandConfig, WallTrimConfig, } from './wall';
3
- describe('wall face bands', () => {
4
- test('defaults to one band while preserving legacy enabled scenes as three bands', () => {
5
- expect(WALL_FACE_BAND_DEFAULT.count).toBe(1);
6
- expect(WALL_FACE_BAND_DEFAULT.lowerHeight).toBe(0.84);
7
- expect(WALL_FACE_BAND_DEFAULT.middleHeight).toBe(0.61);
8
- expect(WALL_FACE_BAND_DEFAULT.upperHeight).toBe(0.61);
9
- expect(WallFaceBandConfig.parse({})).toEqual({
10
- enabled: false,
11
- count: 1,
12
- lowerHeight: 0.84,
13
- middleHeight: 0.61,
14
- upperHeight: 0.61,
15
- });
16
- expect(WallFaceBandConfig.parse({ enabled: true })).toEqual({
17
- enabled: true,
18
- count: 3,
19
- lowerHeight: 0.84,
20
- middleHeight: 0.61,
21
- upperHeight: 0.61,
22
- });
23
- expect(getWallFaceBandConfig({
24
- height: 2.5,
25
- faceBands: {
26
- enabled: true,
27
- count: 3,
28
- lowerHeight: 0.84,
29
- middleHeight: 0.61,
30
- upperHeight: 0.61,
31
- },
32
- })).toMatchObject({
33
- count: 3,
34
- lowerTop: 0.84,
35
- middleTop: 1.45,
36
- });
37
- });
38
- test('four bands adds an upper split below the final top band', () => {
39
- expect(getWallFaceBandConfig({
40
- height: 2.5,
41
- faceBands: {
42
- enabled: true,
43
- count: 4,
44
- lowerHeight: 0.5,
45
- middleHeight: 0.6,
46
- upperHeight: 0.7,
47
- },
48
- })).toMatchObject({
49
- count: 4,
50
- lowerTop: 0.5,
51
- middleTop: 1.1,
52
- upperTop: 1.8,
53
- });
54
- });
55
- test('enabling bands seeds visible solid-color band slots', () => {
56
- const patch = buildEnabledWallFaceBandPatch({
57
- faceBands: {
58
- enabled: false,
59
- count: 1,
60
- lowerHeight: 0.2,
61
- middleHeight: 0.3,
62
- upperHeight: 0.61,
63
- },
64
- slots: {
65
- interior: 'library:interior-finish',
66
- exterior: 'scene:exterior-finish',
67
- lowerInterior: 'library:stale-lower',
68
- middleExterior: 'library:stale-middle',
69
- },
70
- });
71
- expect(patch.faceBands).toEqual({
72
- enabled: true,
73
- count: 2,
74
- lowerHeight: 0.2,
75
- middleHeight: 0.3,
76
- upperHeight: 0.61,
77
- });
78
- expect(patch.slots).toMatchObject({
79
- interior: 'library:interior-finish',
80
- exterior: 'scene:exterior-finish',
81
- lowerInterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.lower,
82
- upperInterior: 'library:interior-finish',
83
- lowerExterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.lower,
84
- upperExterior: 'scene:exterior-finish',
85
- });
86
- expect(patch.slots?.middleInterior).toBeUndefined();
87
- expect(patch.slots?.middleExterior).toBeUndefined();
88
- });
89
- test('band count patch enables only the active slots', () => {
90
- const patch = buildWallFaceBandCountPatch({
91
- faceBands: {
92
- enabled: true,
93
- count: 4,
94
- lowerHeight: 0.2,
95
- middleHeight: 0.3,
96
- upperHeight: 0.61,
97
- },
98
- slots: {
99
- interior: 'library:interior-finish',
100
- exterior: 'scene:exterior-finish',
101
- topInterior: 'library:stale-top',
102
- },
103
- }, 3);
104
- expect(patch.faceBands).toMatchObject({ enabled: true, count: 3 });
105
- expect(patch.slots).toMatchObject({
106
- lowerInterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.lower,
107
- middleInterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.middle,
108
- upperInterior: 'library:stale-top',
109
- lowerExterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.lower,
110
- middleExterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.middle,
111
- upperExterior: 'scene:exterior-finish',
112
- });
113
- expect(patch.slots?.topInterior).toBeUndefined();
114
- expect(patch.slots?.topExterior).toBeUndefined();
115
- });
116
- test('enabling bands replaces stale inactive band slots with solid-color defaults', () => {
117
- const patch = buildEnabledWallFaceBandPatch({
118
- slots: {
119
- lowerInterior: 'library:stale-lower',
120
- middleInterior: 'library:stale-middle',
121
- upperExterior: 'library:stale-upper',
122
- },
123
- });
124
- expect(patch.slots).toEqual({
125
- lowerInterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.lower,
126
- upperInterior: WALL_SURFACE_SLOT_DEFAULTS.interior,
127
- lowerExterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.lower,
128
- upperExterior: WALL_SURFACE_SLOT_DEFAULTS.exterior,
129
- });
130
- expect(patch.slots?.middleInterior).toBeUndefined();
131
- expect(patch.slots?.middleExterior).toBeUndefined();
132
- });
133
- test('increasing band count paints newly active bands with the solid palette', () => {
134
- const patch = buildWallFaceBandCountPatch({
135
- faceBands: {
136
- enabled: true,
137
- count: 2,
138
- lowerHeight: 0.2,
139
- middleHeight: 0.3,
140
- upperHeight: 0.61,
141
- },
142
- slots: {
143
- lowerInterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.lower,
144
- upperInterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.upper,
145
- lowerExterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.lower,
146
- upperExterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.upper,
147
- },
148
- }, 3);
149
- expect(patch.slots).toMatchObject({
150
- lowerInterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.lower,
151
- middleInterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.middle,
152
- upperInterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.upper,
153
- lowerExterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.lower,
154
- middleExterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.middle,
155
- upperExterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.upper,
156
- });
157
- });
158
- test('increasing to four bands keeps the previous top material on the new top band', () => {
159
- const patch = buildWallFaceBandCountPatch({
160
- faceBands: {
161
- enabled: true,
162
- count: 3,
163
- lowerHeight: 0.2,
164
- middleHeight: 0.3,
165
- upperHeight: 0.61,
166
- },
167
- slots: {
168
- lowerInterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.lower,
169
- middleInterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.middle,
170
- upperInterior: 'scene:painted-top-interior',
171
- lowerExterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.lower,
172
- middleExterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.middle,
173
- upperExterior: 'library:painted-top-exterior',
174
- },
175
- }, 4);
176
- expect(patch.slots).toMatchObject({
177
- lowerInterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.lower,
178
- middleInterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.middle,
179
- upperInterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.upper,
180
- topInterior: 'scene:painted-top-interior',
181
- lowerExterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.lower,
182
- middleExterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.middle,
183
- upperExterior: WALL_FACE_BAND_SOLID_SLOT_DEFAULTS.upper,
184
- topExterior: 'library:painted-top-exterior',
185
- });
186
- });
187
- });
188
- describe('wall trim profiles', () => {
189
- test('uses curated defaults while preserving legacy profile values', () => {
190
- expect(WALL_SKIRTING_DEFAULT.profile).toBe('flat');
191
- expect(WALL_CROWN_DEFAULT.profile).toBe('flat');
192
- expect(WALL_CHAIR_RAIL_DEFAULT.profile).toBe('flat');
193
- expect(WallTrimConfig.parse({ profile: 'flat' }).profile).toBe('flat');
194
- expect(WallTrimConfig.parse({ profile: 'crown-layered' }).profile).toBe('crown-layered');
195
- expect(WallTrimConfig.parse({ profile: 'triangle' }).profile).toBe('triangle');
196
- });
197
- test('declares separate default materials for each trim family', () => {
198
- expect(WALL_SKIRTING_SLOT_DEFAULT).toBe('library:preset-softwhite');
199
- expect(WALL_CROWN_SLOT_DEFAULT).toBe('library:preset-white');
200
- expect(WALL_CHAIR_RAIL_SLOT_DEFAULT).toBe('library:preset-cream');
201
- expect(WALL_SURFACE_SLOT_DEFAULTS.skirtingInterior).toBe(WALL_SKIRTING_SLOT_DEFAULT);
202
- expect(WALL_SURFACE_SLOT_DEFAULTS.skirtingExterior).toBe(WALL_SKIRTING_SLOT_DEFAULT);
203
- expect(WALL_SURFACE_SLOT_DEFAULTS.crownInterior).toBe(WALL_CROWN_SLOT_DEFAULT);
204
- expect(WALL_SURFACE_SLOT_DEFAULTS.crownExterior).toBe(WALL_CROWN_SLOT_DEFAULT);
205
- expect(WALL_SURFACE_SLOT_DEFAULTS.chairRailInterior).toBe(WALL_CHAIR_RAIL_SLOT_DEFAULT);
206
- expect(WALL_SURFACE_SLOT_DEFAULTS.chairRailExterior).toBe(WALL_CHAIR_RAIL_SLOT_DEFAULT);
207
- });
208
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=alignment-anchors.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"alignment-anchors.test.d.ts","sourceRoot":"","sources":["../../src/services/alignment-anchors.test.ts"],"names":[],"mappings":""}