This commit is contained in:
2026-03-07 01:33:29 +08:00
parent ebc0b61a1e
commit 57a67309bd
+63 -46
View File
@@ -7,8 +7,7 @@ from OCC.Core.BRepMesh import BRepMesh_IncrementalMesh
from OCC.Core.TopExp import TopExp_Explorer from OCC.Core.TopExp import TopExp_Explorer
from OCC.Core.TopAbs import TopAbs_FACE from OCC.Core.TopAbs import TopAbs_FACE
from OCC.Core.BRep import BRep_Tool from OCC.Core.BRep import BRep_Tool
from OCC.Core.gp import gp_Pnt, gp_Vec from OCC.Core.TopLoc import TopLoc_Location
from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeFace, BRepBuilderAPI_MakeEdge
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -19,70 +18,90 @@ class MeshGenerator:
def __init__(self, quality: str = "medium"): def __init__(self, quality: str = "medium"):
self.quality_settings = { self.quality_settings = {
"low": 1.0, "low": 1.0,
"medium": 0.5, "medium": 0.3,
"high": 0.1 "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: def generate_mesh_from_shape(self, shape, num_points: int = 50000) -> Dict:
"""从PythonOCC形状生成点云数据""" """从PythonOCC形状生成点云数据"""
try: try:
# 生成网格 # 生成网格 - 使用更精细的网格
mesh = BRepMesh_IncrementalMesh(shape, self.quality) mesh = BRepMesh_IncrementalMesh(shape, self.quality, False, 0.5, True)
mesh.Perform() mesh.Perform()
logger.info(f"OCC网格生成完成, 网格状态: {mesh.IsDone()}") logger.info(f"OCC网格生成完成, 网格状态: {mesh.IsDone()}")
# 提取三角形面数据 # 提取三角形面数据
vertices = [] all_vertices = []
faces = [] all_faces = []
vertex_map = {} vertex_offset = 0
vertex_index = 0
# 遍历所有面 # 遍历所有面
explorer = TopExp_Explorer(shape, TopAbs_FACE) explorer = TopExp_Explorer(shape, TopAbs_FACE)
face_count = 0
while explorer.More(): while explorer.More():
face = explorer.Current() 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) tri = face_triangulation.Triangle(i)
# 三角形索引从1开始,需要转换为从0开始
# 获取顶点坐标 idx1 = tri.Value(1)
v1 = BRep_Tool.Pnt(face_triangulation, tri.Value(1) + 1) idx2 = tri.Value(2)
v2 = BRep_Tool.Pnt(face_triangulation, tri.Value(2) + 1) idx3 = tri.Value(3)
v3 = BRep_Tool.Pnt(face_triangulation, tri.Value(3) + 1) # 转换为全局索引
face_indices.append([
# 转换为坐标 vertex_offset + idx1 - 1,
p1 = (v1.X(), v1.Y(), v1.Z()) vertex_offset + idx2 - 1,
p2 = (v2.X(), v2.Y(), v2.Z()) vertex_offset + idx3 - 1
p3 = (v3.X(), v3.Y(), v3.Z()) ])
# 添加顶点并获取索引 all_vertices.extend(face_vertices)
def add_vertex(p): all_faces.extend(face_indices)
nonlocal vertex_index vertex_offset += len(face_vertices)
key = (round(p[0], 6), round(p[1], 6), round(p[2], 6))
if key not in vertex_map: explorer.Next()
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])
vertices = np.array(vertices, dtype=np.float32) if len(all_vertices) == 0:
faces = np.array(faces, dtype=np.int32) 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对象 # 创建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) points, face_idx = trimesh.sample.sample_surface(tri_mesh, num_points)
@@ -106,15 +125,13 @@ class MeshGenerator:
logger.error(f"网格生成失败: {e}") logger.error(f"网格生成失败: {e}")
import traceback import traceback
logger.error(traceback.format_exc()) logger.error(traceback.format_exc())
# 返回示例数据
return self._create_sample_pointcloud() return self._create_sample_pointcloud()
def _create_sample_pointcloud(self) -> Dict: def _create_sample_pointcloud(self) -> Dict:
"""创建示例点云(备用)""" """创建示例点云(备用)"""
# 创建一个简单的立方体点云
mesh = trimesh.creation.box([100, 80, 50]) mesh = trimesh.creation.box([100, 80, 50])
points, _ = trimesh.sample.sample_surface(mesh, 5000) points, _ = trimesh.sample.sample_surface(mesh, 5000)
normals = mesh.face_normals normals = mesh.face_normals[:len(points)]
return { return {
"vertices": mesh.vertices.tolist(), "vertices": mesh.vertices.tolist(),