@inweb/viewer-visualize 25.3.17 → 25.3.19

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.
@@ -24,6 +24,9 @@
24
24
  import { BaseLoader } from "./BaseLoader";
25
25
  import { UpdaterController, UpdateType } from "./UpdaterController";
26
26
 
27
+ const PENDING_REQUESTS_SIZE = 50;
28
+ const PENDING_REQUESTS_TIMEOUT = 250;
29
+
27
30
  export class VsfXPartialLoader extends BaseLoader {
28
31
  override async load(): Promise<void> {
29
32
  if (!this.viewer.visualizeJs) return;
@@ -35,8 +38,6 @@ export class VsfXPartialLoader extends BaseLoader {
35
38
  let servicePartAborted = false;
36
39
 
37
40
  const pendingRequestsMap = new Map();
38
- const PENDING_REQUESTS_SIZE = 50;
39
- const PENDING_REQUESTS_TIMEOUT = 250;
40
41
  let pendingRequestsTimerId = 0;
41
42
  const pendingRequestsAbortHandler = () => clearTimeout(pendingRequestsTimerId);
42
43
 
@@ -51,10 +52,10 @@ export class VsfXPartialLoader extends BaseLoader {
51
52
 
52
53
  visViewer.memoryLimit = this.options.memoryLimit;
53
54
 
54
- const requestLoadHandler = (progress, data, requestId) => {
55
+ const chunkLoadHandler = (progress: number, chunk: Uint8Array, requestId = 0) => {
55
56
  if (!this.viewer.visualizeJs) return;
56
57
 
57
- const state = visViewer.parseVsfxInPartialMode(requestId, data);
58
+ const state = visViewer.parseVsfxInPartialMode(requestId, chunk);
58
59
  updaterController.update(UpdateType.kDelay);
59
60
 
60
61
  this.viewer.emitEvent({ type: "geometryprogress", data: progress, model: this.model });
@@ -66,101 +67,101 @@ export class VsfXPartialLoader extends BaseLoader {
66
67
  this.viewer.syncOptions();
67
68
  this.viewer.resize();
68
69
 
69
- this.viewer.emitEvent({ type: "databasechunk", data, model: this.model });
70
+ this.viewer.emitEvent({ type: "databasechunk", data: chunk, model: this.model });
70
71
  } else {
71
- this.viewer.emitEvent({ type: "geometrychunk", data, model: this.model });
72
+ this.viewer.emitEvent({ type: "geometrychunk", data: chunk, model: this.model });
72
73
  }
73
74
  };
74
75
 
75
- const downloadPartOfFile = async (requestId, records, dataId, isMultipleParts = false) => {
76
+ const downloadResourceRange = async (dataId: string, requestId: number, ranges: any) => {
76
77
  const abortCtrl = new AbortController();
77
78
  abortControllerForRequestMap.set(requestId, abortCtrl);
78
79
  try {
79
- await this.model.downloadFileRange(requestId, records, dataId, requestLoadHandler, abortCtrl.signal);
80
+ await this.model.downloadResourceRange(dataId, ranges, requestId, chunkLoadHandler, abortCtrl.signal);
80
81
  } catch (error) {
81
82
  this.viewer.emitEvent({ type: "geometryerror", data: error, model: this.model });
82
83
  } finally {
83
- const requests = isMultipleParts ? [...new Set(records.map((item) => item.reqId))] : [requestId];
84
- requests.forEach((requestId) => visViewer.onRequestResponseComplete(requestId));
84
+ ranges.forEach((range) => visViewer.onRequestResponseComplete(range.requestId));
85
85
  abortControllerForRequestMap.delete(requestId);
86
86
  updaterController.update(UpdateType.kNormal);
87
87
  }
88
88
  };
89
89
 
90
- const recordsToArray = (requestId, records) => {
91
- const res = [];
90
+ const requestRecordsToRanges = (requestId: number, records: any): any => {
91
+ const ranges = [];
92
92
  for (let i = 0; i < records.size(); i++) {
93
93
  const record = records.get(i);
94
- res.push({
95
- reqId: requestId,
96
- begin: record.begin,
97
- end: record.end,
98
- size: parseInt(record.end, 10) - parseInt(record.begin, 10),
94
+ ranges.push({
95
+ requestId,
96
+ begin: Number(record.begin),
97
+ end: Number(record.end),
99
98
  });
100
99
  record.delete();
101
100
  }
102
- return res;
101
+ return ranges;
103
102
  };
104
103
 
105
104
  const objectHandler = {
106
- onServicePartReceived: (bHasIndex) => {
105
+ onServicePartReceived: (bHasIndex: boolean) => {
107
106
  if (bHasIndex) {
108
107
  servicePartAborted = true;
109
108
  abortController.abort();
110
109
  }
111
110
  },
112
111
 
113
- onRequest: (requestId, records) => {
114
- downloadPartOfFile(requestId, records, this.model.database);
112
+ onRequest: (requestId: number, records: any) => {
113
+ const ranges = requestRecordsToRanges(requestId, records);
114
+ downloadResourceRange(this.model.database, requestId, ranges);
115
115
  },
116
116
 
117
117
  onFullLoaded: () => {
118
118
  updaterController.update(UpdateType.kNormal);
119
- console.timeEnd("File load time");
120
119
  },
121
120
 
122
- onRequestResponseParsed: (requestId) => {
121
+ onRequestResponseParsed: (requestId: number) => {
123
122
  abortControllerForRequestMap.delete(requestId);
124
123
  updaterController.update(UpdateType.kNormal);
125
124
  },
126
125
 
127
- onRequestAborted: (requestId) => {
126
+ onRequestAborted: (requestId: number) => {
128
127
  const abortCtrl = abortControllerForRequestMap.get(requestId);
129
128
  if (abortCtrl) abortCtrl.abort();
130
129
  },
131
130
 
132
- onRequestResourceFile: async (requestId, _, records) => {
131
+ onRequestResourceFile: (requestId: number, _: string, records: any) => {
133
132
  const dataId = `${this.model.fileId}${this.model.file.type}`;
134
-
135
- let pendingRequests = [];
136
- let recNumber = 0;
137
- const pendingRequestsRecord = pendingRequestsMap.get(dataId);
138
- if (pendingRequestsRecord) {
139
- pendingRequests = pendingRequestsRecord.array;
140
- recNumber = pendingRequestsRecord.number;
133
+ const ranges = requestRecordsToRanges(requestId, records);
134
+
135
+ let pendingRanges = [];
136
+ let requestNumber = 0;
137
+ const pendingRequest = pendingRequestsMap.get(dataId);
138
+ if (pendingRequest) {
139
+ pendingRanges = pendingRequest.ranges;
140
+ requestNumber = pendingRequest.number;
141
141
  }
142
142
 
143
143
  // first several records of each file are processed without grouping (they usually require to be processed sequentially)
144
- if (recNumber < 6) {
145
- pendingRequestsMap.set(dataId, { array: pendingRequests, number: recNumber + 1 });
146
- await downloadPartOfFile(requestId, records, dataId);
144
+ if (requestNumber <= 5) {
145
+ pendingRequestsMap.set(dataId, { ranges: [], number: requestNumber + 1 });
146
+ downloadResourceRange(dataId, requestId, ranges);
147
147
  return;
148
148
  }
149
149
 
150
+ pendingRanges = pendingRanges.concat(ranges);
151
+
150
152
  // group requests to each file to launch a combined server request
151
- if (pendingRequests.length >= PENDING_REQUESTS_SIZE) {
153
+ if (pendingRanges.length >= PENDING_REQUESTS_SIZE) {
152
154
  if (pendingRequestsTimerId) {
153
155
  window.clearTimeout(pendingRequestsTimerId);
154
156
  pendingRequestsTimerId = 0;
155
157
  }
156
158
 
157
- downloadPartOfFile(requestId, pendingRequests, dataId, true);
158
- pendingRequests = [...recordsToArray(requestId, records)];
159
- } else {
160
- pendingRequests = [...pendingRequests, ...recordsToArray(requestId, records)];
159
+ pendingRequestsMap.set(dataId, { ranges: [], number: requestNumber + 1 });
160
+ downloadResourceRange(dataId, requestId, pendingRanges);
161
+ return;
161
162
  }
162
163
 
163
- pendingRequestsMap.set(dataId, { array: pendingRequests, number: recNumber + 1 });
164
+ pendingRequestsMap.set(dataId, { ranges: pendingRanges, number: requestNumber + 1 });
164
165
 
165
166
  // set timeout to wait for the new requests, after that process the remaining requests
166
167
  if (pendingRequestsTimerId === 0) {
@@ -168,11 +169,10 @@ export class VsfXPartialLoader extends BaseLoader {
168
169
  pendingRequestsAbortController.signal.removeEventListener("abort", pendingRequestsAbortHandler);
169
170
  pendingRequestsTimerId = 0;
170
171
 
171
- pendingRequestsMap.forEach((requestsRecord, keyFileName) => {
172
- const array = requestsRecord.array;
173
- if (array.length > 0) {
174
- downloadPartOfFile(requestId, array, keyFileName, true);
175
- pendingRequestsMap.set(keyFileName, { array: [], number: requestsRecord.number + 1 });
172
+ pendingRequestsMap.forEach((request, dataId) => {
173
+ if (request.ranges.length > 0) {
174
+ pendingRequestsMap.set(dataId, { ranges: [], number: request.number + 1 });
175
+ downloadResourceRange(dataId, requestId, request.ranges);
176
176
  }
177
177
  });
178
178
  }, PENDING_REQUESTS_TIMEOUT);
@@ -184,12 +184,11 @@ export class VsfXPartialLoader extends BaseLoader {
184
184
 
185
185
  visViewer.attachPartialResolver(objectHandler);
186
186
 
187
- console.time("File load time");
188
187
  try {
189
188
  this.viewer.emitEvent({ type: "geometrystart", model: this.model });
190
189
 
191
190
  await this.model
192
- .downloadFileRange(0, null, this.model.database, requestLoadHandler, abortController.signal)
191
+ .downloadResource(this.model.database, chunkLoadHandler, abortController.signal)
193
192
  .catch((error) => {
194
193
  if (!servicePartAborted) throw error;
195
194
  });
@@ -39,10 +39,10 @@ export class VsfXStreamingLoader extends BaseLoader {
39
39
 
40
40
  let isFireDatabaseChunk = false;
41
41
 
42
- const chunkLoadHandler = (progress, data) => {
42
+ const chunkLoadHandler = (progress: number, chunk: Uint8Array) => {
43
43
  if (!this.viewer.visualizeJs) return;
44
44
 
45
- const status = visViewer.parseVsfx(data);
45
+ const status = visViewer.parseVsfx(chunk);
46
46
  updaterController.update(UpdateType.kDelay);
47
47
 
48
48
  this.viewer.emitEvent({ type: "geometryprogress", data: progress, model: this.model });
@@ -63,9 +63,9 @@ export class VsfXStreamingLoader extends BaseLoader {
63
63
  this.viewer.syncOptions();
64
64
  this.viewer.resize();
65
65
 
66
- this.viewer.emitEvent({ type: "databasechunk", data, model: this.model });
66
+ this.viewer.emitEvent({ type: "databasechunk", data: chunk, model: this.model });
67
67
  } else {
68
- this.viewer.emitEvent({ type: "geometrychunk", data, model: this.model });
68
+ this.viewer.emitEvent({ type: "geometrychunk", data: chunk, model: this.model });
69
69
  }
70
70
  };
71
71
 
@@ -73,7 +73,7 @@ export class VsfXStreamingLoader extends BaseLoader {
73
73
  try {
74
74
  this.viewer.emitEvent({ type: "geometrystart", model: this.model });
75
75
 
76
- await this.model.partialDownloadResource(this.model.database, chunkLoadHandler, abortController.signal);
76
+ await this.model.downloadResource(this.model.database, chunkLoadHandler, abortController.signal);
77
77
  console.timeEnd("File load time");
78
78
 
79
79
  updaterController.update(UpdateType.kNormal);
@@ -27,11 +27,11 @@ import {
27
27
  CANVAS_EVENTS,
28
28
  commands,
29
29
  IClippingPlane,
30
+ IOptions,
30
31
  IOrthogonalCamera,
31
32
  IViewpoint,
32
33
  IViewer,
33
34
  Options,
34
- OptionsData,
35
35
  OptionsEventMap,
36
36
  ViewerEventMap,
37
37
  } from "@inweb/viewer-core";
@@ -423,9 +423,9 @@ export class Viewer extends EventEmitter2<ViewerEventMap & OptionsEventMap> impl
423
423
  try {
424
424
  visualStyleId = visViewer.findVisualStyle("OpenCloud");
425
425
  } catch (e) {
426
- if (!isInitializing) {
427
- console.log("OpenCloud visual style not found, creating it on client side");
428
- }
426
+ // if (!isInitializing) {
427
+ // console.log("OpenCloud visual style not found, creating it on client side");
428
+ // }
429
429
  visualStyleId = visViewer.createVisualStyle("OpenCloud");
430
430
 
431
431
  const colorDef = new visLib.OdTvColorDef(66, 66, 66);
@@ -455,7 +455,7 @@ export class Viewer extends EventEmitter2<ViewerEventMap & OptionsEventMap> impl
455
455
  return this;
456
456
  }
457
457
 
458
- syncOptions(options: OptionsData = this.options.data): this {
458
+ syncOptions(options: IOptions = this.options): this {
459
459
  if (!this.visualizeJs) return this;
460
460
 
461
461
  const visLib = this.visLib();
@@ -526,7 +526,7 @@ export class Viewer extends EventEmitter2<ViewerEventMap & OptionsEventMap> impl
526
526
  return this;
527
527
  }
528
528
 
529
- syncHighlightingOptions(options: OptionsData = this.options.data): this {
529
+ syncHighlightingOptions(options: IOptions = this.options): this {
530
530
  if (!this.visualizeJs) return this;
531
531
 
532
532
  const params = options.enableCustomHighlight ? options : Options.defaults();
@@ -859,13 +859,13 @@ export class Viewer extends EventEmitter2<ViewerEventMap & OptionsEventMap> impl
859
859
 
860
860
  const overrideOptions = new Options();
861
861
  overrideOptions.data = this.options.data;
862
- if (file.type === ".rcs") {
862
+ if (file.type === ".rcs" && !overrideOptions.enablePartialMode) {
863
863
  console.log("Partial load mode is forced for RCS file");
864
864
  overrideOptions.enablePartialMode = true;
865
865
  }
866
866
 
867
867
  const loaderFactory = new LoaderFactory();
868
- const loader = loaderFactory.create(this, model, overrideOptions.data);
868
+ const loader = loaderFactory.create(this, model, overrideOptions);
869
869
 
870
870
  await this.loadReferences(model);
871
871
  await loader.load();
package/src/index.ts CHANGED
@@ -23,6 +23,6 @@
23
23
 
24
24
  import "./Viewer/Commands";
25
25
 
26
- export { commands, Options } from "@inweb/viewer-core";
26
+ export * from "@inweb/viewer-core";
27
27
  export { Viewer } from "./Viewer/Viewer";
28
28
  export { OdBaseDragger } from "./Viewer/Draggers/Common/OdBaseDragger";