diff --git a/web-ifc-three/src/IFC/components/subsets/SubsetCreator.ts b/web-ifc-three/src/IFC/components/subsets/SubsetCreator.ts index 1d5a915..b7a0b70 100644 --- a/web-ifc-three/src/IFC/components/subsets/SubsetCreator.ts +++ b/web-ifc-three/src/IFC/components/subsets/SubsetCreator.ts @@ -73,17 +73,15 @@ export class SubsetCreator { private constructSubsetByMaterial(config: SubsetConfig, subsetID: string) { const model = this.state.models[config.modelID].mesh; const newIndices = { count: 0 }; + const indicesByMaterial = SubsetUtils.getAllIndicesByMaterial(config.ids, this.items.map[config.modelID]); for (let i = 0; i < model.geometry.groups.length; i++) { - this.insertNewIndices(config, subsetID, i, newIndices); + this.insertNewIndices(config, subsetID, i, newIndices, indicesByMaterial[i] || []); } } // If this subset has original materials, insert indices in correct position and update groups // Otherwise, just insert indices at any position - private insertNewIndices(config: SubsetConfig, subsetID: string, materialIndex: number, newIndices: any) { - const items = this.items.map[config.modelID]; - const indicesOfOneMaterial = SubsetUtils.getAllIndicesOfGroup(config.modelID, config.ids, materialIndex, items) as number[]; - + private insertNewIndices(config: SubsetConfig, subsetID: string, materialIndex: number, newIndices: any, indicesOfOneMaterial: number[]) { if (!config.material) { this.insertIndicesAtGroup(subsetID, indicesOfOneMaterial, materialIndex, newIndices); } else { @@ -116,4 +114,4 @@ export class SubsetCreator { group.count = 0; }); } -} \ No newline at end of file +} diff --git a/web-ifc-three/src/IFC/components/subsets/SubsetUtils.ts b/web-ifc-three/src/IFC/components/subsets/SubsetUtils.ts index cedd1e3..0e3fd7b 100644 --- a/web-ifc-three/src/IFC/components/subsets/SubsetUtils.ts +++ b/web-ifc-three/src/IFC/components/subsets/SubsetUtils.ts @@ -1,5 +1,21 @@ export class SubsetUtils { + static getAllIndicesByMaterial(ids: number[], items: any) { + const indicesByMaterial: number[][] = []; + for (const expressID of ids) { + const entry = items.map.get(expressID); + if (!entry) continue; + for (const materialID of Object.keys(entry)) { + const materialIndex = Number(materialID); + const value = entry[materialIndex]; + if (!value) continue; + if (!indicesByMaterial[materialIndex]) indicesByMaterial[materialIndex] = []; + SubsetUtils.getIndexChunk(value, indicesByMaterial[materialIndex], materialIndex, items, true); + } + } + return indicesByMaterial; + } + // If flatten, all indices are in the same array; otherwise, indices are split in subarrays by material static getAllIndicesOfGroup(modelID: number, ids: number[], materialIndex: number, items: any, flatten = true) { const indicesByGroup: any = []; @@ -28,4 +44,4 @@ export class SubsetUtils { } } } -} \ No newline at end of file +} diff --git a/web-ifc-three/test/IFC/Components/SubsetUtils.test.ts b/web-ifc-three/test/IFC/Components/SubsetUtils.test.ts new file mode 100644 index 0000000..0540252 --- /dev/null +++ b/web-ifc-three/test/IFC/Components/SubsetUtils.test.ts @@ -0,0 +1,27 @@ +import {SubsetUtils} from "../../../src/IFC/components/subsets/SubsetUtils"; + +describe("SubsetUtils", () => { + + test("groups indices by material with one map lookup per express ID", () => { + + const sourceMap = new Map([ + [7, {0: [0, 1, 4, 4], 2: [6, 7]}], + [8, {0: [5, 5], 1: [2, 3]}], + ]); + const items = { + indexCache: Uint32Array.from([10, 11, 12, 13, 14, 15, 16, 17]), + map: { + get: jest.fn((id: number) => sourceMap.get(id)) + } + }; + + const result = SubsetUtils.getAllIndicesByMaterial([7, 8, 404], items); + + expect(items.map.get).toHaveBeenCalledTimes(3); + expect(result[0]).toEqual([10, 11, 14, 15]); + expect(result[1]).toEqual([12, 13]); + expect(result[2]).toEqual([16, 17]); + expect(result[3]).toBeUndefined(); + expect(result[0]).toEqual(SubsetUtils.getAllIndicesOfGroup(0, [7, 8, 404], 0, items)); + }); +});