mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
81 lines
3.0 KiB
JavaScript
81 lines
3.0 KiB
JavaScript
/**
|
||
* @file Pure styling helpers for live traffic flow — level → bucket/color/
|
||
* speed/density. Cesium-free so thresholds are unit-testable; the traffic
|
||
* layer maps buckets to Cesium colors at spawn time.
|
||
*
|
||
* `level` is TomTom's `traffic_level`: current speed / free-flow speed,
|
||
* 0..1 where 1 = free flow. Non-finite input degrades to free-flow/neutral
|
||
* everywhere — a road with unusable data must render like the simulation,
|
||
* never as a phantom traffic jam.
|
||
*
|
||
* @module data/trafficFlowStyle
|
||
*/
|
||
|
||
/** @const {number} Levels at/above this render as free-flowing (green). */
|
||
const FREE_THRESHOLD = 0.85;
|
||
/** @const {number} Levels at/above this (and below FREE) render slow (amber); below is jam (red). */
|
||
const SLOW_THRESHOLD = 0.55;
|
||
|
||
/**
|
||
* Bucket color palette as Cesium-free rgba tuples ([r, g, b] 0–255 + alpha 0–1):
|
||
* green #2ecc71 / amber #f0b23e / red #e05252, all at 0.9 alpha.
|
||
* @type {{free:number[], slow:number[], jam:number[]}}
|
||
*/
|
||
export const FLOW_BUCKET_RGBA = {
|
||
free: [46, 204, 113, 0.9],
|
||
slow: [240, 178, 62, 0.9],
|
||
jam: [224, 82, 82, 0.9],
|
||
};
|
||
|
||
/**
|
||
* Classify a traffic level into a congestion bucket.
|
||
* @param {number} level - traffic_level 0..1 (1 = free flow).
|
||
* @returns {'free'|'slow'|'jam'} Bucket name; non-finite input → 'free'.
|
||
*/
|
||
export function flowBucket(level) {
|
||
if (!Number.isFinite(level)) return 'free';
|
||
if (level >= FREE_THRESHOLD) return 'free';
|
||
if (level >= SLOW_THRESHOLD) return 'slow';
|
||
return 'jam';
|
||
}
|
||
|
||
/**
|
||
* rgba tuple for a traffic level (bucket palette lookup).
|
||
* @param {number} level - traffic_level 0..1.
|
||
* @returns {number[]} [r, g, b, a] with rgb 0–255, alpha 0–1.
|
||
*/
|
||
export function flowColor(level) {
|
||
return FLOW_BUCKET_RGBA[flowBucket(level)];
|
||
}
|
||
|
||
/**
|
||
* Dot speed multiplier for a traffic level. Jammed roads crawl but never
|
||
* freeze (0.15 floor keeps the layer visibly alive); free flow is unchanged.
|
||
* @param {number} level - traffic_level 0..1.
|
||
* @returns {number} Multiplier within [0.15, 1]; non-finite input → 1.
|
||
*/
|
||
export function flowSpeedScale(level) {
|
||
if (!Number.isFinite(level)) return 1;
|
||
return Math.min(1, Math.max(0.15, level));
|
||
}
|
||
|
||
/**
|
||
* Dot density multiplier for a traffic level — congestion means more cars on
|
||
* the road, so slower roads pack more dots: 1/max(level, 0.4), capped at 2.5.
|
||
*
|
||
* With `jamBoost` (the jamViz density prototype) the same curve keeps
|
||
* climbing through deep jams — 1/max(level, 0.25), capped at 4.0 — so
|
||
* gridlock gets visibly denser while ordinary jams barely change. The two
|
||
* curves are identical for level ≥ 0.4.
|
||
*
|
||
* @param {number} level - traffic_level 0..1.
|
||
* @param {Object} [opts]
|
||
* @param {boolean} [opts.jamBoost=false] - Deepen the curve below the 2.5 cap.
|
||
* @returns {number} Multiplier within [1, 2.5] (or [1, 4] boosted); non-finite input → 1.
|
||
*/
|
||
export function flowDensityMult(level, { jamBoost = false } = {}) {
|
||
if (!Number.isFinite(level)) return 1;
|
||
if (jamBoost) return Math.min(4, 1 / Math.max(level, 0.25));
|
||
return Math.min(2.5, 1 / Math.max(level, 0.4));
|
||
}
|