mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-06 11:24:00 +00:00
fix(street-level): KartaView marker and camera direction; remaining review P4s
Marker and direction (reported on the PR): - KartaView has its own marker, a purple view cone (Street View's is blue), not GEV's default pin that Mapillary uses. - The camera direction (marker, cones, FOLLOW, a panorama's centre) is the direction of travel to the next photo a few metres on. KartaView's heading is the device compass: whole drives read 0 (no compass) and others sit a steady ~110° off. Until the drive loads the compass stands in (0 = unknown), and the pose is sent again once the course is known. Remaining P4s from the review of #1121: - Segment chaining is linear (a per-point cursor) and capped at 20,000 segments a tile and 5,000 points a line: a hostile tile of 60k segments sharing one point took 1.5 s, now tens of ms. - Decoded tiles are dropped when KartaView is switched off. - No network / a refused request says so and is not retried as a timeout; an unreadable answer says so. - A docked flat photo skips the 2,560 px download until the viewer grows. - The panel counts the drive's photos (countActivePhotos), not the thinned page of cones (2,250, not 217). - After a GPU reset the viewer redraws the photo itself, so a lookup the user started is not cancelled; a failure is still reported. - The gate's keyless page lights KartaView and checks it draws with no key; the fixture answers the sequence count; the line-click step checks the camera looks along the drive when the compass says 200°. - README/CHANGELOG show the share-link form the app writes. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
c99eb93174
commit
e9a4dbb062
15 files changed
+588
-63
No files matched your search
@@ -11,6 +11,7 @@ import {
|
||||
PANO_FULL_SIZE,
|
||||
PANO_MID_SIZE,
|
||||
PANO_PREVIEW_SIZE,
|
||||
cameraBearing,
|
||||
kartaViewPhotoUrl,
|
||||
resizedImageUrl,
|
||||
} from './policy.js';
|
||||
@@ -88,6 +89,7 @@ export function panoSizeFor(canvasPixels, fovDeg) {
|
||||
* @param {(photo: object, delta: -1|1) => Promise<string|null>} options.step The photo `delta` along the sequence, or null at its end.
|
||||
* @param {(imageId: string) => void} options.onStep Open the photo ‹ › chose (through the core, so loading and errors show).
|
||||
* @param {(photo: object) => void} [options.onShown] A photo is on screen.
|
||||
* @param {(imageId: string) => void} [options.onReopen] Draw the same photo again after a GPU reset (default: `onStep`).
|
||||
* @param {object} [options.render] Render governor.
|
||||
* @param {(url: string, options?: object) => Promise<HTMLImageElement>} [options.load]
|
||||
* @param {(canvas: HTMLCanvasElement) => object} [options.createRenderer]
|
||||
@@ -98,6 +100,7 @@ export function createKartaViewViewer({
|
||||
step,
|
||||
onStep,
|
||||
onShown = () => {},
|
||||
onReopen = onStep,
|
||||
render,
|
||||
load = loadImage,
|
||||
createRenderer = createPanoramaRenderer,
|
||||
@@ -125,6 +128,8 @@ export function createKartaViewViewer({
|
||||
let restoreView = null;
|
||||
/** Width of the panorama texture on screen (0: the preview). */
|
||||
let panoWidth = 0;
|
||||
/** The flat photo on screen is the 2,560 px version. */
|
||||
let flatSharp = 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. */
|
||||
@@ -139,7 +144,7 @@ export function createKartaViewViewer({
|
||||
function emit() {
|
||||
if (!photo || !showing) return;
|
||||
const view = showing === 'pano' ? renderer.getView() : null;
|
||||
const heading = photo.heading;
|
||||
const heading = cameraBearing(photo);
|
||||
const pose = {
|
||||
providerId: KARTAVIEW_PROVIDER_ID,
|
||||
imageId: photo.id,
|
||||
@@ -257,7 +262,7 @@ export function createKartaViewViewer({
|
||||
const again = photo.id;
|
||||
show(null);
|
||||
openingId = again;
|
||||
onStep(again);
|
||||
onReopen(again);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -471,6 +476,10 @@ export function createKartaViewViewer({
|
||||
if (kind === 'flat' && target.isPano) return;
|
||||
const size = kind === 'pano' ? panoSizeNow() : FLAT_FULL_SIZE;
|
||||
if (kind === 'pano' && size[0] <= panoWidth) return;
|
||||
// A docked viewer shows the 1,280 px version in full: the 2,560 px one
|
||||
// (~0.6 MB a photo) waits until the viewer is bigger than that.
|
||||
if (kind === 'flat' && (flatSharp || flatPixels() <= FLAT_VIEW_SIZE[0]))
|
||||
return;
|
||||
const url =
|
||||
kind === 'pano'
|
||||
? resizedImageUrl(target.urls.pano, size)
|
||||
@@ -483,13 +492,24 @@ export function createKartaViewViewer({
|
||||
if (!renderer || size[0] <= panoWidth) return;
|
||||
renderer.setImage(image);
|
||||
panoWidth = size[0];
|
||||
} else picture.src = image.src;
|
||||
} else {
|
||||
picture.src = image.src;
|
||||
flatSharp = true;
|
||||
}
|
||||
requestRender();
|
||||
} catch {
|
||||
/* the first version stays */
|
||||
}
|
||||
}
|
||||
|
||||
/** Device pixels across the flat photo's frame. */
|
||||
function flatPixels() {
|
||||
const ratio = globalThis.devicePixelRatio || 1;
|
||||
return (
|
||||
Math.max(picture?.clientWidth || 0, picture?.clientHeight || 0) * ratio
|
||||
);
|
||||
}
|
||||
|
||||
/** The sharp panorama this viewer needs now: 2,048 docked, 4,096 expanded. */
|
||||
function panoSizeNow() {
|
||||
const ratio = Math.min(globalThis.devicePixelRatio || 1, 2);
|
||||
@@ -543,6 +563,7 @@ export function createKartaViewViewer({
|
||||
if (!image) throw failure || new Error(LOAD_FAILED);
|
||||
if (seq !== openSeq) return false;
|
||||
picture.src = image.src;
|
||||
flatSharp = false;
|
||||
photo = target;
|
||||
show('flat');
|
||||
return true;
|
||||
@@ -610,9 +631,11 @@ export function createKartaViewViewer({
|
||||
|
||||
resize() {
|
||||
renderer?.resize();
|
||||
// Expanded: a docked viewer's 2,048 px panorama is now too soft.
|
||||
// Expanded: a docked viewer's first version is now too soft.
|
||||
if (showing === 'pano' && photo && panoSizeNow()[0] > panoWidth)
|
||||
upgrade(photo, openSeq, 'pano');
|
||||
if (showing === 'flat' && photo && !flatSharp)
|
||||
upgrade(photo, openSeq, 'flat');
|
||||
},
|
||||
|
||||
/** FIT / FILL frame a flat photo; a panorama has no frame to fit. */
|
||||
@@ -623,6 +646,11 @@ export function createKartaViewViewer({
|
||||
applyRenderMode();
|
||||
},
|
||||
|
||||
/** The photo's direction became known (its drive loaded): pose again. */
|
||||
refreshPose() {
|
||||
emit();
|
||||
},
|
||||
|
||||
onPose(listener) {
|
||||
listeners.add(listener);
|
||||
return () => listeners.delete(listener);
|
||||
|
||||
Reference in new issue
Block a user