Panéau et couches par défaut limités aux 4 couches conservées
La carte ne conserve que Pente, Aspect, Openness positive et Rugosité : PANEL_VIZ est restreint à DEFAULT_LAYERS, le sélecteur de génération suit le panneau, et ces 4 couches sont allumées par défaut via default_layers (index.html + index_tiles.json). Les autres couches ne sont plus ni affichées ni proposées.
This commit is contained in:
@ -198,13 +198,21 @@ VIZ_LEGENDS = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
# Couche activée par défaut à l'ouverture de la carte.
|
# Couches activées par défaut à l'ouverture de la carte : seules celles-ci
|
||||||
DEFAULT_VIZ = 'hillshade_multi'
|
# sont allumées, toutes les autres sont désactivées (mais restent accessibles
|
||||||
|
# via le panneau). Ordre = pile basse → haute.
|
||||||
|
DEFAULT_LAYERS = ('slope', 'aspect', 'positive_openness', 'roughness')
|
||||||
|
|
||||||
# Restriction optionnelle du panneau de couches : None = proposer toutes
|
# Couche « principale » (mise en avant ; index_tiles.json + affichage en
|
||||||
# les visualisations présentes sur disque (aucune restriction). Le sélecteur
|
# direct de la webapp).
|
||||||
# de génération/régénération est piloté par le même registre (voir _render_html).
|
DEFAULT_VIZ = DEFAULT_LAYERS[0]
|
||||||
PANEL_VIZ = None
|
|
||||||
|
# Restriction du panneau de couches : seule la sélection DEFAULT_LAYERS est
|
||||||
|
# proposée (couches conservées ; les autres ne sont plus ni affichées ni
|
||||||
|
# référencées). None = toutes les visualisations présentes sur disque.
|
||||||
|
# Le sélecteur de génération/régénération est piloté par le même registre
|
||||||
|
# (voir _render_html).
|
||||||
|
PANEL_VIZ = DEFAULT_LAYERS
|
||||||
|
|
||||||
# Correspondance mot-clé de fichier de sortie → nom d'étape --only du pipeline
|
# Correspondance mot-clé de fichier de sortie → nom d'étape --only du pipeline
|
||||||
# (les trois visualisations dont le nom de sortie diffère du nom d'étape,
|
# (les trois visualisations dont le nom de sortie diffère du nom d'étape,
|
||||||
@ -224,6 +232,16 @@ def step_to_keyword(step):
|
|||||||
return STEP_TO_KEYWORD.get(step, step)
|
return STEP_TO_KEYWORD.get(step, step)
|
||||||
|
|
||||||
|
|
||||||
|
def default_layers_present(all_viz_keys):
|
||||||
|
"""Couches activées par défaut (DEFAULT_LAYERS) présentes sur le disque.
|
||||||
|
|
||||||
|
Ordre conservé (DEFAULT_LAYERS) ; sert de base à l'état initial du
|
||||||
|
panneau (toutes les autres couches sont désactivées).
|
||||||
|
"""
|
||||||
|
present = set(all_viz_keys)
|
||||||
|
return [v for v in DEFAULT_LAYERS if v in present]
|
||||||
|
|
||||||
|
|
||||||
def cells_with_all_viz(vis_dir, viz_keys, resolutions=(0.5,)):
|
def cells_with_all_viz(vis_dir, viz_keys, resolutions=(0.5,)):
|
||||||
"""Cellules (col, row) disposant de TOUTES les visualisations demandées.
|
"""Cellules (col, row) disposant de TOUTES les visualisations demandées.
|
||||||
|
|
||||||
@ -1061,7 +1079,9 @@ def build_index(output_dir, output_format='avif'):
|
|||||||
(output_dir / 'index_tiles.json').write_text(json.dumps({
|
(output_dir / 'index_tiles.json').write_text(json.dumps({
|
||||||
'tiles': display_tiles,
|
'tiles': display_tiles,
|
||||||
'viz_meta': {k: {'label': VIZ_LABELS.get(k, k)} for k in ordered_viz},
|
'viz_meta': {k: {'label': VIZ_LABELS.get(k, k)} for k in ordered_viz},
|
||||||
'stats': {'default_viz': default_viz, 'n_tiles': len(display_tiles)},
|
'stats': {'default_viz': default_viz,
|
||||||
|
'default_layers': default_layers_present(all_viz_keys),
|
||||||
|
'n_tiles': len(display_tiles)},
|
||||||
}, ensure_ascii=False), encoding='utf-8')
|
}, ensure_ascii=False), encoding='utf-8')
|
||||||
|
|
||||||
_write_assets(output_dir)
|
_write_assets(output_dir)
|
||||||
@ -1129,13 +1149,15 @@ def _render_html(tiles, global_bbox, all_viz_keys, output_format):
|
|||||||
|
|
||||||
tiles_json = json.dumps(tiles, ensure_ascii=False)
|
tiles_json = json.dumps(tiles, ensure_ascii=False)
|
||||||
|
|
||||||
# Options du sélecteur de génération/régénération : TOUTES les couches du
|
# Options du sélecteur de génération/régénération : les couches du panneau
|
||||||
# registre (mêmes libellés que le panneau ; valeurs = noms d'étapes --only
|
# (PANEL_VIZ si restreint, sinon le registre complet — mêmes libellés,
|
||||||
# du pipeline), y compris celles absentes du disque — pour pouvoir les
|
# valeurs = noms d'étapes --only du pipeline), y compris celles absentes
|
||||||
# générer. Toutes pré-sélectionnées : une régénération refait la dalle
|
# du disque — pour pouvoir les générer. Toutes pré-sélectionnées : une
|
||||||
# complète, l'utilisateur pouvant désélectionner pour cibler.
|
# régénération refait la dalle complète, l'utilisateur pouvant
|
||||||
gen_keys = [v for v in _VIZ_FALLBACK_ORDER if v in VIZ_LABELS]
|
# désélectionner pour cibler.
|
||||||
gen_keys += sorted(k for k in VIZ_LABELS if k not in gen_keys)
|
gen_base = PANEL_VIZ if PANEL_VIZ is not None else VIZ_LABELS
|
||||||
|
gen_keys = [v for v in _VIZ_FALLBACK_ORDER if v in gen_base]
|
||||||
|
gen_keys += sorted(k for k in gen_base if k not in gen_keys)
|
||||||
gen_viz_options = "\n".join(
|
gen_viz_options = "\n".join(
|
||||||
f' <option value="{KEYWORD_TO_STEP.get(v, v)}" selected>'
|
f' <option value="{KEYWORD_TO_STEP.get(v, v)}" selected>'
|
||||||
f'{VIZ_LABELS.get(v, v)}</option>'
|
f'{VIZ_LABELS.get(v, v)}</option>'
|
||||||
@ -1146,7 +1168,10 @@ def _render_html(tiles, global_bbox, all_viz_keys, output_format):
|
|||||||
for k in ordered_viz
|
for k in ordered_viz
|
||||||
}, ensure_ascii=False)
|
}, ensure_ascii=False)
|
||||||
|
|
||||||
stats_json = json.dumps({'default_viz': default_viz, 'n_tiles': len(tiles)},
|
stats_json = json.dumps(
|
||||||
|
{'default_viz': default_viz,
|
||||||
|
'default_layers': default_layers_present(all_viz_keys),
|
||||||
|
'n_tiles': len(tiles)},
|
||||||
ensure_ascii=False)
|
ensure_ascii=False)
|
||||||
|
|
||||||
n_tiles = len(tiles)
|
n_tiles = len(tiles)
|
||||||
@ -1855,10 +1880,17 @@ const LS_KEY = 'lidarLayers_v1';
|
|||||||
|
|
||||||
function defaultLayers() {
|
function defaultLayers() {
|
||||||
const order = Object.keys(VIZ_META);
|
const order = Object.keys(VIZ_META);
|
||||||
const base = STATS.default_viz && VIZ_META[STATS.default_viz]
|
// Couches activées par défaut : seules celles-ci sont allumées, toutes les
|
||||||
? STATS.default_viz : order[0];
|
// autres sont désactivées (mais restent accessibles via le panneau). Repli
|
||||||
|
// sur la couche « principale » (default_viz) si la liste n'est pas fournie
|
||||||
|
// (index ancien) ; sinon la première couche disponible.
|
||||||
|
const list = (Array.isArray(STATS.default_layers) && STATS.default_layers.length)
|
||||||
|
? STATS.default_layers
|
||||||
|
: ((STATS.default_viz && VIZ_META[STATS.default_viz])
|
||||||
|
? [STATS.default_viz] : [order[0]]);
|
||||||
|
const onSet = new Set(list.filter(k => VIZ_META[k]));
|
||||||
const on = {}, opacity = {};
|
const on = {}, opacity = {};
|
||||||
for (const k of order) { on[k] = (k === base); opacity[k] = 1; }
|
for (const k of order) { on[k] = onSet.has(k); opacity[k] = 1; }
|
||||||
return { order, on, opacity, osm: { on: true, opacity: 0.85, dark: true } };
|
return { order, on, opacity, osm: { on: true, opacity: 0.85, dark: true } };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -237,17 +237,18 @@ def test_build_index_generates_html(tmp_path):
|
|||||||
assert (assets / "app.css").read_text(encoding='utf-8').startswith('/*')
|
assert (assets / "app.css").read_text(encoding='utf-8').startswith('/*')
|
||||||
app_js = (assets / "app.js").read_text(encoding='utf-8')
|
app_js = (assets / "app.js").read_text(encoding='utf-8')
|
||||||
assert "Couches" in app_js or "layers" in app_js
|
assert "Couches" in app_js or "layers" in app_js
|
||||||
# Barre de génération : sélecteur proposant TOUTES les couches du registre
|
# Barre de génération : sélecteur restreint au panneau (PANEL_VIZ =
|
||||||
# (valeurs = noms d'étapes --only), y compris celles absentes du panneau
|
# DEFAULT_LAYERS ; valeurs = noms d'étapes --only). Les couches hors
|
||||||
# (svf, hillshade) pour pouvoir les générer. La sélection est envoyée à
|
# panneau (svf, hillshade, wavelet) ne sont plus proposées.
|
||||||
# /api/preview (détection des tuiles incomplètes) comme à /api/generate.
|
|
||||||
assert 'id="genViz"' in content
|
assert 'id="genViz"' in content
|
||||||
assert 'value="wavelet"' in content
|
|
||||||
assert 'value="aniso_open"' not in content
|
|
||||||
assert 'value="pos_open"' in content
|
|
||||||
assert 'value="slope"' in content
|
assert 'value="slope"' in content
|
||||||
assert 'value="svf"' in content
|
assert 'value="pos_open"' in content
|
||||||
assert 'value="hillshade"' in content
|
assert 'value="aspect"' in content
|
||||||
|
assert 'value="roughness"' in content
|
||||||
|
assert 'value="wavelet"' not in content
|
||||||
|
assert 'value="svf"' not in content
|
||||||
|
assert 'value="hillshade"' not in content
|
||||||
|
assert 'value="aniso_open"' not in content
|
||||||
assert "genViz" in app_js and "viz: selectedGenViz()" in app_js
|
assert "genViz" in app_js and "viz: selectedGenViz()" in app_js
|
||||||
assert app_js.count("selectedGenViz()") >= 3 # définition + preview + generate
|
assert app_js.count("selectedGenViz()") >= 3 # définition + preview + generate
|
||||||
# Adoption du dernier run au chargement (redémarrage du serveur) :
|
# Adoption du dernier run au chargement (redémarrage du serveur) :
|
||||||
@ -347,34 +348,34 @@ def test_subtiles_cover_all_layers(tmp_path):
|
|||||||
assert t['viz'][viz]['full'].startswith("index_subtiles/"), viz
|
assert t['viz'][viz]['full'].startswith("index_subtiles/"), viz
|
||||||
|
|
||||||
|
|
||||||
def test_panel_offers_all_layers():
|
def test_panel_restricted_to_kept_layers():
|
||||||
"""Le panneau n'est plus restreint : toutes les couches connues sont proposées."""
|
"""Le panneau est restreint aux couches conservées (DEFAULT_LAYERS)."""
|
||||||
from lidar_pipeline.index import PANEL_VIZ, VIZ_LABELS, KEYWORD_TO_STEP
|
from lidar_pipeline.index import PANEL_VIZ, DEFAULT_LAYERS, KEYWORD_TO_STEP
|
||||||
from lidar_pipeline.pipeline import VIZ_STEPS
|
from lidar_pipeline.pipeline import VIZ_STEPS
|
||||||
assert PANEL_VIZ is None
|
assert PANEL_VIZ == DEFAULT_LAYERS
|
||||||
# Chaque couche connue du registre correspond à une étape --only valide
|
# Chaque couche conservée correspond à une étape --only valide
|
||||||
steps = {name for name, _ in VIZ_STEPS}
|
steps = {name for name, _ in VIZ_STEPS}
|
||||||
assert set(VIZ_LABELS)
|
for key in PANEL_VIZ:
|
||||||
for key in VIZ_LABELS:
|
|
||||||
assert KEYWORD_TO_STEP.get(key, key) in steps
|
assert KEYWORD_TO_STEP.get(key, key) in steps
|
||||||
|
|
||||||
|
|
||||||
def test_panel_selection_lists_full_registry():
|
def test_panel_selection_lists_kept_layers():
|
||||||
"""Le panneau propose le registre complet, même sans données sur disque.
|
"""Le panneau propose uniquement les couches conservées (PANEL_VIZ).
|
||||||
|
|
||||||
Une installation neuve (ou une couche jamais générée) doit quand même
|
Même sans données sur disque, le panneau affiche les couches conservées ;
|
||||||
afficher toutes les couches connues ; les couches historiques présentes
|
une couche absente du panneau n'est plus proposée, même présente sur
|
||||||
sur disque restent proposées (libellé = clé brute).
|
disque.
|
||||||
"""
|
"""
|
||||||
from lidar_pipeline.index import _panel_selection, VIZ_LABELS
|
from lidar_pipeline.index import _panel_selection, PANEL_VIZ
|
||||||
ordered, default = _panel_selection({'aspect'})
|
ordered, default = _panel_selection({'aspect'})
|
||||||
assert set(VIZ_LABELS) <= set(ordered)
|
assert set(ordered) == set(PANEL_VIZ)
|
||||||
assert default == 'aspect'
|
assert default == 'aspect'
|
||||||
ordered, default = _panel_selection(set())
|
ordered, default = _panel_selection(set())
|
||||||
assert set(VIZ_LABELS) <= set(ordered)
|
assert set(ordered) == set(PANEL_VIZ)
|
||||||
assert default # toujours une couche par défaut
|
assert default # toujours une couche par défaut
|
||||||
|
# Une couche présente sur disque mais hors panneau est exclue
|
||||||
ordered, default = _panel_selection({'aniso_open'})
|
ordered, default = _panel_selection({'aniso_open'})
|
||||||
assert 'aniso_open' in ordered
|
assert 'aniso_open' not in ordered
|
||||||
|
|
||||||
|
|
||||||
def test_build_index_merges_cross_resolution_viz(tmp_path):
|
def test_build_index_merges_cross_resolution_viz(tmp_path):
|
||||||
|
|||||||
Reference in New Issue
Block a user