mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 10:53:59 +00:00
fix(street-level): Panoramax IC8 round 2 — shared point budget, selected line, cone cache, DP segments
From the round-2 verification (approve with follow-ups), all follow-ups: - The point budget is shared across the tiles in view once loading settles (water-filling): a sparse tile keeps what it has, a dense city centre takes the rest instead of drawing thinner than its suburbs. The selected sequence is always drawn, and selecting one a cap had left out draws it. - The cones' picture-list cache keeps only finished lists: a re-centre while the cones loaded inherited the aborted load's tiles and drew none in them. - Douglas–Peucker measures to the segment, so dead ends and U-turns keep their far end. - Switching Panoramax off lets its decoded tiles and lists go. - Picture downloads are counted while they stream (a host sending no length cannot fill memory before the cap). - Comments on the via caption and the simplification tolerance match the code. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
1a546bec72
commit
3ae367d0dd
11 files changed
+343
-33
No files matched your search
@@ -76,7 +76,7 @@ function setup(
|
||||
fetchTile: async (tile) => {
|
||||
asked.push(tile);
|
||||
if (fail) throw fail;
|
||||
if (decoded) return decoded(centre);
|
||||
if (decoded) return decoded(centre, tile);
|
||||
return {
|
||||
sequences: [
|
||||
{
|
||||
@@ -247,3 +247,94 @@ test('a point budget skips lines past it, and a shorter one later may still fit'
|
||||
const [tile] = state.coverage.tiles.values();
|
||||
assert.deepEqual([...tile.sequences.keys()], ['three', 'two']);
|
||||
});
|
||||
|
||||
/** A line of `n` points, its id unique to the tile. */
|
||||
function pointsLine(id, n, tile, centre) {
|
||||
return {
|
||||
id,
|
||||
parts: [
|
||||
Array.from({ length: n }, (_, i) => [
|
||||
centre.lon - 0.001 + i * 0.00001,
|
||||
centre.lat,
|
||||
]),
|
||||
],
|
||||
capturedAt: 0,
|
||||
isPano: false,
|
||||
};
|
||||
}
|
||||
|
||||
test('the point budget is shared: a sparse tile keeps its few, a dense one gets the rest', async (t) => {
|
||||
const tuning = {
|
||||
...TUNING,
|
||||
maxTiles: 9,
|
||||
maxSequences: 900,
|
||||
maxPoints: 90,
|
||||
keepOrder: true,
|
||||
};
|
||||
const { state, coverage } = setup(t, {
|
||||
// Street zoom far enough in that several tiles are in view.
|
||||
zoomFor: () => ({ zoom: 18, kind: 'sequence' }),
|
||||
tuning,
|
||||
decoded: (centre, tile) => {
|
||||
const dense = tile.x % 2 === 0 && tile.y % 2 === 0;
|
||||
const lines = dense
|
||||
? Array.from({ length: 30 }, (_, i) =>
|
||||
pointsLine(`d${tile.x}/${tile.y}/${i}`, 5, tile, centre),
|
||||
)
|
||||
: [pointsLine(`s${tile.x}/${tile.y}`, 2, tile, centre)];
|
||||
return { sequences: lines, overview: [] };
|
||||
},
|
||||
});
|
||||
coverage.refresh();
|
||||
assert.ok(
|
||||
await until(
|
||||
() => state.coverage.tiles.size > 1 && !state.coverage.pending.size,
|
||||
),
|
||||
);
|
||||
const entries = [...state.coverage.tiles.values()];
|
||||
const drawn = (entry) => entry.pointsDrawn;
|
||||
const total = entries.reduce((sum, entry) => sum + drawn(entry), 0);
|
||||
assert.ok(total <= tuning.maxPoints, `within the budget: ${total}`);
|
||||
const sparse = entries.filter((entry) => entry.pointDemand === 2);
|
||||
const dense = entries.filter((entry) => entry.pointDemand === 150);
|
||||
assert.ok(sparse.length && dense.length, 'both kinds in view');
|
||||
for (const entry of sparse)
|
||||
assert.equal(drawn(entry), 2, 'a sparse tile keeps all');
|
||||
const fair = Math.floor(tuning.maxPoints / tuning.maxTiles);
|
||||
const left = tuning.maxPoints - sparse.length * 2;
|
||||
for (const entry of dense)
|
||||
assert.ok(
|
||||
drawn(entry) > fair || dense.length * fair >= left,
|
||||
`a dense tile gets more than the even share: ${drawn(entry)}`,
|
||||
);
|
||||
assert.ok(
|
||||
total > tuning.maxPoints - 5 * dense.length,
|
||||
'little budget unused',
|
||||
);
|
||||
});
|
||||
|
||||
test('a selected sequence the budget left out is drawn, highlighted', async (t) => {
|
||||
const { state, coverage } = setup(t, {
|
||||
tuning: {
|
||||
...TUNING,
|
||||
maxTiles: 1,
|
||||
maxSequences: 10,
|
||||
maxPoints: 5,
|
||||
keepOrder: true,
|
||||
},
|
||||
decoded: (centre, tile) => ({
|
||||
sequences: [
|
||||
pointsLine('long', 5, tile, centre),
|
||||
pointsLine('short', 3, tile, centre),
|
||||
],
|
||||
overview: [],
|
||||
}),
|
||||
});
|
||||
coverage.refresh();
|
||||
assert.ok(await until(() => state.coverage.tiles.size === 1));
|
||||
const [tile] = state.coverage.tiles.values();
|
||||
assert.deepEqual([...tile.sequences.keys()], ['long']);
|
||||
state.sequence.selectedId = 'short';
|
||||
coverage.recolorSequence('short', true);
|
||||
assert.deepEqual([...tile.sequences.keys()].sort(), ['long', 'short']);
|
||||
});
|
||||
Reference in new issue
Block a user