cars: add time-based traffic profile with weekend and Sunday peaks
This commit is contained in:
1 parent
19a2759685
commit
e3250a34da
2 files changed
+77
-22
No files matched your search
@@ -317,7 +317,28 @@ window.CONFIG = {
|
|||||||
spreadFloor: 0.30, // share that far side roads keep
|
spreadFloor: 0.30, // share that far side roads keep
|
||||||
speed: 1.0, // flow speed multiplier
|
speed: 1.0, // flow speed multiplier
|
||||||
density: 1.0, // vehicle density multiplier
|
density: 1.0, // vehicle density multiplier
|
||||||
brightness: 1.3 // vehicle light intensity
|
brightness: 1.3, // vehicle light intensity
|
||||||
|
// Time-based traffic profile. Values are multipliers around the
|
||||||
|
// configured density. Times are local scene-clock hours.
|
||||||
|
timeProfile: {
|
||||||
|
enabled: true,
|
||||||
|
weekday: 1.0, // Mon-Fri base traffic
|
||||||
|
saturday: 0.65, // weekend reduction
|
||||||
|
sunday: 0.55, // weekend reduction
|
||||||
|
morningPeak: 7.7, // rush-hour morning peak
|
||||||
|
morningWidth: 1.2, // gaussian sigma in hours
|
||||||
|
morningGain: 0.55, // +55 % at the peak
|
||||||
|
eveningPeak: 17.5, // rush-hour evening peak
|
||||||
|
eveningWidth: 1.4,
|
||||||
|
eveningGain: 0.75, // +75 % at the peak
|
||||||
|
fridayEveningGain: 0.35,
|
||||||
|
sundayEveningPeak: 18.5,
|
||||||
|
sundayEveningWidth: 1.8,
|
||||||
|
sundayEveningGain: 0.85, // commuter return traffic
|
||||||
|
nightReduction: 0.70 // deep-night traffic reduced to 30 %
|
||||||
|
// timeProfile: { enabled: false }
|
||||||
|
// timeProfile: { morningGain: 0.8, eveningGain: 1.0, nightReduction: 0.85 }
|
||||||
|
}
|
||||||
// speed: 2.0, density: 0.6, brightness: 1.0
|
// speed: 2.0, density: 0.6, brightness: 1.0
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Vendored
+55
-21
@@ -3359,6 +3359,58 @@ var CAR_LANE_PX = CAR_TUN.lanePx || 2.6;
|
|||||||
var CAR_BRIGHT = CAR_TUN.brightness || 1.3;
|
var CAR_BRIGHT = CAR_TUN.brightness || 1.3;
|
||||||
var CAR_SPEED = CAR_TUN.speed || 1;
|
var CAR_SPEED = CAR_TUN.speed || 1;
|
||||||
var CAR_DENS = CAR_TUN.density || 1;
|
var CAR_DENS = CAR_TUN.density || 1;
|
||||||
|
var CAR_TIME_CFG = CAR_TUN.timeProfile || {};
|
||||||
|
var CAR_TIME_ON = CAR_TIME_CFG.enabled !== false;
|
||||||
|
function carSmoothstep(a, b, x) {
|
||||||
|
var t = Math.max(0, Math.min(1, (x - a) / Math.max(1e-6, b - a)));
|
||||||
|
return t * t * (3 - 2 * t);
|
||||||
|
}
|
||||||
|
function carGaussian(hh, center, width) {
|
||||||
|
var d = hh - center;
|
||||||
|
if (d > 12) d -= 24;
|
||||||
|
if (d < -12) d += 24;
|
||||||
|
var w = Math.max(0.25, width);
|
||||||
|
return Math.exp(-(d * d) / (2 * w * w));
|
||||||
|
}
|
||||||
|
function carWeekendFactor(dow, hh) {
|
||||||
|
var sat = (typeof CAR_TIME_CFG.saturday === 'number') ? CAR_TIME_CFG.saturday : 0.65;
|
||||||
|
var sun = (typeof CAR_TIME_CFG.sunday === 'number') ? CAR_TIME_CFG.sunday : 0.55;
|
||||||
|
var work = (typeof CAR_TIME_CFG.weekday === 'number') ? CAR_TIME_CFG.weekday : 1.0;
|
||||||
|
function wOf(d) { return d === 0 ? sun : (d === 6 ? sat : work); }
|
||||||
|
var f = wOf(dow);
|
||||||
|
if (hh >= 23) f = f + (wOf((dow + 1) % 7) - f) * (hh - 23);
|
||||||
|
else if (hh < 1) f = wOf((dow + 6) % 7) + (f - wOf((dow + 6) % 7)) * hh;
|
||||||
|
return Math.max(0.15, Math.min(1.5, f));
|
||||||
|
}
|
||||||
|
function carRushFactor(hh, dow) {
|
||||||
|
if (!CAR_TIME_ON || typeof hh !== 'number') return 1;
|
||||||
|
var morningPeak = (typeof CAR_TIME_CFG.morningPeak === 'number') ? CAR_TIME_CFG.morningPeak : 7.7;
|
||||||
|
var morningWidth = (typeof CAR_TIME_CFG.morningWidth === 'number') ? CAR_TIME_CFG.morningWidth : 1.2;
|
||||||
|
var morningGain = (typeof CAR_TIME_CFG.morningGain === 'number') ? CAR_TIME_CFG.morningGain : 0.55;
|
||||||
|
var eveningPeak = (typeof CAR_TIME_CFG.eveningPeak === 'number') ? CAR_TIME_CFG.eveningPeak : 17.5;
|
||||||
|
var eveningWidth = (typeof CAR_TIME_CFG.eveningWidth === 'number') ? CAR_TIME_CFG.eveningWidth : 1.4;
|
||||||
|
var eveningGain = (typeof CAR_TIME_CFG.eveningGain === 'number') ? CAR_TIME_CFG.eveningGain : 0.75;
|
||||||
|
var nightReduction = (typeof CAR_TIME_CFG.nightReduction === 'number') ? CAR_TIME_CFG.nightReduction : 0.70;
|
||||||
|
var fridayGain = (typeof CAR_TIME_CFG.fridayEveningGain === 'number') ? CAR_TIME_CFG.fridayEveningGain : 0.35;
|
||||||
|
var sundayEveningPeak = (typeof CAR_TIME_CFG.sundayEveningPeak === 'number') ? CAR_TIME_CFG.sundayEveningPeak : 18.5;
|
||||||
|
var sundayEveningWidth = (typeof CAR_TIME_CFG.sundayEveningWidth === 'number') ? CAR_TIME_CFG.sundayEveningWidth : 1.8;
|
||||||
|
var sundayEveningGain = (typeof CAR_TIME_CFG.sundayEveningGain === 'number') ? CAR_TIME_CFG.sundayEveningGain : 0.85;
|
||||||
|
|
||||||
|
var rush = 1;
|
||||||
|
rush += morningGain * carGaussian(hh, morningPeak, morningWidth);
|
||||||
|
rush += eveningGain * carGaussian(hh, eveningPeak, eveningWidth);
|
||||||
|
|
||||||
|
if (dow === 5) rush += fridayGain * carGaussian(hh, 18.0, 1.6);
|
||||||
|
if (dow === 0) rush += sundayEveningGain * carGaussian(hh, sundayEveningPeak, sundayEveningWidth);
|
||||||
|
|
||||||
|
var nightEdge = -1;
|
||||||
|
if (hh >= 22) nightEdge = carSmoothstep(22, 24, hh);
|
||||||
|
else if (hh < 5) nightEdge = 1 - carSmoothstep(3, 5, hh);
|
||||||
|
if (nightEdge >= 0) rush *= 1 - nightReduction * nightEdge;
|
||||||
|
|
||||||
|
if (typeof dow === 'number') rush *= carWeekendFactor(dow, hh);
|
||||||
|
return Math.max(0.12, Math.min(2.2, rush));
|
||||||
|
}
|
||||||
// Gaussian spread of traffic around the motorway network: sigma (spreadKm)
|
// Gaussian spread of traffic around the motorway network: sigma (spreadKm)
|
||||||
// and the floor that distant side roads keep (spreadFloor).
|
// and the floor that distant side roads keep (spreadFloor).
|
||||||
var CAR_SIGMA = carMetres((CAR_TUN.spreadKm || 25) * 1000);
|
var CAR_SIGMA = carMetres((CAR_TUN.spreadKm || 25) * 1000);
|
||||||
@@ -6590,30 +6642,12 @@ window.clouds3dRender = function(target) {
|
|||||||
var carPxScale = Math.max(0.45, Math.min(1.25, gl.drawingBufferHeight / 1080));
|
var carPxScale = Math.max(0.45, Math.min(1.25, gl.drawingBufferHeight / 1080));
|
||||||
var tCurve = Math.max(0, Math.min(1, (carNight - 0.10) / 0.40));
|
var tCurve = Math.max(0, Math.min(1, (carNight - 0.10) / 0.40));
|
||||||
tCurve = tCurve * tCurve * (3 - 2 * tCurve); // smoothstep
|
tCurve = tCurve * tCurve * (3 - 2 * tCurve); // smoothstep
|
||||||
// rush-hour shaping: busy evening/early morning, quiet 23:00-04:00
|
// Time-based traffic profile: weekday rush peaks, quiet deep night,
|
||||||
|
// reduced weekend traffic, and a Sunday-evening commuter bump.
|
||||||
var rush = 1;
|
var rush = 1;
|
||||||
var tDay = window.__currentDayProgress;
|
var tDay = window.__currentDayProgress;
|
||||||
if (typeof tDay === 'number') {
|
if (typeof tDay === 'number') {
|
||||||
var hh = tDay * 24;
|
rush = carRushFactor(tDay * 24, window.__flightDow);
|
||||||
var nightPos = hh >= 23 ? (hh - 23) / 5 : (hh < 4 ? (hh + 1) / 5 : -1);
|
|
||||||
if (nightPos >= 0) {
|
|
||||||
var edge = Math.min(1, Math.min(nightPos, 1 - nightPos) * 5);
|
|
||||||
edge = edge * edge * (3 - 2 * edge);
|
|
||||||
rush = 1 - 0.65 * edge; // dips to 0.35
|
|
||||||
}
|
|
||||||
// weekend factor (window.__flightDow: 0=Sun..6=Sat), blended
|
|
||||||
// smoothly over the hour around midnight so nothing pops
|
|
||||||
var dow = window.__flightDow;
|
|
||||||
if (typeof dow === 'number') {
|
|
||||||
var wOf = function (d) { return d === 0 ? 0.55 : (d === 6 ? 0.65 : 1); };
|
|
||||||
var fNow = wOf(dow);
|
|
||||||
if (hh >= 23) {
|
|
||||||
fNow = fNow + (wOf((dow + 1) % 7) - fNow) * (hh - 23);
|
|
||||||
} else if (hh < 1) {
|
|
||||||
fNow = wOf((dow + 6) % 7) + (fNow - wOf((dow + 6) % 7)) * hh;
|
|
||||||
}
|
|
||||||
rush *= fNow;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
gl.useProgram(carProg);
|
gl.useProgram(carProg);
|
||||||
gl.uniformMatrix4fv(carUniforms.proj, false, proj);
|
gl.uniformMatrix4fv(carUniforms.proj, false, proj);
|
||||||
|
|||||||
Reference in new issue
Block a user