Release God's Eye View as open source

This commit is contained in:
Bilawal Sidhu committed 2026-08-24 17:02:16 -05:00
1 parent a5aaea7e16
commit 880a672b5e
433 files changed
+219893 -23

No files matched your search

+92
View File
@@ -0,0 +1,92 @@
/**
* @file Queue-spawn helpers for jammed roads — platoon position math only.
* Cesium-free so bumper-to-bumper spacing is unit-testable; the traffic
* layer maps the returned distances onto Cartesian3 waypoints at spawn time.
*
* Only ever used for live-flow jam-bucket roads (jamViz 'density'/'both');
* the keyless simulation never calls into this module.
*
* @module data/trafficQueue
*/
/** @const {number} Smallest platoon (cars per queue cluster). */
const PLATOON_MIN = 4;
/** @const {number} Random extra cars per platoon (0–4 → sizes 4–8). */
const PLATOON_SPREAD = 5;
/** @const {number} Meters — minimum bumper-to-bumper gap inside a platoon. */
const GAP_MIN_M = 6;
/** @const {number} Meters — random extra gap (6–12 m total). */
const GAP_SPREAD_M = 6;
/**
* Generate `count` along-road distances clustered into bumper-to-bumper
* platoons: each platoon anchors at a random distance and trails 4–8 cars
* behind it at 6–12 m gaps, wrapping around the road start. Platoons are
* returned as separate arrays so the caller can give each queue one shared
* travel direction.
*
* @param {number} totalLen - Road length in meters.
* @param {number} count - Dots to place across all platoons.
* @param {() => number} [rng=Math.random] - Uniform [0,1) source (injectable for tests).
* @returns {number[][]} Platoons of distances in [0, totalLen); total length
* across platoons is `count` (empty on degenerate input).
*/
export function queuePlatoons(totalLen, count, rng = Math.random) {
const platoons = [];
if (!Number.isFinite(totalLen) || totalLen <= 0 || !(count > 0)) return platoons;
let placed = 0;
while (placed < count) {
const platoonSize = Math.min(
count - placed,
PLATOON_MIN + Math.floor(rng() * PLATOON_SPREAD)
);
const anchor = rng() * totalLen;
const platoon = [];
let trail = 0;
for (let j = 0; j < platoonSize; j++) {
if (j > 0) trail += GAP_MIN_M + rng() * GAP_SPREAD_M;
const s = anchor - trail;
platoon.push(((s % totalLen) + totalLen) % totalLen);
}
platoons.push(platoon);
placed += platoonSize;
}
return platoons;
}
/**
* Flat variant of {@link queuePlatoons} — platoon structure discarded.
*
* @param {number} totalLen - Road length in meters.
* @param {number} count - Dots to place.
* @param {() => number} [rng=Math.random] - Uniform [0,1) source (injectable for tests).
* @returns {number[]} Distances in [0, totalLen), length `count` (or empty on
* degenerate input).
*/
export function queueDistances(totalLen, count, rng = Math.random) {
return queuePlatoons(totalLen, count, rng).flat();
}
/**
* Map an along-road distance to its containing segment and parametric t.
* Distances beyond the road clamp to the far end; zero-length segments are
* skipped. A distance landing exactly on a segment boundary resolves to the
* earlier segment at t=1 (the animator treats t≥1 as a crossing).
*
* @param {number[]} segmentDist - Per-segment lengths in meters.
* @param {number} s - Along-road distance in meters.
* @returns {{segIdx:number, t:number}} Segment index + parametric position.
*/
export function locateAlongRoad(segmentDist, s) {
let remaining = Math.max(0, s);
const lastIdx = segmentDist.length - 1;
for (let k = 0; k <= lastIdx; k++) {
const d = segmentDist[k] || 0;
if ((d > 0 && remaining <= d) || k === lastIdx) {
return { segIdx: k, t: d > 0 ? Math.min(1, remaining / d) : 0 };
}
remaining -= d;
}
return { segIdx: 0, t: 0 };
}