@vcmap/core 5.2.1 → 5.3.1
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/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/src/layer/openlayers/vectorTileOpenlayersImpl.d.ts +1 -0
- package/dist/src/layer/openlayers/vectorTileOpenlayersImpl.js +3 -1
- package/dist/src/layer/openlayers/vectorTileOpenlayersImpl.js.map +1 -1
- package/dist/src/layer/vectorTileLayer.d.ts +6 -0
- package/dist/src/layer/vectorTileLayer.js +8 -1
- package/dist/src/layer/vectorTileLayer.js.map +1 -1
- package/dist/src/map/vcsMap.d.ts +1 -0
- package/dist/src/map/vcsMap.js +3 -0
- package/dist/src/map/vcsMap.js.map +1 -1
- package/dist/src/style/declarativeStyleItem.d.ts +1 -0
- package/dist/src/style/declarativeStyleItem.js +7 -1
- package/dist/src/style/declarativeStyleItem.js.map +1 -1
- package/dist/src/util/displayQuality/displayQuality.d.ts +79 -0
- package/dist/src/util/displayQuality/displayQuality.js +232 -0
- package/dist/src/util/displayQuality/displayQuality.js.map +1 -0
- package/dist/src/vcsApp.d.ts +3 -0
- package/dist/src/vcsApp.js +7 -0
- package/dist/src/vcsApp.js.map +1 -1
- package/dist/tests/unit/helpers/cesiumHelpers.js +2 -1
- package/dist/tests/unit/helpers/cesiumHelpers.js.map +1 -1
- package/index.ts +5 -0
- package/package.json +1 -1
- package/src/layer/openlayers/vectorTileOpenlayersImpl.ts +4 -1
- package/src/layer/vectorTileLayer.ts +15 -1
- package/src/map/vcsMap.ts +6 -0
- package/src/style/declarativeStyleItem.ts +7 -1
- package/src/util/displayQuality/displayQuality.ts +304 -0
- package/src/vcsApp.ts +9 -0
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import { check, oneOf } from '@vcsuite/check';
|
|
2
|
+
import VcsApp from '../../vcsApp.js';
|
|
3
|
+
import FeatureStoreLayer from '../../layer/featureStoreLayer.js';
|
|
4
|
+
import CesiumMap from '../../map/cesiumMap.js';
|
|
5
|
+
import { isMobile } from '../isMobile.js';
|
|
6
|
+
import CesiumTilesetLayer from '../../layer/cesiumTilesetLayer.js';
|
|
7
|
+
import VcsEvent from '../../vcsEvent.js';
|
|
8
|
+
|
|
9
|
+
export enum DisplayQualityLevel {
|
|
10
|
+
LOW = 'low',
|
|
11
|
+
MEDIUM = 'medium',
|
|
12
|
+
HIGH = 'high',
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type DisplayQualityViewModelOptions = {
|
|
16
|
+
sse?: number;
|
|
17
|
+
fxaa?: boolean;
|
|
18
|
+
fogEnabled?: boolean;
|
|
19
|
+
fogDensity?: number;
|
|
20
|
+
fogScreenSpaceErrorFactor?: number;
|
|
21
|
+
resolutionScale?: number;
|
|
22
|
+
layerSSEFactor?: number;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type DisplayQualityLayerModel = {
|
|
26
|
+
layerName: string;
|
|
27
|
+
defaultSse: number;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type DisplayQualityOptions = {
|
|
31
|
+
startingQualityLevel?: DisplayQualityLevel;
|
|
32
|
+
startingMobileQualityLevel?: DisplayQualityLevel;
|
|
33
|
+
low?: DisplayQualityViewModelOptions;
|
|
34
|
+
medium?: DisplayQualityViewModelOptions;
|
|
35
|
+
high?: DisplayQualityViewModelOptions;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* DisplayQuality Class
|
|
40
|
+
*/
|
|
41
|
+
class DisplayQuality {
|
|
42
|
+
static get className(): string {
|
|
43
|
+
return 'DisplayQuality';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
static getDefaultOptions(): DisplayQualityOptions {
|
|
47
|
+
return {
|
|
48
|
+
startingQualityLevel: DisplayQualityLevel.MEDIUM,
|
|
49
|
+
startingMobileQualityLevel: DisplayQualityLevel.LOW,
|
|
50
|
+
low: {
|
|
51
|
+
sse: 4,
|
|
52
|
+
fxaa: false,
|
|
53
|
+
fogEnabled: true,
|
|
54
|
+
fogDensity: 0.0009,
|
|
55
|
+
fogScreenSpaceErrorFactor: 6,
|
|
56
|
+
resolutionScale: 0.9,
|
|
57
|
+
layerSSEFactor: 2,
|
|
58
|
+
},
|
|
59
|
+
medium: {
|
|
60
|
+
sse: 2.333,
|
|
61
|
+
fxaa: false,
|
|
62
|
+
fogEnabled: true,
|
|
63
|
+
fogDensity: 0.0005,
|
|
64
|
+
fogScreenSpaceErrorFactor: 4,
|
|
65
|
+
resolutionScale: 1,
|
|
66
|
+
layerSSEFactor: 1.1,
|
|
67
|
+
},
|
|
68
|
+
high: {
|
|
69
|
+
sse: 4 / 3,
|
|
70
|
+
fxaa: true,
|
|
71
|
+
fogEnabled: false,
|
|
72
|
+
fogDensity: 0,
|
|
73
|
+
fogScreenSpaceErrorFactor: 0,
|
|
74
|
+
resolutionScale: 1,
|
|
75
|
+
layerSSEFactor: 0.5,
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private _app: VcsApp;
|
|
81
|
+
|
|
82
|
+
private _layerSettingsCache: DisplayQualityLayerModel[];
|
|
83
|
+
|
|
84
|
+
private _viewModelSettings: DisplayQualityOptions;
|
|
85
|
+
|
|
86
|
+
private _currentQualityLevel: DisplayQualityLevel | undefined;
|
|
87
|
+
|
|
88
|
+
private _listeners: (() => void)[];
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* An event raised when the current quality level has been changed
|
|
92
|
+
*/
|
|
93
|
+
qualityLevelChanged = new VcsEvent<void>();
|
|
94
|
+
|
|
95
|
+
constructor(app: VcsApp) {
|
|
96
|
+
this._app = app;
|
|
97
|
+
this._layerSettingsCache = [];
|
|
98
|
+
this._viewModelSettings = DisplayQuality.getDefaultOptions();
|
|
99
|
+
this._currentQualityLevel = undefined;
|
|
100
|
+
this._listeners = [
|
|
101
|
+
this._app.maps.mapActivated.addEventListener(() => {
|
|
102
|
+
if (
|
|
103
|
+
this._app.maps.activeMap instanceof CesiumMap &&
|
|
104
|
+
!this.currentQualityLevel
|
|
105
|
+
) {
|
|
106
|
+
if (isMobile()) {
|
|
107
|
+
this.setLevel(this._viewModelSettings.startingMobileQualityLevel!);
|
|
108
|
+
} else {
|
|
109
|
+
this.setLevel(this._viewModelSettings.startingQualityLevel!);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}),
|
|
113
|
+
this._app.layers.stateChanged.addEventListener((layer) => {
|
|
114
|
+
if (layer.active && this._app.maps.activeMap instanceof CesiumMap) {
|
|
115
|
+
this._setLayerQuality(layer.name);
|
|
116
|
+
}
|
|
117
|
+
}),
|
|
118
|
+
this._app.layers.removed.addEventListener((layer) => {
|
|
119
|
+
const index = this._layerSettingsCache.findIndex(
|
|
120
|
+
(config) => config.layerName === layer.name,
|
|
121
|
+
);
|
|
122
|
+
if (index > -1) {
|
|
123
|
+
this._layerSettingsCache.splice(index, 1);
|
|
124
|
+
}
|
|
125
|
+
}),
|
|
126
|
+
];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* The starting quality level
|
|
131
|
+
*/
|
|
132
|
+
get startingQualityLevel(): DisplayQualityLevel {
|
|
133
|
+
return this._viewModelSettings.startingQualityLevel!;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* The current quality level
|
|
138
|
+
*/
|
|
139
|
+
get currentQualityLevel(): DisplayQualityLevel | undefined {
|
|
140
|
+
return this._currentQualityLevel;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* The current quality view model
|
|
145
|
+
* @private
|
|
146
|
+
*/
|
|
147
|
+
get _viewModel(): DisplayQualityViewModelOptions | undefined {
|
|
148
|
+
if (this._currentQualityLevel) {
|
|
149
|
+
return this._viewModelSettings[this._currentQualityLevel]!;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Update the display quality options
|
|
157
|
+
* @param options
|
|
158
|
+
* @param silent
|
|
159
|
+
*/
|
|
160
|
+
updateOptions(options: DisplayQualityOptions, silent?: boolean): void {
|
|
161
|
+
check(options, Object);
|
|
162
|
+
const filteredOptions: DisplayQualityOptions = Object.fromEntries(
|
|
163
|
+
Object.entries(options as Record<string, unknown>)
|
|
164
|
+
.filter(([, value]) => value != null)
|
|
165
|
+
.map(([key, value]) => {
|
|
166
|
+
if (
|
|
167
|
+
key === DisplayQualityLevel.LOW ||
|
|
168
|
+
key === DisplayQualityLevel.MEDIUM ||
|
|
169
|
+
key === DisplayQualityLevel.HIGH
|
|
170
|
+
) {
|
|
171
|
+
return [
|
|
172
|
+
key,
|
|
173
|
+
Object.fromEntries(
|
|
174
|
+
Object.entries(value as Record<string, unknown>).filter(
|
|
175
|
+
([, v]) => v != null,
|
|
176
|
+
),
|
|
177
|
+
),
|
|
178
|
+
];
|
|
179
|
+
}
|
|
180
|
+
return [key, value];
|
|
181
|
+
}),
|
|
182
|
+
);
|
|
183
|
+
const defaultOptions = DisplayQuality.getDefaultOptions();
|
|
184
|
+
this._viewModelSettings = {
|
|
185
|
+
...defaultOptions,
|
|
186
|
+
...filteredOptions,
|
|
187
|
+
low: { ...defaultOptions.low, ...filteredOptions.low },
|
|
188
|
+
medium: { ...defaultOptions.medium, ...filteredOptions.medium },
|
|
189
|
+
high: { ...defaultOptions.high, ...filteredOptions.high },
|
|
190
|
+
};
|
|
191
|
+
if (!silent) {
|
|
192
|
+
if (this.currentQualityLevel) {
|
|
193
|
+
this.setLevel(this.currentQualityLevel);
|
|
194
|
+
} else if (isMobile()) {
|
|
195
|
+
this.setLevel(this._viewModelSettings.startingMobileQualityLevel!);
|
|
196
|
+
} else {
|
|
197
|
+
this.setLevel(this._viewModelSettings.startingQualityLevel!);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Set display quality level for 3D map and layers
|
|
204
|
+
* @param level
|
|
205
|
+
*/
|
|
206
|
+
setLevel(level: DisplayQualityLevel): void {
|
|
207
|
+
check(
|
|
208
|
+
level,
|
|
209
|
+
oneOf(
|
|
210
|
+
DisplayQualityLevel.LOW,
|
|
211
|
+
DisplayQualityLevel.MEDIUM,
|
|
212
|
+
DisplayQualityLevel.HIGH,
|
|
213
|
+
),
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
if (!(this._app.maps.activeMap instanceof CesiumMap)) {
|
|
217
|
+
this._currentQualityLevel = undefined;
|
|
218
|
+
this._viewModelSettings.startingQualityLevel = level;
|
|
219
|
+
this._viewModelSettings.startingMobileQualityLevel = level;
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const previousLevel = this._currentQualityLevel;
|
|
224
|
+
this._currentQualityLevel = level;
|
|
225
|
+
|
|
226
|
+
[...this._app.layers]
|
|
227
|
+
.filter(
|
|
228
|
+
(layer) =>
|
|
229
|
+
layer.active &&
|
|
230
|
+
(layer instanceof CesiumTilesetLayer ||
|
|
231
|
+
layer instanceof FeatureStoreLayer),
|
|
232
|
+
)
|
|
233
|
+
.forEach((layer) => {
|
|
234
|
+
this._setLayerQuality(layer.name);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
const viewer = this._app.maps.activeMap.getCesiumWidget();
|
|
238
|
+
if (viewer && this._viewModel) {
|
|
239
|
+
viewer.scene.globe.maximumScreenSpaceError = this._viewModel.sse!;
|
|
240
|
+
if (viewer.scene.postProcessStages) {
|
|
241
|
+
viewer.scene.postProcessStages.fxaa.enabled = this._viewModel.fxaa!;
|
|
242
|
+
}
|
|
243
|
+
viewer.resolutionScale = this._viewModel.resolutionScale!;
|
|
244
|
+
viewer.scene.fog.enabled = this._viewModel.fogEnabled!;
|
|
245
|
+
viewer.scene.fog.density = this._viewModel.fogDensity!;
|
|
246
|
+
viewer.scene.fog.screenSpaceErrorFactor =
|
|
247
|
+
this._viewModel.fogScreenSpaceErrorFactor!;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (this._currentQualityLevel !== previousLevel) {
|
|
251
|
+
this.qualityLevelChanged.raiseEvent();
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Set layer quality
|
|
257
|
+
* @param layerName
|
|
258
|
+
* @private
|
|
259
|
+
*/
|
|
260
|
+
_setLayerQuality(layerName: string | undefined): void {
|
|
261
|
+
check(layerName, String);
|
|
262
|
+
|
|
263
|
+
const layer = this._app.layers.getByKey(layerName);
|
|
264
|
+
if (
|
|
265
|
+
(layer instanceof CesiumTilesetLayer ||
|
|
266
|
+
layer instanceof FeatureStoreLayer) &&
|
|
267
|
+
layer.active
|
|
268
|
+
) {
|
|
269
|
+
let config = this._layerSettingsCache.find(
|
|
270
|
+
(layerConfig) => layerConfig.layerName === layerName,
|
|
271
|
+
);
|
|
272
|
+
let sse;
|
|
273
|
+
if (!config) {
|
|
274
|
+
sse = isMobile()
|
|
275
|
+
? layer.screenSpaceErrorMobile
|
|
276
|
+
: layer.screenSpaceError;
|
|
277
|
+
if (sse) {
|
|
278
|
+
config = {
|
|
279
|
+
layerName: layer.name,
|
|
280
|
+
defaultSse: sse,
|
|
281
|
+
};
|
|
282
|
+
this._layerSettingsCache.push(config);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
if (config && this._viewModel) {
|
|
286
|
+
layer.setMaximumScreenSpaceError(
|
|
287
|
+
config.defaultSse * this._viewModel.layerSSEFactor!,
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Destroys the display quality, clearing its event listeners
|
|
295
|
+
*/
|
|
296
|
+
destroy(): void {
|
|
297
|
+
this._listeners.forEach((cb) => {
|
|
298
|
+
cb();
|
|
299
|
+
});
|
|
300
|
+
this.qualityLevelChanged.destroy();
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export default DisplayQuality;
|
package/src/vcsApp.ts
CHANGED
|
@@ -50,6 +50,7 @@ import FlightInstance, {
|
|
|
50
50
|
FlightInstanceOptions,
|
|
51
51
|
} from './util/flight/flightInstance.js';
|
|
52
52
|
import FlightCollection from './util/flight/flightCollection.js';
|
|
53
|
+
import DisplayQuality from './util/displayQuality/displayQuality.js';
|
|
53
54
|
|
|
54
55
|
function getLogger(): Logger {
|
|
55
56
|
return getLoggerByName('init');
|
|
@@ -120,6 +121,8 @@ class VcsApp {
|
|
|
120
121
|
|
|
121
122
|
private _categories: CategoryCollection;
|
|
122
123
|
|
|
124
|
+
private _displayQuality: DisplayQuality;
|
|
125
|
+
|
|
123
126
|
private _destroyed: VcsEvent<void>;
|
|
124
127
|
|
|
125
128
|
private _moduleMutationChain: {
|
|
@@ -223,6 +226,7 @@ class VcsApp {
|
|
|
223
226
|
categoryClassRegistry,
|
|
224
227
|
);
|
|
225
228
|
this._categories = new CategoryCollection(this);
|
|
229
|
+
this._displayQuality = new DisplayQuality(this);
|
|
226
230
|
this._destroyed = new VcsEvent();
|
|
227
231
|
this._moduleMutationChain = { running: false, items: [] };
|
|
228
232
|
this._categoryItemClassRegistry = new OverrideClassRegistry(
|
|
@@ -303,6 +307,10 @@ class VcsApp {
|
|
|
303
307
|
return this._flights;
|
|
304
308
|
}
|
|
305
309
|
|
|
310
|
+
get displayQuality(): DisplayQuality {
|
|
311
|
+
return this._displayQuality;
|
|
312
|
+
}
|
|
313
|
+
|
|
306
314
|
get destroyed(): VcsEvent<void> {
|
|
307
315
|
return this._destroyed;
|
|
308
316
|
}
|
|
@@ -601,6 +609,7 @@ class VcsApp {
|
|
|
601
609
|
this._categoryItemClassRegistry.destroy();
|
|
602
610
|
this._tileProviderClassRegistry.destroy();
|
|
603
611
|
this._featureProviderClassRegistry.destroy();
|
|
612
|
+
this._displayQuality.destroy();
|
|
604
613
|
this.destroyed.raiseEvent();
|
|
605
614
|
this.destroyed.destroy();
|
|
606
615
|
this.localeChanged.destroy();
|