@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/dist/viewer-visualize.js +70 -59
- package/dist/viewer-visualize.js.map +1 -1
- package/dist/viewer-visualize.min.js +1 -1
- package/dist/viewer-visualize.module.js +83 -67
- package/dist/viewer-visualize.module.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/package.json +1 -1
- package/src/Viewer/Loaders/VsfXLoader.ts +13 -5
- package/src/Viewer/Loaders/VsfXPartialLoader.ts +70 -48
- package/src/Viewer/Loaders/VsfXStreamingLoader.ts +5 -5
- package/src/Viewer/Markup/Api/Impl/Konva/KonvaCloud.ts +1 -1
- package/src/Viewer/Viewer.ts +4 -4
- package/src/index.ts +1 -1
package/lib/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -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
|
|
41
|
-
this.
|
|
42
|
-
|
|
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(
|
|
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
|
|
55
|
+
const chunkLoadHandler = (progress: number, chunk: Uint8Array, requestId = 0) => {
|
|
55
56
|
if (!this.viewer.visualizeJs) return;
|
|
56
57
|
|
|
57
|
-
const state = visViewer.parseVsfxInPartialMode(requestId,
|
|
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
|
|
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.
|
|
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
|
-
|
|
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
|
|
91
|
-
const
|
|
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
|
-
|
|
95
|
-
|
|
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
|
|
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
|
-
|
|
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:
|
|
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
|
|
136
|
-
let
|
|
137
|
-
const
|
|
138
|
-
if (
|
|
139
|
-
|
|
140
|
-
|
|
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 (
|
|
145
|
-
|
|
146
|
-
|
|
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 (
|
|
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
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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, {
|
|
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((
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
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
|
-
.
|
|
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,
|
|
42
|
+
const chunkLoadHandler = (progress: number, chunk: Uint8Array) => {
|
|
43
43
|
if (!this.viewer.visualizeJs) return;
|
|
44
44
|
|
|
45
|
-
const status = visViewer.parseVsfx(
|
|
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.
|
|
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 ??
|
|
34
|
+
strokeWidth: params.lineWidth ?? 4,
|
|
35
35
|
draggable: true,
|
|
36
36
|
strokeScaleEnabled: false,
|
|
37
37
|
globalCompositeOperation: "source-over",
|
package/src/Viewer/Viewer.ts
CHANGED
|
@@ -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
|
-
|
|
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";
|