mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
fix(street-level): address gekh's review of #768
P0 - tileMath: lonToTileX(180) wrapped to column 0, so a whole-world view at z1 loaded only the western column; 180 is now the last column. - coverage.loadTile: a superseded request (after a retire or clear) still deleted the newer request's pending entry and loading count in `finally`, letting a duplicate load attach lines that nothing could remove. Only the request that still owns the key attaches its tile or settles the key. P1 - view/tileMath: a view across the date line read as a ~358 deg box and loaded tiles on the far side of the globe. visibleBbox now returns west > east for such views and tilesForBbox splits them at +/-180; viewCentre averages across the line. - decode: the parts of a multi-line sequence were joined into one line, drawing straight segments over capture gaps. Each part is now its own line (`parts`); later parts carry `~n` in their pick id, and picking or recolouring any part acts on the whole sequence. - viewerHost: a prewarmed MapillaryJS viewer was never destroyed, leaking its WebGL context. Prewarmed adapters are tracked and released on unmount, at once when the layer went off mid-load, and per provider when only that provider is switched off. - nearestImage took the first record the API returned; it now takes the closest one that passes the filter. P2 - groundCast: the cache was cleared after a request counted its corners, dropping ones it relied on; it is now cleared first. - streetLevelControls: the viewer was resized on every render (every frame while a panorama is dragged); the ResizeObserver handles size changes and the viewer is resized once when it opens. The legend now rebuilds when its entries change, not only their count. - panelPositionControls: the portable-panel paths this PR added called the CCTV viewport sync directly; they go through onPanelResized, which the shell routes to CCTV. The "Compose camera panel controls" JSDoc is back on _initCctvPanel. New tests: zoom-1 columns, date-line tiles and bbox, multi-part decode and part pick ids, nearest image, prewarmed viewer release, and the cache ordering (fails on the old order). Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
514788303d
commit
a1f8d6ca25
17 files changed
+435
-117
No files matched your search
@@ -5,8 +5,20 @@ import { decodeCoverageTile } from './decode.js';
|
||||
|
||||
const zigzag = (value) => (value << 1) ^ (value >> 31);
|
||||
|
||||
/** One line part: MoveTo the first point, LineTo the rest (relative). */
|
||||
function linePart(points) {
|
||||
const out = [9, zigzag(points[0][0]), zigzag(points[0][1])];
|
||||
out.push(((points.length - 1) << 3) | 2);
|
||||
for (let i = 1; i < points.length; i++)
|
||||
out.push(
|
||||
zigzag(points[i][0] - points[i - 1][0]),
|
||||
zigzag(points[i][1] - points[i - 1][1]),
|
||||
);
|
||||
return out;
|
||||
}
|
||||
|
||||
/** A minimal mly1_public-shaped tile: one sequence line and one overview point. */
|
||||
function sampleTile() {
|
||||
function sampleTile({ geometry = null } = {}) {
|
||||
const writer = new PbfWriter();
|
||||
writer.writeMessage(
|
||||
3,
|
||||
@@ -37,14 +49,17 @@ function sampleTile() {
|
||||
feature.writeVarintField(1, 7);
|
||||
feature.writePackedVarint(2, [0, 0, 1, 1, 2, 2]);
|
||||
feature.writeVarintField(3, 2); // LineString
|
||||
feature.writePackedVarint(4, [
|
||||
9,
|
||||
zigzag(100),
|
||||
zigzag(100), // MoveTo
|
||||
10,
|
||||
zigzag(200),
|
||||
zigzag(200), // LineTo ×1
|
||||
]);
|
||||
feature.writePackedVarint(
|
||||
4,
|
||||
geometry || [
|
||||
9,
|
||||
zigzag(100),
|
||||
zigzag(100), // MoveTo
|
||||
10,
|
||||
zigzag(200),
|
||||
zigzag(200), // LineTo ×1
|
||||
],
|
||||
);
|
||||
},
|
||||
null,
|
||||
);
|
||||
@@ -86,8 +101,9 @@ test('sequences and overview points decode into lon/lat records', () => {
|
||||
assert.equal(sequence.id, 'seq-42');
|
||||
assert.equal(sequence.capturedAt, 1_700_000_000);
|
||||
assert.equal(sequence.isPano, true);
|
||||
assert.equal(sequence.coordinates.length, 2);
|
||||
const [[lon0, lat0], [lon1, lat1]] = sequence.coordinates;
|
||||
assert.equal(sequence.parts.length, 1);
|
||||
assert.equal(sequence.parts[0].length, 2);
|
||||
const [[lon0, lat0], [lon1, lat1]] = sequence.parts[0];
|
||||
assert.ok(
|
||||
lon0 > -180 && lon0 < 0 && lon1 > lon0,
|
||||
'west half of tile 0/0 at z1',
|
||||
@@ -110,3 +126,35 @@ test('an empty tile decodes to empty lists', () => {
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test('a sequence with a capture gap keeps its parts as separate lines', () => {
|
||||
// Two parts with a gap between (300,300) and (1000,1000); the second part's
|
||||
// MoveTo is relative to the end of the first, as in the MVT encoding.
|
||||
const first = [
|
||||
[100, 100],
|
||||
[300, 300],
|
||||
];
|
||||
const second = [
|
||||
[700, 700],
|
||||
[900, 700],
|
||||
];
|
||||
const geometry = [
|
||||
...linePart(first),
|
||||
9,
|
||||
zigzag(second[0][0] - first[1][0]),
|
||||
zigzag(second[0][1] - first[1][1]),
|
||||
((second.length - 1) << 3) | 2,
|
||||
zigzag(second[1][0] - second[0][0]),
|
||||
zigzag(second[1][1] - second[0][1]),
|
||||
];
|
||||
const [sequence] = decodeCoverageTile(sampleTile({ geometry }), {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 1,
|
||||
}).sequences;
|
||||
assert.equal(sequence.parts.length, 2);
|
||||
assert.equal(sequence.parts[0].length, 2);
|
||||
assert.equal(sequence.parts[1].length, 2);
|
||||
// No part ends where the next begins: the gap is not bridged.
|
||||
assert.notDeepEqual(sequence.parts[0].at(-1), sequence.parts[1][0]);
|
||||
});
|
||||
Reference in new issue
Block a user