@inweb/viewer-visualize 25.3.15 → 25.3.18

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/lib/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import "./Viewer/Commands";
2
- export { commands } from "@inweb/viewer-core";
2
+ export { commands, Options } from "@inweb/viewer-core";
3
3
  export { Viewer } from "./Viewer/Viewer";
4
4
  export { OdBaseDragger } from "./Viewer/Draggers/Common/OdBaseDragger";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inweb/viewer-visualize",
3
- "version": "25.3.15",
3
+ "version": "25.3.18",
4
4
  "description": "3D CAD and BIM data Viewer powered by Visualize",
5
5
  "homepage": "https://cloud.opendesign.com/docs/index.html",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -33,21 +33,28 @@ export class VsfXLoader extends BaseLoader {
33
33
 
34
34
  this.viewer._abortController = abortController;
35
35
 
36
+ const chunkLoadHandler = (progress: number) => {
37
+ this.viewer.emitEvent({ type: "geometryprogress", data: progress, model: this.model });
38
+ };
39
+
36
40
  console.time("File load time");
37
41
  try {
38
42
  this.viewer.emitEvent({ type: "geometrystart", model: this.model });
39
43
 
40
- const progressCb = (progress) =>
41
- this.viewer.emitEvent({ type: "geometryprogress", data: progress, model: this.model });
42
- const arrayBuffer = await this.model.downloadResource(this.model.database, progressCb, abortController.signal);
44
+ const arrayBuffer = await this.model.downloadResource(
45
+ this.model.database,
46
+ chunkLoadHandler,
47
+ abortController.signal
48
+ );
43
49
 
44
50
  if (abortController.signal.aborted) {
45
51
  await Promise.reject(new Error(`Open model aborted ${this.model.name}`));
46
52
  }
47
53
 
54
+ const data = new Uint8Array(arrayBuffer);
55
+
48
56
  if (this.viewer.visualizeJs) {
49
- visViewer.parseVsfx(new Uint8Array(arrayBuffer));
50
- this.viewer.update(true);
57
+ visViewer.parseVsfx(data);
51
58
 
52
59
  this.viewer.syncOpenCloudVisualStyle(false);
53
60
  this.viewer.syncOptions();
@@ -56,6 +63,7 @@ export class VsfXLoader extends BaseLoader {
56
63
 
57
64
  console.timeEnd("File load time");
58
65
 
66
+ this.viewer.emitEvent({ type: "databasechunk", data, model: this.model });
59
67
  this.viewer.emitEvent({ type: "geometryend", model: this.model });
60
68
  } catch (error) {
61
69
  this.viewer.emitEvent({ type: "geometryerror", data: error, model: this.model });
@@ -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,113 +67,135 @@ 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) => {
77
+ console.log("--- VsfXPartialLoader.downloadResourceRange", dataId, requestId, ranges);
78
+
76
79
  const abortCtrl = new AbortController();
77
80
  abortControllerForRequestMap.set(requestId, abortCtrl);
78
81
  try {
79
- await this.model.downloadFileRange(requestId, records, dataId, requestLoadHandler, abortCtrl.signal);
82
+ await this.model.downloadResourceRange(dataId, ranges, requestId, chunkLoadHandler, abortCtrl.signal);
80
83
  } catch (error) {
84
+ console.log("--- VsfXPartialLoader.downloadResourceRange error", dataId, requestId, error);
85
+
81
86
  this.viewer.emitEvent({ type: "geometryerror", data: error, model: this.model });
82
87
  } finally {
83
- const requests = isMultipleParts ? [...new Set(records.map((item) => item.reqId))] : [requestId];
84
- requests.forEach((requestId) => visViewer.onRequestResponseComplete(requestId));
88
+ ranges.forEach((range) => visViewer.onRequestResponseComplete(range.requestId));
85
89
  abortControllerForRequestMap.delete(requestId);
86
90
  updaterController.update(UpdateType.kNormal);
87
91
  }
88
92
  };
89
93
 
90
- const recordsToArray = (requestId, records) => {
91
- const res = [];
94
+ const requestRecordsToRanges = (requestId: number, records: any): any => {
95
+ const ranges = [];
92
96
  for (let i = 0; i < records.size(); i++) {
93
97
  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),
98
+ ranges.push({
99
+ requestId,
100
+ begin: Number(record.begin),
101
+ end: Number(record.end),
99
102
  });
100
103
  record.delete();
101
104
  }
102
- return res;
105
+ return ranges;
103
106
  };
104
107
 
105
108
  const objectHandler = {
106
- onServicePartReceived: (bHasIndex) => {
109
+ onServicePartReceived: (bHasIndex: boolean) => {
110
+ console.log("--- VsfXPartialLoader.onServicePartReceived", bHasIndex);
111
+
107
112
  if (bHasIndex) {
108
113
  servicePartAborted = true;
109
114
  abortController.abort();
110
115
  }
111
116
  },
112
117
 
113
- onRequest: (requestId, records) => {
114
- downloadPartOfFile(requestId, records, this.model.database);
118
+ onRequest: (requestId: number, records: any) => {
119
+ const ranges = requestRecordsToRanges(requestId, records);
120
+
121
+ console.log("--- VsfXPartialLoader.onRequest", this.model.database, requestId, ranges);
122
+
123
+ downloadResourceRange(this.model.database, requestId, ranges);
115
124
  },
116
125
 
117
126
  onFullLoaded: () => {
127
+ console.log("--- VsfXPartialLoader.onFullLoaded");
128
+
118
129
  updaterController.update(UpdateType.kNormal);
119
- console.timeEnd("File load time");
120
130
  },
121
131
 
122
- onRequestResponseParsed: (requestId) => {
132
+ onRequestResponseParsed: (requestId: number) => {
133
+ console.log("--- VsfXPartialLoader.onRequestResponseParsed", requestId);
134
+
123
135
  abortControllerForRequestMap.delete(requestId);
124
136
  updaterController.update(UpdateType.kNormal);
125
137
  },
126
138
 
127
- onRequestAborted: (requestId) => {
139
+ onRequestAborted: (requestId: number) => {
140
+ console.log("--- VsfXPartialLoader.onRequestAborted", requestId);
141
+
128
142
  const abortCtrl = abortControllerForRequestMap.get(requestId);
129
143
  if (abortCtrl) abortCtrl.abort();
130
144
  },
131
145
 
132
- onRequestResourceFile: async (requestId, _, records) => {
133
- const dataId = `${this.model.fileId}${this.model.file.type}`;
146
+ onRequestResourceFile: (requestId: number, dataId: string, records: any) => {
147
+ // const dataId = `${this.model.fileId}${this.model.file.type}`;
148
+ const ranges = requestRecordsToRanges(requestId, records);
149
+
150
+ console.log("--- VsfXPartialLoader.onRequestResourceFile", dataId, requestId, ranges);
134
151
 
135
- let pendingRequests = [];
136
- let recNumber = 0;
137
- const pendingRequestsRecord = pendingRequestsMap.get(dataId);
138
- if (pendingRequestsRecord) {
139
- pendingRequests = pendingRequestsRecord.array;
140
- recNumber = pendingRequestsRecord.number;
152
+ let pendingRanges = [];
153
+ let requestNumber = 0;
154
+ const pendingRequest = pendingRequestsMap.get(dataId);
155
+ if (pendingRequest) {
156
+ pendingRanges = pendingRequest.ranges;
157
+ requestNumber = pendingRequest.number;
141
158
  }
142
159
 
143
160
  // 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);
161
+ if (requestNumber <= 5) {
162
+ console.log("--- VsfXPartialLoader.onRequestResourceFile: requestNumber <= 5");
163
+
164
+ pendingRequestsMap.set(dataId, { ranges: [], number: requestNumber + 1 });
165
+ downloadResourceRange(dataId, requestId, ranges);
147
166
  return;
148
167
  }
149
168
 
169
+ pendingRanges = pendingRanges.concat(ranges);
170
+
150
171
  // group requests to each file to launch a combined server request
151
- if (pendingRequests.length >= PENDING_REQUESTS_SIZE) {
172
+ if (pendingRanges.length >= PENDING_REQUESTS_SIZE) {
173
+ console.log("--- VsfXPartialLoader.onRequestResourceFile: pendingRanges.length >", PENDING_REQUESTS_SIZE);
174
+
152
175
  if (pendingRequestsTimerId) {
153
176
  window.clearTimeout(pendingRequestsTimerId);
154
177
  pendingRequestsTimerId = 0;
155
178
  }
156
179
 
157
- downloadPartOfFile(requestId, pendingRequests, dataId, true);
158
- pendingRequests = [...recordsToArray(requestId, records)];
159
- } else {
160
- pendingRequests = [...pendingRequests, ...recordsToArray(requestId, records)];
180
+ pendingRequestsMap.set(dataId, { ranges: [], number: requestNumber + 1 });
181
+ downloadResourceRange(dataId, requestId, pendingRanges);
182
+ return;
161
183
  }
162
184
 
163
- pendingRequestsMap.set(dataId, { array: pendingRequests, number: recNumber + 1 });
185
+ pendingRequestsMap.set(dataId, { ranges: pendingRanges, number: requestNumber + 1 });
164
186
 
165
187
  // set timeout to wait for the new requests, after that process the remaining requests
166
188
  if (pendingRequestsTimerId === 0) {
167
189
  pendingRequestsTimerId = window.setTimeout(() => {
190
+ console.log("--- VsfXPartialLoader.onRequestResourceFile: timer", PENDING_REQUESTS_SIZE);
191
+
168
192
  pendingRequestsAbortController.signal.removeEventListener("abort", pendingRequestsAbortHandler);
169
193
  pendingRequestsTimerId = 0;
170
194
 
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 });
195
+ pendingRequestsMap.forEach((request, dataId) => {
196
+ if (request.ranges.length > 0) {
197
+ pendingRequestsMap.set(dataId, { ranges: [], number: request.number + 1 });
198
+ downloadResourceRange(dataId, requestId, request.ranges);
176
199
  }
177
200
  });
178
201
  }, PENDING_REQUESTS_TIMEOUT);
@@ -184,12 +207,11 @@ export class VsfXPartialLoader extends BaseLoader {
184
207
 
185
208
  visViewer.attachPartialResolver(objectHandler);
186
209
 
187
- console.time("File load time");
188
210
  try {
189
211
  this.viewer.emitEvent({ type: "geometrystart", model: this.model });
190
212
 
191
213
  await this.model
192
- .downloadFileRange(0, null, this.model.database, requestLoadHandler, abortController.signal)
214
+ .downloadResource(this.model.database, chunkLoadHandler, abortController.signal)
193
215
  .catch((error) => {
194
216
  if (!servicePartAborted) throw error;
195
217
  });
@@ -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);
@@ -31,7 +31,7 @@ export class KonvaCloud implements IMarkupCloud, IMarkupColorable {
31
31
  width: params.width ?? 200,
32
32
  height: params.height ?? 200,
33
33
  stroke: params.color ?? "#ff0000",
34
- strokeWidth: params.lineWidth ?? 5,
34
+ strokeWidth: params.lineWidth ?? 4,
35
35
  draggable: true,
36
36
  strokeScaleEnabled: false,
37
37
  globalCompositeOperation: "source-over",
@@ -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);
@@ -859,7 +859,7 @@ 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
  }
package/src/index.ts CHANGED
@@ -23,6 +23,6 @@
23
23
 
24
24
  import "./Viewer/Commands";
25
25
 
26
- export { commands } from "@inweb/viewer-core";
26
+ export { commands, Options } from "@inweb/viewer-core";
27
27
  export { Viewer } from "./Viewer/Viewer";
28
28
  export { OdBaseDragger } from "./Viewer/Draggers/Common/OdBaseDragger";