BIMInventoryTool.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /*
  2. * BIMInventoryTool.js
  3. *
  4. * @author realor
  5. */
  6. import { Tool } from './Tool.js'
  7. import { TabbedPane } from '../ui/TabbedPane.js'
  8. import { Tree } from '../ui/Tree.js'
  9. import { Controls } from '../ui/Controls.js'
  10. import { ObjectUtils } from '../utils/ObjectUtils.js'
  11. class BIMInventoryTool extends Tool {
  12. constructor(application, options) {
  13. super(application)
  14. this.name = 'bim_inventory'
  15. this.label = 'bim|tool.bim_inventory.label'
  16. this.help = 'bim|tool.bim_inventory.help'
  17. this.className = 'bim_inventory'
  18. this.setOptions(options)
  19. this.types = {}
  20. this.classifications = {}
  21. this.groups = {}
  22. this.layers = {}
  23. this.createPanel()
  24. }
  25. createPanel() {
  26. this.panel = this.application.createPanel(this.label, 'left')
  27. this.panel.bodyElem.classList.add('padding')
  28. this.exploreButton = Controls.addButton(this.panel.bodyElem, 'bim_inventory_explore', 'bim|button.explore_selection', () => this.explore())
  29. // tabs
  30. this.tabbedPane = new TabbedPane(this.panel.bodyElem)
  31. this.tabbedPane.paneElem.classList.add('bim_inventory_tabs')
  32. this.typesPanelElem = this.tabbedPane.addTab('ifc_types', 'bim|tab.types')
  33. this.typesTree = new Tree(this.typesPanelElem)
  34. this.classifPanelElem = this.tabbedPane.addTab('ifc_classif', 'bim|tab.classifications')
  35. this.classifTree = new Tree(this.classifPanelElem)
  36. this.groupsPanelElem = this.tabbedPane.addTab('ifc_groups', 'bim|tab.groups')
  37. this.groupsTree = new Tree(this.groupsPanelElem)
  38. this.layersPanelElem = this.tabbedPane.addTab('ifc_layers', 'bim|tab.layers')
  39. this.layersTree = new Tree(this.layersPanelElem)
  40. }
  41. activate() {
  42. this.panel.visible = true
  43. if (this.needsUpdate()) {
  44. this.types = {}
  45. this.classifications = {}
  46. this.groups = {}
  47. this.typesTree.clear()
  48. this.classifTree.clear()
  49. this.groupsTree.clear()
  50. this.layersTree.clear()
  51. }
  52. }
  53. deactivate() {
  54. this.panel.visible = false
  55. }
  56. explore() {
  57. let baseObjects = this.application.selection.roots
  58. if (baseObjects.length === 0) {
  59. baseObjects = [this.application.baseObject]
  60. }
  61. // types
  62. this.findTypes(baseObjects)
  63. this.showTypes()
  64. // classifications
  65. this.findClassifications(baseObjects)
  66. this.showClassifications()
  67. // groups
  68. this.findGroups(baseObjects)
  69. this.showGroups()
  70. // layers
  71. this.findLayers(baseObjects)
  72. this.showLayers()
  73. }
  74. findTypes(baseObjects) {
  75. this.types = {}
  76. let types = this.types
  77. for (let baseObject of baseObjects) {
  78. baseObject.traverse(object => {
  79. if (object.userData.IFC && object.userData.IFC.ifcClassName && object.type === 'Object3D') {
  80. let ifcClassName = object.userData.IFC.ifcClassName
  81. let type = types[ifcClassName]
  82. if (type === undefined) {
  83. type = {
  84. name: ifcClassName,
  85. objects: [],
  86. subTypes: {}
  87. }
  88. types[ifcClassName] = type
  89. }
  90. type.objects.push(object)
  91. let typeId = object.userData.IFC_type ? object.userData.IFC_type.GlobalId : '?'
  92. let typeName = object.userData.IFC_type ? object.userData.IFC_type.Name || 'Unnamed' : 'Others'
  93. let subType = type.subTypes[typeId]
  94. if (subType === undefined) {
  95. subType = {
  96. typeId: typeId,
  97. name: typeName,
  98. objects: []
  99. }
  100. type.subTypes[typeId] = subType
  101. }
  102. subType.objects.push(object)
  103. }
  104. })
  105. }
  106. }
  107. findClassifications(baseObjects) {
  108. this.classifications = {}
  109. let classifs = this.classifications
  110. // find classifications
  111. for (let baseObject of baseObjects) {
  112. baseObject.traverse(object => {
  113. if (object.userData.IFC && object.type === 'Object3D') {
  114. for (let key in object.userData) {
  115. if (key.indexOf('IFC_classification_') === 0) {
  116. let classifName = key.substring(19)
  117. if (classifs[classifName] === undefined) {
  118. classifs[classifName] = {
  119. name: classifName,
  120. references: {}
  121. }
  122. }
  123. }
  124. }
  125. }
  126. })
  127. }
  128. for (let baseObject of baseObjects) {
  129. baseObject.traverse(object => {
  130. if (object.userData.IFC && object.type === 'Object3D') {
  131. for (let classifName in classifs) {
  132. let key = 'IFC_classification_' + classifName
  133. let classifData = object.userData[key]
  134. let identification = classifData ? classifData.Identification || classifData.ItemReference : '?'
  135. let references = classifs[classifName].references
  136. if (references[identification] === undefined) {
  137. references[identification] = {
  138. identification: identification,
  139. name: classifData ? classifData.Name : 'Not classified',
  140. objects: []
  141. }
  142. }
  143. references[identification].objects.push(object)
  144. }
  145. }
  146. })
  147. }
  148. }
  149. findGroups(baseObjects) {
  150. this.groups = {}
  151. let groups = this.groups
  152. for (let baseObject of baseObjects) {
  153. baseObject.traverse(object => {
  154. if (object.userData.IFC && object.type === 'Object3D') {
  155. for (let key in object.userData) {
  156. if (key.indexOf('IFC_group_') === 0) {
  157. let group = object.userData[key]
  158. let groupName = key.substring(10)
  159. if (groups[groupName] === undefined) {
  160. groups[groupName] = {
  161. ifcClassName: group.ifcClassName,
  162. name: groupName,
  163. objects: []
  164. }
  165. }
  166. groups[groupName].objects.push(object)
  167. }
  168. }
  169. }
  170. })
  171. }
  172. }
  173. findLayers(baseObjects) {
  174. this.layers = {}
  175. let layers = this.layers
  176. for (let baseObject of baseObjects) {
  177. baseObject.traverse(object => {
  178. if (object.userData.IFC_layer) {
  179. let layerName = object.userData.IFC_layer.Name
  180. let layer = layers[layerName]
  181. if (typeof layer === 'undefined') {
  182. layer = { name: layerName, objects: [] }
  183. layers[layerName] = layer
  184. }
  185. layer.objects.push(object)
  186. }
  187. })
  188. }
  189. }
  190. showTypes() {
  191. let typeNames = Object.keys(this.types)
  192. typeNames.sort()
  193. this.typesTree.clear()
  194. for (let typeName of typeNames) {
  195. let type = this.types[typeName]
  196. let objects = type.objects
  197. let label = type.name + ' (' + objects.length + ')'
  198. let className = typeName
  199. let node = this.typesTree.addNode(label, event => this.application.userSelectObjects(objects, event), className)
  200. let subTypes = []
  201. for (let typeId in type.subTypes) {
  202. subTypes.push(type.subTypes[typeId])
  203. }
  204. subTypes.sort((typeA, typeB) => {
  205. if (typeA.name < typeB.name) return -1
  206. if (typeA.name > typeB.name) return 1
  207. return 0
  208. })
  209. if (subTypes.length > 1 || subTypes[0].name !== 'Others') {
  210. for (let subType of subTypes) {
  211. let subObjects = subType.objects
  212. let subLabel = subType.name + ' (' + subObjects.length + ')'
  213. node.addNode(subLabel, event => this.application.userSelectObjects(subObjects, event), 'IfcType')
  214. }
  215. }
  216. }
  217. }
  218. showClassifications() {
  219. let classifNames = Object.keys(this.classifications)
  220. classifNames.sort()
  221. this.classifTree.clear()
  222. for (let classifName of classifNames) {
  223. let classif = this.classifications[classifName]
  224. let label = classif.name
  225. let node = this.classifTree.addNode(label, null, 'IfcClassification')
  226. if (classifNames.length === 1) node.expand()
  227. let references = classif.references
  228. let referenceIds = Object.keys(references)
  229. referenceIds.sort()
  230. for (let referenceId of referenceIds) {
  231. let reference = references[referenceId]
  232. let objects = reference.objects
  233. let subLabel = referenceId
  234. if (reference.name) subLabel += ': ' + reference.name
  235. subLabel += ' (' + objects.length + ')'
  236. node.addNode(subLabel, event => this.application.userSelectObjects(objects, event), 'IfcClassificationReference')
  237. }
  238. }
  239. }
  240. showGroups() {
  241. let groupNames = Object.keys(this.groups)
  242. groupNames.sort()
  243. this.groupsTree.clear()
  244. for (let groupName of groupNames) {
  245. let group = this.groups[groupName]
  246. let objects = group.objects
  247. let label = group.name + ' (' + objects.length + ')'
  248. this.groupsTree.addNode(label, event => this.application.userSelectObjects(objects, event), 'IfcGroup')
  249. }
  250. }
  251. showLayers() {
  252. let layerNames = Object.keys(this.layers)
  253. layerNames.sort()
  254. this.layersTree.clear()
  255. for (let layerName of layerNames) {
  256. let layer = this.layers[layerName]
  257. let objects = layer.objects
  258. let label = layer.name + ' (' + objects.length + ')'
  259. this.layersTree.addNode(label, event => this.application.userSelectObjects(objects, event), 'IfcLayer')
  260. }
  261. }
  262. needsUpdate() {
  263. /* update is needed if objects were removed */
  264. const types = this.types
  265. const baseObject = this.application.baseObject
  266. for (let key in types) {
  267. let type = types[key]
  268. let objects = type.objects
  269. for (let i = 0; i < objects.length; i++) {
  270. let object = objects[i]
  271. if (!ObjectUtils.isObjectDescendantOf(object, baseObject)) return true
  272. }
  273. }
  274. return false
  275. }
  276. }
  277. export { BIMInventoryTool }