feat: 算法升级、整车配准集成与性能分析文档
算法更新: delivery v1.2.1、平整度v1.5、测距v2.2、整车配准v1.3 适配器: vehicle-registration 新增、各算法 manifest 和 adapter 更新 后端: taskCadFiles/source 字段迁移、derivedPointClouds 注册、取消任务联动 前端: ElapsedTime 时长显示、两步算法流程、canRun 逻辑修复 文档: 新增5份算法性能分析报告
This commit is contained in:
69
alg/平整度、平面度、轮廓测量v1.5/io_handler.py
Normal file
69
alg/平整度、平面度、轮廓测量v1.5/io_handler.py
Normal file
@@ -0,0 +1,69 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import numpy as np
|
||||
import open3d as o3d
|
||||
import trimesh
|
||||
|
||||
|
||||
class IOHandler:
|
||||
"""Centralized input validation and file loading."""
|
||||
|
||||
def resolve_path(self, path: str | Path) -> Path:
|
||||
return Path(path).expanduser()
|
||||
|
||||
def require_file(self, path: str | Path, label: str = "file") -> Path:
|
||||
resolved = self.resolve_path(path)
|
||||
if not resolved.exists():
|
||||
raise FileNotFoundError(f"{label} not found: {resolved}")
|
||||
if not resolved.is_file():
|
||||
raise ValueError(f"{label} is not a file: {resolved}")
|
||||
return resolved
|
||||
|
||||
def ensure_parent_dir(self, path: str | Path) -> Path:
|
||||
resolved = self.resolve_path(path)
|
||||
resolved.parent.mkdir(parents=True, exist_ok=True)
|
||||
return resolved
|
||||
|
||||
def load_point_cloud(self, pointcloud_path: str | Path) -> o3d.geometry.PointCloud:
|
||||
path = self.require_file(pointcloud_path, "Point cloud")
|
||||
pcd = o3d.io.read_point_cloud(str(path))
|
||||
if len(pcd.points) == 0:
|
||||
raise ValueError(f"Point cloud is empty or unreadable: {path}")
|
||||
return pcd
|
||||
|
||||
def load_mesh(self, mesh_path: str | Path) -> trimesh.Trimesh:
|
||||
path = self.require_file(mesh_path, "Mesh")
|
||||
mesh = trimesh.load(str(path), force="mesh")
|
||||
if mesh.is_empty:
|
||||
raise ValueError(f"Mesh is empty or unreadable: {path}")
|
||||
return mesh
|
||||
|
||||
def require_cad(self, cad_path: str | Path) -> Path:
|
||||
return self.require_file(cad_path, "CAD")
|
||||
|
||||
def save_point_cloud(self, pointcloud: o3d.geometry.PointCloud, output_path: str | Path) -> Path:
|
||||
path = self.ensure_parent_dir(output_path)
|
||||
ok = o3d.io.write_point_cloud(str(path), pointcloud)
|
||||
if not ok:
|
||||
raise IOError(f"Failed to save point cloud: {path}")
|
||||
return path
|
||||
|
||||
def point_cloud_to_numpy(self, pointcloud: o3d.geometry.PointCloud) -> np.ndarray:
|
||||
points = np.asarray(pointcloud.points, dtype=np.float64)
|
||||
if points.size == 0:
|
||||
raise ValueError("Point cloud has no points.")
|
||||
return points
|
||||
|
||||
def mesh_triangles_to_numpy(self, mesh: trimesh.Trimesh) -> tuple[np.ndarray, np.ndarray]:
|
||||
vertices = np.asarray(mesh.vertices, dtype=np.float64)
|
||||
faces = np.asarray(mesh.faces, dtype=np.int64)
|
||||
if len(vertices) == 0 or len(faces) == 0:
|
||||
raise ValueError("Mesh must contain vertices and faces.")
|
||||
return vertices, faces
|
||||
|
||||
def print_mapping(self, data: dict[str, Any]) -> None:
|
||||
for key, value in data.items():
|
||||
print(f"{key}: {value}")
|
||||
Reference in New Issue
Block a user