cameras: fix world-zoom bbox collapsing to ~48 pins
All checks were successful
build-and-deploy / build (push) Successful in 2m23s

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.
This commit is contained in:
Sirius DevOps 2026-08-27 15:59:22 -04:00
parent 0c7f80655e
commit 1145ce8ec1
2 changed files with 25 additions and 11 deletions

View file

@ -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()

View file

@ -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)}`;
}