Files
gods-eye-view/src/data/trafficFlowStyle.js
T

81 lines
3.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @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));
}