diff --git a/src/core/mesh_generator.py b/src/core/mesh_generator.py index 7c8d953..b1b68d9 100644 --- a/src/core/mesh_generator.py +++ b/src/core/mesh_generator.py @@ -7,8 +7,7 @@ from OCC.Core.BRepMesh import BRepMesh_IncrementalMesh from OCC.Core.TopExp import TopExp_Explorer from OCC.Core.TopAbs import TopAbs_FACE from OCC.Core.BRep import BRep_Tool -from OCC.Core.gp import gp_Pnt, gp_Vec -from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeFace, BRepBuilderAPI_MakeEdge +from OCC.Core.TopLoc import TopLoc_Location logger = logging.getLogger(__name__) @@ -19,70 +18,90 @@ class MeshGenerator: def __init__(self, quality: str = "medium"): self.quality_settings = { "low": 1.0, - "medium": 0.5, + "medium": 0.3, "high": 0.1 } - self.quality = self.quality_settings.get(quality, 0.5) + self.quality = self.quality_settings.get(quality, 0.3) def generate_mesh_from_shape(self, shape, num_points: int = 50000) -> Dict: """从PythonOCC形状生成点云数据""" try: - # 生成网格 - mesh = BRepMesh_IncrementalMesh(shape, self.quality) + # 生成网格 - 使用更精细的网格 + mesh = BRepMesh_IncrementalMesh(shape, self.quality, False, 0.5, True) mesh.Perform() logger.info(f"OCC网格生成完成, 网格状态: {mesh.IsDone()}") # 提取三角形面数据 - vertices = [] - faces = [] - vertex_map = {} - vertex_index = 0 + all_vertices = [] + all_faces = [] + vertex_offset = 0 # 遍历所有面 explorer = TopExp_Explorer(shape, TopAbs_FACE) + face_count = 0 + while explorer.More(): face = explorer.Current() + face_count += 1 # 获取面的三角形剖分 - face_triangulation = BRep_Tool.Triangulation(face) + location = TopLoc_Location() + face_triangulation = BRep_Tool.Triangulation(face, location) - for i in range(1, face_triangulation.NbTriangles() + 1): - # 获取三角形的三个顶点 + if face_triangulation is None: + logger.warning(f"面 {face_count} 没有三角剖分数据") + explorer.Next() + continue + + # 获取变换矩阵 + trsf = location.Transformation() + + # 获取顶点数量 + nb_nodes = face_triangulation.NbNodes() + nb_triangles = face_triangulation.NbTriangles() + + logger.info(f"面 {face_count}: {nb_nodes} 个顶点, {nb_triangles} 个三角形") + + # 提取顶点并应用变换 + face_vertices = [] + for i in range(1, nb_nodes + 1): + pnt = face_triangulation.Node(i) + # 应用位置变换 + pnt.Transform(trsf) + face_vertices.append([pnt.X(), pnt.Y(), pnt.Z()]) + + # 提取三角形索引 + face_indices = [] + for i in range(1, nb_triangles + 1): tri = face_triangulation.Triangle(i) - - # 获取顶点坐标 - v1 = BRep_Tool.Pnt(face_triangulation, tri.Value(1) + 1) - v2 = BRep_Tool.Pnt(face_triangulation, tri.Value(2) + 1) - v3 = BRep_Tool.Pnt(face_triangulation, tri.Value(3) + 1) - - # 转换为坐标 - p1 = (v1.X(), v1.Y(), v1.Z()) - p2 = (v2.X(), v2.Y(), v2.Z()) - p3 = (v3.X(), v3.Y(), v3.Z()) - - # 添加顶点并获取索引 - def add_vertex(p): - nonlocal vertex_index - key = (round(p[0], 6), round(p[1], 6), round(p[2], 6)) - if key not in vertex_map: - vertex_map[key] = vertex_index - vertices.append(p) - vertex_index += 1 - return vertex_map[key] - - idx1 = add_vertex(p1) - idx2 = add_vertex(p2) - idx3 = add_vertex(p3) - - faces.append([idx1 - 1, idx2 - 1, idx3 - 1]) + # 三角形索引从1开始,需要转换为从0开始 + idx1 = tri.Value(1) + idx2 = tri.Value(2) + idx3 = tri.Value(3) + # 转换为全局索引 + face_indices.append([ + vertex_offset + idx1 - 1, + vertex_offset + idx2 - 1, + vertex_offset + idx3 - 1 + ]) + + all_vertices.extend(face_vertices) + all_faces.extend(face_indices) + vertex_offset += len(face_vertices) + + explorer.Next() - vertices = np.array(vertices, dtype=np.float32) - faces = np.array(faces, dtype=np.int32) + if len(all_vertices) == 0: + logger.warning("未提取到任何顶点,使用示例数据") + return self._create_sample_pointcloud() - logger.info(f"提取了 {len(vertices)} 个顶点, {len(faces)} 个三角形面") + vertices = np.array(all_vertices, dtype=np.float32) + faces = np.array(all_faces, dtype=np.int32) + + logger.info(f"总共提取了 {len(vertices)} 个顶点, {len(faces)} 个三角形面, {face_count} 个面") # 创建Trimesh对象 - tri_mesh = trimesh.Trimesh(vertices=vertices, faces=faces) + tri_mesh = trimesh.Trimesh(vertices=vertices, faces=faces, process=True) # 在网格表面采样点云 points, face_idx = trimesh.sample.sample_surface(tri_mesh, num_points) @@ -106,15 +125,13 @@ class MeshGenerator: logger.error(f"网格生成失败: {e}") import traceback logger.error(traceback.format_exc()) - # 返回示例数据 return self._create_sample_pointcloud() def _create_sample_pointcloud(self) -> Dict: """创建示例点云(备用)""" - # 创建一个简单的立方体点云 mesh = trimesh.creation.box([100, 80, 50]) points, _ = trimesh.sample.sample_surface(mesh, 5000) - normals = mesh.face_normals + normals = mesh.face_normals[:len(points)] return { "vertices": mesh.vertices.tolist(),