From 1145ce8ec1c152a4b4602b74145f849d634c7112 Mon Sep 17 00:00:00 2001 From: Sirius DevOps Date: Thu, 27 Aug 2026 15:59:22 -0400 Subject: [PATCH] cameras: fix world-zoom bbox collapsing to ~48 pins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Leaflet worldCopyJump at zoom 2 reports longitudes outside ±180; clamping them independently produced west>=east or a thin sliver. Low zoom now queries the full world, and the API ignores inverted bboxes. --- app/main.py | 12 +++++++----- app/static/index.html | 24 ++++++++++++++++++------ 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/app/main.py b/app/main.py index 1d7474d..9d5f64d 100644 --- a/app/main.py +++ b/app/main.py @@ -741,11 +741,13 @@ async def list_cameras( if not (-180 <= min_lon <= 180 and -180 <= max_lon <= 180 and -90 <= min_lat <= 90 and -90 <= max_lat <= 90): raise HTTPException(422, "bbox coordinates out of range") - stmt = stmt.where( - and_(cam_table.c.location_lat >= min_lat, - cam_table.c.location_lat <= max_lat, - cam_table.c.location_lon >= min_lon, - cam_table.c.location_lon <= max_lon)) + # Inverted/empty box (wrapped world view) → do not filter. + if min_lon < max_lon and min_lat < max_lat: + stmt = stmt.where( + and_(cam_table.c.location_lat >= min_lat, + cam_table.c.location_lat <= max_lat, + cam_table.c.location_lon >= min_lon, + cam_table.c.location_lon <= max_lon)) if source: stmt = stmt.where(cam_table.c.discovery_source == source) rows = (await session.execute(stmt.limit(limit))).mappings().all() diff --git a/app/static/index.html b/app/static/index.html index 6c6c88d..42e7fcc 100644 --- a/app/static/index.html +++ b/app/static/index.html @@ -941,12 +941,24 @@ function mapResetView() { if (map) map.setView([25, 10], 2); } function currentBBox() { const b = map.getBounds(); - // Clamp to world bounds: at low zoom with worldCopyJump the map spans - // multiple world copies, and /api/cameras rejects coords outside ±180/±90. - const west = Math.max(-180, Math.min(180, b.getWest())); - const east = Math.max(-180, Math.min(180, b.getEast())); - const south = Math.max(-90, Math.min(90, b.getSouth())); - const north = Math.max(-90, Math.min(90, b.getNorth())); + // Leaflet at low zoom / worldCopyJump reports longitudes outside ±180 + // (and west>east after clamping). That made /api/cameras return a tiny + // sliver (~dozens of pins) instead of the full set. + let west = b.getWest(); + let east = b.getEast(); + let south = b.getSouth(); + let north = b.getNorth(); + const lonSpan = east - west; + if (map.getZoom() <= 3 || lonSpan >= 300) { + return '-180.0000,-85.0000,180.0000,85.0000'; + } + west = Math.max(-180, Math.min(180, west)); + east = Math.max(-180, Math.min(180, east)); + south = Math.max(-90, Math.min(90, south)); + north = Math.max(-90, Math.min(90, north)); + if (west >= east) { + return '-180.0000,-85.0000,180.0000,85.0000'; + } return `${west.toFixed(4)},${south.toFixed(4)},${east.toFixed(4)},${north.toFixed(4)}`; }