Перенесены backend/frontend/desktop/engine, добавлены вкладки конструктора сцен и генератора датасета с параметрами лучей и длины сетки рельефа, обновлены API и Docker-сборка. Co-authored-by: Cursor <cursoragent@cursor.com>
67 lines
2.9 KiB
Python
67 lines
2.9 KiB
Python
"""Pipeline chain insights (mirrors MainWindow::recomputeInsights)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
|
|
def compute_insights(
|
|
preprocess_plugins: list[str],
|
|
reconstruction_plugin: str,
|
|
) -> dict[str, Any]:
|
|
warnings: list[str] = []
|
|
risk_state = False
|
|
|
|
stages = [s for s in preprocess_plugins if s]
|
|
voxel_idx = stages.index("pcl_voxel_grid") if "pcl_voxel_grid" in stages else -1
|
|
remove_nan_idx = stages.index("pcl_remove_nan") if "pcl_remove_nan" in stages else -1
|
|
remove_nan_normals_idx = (
|
|
stages.index("pcl_remove_nan_normals") if "pcl_remove_nan_normals" in stages else -1
|
|
)
|
|
outlier_indexes = []
|
|
for stage_id in (
|
|
"pcl_statistical_outlier",
|
|
"pcl_radius_outlier",
|
|
"pcl_model_outlier",
|
|
"pcl_shadow_points",
|
|
):
|
|
if stage_id in stages:
|
|
outlier_indexes.append(stages.index(stage_id))
|
|
first_outlier_idx = min(outlier_indexes) if outlier_indexes else -1
|
|
|
|
if not stages:
|
|
risk_state = True
|
|
warnings.append("Добавьте хотя бы один этап препроцессинга перед реконструкцией.")
|
|
else:
|
|
if first_outlier_idx < 0:
|
|
warnings.append("Добавьте outlier removal для стабилизации триангуляции.")
|
|
if first_outlier_idx >= 0:
|
|
nan_idxs = [i for i in (remove_nan_idx, remove_nan_normals_idx) if i >= 0]
|
|
first_nan_preclean_idx = min(nan_idxs) if nan_idxs else -1
|
|
if first_nan_preclean_idx < 0 or first_nan_preclean_idx > first_outlier_idx:
|
|
warnings.append(
|
|
"Удалите NaN сразу после загрузки/обрезки: иначе статистические фильтры работают нестабильно."
|
|
)
|
|
if voxel_idx >= 0 and first_outlier_idx >= 0 and first_outlier_idx > voxel_idx:
|
|
warnings.append(
|
|
"OutlierRemoval стоит после VoxelGrid: лучше сначала очистить шум, затем прореживать."
|
|
)
|
|
if reconstruction_plugin == "pcl_greedy_triangulation" and voxel_idx < 0:
|
|
warnings.append("Greedy triangulation обычно работает лучше после voxel downsampling.")
|
|
|
|
if risk_state:
|
|
chain_health = "Risk"
|
|
recommendation = warnings[0] if warnings else "Проверьте порядок этапов пайплайна."
|
|
elif warnings:
|
|
chain_health = "Warning"
|
|
recommendation = warnings[0]
|
|
else:
|
|
chain_health = "OK"
|
|
recommendation = "Пайплайн сбалансирован. Используйте «Сохр. конф.» для A/B-сравнения."
|
|
|
|
return {
|
|
"chainHealth": chain_health,
|
|
"warningsList": warnings,
|
|
"recommendation": recommendation,
|
|
}
|