lidar-maps : navigation en cache seule et pyramide entretenue en tâche de fond

Sur une petite machine (Raspberry Pi), LIDAR_TILE_CACHE_ONLY sert les tuiles
depuis le cache uniquement (tuile absente = transparente non mémorisable,
X-Tile-Pending) et LIDAR_TILE_BACKGROUND fait surveiller les dalles par un
sondeur : chaque dalle nouvelle ou régénérée par le worker remet sa pyramide
en file, rendue à basse priorité et au ralenti. Scan et état pilotables via
/api/map/background, pré-calcul exhaustif toujours via /api/map/warm.
This commit is contained in:
Antoine Jacquin
2026-09-23 19:05:58 +02:00
parent 053eb2f529
commit 900332cdbc
5 changed files with 416 additions and 10 deletions

View File

@ -325,6 +325,15 @@ def _cell_bounds(col, row):
return (col * 1000.0, (row - 1) * 1000.0, (col + 1) * 1000.0, row * 1000.0)
def cell_bounds_wgs84(col, row):
"""Emprise WGS84 [ouest, sud, est, nord] d'une dalle LHD (4 coins L93)."""
min_x, min_y, max_x, max_y = _cell_bounds(col, row)
xs = (min_x, min_x, max_x, max_x)
ys = (min_y, max_y, min_y, max_y)
lons, lats = _transformer("EPSG:2154", "EPSG:4326").transform(xs, ys)
return (min(lons), min(lats), max(lons), max(lats))
def _dir_mtime(path):
try:
return path.stat().st_mtime
@ -780,6 +789,37 @@ def empty_marker_exists(output_dir, layer, z, x, y, scale=1, fmt="png"):
scale, fmt).with_suffix(".empty").exists()
def cached_tile(output_dir, layer, z, x, y, scale=1, fmt="png"):
"""Tuile depuis le cache UNIQUEMENT — jamais de rendu (mode cache seule).
Retourne ``(data, état)`` :
- ``"fresh"`` : tuile en cache et plus récente que ses dalles sources ;
- ``"empty"`` : aucune source n'intersecte (marqueur `.empty` posé) ;
- ``"pending"``: donnée présente mais tuile absente ou périmée — à rendre
ailleurs (tâche de fond, pré-chauffage), pas au fil de la navigation.
"""
cache = tile_cache_path(output_dir, layer, z, x, y, scale, fmt)
empty = cache.with_suffix(".empty")
sources = _contributing(output_dir, layer, z, x, y, scale)
if not sources:
if not empty.exists():
_write_atomic(empty, b"")
return None, "empty"
if empty.exists():
return None, "empty"
newest = 0.0
for src in sources:
m = src.mtime()
if m and m > newest:
newest = m
try:
if cache.stat().st_mtime >= newest:
return cache.read_bytes(), "fresh"
except OSError:
pass
return None, "pending"
def transparent_tile(scale=1, fmt="png"):
"""Tuile entièrement transparente (zone sans donnée)."""
from PIL import Image