mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-06 03:14:00 +00:00
fix(street-level): KartaView review P2s; budget the gate's pick search
- Viewer: resizes while a sharper photo loads start no second load (the last size is looked at once it lands); decoded bitmaps nobody will draw (an overtaken preview or upgrade) are closed. - Cones: a photo opened while the drive's first page loads is the one they centre on. - A sequence page that lands while a lost WebGL context recovers keeps its cones: no pose is emitted without a renderer, and a viewer error never rejects page data. - Source: an answer turned away unread (HTTP error, 429, length past the cap) aborts its request and cancels its body, freeing the connection. - Gate: findPickPoint no longer picks each centre five times at radius 0, aims step 13's cone pick at the drawn billboards, and caps each evaluation at 4 s, resuming from a cursor on the next poll, so a slow machine cannot spend a whole wait in one evaluation. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
e9a4dbb062
commit
04b3231534
7 files changed
+350
-30
No files matched your search
@@ -73,6 +73,11 @@ async function loadBitmap(url, timeoutMs) {
|
||||
}
|
||||
}
|
||||
|
||||
/** Free a decoded bitmap nobody will draw (an <img> has nothing to free). */
|
||||
function release(image) {
|
||||
image?.close?.();
|
||||
}
|
||||
|
||||
/** The panorama size a canvas this wide can show sharply at this field of view. */
|
||||
export function panoSizeFor(canvasPixels, fovDeg) {
|
||||
const needed = (Math.max(1, canvasPixels) * 360) / Math.max(1, fovDeg);
|
||||
@@ -130,6 +135,10 @@ export function createKartaViewViewer({
|
||||
let panoWidth = 0;
|
||||
/** The flat photo on screen is the 2,560 px version. */
|
||||
let flatSharp = false;
|
||||
/** The sharper version loading ({seq, kind}): a resize starts no second one. */
|
||||
let upgrading = null;
|
||||
/** A resize came while it loaded: look again once it lands. */
|
||||
let upgradeAgain = false;
|
||||
/** The photo an open is fetching: ‹ › step on from it, not the old one. */
|
||||
let openingId = null;
|
||||
/** ‹ › chose this photo: keep the panorama's look direction for it. */
|
||||
@@ -143,6 +152,9 @@ export function createKartaViewViewer({
|
||||
|
||||
function emit() {
|
||||
if (!photo || !showing) return;
|
||||
// A lost GPU context, still being recovered: the open that redraws the
|
||||
// panorama poses once it is on screen.
|
||||
if (showing === 'pano' && !renderer) return;
|
||||
const view = showing === 'pano' ? renderer.getView() : null;
|
||||
const heading = cameraBearing(photo);
|
||||
const pose = {
|
||||
@@ -485,20 +497,40 @@ export function createKartaViewViewer({
|
||||
? resizedImageUrl(target.urls.pano, size)
|
||||
: resizedImageUrl(target.urls.full, size);
|
||||
if (!url) return;
|
||||
// Resizes come in bursts while the panel animates: one load at a time
|
||||
// for this photo, and one more look once it lands.
|
||||
if (upgrading?.seq === seq && upgrading.kind === kind) {
|
||||
upgradeAgain = true;
|
||||
return;
|
||||
}
|
||||
const pending = (upgrading = { seq, kind });
|
||||
upgradeAgain = false;
|
||||
let image = null;
|
||||
try {
|
||||
const image = await load(url, { crossOrigin: kind === 'pano' });
|
||||
image = await load(url, { crossOrigin: kind === 'pano' });
|
||||
if (seq !== openSeq || photo !== target || showing !== kind) return;
|
||||
if (kind === 'pano') {
|
||||
if (!renderer || size[0] <= panoWidth) return;
|
||||
renderer.setImage(image);
|
||||
image = null;
|
||||
panoWidth = size[0];
|
||||
} else {
|
||||
picture.src = image.src;
|
||||
image = null;
|
||||
flatSharp = true;
|
||||
}
|
||||
requestRender();
|
||||
} catch {
|
||||
/* the first version stays */
|
||||
} finally {
|
||||
release(image);
|
||||
if (upgrading === pending) {
|
||||
upgrading = null;
|
||||
if (upgradeAgain && seq === openSeq && photo === target) {
|
||||
upgradeAgain = false;
|
||||
upgrade(target, seq, showing);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -524,10 +556,16 @@ export function createKartaViewViewer({
|
||||
resizedImageUrl(target.urls.pano, PANO_PREVIEW_SIZE),
|
||||
{ crossOrigin: true },
|
||||
);
|
||||
if (seq !== openSeq) return false;
|
||||
if (seq !== openSeq) {
|
||||
release(image);
|
||||
return false;
|
||||
}
|
||||
// The context may have been lost while this loaded: build on the new
|
||||
// canvas, or let the caller show the front view.
|
||||
if (!ensureRenderer()) throw new Error(LOAD_FAILED);
|
||||
if (!ensureRenderer()) {
|
||||
release(image);
|
||||
throw new Error(LOAD_FAILED);
|
||||
}
|
||||
const restore = restoreView?.id === target.id ? restoreView.view : null;
|
||||
restoreView = null;
|
||||
if (restore) renderer.setView(restore);
|
||||
|
||||
Reference in new issue
Block a user