Files
massive-cloud/alg/平整度、平面度、轮廓测量v1.5/io_handler.py
lipan 29f1d45d66 feat: 算法升级、整车配准集成与性能分析文档
算法更新: delivery v1.2.1、平整度v1.5、测距v2.2、整车配准v1.3
适配器: vehicle-registration 新增、各算法 manifest 和 adapter 更新
后端: taskCadFiles/source 字段迁移、derivedPointClouds 注册、取消任务联动
前端: ElapsedTime 时长显示、两步算法流程、canRun 逻辑修复
文档: 新增5份算法性能分析报告
2026-06-25 08:22:20 +00:00

70 lines
2.6 KiB
Python

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}")