isard 1.10.0 → 1.12.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 +58 -0
- package/README.md +1 -1
- package/dist/basemap/vectortiles/vectors.js +2 -1
- package/dist/basemap/vectortiles/vectors.js.map +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_grid_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/layers/vectors.js +6 -0
- package/dist/layers/vectors.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 +37 -0
- package/dist/map/quality.js +63 -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 +16 -8
- package/dist/wasm/isard.js +38 -8
- package/dist/wasm/isard_core.d.ts +11 -8
- package/dist/wasm/isard_core.js +26 -8
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vectors.js","sourceRoot":"","sources":["../../src/layers/vectors.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The fills and lines of a MapLibre style drawn as geometry, tile by tile (`VectorTiles.vectors`), instead of into the\n * images of a raster layer: sharp at any zoom and pitch, on the relief, picked by feature, restyled without cutting the\n * tiles again. The workers cut each vector tile into polygons and lines and style its features; the engine draws the\n * style's layers in their order, each over its zoom range.\n */\n\nimport type { LayerHost } from '../types.ts';\nimport { FLOATS } from '../util/style-floats.ts';\nimport type { Engine } from '../wasm/isard.js';\nimport type { TileVectors } from '../workers/basemap/protocol.ts';\nimport { type Feature, type Size, stops } from './features.ts';\nimport { Layer } from './layers.ts';\nimport type { Tiles3dLayer } from './tiles3d.ts';\n\n/** A style layer as the engine draws it: its kind, zoom range, visibility and dashes (dash, gap, dash, gap, in line\n * widths; zeros: solid) */\nexport interface VectorSublayer {\n /** The style layer's id */\n id: string;\n /** Its source layer, if any (not for a background) */\n sourceLayer: string | undefined;\n kind: 'fill' | 'line' | 'extrusion' | 'circle';\n minZoom: number;\n maxZoom: number;\n visible: boolean;\n /** Its opacity when it depends on the zoom only, evaluated at the camera's zoom (else 1: the features' colors hold\n * it) */\n opacity: Size;\n dash: [number, number, number, number];\n /** The caps of its lines' ends (`line-cap`) */\n cap: 'butt' | 'round' | 'square';\n /** The joins of its lines' pieces (`line-join`), a miter longer than `miterLimit` line widths bevelled\n * (`line-miter-limit`); round and 2 if left out */\n join?: 'miter' | 'bevel' | 'round';\n miterLimit?: number;\n /** How far its fills or lines move on screen (`fill-translate`, `line-translate`: CSS pixels, x right, y down),\n * turning with the map or staying on the screen (`*-translate-anchor`); none and `map` if left out */\n translate?: [number, number];\n translateAnchor?: 'map' | 'viewport';\n /** Its fills have patterns (`fill-pattern`, `background-pattern`): over the relief, the engine finds the ground under\n * them */\n patterned?: boolean;\n /** Its lines glow at night (the streets: its id names a road, not its casing; `setSun`) */\n lit: boolean;\n}\n\n/** The properties of a picked feature, with the style layer that drew it */\nexport type VectorFeature = Feature<Record<string, unknown>> & { layer: string; sourceLayer: string | undefined };\n\n/** The main thread's time a frame gives to uploading tiles (ms): tiles arriving together are uploaded over several\n * frames, not all in the one (copying a tile's buffers to the GPU takes milliseconds) */\nconst UPLOAD_MS = 4;\n\ninterface Tile {\n /** Its number in the engine: tiles are numbered for picking in this order */\n key: number;\n /** What picking needs (its geometry and styles are the engine's only: an engine made anew asks the tiles again) */\n vectors: Pick<TileVectors, 'properties' | 'sublayer'>;\n}\n\nexport class VectorLayer extends Layer {\n private readonly tiles = new Map<string, Tile>();\n /** The tiles waiting for their upload (`UPLOAD_MS` a frame), each with what resolves its `setTile`; `sent`: in the\n * engine already, its blocks still uploading */\n private readonly queue = new Map<string, { vectors: TileVectors; uploaded: () => void; sent?: number }>();\n private flushing = false;\n private sublayers: VectorSublayer[] = [];\n private nextKey = 0;\n /** The whole layer shown (`setVisible`), over each style layer's visibility */\n private shown = true;\n /** Its buildings' walls show their windows (`setFacades`) */\n private facades = false;\n /** @internal Resolved once the style is loaded and its layers drawn known (set by its `VectorTiles`) */\n styled: Promise<void> = Promise.resolve();\n /** @internal Changes a property of a style layer drawn (set by its `VectorTiles`) */\n restyle: ((layer: string, group: 'paint' | 'layout', name: string, value: unknown) => void) | undefined;\n /** @internal Asks the workers for the tiles in view again (set by its `VectorTiles`): an engine made anew has none */\n recut: (() => void) | undefined;\n /** The 3D buildings drawn in place of its raised ones (`vectors({ buildings3d })`), for `map.pickFeature` */\n buildings3d: Tiles3dLayer | undefined;\n\n /** @internal */\n constructor(map: LayerHost) {\n super(map);\n }\n\n /** Resolves once the style is loaded, its layers drawn known (`layers`), and the map has drawn the layer; rejected\n * if the style fails */\n override get ready(): Promise<void> {\n return this.styled.then(() => super.ready);\n }\n\n /** The style layers drawn, in order */\n get layers(): readonly VectorSublayer[] {\n return this.sublayers;\n }\n\n /** Keys of the tiles held (`z/x/y`) */\n get tileKeys(): string[] {\n return [...this.tiles.keys()];\n }\n\n /** @internal Sets the style layers drawn, in order (the tiles' sublayers) */\n setSublayers(sublayers: VectorSublayer[]): void {\n this.sublayers = sublayers;\n this.sendSublayers(this.map.engine, this.id);\n this.map.requestRender();\n }\n\n /** @internal Adds or replaces a tile, cut by the workers (and made ready for the GPU there, with its mesh): uploaded\n * on a coming frame, within its share of the frame (`UPLOAD_MS`); resolves once it is (or once dropped meanwhile) */\n setTile(tile: string, vectors: TileVectors): Promise<void> {\n if (this.removed) return Promise.resolve();\n // The map not idle until it is uploaded\n return this.map.track(\n new Promise((uploaded) => {\n // A newer cut of a tile still waiting takes its place\n this.queue.get(tile)?.uploaded();\n this.queue.set(tile, { vectors, uploaded });\n this.flushSoon();\n }),\n );\n }\n\n /** Uploads the waiting tiles on the next frame */\n private flushSoon(): void {\n if (this.flushing) return;\n this.flushing = true;\n requestAnimationFrame(() => {\n this.flushing = false;\n this.flush();\n });\n }\n\n /** Uploads waiting tiles for `UPLOAD_MS` at most (one at least, or a part of its blocks), the rest on the next\n * frames; a tile's `setTile` resolves once its blocks are all there */\n private flush(): void {\n // Removed meanwhile, or between two engines (the new one asks for the tiles again)\n if (this.id < 0) return;\n\n const start = performance.now();\n const within = () => performance.now() - start <= UPLOAD_MS;\n\n for (const [tile, waiting] of this.queue) {\n waiting.sent ??= this.upload(tile, waiting.vectors);\n\n // A large tile's blocks (a pitched view's far tiles of a city: 10 MB and more), a part at a time\n let left = this.map.engine.uploadVectorTile(this.id, waiting.sent);\n\n while (left && within()) left = this.map.engine.uploadVectorTile(this.id, waiting.sent);\n if (left) break;\n this.queue.delete(tile);\n waiting.uploaded();\n if (!within()) break;\n }\n if (this.queue.size > 0) this.flushSoon();\n this.map.requestRender();\n }\n\n /** Sends a tile to the engine (its blocks' first part); its key */\n private upload(tile: string, vectors: TileVectors): number {\n const key = this.tiles.get(tile)?.key ?? this.nextKey++;\n const { properties, sublayer } = vectors;\n\n this.tiles.set(tile, { key, vectors: { properties, sublayer } });\n this.sendTile(this.map.engine, this.id, key, vectors);\n\n return key;\n }\n\n /** @internal New styles of a tile's features, as the workers evaluated them (the same features) */\n setTileStyles(tile: string, styles: Float32Array): void {\n const waiting = this.queue.get(tile);\n\n // Not uploaded yet: uploaded with them\n if (waiting && waiting.sent === undefined) {\n if (styles.length === waiting.vectors.properties.length * FLOATS) waiting.vectors.styles = styles;\n\n return;\n }\n\n const t = this.tiles.get(tile);\n\n if (!t || styles.length !== t.vectors.properties.length * FLOATS) return;\n this.map.engine.setFeatureStyle(this.id, styles, t.key);\n this.map.requestRender();\n }\n\n override remove(): void {\n super.remove();\n this.dispose();\n }\n\n /** @internal The tiles waiting resolved (dropped), none held */\n override dispose(): void {\n this.queue.forEach((waiting) => {\n waiting.uploaded();\n });\n this.queue.clear();\n this.tiles.clear();\n }\n\n /** @internal */\n removeTile(tile: string): void {\n this.queue.get(tile)?.uploaded();\n this.queue.delete(tile);\n\n const t = this.tiles.get(tile);\n\n if (!t) return;\n this.tiles.delete(tile);\n this.map.engine.removeVectorTile(this.id, t.key);\n this.map.requestRender();\n }\n\n /** The feature of a picked index (no geometry: the tiles hold it cut), its properties and style layer. Tiles are\n * numbered one after the other, in the order they were first added */\n featureAt(index: number): VectorFeature | undefined {\n const tiles = [...this.tiles.values()].sort((a, b) => a.key - b.key);\n // The tile holding the index, and the index among its features (one pass, the features of the tiles before\n // taken off)\n const { tile, rest } = tiles.reduce<{ tile?: Tile; rest: number }>(\n (found, t) => {\n if (found.tile) return found;\n\n const count = t.vectors.properties.length;\n\n return found.rest < count ? { tile: t, rest: found.rest } : { rest: found.rest - count };\n },\n { rest: index },\n );\n\n if (!tile) return undefined;\n\n const properties = tile.vectors.properties[rest];\n const sublayer = this.sublayers[tile.vectors.sublayer[rest] ?? -1];\n\n if (properties === undefined || !sublayer) return undefined;\n\n return { type: 'Feature', properties, geometry: null, layer: sublayer.id, sourceLayer: sublayer.sourceLayer };\n }\n\n /** Changes a paint property of a style layer drawn, as MapLibre's `setPaintProperty`: the tiles are restyled, not cut\n * again */\n setPaintProperty(layer: string, name: string, value: unknown): void {\n this.restyle?.(layer, 'paint', name, value);\n }\n\n /** Changes a layout property of a style layer drawn (`visibility`: shown or hidden at once), as MapLibre's\n * `setLayoutProperty` */\n setLayoutProperty(layer: string, name: string, value: unknown): void {\n this.restyle?.(layer, 'layout', name, value);\n }\n\n /** Whether its buildings' walls show their windows: glass by day, some lit at night (only the lit ones without) */\n setFacades(facades: boolean): void {\n this.facades = facades;\n this.map.engine.setFacades(this.id, facades);\n // Its 3D buildings' walls too\n this.buildings3d?.setFacades(facades);\n this.map.requestRender();\n }\n\n setVisible(visible: boolean): void {\n this.shown = visible;\n this.sendSublayers(this.map.engine, this.id);\n this.map.requestRender();\n }\n\n private sendSublayers(engine: Engine, id: number): void {\n const s = this.sublayers;\n\n engine.setVectorSublayers(\n id,\n Uint8Array.from(s, (l) => ({ fill: 0, line: 1, extrusion: 2, circle: 3 })[l.kind]),\n Float64Array.from(s.flatMap((l) => [l.minZoom, l.maxZoom])),\n Uint8Array.from(s, (l) => (l.visible && this.shown ? 1 : 0)),\n Float32Array.from(s.flatMap((l) => l.dash)),\n Float32Array.from(s.flatMap((l) => stops(l.opacity))),\n Uint8Array.from(s, (l) => ({ butt: 0, round: 1, square: 2 })[l.cap]),\n Uint8Array.from(s, (l) => (l.lit ? 1 : 0)),\n Float32Array.from(s.flatMap((l) => [{ round: 0, miter: 1, bevel: 2 }[l.join ?? 'round'], l.miterLimit ?? 2])),\n Float32Array.from(s.flatMap((l) => [...(l.translate ?? [0, 0]), l.translateAnchor === 'viewport' ? 1 : 0])),\n Uint8Array.from(s, (l) => (l.patterned ? 1 : 0)),\n );\n }\n\n /** A tile to the engine: its mesh uploaded as it is, or without one its geometry, which the engine makes ready */\n private sendTile(engine: Engine, id: number, key: number, vectors: TileVectors): void {\n const { fills, lines, circles, styles, properties, mesh } = vectors;\n\n if (mesh) {\n engine.setVectorTileMesh(\n id,\n key,\n fills.points,\n fills.ringStart,\n fills.polygonStart,\n fills.feature,\n fills.fillStart,\n mesh.vertices,\n mesh.indices,\n mesh.fillRanges,\n mesh.prism,\n mesh.pieces,\n mesh.lineTable,\n mesh.lineRanges,\n mesh.blocks,\n mesh.blockIndices,\n mesh.blockRanges,\n mesh.bounds,\n properties.length,\n );\n } else {\n engine.setVectorTile(\n id,\n key,\n fills.points,\n fills.ringStart,\n fills.polygonStart,\n fills.feature,\n fills.fillStart,\n lines.points,\n lines.start,\n lines.feature,\n lines.lineStart,\n properties.length,\n vectors.tile ?? new Float64Array(),\n fills.roofs ?? new Uint8Array(),\n fills.roofHeights ?? new Float32Array(),\n fills.roofOutlines ?? new Float64Array(),\n fills.roofOutlineStart ?? new Uint32Array(),\n fills.roofMetres ?? 0,\n );\n }\n // The circles' points, once the tile is there\n if (circles) engine.setVectorTilePoints(id, key, circles.points, circles.feature, circles.circleStart);\n engine.setFeatureStyle(id, styles, key);\n }\n\n /** @internal */\n protected create(engine: Engine): number {\n const id = engine.addVectorTiles();\n\n this.sendSublayers(engine, id);\n engine.setFacades(id, this.facades);\n // An engine made anew (after a context loss, or the one with 3D Tiles): its tiles cut again by the workers, once\n // the layer has its id there. Keeping their geometry here would double the memory they take\n this.dispose();\n queueMicrotask(() => this.recut?.());\n\n return id;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"vectors.js","sourceRoot":"","sources":["../../src/layers/vectors.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The fills and lines of a MapLibre style drawn as geometry, tile by tile (`VectorTiles.vectors`), instead of into the\n * images of a raster layer: sharp at any zoom and pitch, on the relief, picked by feature, restyled without cutting the\n * tiles again. The workers cut each vector tile into polygons and lines and style its features; the engine draws the\n * style's layers in their order, each over its zoom range.\n */\n\nimport type { LayerHost } from '../types.ts';\nimport { FLOATS } from '../util/style-floats.ts';\nimport type { Engine } from '../wasm/isard.js';\nimport type { TileVectors } from '../workers/basemap/protocol.ts';\nimport { type Feature, type Size, stops } from './features.ts';\nimport { Layer } from './layers.ts';\nimport type { Tiles3dLayer } from './tiles3d.ts';\n\n/** A style layer as the engine draws it: its kind, zoom range, visibility and dashes (dash, gap, dash, gap, in line\n * widths; zeros: solid) */\nexport interface VectorSublayer {\n /** The style layer's id */\n id: string;\n /** Its source layer, if any (not for a background) */\n sourceLayer: string | undefined;\n kind: 'fill' | 'line' | 'extrusion' | 'circle';\n minZoom: number;\n maxZoom: number;\n visible: boolean;\n /** Its opacity when it depends on the zoom only, evaluated at the camera's zoom (else 1: the features' colors hold\n * it) */\n opacity: Size;\n dash: [number, number, number, number];\n /** The caps of its lines' ends (`line-cap`) */\n cap: 'butt' | 'round' | 'square';\n /** The joins of its lines' pieces (`line-join`), a miter longer than `miterLimit` line widths bevelled\n * (`line-miter-limit`); round and 2 if left out */\n join?: 'miter' | 'bevel' | 'round';\n miterLimit?: number;\n /** How far its fills or lines move on screen (`fill-translate`, `line-translate`: CSS pixels, x right, y down),\n * turning with the map or staying on the screen (`*-translate-anchor`); none and `map` if left out */\n translate?: [number, number];\n translateAnchor?: 'map' | 'viewport';\n /** Its fills have patterns (`fill-pattern`, `background-pattern`): over the relief, the engine finds the ground under\n * them */\n patterned?: boolean;\n /** Its lines glow at night (the streets: its id names a road, not its casing; `setSun`) */\n lit: boolean;\n}\n\n/** The properties of a picked feature, with the style layer that drew it */\nexport type VectorFeature = Feature<Record<string, unknown>> & { layer: string; sourceLayer: string | undefined };\n\n/** The main thread's time a frame gives to uploading tiles (ms): tiles arriving together are uploaded over several\n * frames, not all in the one (copying a tile's buffers to the GPU takes milliseconds) */\nconst UPLOAD_MS = 4;\n\ninterface Tile {\n /** Its number in the engine: tiles are numbered for picking in this order */\n key: number;\n /** What picking needs (its geometry and styles are the engine's only: an engine made anew asks the tiles again) */\n vectors: Pick<TileVectors, 'properties' | 'sublayer'>;\n}\n\nexport class VectorLayer extends Layer {\n private readonly tiles = new Map<string, Tile>();\n /** The tiles waiting for their upload (`UPLOAD_MS` a frame), each with what resolves its `setTile`; `sent`: in the\n * engine already, its blocks still uploading */\n private readonly queue = new Map<string, { vectors: TileVectors; uploaded: () => void; sent?: number }>();\n private flushing = false;\n private sublayers: VectorSublayer[] = [];\n private nextKey = 0;\n /** The whole layer shown (`setVisible`), over each style layer's visibility */\n private shown = true;\n /** Its buildings' walls show their windows (`setFacades`) */\n private facades = false;\n /** @internal Resolved once the style is loaded and its layers drawn known (set by its `VectorTiles`) */\n styled: Promise<void> = Promise.resolve();\n /** @internal Changes a property of a style layer drawn (set by its `VectorTiles`) */\n restyle: ((layer: string, group: 'paint' | 'layout', name: string, value: unknown) => void) | undefined;\n /** @internal Asks the workers for the tiles in view again (set by its `VectorTiles`): an engine made anew has none */\n recut: (() => void) | undefined;\n /** @internal Asks for the tiles in view (set by its `VectorTiles`): those of a new quality */\n refresh: (() => void) | undefined;\n /** The 3D buildings drawn in place of its raised ones (`vectors({ buildings3d })`), for `map.pickFeature` */\n buildings3d: Tiles3dLayer | undefined;\n\n /** @internal */\n constructor(map: LayerHost) {\n super(map);\n }\n\n /** @internal Its tiles as far as the map's quality reaches */\n override qualityChanged(): void {\n this.refresh?.();\n }\n\n /** Resolves once the style is loaded, its layers drawn known (`layers`), and the map has drawn the layer; rejected\n * if the style fails */\n override get ready(): Promise<void> {\n return this.styled.then(() => super.ready);\n }\n\n /** The style layers drawn, in order */\n get layers(): readonly VectorSublayer[] {\n return this.sublayers;\n }\n\n /** Keys of the tiles held (`z/x/y`) */\n get tileKeys(): string[] {\n return [...this.tiles.keys()];\n }\n\n /** @internal Sets the style layers drawn, in order (the tiles' sublayers) */\n setSublayers(sublayers: VectorSublayer[]): void {\n this.sublayers = sublayers;\n this.sendSublayers(this.map.engine, this.id);\n this.map.requestRender();\n }\n\n /** @internal Adds or replaces a tile, cut by the workers (and made ready for the GPU there, with its mesh): uploaded\n * on a coming frame, within its share of the frame (`UPLOAD_MS`); resolves once it is (or once dropped meanwhile) */\n setTile(tile: string, vectors: TileVectors): Promise<void> {\n if (this.removed) return Promise.resolve();\n // The map not idle until it is uploaded\n return this.map.track(\n new Promise((uploaded) => {\n // A newer cut of a tile still waiting takes its place\n this.queue.get(tile)?.uploaded();\n this.queue.set(tile, { vectors, uploaded });\n this.flushSoon();\n }),\n );\n }\n\n /** Uploads the waiting tiles on the next frame */\n private flushSoon(): void {\n if (this.flushing) return;\n this.flushing = true;\n requestAnimationFrame(() => {\n this.flushing = false;\n this.flush();\n });\n }\n\n /** Uploads waiting tiles for `UPLOAD_MS` at most (one at least, or a part of its blocks), the rest on the next\n * frames; a tile's `setTile` resolves once its blocks are all there */\n private flush(): void {\n // Removed meanwhile, or between two engines (the new one asks for the tiles again)\n if (this.id < 0) return;\n\n const start = performance.now();\n const within = () => performance.now() - start <= UPLOAD_MS;\n\n for (const [tile, waiting] of this.queue) {\n waiting.sent ??= this.upload(tile, waiting.vectors);\n\n // A large tile's blocks (a pitched view's far tiles of a city: 10 MB and more), a part at a time\n let left = this.map.engine.uploadVectorTile(this.id, waiting.sent);\n\n while (left && within()) left = this.map.engine.uploadVectorTile(this.id, waiting.sent);\n if (left) break;\n this.queue.delete(tile);\n waiting.uploaded();\n if (!within()) break;\n }\n if (this.queue.size > 0) this.flushSoon();\n this.map.requestRender();\n }\n\n /** Sends a tile to the engine (its blocks' first part); its key */\n private upload(tile: string, vectors: TileVectors): number {\n const key = this.tiles.get(tile)?.key ?? this.nextKey++;\n const { properties, sublayer } = vectors;\n\n this.tiles.set(tile, { key, vectors: { properties, sublayer } });\n this.sendTile(this.map.engine, this.id, key, vectors);\n\n return key;\n }\n\n /** @internal New styles of a tile's features, as the workers evaluated them (the same features) */\n setTileStyles(tile: string, styles: Float32Array): void {\n const waiting = this.queue.get(tile);\n\n // Not uploaded yet: uploaded with them\n if (waiting && waiting.sent === undefined) {\n if (styles.length === waiting.vectors.properties.length * FLOATS) waiting.vectors.styles = styles;\n\n return;\n }\n\n const t = this.tiles.get(tile);\n\n if (!t || styles.length !== t.vectors.properties.length * FLOATS) return;\n this.map.engine.setFeatureStyle(this.id, styles, t.key);\n this.map.requestRender();\n }\n\n override remove(): void {\n super.remove();\n this.dispose();\n }\n\n /** @internal The tiles waiting resolved (dropped), none held */\n override dispose(): void {\n this.queue.forEach((waiting) => {\n waiting.uploaded();\n });\n this.queue.clear();\n this.tiles.clear();\n }\n\n /** @internal */\n removeTile(tile: string): void {\n this.queue.get(tile)?.uploaded();\n this.queue.delete(tile);\n\n const t = this.tiles.get(tile);\n\n if (!t) return;\n this.tiles.delete(tile);\n this.map.engine.removeVectorTile(this.id, t.key);\n this.map.requestRender();\n }\n\n /** The feature of a picked index (no geometry: the tiles hold it cut), its properties and style layer. Tiles are\n * numbered one after the other, in the order they were first added */\n featureAt(index: number): VectorFeature | undefined {\n const tiles = [...this.tiles.values()].sort((a, b) => a.key - b.key);\n // The tile holding the index, and the index among its features (one pass, the features of the tiles before\n // taken off)\n const { tile, rest } = tiles.reduce<{ tile?: Tile; rest: number }>(\n (found, t) => {\n if (found.tile) return found;\n\n const count = t.vectors.properties.length;\n\n return found.rest < count ? { tile: t, rest: found.rest } : { rest: found.rest - count };\n },\n { rest: index },\n );\n\n if (!tile) return undefined;\n\n const properties = tile.vectors.properties[rest];\n const sublayer = this.sublayers[tile.vectors.sublayer[rest] ?? -1];\n\n if (properties === undefined || !sublayer) return undefined;\n\n return { type: 'Feature', properties, geometry: null, layer: sublayer.id, sourceLayer: sublayer.sourceLayer };\n }\n\n /** Changes a paint property of a style layer drawn, as MapLibre's `setPaintProperty`: the tiles are restyled, not cut\n * again */\n setPaintProperty(layer: string, name: string, value: unknown): void {\n this.restyle?.(layer, 'paint', name, value);\n }\n\n /** Changes a layout property of a style layer drawn (`visibility`: shown or hidden at once), as MapLibre's\n * `setLayoutProperty` */\n setLayoutProperty(layer: string, name: string, value: unknown): void {\n this.restyle?.(layer, 'layout', name, value);\n }\n\n /** Whether its buildings' walls show their windows: glass by day, some lit at night (only the lit ones without) */\n setFacades(facades: boolean): void {\n this.facades = facades;\n this.map.engine.setFacades(this.id, facades);\n // Its 3D buildings' walls too\n this.buildings3d?.setFacades(facades);\n this.map.requestRender();\n }\n\n setVisible(visible: boolean): void {\n this.shown = visible;\n this.sendSublayers(this.map.engine, this.id);\n this.map.requestRender();\n }\n\n private sendSublayers(engine: Engine, id: number): void {\n const s = this.sublayers;\n\n engine.setVectorSublayers(\n id,\n Uint8Array.from(s, (l) => ({ fill: 0, line: 1, extrusion: 2, circle: 3 })[l.kind]),\n Float64Array.from(s.flatMap((l) => [l.minZoom, l.maxZoom])),\n Uint8Array.from(s, (l) => (l.visible && this.shown ? 1 : 0)),\n Float32Array.from(s.flatMap((l) => l.dash)),\n Float32Array.from(s.flatMap((l) => stops(l.opacity))),\n Uint8Array.from(s, (l) => ({ butt: 0, round: 1, square: 2 })[l.cap]),\n Uint8Array.from(s, (l) => (l.lit ? 1 : 0)),\n Float32Array.from(s.flatMap((l) => [{ round: 0, miter: 1, bevel: 2 }[l.join ?? 'round'], l.miterLimit ?? 2])),\n Float32Array.from(s.flatMap((l) => [...(l.translate ?? [0, 0]), l.translateAnchor === 'viewport' ? 1 : 0])),\n Uint8Array.from(s, (l) => (l.patterned ? 1 : 0)),\n );\n }\n\n /** A tile to the engine: its mesh uploaded as it is, or without one its geometry, which the engine makes ready */\n private sendTile(engine: Engine, id: number, key: number, vectors: TileVectors): void {\n const { fills, lines, circles, styles, properties, mesh } = vectors;\n\n if (mesh) {\n engine.setVectorTileMesh(\n id,\n key,\n fills.points,\n fills.ringStart,\n fills.polygonStart,\n fills.feature,\n fills.fillStart,\n mesh.vertices,\n mesh.indices,\n mesh.fillRanges,\n mesh.prism,\n mesh.pieces,\n mesh.lineTable,\n mesh.lineRanges,\n mesh.blocks,\n mesh.blockIndices,\n mesh.blockRanges,\n mesh.bounds,\n properties.length,\n );\n } else {\n engine.setVectorTile(\n id,\n key,\n fills.points,\n fills.ringStart,\n fills.polygonStart,\n fills.feature,\n fills.fillStart,\n lines.points,\n lines.start,\n lines.feature,\n lines.lineStart,\n properties.length,\n vectors.tile ?? new Float64Array(),\n fills.roofs ?? new Uint8Array(),\n fills.roofHeights ?? new Float32Array(),\n fills.roofOutlines ?? new Float64Array(),\n fills.roofOutlineStart ?? new Uint32Array(),\n fills.roofMetres ?? 0,\n );\n }\n // The circles' points, once the tile is there\n if (circles) engine.setVectorTilePoints(id, key, circles.points, circles.feature, circles.circleStart);\n engine.setFeatureStyle(id, styles, key);\n }\n\n /** @internal */\n protected create(engine: Engine): number {\n const id = engine.addVectorTiles();\n\n this.sendSublayers(engine, id);\n engine.setFacades(id, this.facades);\n // An engine made anew (after a context loss, or the one with 3D Tiles): its tiles cut again by the workers, once\n // the layer has its id there. Keeping their geometry here would double the memory they take\n this.dispose();\n queueMicrotask(() => this.recut?.());\n\n return id;\n }\n}\n"]}
|
package/dist/map/events.js
CHANGED
package/dist/map/events.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/map/events.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAG9E,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAIrC,iDAAiD;AACjD,MAAM,OAAO,YAAY;IACN,SAAS,GAAc;QACtC,SAAS,EAAE,IAAI,GAAG,EAAE;QACpB,IAAI,EAAE,IAAI,GAAG,EAAE;QACf,OAAO,EAAE,IAAI,GAAG,EAAE;QAClB,MAAM,EAAE,IAAI,GAAG,EAAE;QACjB,KAAK,EAAE,IAAI,GAAG,EAAE;QAChB,YAAY,EAAE,IAAI,GAAG,EAAE;QACvB,KAAK,EAAE,IAAI,GAAG,EAAE;QAChB,MAAM,EAAE,IAAI,GAAG,EAAE;QACjB,IAAI,EAAE,IAAI,GAAG,EAAE;QACf,KAAK,EAAE,IAAI,GAAG,EAAE;KACjB,CAAC;IAEF,qEAAqE;IACrE,EAAE,CAA4B,IAAO,EAAE,QAAuC;QAC5E,MAAM,SAAS,GAAuC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAE3E,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAExB,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAED,kGAAkG;IAClG,IAAI,CAA4B,IAAO,EAAE,KAAmB;QAC1D,MAAM,SAAS,GAAuC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAE3E,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;YAC7B,IAAI,CAAC;gBACH,QAAQ,CAAC,KAAK,CAAC,CAAC;YAClB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,kCAAkC;IAClC,GAAG,CAAC,IAAqB;QACvB,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;IACvC,CAAC;IAED,6BAA6B;IAC7B,KAAK;QACH,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE;YAClD,SAAS,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC,CAAC,CAAC;IACL,CAAC;CACF","sourcesContent":["/** The listeners of the map's events: added, called, cleared with the map. */\n\nimport type { MapEvents } from '../types.ts';\nimport { report } from './checks.ts';\n\ntype Listeners = { [K in keyof MapEvents]: Set<(event: MapEvents[K]) => void> };\n\n/** The listeners of the map's events, by type */\nexport class MapListeners {\n private readonly listeners: Listeners = {\n movestart: new Set(),\n move: new Set(),\n moveend: new Set(),\n resize: new Set(),\n hover: new Set(),\n hoverfeature: new Set(),\n click: new Set(),\n render: new Set(),\n idle: new Set(),\n leave: new Set(),\n };\n\n /** Listens to an event; returns the function that stops listening */\n on<K extends keyof MapEvents>(type: K, listener: (event: MapEvents[K]) => void): () => void {\n const listeners: Set<(event: MapEvents[K]) => void> = this.listeners[type];\n\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n }\n\n /** Calls the listeners; one that throws is reported and does not stop the others nor the frame */\n emit<K extends keyof MapEvents>(type: K, event: MapEvents[K]): void {\n const listeners: Set<(event: MapEvents[K]) => void> = this.listeners[type];\n\n listeners.forEach((listener) => {\n try {\n listener(event);\n } catch (error) {\n report(error);\n }\n });\n }\n\n /** Something listens to `type` */\n has(type: keyof MapEvents): boolean {\n return this.listeners[type].size > 0;\n }\n\n /** Forgets every listener */\n clear(): void {\n Object.values(this.listeners).forEach((listeners) => {\n listeners.clear();\n });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/map/events.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAG9E,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAIrC,iDAAiD;AACjD,MAAM,OAAO,YAAY;IACN,SAAS,GAAc;QACtC,SAAS,EAAE,IAAI,GAAG,EAAE;QACpB,IAAI,EAAE,IAAI,GAAG,EAAE;QACf,OAAO,EAAE,IAAI,GAAG,EAAE;QAClB,MAAM,EAAE,IAAI,GAAG,EAAE;QACjB,KAAK,EAAE,IAAI,GAAG,EAAE;QAChB,YAAY,EAAE,IAAI,GAAG,EAAE;QACvB,KAAK,EAAE,IAAI,GAAG,EAAE;QAChB,MAAM,EAAE,IAAI,GAAG,EAAE;QACjB,OAAO,EAAE,IAAI,GAAG,EAAE;QAClB,IAAI,EAAE,IAAI,GAAG,EAAE;QACf,KAAK,EAAE,IAAI,GAAG,EAAE;KACjB,CAAC;IAEF,qEAAqE;IACrE,EAAE,CAA4B,IAAO,EAAE,QAAuC;QAC5E,MAAM,SAAS,GAAuC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAE3E,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAExB,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAED,kGAAkG;IAClG,IAAI,CAA4B,IAAO,EAAE,KAAmB;QAC1D,MAAM,SAAS,GAAuC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAE3E,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;YAC7B,IAAI,CAAC;gBACH,QAAQ,CAAC,KAAK,CAAC,CAAC;YAClB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,kCAAkC;IAClC,GAAG,CAAC,IAAqB;QACvB,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;IACvC,CAAC;IAED,6BAA6B;IAC7B,KAAK;QACH,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE;YAClD,SAAS,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC,CAAC,CAAC;IACL,CAAC;CACF","sourcesContent":["/** The listeners of the map's events: added, called, cleared with the map. */\n\nimport type { MapEvents } from '../types.ts';\nimport { report } from './checks.ts';\n\ntype Listeners = { [K in keyof MapEvents]: Set<(event: MapEvents[K]) => void> };\n\n/** The listeners of the map's events, by type */\nexport class MapListeners {\n private readonly listeners: Listeners = {\n movestart: new Set(),\n move: new Set(),\n moveend: new Set(),\n resize: new Set(),\n hover: new Set(),\n hoverfeature: new Set(),\n click: new Set(),\n render: new Set(),\n quality: new Set(),\n idle: new Set(),\n leave: new Set(),\n };\n\n /** Listens to an event; returns the function that stops listening */\n on<K extends keyof MapEvents>(type: K, listener: (event: MapEvents[K]) => void): () => void {\n const listeners: Set<(event: MapEvents[K]) => void> = this.listeners[type];\n\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n }\n\n /** Calls the listeners; one that throws is reported and does not stop the others nor the frame */\n emit<K extends keyof MapEvents>(type: K, event: MapEvents[K]): void {\n const listeners: Set<(event: MapEvents[K]) => void> = this.listeners[type];\n\n listeners.forEach((listener) => {\n try {\n listener(event);\n } catch (error) {\n report(error);\n }\n });\n }\n\n /** Something listens to `type` */\n has(type: keyof MapEvents): boolean {\n return this.listeners[type].size > 0;\n }\n\n /** Forgets every listener */\n clear(): void {\n Object.values(this.listeners).forEach((listeners) => {\n listeners.clear();\n });\n }\n}\n"]}
|
|
@@ -0,0 +1,37 @@
|
|
|
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), how far the 3D Tiles are
|
|
5
|
+
* refined (their screen-space error multiplied: fewer, coarser tiles far away) and how far toward the horizon the
|
|
6
|
+
* vector tiles go (a city's tiles there carry its whole detail over square kilometres, mostly above the screen's top
|
|
7
|
+
* edge: Paris tilted 65° on a phone, 940 MB of a page against 720 without them, the view the same). 'auto' starts high
|
|
8
|
+
* and steps down when the frames stay slow while the map moves.
|
|
9
|
+
*/
|
|
10
|
+
import type { Quality } from '../types.ts';
|
|
11
|
+
/** What a level draws */
|
|
12
|
+
export interface QualitySettings {
|
|
13
|
+
/** The highest pixel ratio drawn */
|
|
14
|
+
pixelRatio: number;
|
|
15
|
+
/** The sun casts its shadows (its light and the night stay without) */
|
|
16
|
+
shadows: boolean;
|
|
17
|
+
/** Multiplies the 3D Tiles' screen-space error */
|
|
18
|
+
errorScale: number;
|
|
19
|
+
/** How far toward the horizon the vector tiles go, in distances of the screen center */
|
|
20
|
+
reach: number;
|
|
21
|
+
}
|
|
22
|
+
export declare const QUALITY: Readonly<Record<Quality, QualitySettings>>;
|
|
23
|
+
/**
|
|
24
|
+
* 'auto': the intervals between the frames drawn while the map moves; once a window of them (`WINDOW`) has a median
|
|
25
|
+
* past `SLOW_MS`, `step` is called with the level under the current one. It never steps up: at the display's rate a fast
|
|
26
|
+
* frame tells nothing of what a finer level would cost
|
|
27
|
+
*/
|
|
28
|
+
export declare class QualityWatch {
|
|
29
|
+
private level;
|
|
30
|
+
private readonly step;
|
|
31
|
+
private readonly intervals;
|
|
32
|
+
private last;
|
|
33
|
+
private settled;
|
|
34
|
+
constructor(level: Quality, step: (level: Quality) => void);
|
|
35
|
+
/** A frame drawn at `now` (ms), the map moving or not */
|
|
36
|
+
frame(now: number, moving: boolean): void;
|
|
37
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
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), how far the 3D Tiles are
|
|
5
|
+
* refined (their screen-space error multiplied: fewer, coarser tiles far away) and how far toward the horizon the
|
|
6
|
+
* vector tiles go (a city's tiles there carry its whole detail over square kilometres, mostly above the screen's top
|
|
7
|
+
* edge: Paris tilted 65° on a phone, 940 MB of a page against 720 without them, the view the same). 'auto' starts high
|
|
8
|
+
* and steps down when the frames stay slow while the map moves.
|
|
9
|
+
*/
|
|
10
|
+
export const QUALITY = {
|
|
11
|
+
high: { pixelRatio: Number.POSITIVE_INFINITY, shadows: true, errorScale: 1, reach: Number.POSITIVE_INFINITY },
|
|
12
|
+
medium: { pixelRatio: 1.5, shadows: true, errorScale: 1.5, reach: 3 },
|
|
13
|
+
low: { pixelRatio: 1, shadows: false, errorScale: 2.5, reach: 3 },
|
|
14
|
+
};
|
|
15
|
+
/** The level under each, for 'auto' */
|
|
16
|
+
const LOWER = { high: 'medium', medium: 'low', low: undefined };
|
|
17
|
+
/** A move measured before it is judged: `WINDOW` frames, or `WINDOW_MS` of them on a slow device (at least
|
|
18
|
+
* `MIN_FRAMES`); a gap past `GAP_MS` between two frames is no move (the map was still) */
|
|
19
|
+
const WINDOW = 60;
|
|
20
|
+
const WINDOW_MS = 2000;
|
|
21
|
+
const MIN_FRAMES = 10;
|
|
22
|
+
const GAP_MS = 500;
|
|
23
|
+
/** The median interval between the frames of a move past which the map steps down (some 40 frames a second) */
|
|
24
|
+
const SLOW_MS = 25;
|
|
25
|
+
/** After a step down, the time the new level is given before it is judged */
|
|
26
|
+
const SETTLE_MS = 3000;
|
|
27
|
+
/**
|
|
28
|
+
* 'auto': the intervals between the frames drawn while the map moves; once a window of them (`WINDOW`) has a median
|
|
29
|
+
* past `SLOW_MS`, `step` is called with the level under the current one. It never steps up: at the display's rate a fast
|
|
30
|
+
* frame tells nothing of what a finer level would cost
|
|
31
|
+
*/
|
|
32
|
+
export class QualityWatch {
|
|
33
|
+
level;
|
|
34
|
+
step;
|
|
35
|
+
intervals = [];
|
|
36
|
+
last = 0;
|
|
37
|
+
settled = 0;
|
|
38
|
+
constructor(level, step) {
|
|
39
|
+
this.level = level;
|
|
40
|
+
this.step = step;
|
|
41
|
+
}
|
|
42
|
+
/** A frame drawn at `now` (ms), the map moving or not */
|
|
43
|
+
frame(now, moving) {
|
|
44
|
+
const gap = now - this.last;
|
|
45
|
+
this.last = now;
|
|
46
|
+
if (!moving || gap > GAP_MS || now < this.settled)
|
|
47
|
+
return;
|
|
48
|
+
this.intervals.push(gap);
|
|
49
|
+
const spent = this.intervals.reduce((sum, i) => sum + i, 0);
|
|
50
|
+
if (this.intervals.length < WINDOW && (spent < WINDOW_MS || this.intervals.length < MIN_FRAMES))
|
|
51
|
+
return;
|
|
52
|
+
const sorted = [...this.intervals].sort((a, b) => a - b);
|
|
53
|
+
const median = sorted[Math.floor(sorted.length / 2)] ?? 0;
|
|
54
|
+
const lower = LOWER[this.level];
|
|
55
|
+
this.intervals.length = 0;
|
|
56
|
+
if (median <= SLOW_MS || !lower)
|
|
57
|
+
return;
|
|
58
|
+
this.level = lower;
|
|
59
|
+
this.settled = now + SETTLE_MS;
|
|
60
|
+
this.step(lower);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=quality.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quality.js","sourceRoot":"","sources":["../../src/map/quality.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAgBH,MAAM,CAAC,MAAM,OAAO,GAA+C;IACjE,IAAI,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,iBAAiB,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,iBAAiB,EAAE;IAC7G,MAAM,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE;IACrE,GAAG,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE;CAClE,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), how far the 3D Tiles are\n * refined (their screen-space error multiplied: fewer, coarser tiles far away) and how far toward the horizon the\n * vector tiles go (a city's tiles there carry its whole detail over square kilometres, mostly above the screen's top\n * edge: Paris tilted 65° on a phone, 940 MB of a page against 720 without them, the view the same). 'auto' starts high\n * and steps down 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 /** How far toward the horizon the vector tiles go, in distances of the screen center */\n reach: number;\n}\n\nexport const QUALITY: Readonly<Record<Quality, QualitySettings>> = {\n high: { pixelRatio: Number.POSITIVE_INFINITY, shadows: true, errorScale: 1, reach: Number.POSITIVE_INFINITY },\n medium: { pixelRatio: 1.5, shadows: true, errorScale: 1.5, reach: 3 },\n low: { pixelRatio: 1, shadows: false, errorScale: 2.5, reach: 3 },\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);
|