@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.
- package/dist/viewer-visualize.js +143 -131
- package/dist/viewer-visualize.js.map +1 -1
- package/dist/viewer-visualize.min.js +1 -1
- package/dist/viewer-visualize.module.js +156 -139
- package/dist/viewer-visualize.module.js.map +1 -1
- package/lib/ConvetMath.d.ts +28 -0
- package/lib/Viewer/Loaders/BaseLoader.d.ts +3 -3
- package/lib/Viewer/Loaders/LoaderFactory.d.ts +2 -2
- package/lib/Viewer/Viewer.d.ts +3 -3
- package/lib/index.d.ts +1 -1
- package/package.json +4 -4
- package/src/ConvetMath.ts +372 -0
- package/src/Viewer/Loaders/BaseLoader.ts +3 -3
- package/src/Viewer/Loaders/LoaderFactory.ts +3 -2
- package/src/Viewer/Loaders/TCSLoader.ts +1 -1
- package/src/Viewer/Loaders/VsfXLoader.ts +13 -5
- package/src/Viewer/Loaders/VsfXPartialLoader.ts +47 -48
- package/src/Viewer/Loaders/VsfXStreamingLoader.ts +5 -5
- package/src/Viewer/Viewer.ts +8 -8
- package/src/index.ts +1 -1
|
@@ -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,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
|
|
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.
|
|
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
|
-
|
|
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
|
|
91
|
-
const
|
|
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
|
-
|
|
95
|
-
|
|
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
|
|
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
|
-
|
|
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:
|
|
131
|
+
onRequestResourceFile: (requestId: number, _: string, records: any) => {
|
|
133
132
|
const dataId = `${this.model.fileId}${this.model.file.type}`;
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
let
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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 (
|
|
145
|
-
pendingRequestsMap.set(dataId, {
|
|
146
|
-
|
|
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 (
|
|
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
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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, {
|
|
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((
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
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
|
-
.
|
|
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,
|
|
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);
|
package/src/Viewer/Viewer.ts
CHANGED
|
@@ -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
|
-
|
|
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:
|
|
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:
|
|
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
|
|
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