car: cap road chain stitching to avoid Set overflow
This commit is contained in:
1 parent
03ae45e0e5
commit
4ac48b188a
1 file changed
+31
-4
Vendored
+31
-4
@@ -4485,6 +4485,22 @@ function carMergeChains(polys, cfg) {
|
|||||||
eps.push(r);
|
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)
|
// canonical numeric key for an endpoint pair (way index + end side)
|
||||||
function pairKey(A, B) {
|
function pairKey(A, B) {
|
||||||
var x = A.w * 2 + A.e, y = B.w * 2 + B.e;
|
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 T = TIERS[t];
|
||||||
var cands = candsByTier[t];
|
var cands = candsByTier[t];
|
||||||
var seenPair = new Set();
|
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);
|
if ((i & 8191) === 8191) geoProgress('join tier ' + t, i, eps.length);
|
||||||
var A2 = eps[i];
|
var A2 = eps[i];
|
||||||
var gx = Math.floor(A2.x / NEAR), gz = Math.floor(A2.z / NEAR);
|
var gx = Math.floor(A2.x / NEAR), gz = Math.floor(A2.z / NEAR);
|
||||||
for (var ox = -1; ox <= 1; ox++) {
|
for (var ox = -1; ox <= 1 && !seenFull; ox++) {
|
||||||
for (var oz = -1; oz <= 1; oz++) {
|
for (var oz = -1; oz <= 1 && !seenFull; oz++) {
|
||||||
var bucket = grid.get((gx + ox) + '_' + (gz + oz));
|
var bucket = grid.get((gx + ox) + '_' + (gz + oz));
|
||||||
if (!bucket) continue;
|
if (!bucket) continue;
|
||||||
for (j = 0; j < bucket.length; j++) {
|
for (j = 0; j < bucket.length && !seenFull; j++) {
|
||||||
var B2 = bucket[j];
|
var B2 = bucket[j];
|
||||||
if (B2.w === A2.w) continue;
|
if (B2.w === A2.w) continue;
|
||||||
var pk2 = pairKey(A2, B2);
|
var pk2 = pairKey(A2, B2);
|
||||||
if (seenPair.has(pk2)) continue;
|
if (seenPair.has(pk2)) continue;
|
||||||
|
if (seenPair.size >= SEEN_PAIR_LIMIT) {
|
||||||
|
seenFull = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
seenPair.add(pk2);
|
seenPair.add(pk2);
|
||||||
var gm = geomFor(A2, B2);
|
var gm = geomFor(A2, B2);
|
||||||
if (gm.dot <= T.dot) continue;
|
if (gm.dot <= T.dot) continue;
|
||||||
if (gm.lat > T.lat) continue; // opposite carriageway: reject
|
if (gm.lat > T.lat) continue; // opposite carriageway: reject
|
||||||
if (gm.along < T.alongLo || gm.along > T.alongHi) continue;
|
if (gm.along < T.alongLo || gm.along > T.alongHi) continue;
|
||||||
cands.push({ a: A2, b: B2, s: gm.s });
|
cands.push({ a: A2, b: B2, s: gm.s });
|
||||||
|
if (cands.length >= CAND_LIMIT) {
|
||||||
|
seenFull = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user