emergency: select routes that pass near the start city

This commit is contained in:
Richard Zink committed 2026-10-13 07:31:29 +02:00
1 parent 4cb1e3a704
commit f06c50409a
1 file changed
+45 -14
+45 -14
View File
@@ -3549,16 +3549,36 @@ function emergencyCollectCandidates(net, netKey, startCity, minKm, maxKm, nearLi
var lastX = net.pts[last], lastZ = net.pts[last + 1], lastD = net.pts[last + 2];
var len = Math.max(0, lastD - firstD);
var lenKm = len * KM_PER_TILE;
var dStart = Math.hypot(firstX - startCity.x, firstZ - startCity.z);
if (lenKm >= minKm && lenKm <= maxKm) {
var near = Math.hypot(firstX - startCity.x, firstZ - startCity.z);
var startD = 0;
var dEnd = Math.hypot(lastX - startCity.x, lastZ - startCity.z);
var near = Math.min(dStart, dEnd);
if (near <= nearLimit && lenKm >= minKm && lenKm <= maxKm) {
if (dEnd < near) {
near = dEnd;
startD = len;
}
// A long road can pass close to the start city even when both
// of its endpoints are far away. Sample the chain coarsely.
if (near > nearLimit && n > 4) {
var step = Math.max(1, Math.floor(n / 16));
for (var q = step; q < n - step; q += step) {
var off = k + q * 3;
var dd = Math.hypot(net.pts[off] - startCity.x, net.pts[off + 1] - startCity.z);
if (dd < near) {
near = dd;
startD = Math.max(0, Math.min(len, net.pts[off + 2] - firstD));
}
}
}
if (near <= nearLimit) {
out.push({
net: net, netKey: netKey, ci: ci, len: len, lenKm: lenKm, near: near,
net: net, netKey: netKey, ci: ci, len: len, lenKm: lenKm,
near: near, startD: startD,
score: Math.abs(lenKm - targetKm) + near * 18,
reverse: dEnd < dStart
reverse: false
});
}
}
k += n * 3;
}
return out;
@@ -3620,11 +3640,7 @@ function selectEmergencyRoutes() {
if (used[usedKey]) continue;
used[usedKey] = true;
var route = emergencyChainAt(cand.net, cand.ci);
if (cand.reverse) {
route.reverse();
var maxD = route.length ? route[0].d : 0;
for (var rp = 0; rp < route.length; rp++) route[rp].d = maxD - route[rp].d;
} else if (route.length) {
if (route.length) {
var base = route[0].d;
for (var rp2 = 0; rp2 < route.length; rp2++) route[rp2].d -= base;
}
@@ -3637,12 +3653,20 @@ function selectEmergencyRoutes() {
});
continue;
}
emergencyRoutes.push({ pts: route, len: len, lenKm: len * KM_PER_TILE, nearKm: cand.near * KM_PER_TILE });
emergencyRoutes.push({
pts: route, len: len, lenKm: len * KM_PER_TILE,
nearKm: cand.near * KM_PER_TILE,
startD: Math.max(0, Math.min(len, cand.startD || 0))
});
}
for (var v = 0; v < emergencyRoutes.length; v++) {
var rr = emergencyRoutes[v];
var spread = rr.len * 0.18;
var d = (rr.startD || 0) + (Math.random() - 0.5) * spread;
d = Math.max(0, Math.min(rr.len, d));
emergencyVehicles.push({
route: v,
d: emergencyRoutes[v].len * (0.05 + 0.85 * Math.random()),
d: d,
dir: Math.random() < 0.5 ? 1 : -1,
seed: Math.random()
});
@@ -3662,12 +3686,19 @@ function selectEmergencyRoutes() {
candidateSample: top.slice(0, 5).map(function (c) {
return {
netKey: c.netKey, ci: c.ci, lenKm: +c.lenKm.toFixed(1),
nearKm: +(c.near * KM_PER_TILE).toFixed(1), reverse: c.reverse
nearKm: +(c.near * KM_PER_TILE).toFixed(1),
startKm: +((c.startD || 0) * KM_PER_TILE).toFixed(1)
};
}),
routeFailures: routeFailures.slice(0, 5),
networks: nets.map(function (n) { return { key: n.key, chains: n.net.cnts.length }; }),
routes: emergencyRoutes.map(function (r) { return { km: +r.lenKm.toFixed(1), nearKm: +r.nearKm.toFixed(1) }; })
routes: emergencyRoutes.map(function (r) {
return {
km: +r.lenKm.toFixed(1),
nearKm: +r.nearKm.toFixed(1),
startKm: +(r.startD * KM_PER_TILE).toFixed(1)
};
})
};
}