Commit Graph
8 Commits
Author SHA1 Message Date
German KhokhlovandClaude Opus 5.5 6390a3346f Merge origin/main: Google Street View, KartaView and Panoramax on the slim Street Level
Main gained three imagery providers (Google Street View, KartaView,
Panoramax), shared line-coverage, cone and photo-viewer modules, one source
lit at a time and the translated interface. Their shared modules still
carried what this branch removes, so the merge ports them onto it:

- lineCoverage.js is this branch's coverage.js made provider-neutral
  (draped lines near the ground only, the selection drawn over them, key
  and rate-limit blocking); sequenceCones.js is sequences.js the same way.
  Mapillary, KartaView and Panoramax all build on them; Mapillary moves
  back to providers/mapillary/ beside the others.
- No ground casting, mesh sampling, surface modes, FOLLOW, legend, prewarm,
  orbit overview points (Panoramax's density dots included), stale-tile
  swaps or water-filled point budget come back.
- Kept from main because the new providers need them: requiresMapStack and
  attachMapStackController (Street View on Google 3D only), ground clicks,
  openNearest with an optional provider nearestImage, openImage {frame},
  reportError, the view-cone marker (now an SVG glyph), filters /
  coverageLabel / sinceBasis, OPEN STREET VIEW, keyAlternatives and i18n.
- photoViewer.js treats the viewer as expanded when its wrap is full screen
  or the iPhone popover, as EXPAND now is.
- The fixture browser gate keeps its 8 steps and adds one each for
  KartaView and Panoramax; catalogs, docs, boundaries and format scope
  follow.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-19 13:51:45 +04:00
German KhokhlovandClaude Opus 5.5 7fd1dd867f Merge origin/main: Panoramax, bikeshare Norway/Detroit, cloud filter strength, Overpass cache
Conflicts:
- KartaView viewer moved into the shared photoViewer.js on main; its
  labels now take the provider name ("{name} street-level photo") and
  are translated there.
- Weather: main's cloud filter strength slider, with its labels in t().
- Street Level caption: translated creator line plus main's licence.

Panoramax status and error texts are marked like KartaView's, and
"Panoramax answered HTTP {status}" gets a template in the panel and the
layer row. Catalogs: es/ru 2553 messages each, complete.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-16 00:06:45 +04:00
Said TurkseverandClaude Opus 5.5 b645a767c8 Street Level: Panoramax review follow-ups (gekh, #1134)
Image loading (photoViewer.js)
- One AbortController per open: a new open, close or unmount stops the
  previous photo's first and sharper downloads (an <img> by src = '').
  A collapsed viewer never falls back to the original; Panoramax's flat
  fallback is the thumbnail. A superseded open resolves quietly.
- Flat HD tracked as "loading" and "shown" apart: a discarded response no
  longer blocks later upgrades, and resizes while it loads ask once.
- No upgrade of the photo still shown while another opens.
- Size limits before decoding: imageSize.js reads JPEG/PNG/WebP/GIF
  headers; more than 64 MP or 16,384 px a side is refused undecoded, an
  <img> that decodes larger is refused and let go, flat HD needs a known
  width of at most 8,192 px, and panoramas always decode with a resize.

Panoramax provider
- Retry-After parsed as seconds or an HTTP date; the browser cannot read
  it here, so busy answers back off 5 s doubling to 300 s, reset once
  answered.
- Headers timed, then the body by an idle timeout (15 s of silence), so a
  slow link still gets its megabyte tiles.
- Cones centre only on the picture shown (onShowing), never on a late
  lookup; lookups nobody waits for are aborted (shared, refcounted).
- onReopen: a GPU reset redraws in the viewer, not through the core.
- Cones draw the home z15 tile at once and add neighbours as they arrive;
  a neighbour that failed is not counted as drawn.
- Coverage tiles decode in ~8 ms slices (a 2 MB z10 tile over Paris was
  one ~85-200 ms task); sorted by measured length without a Map.
- Box search asks for 20, not 100 (the API returns them nearest first).
- looksLikeEmail checks every '@'; creatorOf de-duplicates with a Set.

lineCoverage.js
- A redraw while a swap still builds keeps what is on screen (the swap's
  old lines and its ready new ones) and drops only the unready ones.

Tests for each (mutation-checked), two vacuous tests made real, the
cones' pictures lane and readable()'s busy/timeout paths covered; the
fixture's box search is nearest first. Docs: README filters and share
links, CHANGELOG HD wording, CURRENT-STATE.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 16:55:59 +01:00
Said TurkseverandClaude Opus 5.5 3ae367d0dd 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]>
2026-10-14 15:39:10 +01:00
Said TurkseverandClaude Opus 5.5 cf502429a3 fix(street-level): Panoramax IC8 review — line geometry budget, caches, attribution, tests
From a five-lens IC8 review (correctness, security, tests with mutation
testing, performance, UX):
- P0: over Paris at 12–60 km the unsimplified z10–z12 lines sent ~2M
  points to Cesium's ground-polyline builder (gigabytes of geometry; the
  tab hung). decode.js now simplifies lines (Douglas–Peucker, 4 tile
  units: 6–10% of the points), and lineCoverage gains an opt-in point
  budget (`maxPoints`, 10,000 a tile for Panoramax).
- Decoded coverage tiles are kept (KartaView's tile cache moves to the
  shared tileCache.js); a sequence's z15 picture lists are kept and load
  on their own connection; cones know their tiles from the start of a
  load, so a picture opening meanwhile re-centres them and ‹ › no longer
  restarts the load.
- The HD panorama loads only for the expanded viewer (a docked one on a
  dense screen asked for 3 MB originals) and is aborted when another
  photo opens; picture files over 48 MB or 16,384 px are refused; a
  bitmap no renderer took after a context loss is closed.
- A nearest lookup survives one of its two searches failing; only a
  timeout is retried; offline reads as unreachable; Retry-After is
  capped at five minutes; the search box stays on the map at ±180°;
  cones near both edges of a narrow (high-latitude) tile read both.
- Every producer is credited (app and photographer); with none to name,
  the caption says "via <instance>" rather than crediting the host.
- Esc anywhere in the docked viewer (toolbar, caption) clears the
  sequence before the panel takes it. A filter that hides every density
  dot says so; wording aligned ("coverage", "photo").
- Tests for every surviving mutant (Esc consumed, keepOrder and dot-size
  wiring, licence in the core, limiter aborts, radius floor, bbox corner,
  first-producer-only, byte and size caps), a limiter test, and a gate
  fixture that answers box searches and leaves out pictures facing away;
  the gate now clicks over the other sequence's pictures, so only the
  line click's own-sequence lookup can pass.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 15:24:13 +01:00
Said TurkseverandClaude Opus 5.5 5526666894 fix(street-level): Panoramax UX QA — connection budget, coverage to 60 km, Esc, attribution
From a UX QA round in the browser against the live API:
- A line click could time out while coverage loaded: the meta-catalogue
  speaks HTTP/1.1 only (six connections), and six tiles plus four
  searches queued the lookup behind megabyte tiles. Tiles now take
  three connections and searches two; a search that timed out is asked
  once more.
- Between 30 and ~100 km Paris read as empty: the density grid is ~10 km
  a cell. Lines now draw to 60 km (z10), as Mapillary's do; above, dots
  grow with the pictures they stand for.
- Esc in the docked viewer collapsed the whole panel instead of clearing
  the sequence the panel says it clears (shared photo viewer: KartaView
  too). The viewer now offers Esc to the provider first; expanded, the
  dialog keeps it.
- A picture whose producer is an email address is credited to the
  instance holding it (its `via` host), so Licence Ouverte pictures name
  their source.
- Empty states say why: "no Panoramax photos here match the filters"
  when the filter hid every line, and nothing to zoom into over empty
  sea. Wording follows KartaView's ("photos", "click a line for its
  nearest photo").

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 14:37:45 +01:00
Said TurkseverandClaude Opus 5.5 bce3044e0c fix(street-level): Panoramax functional QA — nearest lookup, line cap order, hostile data
From an adversarial functional QA round against the live API:
- The nearest lookup missed pictures looking away from the click
  (place_position leaves them out at any tolerance): it now runs a
  bounding-box search beside it and ranks both by distance. A line
  clicked from high up searches its sequence within height / 100
  (50–400 m).
- The per-tile line cap kept the newest sequences, not the longest
  (lineCoverage re-sorted them): providers can now keep their decoded
  order (`keepOrder`).
- A long producer name froze the tab (quadratic email regex): linear
  check. A malformed link escape no longer fails the lookup; null or
  string coordinates no longer land at 0,0.
- A line with no camera type or day stays drawn under the filters.
- A sky click on a line changes nothing (as KartaView), instead of
  selecting a sequence with no cones.
- An unreadable tile reads as such; a failed neighbour z15 tile only
  thins the cones; unknown or refused ids say the picture is gone.
- Shared viewer: the sharp-panorama guard is per open (a late download
  of the previous photo no longer lets a second one start); an HD-only
  360° picture is shrunk or skipped like any original; panorama.js read
  the bitmap size after closing it, so 2:1 power-of-two panoramas
  clamped instead of wrapping.
- Tests for each, and for the gaps mutation testing found (preferred
  point, cone order, no reload within drawn tiles, newest-first gate,
  stale bitmap release, flat upgrade retry).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 13:34:25 +01:00
Said TurkseverandClaude Opus 5.5 00d2b73b6a feat(street-level): Panoramax as a fourth, keyless imagery provider
Panoramax, the open federated street-level commons, registers beside
Mapillary, Google Street View and KartaView. Its meta-catalogue
(api.panoramax.xyz) is keyless and CORS-open, so it runs in the browser:

- coverage from its vector tiles: sequence lines at z11–14 below 30 km
  (longest first under the per-tile cap), and above that the grid layer's
  density cells as binned points, not counted as sequences;
- a click on a line opens that sequence's picture nearest the click
  (STAC search, any direction), without moving the camera, then any
  sequence's if it has none within 50 m; the 360° and since filters go to
  the lines and to the API;
- cones from the z15 tiles' pictures layer around the open picture
  (~110 bytes a picture, against ~7.5 kB for a STAC item), re-centred when
  a picture opens outside them; ‹ › follow the picture's prev/next links;
- the caption names the author (not an account named by an email
  address) and the picture's licence (StreetPose `license`), and links to
  the picture in the Panoramax viewer; the globe credits Panoramax.

KartaView's viewer becomes the shared photoViewer.js (flat <img>, 360° on
panorama.js, ‹ ›, keyboard, pinch, context loss), driven by a per-provider
PhotoSources table; the request limiter moves to limiter.js. Panoramax shows
the 2,048 px SD derivative and fetches the HD original only when the viewer
is wide enough, once, shrunk while it decodes (never above 8,192 px).

Orange #ff6f00 (Panoramax's own), off by default, share option
0.m.0_0.r.panoramax-1. The MCP panel allows the meta-catalogue and the
biggest instances. Tests: policy, decode, source, viewer, provider, and a
Panoramax fixture in the hermetic browser gate.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 13:10:40 +01:00