mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 18:34:02 +00:00
Traffic figures for a radius area counted roads anywhere in its bounding box, and a tile that failed to load silently changed them. Roads are now cut to the circle, and the flow source reports per request whether any tile failed so the answer can say its figures are partial.
58 lines
1.9 KiB
JavaScript
58 lines
1.9 KiB
JavaScript
import { isDrivableFlowSegment } from './roadModes.js';
|
|
import { createVectorTileSource } from '../../sources/vectorTiles.js';
|
|
import { clipTileLine } from '../../sources/openFreeMap.js';
|
|
import { tileToBBox } from '../../data/tomtomTiles.js';
|
|
import { decodeFlowTile } from './flowDecode.js';
|
|
|
|
/** Own one bounded decoded flow cache; every request still passes the server tile budget. */
|
|
export function createFlowTileSource({
|
|
fetchImpl = (...args) => globalThis.fetch(...args),
|
|
} = {}) {
|
|
const tiles = createVectorTileSource({
|
|
template: '/api/tomtom/flow/{z}/{x}/{y}.pbf',
|
|
allowedOrigin: 'http://localhost',
|
|
decode: (bytes, z, x, y) =>
|
|
decodeFlowTile(bytes, z, x, y, { strict: true })
|
|
.filter(isDrivableFlowSegment)
|
|
.flatMap((segment) =>
|
|
clipTileLine(segment.coords, tileToBBox(z, x, y)).map((coords) => ({
|
|
...segment,
|
|
coords,
|
|
})),
|
|
),
|
|
fetchImpl,
|
|
ttlMs: 120_000,
|
|
maxTiles: 16,
|
|
});
|
|
let partial = false;
|
|
/**
|
|
* Flow segments for bounds, with whether any covering tile failed to load
|
|
* for this request.
|
|
*/
|
|
async function fetchFlowDetail(bounds, { signal, zoom = 12 } = {}) {
|
|
const result = await tiles.fetchBounds(bounds, {
|
|
zoom,
|
|
signal,
|
|
tiles: bounds.coverage?.coarse,
|
|
});
|
|
partial = result.partial;
|
|
const segments = bounds.coverage
|
|
? result.tiles.flat()
|
|
: result.tiles.flat().flatMap((segment) =>
|
|
clipTileLine(segment.coords, bounds).map((coords) => ({
|
|
...segment,
|
|
coords,
|
|
})),
|
|
);
|
|
return { segments, partial: result.partial === true };
|
|
}
|
|
return {
|
|
fetchFlowDetail,
|
|
async fetchFlowForBounds(bounds, options) {
|
|
return (await fetchFlowDetail(bounds, options)).segments;
|
|
},
|
|
getFlowSessionStats: () => ({ ...tiles.getStats(), partial }),
|
|
resetFlowTileCache: () => tiles.clear(),
|
|
};
|
|
}
|