bimatter-viewer-react 0.5.11 → 0.5.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -268,6 +268,32 @@ Use `viewerRef.current.colors` to apply temporary color overrides to model eleme
268
268
 
269
269
  ```tsx
270
270
  viewerRef.current?.colors.setColor(0, [10, 20, 30], "#ff3355");
271
+ viewerRef.current?.colors.rebuildByColors({
272
+ 0: {
273
+ "#ff3355": [10, 20, 30],
274
+ "#3b82f6": [40, 50],
275
+ },
276
+ 1: {
277
+ "#22c55e": [10, 20],
278
+ },
279
+ });
280
+ viewerRef.current?.colors.rebuildByColors(
281
+ {
282
+ 0: {
283
+ "#ff3355": [10, 20, 30],
284
+ "#3b82f6": [40, 50],
285
+ },
286
+ },
287
+ "#d1d5db",
288
+ );
289
+ viewerRef.current?.colors.rebuildModelByColors(
290
+ 0,
291
+ {
292
+ "#ff3355": [10, 20, 30],
293
+ "#3b82f6": [40, 50],
294
+ },
295
+ "#d1d5db",
296
+ );
271
297
  viewerRef.current?.colors.clearColor(0, [10, 20]);
272
298
  viewerRef.current?.colors.clearModelColors(0);
273
299
  viewerRef.current?.colors.clearAllColors();
@@ -455,6 +481,56 @@ With `ofLevel(level)`, `toElements()` returns `{ elementID, props }[]` and `toEl
455
481
 
456
482
  `ofType()` accepts `IfcClass | string`, so TypeScript suggests IFC classes like `"IfcWall"` while still allowing custom type strings.
457
483
 
484
+ ## Using Colorize With Collectors
485
+
486
+ Collectors can be used directly as color inputs. This is useful when you want to highlight elements by IFC type, level, or property value:
487
+
488
+ ```tsx
489
+ const viewer = viewerRef.current;
490
+
491
+ viewer?.colors.rebuildModelByColors(
492
+ 0,
493
+ {
494
+ "#ff3355":
495
+ viewer.selector
496
+ .collector()
497
+ .ofModel(0)
498
+ .Where((element) => {
499
+ return (
500
+ viewer.properties.getParamValueByName(
501
+ element.props,
502
+ "System Name",
503
+ "Mechanical",
504
+ ) === "Mechanical Supply Air 2"
505
+ );
506
+ })
507
+ .toElementsIds() ?? [],
508
+ },
509
+ "#d1d5db",
510
+ );
511
+ ```
512
+
513
+ You can also combine level filters with type filters:
514
+
515
+ ```tsx
516
+ const viewer = viewerRef.current;
517
+ const firstLevel = viewer?.properties.getAllModelLevels(0, true)[0];
518
+
519
+ if (viewer && firstLevel) {
520
+ viewer.colors.rebuildModelByColors(
521
+ 0,
522
+ {
523
+ "#3b82f6": viewer.selector
524
+ .collector()
525
+ .ofLevel(firstLevel)
526
+ .ofType("IfcWall")
527
+ .toElementsIds(),
528
+ },
529
+ "#d1d5db",
530
+ );
531
+ }
532
+ ```
533
+
458
534
  ## Stats And Profiling
459
535
 
460
536
  Enable FPS stats and console timing logs:
@@ -191328,60 +191328,61 @@ var h_ = class {
191328
191328
  constructor(e) {
191329
191329
  this.parser = e;
191330
191330
  }
191331
- async serializeAllProperties(e, t) {
191332
- return await this.getPropertiesAsBlobs(e, t);
191333
- }
191334
- async getPropertiesAsBlobs(e, t) {
191335
- let n = await this.getAllRelDefinesByProps(e), r = {}, i = this.parser.GetLineIDsWithType(e, yd).get(0);
191336
- if (i === void 0) return r;
191337
- let a = await this.getItemProperty(e, i) ?? {
191338
- id: i,
191331
+ async serializeAllProperties(e, t, n) {
191332
+ return await this.getPropertiesAsBlobs(e, t, n);
191333
+ }
191334
+ async getPropertiesAsBlobs(e, t, n) {
191335
+ let r = await this.getAllRelDefinesByProps(e), i = r.size, a = t.size, o = {}, s = this.parser.GetLineIDsWithType(e, yd).get(0);
191336
+ if (s === void 0) return o;
191337
+ let c = await this.getItemProperty(e, s) ?? {
191338
+ id: s,
191339
191339
  props: {},
191340
191340
  sets: []
191341
191341
  };
191342
- a.sets = [], r[i] = a;
191343
- for (let t of n) {
191344
- let n = await this.getItemProperty(e, t);
191345
- if (n) {
191346
- let t = p_(n.RelatingPropertyDefinition);
191342
+ c.sets = [], o[s] = c;
191343
+ let l = 0;
191344
+ for (let t of r) {
191345
+ let r = await this.getItemProperty(e, t);
191346
+ if (r) {
191347
+ let t = p_(r.RelatingPropertyDefinition);
191347
191348
  if (t === null) continue;
191348
- let i = await this.getItemProperty(e, t, !0), a = {
191349
+ let n = await this.getItemProperty(e, t, !0), i = {
191349
191350
  id: t,
191350
191351
  guid: "null",
191351
191352
  name: "null",
191352
191353
  props: [],
191353
191354
  isQuantities: !1
191354
191355
  };
191355
- if (i && (i.HasProperties || i.Quantities)) {
191356
- if (i.Quantities) for (let e of i.Quantities) this.formatItemProperties(e);
191357
- if (i.HasProperties) for (let e of i.HasProperties) this.formatItemProperties(e);
191358
- a = {
191356
+ if (n && (n.HasProperties || n.Quantities)) {
191357
+ if (n.Quantities) for (let e of n.Quantities) this.formatItemProperties(e);
191358
+ if (n.HasProperties) for (let e of n.HasProperties) this.formatItemProperties(e);
191359
+ i = {
191359
191360
  id: t,
191360
- guid: this.getStringValue(i.GlobalId) ?? "null",
191361
- name: this.getStringValue(i.Name) ?? "null",
191362
- props: i.HasProperties ? i.HasProperties : i.Quantities ? i.Quantities : [],
191363
- isQuantities: !!i.Quantities
191361
+ guid: this.getStringValue(n.GlobalId) ?? "null",
191362
+ name: this.getStringValue(n.Name) ?? "null",
191363
+ props: n.HasProperties ? n.HasProperties : n.Quantities ? n.Quantities : [],
191364
+ isQuantities: !!n.Quantities
191364
191365
  };
191365
191366
  }
191366
- let o = m_(n.RelatedObjects);
191367
- for (let t of o) if (r[t]) r[t].sets ??= [], r[t].sets.push(a);
191367
+ let a = m_(r.RelatedObjects);
191368
+ for (let t of a) if (o[t]) o[t].sets ??= [], o[t].sets.push(i);
191368
191369
  else {
191369
191370
  let n = await this.getItemProperty(e, t);
191370
191371
  if (n) {
191371
- let e = this.getStringValue(n.GlobalId), i = n.Name, o = n.ObjectType, s = n.LongName, c = this.getStringValue(n.type), l = {
191372
- name: i,
191373
- typeName: o,
191372
+ let e = this.getStringValue(n.GlobalId), r = n.Name, a = n.ObjectType, s = n.LongName, c = this.getStringValue(n.type), l = {
191373
+ name: r,
191374
+ typeName: a,
191374
191375
  longName: s,
191375
191376
  type: c,
191376
191377
  elevation: void 0
191377
191378
  };
191378
- r[t] = {
191379
+ o[t] = {
191379
191380
  id: t,
191380
191381
  guid: e,
191381
191382
  props: l,
191382
- sets: [a]
191383
+ sets: [i]
191383
191384
  }, c === "IfcBuildingStorey" && (l.elevation = n.Elevation);
191384
- } else r[t] = {
191385
+ } else o[t] = {
191385
191386
  id: t,
191386
191387
  guid: "null",
191387
191388
  props: {
@@ -191391,16 +191392,29 @@ var h_ = class {
191391
191392
  type: "null",
191392
191393
  elevation: void 0
191393
191394
  },
191394
- sets: [a]
191395
+ sets: [i]
191395
191396
  };
191396
191397
  }
191397
191398
  }
191399
+ l += 1, this.shouldEmitProgress(l, i) && n?.({
191400
+ loaded: l,
191401
+ phase: "propertySets",
191402
+ total: i
191403
+ });
191398
191404
  }
191399
- for (let n of t) {
191400
- if (r[n]) continue;
191401
- let t = await this.getItemProperty(e, n);
191402
- t ? r[n] = {
191403
- id: n,
191405
+ let u = 0;
191406
+ for (let r of t) {
191407
+ if (o[r]) {
191408
+ u += 1, this.shouldEmitProgress(u, a) && n?.({
191409
+ loaded: u,
191410
+ phase: "elements",
191411
+ total: a
191412
+ });
191413
+ continue;
191414
+ }
191415
+ let t = await this.getItemProperty(e, r);
191416
+ t ? o[r] = {
191417
+ id: r,
191404
191418
  guid: this.getStringValue(t.GlobalId),
191405
191419
  props: {
191406
191420
  name: t.Name,
@@ -191410,8 +191424,8 @@ var h_ = class {
191410
191424
  elevation: void 0
191411
191425
  },
191412
191426
  sets: []
191413
- } : r[n] = {
191414
- id: n,
191427
+ } : o[r] = {
191428
+ id: r,
191415
191429
  guid: "null",
191416
191430
  props: {
191417
191431
  name: "null",
@@ -191421,9 +191435,13 @@ var h_ = class {
191421
191435
  elevation: void 0
191422
191436
  },
191423
191437
  sets: []
191424
- };
191438
+ }, u += 1, this.shouldEmitProgress(u, a) && n?.({
191439
+ loaded: u,
191440
+ phase: "elements",
191441
+ total: a
191442
+ });
191425
191443
  }
191426
- return r;
191444
+ return o;
191427
191445
  }
191428
191446
  async getItemProperty(e, t, n = !1) {
191429
191447
  try {
@@ -191585,6 +191603,9 @@ var h_ = class {
191585
191603
  let i = m_(n[t.related]);
191586
191604
  e[r] == null ? e[r] = i : e[r] = e[r].concat(i);
191587
191605
  }
191606
+ shouldEmitProgress(e, t) {
191607
+ return t <= 0 || e <= 0 || e >= t ? !0 : e % Math.max(1, Math.floor(t / 100)) === 0;
191608
+ }
191588
191609
  };
191589
191610
  //#endregion
191590
191611
  //#region src/viewer/Loaders/IFCLoader/IfcGrid.ts
@@ -191820,7 +191841,7 @@ var __ = class {
191820
191841
  n && (d[t] = this.transformGridData(n, l));
191821
191842
  }
191822
191843
  r?.onPhase?.("properties");
191823
- let f = await this.propertySerializer.serializeAllProperties(a, o), p = await this.propertySerializer.getSpatialStructure(a, !1);
191844
+ let f = await this.propertySerializer.serializeAllProperties(a, o, r?.onPropertiesProgress), p = await this.propertySerializer.getSpatialStructure(a, !1);
191824
191845
  return c.coordinationMatrix ??= this.coordinationMatrixData, c.props = f, c.structure = p, c.grids = d, {
191825
191846
  structure: p,
191826
191847
  propsData: f,
@@ -11,6 +11,16 @@ export type BmtActiveViewFilterParams = {
11
11
  modelID: number;
12
12
  };
13
13
  export type BmtActiveViewFilter = (params: BmtActiveViewFilterParams) => boolean;
14
+ export type BmtConverterProgressPhase = "preparing" | "filtering" | "properties" | "geometry" | "metadata" | "writing" | "complete";
15
+ export type BmtConverterProgressEvent = {
16
+ loaded?: number;
17
+ message?: string;
18
+ modelID: number;
19
+ modelIndex: number;
20
+ phase: BmtConverterProgressPhase;
21
+ progress: number;
22
+ total?: number;
23
+ };
14
24
  export type BmtConverterOptions = {
15
25
  activeView?: boolean;
16
26
  activeViewRoot?: Object3D | Object3D[] | null;
@@ -20,6 +30,7 @@ export type BmtConverterOptions = {
20
30
  fileNames?: Record<string | number, string>;
21
31
  filterElement?: BmtActiveViewFilter;
22
32
  maxMeshBytes?: number;
33
+ onProgress?: (progress: BmtConverterProgressEvent) => void;
23
34
  useIfcColors?: boolean;
24
35
  useIfcElementAssembly?: boolean;
25
36
  useIfcSpace?: boolean;
@@ -89,6 +100,8 @@ export declare class BmtConverter {
89
100
  private deflateBytes;
90
101
  private encodeText;
91
102
  private encodePrettyJson;
103
+ private shouldEmitItemProgress;
104
+ private clampProgress;
92
105
  private isRecord;
93
106
  }
94
107
  export declare const bmtConverter: BmtConverter;
@@ -1,4 +1,4 @@
1
- import { type IfcElementsAssembly } from "./PropertySerializer";
1
+ import { type IfcElementsAssembly, type IfcPropertiesProgressData } from "./PropertySerializer";
2
2
  import { Matrix4 } from "three";
3
3
  import { IfcAPI, type LocateFileHandlerFn } from "web-ifc";
4
4
  import { type GridData } from "./IfcGrid";
@@ -30,11 +30,13 @@ export type IfcGeometryProgressData = {
30
30
  processed: number;
31
31
  total: number;
32
32
  };
33
+ export type IfcPropertyProgressData = IfcPropertiesProgressData;
33
34
  export type IfcParsePhase = "opening" | "opened" | "streaming" | "properties" | "metadata";
34
35
  export type IfcParseCallbacks = {
35
36
  onGeometryChunk?: (chunk: IfcGeometryChunkData) => void;
36
37
  onGeometryProgress?: (progress: IfcGeometryProgressData) => void;
37
38
  onPhase?: (phase: IfcParsePhase) => void;
39
+ onPropertiesProgress?: (progress: IfcPropertyProgressData) => void;
38
40
  streamGeometryChunks?: boolean;
39
41
  };
40
42
  export declare class IFCLoader {
@@ -30,12 +30,18 @@ export type IfcElementsAssembly = {
30
30
  dict: Record<number, number>;
31
31
  ids: number[];
32
32
  };
33
+ export type IfcPropertiesProgressData = {
34
+ loaded: number;
35
+ phase: "propertySets" | "elements";
36
+ total: number;
37
+ };
38
+ export type IfcPropertiesProgressCallback = (progress: IfcPropertiesProgressData) => void;
33
39
  export declare class PropertySerializer {
34
40
  private PropsNames;
35
41
  readonly parser: IfcAPI;
36
42
  constructor(parser: IfcAPI);
37
- serializeAllProperties(modelID: number, ids: Set<number>): Promise<BmtModelProps>;
38
- getPropertiesAsBlobs(modelID: number, ids: Set<number>): Promise<BmtModelProps>;
43
+ serializeAllProperties(modelID: number, ids: Set<number>, onProgress?: IfcPropertiesProgressCallback): Promise<BmtModelProps>;
44
+ getPropertiesAsBlobs(modelID: number, ids: Set<number>, onProgress?: IfcPropertiesProgressCallback): Promise<BmtModelProps>;
39
45
  getItemProperty(modelID: number, id: number, flatten?: boolean): Promise<IfcLineData | null>;
40
46
  getElementsAssembly(modelID: number): Promise<IfcElementsAssembly>;
41
47
  private formatItemProperties;
@@ -53,5 +59,6 @@ export declare class PropertySerializer {
53
59
  newNode(id: number, data: IfcLineData): BmtModelStructureNode;
54
60
  getSpatialTreeChunks(modelID: number): Promise<SpatialTreeChunks>;
55
61
  saveChunk(chunks: SpatialTreeChunks, propNames: PropertyRelationConfig, rel: IfcLineData): void;
62
+ private shouldEmitProgress;
56
63
  }
57
64
  export {};
@@ -1,3 +1,4 @@
1
+ import { type Vector3 } from "three";
1
2
  import type { CameraUtilsApi } from "../Camera/useCameraUtils";
2
3
  import type { ViewerControlsRef, ViewerModelRef } from "../types";
3
- export default function useSelector(modelRef: ViewerModelRef, controlRef: ViewerControlsRef, cameraUtils: CameraUtilsApi): void;
4
+ export default function useSelector(modelRef: ViewerModelRef, controlRef: ViewerControlsRef, cameraUtils: CameraUtilsApi, setSelectionOrbitPoint?: (point: Vector3) => void): void;
@@ -2,11 +2,13 @@ import type { ColorRepresentation } from "three";
2
2
  import type { SelectedStore, UserDevice, ViewerGridAxesVisibility, ViewerGridAxisSide, ViewerStoreApi } from "../store/ViewerStore";
3
3
  import { type ViewerPropertiesApi } from "./ViewerPropertiesApi";
4
4
  import type { ViewerClippingApi } from "../utils/ClippingUtils";
5
+ import type { ViewerColorConfigByModel, ViewerModelColorConfig } from "../utils/ColorsUtils/useElementColors";
5
6
  import type { ViewerDimensionsApi } from "../utils/DimentionsUtils";
6
7
  import type { ViewerCameraGetIntersection } from "../Camera/useCameraUtils";
7
8
  import type { BmtConversionResult, BmtConverterOptions, BmtConverterSource } from "../Loaders/BmtConverter";
8
9
  import { FilteredElementsCollector } from "../Selector/FilteredElementsCollector";
9
10
  export type { ViewerClippingApi } from "../utils/ClippingUtils";
11
+ export type { ViewerColorConfigByModel, ViewerModelColorConfig, } from "../utils/ColorsUtils/useElementColors";
10
12
  export type { ViewerDimensionsApi } from "../utils/DimentionsUtils";
11
13
  export type { ViewerCameraGetIntersection } from "../Camera/useCameraUtils";
12
14
  export type ViewerSelection = Record<number, number[]>;
@@ -42,6 +44,8 @@ export type ViewerColorsApi = {
42
44
  clearAllColors: () => void;
43
45
  clearColor: (modelID: number, ids: number[]) => void;
44
46
  clearModelColors: (modelID: number) => void;
47
+ rebuildByColors: (colorsByModel: ViewerColorConfigByModel, defaultColor?: ColorRepresentation) => void;
48
+ rebuildModelByColors: (modelID: number, colorsByIds: ViewerModelColorConfig, defaultColor?: ColorRepresentation) => void;
45
49
  setColor: (modelID: number, ids: number[], color: ColorRepresentation) => void;
46
50
  };
47
51
  export type ViewerUtilsApi = {
@@ -1,6 +1,6 @@
1
1
  import type { ViewerModelPropsStore, ViewerModelStructureStore, ViewerStoreApi } from "../store/ViewerStore";
2
2
  import { type ExportedExcelFile, type ModelPropertiesExcelOptions } from "../utils/ExportUtils";
3
- import type { BmtModelStructureNode, BmtPropertyRecord, BmtPropertySet, BmtPropertyValue } from "../Loaders/BmtLoader";
3
+ import type { BmtElementProps, BmtModelStructureNode, BmtPropertyRecord, BmtPropertySet, BmtPropertyValue } from "../Loaders/BmtLoader";
4
4
  export type ViewerPropertiesExcelOptions = ModelPropertiesExcelOptions;
5
5
  type ViewerModelLevelValue = BmtModelStructureNode[] | BmtPropertyRecord | BmtPropertySet[] | BmtPropertyValue;
6
6
  export type ViewerModelLevel = Record<string, ViewerModelLevelValue | undefined> & {
@@ -15,6 +15,9 @@ export type ViewerPropertiesApi = {
15
15
  getAllModelLevels: (modelID: number, recursive?: boolean) => ViewerModelLevel[];
16
16
  getModelProps: () => ViewerModelPropsStore;
17
17
  getModelStructure: () => ViewerModelStructureStore;
18
+ getParamsByElement: (modelID: number, elementID: number) => BmtElementProps | undefined;
19
+ getParamValueByName: (elementParams: BmtElementProps | null | undefined, paramName: string, setName?: string) => BmtPropertyValue | undefined;
20
+ getParamValueByElement: (modelID: number, elementID: number, paramName: string, setName?: string) => BmtPropertyValue | undefined;
18
21
  };
19
22
  export declare function createViewerPropertiesApi(viewerStore: ViewerStoreApi): ViewerPropertiesApi;
20
23
  export {};