car: cap road chain stitching to avoid Set overflow

This commit is contained in:
Richard Zink committed 2026-10-13 07:14:19 +02:00
1 parent 03ae45e0e5
commit 4ac48b188a
1 file changed
+31 -4
+31 -4
View File
@@ -4485,6 +4485,22 @@ function carMergeChains(polys, cfg) {
eps.push(r);
}
}
// Safety valve: dense residential/tertiary cells can create far more
// endpoints than the join search can safely hold. In that case keep the
// roads as individual chains instead of trying to stitch everything.
var JOIN_ENDPOINT_LIMIT = 180000;
if (eps.length > JOIN_ENDPOINT_LIMIT) {
var isoOut = [], isoMax = 0;
for (i = 0; i < n; i++) {
if (polys[i] && polys[i].length > 1) {
isoOut.push(polys[i]);
var isoSpan = Math.max(polys[i][0].d, polys[i][polys[i].length - 1].d);
if (isoSpan > isoMax) isoMax = isoSpan;
}
}
return { out: isoOut, n: n, joins: 0,
maxChainKm: n ? isoMax * cfg.KM_PER_TILE : 0 };
}
// canonical numeric key for an endpoint pair (way index + end side)
function pairKey(A, B) {
var x = A.w * 2 + A.e, y = B.w * 2 + B.e;
@@ -4510,25 +4526,36 @@ function carMergeChains(polys, cfg) {
var T = TIERS[t];
var cands = candsByTier[t];
var seenPair = new Set();
for (i = 0; i < eps.length; i++) {
var seenFull = false;
var SEEN_PAIR_LIMIT = 2000000;
var CAND_LIMIT = 1200000;
for (i = 0; i < eps.length && !seenFull; i++) {
if ((i & 8191) === 8191) geoProgress('join tier ' + t, i, eps.length);
var A2 = eps[i];
var gx = Math.floor(A2.x / NEAR), gz = Math.floor(A2.z / NEAR);
for (var ox = -1; ox <= 1; ox++) {
for (var oz = -1; oz <= 1; oz++) {
for (var ox = -1; ox <= 1 && !seenFull; ox++) {
for (var oz = -1; oz <= 1 && !seenFull; oz++) {
var bucket = grid.get((gx + ox) + '_' + (gz + oz));
if (!bucket) continue;
for (j = 0; j < bucket.length; j++) {
for (j = 0; j < bucket.length && !seenFull; j++) {
var B2 = bucket[j];
if (B2.w === A2.w) continue;
var pk2 = pairKey(A2, B2);
if (seenPair.has(pk2)) continue;
if (seenPair.size >= SEEN_PAIR_LIMIT) {
seenFull = true;
break;
}
seenPair.add(pk2);
var gm = geomFor(A2, B2);
if (gm.dot <= T.dot) continue;
if (gm.lat > T.lat) continue; // opposite carriageway: reject
if (gm.along < T.alongLo || gm.along > T.alongHi) continue;
cands.push({ a: A2, b: B2, s: gm.s });
if (cands.length >= CAND_LIMIT) {
seenFull = true;
break;
}
}
}
}