@ifc-lite/create 4.0.0 → 5.1.0

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 (325) hide show
  1. package/README.md +34 -0
  2. package/dist/in-store/align-boxes.d.ts +38 -0
  3. package/dist/in-store/align-boxes.d.ts.map +1 -0
  4. package/dist/in-store/align-boxes.js +97 -0
  5. package/dist/in-store/align-boxes.js.map +1 -0
  6. package/dist/in-store/anchor.d.ts.map +1 -1
  7. package/dist/in-store/anchor.js +13 -2
  8. package/dist/in-store/anchor.js.map +1 -1
  9. package/dist/in-store/beam.d.ts.map +1 -1
  10. package/dist/in-store/beam.js +3 -10
  11. package/dist/in-store/beam.js.map +1 -1
  12. package/dist/in-store/copy-array.d.ts +17 -0
  13. package/dist/in-store/copy-array.d.ts.map +1 -0
  14. package/dist/in-store/copy-array.js +47 -0
  15. package/dist/in-store/copy-array.js.map +1 -0
  16. package/dist/in-store/copy-batch.d.ts +27 -0
  17. package/dist/in-store/copy-batch.d.ts.map +1 -0
  18. package/dist/in-store/copy-batch.js +101 -0
  19. package/dist/in-store/copy-batch.js.map +1 -0
  20. package/dist/in-store/copy-dependent-walk.d.ts +27 -0
  21. package/dist/in-store/copy-dependent-walk.d.ts.map +1 -0
  22. package/dist/in-store/copy-dependent-walk.js +61 -0
  23. package/dist/in-store/copy-dependent-walk.js.map +1 -0
  24. package/dist/in-store/copy-frame.d.ts +4 -3
  25. package/dist/in-store/copy-frame.d.ts.map +1 -1
  26. package/dist/in-store/copy-frame.js +14 -1
  27. package/dist/in-store/copy-frame.js.map +1 -1
  28. package/dist/in-store/copy-product.d.ts +0 -20
  29. package/dist/in-store/copy-product.d.ts.map +1 -1
  30. package/dist/in-store/copy-product.js +35 -35
  31. package/dist/in-store/copy-product.js.map +1 -1
  32. package/dist/in-store/edit/effective-mutation-view.d.ts +6 -0
  33. package/dist/in-store/edit/effective-mutation-view.d.ts.map +1 -0
  34. package/dist/in-store/edit/effective-mutation-view.js +45 -0
  35. package/dist/in-store/edit/effective-mutation-view.js.map +1 -0
  36. package/dist/in-store/edit/effective-storey.d.ts +13 -0
  37. package/dist/in-store/edit/effective-storey.d.ts.map +1 -0
  38. package/dist/in-store/edit/effective-storey.js +36 -0
  39. package/dist/in-store/edit/effective-storey.js.map +1 -0
  40. package/dist/in-store/edit/effective-storeys.d.ts +9 -0
  41. package/dist/in-store/edit/effective-storeys.d.ts.map +1 -0
  42. package/dist/in-store/edit/effective-storeys.js +16 -0
  43. package/dist/in-store/edit/effective-storeys.js.map +1 -0
  44. package/dist/in-store/edit/hosted-opening-refit.d.ts +29 -0
  45. package/dist/in-store/edit/hosted-opening-refit.d.ts.map +1 -0
  46. package/dist/in-store/edit/hosted-opening-refit.js +168 -0
  47. package/dist/in-store/edit/hosted-opening-refit.js.map +1 -0
  48. package/dist/in-store/edit/length-unit-scale.d.ts +24 -0
  49. package/dist/in-store/edit/length-unit-scale.d.ts.map +1 -0
  50. package/dist/in-store/edit/length-unit-scale.js +37 -0
  51. package/dist/in-store/edit/length-unit-scale.js.map +1 -0
  52. package/dist/in-store/edit/linear-element-edit.d.ts +131 -0
  53. package/dist/in-store/edit/linear-element-edit.d.ts.map +1 -0
  54. package/dist/in-store/edit/linear-element-edit.js +259 -0
  55. package/dist/in-store/edit/linear-element-edit.js.map +1 -0
  56. package/dist/in-store/edit/metadata-clone-effective.d.ts +5 -0
  57. package/dist/in-store/edit/metadata-clone-effective.d.ts.map +1 -0
  58. package/dist/in-store/edit/metadata-clone-effective.js +47 -0
  59. package/dist/in-store/edit/metadata-clone-effective.js.map +1 -0
  60. package/dist/in-store/edit/metadata-clone.d.ts +40 -0
  61. package/dist/in-store/edit/metadata-clone.d.ts.map +1 -0
  62. package/dist/in-store/edit/metadata-clone.js +107 -0
  63. package/dist/in-store/edit/metadata-clone.js.map +1 -0
  64. package/dist/in-store/edit/placement-core.d.ts +140 -0
  65. package/dist/in-store/edit/placement-core.d.ts.map +1 -0
  66. package/dist/in-store/edit/placement-core.js +317 -0
  67. package/dist/in-store/edit/placement-core.js.map +1 -0
  68. package/dist/in-store/edit/polygon-clip.d.ts +58 -0
  69. package/dist/in-store/edit/polygon-clip.d.ts.map +1 -0
  70. package/dist/in-store/edit/polygon-clip.js +153 -0
  71. package/dist/in-store/edit/polygon-clip.js.map +1 -0
  72. package/dist/in-store/edit/read-profile.d.ts +6 -0
  73. package/dist/in-store/edit/read-profile.d.ts.map +1 -0
  74. package/dist/in-store/edit/read-profile.js +95 -0
  75. package/dist/in-store/edit/read-profile.js.map +1 -0
  76. package/dist/in-store/edit/slab-edit-frame.d.ts +40 -0
  77. package/dist/in-store/edit/slab-edit-frame.d.ts.map +1 -0
  78. package/dist/in-store/edit/slab-edit-frame.js +146 -0
  79. package/dist/in-store/edit/slab-edit-frame.js.map +1 -0
  80. package/dist/in-store/edit/slab-edit.d.ts +112 -0
  81. package/dist/in-store/edit/slab-edit.d.ts.map +1 -0
  82. package/dist/in-store/edit/slab-edit.js +275 -0
  83. package/dist/in-store/edit/slab-edit.js.map +1 -0
  84. package/dist/in-store/edit/slab-opening-carry.d.ts +10 -0
  85. package/dist/in-store/edit/slab-opening-carry.d.ts.map +1 -0
  86. package/dist/in-store/edit/slab-opening-carry.js +65 -0
  87. package/dist/in-store/edit/slab-opening-carry.js.map +1 -0
  88. package/dist/in-store/edit/split-guid.d.ts +29 -0
  89. package/dist/in-store/edit/split-guid.d.ts.map +1 -0
  90. package/dist/in-store/edit/split-guid.js +64 -0
  91. package/dist/in-store/edit/split-guid.js.map +1 -0
  92. package/dist/in-store/edit/split-target.d.ts +90 -0
  93. package/dist/in-store/edit/split-target.d.ts.map +1 -0
  94. package/dist/in-store/edit/split-target.js +116 -0
  95. package/dist/in-store/edit/split-target.js.map +1 -0
  96. package/dist/in-store/edit/target.d.ts +8 -0
  97. package/dist/in-store/edit/target.d.ts.map +1 -0
  98. package/dist/in-store/edit/target.js +5 -0
  99. package/dist/in-store/edit/target.js.map +1 -0
  100. package/dist/in-store/edit/trim-extend-geometry.d.ts +99 -0
  101. package/dist/in-store/edit/trim-extend-geometry.d.ts.map +1 -0
  102. package/dist/in-store/edit/trim-extend-geometry.js +105 -0
  103. package/dist/in-store/edit/trim-extend-geometry.js.map +1 -0
  104. package/dist/in-store/edit/wall-axis-edit.d.ts +16 -0
  105. package/dist/in-store/edit/wall-axis-edit.d.ts.map +1 -0
  106. package/dist/in-store/edit/wall-axis-edit.js +40 -0
  107. package/dist/in-store/edit/wall-axis-edit.js.map +1 -0
  108. package/dist/in-store/edit/wall-edit.d.ts +157 -0
  109. package/dist/in-store/edit/wall-edit.d.ts.map +1 -0
  110. package/dist/in-store/edit/wall-edit.js +276 -0
  111. package/dist/in-store/edit/wall-edit.js.map +1 -0
  112. package/dist/in-store/edit/wall-hosted-cuts.d.ts +35 -0
  113. package/dist/in-store/edit/wall-hosted-cuts.d.ts.map +1 -0
  114. package/dist/in-store/edit/wall-hosted-cuts.js +27 -0
  115. package/dist/in-store/edit/wall-hosted-cuts.js.map +1 -0
  116. package/dist/in-store/edit/wall-opening-reassign.d.ts +18 -0
  117. package/dist/in-store/edit/wall-opening-reassign.d.ts.map +1 -0
  118. package/dist/in-store/edit/wall-opening-reassign.js +50 -0
  119. package/dist/in-store/edit/wall-opening-reassign.js.map +1 -0
  120. package/dist/in-store/element-align.d.ts +13 -0
  121. package/dist/in-store/element-align.d.ts.map +1 -0
  122. package/dist/in-store/element-align.js +90 -0
  123. package/dist/in-store/element-align.js.map +1 -0
  124. package/dist/in-store/element-replacement.d.ts +26 -0
  125. package/dist/in-store/element-replacement.d.ts.map +1 -0
  126. package/dist/in-store/element-replacement.js +68 -0
  127. package/dist/in-store/element-replacement.js.map +1 -0
  128. package/dist/in-store/element-size-edit.d.ts +40 -0
  129. package/dist/in-store/element-size-edit.d.ts.map +1 -0
  130. package/dist/in-store/element-size-edit.js +103 -0
  131. package/dist/in-store/element-size-edit.js.map +1 -0
  132. package/dist/in-store/element-split-axis.d.ts +6 -0
  133. package/dist/in-store/element-split-axis.d.ts.map +1 -0
  134. package/dist/in-store/element-split-axis.js +87 -0
  135. package/dist/in-store/element-split-axis.js.map +1 -0
  136. package/dist/in-store/element-split-joined.d.ts +13 -0
  137. package/dist/in-store/element-split-joined.d.ts.map +1 -0
  138. package/dist/in-store/element-split-joined.js +74 -0
  139. package/dist/in-store/element-split-joined.js.map +1 -0
  140. package/dist/in-store/element-split-placement.d.ts +19 -0
  141. package/dist/in-store/element-split-placement.d.ts.map +1 -0
  142. package/dist/in-store/element-split-placement.js +48 -0
  143. package/dist/in-store/element-split-placement.js.map +1 -0
  144. package/dist/in-store/element-split-slab.d.ts +19 -0
  145. package/dist/in-store/element-split-slab.d.ts.map +1 -0
  146. package/dist/in-store/element-split-slab.js +86 -0
  147. package/dist/in-store/element-split-slab.js.map +1 -0
  148. package/dist/in-store/element-split.d.ts +49 -0
  149. package/dist/in-store/element-split.d.ts.map +1 -0
  150. package/dist/in-store/element-split.js +52 -0
  151. package/dist/in-store/element-split.js.map +1 -0
  152. package/dist/in-store/element-transform-edit.d.ts +33 -0
  153. package/dist/in-store/element-transform-edit.d.ts.map +1 -0
  154. package/dist/in-store/element-transform-edit.js +97 -0
  155. package/dist/in-store/element-transform-edit.js.map +1 -0
  156. package/dist/in-store/element-transform-frames.d.ts +58 -0
  157. package/dist/in-store/element-transform-frames.d.ts.map +1 -0
  158. package/dist/in-store/element-transform-frames.js +110 -0
  159. package/dist/in-store/element-transform-frames.js.map +1 -0
  160. package/dist/in-store/element-transform-joins.d.ts +4 -0
  161. package/dist/in-store/element-transform-joins.d.ts.map +1 -0
  162. package/dist/in-store/element-transform-joins.js +62 -0
  163. package/dist/in-store/element-transform-joins.js.map +1 -0
  164. package/dist/in-store/element-transform-plan.d.ts +38 -0
  165. package/dist/in-store/element-transform-plan.d.ts.map +1 -0
  166. package/dist/in-store/element-transform-plan.js +115 -0
  167. package/dist/in-store/element-transform-plan.js.map +1 -0
  168. package/dist/in-store/element-trim-extend.d.ts +25 -0
  169. package/dist/in-store/element-trim-extend.d.ts.map +1 -0
  170. package/dist/in-store/element-trim-extend.js +97 -0
  171. package/dist/in-store/element-trim-extend.js.map +1 -0
  172. package/dist/in-store/extract-grids.d.ts +7 -17
  173. package/dist/in-store/extract-grids.d.ts.map +1 -1
  174. package/dist/in-store/extract-grids.js +11 -2
  175. package/dist/in-store/extract-grids.js.map +1 -1
  176. package/dist/in-store/grid-column.d.ts +23 -0
  177. package/dist/in-store/grid-column.d.ts.map +1 -0
  178. package/dist/in-store/grid-column.js +73 -0
  179. package/dist/in-store/grid-column.js.map +1 -0
  180. package/dist/in-store/grid-intersection-read.d.ts +10 -0
  181. package/dist/in-store/grid-intersection-read.d.ts.map +1 -0
  182. package/dist/in-store/grid-intersection-read.js +45 -0
  183. package/dist/in-store/grid-intersection-read.js.map +1 -0
  184. package/dist/in-store/grid.d.ts +7 -1
  185. package/dist/in-store/grid.d.ts.map +1 -1
  186. package/dist/in-store/grid.js +12 -2
  187. package/dist/in-store/grid.js.map +1 -1
  188. package/dist/in-store/group-evidence.d.ts +49 -0
  189. package/dist/in-store/group-evidence.d.ts.map +1 -0
  190. package/dist/in-store/group-evidence.js +111 -0
  191. package/dist/in-store/group-evidence.js.map +1 -0
  192. package/dist/in-store/group-graph.d.ts +51 -0
  193. package/dist/in-store/group-graph.d.ts.map +1 -0
  194. package/dist/in-store/group-graph.js +213 -0
  195. package/dist/in-store/group-graph.js.map +1 -0
  196. package/dist/in-store/group.d.ts +34 -0
  197. package/dist/in-store/group.d.ts.map +1 -0
  198. package/dist/in-store/group.js +181 -0
  199. package/dist/in-store/group.js.map +1 -0
  200. package/dist/in-store/host-geometry-frame.d.ts +5 -1
  201. package/dist/in-store/host-geometry-frame.d.ts.map +1 -1
  202. package/dist/in-store/host-geometry-frame.js +46 -2
  203. package/dist/in-store/host-geometry-frame.js.map +1 -1
  204. package/dist/in-store/index.d.ts +7 -0
  205. package/dist/in-store/index.d.ts.map +1 -1
  206. package/dist/in-store/index.js +7 -0
  207. package/dist/in-store/index.js.map +1 -1
  208. package/dist/in-store/linear-profile-frame.d.ts +10 -0
  209. package/dist/in-store/linear-profile-frame.d.ts.map +1 -0
  210. package/dist/in-store/linear-profile-frame.js +17 -0
  211. package/dist/in-store/linear-profile-frame.js.map +1 -0
  212. package/dist/in-store/material.d.ts.map +1 -1
  213. package/dist/in-store/material.js +17 -6
  214. package/dist/in-store/material.js.map +1 -1
  215. package/dist/in-store/member.d.ts.map +1 -1
  216. package/dist/in-store/member.js +3 -7
  217. package/dist/in-store/member.js.map +1 -1
  218. package/dist/in-store/ordinary-element.d.ts +47 -0
  219. package/dist/in-store/ordinary-element.d.ts.map +1 -0
  220. package/dist/in-store/ordinary-element.js +38 -0
  221. package/dist/in-store/ordinary-element.js.map +1 -0
  222. package/dist/in-store/placement-frame.d.ts +6 -1
  223. package/dist/in-store/placement-frame.d.ts.map +1 -1
  224. package/dist/in-store/placement-frame.js +5 -1
  225. package/dist/in-store/placement-frame.js.map +1 -1
  226. package/dist/in-store/resolve-anchor.d.ts +3 -2
  227. package/dist/in-store/resolve-anchor.d.ts.map +1 -1
  228. package/dist/in-store/resolve-anchor.js +7 -5
  229. package/dist/in-store/resolve-anchor.js.map +1 -1
  230. package/dist/in-store/resolve-relations.d.ts +3 -1
  231. package/dist/in-store/resolve-relations.d.ts.map +1 -1
  232. package/dist/in-store/resolve-relations.js +8 -3
  233. package/dist/in-store/resolve-relations.js.map +1 -1
  234. package/dist/in-store/room-candidates.d.ts +58 -0
  235. package/dist/in-store/room-candidates.d.ts.map +1 -0
  236. package/dist/in-store/room-candidates.js +135 -0
  237. package/dist/in-store/room-candidates.js.map +1 -0
  238. package/dist/in-store/room-creation-plan.d.ts +16 -0
  239. package/dist/in-store/room-creation-plan.d.ts.map +1 -0
  240. package/dist/in-store/room-creation-plan.js +28 -0
  241. package/dist/in-store/room-creation-plan.js.map +1 -0
  242. package/dist/in-store/room-floor-height.d.ts +24 -0
  243. package/dist/in-store/room-floor-height.d.ts.map +1 -0
  244. package/dist/in-store/room-floor-height.js +32 -0
  245. package/dist/in-store/room-floor-height.js.map +1 -0
  246. package/dist/in-store/room-footprint-native.d.ts +19 -0
  247. package/dist/in-store/room-footprint-native.d.ts.map +1 -0
  248. package/dist/in-store/room-footprint-native.js +117 -0
  249. package/dist/in-store/room-footprint-native.js.map +1 -0
  250. package/dist/in-store/room-layout-cache.d.ts +23 -0
  251. package/dist/in-store/room-layout-cache.d.ts.map +1 -0
  252. package/dist/in-store/room-layout-cache.js +84 -0
  253. package/dist/in-store/room-layout-cache.js.map +1 -0
  254. package/dist/in-store/room-layout-core.d.ts +68 -0
  255. package/dist/in-store/room-layout-core.d.ts.map +1 -0
  256. package/dist/in-store/room-layout-core.js +153 -0
  257. package/dist/in-store/room-layout-core.js.map +1 -0
  258. package/dist/in-store/room-population.d.ts +5 -0
  259. package/dist/in-store/room-population.d.ts.map +1 -0
  260. package/dist/in-store/room-population.js +28 -0
  261. package/dist/in-store/room-population.js.map +1 -0
  262. package/dist/in-store/room-space-meshes.d.ts +15 -0
  263. package/dist/in-store/room-space-meshes.d.ts.map +1 -0
  264. package/dist/in-store/room-space-meshes.js +38 -0
  265. package/dist/in-store/room-space-meshes.js.map +1 -0
  266. package/dist/in-store/room-store.d.ts +55 -0
  267. package/dist/in-store/room-store.d.ts.map +1 -0
  268. package/dist/in-store/room-store.js +173 -0
  269. package/dist/in-store/room-store.js.map +1 -0
  270. package/dist/in-store/room-storey-elevation.d.ts +5 -0
  271. package/dist/in-store/room-storey-elevation.d.ts.map +1 -0
  272. package/dist/in-store/room-storey-elevation.js +42 -0
  273. package/dist/in-store/room-storey-elevation.js.map +1 -0
  274. package/dist/in-store/room-storey-frame.d.ts +47 -0
  275. package/dist/in-store/room-storey-frame.d.ts.map +1 -0
  276. package/dist/in-store/room-storey-frame.js +48 -0
  277. package/dist/in-store/room-storey-frame.js.map +1 -0
  278. package/dist/in-store/room-wall-rects.d.ts +117 -0
  279. package/dist/in-store/room-wall-rects.d.ts.map +1 -0
  280. package/dist/in-store/room-wall-rects.js +157 -0
  281. package/dist/in-store/room-wall-rects.js.map +1 -0
  282. package/dist/in-store/schema-attributes.d.ts +3 -3
  283. package/dist/in-store/schema-attributes.d.ts.map +1 -1
  284. package/dist/in-store/schema-attributes.js +9 -7
  285. package/dist/in-store/schema-attributes.js.map +1 -1
  286. package/dist/in-store/slab.d.ts.map +1 -1
  287. package/dist/in-store/slab.js +1 -4
  288. package/dist/in-store/slab.js.map +1 -1
  289. package/dist/in-store/stair-removal.d.ts +17 -0
  290. package/dist/in-store/stair-removal.d.ts.map +1 -0
  291. package/dist/in-store/stair-removal.js +134 -0
  292. package/dist/in-store/stair-removal.js.map +1 -0
  293. package/dist/in-store/storey-plan-frame.d.ts +2 -1
  294. package/dist/in-store/storey-plan-frame.d.ts.map +1 -1
  295. package/dist/in-store/storey-plan-frame.js +20 -11
  296. package/dist/in-store/storey-plan-frame.js.map +1 -1
  297. package/dist/in-store/storey-reassignment-plan.d.ts +53 -0
  298. package/dist/in-store/storey-reassignment-plan.d.ts.map +1 -0
  299. package/dist/in-store/storey-reassignment-plan.js +237 -0
  300. package/dist/in-store/storey-reassignment-plan.js.map +1 -0
  301. package/dist/in-store/storey-reassignment.d.ts +8 -0
  302. package/dist/in-store/storey-reassignment.d.ts.map +1 -0
  303. package/dist/in-store/storey-reassignment.js +52 -0
  304. package/dist/in-store/storey-reassignment.js.map +1 -0
  305. package/dist/in-store/trim-extend-plan.d.ts +27 -0
  306. package/dist/in-store/trim-extend-plan.d.ts.map +1 -0
  307. package/dist/in-store/trim-extend-plan.js +49 -0
  308. package/dist/in-store/trim-extend-plan.js.map +1 -0
  309. package/dist/in-store/wall-join-edit.d.ts +0 -17
  310. package/dist/in-store/wall-join-edit.d.ts.map +1 -1
  311. package/dist/in-store/wall-join-edit.js +41 -7
  312. package/dist/in-store/wall-join-edit.js.map +1 -1
  313. package/dist/in-store/wall-section-edit.d.ts +16 -0
  314. package/dist/in-store/wall-section-edit.d.ts.map +1 -0
  315. package/dist/in-store/wall-section-edit.js +75 -0
  316. package/dist/in-store/wall-section-edit.js.map +1 -0
  317. package/dist/in-store/wall-size-edit.d.ts +29 -0
  318. package/dist/in-store/wall-size-edit.d.ts.map +1 -0
  319. package/dist/in-store/wall-size-edit.js +65 -0
  320. package/dist/in-store/wall-size-edit.js.map +1 -0
  321. package/dist/index.d.ts +24 -0
  322. package/dist/index.d.ts.map +1 -1
  323. package/dist/index.js +23 -0
  324. package/dist/index.js.map +1 -1
  325. package/package.json +8 -7
@@ -0,0 +1,275 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ import { asExpressIdRef, asCoordinateTriple, readAttributes, resolvePlacementChain, } from './placement-core.js';
5
+ import { clipPolygonByLine } from './polygon-clip.js';
6
+ import { polygonArea } from '../room-footprint-offset.js';
7
+ import { resolveSolidPositionXform, slabExtrusionFrame } from './slab-edit-frame.js';
8
+ const SLAB_LIKE_STEP_TYPES = {
9
+ IFCSLAB: 'IfcSlab',
10
+ IFCROOF: 'IfcRoof',
11
+ IFCPLATE: 'IfcPlate',
12
+ IFCSPACE: 'IfcSpace',
13
+ };
14
+ function stepTypeToSlabLike(stepType) {
15
+ return SLAB_LIKE_STEP_TYPES[stepType.toUpperCase()] ?? null;
16
+ }
17
+ /**
18
+ * Derive a rectangle profile's outline from its centred placement.
19
+ * `IfcRectangleProfileDef` extends from `-XDim/2` to `+XDim/2`
20
+ * along the profile's local X (and same for YDim along local Y),
21
+ * centred at the IfcAxis2Placement2D's Location point.
22
+ */
23
+ function rectangleFootprint(placementOrigin, profileOrigin2D, xdim, ydim, solidXform) {
24
+ // Rectangle corners in the profile coordinate system (centred on the
25
+ // profile origin), mapped through the solid Position into plan space,
26
+ // then offset by the slab's placement origin.
27
+ const [px, py] = placementOrigin;
28
+ const [cx, cy] = profileOrigin2D;
29
+ const corners = [
30
+ [cx - xdim / 2, cy - ydim / 2],
31
+ [cx + xdim / 2, cy - ydim / 2],
32
+ [cx + xdim / 2, cy + ydim / 2],
33
+ [cx - xdim / 2, cy + ydim / 2],
34
+ ];
35
+ return corners.map((c) => {
36
+ const [wx, wy] = solidXform(c);
37
+ return [px + wx, py + wy];
38
+ });
39
+ }
40
+ /**
41
+ * Read an IfcPolyline's vertex list and return them as 2D storey-
42
+ * local points (adding the placement origin so the result is in
43
+ * the same frame as a rectangle footprint).
44
+ */
45
+ function polylineFootprint(dataStore, view, editor, polylineId, placementOrigin, profileOrigin2D, solidXform) {
46
+ const attrs = readAttributes(dataStore, view, editor, polylineId);
47
+ if (!attrs)
48
+ return null;
49
+ // IfcPolyline.Points is a list of IfcCartesianPoint refs at attr 0.
50
+ const refList = attrs[0];
51
+ if (!Array.isArray(refList) || refList.length < 3)
52
+ return null;
53
+ const [px, py] = placementOrigin;
54
+ const [cx, cy] = profileOrigin2D;
55
+ const out = [];
56
+ for (const ref of refList) {
57
+ const ptId = asExpressIdRef(ref);
58
+ if (ptId === null)
59
+ return null;
60
+ const ptAttrs = readAttributes(dataStore, view, editor, ptId);
61
+ if (!ptAttrs)
62
+ return null;
63
+ // IfcCartesianPoint.Coordinates is a list of doubles at attr 0.
64
+ // Polyline points are 2D here (slab profiles), but treat 3D
65
+ // tolerantly — IFC files in the wild sometimes pad with Z=0.
66
+ const coords = asCoordinateTriple(ptAttrs[0]);
67
+ if (!coords)
68
+ return null;
69
+ // Point in profile CS → solid plan (Position translation + rotation)
70
+ // → slab placement origin.
71
+ const [wx, wy] = solidXform([cx + coords[0], cy + coords[1]]);
72
+ out.push([px + wx, py + wy]);
73
+ }
74
+ // IfcPolyline for a closed profile may or may not repeat the
75
+ // first vertex at the end — strip if present, our clip API
76
+ // wants the implicit-close form.
77
+ if (out.length >= 2) {
78
+ const first = out[0];
79
+ const last = out[out.length - 1];
80
+ if (Math.abs(first[0] - last[0]) < 1e-9 && Math.abs(first[1] - last[1]) < 1e-9) {
81
+ out.pop();
82
+ }
83
+ }
84
+ return out.length >= 3 ? out : null;
85
+ }
86
+ /**
87
+ * Scale a chain's coordinate-bearing fields (footprint, placement
88
+ * origin, thickness) by `scale`. Identity when `scale === 1`. Used to
89
+ * lift a native-unit (e.g. millimetre) STEP read into the viewer's
90
+ * metre working space — see `resolveSlabEditChain`'s `lengthUnitScale`.
91
+ */
92
+ function scaleSlabChain(chain, scale) {
93
+ const scaled = scale === 1 ? chain : {
94
+ ...chain,
95
+ placementOrigin: [
96
+ chain.placementOrigin[0] * scale,
97
+ chain.placementOrigin[1] * scale,
98
+ chain.placementOrigin[2] * scale,
99
+ ],
100
+ baseElevation: chain.baseElevation === null ? null : chain.baseElevation * scale,
101
+ footprint: chain.footprint.map(([x, y]) => [x * scale, y * scale]),
102
+ thickness: chain.thickness * scale,
103
+ };
104
+ if (!Number.isFinite(scaled.thickness) || scaled.thickness <= 0
105
+ || !scaled.placementOrigin.every(Number.isFinite)
106
+ || (scaled.baseElevation !== null && !Number.isFinite(scaled.baseElevation))
107
+ || scaled.footprint.some(point => !point.every(Number.isFinite)))
108
+ return null;
109
+ const area = polygonArea(scaled.footprint);
110
+ // Tilted extrusions may project to a line; their null baseElevation already refuses plan splitting.
111
+ return Number.isFinite(area) && (scaled.baseElevation === null || area > 0) ? scaled : null;
112
+ }
113
+ /**
114
+ * Resolve the slab chain (placement + footprint + extrusion). Works
115
+ * for IfcSlab / IfcRoof / IfcPlate / IfcSpace whose representation
116
+ * matches the in-store builder shape; null otherwise.
117
+ *
118
+ * `lengthUnitScale` is the model's native-unit → metre factor (e.g.
119
+ * `0.001` for a millimetre file). Raw STEP coordinate reads are in
120
+ * native units, but the rest of the split flow — raycast cut points,
121
+ * preview meshes, selection hit-tests — lives in metres, so the
122
+ * resolved footprint/thickness are scaled to match. Authored overlay
123
+ * entities are scaled too: the in-store builders convert their metre
124
+ * params to the file's native unit (`toNativePoint3` / `toNativeLength`),
125
+ * so an authored slab in a millimetre file stores millimetres (#6233).
126
+ */
127
+ export function resolveSlabEditChain(dataStore, view, editor, expressId, lengthUnitScale = 1,
128
+ /** A validated extrusion beneath an envelope's clipping results. */
129
+ bodyItemId) {
130
+ const rawType = editor.getEntityType(expressId);
131
+ if (!rawType)
132
+ return null;
133
+ const elementType = stepTypeToSlabLike(rawType);
134
+ if (!elementType)
135
+ return null;
136
+ const scale = lengthUnitScale;
137
+ if (!Number.isFinite(scale) || scale <= 0)
138
+ return null;
139
+ const chain = resolvePlacementChain(dataStore, view, editor, expressId);
140
+ if (!chain)
141
+ return null;
142
+ const placementOrigin = chain.coordinates;
143
+ const elementAttrs = readAttributes(dataStore, view, editor, expressId);
144
+ if (!elementAttrs)
145
+ return null;
146
+ const productShapeId = asExpressIdRef(elementAttrs[6]);
147
+ if (productShapeId === null)
148
+ return null;
149
+ const productShapeAttrs = readAttributes(dataStore, view, editor, productShapeId);
150
+ if (!productShapeAttrs)
151
+ return null;
152
+ const reps = productShapeAttrs[2];
153
+ if (!Array.isArray(reps) || reps.length === 0)
154
+ return null;
155
+ const shapeRepId = asExpressIdRef(reps[0]);
156
+ if (shapeRepId === null)
157
+ return null;
158
+ const shapeRepAttrs = readAttributes(dataStore, view, editor, shapeRepId);
159
+ if (!shapeRepAttrs)
160
+ return null;
161
+ const items = shapeRepAttrs[3];
162
+ if (!Array.isArray(items) || items.length === 0)
163
+ return null;
164
+ const solidId = bodyItemId ?? asExpressIdRef(items[0]);
165
+ if (solidId === null)
166
+ return null;
167
+ if (editor.getEntityType(solidId)?.toUpperCase() !== 'IFCEXTRUDEDAREASOLID')
168
+ return null;
169
+ const solidAttrs = readAttributes(dataStore, view, editor, solidId);
170
+ if (!solidAttrs)
171
+ return null;
172
+ const profileId = asExpressIdRef(solidAttrs[0]);
173
+ const thicknessRaw = solidAttrs[3];
174
+ if (profileId === null || typeof thicknessRaw !== 'number' || !Number.isFinite(thicknessRaw) || thicknessRaw <= 0)
175
+ return null;
176
+ // Only a vertical extrusion of the plan outline can be cut in plan (#6233).
177
+ const frame = slabExtrusionFrame(dataStore, view, editor, chain.axisPlacementId, solidAttrs, thicknessRaw);
178
+ const baseElevation = frame === null ? null : placementOrigin[2] + frame.base;
179
+ const extrusionUp = frame?.up ?? true;
180
+ // IfcExtrudedAreaSolid.Position (attr 1) is an IfcAxis2Placement3D that
181
+ // places the profile in the solid's frame — real authoring tools bake
182
+ // the slab's plan offset + rotation here (in-store-built slabs leave it
183
+ // identity). Fold it into the footprint so the preview, cut line, and
184
+ // resulting halves land where the rendered mesh actually is.
185
+ const solidXform = resolveSolidPositionXform(dataStore, view, editor, asExpressIdRef(solidAttrs[1]));
186
+ // Profile dispatch — rectangle vs polygon, both produced by
187
+ // addSlabToStore. Source-buffer slabs with mapped representations,
188
+ // I-shape profiles, etc. land in `null` here and the slice
189
+ // surfaces a "not supported" toast.
190
+ const profileAttrs = readAttributes(dataStore, view, editor, profileId);
191
+ if (!profileAttrs)
192
+ return null;
193
+ const profileType = editor.getEntityType(profileId);
194
+ // Profile-local origin (IfcAxis2Placement2D.Location) — both
195
+ // profile kinds share this. May be null for the slot, in which
196
+ // case the spec defaults to origin = (0, 0).
197
+ const profilePosId = asExpressIdRef(profileAttrs[2]);
198
+ let profileOrigin2D = [0, 0];
199
+ if (profilePosId !== null) {
200
+ const profilePosAttrs = readAttributes(dataStore, view, editor, profilePosId);
201
+ if (profilePosAttrs) {
202
+ const profileOriginPtId = asExpressIdRef(profilePosAttrs[0]);
203
+ if (profileOriginPtId !== null) {
204
+ const profileOriginAttrs = readAttributes(dataStore, view, editor, profileOriginPtId);
205
+ if (profileOriginAttrs) {
206
+ const c = asCoordinateTriple(profileOriginAttrs[0]);
207
+ if (c)
208
+ profileOrigin2D = [c[0], c[1]];
209
+ }
210
+ }
211
+ }
212
+ }
213
+ if (profileType && profileType.toUpperCase() === 'IFCRECTANGLEPROFILEDEF') {
214
+ const xdim = profileAttrs[3];
215
+ const ydim = profileAttrs[4];
216
+ if (typeof xdim !== 'number' || typeof ydim !== 'number'
217
+ || !Number.isFinite(xdim) || xdim <= 0 || !Number.isFinite(ydim) || ydim <= 0)
218
+ return null;
219
+ return scaleSlabChain({
220
+ elementType,
221
+ placementOrigin,
222
+ baseElevation,
223
+ extrusionUp,
224
+ footprint: rectangleFootprint(placementOrigin, profileOrigin2D, xdim, ydim, solidXform),
225
+ extrudedSolidId: solidId,
226
+ thickness: thicknessRaw,
227
+ profileKind: 'rectangle',
228
+ }, scale);
229
+ }
230
+ if (profileType && profileType.toUpperCase() === 'IFCARBITRARYCLOSEDPROFILEDEF') {
231
+ // OuterCurve at attr 2.
232
+ const polylineId = asExpressIdRef(profileAttrs[2]);
233
+ if (polylineId === null)
234
+ return null;
235
+ const fp = polylineFootprint(dataStore, view, editor, polylineId, placementOrigin, profileOrigin2D, solidXform);
236
+ if (!fp)
237
+ return null;
238
+ return scaleSlabChain({
239
+ elementType,
240
+ placementOrigin,
241
+ baseElevation,
242
+ extrusionUp,
243
+ footprint: fp,
244
+ extrudedSolidId: solidId,
245
+ thickness: thicknessRaw,
246
+ profileKind: 'polygon',
247
+ }, scale);
248
+ }
249
+ return null;
250
+ }
251
+ /**
252
+ * Pure split-geometry helper. Clips the slab's footprint by a cut
253
+ * line (defined by two storey-local 2D points) and returns the two
254
+ * halves so the caller can build new slabs with `addSlab`. Both
255
+ * halves carry the source's thickness + storey placement; only the
256
+ * outer-curve polygon changes.
257
+ *
258
+ * Returns the underlying polygon-clip reason on failure so the UI
259
+ * can surface "Cut line does not cross the slab" verbatim.
260
+ */
261
+ export function computeSlabSplitGeometry(chain, cutA, cutB) {
262
+ const clipped = clipPolygonByLine(chain.footprint, cutA, cutB);
263
+ if (!clipped.ok) {
264
+ return { ok: false, reason: clipped.reason };
265
+ }
266
+ return {
267
+ ok: true,
268
+ leftFootprint: clipped.left,
269
+ rightFootprint: clipped.right,
270
+ thickness: chain.thickness,
271
+ placementOrigin: chain.placementOrigin,
272
+ elementType: chain.elementType,
273
+ };
274
+ }
275
+ //# sourceMappingURL=slab-edit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slab-edit.js","sourceRoot":"","sources":["../../../src/in-store/edit/slab-edit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { SplitEnvironment as SplitEnv } from '../element-split.js';
2
+ import type { SlabEditChain } from './slab-edit.js';
3
+ import type { Point2D } from './polygon-clip.js';
4
+ export interface SlabOpeningCarry {
5
+ readonly openingId: number;
6
+ /** Native-unit location in the new host, which starts at the body base. */
7
+ readonly location: [number, number, number];
8
+ }
9
+ export declare function planSlabOpeningCarry(env: SplitEnv, sourceId: number, chain: SlabEditChain, cut: readonly Point2D[], cutA: Point2D, cutB: Point2D, baseElevation: number): SlabOpeningCarry[];
10
+ //# sourceMappingURL=slab-opening-carry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slab-opening-carry.d.ts","sourceRoot":"","sources":["../../../src/in-store/edit/slab-opening-carry.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,gBAAgB,IAAI,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7C;AAED,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,OAAO,EAAE,EAC9E,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,GAClD,gBAAgB,EAAE,CA0CpB"}
@@ -0,0 +1,65 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ /** #6232: classify the entire physical cut before a slab split writes.
5
+ * Conservative canonical body bounds may refuse a crossing cut; a cut is
6
+ * never assigned from its origin alone. The shared placement writer commits
7
+ * the plan after the destination host exists. */
8
+ import { placedBodyExtent } from '../resolve-host.js';
9
+ import { resolveSpatialAnchor } from '../resolve-anchor.js';
10
+ import { toNativeLength } from '../anchor.js';
11
+ import { readHostedOpeningBatch } from '../hosted-fill-read.js';
12
+ import { AnchorEntityReader } from '../resolve-anchor.js';
13
+ import { refId } from '../host-geometry-frame.js';
14
+ export function planSlabOpeningCarry(env, sourceId, chain, cut, cutA, cutB, baseElevation) {
15
+ const reader = new AnchorEntityReader(env.dataStore, env.view), openingIds = new Set();
16
+ for (const id of reader.ids('IFCRELVOIDSELEMENT')) {
17
+ const rel = reader.entity(id);
18
+ if (!rel || refId(rel.attributes[4]) !== sourceId)
19
+ continue;
20
+ const openingId = refId(rel.attributes[5]);
21
+ if (openingId === null || openingIds.has(openingId))
22
+ throw new Error('A slab cut requires one readable void relationship per opening');
23
+ openingIds.add(openingId);
24
+ }
25
+ if (openingIds.size === 0)
26
+ return [];
27
+ // The footprint reader's accepted frame is unrotated and storey-local.
28
+ // Refuse a different placement parent rather than infer world offsets.
29
+ const host = reader.entity(sourceId), placementId = host ? refId(host.attributes[5]) : null;
30
+ const placement = placementId === null ? null : reader.entity(placementId);
31
+ const anchor = resolveSpatialAnchor(env.dataStore, env.storeyExpressId, env.view);
32
+ if (refId(placement?.attributes[0]) !== anchor.storeyPlacementId)
33
+ throw new Error('A slab with openings must be placed directly in its storey to split safely');
34
+ const dx = cutB[0] - cutA[0], dy = cutB[1] - cutA[1], length = Math.hypot(dx, dy);
35
+ const distance = (x, y) => (dx * (y - cutA[1]) - dy * (x - cutA[0])) / length;
36
+ const epsilon = 1e-7;
37
+ const sample = cut.map(([x, y]) => distance(x, y)).find(value => Math.abs(value) > epsilon);
38
+ if (sample === undefined)
39
+ throw new Error('The destination slab has no readable side of the cut');
40
+ const moves = [], k = env.lengthUnitScale;
41
+ const native = (metres) => toNativeLength({ lengthUnitScale: k }, metres);
42
+ const reads = readHostedOpeningBatch(env.dataStore, openingIds, env.view);
43
+ for (const openingId of openingIds) {
44
+ const read = reads.get(openingId);
45
+ const bounds = placedBodyExtent(env.dataStore, openingId, env.view);
46
+ if (!read || read.hostId !== sourceId || !bounds)
47
+ throw new Error('An unreadable slab opening cannot be carried safely');
48
+ const values = [bounds.min[0], bounds.max[0]].flatMap(x => [bounds.min[1], bounds.max[1]].map(y => distance(x * k + chain.placementOrigin[0], y * k + chain.placementOrigin[1])));
49
+ const min = Math.min(...values), max = Math.max(...values);
50
+ if (min < -epsilon && max > epsilon)
51
+ throw new Error('The slab split crosses a hosted opening');
52
+ const side = max > epsilon ? 1 : min < -epsilon ? -1 : 0;
53
+ if (side === 0)
54
+ throw new Error('The slab opening has no readable side of the cut');
55
+ if (side !== Math.sign(sample))
56
+ continue;
57
+ moves.push({ openingId, location: [
58
+ read.location[0] + native(chain.placementOrigin[0]),
59
+ read.location[1] + native(chain.placementOrigin[1]),
60
+ read.location[2] + native(chain.placementOrigin[2] - baseElevation),
61
+ ] });
62
+ }
63
+ return moves;
64
+ }
65
+ //# sourceMappingURL=slab-opening-carry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slab-opening-carry.js","sourceRoot":"","sources":["../../../src/in-store/edit/slab-opening-carry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { IfcDataStore } from '@ifc-lite/parser';
2
+ import type { MutablePropertyView } from '@ifc-lite/mutations';
3
+ /** ifc-lite's fixed namespace for split-piece GlobalIds. Never change it:
4
+ * every derived id in every saved model depends on it. */
5
+ export declare const SPLIT_GLOBALID_NAMESPACE = "5e904553-f79a-466a-8ec3-53d331437713";
6
+ /**
7
+ * The GlobalId for the next piece split off `sourceGlobalId`: the first
8
+ * `k = 0, 1, …` whose candidate `isTaken` rejects. Pure: the same source and
9
+ * the same set of existing ids give the same result.
10
+ */
11
+ export declare function deriveSplitGlobalId(sourceGlobalId: string, isTaken: (globalId: string) => boolean): string;
12
+ /**
13
+ * Whether the FIRST piece (the one containing the axis / profile start) keeps
14
+ * the source identity: it is at least as large as the second. Sizes are
15
+ * lengths or areas.
16
+ */
17
+ export declare function keepsFirstPiece(firstSize: number, secondSize: number): boolean;
18
+ /** What {@link globalIdTakenIn} needs of one loaded model. */
19
+ export interface GlobalIdScope {
20
+ dataStore: Pick<IfcDataStore, 'entities'> | null | undefined;
21
+ view: Pick<MutablePropertyView, 'getNewEntities'> | null | undefined;
22
+ }
23
+ /**
24
+ * "Does any loaded model already carry this GlobalId?" over the parsed index
25
+ * AND the entities authored this session, across every federated model — a
26
+ * split piece must not collide with an element of another model either.
27
+ */
28
+ export declare function globalIdTakenIn(scopes: Iterable<GlobalIdScope>): (globalId: string) => boolean;
29
+ //# sourceMappingURL=split-guid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"split-guid.d.ts","sourceRoot":"","sources":["../../../src/in-store/edit/split-guid.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D;2DAC2D;AAC3D,eAAO,MAAM,wBAAwB,yCAAyC,CAAC;AAE/E;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,GAAG,MAAM,CAK1G;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAE9E;AAED,8DAA8D;AAC9D,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;IAC7D,IAAI,EAAE,IAAI,CAAC,mBAAmB,EAAE,gBAAgB,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;CACtE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAY9F"}
@@ -0,0 +1,64 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ /**
5
+ * Identity policy for a split element (#6233, charter #6232 "Decisions").
6
+ *
7
+ * - The LARGER piece keeps the source entity: express id, GlobalId,
8
+ * containment, type, material, property sets. Larger is length for walls /
9
+ * beams / members / columns and footprint area for slabs / roofs / plates /
10
+ * spaces; a tie goes to the piece containing the axis / profile start
11
+ * ({@link keepsFirstPiece}).
12
+ * - The NEW piece's GlobalId is a name-based UUID (v5) of
13
+ * `${sourceGlobalId}/split/${k}` in {@link SPLIT_GLOBALID_NAMESPACE},
14
+ * encoded as the 22-character IFC GlobalId. `k` starts at 0 and increments
15
+ * while the candidate already exists ({@link deriveSplitGlobalId}). It does
16
+ * not depend on where the cut is, so the same source in the same model
17
+ * always yields the same id: a split replayed on another machine, or
18
+ * re-done after an undo, reproduces it.
19
+ */
20
+ import { uuidToIfcGuid, uuidV5 } from '@ifc-lite/encoding';
21
+ /** ifc-lite's fixed namespace for split-piece GlobalIds. Never change it:
22
+ * every derived id in every saved model depends on it. */
23
+ export const SPLIT_GLOBALID_NAMESPACE = '5e904553-f79a-466a-8ec3-53d331437713';
24
+ /**
25
+ * The GlobalId for the next piece split off `sourceGlobalId`: the first
26
+ * `k = 0, 1, …` whose candidate `isTaken` rejects. Pure: the same source and
27
+ * the same set of existing ids give the same result.
28
+ */
29
+ export function deriveSplitGlobalId(sourceGlobalId, isTaken) {
30
+ for (let k = 0;; k++) {
31
+ const candidate = uuidToIfcGuid(uuidV5(SPLIT_GLOBALID_NAMESPACE, `${sourceGlobalId}/split/${k}`));
32
+ if (!isTaken(candidate))
33
+ return candidate;
34
+ }
35
+ }
36
+ /**
37
+ * Whether the FIRST piece (the one containing the axis / profile start) keeps
38
+ * the source identity: it is at least as large as the second. Sizes are
39
+ * lengths or areas.
40
+ */
41
+ export function keepsFirstPiece(firstSize, secondSize) {
42
+ return firstSize >= secondSize;
43
+ }
44
+ /**
45
+ * "Does any loaded model already carry this GlobalId?" over the parsed index
46
+ * AND the entities authored this session, across every federated model — a
47
+ * split piece must not collide with an element of another model either.
48
+ */
49
+ export function globalIdTakenIn(scopes) {
50
+ const authored = new Set();
51
+ const stores = [];
52
+ for (const { dataStore, view } of scopes) {
53
+ if (dataStore)
54
+ stores.push(dataStore);
55
+ for (const entity of view?.getNewEntities() ?? []) {
56
+ const guid = entity.attributes[0];
57
+ if (typeof guid === 'string')
58
+ authored.add(guid);
59
+ }
60
+ }
61
+ return (globalId) => authored.has(globalId)
62
+ || stores.some((store) => (store.entities.getExpressIdByGlobalId?.(globalId) ?? -1) > 0);
63
+ }
64
+ //# sourceMappingURL=split-guid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"split-guid.js","sourceRoot":"","sources":["../../../src/in-store/edit/split-guid.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAI3D;2DAC2D;AAC3D,MAAM,CAAC,MAAM,wBAAwB,GAAG,sCAAsC,CAAC;AAE/E;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,cAAsB,EAAE,OAAsC;IAChG,KAAK,IAAI,CAAC,GAAG,CAAC,GAAI,CAAC,EAAE,EAAE,CAAC;QACtB,MAAM,SAAS,GAAG,aAAa,CAAC,MAAM,CAAC,wBAAwB,EAAE,GAAG,cAAc,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;QAClG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;IAC5C,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,SAAiB,EAAE,UAAkB;IACnE,OAAO,SAAS,IAAI,UAAU,CAAC;AACjC,CAAC;AAQD;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,MAA+B;IAC7D,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IACnC,MAAM,MAAM,GAA0C,EAAE,CAAC;IACzD,KAAK,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,MAAM,EAAE,CAAC;QACzC,IAAI,SAAS;YAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACtC,KAAK,MAAM,MAAM,IAAI,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,EAAE,CAAC;YAClD,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAClC,IAAI,OAAO,IAAI,KAAK,QAAQ;gBAAE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IACD,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC;WACtC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,sBAAsB,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7F,CAAC"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * The ONE answer to "can the Split tool cut this element, and how?" (#6233).
3
+ *
4
+ * The Properties panel's Split button, the canvas click that commits a cut,
5
+ * and the numeric-distance entry all route through {@link resolveSplitTarget}.
6
+ * They used to ask different questions: the button probed the wall reader
7
+ * (which, lacking a type check, also accepted beams and members), the click
8
+ * tried wall → linear → slab and on a miss printed a generic "not a
9
+ * splittable element". So the button could offer a split the commit then
10
+ * refused, and hide one with no explanation.
11
+ *
12
+ * A target is exactly one of three chain kinds, dispatched by IFC class:
13
+ * - `wall` — IfcWall / IfcWallStandardCase, rectangle profile, split by
14
+ * re-authoring two walls (`splitWallAtDistance`).
15
+ * - `linear` — IfcBeam / IfcColumn / IfcMember, rectangle profile, split by
16
+ * shrinking the extrusion (`splitLinearElementAtDistance`).
17
+ * - `slab` — IfcSlab / IfcRoof / IfcPlate / IfcSpace, rectangle or
18
+ * polyline profile, split by a cut line (`splitSlabByLine`).
19
+ * Anything else is a {@link SplitUnavailableCode} naming WHY, which the UI
20
+ * shows as the disabled button's tooltip and the tool's error notice.
21
+ */
22
+ import type { IfcDataStore } from '@ifc-lite/parser';
23
+ import type { MutablePropertyView, StoreEditor } from '@ifc-lite/mutations';
24
+ type TranslationKey = `splitTool.unavailable.${SplitUnavailableCode | 'kind'}`;
25
+ import { type WallEditChain } from './wall-edit.js';
26
+ import { type LinearElementEditChain } from './linear-element-edit.js';
27
+ import { type SlabEditChain } from './slab-edit.js';
28
+ export type SplitUnavailableCode =
29
+ /** Not a wall / beam / column / member / slab / roof / plate / space. */
30
+ 'type'
31
+ /** Not contained in any spatial element; the halves need a storey to live in. */
32
+ | 'storey'
33
+ /** Contained in a spatial element that is not a storey (IfcBuilding, IfcSite): the halves still need one. */
34
+ | 'container'
35
+ /** No body representation to cut. */
36
+ | 'noBody'
37
+ /** Triangulated / faceted / B-rep / surface-model body: no profile to cut. */
38
+ | 'mesh'
39
+ /** A mapped (type-instanced) body: cutting it would cut every instance. */
40
+ | 'mapped'
41
+ /** A boolean-clipped body (e.g. a wall clipped under a roof). */
42
+ | 'boolean'
43
+ /** An extrusion, but of a profile the cut math does not handle. */
44
+ | 'profile'
45
+ /** Supported shape family, but its placement / representation layout is not the one the reader walks. */
46
+ | 'shape';
47
+ /** A slab-like chain the split can cut: a vertical extrusion of its outline. */
48
+ export type SlabSplitChain = SlabEditChain & {
49
+ baseElevation: number;
50
+ };
51
+ export type SplitTarget = {
52
+ ok: true;
53
+ kind: 'wall';
54
+ chain: WallEditChain;
55
+ } | {
56
+ ok: true;
57
+ kind: 'linear';
58
+ chain: LinearElementEditChain;
59
+ } | {
60
+ ok: true;
61
+ kind: 'slab';
62
+ chain: SlabSplitChain;
63
+ } | {
64
+ ok: false;
65
+ code: SplitUnavailableCode;
66
+ };
67
+ /**
68
+ * Classify `expressId` for the Split tool. All lengths on a returned chain
69
+ * are metres (`lengthUnitScale` is the model's native-unit → metre factor).
70
+ */
71
+ export declare function resolveSplitTarget(dataStore: IfcDataStore, view: MutablePropertyView, editor: StoreEditor, expressId: number, lengthUnitScale: number): SplitTarget;
72
+ export interface SplitChains {
73
+ wall: WallEditChain;
74
+ linear: LinearElementEditChain;
75
+ slab: SlabSplitChain;
76
+ }
77
+ /**
78
+ * A commit action's gate: the chain when `target` is the `kind` that action
79
+ * cuts, else the catalogue key of the refusal — the same reason the Split
80
+ * button's tooltip shows for this element.
81
+ */
82
+ export declare function splitChainOfKind<K extends keyof SplitChains>(target: SplitTarget, kind: K): {
83
+ chain: SplitChains[K];
84
+ } | {
85
+ reasonKey: TranslationKey;
86
+ };
87
+ /** Catalogue key for each {@link SplitUnavailableCode}. */
88
+ export declare function splitUnavailableKey(code: SplitUnavailableCode): TranslationKey;
89
+ export {};
90
+ //# sourceMappingURL=split-target.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"split-target.d.ts","sourceRoot":"","sources":["../../../src/in-store/edit/split-target.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC5E,KAAK,cAAc,GAAG,yBAAyB,oBAAoB,GAAG,MAAM,EAAE,CAAC;AAE/E,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC1E,OAAO,EAA6B,KAAK,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClG,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAG1E,MAAM,MAAM,oBAAoB;AAC9B,yEAAyE;AACvE,MAAM;AACR,iFAAiF;GAC/E,QAAQ;AACV,6GAA6G;GAC3G,WAAW;AACb,qCAAqC;GACnC,QAAQ;AACV,8EAA8E;GAC5E,MAAM;AACR,2EAA2E;GACzE,QAAQ;AACV,iEAAiE;GAC/D,SAAS;AACX,mEAAmE;GACjE,SAAS;AACX,yGAAyG;GACvG,OAAO,CAAC;AAEZ,gFAAgF;AAChF,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvE,MAAM,MAAM,WAAW,GACnB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,aAAa,CAAA;CAAE,GAChD;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,sBAAsB,CAAA;CAAE,GAC3D;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,cAAc,CAAA;CAAE,GACjD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,oBAAoB,CAAA;CAAE,CAAC;AAW9C;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,YAAY,EACvB,IAAI,EAAE,mBAAmB,EACzB,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,MAAM,GACtB,WAAW,CA0Bb;AAqCD,MAAM,WAAW,WAAW;IAAG,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,sBAAsB,CAAC;IAAC,IAAI,EAAE,cAAc,CAAA;CAAE;AAE1G;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,WAAW,EAC1D,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,CAAC,GACN;IAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,CAAA;CAAE,GAAG;IAAE,SAAS,EAAE,cAAc,CAAA;CAAE,CAK3D;AAED,2DAA2D;AAC3D,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,oBAAoB,GAAG,cAAc,CAY9E"}