cdn.jsdelivr.net_npm_web-ifc-three@0.0.126_IFCLoader.js 78 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657
  1. import * as WebIFC from 'web-ifc';
  2. import { IFCSPACE, IFCOPENINGELEMENT, IFCPRODUCTDEFINITIONSHAPE, IFCRELAGGREGATES, IFCRELCONTAINEDINSPATIALSTRUCTURE, IFCRELDEFINESBYPROPERTIES, IFCRELASSOCIATESMATERIAL, IFCRELDEFINESBYTYPE, IFCPROJECT, IFCBUILDING } from 'web-ifc';
  3. import { Mesh, Color, MeshLambertMaterial, DoubleSide, Matrix4, BufferGeometry, BufferAttribute, Loader, FileLoader } from 'three';
  4. import { mergeGeometries } from 'three/examples/jsm/utils/BufferGeometryUtils';
  5. const nullIfcManagerErrorMessage = 'IfcManager is null!';
  6. class IFCModel extends Mesh {
  7. constructor() {
  8. super(...arguments);
  9. this.modelID = IFCModel.modelIdCounter++;
  10. this.ifcManager = null;
  11. this.mesh = this;
  12. }
  13. static dispose() {
  14. IFCModel.modelIdCounter = 0;
  15. }
  16. setIFCManager(manager) {
  17. this.ifcManager = manager;
  18. }
  19. setWasmPath(path) {
  20. if (this.ifcManager === null)
  21. throw new Error(nullIfcManagerErrorMessage);
  22. this.ifcManager.setWasmPath(path);
  23. }
  24. close(scene) {
  25. if (this.ifcManager === null)
  26. throw new Error(nullIfcManagerErrorMessage);
  27. this.ifcManager.close(this.modelID, scene);
  28. }
  29. getExpressId(geometry, faceIndex) {
  30. if (this.ifcManager === null)
  31. throw new Error(nullIfcManagerErrorMessage);
  32. return this.ifcManager.getExpressId(geometry, faceIndex);
  33. }
  34. getAllItemsOfType(type, verbose) {
  35. if (this.ifcManager === null)
  36. throw new Error(nullIfcManagerErrorMessage);
  37. return this.ifcManager.getAllItemsOfType(this.modelID, type, verbose);
  38. }
  39. getItemProperties(id, recursive = false) {
  40. if (this.ifcManager === null)
  41. throw new Error(nullIfcManagerErrorMessage);
  42. return this.ifcManager.getItemProperties(this.modelID, id, recursive);
  43. }
  44. getPropertySets(id, recursive = false) {
  45. if (this.ifcManager === null)
  46. throw new Error(nullIfcManagerErrorMessage);
  47. return this.ifcManager.getPropertySets(this.modelID, id, recursive);
  48. }
  49. getTypeProperties(id, recursive = false) {
  50. if (this.ifcManager === null)
  51. throw new Error(nullIfcManagerErrorMessage);
  52. return this.ifcManager.getTypeProperties(this.modelID, id, recursive);
  53. }
  54. getIfcType(id) {
  55. if (this.ifcManager === null)
  56. throw new Error(nullIfcManagerErrorMessage);
  57. return this.ifcManager.getIfcType(this.modelID, id);
  58. }
  59. getSpatialStructure() {
  60. if (this.ifcManager === null)
  61. throw new Error(nullIfcManagerErrorMessage);
  62. return this.ifcManager.getSpatialStructure(this.modelID);
  63. }
  64. getSubset(material) {
  65. if (this.ifcManager === null)
  66. throw new Error(nullIfcManagerErrorMessage);
  67. return this.ifcManager.getSubset(this.modelID, material);
  68. }
  69. removeSubset(material, customID) {
  70. if (this.ifcManager === null)
  71. throw new Error(nullIfcManagerErrorMessage);
  72. this.ifcManager.removeSubset(this.modelID, material, customID);
  73. }
  74. createSubset(config) {
  75. if (this.ifcManager === null)
  76. throw new Error(nullIfcManagerErrorMessage);
  77. const modelConfig = {
  78. ...config,
  79. modelID: this.modelID
  80. };
  81. return this.ifcManager.createSubset(modelConfig);
  82. }
  83. }
  84. IFCModel.modelIdCounter = 0;
  85. class IFCParser {
  86. constructor(state, BVH) {
  87. this.state = state;
  88. this.BVH = BVH;
  89. this.loadedModels = 0;
  90. this.optionalCategories = {
  91. [IFCSPACE]: true,
  92. [IFCOPENINGELEMENT]: false
  93. };
  94. this.geometriesByMaterials = {};
  95. this.loadingState = {
  96. total: 0,
  97. current: 0,
  98. step: 0.1
  99. };
  100. this.currentWebIfcID = -1;
  101. this.currentModelID = -1;
  102. }
  103. async setupOptionalCategories(config) {
  104. this.optionalCategories = config;
  105. }
  106. async parse(buffer, coordinationMatrix) {
  107. if (this.state.api.wasmModule === undefined)
  108. await this.state.api.Init();
  109. await this.newIfcModel(buffer);
  110. this.loadedModels++;
  111. if (coordinationMatrix) {
  112. await this.state.api.SetGeometryTransformation(this.currentWebIfcID, coordinationMatrix);
  113. }
  114. return this.loadAllGeometry(this.currentWebIfcID);
  115. }
  116. getAndClearErrors(_modelId) {}
  117. notifyProgress(loaded, total) {
  118. if (this.state.onProgress)
  119. this.state.onProgress({
  120. loaded,
  121. total
  122. });
  123. }
  124. async newIfcModel(buffer) {
  125. const data = new Uint8Array(buffer);
  126. this.currentWebIfcID = await this.state.api.OpenModel(data, this.state.webIfcSettings);
  127. this.currentModelID = this.state.useJSON ? this.loadedModels : this.currentWebIfcID;
  128. this.state.models[this.currentModelID] = {
  129. modelID: this.currentModelID,
  130. mesh: {},
  131. types: {},
  132. jsonData: {}
  133. };
  134. }
  135. async loadAllGeometry(modelID) {
  136. this.addOptionalCategories(modelID);
  137. await this.initializeLoadingState(modelID);
  138. this.state.api.StreamAllMeshes(modelID, (mesh) => {
  139. this.updateLoadingState();
  140. this.streamMesh(modelID, mesh);
  141. });
  142. this.notifyLoadingEnded();
  143. const geometries = [];
  144. const materials = [];
  145. Object.keys(this.geometriesByMaterials).forEach((key) => {
  146. const geometriesByMaterial = this.geometriesByMaterials[key].geometries;
  147. const merged = mergeGeometries(geometriesByMaterial);
  148. materials.push(this.geometriesByMaterials[key].material);
  149. geometries.push(merged);
  150. });
  151. const combinedGeometry = mergeGeometries(geometries, true);
  152. this.cleanUpGeometryMemory(geometries);
  153. if (this.BVH)
  154. this.BVH.applyThreeMeshBVH(combinedGeometry);
  155. const model = new IFCModel(combinedGeometry, materials);
  156. this.state.models[this.currentModelID].mesh = model;
  157. return model;
  158. }
  159. async initializeLoadingState(modelID) {
  160. const shapes = await this.state.api.GetLineIDsWithType(modelID, IFCPRODUCTDEFINITIONSHAPE);
  161. this.loadingState.total = shapes.size();
  162. this.loadingState.current = 0;
  163. this.loadingState.step = 0.1;
  164. }
  165. notifyLoadingEnded() {
  166. this.notifyProgress(this.loadingState.total, this.loadingState.total);
  167. }
  168. updateLoadingState() {
  169. const realCurrentItem = Math.min(this.loadingState.current++, this.loadingState.total);
  170. if (realCurrentItem / this.loadingState.total >= this.loadingState.step) {
  171. const currentProgress = Math.ceil(this.loadingState.total * this.loadingState.step);
  172. this.notifyProgress(currentProgress, this.loadingState.total);
  173. this.loadingState.step += 0.1;
  174. }
  175. }
  176. addOptionalCategories(modelID) {
  177. const optionalTypes = [];
  178. for (let key in this.optionalCategories) {
  179. if (this.optionalCategories.hasOwnProperty(key)) {
  180. const category = parseInt(key);
  181. if (this.optionalCategories[category])
  182. optionalTypes.push(category);
  183. }
  184. }
  185. this.state.api.StreamAllMeshesWithTypes(this.currentWebIfcID, optionalTypes, (mesh) => {
  186. this.streamMesh(modelID, mesh);
  187. });
  188. }
  189. streamMesh(modelID, mesh) {
  190. const placedGeometries = mesh.geometries;
  191. const size = placedGeometries.size();
  192. for (let i = 0; i < size; i++) {
  193. const placedGeometry = placedGeometries.get(i);
  194. let itemMesh = this.getPlacedGeometry(modelID, mesh.expressID, placedGeometry);
  195. let geom = itemMesh.geometry.applyMatrix4(itemMesh.matrix);
  196. this.storeGeometryByMaterial(placedGeometry.color, geom);
  197. }
  198. }
  199. getPlacedGeometry(modelID, expressID, placedGeometry) {
  200. const geometry = this.getBufferGeometry(modelID, expressID, placedGeometry);
  201. const mesh = new Mesh(geometry);
  202. mesh.matrix = this.getMeshMatrix(placedGeometry.flatTransformation);
  203. mesh.matrixAutoUpdate = false;
  204. return mesh;
  205. }
  206. getBufferGeometry(modelID, expressID, placedGeometry) {
  207. const geometry = this.state.api.GetGeometry(modelID, placedGeometry.geometryExpressID);
  208. const verts = this.state.api.GetVertexArray(geometry.GetVertexData(), geometry.GetVertexDataSize());
  209. const indices = this.state.api.GetIndexArray(geometry.GetIndexData(), geometry.GetIndexDataSize());
  210. const buffer = this.ifcGeometryToBuffer(expressID, verts, indices);
  211. geometry.delete();
  212. return buffer;
  213. }
  214. storeGeometryByMaterial(color, geometry) {
  215. let colID = `${color.x}${color.y}${color.z}${color.w}`;
  216. if (this.geometriesByMaterials[colID]) {
  217. this.geometriesByMaterials[colID].geometries.push(geometry);
  218. return;
  219. }
  220. const col = new Color().setRGB(color.x, color.y, color.z, 'srgb');
  221. const material = new MeshLambertMaterial({
  222. color: col,
  223. side: DoubleSide
  224. });
  225. material.transparent = color.w !== 1;
  226. if (material.transparent)
  227. material.opacity = color.w;
  228. this.geometriesByMaterials[colID] = {
  229. material,
  230. geometries: [geometry]
  231. };
  232. }
  233. getMeshMatrix(matrix) {
  234. const mat = new Matrix4();
  235. mat.fromArray(matrix);
  236. return mat;
  237. }
  238. ifcGeometryToBuffer(expressID, vertexData, indexData) {
  239. const geometry = new BufferGeometry();
  240. const posFloats = new Float32Array(vertexData.length / 2);
  241. const normFloats = new Float32Array(vertexData.length / 2);
  242. const idAttribute = new Uint32Array(vertexData.length / 6);
  243. for (let i = 0; i < vertexData.length; i += 6) {
  244. posFloats[i / 2] = vertexData[i];
  245. posFloats[i / 2 + 1] = vertexData[i + 1];
  246. posFloats[i / 2 + 2] = vertexData[i + 2];
  247. normFloats[i / 2] = vertexData[i + 3];
  248. normFloats[i / 2 + 1] = vertexData[i + 4];
  249. normFloats[i / 2 + 2] = vertexData[i + 5];
  250. idAttribute[i / 6] = expressID;
  251. }
  252. geometry.setAttribute('position', new BufferAttribute(posFloats, 3));
  253. geometry.setAttribute('normal', new BufferAttribute(normFloats, 3));
  254. geometry.setAttribute('expressID', new BufferAttribute(idAttribute, 1));
  255. geometry.setIndex(new BufferAttribute(indexData, 1));
  256. return geometry;
  257. }
  258. cleanUpGeometryMemory(geometries) {
  259. geometries.forEach(geometry => geometry.dispose());
  260. Object.keys(this.geometriesByMaterials).forEach((materialID) => {
  261. const geometriesByMaterial = this.geometriesByMaterials[materialID];
  262. geometriesByMaterial.geometries.forEach(geometry => geometry.dispose());
  263. geometriesByMaterial.geometries = [];
  264. geometriesByMaterial.material = null;
  265. });
  266. this.geometriesByMaterials = {};
  267. }
  268. }
  269. class ItemsMap {
  270. constructor(state) {
  271. this.state = state;
  272. this.map = {};
  273. }
  274. generateGeometryIndexMap(modelID) {
  275. if (this.map[modelID])
  276. return;
  277. const geometry = this.getGeometry(modelID);
  278. const items = this.newItemsMap(modelID, geometry);
  279. for (const group of geometry.groups) {
  280. this.fillItemsWithGroupInfo(group, geometry, items);
  281. }
  282. }
  283. getSubsetID(modelID, material, customID = 'DEFAULT') {
  284. const baseID = modelID;
  285. const materialID = material ? material.uuid : 'DEFAULT';
  286. return `${baseID} - ${materialID} - ${customID}`;
  287. }
  288. dispose() {
  289. Object.values(this.map).forEach(model => {
  290. model.indexCache = null;
  291. model.map = null;
  292. });
  293. this.map = null;
  294. }
  295. getGeometry(modelID) {
  296. const geometry = this.state.models[modelID].mesh.geometry;
  297. if (!geometry)
  298. throw new Error('Model without geometry.');
  299. if (!geometry.index)
  300. throw new Error('Geometry must be indexed');
  301. return geometry;
  302. }
  303. newItemsMap(modelID, geometry) {
  304. const startIndices = geometry.index.array;
  305. this.map[modelID] = {
  306. indexCache: startIndices.slice(0, geometry.index.array.length),
  307. map: new Map()
  308. };
  309. return this.map[modelID];
  310. }
  311. fillItemsWithGroupInfo(group, geometry, items) {
  312. let prevExpressID = -1;
  313. const materialIndex = group.materialIndex;
  314. const materialStart = group.start;
  315. const materialEnd = materialStart + group.count - 1;
  316. let objectStart = -1;
  317. let objectEnd = -1;
  318. for (let i = materialStart; i <= materialEnd; i++) {
  319. const index = geometry.index.array[i];
  320. const bufferAttr = geometry.attributes.expressID;
  321. const expressID = bufferAttr.array[index];
  322. if (prevExpressID === -1) {
  323. prevExpressID = expressID;
  324. objectStart = i;
  325. }
  326. const isEndOfMaterial = i === materialEnd;
  327. if (isEndOfMaterial) {
  328. const store = this.getMaterialStore(items.map, expressID, materialIndex);
  329. store.push(objectStart, materialEnd);
  330. break;
  331. }
  332. if (prevExpressID === expressID)
  333. continue;
  334. const store = this.getMaterialStore(items.map, prevExpressID, materialIndex);
  335. objectEnd = i - 1;
  336. store.push(objectStart, objectEnd);
  337. prevExpressID = expressID;
  338. objectStart = i;
  339. }
  340. }
  341. getMaterialStore(map, id, matIndex) {
  342. if (map.get(id) === undefined) {
  343. map.set(id, {});
  344. }
  345. const storedIfcItem = map.get(id);
  346. if (storedIfcItem === undefined)
  347. throw new Error('Geometry map generation error');
  348. if (storedIfcItem[matIndex] === undefined) {
  349. storedIfcItem[matIndex] = [];
  350. }
  351. return storedIfcItem[matIndex];
  352. }
  353. }
  354. class SubsetUtils {
  355. static getAllIndicesOfGroup(modelID, ids, materialIndex, items, flatten = true) {
  356. const indicesByGroup = [];
  357. for (const expressID of ids) {
  358. const entry = items.map.get(expressID);
  359. if (!entry)
  360. continue;
  361. const value = entry[materialIndex];
  362. if (!value)
  363. continue;
  364. SubsetUtils.getIndexChunk(value, indicesByGroup, materialIndex, items, flatten);
  365. }
  366. return indicesByGroup;
  367. }
  368. static getIndexChunk(value, indicesByGroup, materialIndex, items, flatten) {
  369. const pairs = value.length / 2;
  370. for (let pair = 0; pair < pairs; pair++) {
  371. const pairIndex = pair * 2;
  372. const start = value[pairIndex];
  373. const end = value[pairIndex + 1];
  374. for (let j = start; j <= end; j++) {
  375. if (flatten)
  376. indicesByGroup.push(items.indexCache[j]);
  377. else {
  378. if (!indicesByGroup[materialIndex])
  379. indicesByGroup[materialIndex] = [];
  380. indicesByGroup[materialIndex].push(items.indexCache[j]);
  381. }
  382. }
  383. }
  384. }
  385. }
  386. class SubsetCreator {
  387. constructor(state, items, subsets, BVH) {
  388. this.state = state;
  389. this.items = items;
  390. this.subsets = subsets;
  391. this.BVH = BVH;
  392. this.tempIndex = [];
  393. }
  394. createSubset(config, subsetID) {
  395. if (!this.items.map[config.modelID])
  396. this.items.generateGeometryIndexMap(config.modelID);
  397. if (!this.subsets[subsetID])
  398. this.initializeSubset(config, subsetID);
  399. this.filterIndices(config, subsetID);
  400. this.constructSubsetByMaterial(config, subsetID);
  401. config.ids.forEach(id => this.subsets[subsetID].ids.add(id));
  402. this.subsets[subsetID].mesh.geometry.setIndex(this.tempIndex);
  403. this.tempIndex.length = 0;
  404. const subset = this.subsets[subsetID].mesh;
  405. if (config.applyBVH)
  406. this.BVH.applyThreeMeshBVH(subset.geometry);
  407. if (config.scene)
  408. config.scene.add(subset);
  409. return this.subsets[subsetID].mesh;
  410. }
  411. dispose() {
  412. this.tempIndex = [];
  413. }
  414. initializeSubset(config, subsetID) {
  415. const model = this.state.models[config.modelID].mesh;
  416. const subsetGeom = new BufferGeometry();
  417. this.initializeSubsetAttributes(subsetGeom, model);
  418. if (!config.material)
  419. this.initializeSubsetGroups(subsetGeom, model);
  420. const mesh = new Mesh(subsetGeom, config.material || model.material);
  421. mesh.modelID = config.modelID;
  422. const bvh = Boolean(config.applyBVH);
  423. this.subsets[subsetID] = {
  424. ids: new Set(),
  425. mesh,
  426. bvh
  427. };
  428. model.add(mesh);
  429. }
  430. initializeSubsetAttributes(subsetGeom, model) {
  431. subsetGeom.setAttribute('position', model.geometry.attributes.position);
  432. subsetGeom.setAttribute('normal', model.geometry.attributes.normal);
  433. subsetGeom.setAttribute('expressID', model.geometry.attributes.expressID);
  434. subsetGeom.setIndex([]);
  435. }
  436. initializeSubsetGroups(subsetGeom, model) {
  437. subsetGeom.groups = JSON.parse(JSON.stringify(model.geometry.groups));
  438. this.resetGroups(subsetGeom);
  439. }
  440. filterIndices(config, subsetID) {
  441. const geometry = this.subsets[subsetID].mesh.geometry;
  442. if (config.removePrevious) {
  443. geometry.setIndex([]);
  444. this.resetGroups(geometry);
  445. return;
  446. }
  447. const previousIndices = geometry.index.array;
  448. const previousIDs = this.subsets[subsetID].ids;
  449. config.ids = config.ids.filter(id => !previousIDs.has(id));
  450. this.tempIndex = Array.from(previousIndices);
  451. }
  452. constructSubsetByMaterial(config, subsetID) {
  453. const model = this.state.models[config.modelID].mesh;
  454. const newIndices = {
  455. count: 0
  456. };
  457. for (let i = 0; i < model.geometry.groups.length; i++) {
  458. this.insertNewIndices(config, subsetID, i, newIndices);
  459. }
  460. }
  461. insertNewIndices(config, subsetID, materialIndex, newIndices) {
  462. const items = this.items.map[config.modelID];
  463. const indicesOfOneMaterial = SubsetUtils.getAllIndicesOfGroup(config.modelID, config.ids, materialIndex, items);
  464. if (!config.material) {
  465. this.insertIndicesAtGroup(subsetID, indicesOfOneMaterial, materialIndex, newIndices);
  466. } else {
  467. indicesOfOneMaterial.forEach(index => this.tempIndex.push(index));
  468. }
  469. }
  470. insertIndicesAtGroup(subsetID, indicesByGroup, index, newIndices) {
  471. const currentGroup = this.getCurrentGroup(subsetID, index);
  472. currentGroup.start += newIndices.count;
  473. let newIndicesPosition = currentGroup.start + currentGroup.count;
  474. newIndices.count += indicesByGroup.length;
  475. if (indicesByGroup.length > 0) {
  476. let position = newIndicesPosition;
  477. const start = this.tempIndex.slice(0, position);
  478. const end = this.tempIndex.slice(position);
  479. this.tempIndex = Array.prototype.concat.apply([], [start, indicesByGroup, end]);
  480. currentGroup.count += indicesByGroup.length;
  481. }
  482. }
  483. getCurrentGroup(subsetID, groupIndex) {
  484. const geometry = this.subsets[subsetID].mesh.geometry;
  485. return geometry.groups[groupIndex];
  486. }
  487. resetGroups(geometry) {
  488. geometry.groups.forEach((group) => {
  489. group.start = 0;
  490. group.count = 0;
  491. });
  492. }
  493. }
  494. class SubsetManager {
  495. constructor(state, BVH) {
  496. this.subsets = {};
  497. this.state = state;
  498. this.items = new ItemsMap(state);
  499. this.BVH = BVH;
  500. this.subsetCreator = new SubsetCreator(state, this.items, this.subsets, this.BVH);
  501. }
  502. getAllSubsets() {
  503. return this.subsets;
  504. }
  505. getSubset(modelID, material, customId) {
  506. const subsetID = this.getSubsetID(modelID, material, customId);
  507. return this.subsets[subsetID].mesh;
  508. }
  509. removeSubset(modelID, material, customID) {
  510. const subsetID = this.getSubsetID(modelID, material, customID);
  511. const subset = this.subsets[subsetID];
  512. if (!subset)
  513. return;
  514. if (subset.mesh.parent)
  515. subset.mesh.removeFromParent();
  516. subset.mesh.geometry.attributes = {};
  517. subset.mesh.geometry.index = null;
  518. subset.mesh.geometry.dispose();
  519. subset.mesh.geometry = null;
  520. delete this.subsets[subsetID];
  521. }
  522. createSubset(config) {
  523. const subsetID = this.getSubsetID(config.modelID, config.material, config.customID);
  524. return this.subsetCreator.createSubset(config, subsetID);
  525. }
  526. removeFromSubset(modelID, ids, customID, material) {
  527. const subsetID = this.getSubsetID(modelID, material, customID);
  528. if (!this.subsets[subsetID])
  529. return;
  530. const previousIDs = this.subsets[subsetID].ids;
  531. ids.forEach((id) => {
  532. if (previousIDs.has(id))
  533. previousIDs.delete(id);
  534. });
  535. return this.createSubset({
  536. modelID,
  537. removePrevious: true,
  538. material,
  539. customID,
  540. applyBVH: this.subsets[subsetID].bvh,
  541. ids: Array.from(previousIDs),
  542. scene: this.subsets[subsetID].mesh.parent
  543. });
  544. }
  545. clearSubset(modelID, customID, material) {
  546. const subsetID = this.getSubsetID(modelID, material, customID);
  547. if (!this.subsets[subsetID])
  548. return;
  549. this.subsets[subsetID].ids.clear();
  550. const subset = this.getSubset(modelID, material, customID);
  551. subset.geometry.setIndex([]);
  552. }
  553. dispose() {
  554. this.items.dispose();
  555. this.subsetCreator.dispose();
  556. Object.values(this.subsets).forEach(subset => {
  557. subset.ids = null;
  558. subset.mesh.removeFromParent();
  559. const mats = subset.mesh.material;
  560. if (Array.isArray(mats))
  561. mats.forEach(mat => mat.dispose());
  562. else
  563. mats.dispose();
  564. subset.mesh.geometry.index = null;
  565. subset.mesh.geometry.dispose();
  566. const geom = subset.mesh.geometry;
  567. if (geom.disposeBoundsTree)
  568. geom.disposeBoundsTree();
  569. subset.mesh = null;
  570. });
  571. this.subsets = null;
  572. }
  573. getSubsetID(modelID, material, customID = 'DEFAULT') {
  574. const baseID = modelID;
  575. const materialID = material ? material.uuid : 'DEFAULT';
  576. return `${baseID} - ${materialID} - ${customID}`;
  577. }
  578. }
  579. const IdAttrName = 'expressID';
  580. const PropsNames = {
  581. aggregates: {
  582. name: IFCRELAGGREGATES,
  583. relating: 'RelatingObject',
  584. related: 'RelatedObjects',
  585. key: 'children'
  586. },
  587. spatial: {
  588. name: IFCRELCONTAINEDINSPATIALSTRUCTURE,
  589. relating: 'RelatingStructure',
  590. related: 'RelatedElements',
  591. key: 'children'
  592. },
  593. psets: {
  594. name: IFCRELDEFINESBYPROPERTIES,
  595. relating: 'RelatingPropertyDefinition',
  596. related: 'RelatedObjects',
  597. key: 'hasPsets'
  598. },
  599. materials: {
  600. name: IFCRELASSOCIATESMATERIAL,
  601. relating: 'RelatingMaterial',
  602. related: 'RelatedObjects',
  603. key: 'hasMaterial'
  604. },
  605. type: {
  606. name: IFCRELDEFINESBYTYPE,
  607. relating: 'RelatingType',
  608. related: 'RelatedObjects',
  609. key: 'hasType'
  610. }
  611. };
  612. class BasePropertyManager {
  613. constructor(state) {
  614. this.state = state;
  615. }
  616. async getPropertySets(modelID, elementID, recursive = false) {
  617. return await this.getProperty(modelID, elementID, recursive, PropsNames.psets);
  618. }
  619. async getTypeProperties(modelID, elementID, recursive = false) {
  620. return await this.getProperty(modelID, elementID, recursive, PropsNames.type);
  621. }
  622. async getMaterialsProperties(modelID, elementID, recursive = false) {
  623. return await this.getProperty(modelID, elementID, recursive, PropsNames.materials);
  624. }
  625. async getSpatialNode(modelID, node, treeChunks, includeProperties) {
  626. await this.getChildren(modelID, node, treeChunks, PropsNames.aggregates, includeProperties);
  627. await this.getChildren(modelID, node, treeChunks, PropsNames.spatial, includeProperties);
  628. }
  629. async getChildren(modelID, node, treeChunks, propNames, includeProperties) {
  630. const children = treeChunks[node.expressID];
  631. if (children == undefined)
  632. return;
  633. const prop = propNames.key;
  634. const nodes = [];
  635. for (let i = 0; i < children.length; i++) {
  636. const child = children[i];
  637. let node = this.newNode(modelID, child);
  638. if (includeProperties) {
  639. const properties = await this.getItemProperties(modelID, node.expressID);
  640. node = {
  641. ...properties, ...node
  642. };
  643. }
  644. await this.getSpatialNode(modelID, node, treeChunks, includeProperties);
  645. nodes.push(node);
  646. }
  647. node[prop] = nodes;
  648. }
  649. newNode(modelID, id) {
  650. const typeName = this.getNodeType(modelID, id);
  651. return {
  652. expressID: id,
  653. type: typeName,
  654. children: []
  655. };
  656. }
  657. async getSpatialTreeChunks(modelID) {
  658. const treeChunks = {};
  659. await this.getChunks(modelID, treeChunks, PropsNames.aggregates);
  660. await this.getChunks(modelID, treeChunks, PropsNames.spatial);
  661. return treeChunks;
  662. }
  663. saveChunk(chunks, propNames, rel) {
  664. const relating = rel[propNames.relating].value;
  665. const related = rel[propNames.related].map((r) => r.value);
  666. if (chunks[relating] == undefined) {
  667. chunks[relating] = related;
  668. } else {
  669. chunks[relating] = chunks[relating].concat(related);
  670. }
  671. }
  672. getRelated(rel, propNames, IDs) {
  673. const element = rel[propNames.relating];
  674. if (!element) {
  675. return console.warn(`The object with ID ${rel.expressID} has a broken reference.`);
  676. }
  677. if (!Array.isArray(element))
  678. IDs.push(element.value);
  679. else
  680. element.forEach((ele) => IDs.push(ele.value));
  681. }
  682. static isRelated(id, rel, propNames) {
  683. const relatedItems = rel[propNames.related];
  684. if (Array.isArray(relatedItems)) {
  685. const values = relatedItems.map((item) => item.value);
  686. return values.includes(id);
  687. }
  688. return relatedItems.value === id;
  689. }
  690. static newIfcProject(id) {
  691. return {
  692. expressID: id,
  693. type: 'IFCPROJECT',
  694. children: []
  695. };
  696. }
  697. async getProperty(modelID, elementID, recursive = false, propName) {}
  698. async getChunks(modelID, chunks, propNames) {}
  699. async getItemProperties(modelID, expressID, recursive = false) {}
  700. getNodeType(modelID, id) {}
  701. }
  702. class WebIfcPropertyManager extends BasePropertyManager {
  703. async getItemProperties(modelID, id, recursive = false) {
  704. return this.state.api.GetLine(modelID, id, recursive);
  705. }
  706. async getHeaderLine(modelID, headerType) {
  707. return this.state.api.GetHeaderLine(modelID, headerType);
  708. }
  709. async getSpatialStructure(modelID, includeProperties) {
  710. const chunks = await this.getSpatialTreeChunks(modelID);
  711. const allLines = await this.state.api.GetLineIDsWithType(modelID, IFCPROJECT);
  712. const projectID = allLines.get(0);
  713. const project = WebIfcPropertyManager.newIfcProject(projectID);
  714. await this.getSpatialNode(modelID, project, chunks, includeProperties);
  715. return project;
  716. }
  717. async getAllItemsOfType(modelID, type, verbose) {
  718. let items = [];
  719. const lines = await this.state.api.GetLineIDsWithType(modelID, type);
  720. for (let i = 0; i < lines.size(); i++)
  721. items.push(lines.get(i));
  722. if (!verbose)
  723. return items;
  724. const result = [];
  725. for (let i = 0; i < items.length; i++) {
  726. result.push(await this.state.api.GetLine(modelID, items[i]));
  727. }
  728. return result;
  729. }
  730. async getProperty(modelID, elementID, recursive = false, propName) {
  731. const propSetIds = await this.getAllRelatedItemsOfType(modelID, elementID, propName);
  732. const result = [];
  733. for (let i = 0; i < propSetIds.length; i++) {
  734. result.push(await this.state.api.GetLine(modelID, propSetIds[i], recursive));
  735. }
  736. return result;
  737. }
  738. getNodeType(modelID, id) {
  739. const typeID = this.state.models[modelID].types[id];
  740. return this.state.api.GetNameFromTypeCode(typeID);
  741. }
  742. async getChunks(modelID, chunks, propNames) {
  743. const relation = await this.state.api.GetLineIDsWithType(modelID, propNames.name);
  744. for (let i = 0; i < relation.size(); i++) {
  745. const rel = await this.state.api.GetLine(modelID, relation.get(i), false);
  746. this.saveChunk(chunks, propNames, rel);
  747. }
  748. }
  749. async getAllRelatedItemsOfType(modelID, id, propNames) {
  750. const lines = await this.state.api.GetLineIDsWithType(modelID, propNames.name);
  751. const IDs = [];
  752. for (let i = 0; i < lines.size(); i++) {
  753. const rel = await this.state.api.GetLine(modelID, lines.get(i));
  754. const isRelated = BasePropertyManager.isRelated(id, rel, propNames);
  755. if (isRelated)
  756. this.getRelated(rel, propNames, IDs);
  757. }
  758. return IDs;
  759. }
  760. }
  761. class JSONPropertyManager extends BasePropertyManager {
  762. async getItemProperties(modelID, id, recursive = false) {
  763. return {
  764. ...this.state.models[modelID].jsonData[id]
  765. };
  766. }
  767. async getHeaderLine(modelID) {
  768. return {};
  769. }
  770. async getSpatialStructure(modelID, includeProperties) {
  771. const chunks = await this.getSpatialTreeChunks(modelID);
  772. const projectsIDs = await this.getAllItemsOfType(modelID, IFCPROJECT, false);
  773. const projectID = projectsIDs[0];
  774. const project = JSONPropertyManager.newIfcProject(projectID);
  775. await this.getSpatialNode(modelID, project, chunks, includeProperties);
  776. return {
  777. ...project
  778. };
  779. }
  780. async getAllItemsOfType(modelID, type, verbose) {
  781. const data = this.state.models[modelID].jsonData;
  782. const typeName = await this.state.api.GetNameFromTypeCode(type);
  783. if (!typeName) {
  784. throw new Error(`Type not found: ${type}`);
  785. }
  786. return this.filterItemsByType(data, typeName, verbose);
  787. }
  788. async getProperty(modelID, elementID, recursive = false, propName) {
  789. const resultIDs = await this.getAllRelatedItemsOfType(modelID, elementID, propName);
  790. const result = this.getItemsByID(modelID, resultIDs);
  791. if (recursive) {
  792. result.forEach(result => this.getReferencesRecursively(modelID, result));
  793. }
  794. return result;
  795. }
  796. getNodeType(modelID, id) {
  797. return this.state.models[modelID].jsonData[id].type;
  798. }
  799. async getChunks(modelID, chunks, propNames) {
  800. const relation = await this.getAllItemsOfType(modelID, propNames.name, true);
  801. relation.forEach(rel => {
  802. this.saveChunk(chunks, propNames, rel);
  803. });
  804. }
  805. filterItemsByType(data, typeName, verbose) {
  806. const result = [];
  807. Object.keys(data).forEach(key => {
  808. const numKey = parseInt(key);
  809. if (data[numKey].type.toUpperCase() === typeName) {
  810. result.push(verbose ? {
  811. ...data[numKey]
  812. } : numKey);
  813. }
  814. });
  815. return result;
  816. }
  817. async getAllRelatedItemsOfType(modelID, id, propNames) {
  818. const lines = await this.getAllItemsOfType(modelID, propNames.name, true);
  819. const IDs = [];
  820. lines.forEach(line => {
  821. const isRelated = JSONPropertyManager.isRelated(id, line, propNames);
  822. if (isRelated)
  823. this.getRelated(line, propNames, IDs);
  824. });
  825. return IDs;
  826. }
  827. getItemsByID(modelID, ids) {
  828. const data = this.state.models[modelID].jsonData;
  829. const result = [];
  830. ids.forEach(id => result.push({
  831. ...data[id]
  832. }));
  833. return result;
  834. }
  835. getReferencesRecursively(modelID, jsonObject) {
  836. if (jsonObject == undefined)
  837. return;
  838. const keys = Object.keys(jsonObject);
  839. for (let i = 0; i < keys.length; i++) {
  840. const key = keys[i];
  841. this.getJSONItem(modelID, jsonObject, key);
  842. }
  843. }
  844. getJSONItem(modelID, jsonObject, key) {
  845. if (Array.isArray(jsonObject[key])) {
  846. return this.getMultipleJSONItems(modelID, jsonObject, key);
  847. }
  848. if (jsonObject[key] && jsonObject[key].type === 5) {
  849. jsonObject[key] = this.getItemsByID(modelID, [jsonObject[key].value])[0];
  850. this.getReferencesRecursively(modelID, jsonObject[key]);
  851. }
  852. }
  853. getMultipleJSONItems(modelID, jsonObject, key) {
  854. jsonObject[key] = jsonObject[key].map((item) => {
  855. if (item.type === 5) {
  856. item = this.getItemsByID(modelID, [item.value])[0];
  857. this.getReferencesRecursively(modelID, item);
  858. }
  859. return item;
  860. });
  861. }
  862. }
  863. const geometryTypes = new Set([
  864. 1123145078, 574549367, 1675464909, 2059837836, 3798115385, 32440307, 3125803723, 3207858831,
  865. 2740243338, 2624227202, 4240577450, 3615266464, 3724593414, 220341763, 477187591, 1878645084,
  866. 1300840506, 3303107099, 1607154358, 1878645084, 846575682, 1351298697, 2417041796, 3049322572,
  867. 3331915920, 1416205885, 776857604, 3285139300, 3958052878, 2827736869, 2732653382, 673634403,
  868. 3448662350, 4142052618, 2924175390, 803316827, 2556980723, 1809719519, 2205249479, 807026263,
  869. 3737207727, 1660063152, 2347385850, 3940055652, 2705031697, 3732776249, 2485617015, 2611217952,
  870. 1704287377, 2937912522, 2770003689, 1281925730, 1484403080, 3448662350, 4142052618, 3800577675,
  871. 4006246654, 3590301190, 1383045692, 2775532180, 2047409740, 370225590, 3593883385, 2665983363,
  872. 4124623270, 812098782, 3649129432, 987898635, 1105321065, 3510044353, 1635779807, 2603310189,
  873. 3406155212, 1310608509, 4261334040, 2736907675, 3649129432, 1136057603, 1260505505, 4182860854,
  874. 2713105998, 2898889636, 59481748, 3749851601, 3486308946, 3150382593, 1062206242, 3264961684,
  875. 15328376, 1485152156, 370225590, 1981873012, 2859738748, 45288368, 2614616156, 2732653382,
  876. 775493141, 2147822146, 2601014836, 2629017746, 1186437898, 2367409068, 1213902940, 3632507154,
  877. 3900360178, 476780140, 1472233963, 2804161546, 3008276851, 738692330, 374418227, 315944413,
  878. 3905492369, 3570813810, 2571569899, 178912537, 2294589976, 1437953363, 2133299955, 572779678,
  879. 3092502836, 388784114, 2624227202, 1425443689, 3057273783, 2347385850, 1682466193, 2519244187,
  880. 2839578677, 3958567839, 2513912981, 2830218821, 427810014
  881. ]);
  882. class PropertySerializer {
  883. constructor(webIfc) {
  884. this.webIfc = webIfc;
  885. }
  886. dispose() {
  887. this.webIfc = null;
  888. }
  889. async serializeAllProperties(modelID, maxSize, event) {
  890. const blobs = [];
  891. await this.getPropertiesAsBlobs(modelID, blobs, maxSize, event);
  892. return blobs;
  893. }
  894. async getPropertiesAsBlobs(modelID, blobs, maxSize, event) {
  895. const geometriesIDs = await this.getAllGeometriesIDs(modelID);
  896. let properties = await this.initializePropertiesObject(modelID);
  897. const allLinesIDs = await this.webIfc.GetAllLines(modelID);
  898. const linesCount = allLinesIDs.size();
  899. let lastEvent = 0.1;
  900. let counter = 0;
  901. for (let i = 0; i < linesCount; i++) {
  902. const id = allLinesIDs.get(i);
  903. if (!geometriesIDs.has(id)) {
  904. await this.getItemProperty(modelID, id, properties);
  905. counter++;
  906. }
  907. if (maxSize && counter > maxSize) {
  908. blobs.push(new Blob([JSON.stringify(properties)], {
  909. type: 'application/json'
  910. }));
  911. properties = {};
  912. counter = 0;
  913. }
  914. if (event && i / linesCount > lastEvent) {
  915. event(i, linesCount);
  916. lastEvent += 0.1;
  917. }
  918. }
  919. blobs.push(new Blob([JSON.stringify(properties)], {
  920. type: 'application/json'
  921. }));
  922. }
  923. async getItemProperty(modelID, id, properties) {
  924. try {
  925. const props = await this.webIfc.GetLine(modelID, id);
  926. if (props.type) {
  927. props.type = this.webIfc.GetNameFromTypeCode(props.type);
  928. }
  929. this.formatItemProperties(props);
  930. properties[id] = props;
  931. } catch (e) {
  932. console.log(`There was a problem getting the properties of the item with ID ${id}`);
  933. }
  934. }
  935. formatItemProperties(props) {
  936. Object.keys(props).forEach((key) => {
  937. const value = props[key];
  938. if (value && value.value !== undefined)
  939. props[key] = value.value;
  940. else if (Array.isArray(value))
  941. props[key] = value.map((item) => {
  942. if (item && item.value)
  943. return item.value;
  944. return item;
  945. });
  946. });
  947. }
  948. async initializePropertiesObject(modelID) {
  949. return {
  950. coordinationMatrix: await this.webIfc.GetCoordinationMatrix(modelID),
  951. globalHeight: await this.getBuildingHeight(modelID)
  952. };
  953. }
  954. async getBuildingHeight(modelID) {
  955. const building = await this.getBuilding(modelID);
  956. let placement;
  957. const siteReference = building.ObjectPlacement.PlacementRelTo;
  958. if (siteReference)
  959. placement = siteReference.RelativePlacement.Location;
  960. else
  961. placement = building.ObjectPlacement.RelativePlacement.Location;
  962. const transform = placement.Coordinates.map((coord) => coord.value);
  963. return transform[2];
  964. }
  965. async getBuilding(modelID) {
  966. const allBuildingsIDs = await this.webIfc.GetLineIDsWithType(modelID, IFCBUILDING);
  967. const buildingID = allBuildingsIDs.get(0);
  968. return this.webIfc.GetLine(modelID, buildingID, true);
  969. }
  970. async getAllGeometriesIDs(modelID) {
  971. const geometriesIDs = new Set();
  972. const geomTypesArray = Array.from(geometryTypes);
  973. for (let i = 0; i < geomTypesArray.length; i++) {
  974. const category = geomTypesArray[i];
  975. const ids = await this.webIfc.GetLineIDsWithType(modelID, category);
  976. const idsSize = ids.size();
  977. for (let j = 0; j < idsSize; j++) {
  978. geometriesIDs.add(ids.get(j));
  979. }
  980. }
  981. return geometriesIDs;
  982. }
  983. }
  984. class PropertyManager {
  985. constructor(state) {
  986. this.state = state;
  987. this.webIfcProps = new WebIfcPropertyManager(state);
  988. this.jsonProps = new JSONPropertyManager(state);
  989. this.currentProps = this.webIfcProps;
  990. this.serializer = new PropertySerializer(this.state.api);
  991. }
  992. getExpressId(geometry, faceIndex) {
  993. if (!geometry.index)
  994. throw new Error('Geometry does not have index information.');
  995. const geoIndex = geometry.index.array;
  996. const bufferAttr = geometry.attributes[IdAttrName];
  997. return bufferAttr.getX(geoIndex[3 * faceIndex]);
  998. }
  999. async getHeaderLine(modelID, headerType) {
  1000. this.updateCurrentProps();
  1001. return this.currentProps.getHeaderLine(modelID, headerType);
  1002. }
  1003. async getItemProperties(modelID, elementID, recursive = false) {
  1004. this.updateCurrentProps();
  1005. return this.currentProps.getItemProperties(modelID, elementID, recursive);
  1006. }
  1007. async getAllItemsOfType(modelID, type, verbose) {
  1008. this.updateCurrentProps();
  1009. return this.currentProps.getAllItemsOfType(modelID, type, verbose);
  1010. }
  1011. async getPropertySets(modelID, elementID, recursive = false) {
  1012. this.updateCurrentProps();
  1013. return this.currentProps.getPropertySets(modelID, elementID, recursive);
  1014. }
  1015. async getTypeProperties(modelID, elementID, recursive = false) {
  1016. this.updateCurrentProps();
  1017. return this.currentProps.getTypeProperties(modelID, elementID, recursive);
  1018. }
  1019. async getMaterialsProperties(modelID, elementID, recursive = false) {
  1020. this.updateCurrentProps();
  1021. return this.currentProps.getMaterialsProperties(modelID, elementID, recursive);
  1022. }
  1023. async getSpatialStructure(modelID, includeProperties) {
  1024. this.updateCurrentProps();
  1025. if (!this.state.useJSON && includeProperties) {
  1026. console.warn('Including properties in getSpatialStructure with the JSON workflow disabled can lead to poor performance.');
  1027. }
  1028. return await this.currentProps.getSpatialStructure(modelID, includeProperties);
  1029. }
  1030. updateCurrentProps() {
  1031. this.currentProps = this.state.useJSON ? this.jsonProps : this.webIfcProps;
  1032. }
  1033. }
  1034. class TypeManager {
  1035. constructor(state) {
  1036. this.state = state;
  1037. this.state = state;
  1038. }
  1039. async getAllTypes(worker) {
  1040. for (let modelID in this.state.models) {
  1041. if (this.state.models.hasOwnProperty(modelID)) {
  1042. const types = this.state.models[modelID].types;
  1043. if (Object.keys(types).length == 0) {
  1044. await this.getAllTypesOfModel(parseInt(modelID), worker);
  1045. }
  1046. }
  1047. }
  1048. }
  1049. async getAllTypesOfModel(modelID, worker) {
  1050. const result = {};
  1051. const elements = await this.state.api.GetIfcEntityList(modelID);
  1052. for (let i = 0; i < elements.length; i++) {
  1053. const element = elements[i];
  1054. const lines = await this.state.api.GetLineIDsWithType(modelID, element);
  1055. const size = lines.size();
  1056. for (let i = 0; i < size; i++)
  1057. result[lines.get(i)] = element;
  1058. }
  1059. if (this.state.worker.active && worker) {
  1060. await worker.workerState.updateModelStateTypes(modelID, result);
  1061. }
  1062. this.state.models[modelID].types = result;
  1063. }
  1064. }
  1065. class BvhManager {
  1066. initializeMeshBVH(computeBoundsTree, disposeBoundsTree, acceleratedRaycast) {
  1067. this.computeBoundsTree = computeBoundsTree;
  1068. this.disposeBoundsTree = disposeBoundsTree;
  1069. this.acceleratedRaycast = acceleratedRaycast;
  1070. this.setupThreeMeshBVH();
  1071. }
  1072. applyThreeMeshBVH(geometry) {
  1073. if (this.computeBoundsTree)
  1074. geometry.computeBoundsTree();
  1075. }
  1076. setupThreeMeshBVH() {
  1077. if (!this.computeBoundsTree || !this.disposeBoundsTree || !this.acceleratedRaycast)
  1078. return;
  1079. BufferGeometry.prototype.computeBoundsTree = this.computeBoundsTree;
  1080. BufferGeometry.prototype.disposeBoundsTree = this.disposeBoundsTree;
  1081. Mesh.prototype.raycast = this.acceleratedRaycast;
  1082. }
  1083. }
  1084. var WorkerActions;
  1085. (function(WorkerActions) {
  1086. WorkerActions["updateStateUseJson"] = "updateStateUseJson";
  1087. WorkerActions["updateStateWebIfcSettings"] = "updateStateWebIfcSettings";
  1088. WorkerActions["updateModelStateTypes"] = "updateModelStateTypes";
  1089. WorkerActions["updateModelStateJsonData"] = "updateModelStateJsonData";
  1090. WorkerActions["loadJsonDataFromWorker"] = "loadJsonDataFromWorker";
  1091. WorkerActions["dispose"] = "dispose";
  1092. WorkerActions["Close"] = "Close";
  1093. WorkerActions["DisposeWebIfc"] = "DisposeWebIfc";
  1094. WorkerActions["Init"] = "Init";
  1095. WorkerActions["OpenModel"] = "OpenModel";
  1096. WorkerActions["CreateModel"] = "CreateModel";
  1097. WorkerActions["ExportFileAsIFC"] = "ExportFileAsIFC";
  1098. WorkerActions["GetGeometry"] = "GetGeometry";
  1099. WorkerActions["GetLine"] = "GetLine";
  1100. WorkerActions["GetAndClearErrors"] = "GetAndClearErrors";
  1101. WorkerActions["WriteLine"] = "WriteLine";
  1102. WorkerActions["FlattenLine"] = "FlattenLine";
  1103. WorkerActions["GetRawLineData"] = "GetRawLineData";
  1104. WorkerActions["WriteRawLineData"] = "WriteRawLineData";
  1105. WorkerActions["GetLineIDsWithType"] = "GetLineIDsWithType";
  1106. WorkerActions["GetAllLines"] = "GetAllLines";
  1107. WorkerActions["SetGeometryTransformation"] = "SetGeometryTransformation";
  1108. WorkerActions["GetCoordinationMatrix"] = "GetCoordinationMatrix";
  1109. WorkerActions["GetVertexArray"] = "GetVertexArray";
  1110. WorkerActions["GetIndexArray"] = "GetIndexArray";
  1111. WorkerActions["getSubArray"] = "getSubArray";
  1112. WorkerActions["CloseModel"] = "CloseModel";
  1113. WorkerActions["StreamAllMeshes"] = "StreamAllMeshes";
  1114. WorkerActions["StreamAllMeshesWithTypes"] = "StreamAllMeshesWithTypes";
  1115. WorkerActions["IsModelOpen"] = "IsModelOpen";
  1116. WorkerActions["LoadAllGeometry"] = "LoadAllGeometry";
  1117. WorkerActions["GetFlatMesh"] = "GetFlatMesh";
  1118. WorkerActions["SetWasmPath"] = "SetWasmPath";
  1119. WorkerActions["GetNameFromTypeCode"] = "GetNameFromTypeCode";
  1120. WorkerActions["GetIfcEntityList"] = "GetIfcEntityList";
  1121. WorkerActions["GetTypeCodeFromName"] = "GetTypeCodeFromName";
  1122. WorkerActions["parse"] = "parse";
  1123. WorkerActions["setupOptionalCategories"] = "setupOptionalCategories";
  1124. WorkerActions["getExpressId"] = "getExpressId";
  1125. WorkerActions["initializeProperties"] = "initializeProperties";
  1126. WorkerActions["getAllItemsOfType"] = "getAllItemsOfType";
  1127. WorkerActions["getItemProperties"] = "getItemProperties";
  1128. WorkerActions["getMaterialsProperties"] = "getMaterialsProperties";
  1129. WorkerActions["getPropertySets"] = "getPropertySets";
  1130. WorkerActions["getSpatialStructure"] = "getSpatialStructure";
  1131. WorkerActions["getTypeProperties"] = "getTypeProperties";
  1132. WorkerActions["getHeaderLine"] = "getHeaderLine";
  1133. })(WorkerActions || (WorkerActions = {}));
  1134. var WorkerAPIs;
  1135. (function(WorkerAPIs) {
  1136. WorkerAPIs["workerState"] = "workerState";
  1137. WorkerAPIs["webIfc"] = "webIfc";
  1138. WorkerAPIs["properties"] = "properties";
  1139. WorkerAPIs["parser"] = "parser";
  1140. })(WorkerAPIs || (WorkerAPIs = {}));
  1141. class Vector {
  1142. constructor(vector) {
  1143. this._data = {};
  1144. this._size = vector.size;
  1145. const keys = Object.keys(vector).filter((key) => key.indexOf('size') === -1).map(key => parseInt(key));
  1146. keys.forEach((key) => this._data[key] = vector[key]);
  1147. }
  1148. size() {
  1149. return this._size;
  1150. }
  1151. get(index) {
  1152. return this._data[index];
  1153. }
  1154. }
  1155. class IfcGeometry {
  1156. constructor(vector) {
  1157. this._GetVertexData = vector.GetVertexData;
  1158. this._GetVertexDataSize = vector.GetVertexDataSize;
  1159. this._GetIndexData = vector.GetIndexData;
  1160. this._GetIndexDataSize = vector.GetIndexDataSize;
  1161. }
  1162. GetVertexData() {
  1163. return this._GetVertexData;
  1164. }
  1165. GetVertexDataSize() {
  1166. return this._GetVertexDataSize;
  1167. }
  1168. GetIndexData() {
  1169. return this._GetIndexData;
  1170. }
  1171. GetIndexDataSize() {
  1172. return this._GetIndexDataSize;
  1173. }
  1174. }
  1175. class FlatMesh {
  1176. constructor(serializer, flatMesh) {
  1177. this.expressID = flatMesh.expressID;
  1178. this.geometries = serializer.reconstructVector(flatMesh.geometries);
  1179. }
  1180. }
  1181. class FlatMeshVector {
  1182. constructor(serializer, vector) {
  1183. this._data = {};
  1184. this._size = vector.size;
  1185. const keys = Object.keys(vector).filter((key) => key.indexOf('size') === -1).map(key => parseInt(key));
  1186. keys.forEach(key => this._data[key] = serializer.reconstructFlatMesh(vector[key]));
  1187. }
  1188. size() {
  1189. return this._size;
  1190. }
  1191. get(index) {
  1192. return this._data[index];
  1193. }
  1194. }
  1195. class SerializedMaterial {
  1196. constructor(material) {
  1197. this.color = [material.color.r, material.color.g, material.color.b];
  1198. this.opacity = material.opacity;
  1199. this.transparent = material.transparent;
  1200. }
  1201. }
  1202. class MaterialReconstructor {
  1203. static new(material) {
  1204. return new MeshLambertMaterial({
  1205. color: new Color(material.color[0], material.color[1], material.color[2]),
  1206. opacity: material.opacity,
  1207. transparent: material.transparent,
  1208. side: DoubleSide
  1209. });
  1210. }
  1211. }
  1212. class SerializedGeometry {
  1213. constructor(geometry) {
  1214. var _a,
  1215. _b,
  1216. _c,
  1217. _d;
  1218. this.position = ((_a = geometry.attributes.position) === null || _a === void 0 ? void 0 : _a.array) || [];
  1219. this.normal = ((_b = geometry.attributes.normal) === null || _b === void 0 ? void 0 : _b.array) || [];
  1220. this.expressID = ((_c = geometry.attributes.expressID) === null || _c === void 0 ? void 0 : _c.array) || [];
  1221. this.index = ((_d = geometry.index) === null || _d === void 0 ? void 0 : _d.array) || [];
  1222. this.groups = geometry.groups;
  1223. }
  1224. }
  1225. class GeometryReconstructor {
  1226. static new(serialized) {
  1227. const geom = new BufferGeometry();
  1228. GeometryReconstructor.set(geom, 'expressID', new Uint32Array(serialized.expressID), 1);
  1229. GeometryReconstructor.set(geom, 'position', new Float32Array(serialized.position), 3);
  1230. GeometryReconstructor.set(geom, 'normal', new Float32Array(serialized.normal), 3);
  1231. geom.setIndex(Array. from (serialized.index));
  1232. geom.groups = serialized.groups;
  1233. return geom;
  1234. }
  1235. static set(geom, name, data, size) {
  1236. if (data.length > 0) {
  1237. geom.setAttribute(name, new BufferAttribute(data, size));
  1238. }
  1239. }
  1240. }
  1241. class SerializedMesh {
  1242. constructor(model) {
  1243. this.materials = [];
  1244. this.modelID = model.modelID;
  1245. this.geometry = new SerializedGeometry(model.geometry);
  1246. if (Array.isArray(model.material)) {
  1247. model.material.forEach(mat => {
  1248. this.materials.push(new SerializedMaterial(mat));
  1249. });
  1250. } else {
  1251. this.materials.push(new SerializedMaterial(model.material));
  1252. }
  1253. }
  1254. }
  1255. class MeshReconstructor {
  1256. static new(serialized) {
  1257. const model = new IFCModel();
  1258. model.modelID = serialized.modelID;
  1259. model.geometry = GeometryReconstructor.new(serialized.geometry);
  1260. MeshReconstructor.getMaterials(serialized, model);
  1261. return model;
  1262. }
  1263. static getMaterials(serialized, model) {
  1264. model.material = [];
  1265. const mats = model.material;
  1266. serialized.materials.forEach(mat => {
  1267. mats.push(MaterialReconstructor.new(mat));
  1268. });
  1269. }
  1270. }
  1271. class Serializer {
  1272. serializeVector(vector) {
  1273. const size = vector.size();
  1274. const serialized = {
  1275. size
  1276. };
  1277. for (let i = 0; i < size; i++) {
  1278. serialized[i] = vector.get(i);
  1279. }
  1280. return serialized;
  1281. }
  1282. reconstructVector(vector) {
  1283. return new Vector(vector);
  1284. }
  1285. serializeIfcGeometry(geometry) {
  1286. const GetVertexData = geometry.GetVertexData();
  1287. const GetVertexDataSize = geometry.GetVertexDataSize();
  1288. const GetIndexData = geometry.GetIndexData();
  1289. const GetIndexDataSize = geometry.GetIndexDataSize();
  1290. return {
  1291. GetVertexData,
  1292. GetVertexDataSize,
  1293. GetIndexData,
  1294. GetIndexDataSize
  1295. };
  1296. }
  1297. reconstructIfcGeometry(geometry) {
  1298. return new IfcGeometry(geometry);
  1299. }
  1300. serializeFlatMesh(flatMesh) {
  1301. return {
  1302. expressID: flatMesh.expressID,
  1303. geometries: this.serializeVector(flatMesh.geometries)
  1304. };
  1305. }
  1306. reconstructFlatMesh(flatMesh) {
  1307. return new FlatMesh(this, flatMesh);
  1308. }
  1309. serializeFlatMeshVector(vector) {
  1310. const size = vector.size();
  1311. const serialized = {
  1312. size
  1313. };
  1314. for (let i = 0; i < size; i++) {
  1315. const flatMesh = vector.get(i);
  1316. serialized[i] = this.serializeFlatMesh(flatMesh);
  1317. }
  1318. return serialized;
  1319. }
  1320. reconstructFlatMeshVector(vector) {
  1321. return new FlatMeshVector(this, vector);
  1322. }
  1323. serializeIfcModel(model) {
  1324. return new SerializedMesh(model);
  1325. }
  1326. reconstructIfcModel(model) {
  1327. return MeshReconstructor.new(model);
  1328. }
  1329. }
  1330. class PropertyHandler {
  1331. constructor(handler) {
  1332. this.handler = handler;
  1333. this.API = WorkerAPIs.properties;
  1334. }
  1335. getExpressId(geometry, faceIndex) {
  1336. if (!geometry.index)
  1337. throw new Error('Geometry does not have index information.');
  1338. const geoIndex = geometry.index.array;
  1339. const bufferAttr = geometry.attributes[IdAttrName];
  1340. return bufferAttr.getX(geoIndex[3 * faceIndex]);
  1341. }
  1342. getHeaderLine(modelID, headerType) {
  1343. return this.handler.request(this.API, WorkerActions.getHeaderLine, {
  1344. modelID,
  1345. headerType
  1346. });
  1347. }
  1348. getAllItemsOfType(modelID, type, verbose) {
  1349. return this.handler.request(this.API, WorkerActions.getAllItemsOfType, {
  1350. modelID,
  1351. type,
  1352. verbose
  1353. });
  1354. }
  1355. getItemProperties(modelID, elementID, recursive) {
  1356. return this.handler.request(this.API, WorkerActions.getItemProperties, {
  1357. modelID,
  1358. elementID,
  1359. recursive
  1360. });
  1361. }
  1362. getMaterialsProperties(modelID, elementID, recursive) {
  1363. return this.handler.request(this.API, WorkerActions.getMaterialsProperties, {
  1364. modelID,
  1365. elementID,
  1366. recursive
  1367. });
  1368. }
  1369. getPropertySets(modelID, elementID, recursive) {
  1370. return this.handler.request(this.API, WorkerActions.getPropertySets, {
  1371. modelID,
  1372. elementID,
  1373. recursive
  1374. });
  1375. }
  1376. getTypeProperties(modelID, elementID, recursive) {
  1377. return this.handler.request(this.API, WorkerActions.getTypeProperties, {
  1378. modelID,
  1379. elementID,
  1380. recursive
  1381. });
  1382. }
  1383. getSpatialStructure(modelID, includeProperties) {
  1384. return this.handler.request(this.API, WorkerActions.getSpatialStructure, {
  1385. modelID,
  1386. includeProperties
  1387. });
  1388. }
  1389. }
  1390. class WebIfcHandler {
  1391. constructor(handler, serializer) {
  1392. this.handler = handler;
  1393. this.serializer = serializer;
  1394. this.API = WorkerAPIs.webIfc;
  1395. }
  1396. async Init() {
  1397. this.wasmModule = true;
  1398. return this.handler.request(this.API, WorkerActions.Init);
  1399. }
  1400. async OpenModel(data, settings) {
  1401. return this.handler.request(this.API, WorkerActions.OpenModel, {
  1402. data,
  1403. settings
  1404. });
  1405. }
  1406. async CreateModel(model, settings) {
  1407. return this.handler.request(this.API, WorkerActions.CreateModel, {
  1408. model,
  1409. settings
  1410. });
  1411. }
  1412. async ExportFileAsIFC(modelID) {
  1413. return this.handler.request(this.API, WorkerActions.ExportFileAsIFC, {
  1414. modelID
  1415. });
  1416. }
  1417. async GetHeaderLine(modelID, headerType) {
  1418. return this.handler.request(this.API, WorkerActions.getHeaderLine, {
  1419. modelID,
  1420. headerType
  1421. });
  1422. }
  1423. async GetGeometry(modelID, geometryExpressID) {
  1424. this.handler.serializeHandlers[this.handler.requestID] = (geom) => {
  1425. return this.serializer.reconstructIfcGeometry(geom);
  1426. };
  1427. return this.handler.request(this.API, WorkerActions.GetGeometry, {
  1428. modelID,
  1429. geometryExpressID
  1430. });
  1431. }
  1432. async GetLine(modelID, expressID, flatten) {
  1433. return this.handler.request(this.API, WorkerActions.GetLine, {
  1434. modelID,
  1435. expressID,
  1436. flatten
  1437. });
  1438. }
  1439. async GetAndClearErrors(modelID) {
  1440. this.handler.serializeHandlers[this.handler.requestID] = (vector) => {
  1441. return this.serializer.reconstructVector(vector);
  1442. };
  1443. return this.handler.request(this.API, WorkerActions.GetAndClearErrors, {
  1444. modelID
  1445. });
  1446. }
  1447. async GetNameFromTypeCode(type) {
  1448. return this.handler.request(this.API, WorkerActions.GetNameFromTypeCode, {
  1449. type
  1450. });
  1451. }
  1452. async GetIfcEntityList(modelID) {
  1453. return this.handler.request(this.API, WorkerActions.GetIfcEntityList, {
  1454. modelID
  1455. });
  1456. }
  1457. async GetTypeCodeFromName(modelID, typeName) {
  1458. return this.handler.request(this.API, WorkerActions.GetTypeCodeFromName, {
  1459. modelID,
  1460. typeName
  1461. });
  1462. }
  1463. async WriteLine(modelID, lineObject) {
  1464. return this.handler.request(this.API, WorkerActions.WriteLine, {
  1465. modelID,
  1466. lineObject
  1467. });
  1468. }
  1469. async FlattenLine(modelID, line) {
  1470. return this.handler.request(this.API, WorkerActions.FlattenLine, {
  1471. modelID,
  1472. line
  1473. });
  1474. }
  1475. async GetRawLineData(modelID, expressID) {
  1476. return this.handler.request(this.API, WorkerActions.GetRawLineData, {
  1477. modelID,
  1478. expressID
  1479. });
  1480. }
  1481. async WriteRawLineData(modelID, data) {
  1482. return this.handler.request(this.API, WorkerActions.WriteRawLineData, {
  1483. modelID,
  1484. data
  1485. });
  1486. }
  1487. async GetLineIDsWithType(modelID, type) {
  1488. this.handler.serializeHandlers[this.handler.requestID] = (vector) => {
  1489. return this.serializer.reconstructVector(vector);
  1490. };
  1491. return this.handler.request(this.API, WorkerActions.GetLineIDsWithType, {
  1492. modelID,
  1493. type
  1494. });
  1495. }
  1496. async GetAllLines(modelID) {
  1497. this.handler.serializeHandlers[this.handler.requestID] = (vector) => {
  1498. return this.serializer.reconstructVector(vector);
  1499. };
  1500. return this.handler.request(this.API, WorkerActions.GetAllLines, {
  1501. modelID
  1502. });
  1503. }
  1504. async SetGeometryTransformation(modelID, transformationMatrix) {
  1505. return this.handler.request(this.API, WorkerActions.SetGeometryTransformation, {
  1506. modelID,
  1507. transformationMatrix
  1508. });
  1509. }
  1510. async GetCoordinationMatrix(modelID) {
  1511. return this.handler.request(this.API, WorkerActions.GetCoordinationMatrix, {
  1512. modelID
  1513. });
  1514. }
  1515. async GetVertexArray(ptr, size) {
  1516. return this.handler.request(this.API, WorkerActions.GetVertexArray, {
  1517. ptr,
  1518. size
  1519. });
  1520. }
  1521. async GetIndexArray(ptr, size) {
  1522. return this.handler.request(this.API, WorkerActions.GetIndexArray, {
  1523. ptr,
  1524. size
  1525. });
  1526. }
  1527. async getSubArray(heap, startPtr, sizeBytes) {
  1528. return this.handler.request(this.API, WorkerActions.getSubArray, {
  1529. heap,
  1530. startPtr,
  1531. sizeBytes
  1532. });
  1533. }
  1534. async CloseModel(modelID) {
  1535. return this.handler.request(this.API, WorkerActions.CloseModel, {
  1536. modelID
  1537. });
  1538. }
  1539. async StreamAllMeshes(modelID, meshCallback) {
  1540. this.handler.callbackHandlers[this.handler.requestID] = {
  1541. action: meshCallback,
  1542. serializer: this.serializer.reconstructFlatMesh
  1543. };
  1544. return this.handler.request(this.API, WorkerActions.StreamAllMeshes, {
  1545. modelID
  1546. });
  1547. }
  1548. async StreamAllMeshesWithTypes(modelID, types, meshCallback) {
  1549. this.handler.callbackHandlers[this.handler.requestID] = {
  1550. action: meshCallback,
  1551. serializer: this.serializer.reconstructFlatMesh
  1552. };
  1553. return this.handler.request(this.API, WorkerActions.StreamAllMeshesWithTypes, {
  1554. modelID,
  1555. types
  1556. });
  1557. }
  1558. async IsModelOpen(modelID) {
  1559. return this.handler.request(this.API, WorkerActions.IsModelOpen, {
  1560. modelID
  1561. });
  1562. }
  1563. async LoadAllGeometry(modelID) {
  1564. this.handler.serializeHandlers[this.handler.requestID] = (vector) => {
  1565. return this.serializer.reconstructFlatMeshVector(vector);
  1566. };
  1567. return this.handler.request(this.API, WorkerActions.LoadAllGeometry, {
  1568. modelID
  1569. });
  1570. }
  1571. async GetFlatMesh(modelID, expressID) {
  1572. this.handler.serializeHandlers[this.handler.requestID] = (flatMesh) => {
  1573. return this.serializer.reconstructFlatMesh(flatMesh);
  1574. };
  1575. return this.handler.request(this.API, WorkerActions.GetFlatMesh, {
  1576. modelID,
  1577. expressID
  1578. });
  1579. }
  1580. async SetWasmPath(path) {
  1581. return this.handler.request(this.API, WorkerActions.SetWasmPath, {
  1582. path
  1583. });
  1584. }
  1585. }
  1586. class WorkerStateHandler {
  1587. constructor(handler) {
  1588. this.handler = handler;
  1589. this.API = WorkerAPIs.workerState;
  1590. this.state = this.handler.state;
  1591. }
  1592. async updateStateUseJson() {
  1593. const useJson = this.state.useJSON;
  1594. return this.handler.request(this.API, WorkerActions.updateStateUseJson, {
  1595. useJson
  1596. });
  1597. }
  1598. async updateStateWebIfcSettings() {
  1599. const webIfcSettings = this.state.webIfcSettings;
  1600. return this.handler.request(this.API, WorkerActions.updateStateWebIfcSettings, {
  1601. webIfcSettings
  1602. });
  1603. }
  1604. async updateModelStateTypes(modelID, types) {
  1605. return this.handler.request(this.API, WorkerActions.updateModelStateTypes, {
  1606. modelID,
  1607. types
  1608. });
  1609. }
  1610. async updateModelStateJsonData(modelID, jsonData) {
  1611. return this.handler.request(this.API, WorkerActions.updateModelStateJsonData, {
  1612. modelID,
  1613. jsonData
  1614. });
  1615. }
  1616. async loadJsonDataFromWorker(modelID, path) {
  1617. return this.handler.request(this.API, WorkerActions.loadJsonDataFromWorker, {
  1618. modelID,
  1619. path
  1620. });
  1621. }
  1622. }
  1623. var DBOperation;
  1624. (function(DBOperation) {
  1625. DBOperation[DBOperation["transferIfcModel"] = 0] = "transferIfcModel";
  1626. DBOperation[DBOperation["transferIndividualItems"] = 1] = "transferIndividualItems";
  1627. })(DBOperation || (DBOperation = {}));
  1628. class IndexedDatabase {
  1629. async save(item, id) {
  1630. const open = IndexedDatabase.openOrCreateDB(id);
  1631. this.createSchema(open, id);
  1632. return new Promise((resolve, reject) => {
  1633. open.onsuccess = () => this.saveItem(item, open, id, resolve);
  1634. });
  1635. }
  1636. async load(id) {
  1637. const open = IndexedDatabase.openOrCreateDB(id);
  1638. return new Promise((resolve, reject) => {
  1639. open.onsuccess = () => this.loadItem(open, id, resolve);
  1640. });
  1641. }
  1642. createSchema(open, id) {
  1643. open.onupgradeneeded = function() {
  1644. const db = open.result;
  1645. db.createObjectStore(id.toString(), {
  1646. keyPath: "id"
  1647. });
  1648. };
  1649. }
  1650. saveItem(item, open, id, resolve) {
  1651. const {db, tx, store} = IndexedDatabase.getDBItems(open, id);
  1652. item.id = id;
  1653. store.put(item);
  1654. tx.oncomplete = () => IndexedDatabase.closeDB(db, tx, resolve);
  1655. }
  1656. loadItem(open, id, resolve) {
  1657. const {db, tx, store} = IndexedDatabase.getDBItems(open, id);
  1658. const item = store.get(id);
  1659. const callback = () => {
  1660. delete item.result.id;
  1661. resolve(item.result);
  1662. };
  1663. tx.oncomplete = () => IndexedDatabase.closeDB(db, tx, callback);
  1664. }
  1665. static getDBItems(open, id) {
  1666. const db = open.result;
  1667. const tx = db.transaction(id.toString(), "readwrite");
  1668. const store = tx.objectStore(id.toString());
  1669. return {
  1670. db,
  1671. tx,
  1672. store
  1673. };
  1674. }
  1675. static openOrCreateDB(id) {
  1676. return indexedDB.open(id.toString(), 1);
  1677. }
  1678. static closeDB(db, tx, resolve) {
  1679. db.close();
  1680. resolve("success");
  1681. }
  1682. }
  1683. class ParserHandler {
  1684. constructor(handler, serializer, BVH, IDB) {
  1685. this.handler = handler;
  1686. this.serializer = serializer;
  1687. this.BVH = BVH;
  1688. this.IDB = IDB;
  1689. this.optionalCategories = {
  1690. [IFCSPACE]: true,
  1691. [IFCOPENINGELEMENT]: false
  1692. };
  1693. this.API = WorkerAPIs.parser;
  1694. }
  1695. async setupOptionalCategories(config) {
  1696. this.optionalCategories = config;
  1697. return this.handler.request(this.API, WorkerActions.setupOptionalCategories, {
  1698. config
  1699. });
  1700. }
  1701. async parse(buffer, coordinationMatrix) {
  1702. this.handler.onprogressHandlers[this.handler.requestID] = (progress) => {
  1703. if (this.handler.state.onProgress)
  1704. this.handler.state.onProgress(progress);
  1705. };
  1706. this.handler.serializeHandlers[this.handler.requestID] = async (result) => {
  1707. this.updateState(result.modelID);
  1708. return this.getModel();
  1709. };
  1710. return this.handler.request(this.API, WorkerActions.parse, {
  1711. buffer,
  1712. coordinationMatrix
  1713. });
  1714. }
  1715. getAndClearErrors(_modelId) {}
  1716. updateState(modelID) {
  1717. this.handler.state.models[modelID] = {
  1718. modelID: modelID,
  1719. mesh: {},
  1720. types: {},
  1721. jsonData: {}
  1722. };
  1723. }
  1724. async getModel() {
  1725. const serializedModel = await this.IDB.load(DBOperation.transferIfcModel);
  1726. const model = this.serializer.reconstructIfcModel(serializedModel);
  1727. this.BVH.applyThreeMeshBVH(model.geometry);
  1728. this.handler.state.models[model.modelID].mesh = model;
  1729. return model;
  1730. }
  1731. }
  1732. class IFCWorkerHandler {
  1733. constructor(state, BVH) {
  1734. this.state = state;
  1735. this.BVH = BVH;
  1736. this.requestID = 0;
  1737. this.rejectHandlers = {};
  1738. this.resolveHandlers = {};
  1739. this.serializeHandlers = {};
  1740. this.callbackHandlers = {};
  1741. this.onprogressHandlers = {};
  1742. this.serializer = new Serializer();
  1743. this.IDB = new IndexedDatabase();
  1744. this.workerPath = this.state.worker.path;
  1745. this.ifcWorker = new Worker(this.workerPath);
  1746. this.ifcWorker.onmessage = (data) => this.handleResponse(data);
  1747. this.properties = new PropertyHandler(this);
  1748. this.parser = new ParserHandler(this, this.serializer, this.BVH, this.IDB);
  1749. this.webIfc = new WebIfcHandler(this, this.serializer);
  1750. this.workerState = new WorkerStateHandler(this);
  1751. }
  1752. request(worker, action, args) {
  1753. const data = {
  1754. worker,
  1755. action,
  1756. args,
  1757. id: this.requestID,
  1758. result: undefined,
  1759. onProgress: false
  1760. };
  1761. return new Promise((resolve, reject) => {
  1762. this.resolveHandlers[this.requestID] = resolve;
  1763. this.rejectHandlers[this.requestID] = reject;
  1764. this.requestID++;
  1765. this.ifcWorker.postMessage(data);
  1766. });
  1767. }
  1768. async terminate() {
  1769. await this.request(WorkerAPIs.workerState, WorkerActions.dispose);
  1770. await this.request(WorkerAPIs.webIfc, WorkerActions.DisposeWebIfc);
  1771. this.ifcWorker.terminate();
  1772. }
  1773. async Close() {
  1774. await this.request(WorkerAPIs.webIfc, WorkerActions.Close);
  1775. }
  1776. handleResponse(event) {
  1777. const data = event.data;
  1778. if (data.onProgress) {
  1779. this.resolveOnProgress(data);
  1780. return;
  1781. }
  1782. this.callHandlers(data);
  1783. delete this.resolveHandlers[data.id];
  1784. delete this.rejectHandlers[data.id];
  1785. delete this.onprogressHandlers[data.id];
  1786. }
  1787. callHandlers(data) {
  1788. try {
  1789. this.resolveSerializations(data);
  1790. this.resolveCallbacks(data);
  1791. this.resolveHandlers[data.id](data.result);
  1792. } catch (error) {
  1793. this.rejectHandlers[data.id](error);
  1794. }
  1795. }
  1796. resolveOnProgress(data) {
  1797. if (this.onprogressHandlers[data.id]) {
  1798. data.result = this.onprogressHandlers[data.id](data.result);
  1799. }
  1800. }
  1801. resolveSerializations(data) {
  1802. if (this.serializeHandlers[data.id]) {
  1803. data.result = this.serializeHandlers[data.id](data.result);
  1804. delete this.serializeHandlers[data.id];
  1805. }
  1806. }
  1807. resolveCallbacks(data) {
  1808. if (this.callbackHandlers[data.id]) {
  1809. let callbackParameter = data.result;
  1810. if (this.callbackHandlers[data.id].serializer) {
  1811. callbackParameter = this.callbackHandlers[data.id].serializer(data.result);
  1812. }
  1813. this.callbackHandlers[data.id].action(callbackParameter);
  1814. }
  1815. }
  1816. }
  1817. class MemoryCleaner {
  1818. constructor(state) {
  1819. this.state = state;
  1820. }
  1821. async dispose() {
  1822. Object.keys(this.state.models).forEach(modelID => {
  1823. const model = this.state.models[parseInt(modelID, 10)];
  1824. model.mesh.removeFromParent();
  1825. const geom = model.mesh.geometry;
  1826. if (geom.disposeBoundsTree)
  1827. geom.disposeBoundsTree();
  1828. geom.dispose();
  1829. if (!Array.isArray(model.mesh.material))
  1830. model.mesh.material.dispose();
  1831. else
  1832. model.mesh.material.forEach(mat => mat.dispose());
  1833. model.mesh = null;
  1834. model.types = null;
  1835. model.jsonData = null;
  1836. });
  1837. this.state.api = null;
  1838. this.state.models = null;
  1839. }
  1840. }
  1841. class IFCUtils {
  1842. constructor(state) {
  1843. this.state = state;
  1844. this.map = {};
  1845. }
  1846. isA(entity, entity_class) {
  1847. var test = false;
  1848. if (entity_class) {
  1849. if (this.state.api.GetNameFromTypeCode(entity.type) === entity_class.toUpperCase()) {
  1850. test = true;
  1851. }
  1852. return test;
  1853. } else {
  1854. return this.state.api.GetNameFromTypeCode(entity.type);
  1855. }
  1856. }
  1857. async byId(modelID, id) {
  1858. return this.state.api.GetLine(modelID, id);
  1859. }
  1860. async idsByType(modelID, entity_class) {
  1861. let entities_ids = await this.state.api.GetLineIDsWithType(modelID, Number(this.state.api.GetTypeCodeFromName(modelID, entity_class.toUpperCase())));
  1862. return entities_ids;
  1863. }
  1864. async byType(modelID, entity_class) {
  1865. let entities_ids = await this.idsByType(modelID, entity_class);
  1866. if (entities_ids !== null) {
  1867. let items = [];
  1868. for (let i = 0; i < entities_ids.size(); i++) {
  1869. let entity = await this.byId(modelID, entities_ids.get(i));
  1870. items.push(entity);
  1871. }
  1872. return items;
  1873. }
  1874. }
  1875. }
  1876. class Data {
  1877. constructor(state) {
  1878. this.state = state;
  1879. this.isLoaded = false;
  1880. this.workPlans = {};
  1881. this.workSchedules = {};
  1882. this.workCalendars = {};
  1883. this.workTimes = {};
  1884. this.recurrencePatterns = {};
  1885. this.timePeriods = {};
  1886. this.tasks = {};
  1887. this.taskTimes = {};
  1888. this.lagTimes = {};
  1889. this.sequences = {};
  1890. this.utils = new IFCUtils(this.state);
  1891. }
  1892. async load(modelID) {
  1893. await this.loadTasks(modelID);
  1894. await this.loadWorkSchedules(modelID);
  1895. await this.loadWorkCalendars(modelID);
  1896. await this.loadWorkTimes(modelID);
  1897. await this.loadTimePeriods(modelID);
  1898. this.isLoaded = true;
  1899. }
  1900. async loadWorkSchedules(modelID) {
  1901. let workSchedules = await this.utils.byType(modelID, "IfcWorkSchedule");
  1902. for (let i = 0; i < workSchedules.length; i++) {
  1903. let workSchedule = workSchedules[i];
  1904. this.workSchedules[workSchedule.expressID] = {
  1905. "Id": workSchedule.expressID,
  1906. "Name": workSchedule.Name.value,
  1907. "Description": ((workSchedule.Description) ? workSchedule.Description.value : ""),
  1908. "Creators": [],
  1909. "CreationDate": ((workSchedule.CreationDate) ? workSchedule.CreationDate.value : ""),
  1910. "StartTime": ((workSchedule.StartTime) ? workSchedule.StartTime.value : ""),
  1911. "FinishTime": ((workSchedule.FinishTime) ? workSchedule.FinishTime.value : ""),
  1912. "TotalFloat": ((workSchedule.TotalFloat) ? workSchedule.TotalFloat.value : ""),
  1913. "RelatedObjects": [],
  1914. };
  1915. }
  1916. this.loadWorkScheduleRelatedObjects(modelID);
  1917. }
  1918. async loadWorkScheduleRelatedObjects(modelID) {
  1919. let relsControls = await this.utils.byType(modelID, "IfcRelAssignsToControl");
  1920. for (let i = 0; i < relsControls.length; i++) {
  1921. let relControls = relsControls[i];
  1922. let relatingControl = await this.utils.byId(modelID, relControls.RelatingControl.value);
  1923. let relatedObjects = relControls.RelatedObjects;
  1924. if (this.utils.isA(relatingControl, "IfcWorkSchedule")) {
  1925. for (var objectIndex = 0; objectIndex < relatedObjects.length; objectIndex++) {
  1926. this.workSchedules[relatingControl.expressID]["RelatedObjects"].push(relatedObjects[objectIndex].value);
  1927. }
  1928. }
  1929. }
  1930. }
  1931. async loadTasks(modelID) {
  1932. let tasks = await this.utils.byType(modelID, "IfcTask");
  1933. for (let i = 0; i < tasks.length; i++) {
  1934. let task = tasks[i];
  1935. this.tasks[task.expressID] = {
  1936. "Id": task.expressID,
  1937. "Name": ((task.Name) ? task.Name.value : ""),
  1938. "PredefinedType": ((task.PredefinedType) ? task.PredefinedType.value : ""),
  1939. "TaskTime": ((task.TaskTime) ? await this.utils.byId(modelID, task.TaskTime.value) : ""),
  1940. "Identification": ((task.Identification) ? task.Identification.value : ""),
  1941. "IsMilestone": ((task.IsMilestone) ? task.IsMilestone.value : ""),
  1942. "IsPredecessorTo": [],
  1943. "IsSucessorFrom": [],
  1944. "Inputs": [],
  1945. "Resources": [],
  1946. "Outputs": [],
  1947. "Controls": [],
  1948. "Nests": [],
  1949. "IsNestedBy": [],
  1950. "OperatesOn": [],
  1951. "HasAssignmentsWorkCalendars": [],
  1952. };
  1953. }
  1954. await this.loadTaskSequence(modelID);
  1955. await this.loadTaskOutputs(modelID);
  1956. await this.loadTaskNesting(modelID);
  1957. await this.loadTaskOperations(modelID);
  1958. await this.loadAssignementsWorkCalendar(modelID);
  1959. }
  1960. async loadTaskSequence(modelID) {
  1961. let relsSequence = await this.utils.idsByType(modelID, "IfcRelSequence");
  1962. for (let i = 0; i < relsSequence.size(); i++) {
  1963. let relSequenceId = relsSequence.get(i);
  1964. if (relSequenceId !== 0) {
  1965. let relSequence = await this.utils.byId(modelID, relSequenceId);
  1966. let related_process = relSequence.RelatedProcess.value;
  1967. let relatingProcess = relSequence.RelatingProcess.value;
  1968. this.tasks[relatingProcess]["IsPredecessorTo"].push(relSequence.expressID);
  1969. this.tasks[related_process]["IsSucessorFrom"].push(relSequence.expressID);
  1970. }
  1971. }
  1972. }
  1973. async loadTaskOutputs(modelID) {
  1974. let rels_assigns_to_product = await this.utils.byType(modelID, "IfcRelAssignsToProduct");
  1975. for (let i = 0; i < rels_assigns_to_product.length; i++) {
  1976. let relAssignsToProduct = rels_assigns_to_product[i];
  1977. let relatedObject = await this.utils.byId(modelID, relAssignsToProduct.RelatedObjects[0].value);
  1978. if (this.utils.isA(relatedObject, "IfcTask")) {
  1979. let relatingProduct = await this.utils.byId(modelID, relAssignsToProduct.RelatingProduct.value);
  1980. this.tasks[relatedObject.expressID]["Outputs"].push(relatingProduct.expressID);
  1981. }
  1982. }
  1983. }
  1984. async loadTaskNesting(modelID) {
  1985. let rels_nests = await this.utils.byType(modelID, "IfcRelNests");
  1986. for (let i = 0; i < rels_nests.length; i++) {
  1987. let relNests = rels_nests[i];
  1988. let relating_object = await this.utils.byId(modelID, relNests.RelatingObject.value);
  1989. if (this.utils.isA(relating_object, "IfcTask")) {
  1990. let relatedObjects = relNests.RelatedObjects;
  1991. for (var object_index = 0; object_index < relatedObjects.length; object_index++) {
  1992. this.tasks[relating_object.expressID]["IsNestedBy"].push(relatedObjects[object_index].value);
  1993. this.tasks[relatedObjects[object_index].value]["Nests"].push(relating_object.expressID);
  1994. }
  1995. }
  1996. }
  1997. }
  1998. async loadTaskOperations(modelID) {
  1999. let relsAssignsToProcess = await this.utils.byType(modelID, "IfcRelAssignsToProcess");
  2000. for (let i = 0; i < relsAssignsToProcess.length; i++) {
  2001. let relAssignToProcess = relsAssignsToProcess[i];
  2002. let relatingProcess = await this.utils.byId(modelID, relAssignToProcess.RelatingProcess.value);
  2003. if (this.utils.isA(relatingProcess, "IfcTask")) {
  2004. let relatedObjects = relAssignToProcess.RelatedObjects;
  2005. for (var object_index = 0; object_index < relatedObjects.length; object_index++) {
  2006. this.tasks[relatingProcess.expressID]["OperatesOn"].push(relatedObjects[object_index].value);
  2007. }
  2008. }
  2009. }
  2010. }
  2011. async loadAssignementsWorkCalendar(modelID) {
  2012. let relsAssignsToControl = await this.utils.byType(modelID, "IfcRelAssignsToControl");
  2013. for (let i = 0; i < relsAssignsToControl.length; i++) {
  2014. let relAssignsToControl = relsAssignsToControl[i];
  2015. let relatingControl = await this.utils.byId(modelID, relAssignsToControl.RelatingControl.value);
  2016. if (this.utils.isA(relatingControl, "IfcWorkCalendar")) {
  2017. let relatedObjects = relAssignsToControl.RelatedObjects;
  2018. for (var object_index = 0; object_index < relatedObjects.length; object_index++) {
  2019. this.tasks[relatedObjects[object_index].value]["HasAssignmentsWorkCalendars"].push(relatingControl.expressID);
  2020. }
  2021. }
  2022. }
  2023. }
  2024. async loadWorkCalendars(modelID) {
  2025. let workCalendars = await this.utils.byType(modelID, "IfcWorkCalendar");
  2026. for (let i = 0; i < workCalendars.length; i++) {
  2027. let workCalendar = workCalendars[i];
  2028. let workCalenderData = {
  2029. "Id": workCalendar.expressID,
  2030. "Name": ((workCalendar.Name) ? workCalendar.Name.value : ""),
  2031. "Description": ((workCalendar.Description) ? workCalendar.Description.value : ""),
  2032. "WorkingTimes": ((workCalendar.WorkingTimes) ? workCalendar.WorkingTimes : []),
  2033. "ExceptionTimes": ((workCalendar.ExceptionTimes) ? workCalendar.ExceptionTimes : []),
  2034. };
  2035. this.workCalendars[workCalendar.expressID] = workCalenderData;
  2036. }
  2037. }
  2038. async loadWorkTimes(modelID) {
  2039. let workTimes = await this.utils.byType(modelID, "IfcWorkTime");
  2040. for (let i = 0; i < workTimes.length; i++) {
  2041. let workTime = workTimes[i];
  2042. let workTimeData = {
  2043. "Name": ((workTime.Name) ? workTime.Name.value : ""),
  2044. "RecurrencePattern": ((workTime.RecurrencePattern) ? await this.utils.byId(modelID, workTime.RecurrencePattern.value) : ""),
  2045. "Start": ((workTime.Start) ? new Date(workTime.Start.value) : ""),
  2046. "Finish": ((workTime.Finish) ? new Date(workTime.Finish.value) : ""),
  2047. };
  2048. this.workTimes[workTime.expressID] = workTimeData;
  2049. }
  2050. }
  2051. async loadTimePeriods(modelID) {
  2052. let timePeriods = await this.utils.byType(modelID, "IfcTimePeriod");
  2053. for (let i = 0; i < timePeriods.length; i++) {
  2054. let timePeriod = timePeriods[i];
  2055. let workTimeData = {
  2056. "StartTime": ((timePeriod.StartTime) ? new Date(timePeriod.StartTime.value) : ""),
  2057. "EndTime": ((timePeriod.EndTime) ? new Date(timePeriod.EndTime.value) : ""),
  2058. };
  2059. this.timePeriods[timePeriod.expressID] = workTimeData;
  2060. }
  2061. }
  2062. }
  2063. class IFCManager {
  2064. constructor() {
  2065. this.state = {
  2066. models: [],
  2067. api: new WebIFC.IfcAPI(),
  2068. useJSON: false,
  2069. worker: {
  2070. active: false,
  2071. path: ''
  2072. }
  2073. };
  2074. this.BVH = new BvhManager();
  2075. this.parser = new IFCParser(this.state, this.BVH);
  2076. this.subsets = new SubsetManager(this.state, this.BVH);
  2077. this.utils = new IFCUtils(this.state);
  2078. this.sequenceData = new Data(this.state);
  2079. this.properties = new PropertyManager(this.state);
  2080. this.types = new TypeManager(this.state);
  2081. this.useFragments = false;
  2082. this.cleaner = new MemoryCleaner(this.state);
  2083. }
  2084. get ifcAPI() {
  2085. return this.state.api;
  2086. }
  2087. async parse(buffer) {
  2088. var _a;
  2089. let model = await this.parser.parse(buffer, (_a = this.state.coordinationMatrix) === null || _a === void 0 ? void 0 : _a.toArray());
  2090. model.setIFCManager(this);
  2091. try {
  2092. await this.types.getAllTypes(this.worker);
  2093. } catch (e) {
  2094. console.log("Could not get all types of model.");
  2095. }
  2096. return model;
  2097. }
  2098. async setWasmPath(path) {
  2099. this.state.api.SetWasmPath(path);
  2100. this.state.wasmPath = path;
  2101. }
  2102. setupThreeMeshBVH(computeBoundsTree, disposeBoundsTree, acceleratedRaycast) {
  2103. this.BVH.initializeMeshBVH(computeBoundsTree, disposeBoundsTree, acceleratedRaycast);
  2104. }
  2105. setOnProgress(onProgress) {
  2106. this.state.onProgress = onProgress;
  2107. }
  2108. setupCoordinationMatrix(matrix) {
  2109. this.state.coordinationMatrix = matrix;
  2110. }
  2111. clearCoordinationMatrix() {
  2112. delete this.state.coordinationMatrix;
  2113. }
  2114. async applyWebIfcConfig(settings) {
  2115. this.state.webIfcSettings = settings;
  2116. if (this.state.worker.active && this.worker) {
  2117. await this.worker.workerState.updateStateWebIfcSettings();
  2118. }
  2119. }
  2120. async useWebWorkers(active, path) {
  2121. if (this.state.worker.active === active)
  2122. return;
  2123. this.state.api = null;
  2124. if (active) {
  2125. if (!path)
  2126. throw new Error('You must provide a path to the web worker.');
  2127. this.state.worker.active = active;
  2128. this.state.worker.path = path;
  2129. await this.initializeWorkers();
  2130. const wasm = this.state.wasmPath;
  2131. if (wasm)
  2132. await this.setWasmPath(wasm);
  2133. } else {
  2134. this.state.api = new WebIFC.IfcAPI();
  2135. }
  2136. }
  2137. async useJSONData(useJSON = true) {
  2138. var _a;
  2139. this.state.useJSON = useJSON;
  2140. if (useJSON) {
  2141. await ((_a = this.worker) === null || _a === void 0 ? void 0 : _a.workerState.updateStateUseJson());
  2142. }
  2143. }
  2144. async addModelJSONData(modelID, data) {
  2145. var _a;
  2146. const model = this.state.models[modelID];
  2147. if (!model)
  2148. throw new Error('The specified model for the JSON data does not exist');
  2149. if (this.state.worker.active) {
  2150. await ((_a = this.worker) === null || _a === void 0 ? void 0 : _a.workerState.updateModelStateJsonData(modelID, data));
  2151. } else {
  2152. model.jsonData = data;
  2153. }
  2154. }
  2155. async loadJsonDataFromWorker(modelID, path) {
  2156. var _a;
  2157. if (this.state.worker.active) {
  2158. await ((_a = this.worker) === null || _a === void 0 ? void 0 : _a.workerState.loadJsonDataFromWorker(modelID, path));
  2159. }
  2160. }
  2161. close(modelID, scene) {
  2162. try {
  2163. this.state.api.CloseModel(modelID);
  2164. const mesh = this.state.models[modelID].mesh;
  2165. const {geometry, material} = mesh;
  2166. if (scene)
  2167. scene.remove(mesh);
  2168. geometry === null || geometry === void 0 ? void 0 : geometry.dispose();
  2169. Array.isArray(material) ? material.forEach(m => m.dispose()) : material === null || material === void 0 ? void 0 : material.dispose();
  2170. delete this.state.models[modelID];
  2171. } catch (e) {
  2172. console.warn(`Close IFCModel ${modelID} failed`);
  2173. }
  2174. }
  2175. getExpressId(geometry, faceIndex) {
  2176. return this.properties.getExpressId(geometry, faceIndex);
  2177. }
  2178. getAllItemsOfType(modelID, type, verbose) {
  2179. return this.properties.getAllItemsOfType(modelID, type, verbose);
  2180. }
  2181. getItemProperties(modelID, id, recursive = false) {
  2182. return this.properties.getItemProperties(modelID, id, recursive);
  2183. }
  2184. getPropertySets(modelID, id, recursive = false) {
  2185. return this.properties.getPropertySets(modelID, id, recursive);
  2186. }
  2187. getTypeProperties(modelID, id, recursive = false) {
  2188. return this.properties.getTypeProperties(modelID, id, recursive);
  2189. }
  2190. getMaterialsProperties(modelID, id, recursive = false) {
  2191. return this.properties.getMaterialsProperties(modelID, id, recursive);
  2192. }
  2193. getIfcType(modelID, id) {
  2194. const typeID = this.state.models[modelID].types[id];
  2195. return this.state.api.GetNameFromTypeCode(typeID);
  2196. }
  2197. getSpatialStructure(modelID, includeProperties) {
  2198. return this.properties.getSpatialStructure(modelID, includeProperties);
  2199. }
  2200. getSubset(modelID, material, customId) {
  2201. return this.subsets.getSubset(modelID, material, customId);
  2202. }
  2203. removeSubset(modelID, material, customID) {
  2204. this.subsets.removeSubset(modelID, material, customID);
  2205. }
  2206. createSubset(config) {
  2207. return this.subsets.createSubset(config);
  2208. }
  2209. removeFromSubset(modelID, ids, customID, material) {
  2210. return this.subsets.removeFromSubset(modelID, ids, customID, material);
  2211. }
  2212. clearSubset(modelID, customID, material) {
  2213. return this.subsets.clearSubset(modelID, customID, material);
  2214. }
  2215. async isA(entity, entity_class) {
  2216. return this.utils.isA(entity, entity_class);
  2217. }
  2218. async getSequenceData(modelID) {
  2219. await this.sequenceData.load(modelID);
  2220. return this.sequenceData;
  2221. }
  2222. async byType(modelID, entityClass) {
  2223. return this.utils.byType(modelID, entityClass);
  2224. }
  2225. async byId(modelID, id) {
  2226. return this.utils.byId(modelID, id);
  2227. }
  2228. async idsByType(modelID, entityClass) {
  2229. return this.utils.idsByType(modelID, entityClass);
  2230. }
  2231. async dispose() {
  2232. IFCModel.dispose();
  2233. await this.cleaner.dispose();
  2234. this.subsets.dispose();
  2235. if (this.worker && this.state.worker.active)
  2236. await this.worker.terminate();
  2237. this.state = null;
  2238. }
  2239. async disposeMemory() {
  2240. var _a;
  2241. if (this.state.worker.active) {
  2242. await ((_a = this.worker) === null || _a === void 0 ? void 0 : _a.Close());
  2243. } else {
  2244. this.state.api.Close();
  2245. this.state.api = null;
  2246. this.state.api = new WebIFC.IfcAPI();
  2247. }
  2248. }
  2249. getAndClearErrors(modelID) {
  2250. return this.parser.getAndClearErrors(modelID);
  2251. }
  2252. async initializeWorkers() {
  2253. this.worker = new IFCWorkerHandler(this.state, this.BVH);
  2254. this.state.api = this.worker.webIfc;
  2255. this.properties = this.worker.properties;
  2256. await this.worker.parser.setupOptionalCategories(this.parser.optionalCategories);
  2257. this.parser = this.worker.parser;
  2258. await this.worker.workerState.updateStateUseJson();
  2259. await this.worker.workerState.updateStateWebIfcSettings();
  2260. }
  2261. }
  2262. class IFCLoader extends Loader {
  2263. constructor(manager) {
  2264. super(manager);
  2265. this.ifcManager = new IFCManager();
  2266. }
  2267. load(url, onLoad, onProgress, onError) {
  2268. const scope = this;
  2269. const loader = new FileLoader(scope.manager);
  2270. this.onProgress = onProgress;
  2271. loader.setPath(scope.path);
  2272. loader.setResponseType('arraybuffer');
  2273. loader.setRequestHeader(scope.requestHeader);
  2274. loader.setWithCredentials(scope.withCredentials);
  2275. loader.load(url, async function (buffer) {
  2276. try {
  2277. if (typeof buffer == 'string') {
  2278. throw new Error('IFC files must be given as a buffer!');
  2279. }
  2280. onLoad(await scope.parse(buffer));
  2281. } catch (e) {
  2282. if (onError) {
  2283. onError(e);
  2284. } else {
  2285. console.error(e);
  2286. }
  2287. scope.manager.itemError(url);
  2288. }
  2289. }, onProgress, onError);
  2290. }
  2291. parse(buffer) {
  2292. return this.ifcManager.parse(buffer);
  2293. }
  2294. }
  2295. export { IFCLoader };
  2296. //# sourceMappingURL=IFCLoader.js.map