feat(street-level): KartaView as a third, keyless imagery provider

Coverage lines from KartaView's z13-14 JSON tiles (OSM ways with photos,
chained end to start), the photo nearest a clicked line, cones along its
sequence, and a viewer for flat photos and 360° panoramas (a small WebGL
equirectangular renderer, no new dependency) with ‹ › along the sequence.

Mapillary's camera-driven line coverage and sequence cones move to the
provider-neutral core (lineCoverage.js, sequenceCones.js) with the tile
fetch, zoom ladder, colours and pick prefixes injected; Mapillary keeps
thin wrappers and its tests pass unchanged.

KartaView quirks handled: api.kartaview.org (the documented
api.openstreetcam.org serves empty tiles), photo URLs that name storage1
for photos stored elsewhere, and a photo API that answers 429 to more than
about three requests at once (two in flight, retried with backoff).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Said TurkseverandClaude Opus 5.5 committed 2026-10-13 18:33:14 +01:00
1 parent 9beadbda63
commit cb01014e36
33 files changed
+4046 -1196

No files matched your search

+6 -1
View File
@@ -15,7 +15,8 @@ export const PANEL_WORKER_PRELUDE_PATH = 'cesium/worker-prelude.js';
/**
* Sites the app's browser code loads from directly: map imagery, 3D tiles,
* terrain, fonts, and Street Level's Mapillary Graph API and image CDN (its
* coverage tiles come through the app's server). Everything from the app's
* coverage tiles come through the app's server), Google Street View and
* KartaView. Everything from the app's
* own server comes through the MCP server.
*/
const PROVIDER_ORIGINS = Object.freeze([
@@ -44,6 +45,10 @@ const PROVIDER_ORIGINS = Object.freeze([
'https://*.ggpht.com',
// Mapillary photos come from regional hosts, e.g. scontent-man2-1.xx.fbcdn.net.
'https://*.xx.fbcdn.net',
// KartaView's API, its image proxy and its photo storage (storage1…storage13).
'https://api.kartaview.org',
'https://cdn.kartaview.org',
'https://*.openstreetcam.org',
]);
export const MCP_APP_MIME_TYPE = 'text/html;profile=mcp-app';