from shapely.geometry import Polygon
import triangle
from shapely.ops import unary_union
from stl import mesh
import numpy as np
from collections import defaultdict
from 三维投影线段寻找 import get_adjusted_clusters,get_clusters,get_intersect_lines
import networkx as nx
if __name__ == "__main__":dxf_file_path = 'a.dxf'clusters=get_clusters(dxf_file_path)adjusted_clusters,yz中间面线段集,xy上下面线段集,xz左右面线段集 =get_adjusted_clusters(clusters)intersect_lines=get_intersect_lines(xz左右面线段集,yz中间面线段集,xy上下面线段集)intersect_lines1,intersect_lines2,intersect_lines3 = intersect_lines
# 定义一个函数来消除坐标差异
def align_coordinates(lines, step):aligned_lines = []for line in lines:# 四舍五入坐标到最近的step的倍数aligned_line = ((np.round(line[0][0] / step) * step, np.round(line[0][1] / step) * step, np.round(line[0][2] / step) * step),(np.round(line[1][0] / step) * step, np.round(line[1][1] / step) * step, np.round(line[1][2] / step) * step),)aligned_lines.append(aligned_line)return aligned_lines# 使用函数消除坐标差异,这里以0.2为步长
aligned_intersectlines1 = align_coordinates(intersect_lines1, 0.2)
aligned_intersectlines2 = align_coordinates(intersect_lines2, 0.2)
aligned_intersectlines3 = align_coordinates(intersect_lines3, 0.2)
lines_grouped_by_y = defaultdict(list)
lines_grouped_by_x = defaultdict(list)
lines_grouped_by_z = defaultdict(list)
for line in aligned_intersectlines1:y = line[0][1] # 假设y值是线段第一个点的y坐标lines_grouped_by_y[y].append(line)
for line in aligned_intersectlines2:z = line[0][2] # 假设y值是线段第一个点的y坐标lines_grouped_by_z[z].append(line)
for line in aligned_intersectlines3:x = line[0][0] # 假设y值是线段第一个点的y坐标lines_grouped_by_x[x].append(line)
print(f"y找到了{len(lines_grouped_by_y )}个面")
print(f"z找到了{len(lines_grouped_by_z )}个面")
print(f"x找到了{len(lines_grouped_by_x )}个面")def get_2d_polygon(d,nodes):if d==0:polygon = Polygon([(y,z) for x,y, z in nodes])elif d==1:polygon = Polygon([(x,z) for x,y, z in nodes])else:polygon = Polygon([(x,y) for x,y, z in nodes])return polygon
def get_3dvertices_array(d,t, vertices):if d==0:vertices_array = np.array([(t, y, z) for y, z in vertices])elif d==1:vertices_array = np.array([(x, t, z) for x, z in vertices])else :vertices_array = np.array([(x, y, t) for x, y in vertices])return vertices_arraydef polygon_to_mesh(d,t,polygon):vertices = list(polygon.exterior.coords)[:-1]# 创建外环边界的线段列表segments = [[i, i+1] for i in range(0,len(vertices)-1 )]segments.append([len(vertices) - 1, 0]) tridict = {'vertices': vertices,'segments': segments, # 注意:segments 应该是一个列表的列表 }tri = triangle.triangulate(tridict, 'p')triangles = tri['triangles']vertices=tri['vertices']# print(" triangles", triangles)# print(" vertices2", vertices)faces_array = np.array(triangles) # STL 文件中的索引是从1开始的vertices_array=get_3dvertices_array(d,t,vertices)# 创建 mesh 对象triangle_mesh = mesh.Mesh(np.zeros(faces_array.shape[0], dtype=mesh.Mesh.dtype))for i, fa in enumerate(faces_array):for j in range(3):triangle_mesh.vectors[i][j] = vertices_array[fa[j], :]return triangle_mesh
def merge_meshes(meshes_to_merge):# 合并所有网格的顶点combined_data = []for m in meshes_to_merge:combined_data.append(m.data)combined_mesh = mesh.Mesh(np.concatenate(combined_data))return combined_mesh
def get_closed_subgraphs_in_open_faces(d,lines_grouped_by):meshes_to_merge=[]for t, items in lines_grouped_by.items():polygons=[]G = nx.Graph()G.add_edges_from(items)outer_ring=Noneinner_rings=[]if not nx.is_connected(G):closed_subgraphs_in_current_faces = []# 对于不闭合的面,找到所有的连通分量for component in nx.connected_components(G):# 创建一个子图,只包含当前连通分量中的节点和边subgraph = G.subgraph(component)# 检查子图是否闭合(形成一个环)if nx.is_eulerian(subgraph):print(f"当前面闭合图形数{len(closed_subgraphs_in_current_faces)}")eulerian_circuit = list(nx.eulerian_circuit(subgraph))# 提取顶点列表subgraph_nodes = [edge[0] for edge in eulerian_circuit]subgraph_polygon = get_2d_polygon(d, subgraph_nodes )# 检查是否有环在另一个环内部for other_polygon in closed_subgraphs_in_current_faces:if subgraph_polygon.within( other_polygon):# 如果内环在外环内,则可以在这里处理(例如,进行三角剖分切割)#用shaply对内外环形成的图形内部做三角剖分切割print("这是一个内环")outer_ring= other_polygoninner_rings.append(subgraph_polygon)breakelif other_polygon.within(subgraph_polygon):print("这是一个外环")outer_ring=subgraph_polygoninner_rings.append( other_polygon)breakelse:print("分开环")closed_subgraphs_in_current_faces.append(subgraph_polygon ) if outer_ring:inner_rings_union = unary_union(inner_rings)poly=outer_ring.difference(inner_rings_union)# print("poly",poly)# 提取多边形的顶点和边界vertices = list(poly.exterior.coords)[:-1]# 创建外环边界的线段列表segments = [[i, i+1] for i in range(0,len(vertices)-1 )]segments.append([len(vertices) - 1, 0]) # 连接最后一个和第一个外环顶点# 提取所有内环的顶点,并添加到 vertices 列表中for interior_ring in poly.interiors:vertices.extend(list(interior_ring.coords)[:-1]) # 内环顶点,去掉最后一个重复点# 创建内环边界的线段列表for interior_ring in poly.interiors:start_index = len(vertices) - len(interior_ring.coords)+1for i in range(len(interior_ring.coords) - 2):segments.append([start_index + i, start_index + i + 1])segments.append([start_index + len(interior_ring.coords) - 2, start_index]) # 连接最后一个和第一个内环顶点holes = []for interior_ring in poly.interiors:# 可以使用内环的几何中心点作为洞的位置holes.append(list(interior_ring.centroid.coords)[0])# 创建一个三角形库的输入字典tridict = {'vertices': vertices,'segments': segments, # 注意:segments 应该是一个列表的列表'holes': holes # 如果没有内环,则不需要这一项}# print( 'vertices', vertices)# print( 'segments', segments)# print( 'holes', holes)# 使用 triangle 进行三角划分tri = triangle.triangulate(tridict, 'p')# 假设 tri['triangles'] 包含了三角划分的结果triangles = tri['triangles']vertices=tri['vertices']# print(" triangles", triangles)# print(" vertices2", vertices)# 创建一个 numpy 数组来保存顶点和三角形信息#draw_3d_p(vertices_array)faces_array = np.array(triangles) # STL 文件中的索引是从1开始的vertices_array=get_3dvertices_array(d,t,vertices)# 创建 mesh 对象triangle_mesh = mesh.Mesh(np.zeros(faces_array.shape[0], dtype=mesh.Mesh.dtype))for i, fa in enumerate(faces_array):for j in range(3):triangle_mesh.vectors[i][j] = vertices_array[fa[j], :]meshes_to_merge.append(triangle_mesh)else :polygons.extend(closed_subgraphs_in_current_faces) else: eulerian_circuit = list(nx.eulerian_circuit(G))subgraph_nodes = [edge[0] for edge in eulerian_circuit]eulerian_polygon = get_2d_polygon(d, subgraph_nodes )polygons.append(eulerian_polygon)for polygon in polygons:triangle_mesh=polygon_to_mesh(d,t,polygon)meshes_to_merge.append(triangle_mesh)#我这里也要生成triangle_mesh然后合并起来一起导出return meshes_to_merge
meshes_to_merge0=get_closed_subgraphs_in_open_faces(0,lines_grouped_by_x)
meshes_to_merge1=get_closed_subgraphs_in_open_faces(1,lines_grouped_by_y)
meshes_to_merge2=get_closed_subgraphs_in_open_faces(2,lines_grouped_by_z)meshes_to_merge = []# 将其他列表的内容添加到这个列表中
meshes_to_merge.extend(meshes_to_merge0)
meshes_to_merge.extend(meshes_to_merge1)
meshes_to_merge.extend(meshes_to_merge2)# 现在meshes_to_merge包含了所有网格,可以用来合并
mesh_merged = merge_meshes(meshes_to_merge)mesh_merged.save('merged_output_mesh.stl')
一跑就通,别的ai做得到吗
readdxf: 三视图,工程图转模型