isard 1.10.0 → 1.11.0
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/CHANGELOG.md +36 -0
- package/README.md +1 -1
- package/dist/basemap/vectortiles.d.ts +13 -8
- package/dist/basemap/vectortiles.js.map +1 -1
- package/dist/bind/layers.js +7 -2
- package/dist/bind/layers.js.map +1 -1
- package/dist/decoder.worker.js +3 -3
- package/dist/decoder.worker.js.map +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/isard_bg.wasm +0 -0
- package/dist/isard_core_bg.wasm +0 -0
- package/dist/isard_tess_bg.wasm +0 -0
- package/dist/layers/features.d.ts +7 -0
- package/dist/layers/features.js +21 -5
- package/dist/layers/features.js.map +1 -1
- package/dist/layers/layers.js +2 -0
- package/dist/layers/layers.js.map +1 -1
- package/dist/layers/tiles3d.d.ts +1 -0
- package/dist/layers/tiles3d.js +42 -2
- package/dist/layers/tiles3d.js.map +1 -1
- package/dist/map/events.js +1 -0
- package/dist/map/events.js.map +1 -1
- package/dist/map/quality.d.ts +33 -0
- package/dist/map/quality.js +61 -0
- package/dist/map/quality.js.map +1 -0
- package/dist/map.d.ts +12 -1
- package/dist/map.js +64 -6
- package/dist/map.js.map +1 -1
- package/dist/react/IsardMap.d.ts +1 -0
- package/dist/react/IsardMap.js +2 -0
- package/dist/react/IsardMap.js.map +1 -1
- package/dist/react/VectorTiles.d.ts +5 -1
- package/dist/react/VectorTiles.js +8 -0
- package/dist/react/VectorTiles.js.map +1 -1
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.js +1 -1
- package/dist/react/index.js.map +1 -1
- package/dist/types.d.ts +20 -0
- package/dist/types.js.map +1 -1
- package/dist/wasm/isard.d.ts +12 -5
- package/dist/wasm/isard.js +33 -5
- package/dist/wasm/isard_core.d.ts +7 -5
- package/dist/wasm/isard_core.js +21 -5
- package/package.json +1 -1
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The map's quality: what it draws less of on a device that cannot keep up. Each level a ceiling on the pixels drawn
|
|
3
|
+
* (the device's pixel ratio capped: a high-density screen draws four times the pixels of its CSS size), the sun's
|
|
4
|
+
* shadows (the solid scene drawn twice more for them: the sun's map, the camera's depth) and how far the 3D Tiles are
|
|
5
|
+
* refined (their screen-space error multiplied: fewer, coarser tiles far away). 'auto' starts high and steps down
|
|
6
|
+
* when the frames stay slow while the map moves.
|
|
7
|
+
*/
|
|
8
|
+
export const QUALITY = {
|
|
9
|
+
high: { pixelRatio: Number.POSITIVE_INFINITY, shadows: true, errorScale: 1 },
|
|
10
|
+
medium: { pixelRatio: 1.5, shadows: true, errorScale: 1.5 },
|
|
11
|
+
low: { pixelRatio: 1, shadows: false, errorScale: 2.5 },
|
|
12
|
+
};
|
|
13
|
+
/** The level under each, for 'auto' */
|
|
14
|
+
const LOWER = { high: 'medium', medium: 'low', low: undefined };
|
|
15
|
+
/** A move measured before it is judged: `WINDOW` frames, or `WINDOW_MS` of them on a slow device (at least
|
|
16
|
+
* `MIN_FRAMES`); a gap past `GAP_MS` between two frames is no move (the map was still) */
|
|
17
|
+
const WINDOW = 60;
|
|
18
|
+
const WINDOW_MS = 2000;
|
|
19
|
+
const MIN_FRAMES = 10;
|
|
20
|
+
const GAP_MS = 500;
|
|
21
|
+
/** The median interval between the frames of a move past which the map steps down (some 40 frames a second) */
|
|
22
|
+
const SLOW_MS = 25;
|
|
23
|
+
/** After a step down, the time the new level is given before it is judged */
|
|
24
|
+
const SETTLE_MS = 3000;
|
|
25
|
+
/**
|
|
26
|
+
* 'auto': the intervals between the frames drawn while the map moves; once a window of them (`WINDOW`) has a median
|
|
27
|
+
* past `SLOW_MS`, `step` is called with the level under the current one. It never steps up: at the display's rate a fast
|
|
28
|
+
* frame tells nothing of what a finer level would cost
|
|
29
|
+
*/
|
|
30
|
+
export class QualityWatch {
|
|
31
|
+
level;
|
|
32
|
+
step;
|
|
33
|
+
intervals = [];
|
|
34
|
+
last = 0;
|
|
35
|
+
settled = 0;
|
|
36
|
+
constructor(level, step) {
|
|
37
|
+
this.level = level;
|
|
38
|
+
this.step = step;
|
|
39
|
+
}
|
|
40
|
+
/** A frame drawn at `now` (ms), the map moving or not */
|
|
41
|
+
frame(now, moving) {
|
|
42
|
+
const gap = now - this.last;
|
|
43
|
+
this.last = now;
|
|
44
|
+
if (!moving || gap > GAP_MS || now < this.settled)
|
|
45
|
+
return;
|
|
46
|
+
this.intervals.push(gap);
|
|
47
|
+
const spent = this.intervals.reduce((sum, i) => sum + i, 0);
|
|
48
|
+
if (this.intervals.length < WINDOW && (spent < WINDOW_MS || this.intervals.length < MIN_FRAMES))
|
|
49
|
+
return;
|
|
50
|
+
const sorted = [...this.intervals].sort((a, b) => a - b);
|
|
51
|
+
const median = sorted[Math.floor(sorted.length / 2)] ?? 0;
|
|
52
|
+
const lower = LOWER[this.level];
|
|
53
|
+
this.intervals.length = 0;
|
|
54
|
+
if (median <= SLOW_MS || !lower)
|
|
55
|
+
return;
|
|
56
|
+
this.level = lower;
|
|
57
|
+
this.settled = now + SETTLE_MS;
|
|
58
|
+
this.step(lower);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=quality.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quality.js","sourceRoot":"","sources":["../../src/map/quality.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAcH,MAAM,CAAC,MAAM,OAAO,GAA+C;IACjE,IAAI,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,iBAAiB,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE;IAC5E,MAAM,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE;IAC3D,GAAG,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE;CACxD,CAAC;AAEF,uCAAuC;AACvC,MAAM,KAAK,GAAmD,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;AAEhH;0FAC0F;AAC1F,MAAM,MAAM,GAAG,EAAE,CAAC;AAClB,MAAM,SAAS,GAAG,IAAI,CAAC;AACvB,MAAM,UAAU,GAAG,EAAE,CAAC;AACtB,MAAM,MAAM,GAAG,GAAG,CAAC;AAEnB,+GAA+G;AAC/G,MAAM,OAAO,GAAG,EAAE,CAAC;AAEnB,6EAA6E;AAC7E,MAAM,SAAS,GAAG,IAAI,CAAC;AAEvB;;;;GAIG;AACH,MAAM,OAAO,YAAY;IAMb;IACS;IANF,SAAS,GAAa,EAAE,CAAC;IAClC,IAAI,GAAG,CAAC,CAAC;IACT,OAAO,GAAG,CAAC,CAAC;IAEpB,YACU,KAAc,EACL,IAA8B;QADvC,UAAK,GAAL,KAAK,CAAS;QACL,SAAI,GAAJ,IAAI,CAA0B;IAC9C,CAAC;IAEJ,yDAAyD;IACzD,KAAK,CAAC,GAAW,EAAE,MAAe;QAChC,MAAM,GAAG,GAAG,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC;QAE5B,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;QAChB,IAAI,CAAC,MAAM,IAAI,GAAG,GAAG,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO;YAAE,OAAO;QAC1D,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEzB,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAE5D,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,GAAG,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,UAAU,CAAC;YAAE,OAAO;QAExG,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC1D,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEhC,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;QAC1B,IAAI,MAAM,IAAI,OAAO,IAAI,CAAC,KAAK;YAAE,OAAO;QACxC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,OAAO,GAAG,GAAG,GAAG,SAAS,CAAC;QAC/B,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnB,CAAC;CACF","sourcesContent":["/**\n * The map's quality: what it draws less of on a device that cannot keep up. Each level a ceiling on the pixels drawn\n * (the device's pixel ratio capped: a high-density screen draws four times the pixels of its CSS size), the sun's\n * shadows (the solid scene drawn twice more for them: the sun's map, the camera's depth) and how far the 3D Tiles are\n * refined (their screen-space error multiplied: fewer, coarser tiles far away). 'auto' starts high and steps down\n * when the frames stay slow while the map moves.\n */\n\nimport type { Quality } from '../types.ts';\n\n/** What a level draws */\nexport interface QualitySettings {\n /** The highest pixel ratio drawn */\n pixelRatio: number;\n /** The sun casts its shadows (its light and the night stay without) */\n shadows: boolean;\n /** Multiplies the 3D Tiles' screen-space error */\n errorScale: number;\n}\n\nexport const QUALITY: Readonly<Record<Quality, QualitySettings>> = {\n high: { pixelRatio: Number.POSITIVE_INFINITY, shadows: true, errorScale: 1 },\n medium: { pixelRatio: 1.5, shadows: true, errorScale: 1.5 },\n low: { pixelRatio: 1, shadows: false, errorScale: 2.5 },\n};\n\n/** The level under each, for 'auto' */\nconst LOWER: Readonly<Record<Quality, Quality | undefined>> = { high: 'medium', medium: 'low', low: undefined };\n\n/** A move measured before it is judged: `WINDOW` frames, or `WINDOW_MS` of them on a slow device (at least\n * `MIN_FRAMES`); a gap past `GAP_MS` between two frames is no move (the map was still) */\nconst WINDOW = 60;\nconst WINDOW_MS = 2000;\nconst MIN_FRAMES = 10;\nconst GAP_MS = 500;\n\n/** The median interval between the frames of a move past which the map steps down (some 40 frames a second) */\nconst SLOW_MS = 25;\n\n/** After a step down, the time the new level is given before it is judged */\nconst SETTLE_MS = 3000;\n\n/**\n * 'auto': the intervals between the frames drawn while the map moves; once a window of them (`WINDOW`) has a median\n * past `SLOW_MS`, `step` is called with the level under the current one. It never steps up: at the display's rate a fast\n * frame tells nothing of what a finer level would cost\n */\nexport class QualityWatch {\n private readonly intervals: number[] = [];\n private last = 0;\n private settled = 0;\n\n constructor(\n private level: Quality,\n private readonly step: (level: Quality) => void,\n ) {}\n\n /** A frame drawn at `now` (ms), the map moving or not */\n frame(now: number, moving: boolean): void {\n const gap = now - this.last;\n\n this.last = now;\n if (!moving || gap > GAP_MS || now < this.settled) return;\n this.intervals.push(gap);\n\n const spent = this.intervals.reduce((sum, i) => sum + i, 0);\n\n if (this.intervals.length < WINDOW && (spent < WINDOW_MS || this.intervals.length < MIN_FRAMES)) return;\n\n const sorted = [...this.intervals].sort((a, b) => a - b);\n const median = sorted[Math.floor(sorted.length / 2)] ?? 0;\n const lower = LOWER[this.level];\n\n this.intervals.length = 0;\n if (median <= SLOW_MS || !lower) return;\n this.level = lower;\n this.settled = now + SETTLE_MS;\n this.step(lower);\n }\n}\n"]}
|
package/dist/map.d.ts
CHANGED
|
@@ -26,7 +26,7 @@ import { Tiles3dLayer } from './layers/tiles3d.ts';
|
|
|
26
26
|
import { type TreeOptions } from './layers/trees.ts';
|
|
27
27
|
import { type HoverPicking } from './map/hover-pick.ts';
|
|
28
28
|
import { type LayerSpec } from './map/layer-spec.ts';
|
|
29
|
-
import type { AnimationOptions, AtmosphereOptions, Basemap, FeatureHit, FirstPersonView, FlyToOptions, GeoMapOptions, LoadingMode, LonLat, MapEvents, NetworkOptions, PickOptions, Point, Projection, RasterOptions, SunOptions, SwipeOptions, TerrainModel, TerrainOptions, Tiles3dOptions, ViewshedOptions } from './types.ts';
|
|
29
|
+
import type { AnimationOptions, AtmosphereOptions, Basemap, FeatureHit, FirstPersonView, FlyToOptions, GeoMapOptions, LoadingMode, LonLat, MapEvents, NetworkOptions, PickOptions, Point, Projection, Quality, RasterOptions, SunOptions, SwipeOptions, TerrainModel, TerrainOptions, Tiles3dOptions, ViewshedOptions } from './types.ts';
|
|
30
30
|
import { type Control, type ControlPosition } from './ui/controls.ts';
|
|
31
31
|
import type { Camera, PickHit, RasterLayerStats } from './wasm/isard.js';
|
|
32
32
|
export type { LayerSpec } from './map/layer-spec.ts';
|
|
@@ -119,8 +119,19 @@ export declare class GeoMap {
|
|
|
119
119
|
setSwipe(options: SwipeOptions | undefined): void;
|
|
120
120
|
private applySwipe;
|
|
121
121
|
private addLayer;
|
|
122
|
+
/** Whether the canvas's WebGL context is lost, its event come or not */
|
|
123
|
+
private contextLost;
|
|
122
124
|
/** Listens to an event; returns the function that stops listening */
|
|
123
125
|
on<K extends keyof MapEvents>(type: K, listener: (event: MapEvents[K]) => void): () => void;
|
|
126
|
+
/** 'auto': the frames watched, the map stepped down while they stay slow */
|
|
127
|
+
private qualityWatch;
|
|
128
|
+
private movingNow;
|
|
129
|
+
/** The map's quality: `'high'`, `'medium'` or `'low'` (as `GeoMapOptions.quality` says; `'auto'` the level it
|
|
130
|
+
* stepped down to) */
|
|
131
|
+
getQuality(): Quality;
|
|
132
|
+
/** Sets the map's quality (`GeoMapOptions.quality`); `'auto'` starts again from `'high'` */
|
|
133
|
+
setQuality(quality: Quality | 'auto'): void;
|
|
134
|
+
private applyQuality;
|
|
124
135
|
getCamera(): Camera;
|
|
125
136
|
setCamera(camera: Partial<Camera>): void;
|
|
126
137
|
/** Animated move to a camera: over `duration` milliseconds (or the options), ease-out by default */
|
package/dist/map.js
CHANGED
|
@@ -39,6 +39,7 @@ import { addSpec } from "./map/layer-spec.js";
|
|
|
39
39
|
import { LayerStack } from "./map/layer-stack.js";
|
|
40
40
|
import { OverlayHost } from "./map/overlay-host.js";
|
|
41
41
|
import { panoramaHost } from "./map/panorama-host.js";
|
|
42
|
+
import { QUALITY, QualityWatch } from "./map/quality.js";
|
|
42
43
|
import { rasterSource } from "./map/raster-source.js";
|
|
43
44
|
import { SymbolAtlases } from "./map/symbol-atlases.js";
|
|
44
45
|
import { applyViewshed } from "./map/viewshed.js";
|
|
@@ -158,6 +159,7 @@ export class GeoMap {
|
|
|
158
159
|
upgrading: () => this.engines.upgrading !== undefined,
|
|
159
160
|
working: () => this.#working > 0,
|
|
160
161
|
drawn: (hovered) => {
|
|
162
|
+
this.qualityWatch?.frame(performance.now(), this.movingNow);
|
|
161
163
|
// The picking pass sees the frame just drawn; its answer comes on a later frame
|
|
162
164
|
if (hovered && this.listeners.has('hoverfeature'))
|
|
163
165
|
this.hoverPick.request(hovered, this.hoverPicking);
|
|
@@ -181,6 +183,17 @@ export class GeoMap {
|
|
|
181
183
|
this.setSun(options.sun);
|
|
182
184
|
this.resizeObserver = new ResizeObserver(() => this.resize());
|
|
183
185
|
this.resizeObserver.observe(container);
|
|
186
|
+
this.#quality = options.quality === 'auto' || options.quality === undefined ? 'high' : options.quality;
|
|
187
|
+
if (options.quality === 'auto') {
|
|
188
|
+
this.qualityWatch = new QualityWatch('high', (level) => this.applyQuality(level));
|
|
189
|
+
// The frames measured are those of a move
|
|
190
|
+
this.on('movestart', () => {
|
|
191
|
+
this.movingNow = true;
|
|
192
|
+
});
|
|
193
|
+
this.on('moveend', () => {
|
|
194
|
+
this.movingNow = false;
|
|
195
|
+
});
|
|
196
|
+
}
|
|
184
197
|
this.unwatchRatio = watchPixelRatio(() => this.resize());
|
|
185
198
|
this.resize();
|
|
186
199
|
const interactive = options.interactive ?? true;
|
|
@@ -345,13 +358,26 @@ export class GeoMap {
|
|
|
345
358
|
// others on it
|
|
346
359
|
if (layer.needsFullEngine && !this.engines.tiles3d)
|
|
347
360
|
this.upgrade();
|
|
348
|
-
else
|
|
349
|
-
|
|
361
|
+
else {
|
|
362
|
+
try {
|
|
363
|
+
layer.attach(this.engine);
|
|
364
|
+
}
|
|
365
|
+
catch (error) {
|
|
366
|
+
// A context lost before the browser says so (its event comes later): nothing could be made on it, the layer is
|
|
367
|
+
// made with the others on the next engine (`restore`). Any other failure is the caller's
|
|
368
|
+
if (!this.contextLost())
|
|
369
|
+
throw error;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
350
372
|
// Under the layers kept on top (the basemap's labels)
|
|
351
373
|
this.stack.add(layer);
|
|
352
374
|
this.requestRender();
|
|
353
375
|
return layer;
|
|
354
376
|
}
|
|
377
|
+
/** Whether the canvas's WebGL context is lost, its event come or not */
|
|
378
|
+
contextLost() {
|
|
379
|
+
return this.lost || this.canvas.getContext('webgl2')?.isContextLost() === true;
|
|
380
|
+
}
|
|
355
381
|
/** @internal Keeps a layer above the layers added after it (they go under it), as the labels of a basemap */
|
|
356
382
|
keepOnTop(layer) {
|
|
357
383
|
this.onTop.add(layer);
|
|
@@ -375,6 +401,38 @@ export class GeoMap {
|
|
|
375
401
|
this.listeners.emit(type, event);
|
|
376
402
|
}
|
|
377
403
|
// ── Camera ──
|
|
404
|
+
#quality = 'high';
|
|
405
|
+
/** 'auto': the frames watched, the map stepped down while they stay slow */
|
|
406
|
+
qualityWatch;
|
|
407
|
+
movingNow = false;
|
|
408
|
+
/** The map's quality: `'high'`, `'medium'` or `'low'` (as `GeoMapOptions.quality` says; `'auto'` the level it
|
|
409
|
+
* stepped down to) */
|
|
410
|
+
getQuality() {
|
|
411
|
+
return this.#quality;
|
|
412
|
+
}
|
|
413
|
+
/** @internal What its quality draws */
|
|
414
|
+
get quality() {
|
|
415
|
+
return QUALITY[this.#quality];
|
|
416
|
+
}
|
|
417
|
+
/** Sets the map's quality (`GeoMapOptions.quality`); `'auto'` starts again from `'high'` */
|
|
418
|
+
setQuality(quality) {
|
|
419
|
+
this.qualityWatch = quality === 'auto' ? new QualityWatch('high', (level) => this.applyQuality(level)) : undefined;
|
|
420
|
+
this.applyQuality(quality === 'auto' ? 'high' : quality);
|
|
421
|
+
}
|
|
422
|
+
applyQuality(quality) {
|
|
423
|
+
if (quality === this.#quality)
|
|
424
|
+
return;
|
|
425
|
+
this.#quality = quality;
|
|
426
|
+
// The canvas at its pixel ratio, the sun's shadows, the layers' detail
|
|
427
|
+
this.resize();
|
|
428
|
+
if (this.sun)
|
|
429
|
+
this.setSun(this.sun);
|
|
430
|
+
this.layers.forEach((layer) => {
|
|
431
|
+
layer.qualityChanged();
|
|
432
|
+
});
|
|
433
|
+
this.emit('quality', { quality });
|
|
434
|
+
this.requestRender();
|
|
435
|
+
}
|
|
378
436
|
getCamera() {
|
|
379
437
|
return this.frames.camera ?? this.engine.camera();
|
|
380
438
|
}
|
|
@@ -473,8 +531,8 @@ export class GeoMap {
|
|
|
473
531
|
// The twilight: from 6° above the horizon to 6° under it, smoothly
|
|
474
532
|
const dusk = Math.min(1, Math.max(0, (6 - altitude) / 12));
|
|
475
533
|
const night = Math.min(1, Math.max(0, options.night ?? dusk * dusk * (3 - 2 * dusk)));
|
|
476
|
-
// The shadows fade with the sun's light
|
|
477
|
-
const opacity = Math.min(1, Math.max(0, options.opacity ?? 0.35)) * (1 - night);
|
|
534
|
+
// The shadows fade with the sun's light; none at a low quality (its light and the night stay)
|
|
535
|
+
const opacity = this.quality.shadows ? Math.min(1, Math.max(0, options.opacity ?? 0.35)) * (1 - night) : 0;
|
|
478
536
|
this.engine.setSun(azimuth, altitude, opacity, night);
|
|
479
537
|
this.requestRender();
|
|
480
538
|
}
|
|
@@ -728,7 +786,7 @@ export class GeoMap {
|
|
|
728
786
|
}
|
|
729
787
|
/** Lines from GeoJSON (line strings, and polygon outlines), styled per feature */
|
|
730
788
|
addLines(options) {
|
|
731
|
-
return this.place(new LineLayer(this, options.data, lineStyle(options)), options.before);
|
|
789
|
+
return this.place(new LineLayer(this, options.data, lineStyle(options), options.altitudeReference), options.before);
|
|
732
790
|
}
|
|
733
791
|
/** Discs from GeoJSON points, styled per feature */
|
|
734
792
|
addCircles(options) {
|
|
@@ -888,7 +946,7 @@ export class GeoMap {
|
|
|
888
946
|
if (this.lost)
|
|
889
947
|
return;
|
|
890
948
|
const { clientWidth: width, clientHeight: height } = this.canvas;
|
|
891
|
-
const ratio = window.devicePixelRatio || 1;
|
|
949
|
+
const ratio = Math.min(window.devicePixelRatio || 1, this.quality.pixelRatio);
|
|
892
950
|
this.canvas.width = Math.round(width * ratio);
|
|
893
951
|
this.canvas.height = Math.round(height * ratio);
|
|
894
952
|
this.engine.resize(width, height, ratio);
|