feat: preserve flatness suite measurement outputs

This commit is contained in:
2026-07-22 11:06:44 +08:00
parent 8555aa2f2e
commit 752ea3f944
9 changed files with 813 additions and 22 deletions

View File

@@ -31,6 +31,7 @@ from _plugin_io import (
write_error_result,
write_result,
)
from flatness_suite_measurements import measurements_from_batch_result
def _safe_float(v: object) -> float | None:
@@ -40,6 +41,25 @@ def _safe_float(v: object) -> float | None:
return None
def _config_bool(config: dict, key: str, default: bool = False) -> bool:
value = config.get(key, default)
if isinstance(value, bool):
return value
if isinstance(value, str):
return value.strip().lower() in {"1", "true", "yes", "on"}
return bool(value)
def _cleanup_temporary_artifacts(out_dir: Path) -> None:
# 仅删除适配器自己创建、且不会写入 result.json 的固定临时文件。
# 不使用通配符,避免误删算法结果或用户要求保留的产物。
for name in ("_roi_cropped.ply",):
try:
(out_dir / name).unlink(missing_ok=True)
except OSError as exc:
print(f"[flatness-suite] 清理临时文件失败 {name}: {exc}", file=sys.stderr)
def _mesh_cache_path(cad_path: str, mesh_deflection: float) -> Path:
"""根据 STEP 路径 + 文件指纹 + 三角化精度生成缓存路径。
@@ -191,12 +211,21 @@ def main() -> int:
if use_batch_mode and module == "contour":
emit_progress(0.20, "批量模式:从 datasets/Noise_PointCloud/ 读取所有面板点云")
data_root = alg_dir / "datasets"
# 所选整车点云作为可视化背景;用户也可在 contextPointCloudPath 里手动指定
context_pc = (inputs.get("contextPointCloudPath")
or pc_path_raw
or None)
# combined_contour.ply 可能包含完整整车点云,单次可达十几 GB。
# 平台页面只使用各面板 *_contour.ply,因此默认从源头跳过组合文件;
# 仅在用户显式开启时才生成,并作为可下载产物登记。
keep_combined_contour = _config_bool(config, "keepCombinedContour", False)
context_pc = None
if keep_combined_contour:
context_pc = (config.get("contextPointCloudPath")
or inputs.get("contextPointCloudPath")
or pc_path_raw
or None)
save_dir = str(out_dir / "contour_batch")
excel_path = str(out_dir / "contour.xlsx")
result_template_path = alg_dir / "excel" / "测量结果.xlsx"
if not result_template_path.is_file():
raise RuntimeError(f"内置测量结果模板不存在: {result_template_path}")
res = pipeline.run_contour_batch(
all_tasks=True,
data_root=str(data_root),
@@ -205,20 +234,13 @@ def main() -> int:
triangle_chunk_size=512,
save_path=save_dir,
excel_output_path=excel_path,
result_template_path=str(result_template_path),
combined_context_pointcloud_path=context_pc,
save_combined_visualization=keep_combined_contour,
no_visualize=True,
)
emit_progress(0.95, "整理批量结果")
batch_stats = res.get("batch_stats") or {}
measurements: list[dict] = []
for task_id, task_res in (res.get("results") or {}).items():
s = task_res.get("distance_stats") or {}
if s:
measurements.append({
"name": f"任务{task_id} 轮廓偏差均值",
"value": round(float(s.get("mean", 0)), 4),
"unit": "mm", "status": "info",
})
measurements = measurements_from_batch_result(res, result_template_path)
# 各面板热力图 PLY 列表(不含背景点,全部是有意义的颜色)
panel_plys = sorted([
f"contour_batch/{p.name}"
@@ -229,12 +251,19 @@ def main() -> int:
overlay3d = {"kind": "ply", "file": panel_plys[0], "files": panel_plys}
else:
overlay3d = {"kind": "none"}
combined_rel = "contour_batch/combined_contour.ply"
result_files = [combined_rel] if keep_combined_contour and (out_dir / combined_rel).is_file() else []
write_result(out_dir, {
"status": "completed",
"message": f"批量完成 {len(res.get('results', {}))} 个面板测量",
"message": f"批量完成 {len(res.get('rows') or [])} 个面板测量",
"measurements": measurements,
"overlay3d": overlay3d,
"extra": {"module": "contour_batch", "excelPath": "contour.xlsx"},
"files": result_files,
"extra": {
"module": "contour_batch",
"excelPath": "contour.xlsx",
"combinedContourKept": bool(result_files),
},
})
return 0
@@ -430,6 +459,8 @@ def main() -> int:
extra={"traceback": traceback.format_exc()},
)
return 1
finally:
_cleanup_temporary_artifacts(out_dir)
if __name__ == "__main__":