import os import json import requests import shutil import time import random import matplotlib.pyplot as plt import open3d as o3d import numpy as np from plyfile import PlyData, PlyElement from config import print_factory_type_dir from general import mesh_tranform_to_pcd from general import need_upload_result from general import read_mesh from compute_print_net import get_models_bbox from compute_print_net import arrange_models_on_platform from compute_print_net import Platform from compute_print_net import down_sample from compute_print_net import compute_bbox_all from compute_print_net import compute_bbox_all_ext def make_bbox_for_print(base_original_obj_dir,dict_bad,dict_origin,is_downsample): """获取需要的盒子大小""" start_time = time.time() obj_id_list = [aa.split(".o")[0] for aa in os.listdir(base_original_obj_dir) if aa.endswith(".obj")] obj_id_list = obj_id_list dict_mesh_obj = {} index = 0 for pid_t_y in obj_id_list: start_time1 = time.time() obj_name = pid_t_y+".obj" obj_path = os.path.join(base_original_obj_dir,obj_name) mesh_obj = read_mesh(obj_path) if mesh_obj is None: dict_bad[obj_name]=obj_name # 记录错误文件 error_log = os.path.join(base_original_obj_dir, "error_files.txt") with open(error_log, 'a') as f: f.write(f"{obj_path}\n") print(f"Skipping invalid file: {obj_path}") continue dict_origin[obj_name] = mesh_obj dict_mesh_obj[obj_name] = mesh_obj print(f"make_bbox_for_print {index} {obj_name} time={time.time()-start_time1}") index = index + 1 print(f"make_bbox_for_print total_time={time.time()-start_time}") # dict_total_matrix,all_models = compute_bbox_all_ext(base_original_obj_dir, is_downsample) dict_total_matrix,all_models = compute_bbox_all(dict_mesh_obj, is_downsample) return get_dict_pcd(dict_mesh_obj,dict_total_matrix,all_models) def get_dict_pcd(dict_mesh_obj,dict_total_matrix,all_models): dict_pcd_fix = {} dict_ply_name = {} for model in all_models: ply_name = model['name'] dict_ply_name[f"{ply_name.split("=")[0]}.obj"] = ply_name dict_pcd_fix = get_pcd_by_matrix(dict_mesh_obj,dict_total_matrix,dict_ply_name) return dict_total_matrix,all_models,dict_pcd_fix def get_pcd_by_matrix(dict_mesh_obj,dict_total_matrix,dict_ply_name): dict_pcd_fix= {} for key, value in dict_mesh_obj.items(): obj_name = key mesh_obj = value pcd_fix = mesh_tranform_to_pcd(mesh_obj, dict_total_matrix[obj_name]) dict_pcd_fix[dict_ply_name[obj_name]] = pcd_fix dict_mesh_obj.clear() del dict_mesh_obj return dict_pcd_fix def ply_print_layout_platform(dict_pcd_fix,dict_pcd_fix2,machine_size,dict_total_matrix,all_models): """根据排版结果移动点云到指定位置""" # placed_models,unplaced_models = get_models_box_size(dict_fix,machine_size) # 1. 获取模型bbox尺寸 # all_models = get_models_bbox_net(dict_pcd_fix) print("all_models", all_models) # 2. 模型排版布局 print("开始计算排序...") placed_models, unplaced_models = arrange_models_on_platform(all_models, machine_size) if len(placed_models) ==0: print("放进打印盒的数量为0") return # 3. 根据排版结果移动点云和模型(原有逻辑不变) for model in placed_models: print(f" - {model['name']} at {model['position']} with dimensions {model['dimensions']}") ply_file_name = model['name'] move_position = model['position'] # print("要读取的点云数据路径",ply_origin_path) pcd = dict_pcd_fix[ply_file_name] # print("dict_fix read",ply_file_name,move_position) points = np.asarray(pcd.points) min_bound = np.min(points, axis=0) # 获取点云的最小边界 max_bound = np.max(points, axis=0) min_bound[1] = max(min_bound[1], 0) bbox_center = (min_bound + max_bound) / 2 # 计算包围盒的中心点 bbox_extent = (max_bound - min_bound) new_bbox = o3d.geometry.OrientedBoundingBox(center=bbox_center, R=np.eye(3), # 旋转矩阵,默认没有旋转 extent=bbox_extent) x = move_position[0] y = move_position[1] z = move_position[2] # move_position = np.array([x,y,z])/100 move_position = np.array([x, y, z]) # translation_vector = -move_position translation_vector = move_position pcd.translate(translation_vector) new_bbox.translate(translation_vector) obj_name = ply_file_name.split("=")[0]+".obj" T_trans1 = np.eye(4) T_trans1[:3, 3] = translation_vector dict_total_matrix[obj_name]= T_trans1 @ dict_total_matrix[obj_name] new_bbox_lines = o3d.geometry.LineSet.create_from_oriented_bounding_box(new_bbox) new_bbox_lines.paint_uniform_color([1, 0, 0]) # 红色 dict_pcd_fix2[ply_file_name] = pcd return placed_models def get_models_bbox_net(dict_pcd_fix): return get_models_bbox(dict_pcd_fix) """ def get_models_box_size(dict_fix,machine_size): #获取排版的盒子大小 models = [] for ply_file in dict_fix: bbox_with_text = ply_file.split("=") bbox_with = bbox_with_text[-1] split_text = bbox_with.replace(".ply","").split("+") extend_dist = 2 x_length = int(float(split_text[2])*100) + extend_dist y_length = int(float(split_text[0])*100) + extend_dist z_length = int(float(split_text[1])*100) + extend_dist #print("get_models_box_size",x_length,y_length,z_length) models.append({'name':ply_file,'dimensions':(int(x_length/100),int(z_length/100),int(y_length/100))}) print(models) platform = Platform(int(machine_size[0]), int(machine_size[1]), int(machine_size[2])) print("开始计算排序...") platform.arrange_models(models) platform.print_results() return platform.get_result() """ def compute_distance(pcd1, pcd2): """ 正确计算两个点云之间距离的函数。 返回两个点云之间最近距离的平均值、最小值以及全部距离数组。 """ # 使用Open3D内置的高效方法计算距离 # 计算pcd1中每个点到pcd2中最近点的距离 distances = pcd1.compute_point_cloud_distance(pcd2) distances = np.asarray(distances) # 计算有意义的统计量 min_dist = np.min(distances) # 所有点中的最小距离 mean_dist = np.mean(distances) # 距离的平均值 # return min_dist, mean_dist, distances return min_dist def compute_distance_x(pcd1, pcd2): points1 = np.asarray(pcd1.points)[:, 0] # 提取所有X坐标[3](@ref) points2 = np.asarray(pcd2.points)[:, 0] x_diff = np.abs(points1[:, np.newaxis] - points2) return np.min(x_diff) def compute_distance_y(pcd1, pcd2): points1 = np.asarray(pcd1.points)[:, 1] # 提取所有Y坐标[3](@ref) points2 = np.asarray(pcd2.points)[:, 1] y_diff = np.abs(points1.reshape(-1, 1) - points2) return np.min(y_diff) def check_collision_x(pcd_moving, static_pcds,collision_threshold): moving_points = np.asarray(pcd_moving.points) min_distance_to_x_axis = np.min(np.abs(moving_points[:, 1])) # Y 坐标即为与 X 轴的距离 #print(f"与 X 轴的最小距离: {min_distance_to_x_axis}") #print(f"与 Y 轴的最小距离: {min_distance_to_y_axis}") #print(f"pcd_moving{len(static_pcds)}") if min_distance_to_x_axis < collision_threshold: print(f"与 X 轴发生碰撞! 最小距离: {min_distance_to_x_axis}") return True return check_collision_all(pcd_moving, static_pcds,collision_threshold) def check_collision_y(pcd_moving, static_pcds,collision_threshold): moving_points = np.asarray(pcd_moving.points) #print(f"与 X 轴的最小距离: {min_distance_to_x_axis}") min_distance_to_y_axis = np.min(np.abs(moving_points[:, 0])) # X 坐标即为与 Y 轴的距离 #print(f"与 Y 轴的最小距离: {min_distance_to_y_axis}") #print(f"pcd_moving{len(static_pcds)}") if min_distance_to_y_axis < collision_threshold: print(f"与 Y 轴发生碰撞! 最小距离: {min_distance_to_y_axis}") return True return check_collision_all(pcd_moving, static_pcds,collision_threshold) import numpy as np def compute_aabb(pcd): """计算点云的AABB包围盒""" points = np.asarray(pcd.points) return { 'min': np.min(points, axis=0), 'max': np.max(points, axis=0) } def aabb_intersect(a, b, collision_threshold): """判断两个AABB包围盒是否相交[2,8](@ref)""" return (a['max'][0] > b['min'][0] - collision_threshold and a['min'][0] < b['max'][0] + collision_threshold) and \ (a['max'][1] > b['min'][1] - collision_threshold and a['min'][1] < b['max'][1] + collision_threshold) and \ (a['max'][2] > b['min'][2] - collision_threshold and a['min'][2] < b['max'][2] + collision_threshold) def check_collision_all(pcd_moving, static_pcds, collision_threshold): # 预计算移动点云AABB moving_aabb = compute_aabb(pcd_moving) for static_pcd in static_pcds: if static_pcd == pcd_moving: continue # 第一阶段:AABB快速排除[1,6](@ref) static_aabb = compute_aabb(static_pcd) # print("len(static_pcd.points)=",len(static_pcd.points),"len(moving_aabb.points)=",len(pcd_moving.points)) if not aabb_intersect(moving_aabb, static_aabb, collision_threshold): continue # 包围盒无交集,直接跳过 if not aabb_intersect(moving_aabb, static_aabb, collision_threshold): return False # 第二阶段:精确点距离计算 min_distance = compute_distance(pcd_moving, static_pcd) # print("check_collision_all",min_distance) if min_distance < collision_threshold: return True return False def compute_centroid(pcd): # 获取点云的所有点 points = np.asarray(pcd.points) # 计算质心(只考虑 X 和 Y 坐标) centroid = np.mean(points[:, :2], axis=0) # 只考虑前两个维度(X 和 Y) return centroid def compute_distance_to_origin(centroid): # 计算质心距离原点的距离(只考虑 X 和 Y 坐标) return np.linalg.norm(centroid) # 计算 X 和 Y 的欧几里得距离 def compute_closest_distance_to_origin(pcd): # 获取点云的所有点坐标 points = np.asarray(pcd.points) # 计算每个点到原点的距离 distances = np.linalg.norm(points, axis=1) # 返回最小距离 return np.min(distances) def sort_ply_files_by_closest_distance(folder_path): ply_files = [f for f in os.listdir(folder_path) if f.endswith('.ply')] distances = [] for ply_file in ply_files: # 读取点云数据 pcd = o3d.io.read_point_cloud(os.path.join(folder_path, ply_file)) # 计算离原点最近的点的距离 closest_distance = compute_closest_distance_to_origin(pcd) distances.append((ply_file, closest_distance)) # 按照最近点的距离排序(由近到远) distances.sort(key=lambda x: x[1]) # 返回排序后的文件列表 sorted_files = [item[0] for item in distances] print("Sorted files:", sorted_files) return sorted_files def compact_mode_for_min_dis_json(placed_models,dict_unplaced,dict_bounds_fix,machine_size,dict_total_matrix): y_step=1 x_step=1 delta = 10 edge_x_min=0 + 4 edge_y_min=0 + 4 edge_x_max=machine_size[0] edge_y_max=machine_size[1] collision_threshold=2 move_last = True pcd_all = [] pcd_processed = [] pcd_processed_x_top = [] pcd_processed_no_x_top = [] # name_list = [] dict_name = {} # model_list = [] dict_model = {} last_pcd_list = [] # last_name_list = [] dic_last_name = {} last_pcd_processed = [] max_x = machine_size[0] min_x = 0 max_delta_x = 0 x_top_delta = 1 border_delta = 4 pcd_first= [] pcd_second= [] index = 0 for model in placed_models: pcd = dict_bounds_fix[model['name']] pcd_all.append(pcd) if (get_axis_aligned_bbox(pcd)['y_min']>edge_y_max*0.3 or True): pcd_first.append(pcd) else: pcd_second.append(pcd) # pcd_all.append(pcd_downsampled) # name_list.append(model['name']) # model_list.append(model) dict_name[pcd] = model['name'] dict_model[pcd] = model dx = model['dimensions'][0] x = model['position'][0] if (x>=edge_x_max-x_top_delta) : pcd_processed_x_top.append(pcd) print("pcd_processed_x_top", model['name']) if dx > max_x: max_x = dx if dx < min_x: min_x = dx max_delta_x = max_x - min_x index += 1 # print("compact_mode_for_min_dis1_json", model, max_delta_x) draw_down = False if max_delta_x < 10: draw_down = False # for idx, pcd in enumerate(pcd_all): for idx, pcd in enumerate(pcd_first): if dict_model[pcd]['first_line']: pcd_processed.append(pcd) last_pcd_processed.append(pcd) continue x = dict_model[pcd]['position'][0] y = dict_model[pcd]['position'][1] dx = dict_model[pcd]['dimensions'][0] print("compact_mode", dict_name[pcd], dx, x) ply_file_name = dict_name[pcd] obj_name = ply_file_name.split("=")[0]+".obj" T_trans1 = np.eye(4) dist_x = 50 dist_y = 20 is_x_top = False if x - 10 < edge_x_min: dist_x = x - edge_x_min if y - 10 < edge_y_min: dist_y = y - edge_y_min if (x 80: y_init_big = 10 x_init_big = y_init_big - 1 if check_collision_all(pcd, pcd_processed_curr, 1): while True: step = 25 pcd.translate([0, -step, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, -step, 0] T_trans1 = T_transTemp @ T_trans1 # pcd.translate([-step, 0, 0]) # T_transTemp[:3, 3] = [-step, 0, 0] # T_trans1 = T_transTemp @ T_trans1 if not check_collision_all(pcd, pcd_processed_curr, collision_threshold_big): break """ while True: bbox = get_axis_aligned_bbox(pcd) if bbox['y_max'] >= edge_y_max - collision_threshold: pcd.translate([-x_step_big, -y_step_big, 0]) print("compact_mode y_max", idx, bbox['y_max'], edge_y_max - collision_threshold_big) break if bbox['x_max'] >= edge_x_max - collision_threshold: pcd.translate([-x_step_big, -y_step_big, 0]) print("compact_mode x_max", idx, bbox['x_max'], edge_x_max - collision_threshold_big) break if check_collision_all(pcd, pcd_processed_curr,collision_threshold_big): pcd.translate([-x_step_big, -y_step_big, 0]) break pcd.translate([x_step_big, y_step_big, 0]) #""" #""" while True: bbox = get_axis_aligned_bbox(pcd) # print("x_max",bbox['x_max'],bbox['x_min'],bbox['y_max'],bbox['y_min']) if bbox['y_min'] <= edge_y_min + collision_threshold_big and False: pcd.translate([0, y_step_big, 0]) break if bbox['y_max'] >= edge_y_max - collision_threshold_big: pcd.translate([0, -y_step_big, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, -y_step_big, 0] T_trans1 = T_transTemp @ T_trans1 break if check_collision_all(pcd, pcd_processed_curr,collision_threshold_big+y_init_big): #5 pcd.translate([0, -y_step_big, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, -y_step_big, 0] T_trans1 = T_transTemp @ T_trans1 break pcd.translate([0, y_step_big, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, y_step_big, 0] T_trans1 = T_transTemp @ T_trans1 while True: bbox = get_axis_aligned_bbox(pcd) if bbox['x_min'] <= edge_x_min + collision_threshold_big and False: pcd.translate([x_step_big, 0, 0]) break if bbox['x_max'] >= edge_x_max - collision_threshold_big: pcd.translate([-x_step_big, 0, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [-x_step_big, 0, 0] T_trans1 = T_transTemp @ T_trans1 break if check_collision_all(pcd, pcd_processed_curr,collision_threshold_big+x_init_big): pcd.translate([-x_step_big, 0, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [-x_step_big, 0, 0] T_trans1 = T_transTemp @ T_trans1 break pcd.translate([x_step_big, 0, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [x_step_big, 0, 0] T_trans1 = T_transTemp @ T_trans1 #""" #""" collision_threshold_init = collision_threshold+6 while True: bbox = get_axis_aligned_bbox(pcd) if bbox['y_min'] <= edge_y_min + collision_threshold_init and False: pcd.translate([0, y_step, 0]) break # if bbox['y_max'] >= edge_y_max - collision_threshold_init: if bbox['y_max'] >= edge_y_max - border_delta: pcd.translate([0, -y_step, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, -y_step, 0] T_trans1 = T_transTemp @ T_trans1 break if check_collision_all(pcd, pcd_processed_curr,collision_threshold_init+1): #5 pcd.translate([0, -y_step, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, -y_step, 0] T_trans1 = T_transTemp @ T_trans1 break pcd.translate([0, y_step, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, y_step, 0] T_trans1 = T_transTemp @ T_trans1 #""" #""" while True: bbox = get_axis_aligned_bbox(pcd) if bbox['x_min'] <= edge_x_min + collision_threshold_init and False: pcd.translate([x_step, 0, 0]) break # if bbox['x_max'] >= edge_x_max - collision_threshold_init: if bbox['x_max'] >= edge_x_max - border_delta: # print("1pcd.translate([-x_step, 0, 0])",name_list[idx]) pcd.translate([-x_step, 0, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [-x_step, 0, 0] T_trans1 = T_transTemp @ T_trans1 break if check_collision_all(pcd, pcd_processed_curr,collision_threshold_init): # print("2pcd.translate([-x_step, 0, 0])",name_list[idx]) pcd.translate([-x_step, 0, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [-x_step, 0, 0] T_trans1 = T_transTemp @ T_trans1 break pcd.translate([x_step, 0, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [x_step, 0, 0] T_trans1 = T_transTemp @ T_trans1 #""" #""" collision_threshold_init = collision_threshold+2 while True: bbox = get_axis_aligned_bbox(pcd) if bbox['y_min'] <= edge_y_min + collision_threshold_init and False: pcd.translate([0, y_step, 0]) break if bbox['y_max'] >= edge_y_max - collision_threshold_init: pcd.translate([0, -y_step, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, -y_step, 0] T_trans1 = T_transTemp @ T_trans1 break if check_collision_all(pcd, pcd_processed_curr,collision_threshold_init+1): #5 pcd.translate([0, -y_step, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, -y_step, 0] T_trans1 = T_transTemp @ T_trans1 break pcd.translate([0, y_step, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, y_step, 0] T_trans1 = T_transTemp @ T_trans1 while True: bbox = get_axis_aligned_bbox(pcd) if bbox['x_min'] <= edge_x_min + collision_threshold_init and False: pcd.translate([x_step, 0, 0]) break if bbox['x_max'] >= edge_x_max - collision_threshold_init: pcd.translate([-x_step, 0, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [-x_step, 0, 0] T_trans1 = T_transTemp @ T_trans1 break if check_collision_all(pcd, pcd_processed_curr,collision_threshold_init): pcd.translate([-x_step, 0, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [-x_step, 0, 0] T_trans1 = T_transTemp @ T_trans1 break pcd.translate([x_step, 0, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [x_step, 0, 0] T_trans1 = T_transTemp @ T_trans1 # place again collision_threshold_init = collision_threshold+1 while True: bbox = get_axis_aligned_bbox(pcd) if bbox['y_min'] <= edge_y_min + collision_threshold_init and False: pcd.translate([0, y_step, 0]) break if bbox['y_max'] >= edge_y_max - collision_threshold_init: pcd.translate([0, -y_step, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, -y_step, 0] T_trans1 = T_transTemp @ T_trans1 break if check_collision_all(pcd, pcd_processed_curr,collision_threshold_init): #5 pcd.translate([0, -y_step, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, -y_step, 0] T_trans1 = T_transTemp @ T_trans1 break pcd.translate([0, y_step, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, y_step, 0] T_trans1 = T_transTemp @ T_trans1 #""" pcd_processed.append(pcd) pcd_processed_x_top.append(pcd) if not is_x_top: pcd_processed_no_x_top.append(pcd) cross_border = False bbox = get_axis_aligned_bbox(pcd) if bbox['x_min'] <= edge_x_min + 1 or bbox['y_min'] <= edge_y_min + 1: cross_border = True print("coross_border",ply_file_name) if cross_border: pcd_second.append(pcd) dic_last_name[pcd] = ply_file_name else: last_pcd_processed.append(pcd) dict_total_matrix[obj_name]= T_trans1 @ dict_total_matrix[obj_name] volumes = [] # for idx, pcd in enumerate(last_pcd_list): for idx, pcd in enumerate(pcd_second): bbox = get_axis_aligned_bbox(pcd) x_length = bbox['x_max'] - bbox['x_min'] y_length = bbox['y_max'] - bbox['y_min'] z_length = bbox['z_max'] - bbox['z_min'] volume = x_length * y_length * z_length volumes.append(volume) # print("last_pcd_list", len(last_pcd_list), len(last_pcd_list), len(last_pcd_processed), len(pcd_all)) # sorted_indices = np.argsort(volumes)[::-1] # last_pcd_list2 = [last_pcd_list[i] for i in sorted_indices] # print("last_pcd_list2", len(last_pcd_list2)) print(f"pcd_second : len(pcd_first)={len(pcd_first)}, len(pcd_second)={len(pcd_second)}, len(last_pcd_processed)={len(last_pcd_processed)}, len(pcd_all)={len(pcd_all)}") sorted_indices = np.argsort(volumes)[::-1] pcd_second2 = [pcd_second[i] for i in sorted_indices] # print("pcd_second2 len", len(pcd_second2)) for idx, pcd in enumerate(pcd_second2): ply_file_name = dict_name[pcd] obj_name = ply_file_name.split("=")[0]+".obj" # print("pcd_second2", obj_name) T_trans1 = np.eye(4) points = np.asarray(pcd.points) min_x = np.min(points[:, 0]) max_y = np.max(points[:, 1]) # 当前最大y值 tx = edge_x_min - min_x ty = -max_y - 0.001 T_transTemp = move_to_top_left(pcd, edge_x_min+2, edge_y_max-2) T_trans1 = T_transTemp @ T_trans1 name = dict_name[pcd] # print("pcd_second2",name,"tx",tx,"ty",ty) succ_move = True y_accum = 0 finish_move2 = False while True: bbox = get_axis_aligned_bbox(pcd) collision_threshold_init = collision_threshold+1 if bbox['y_min'] <= edge_y_min + collision_threshold_init: print("succ_move False",name,bbox['y_min'],edge_y_min + collision_threshold_init) succ_move = False finish_move2 = True if (finish_move2): break else: if not check_collision_all(pcd, last_pcd_processed,collision_threshold_init): print("succ_move1",name,bbox['x_max'],bbox['y_max'],len(last_pcd_processed)) break pcd.translate([0, -y_step, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, -y_step, 0] T_trans1 = T_transTemp @ T_trans1 y_accum += y_step if succ_move: #print("succ_move2", name) """ while True: bbox = get_axis_aligned_bbox(pcd) if bbox['x_max'] >= edge_x_max - collision_threshold_big: pcd.translate([-x_step_big, 0, 0]) break if check_collision_all(pcd, last_pcd_processed,collision_threshold_big): pcd.translate([-x_step_big, 0, 0]) break pcd.translate([x_step_big, 0, 0]) while True: bbox = get_axis_aligned_bbox(pcd) if bbox['y_max'] >= edge_y_max - collision_threshold: pcd.translate([0, -y_step, 0]) break if check_collision_all(pcd, last_pcd_processed,collision_threshold+1): #5 pcd.translate([0, -y_step, 0]) break pcd.translate([0, y_step, 0]) while True: bbox = get_axis_aligned_bbox(pcd) if bbox['x_max'] >= edge_x_max - collision_threshold: pcd.translate([-x_step, 0, 0]) break if check_collision_all(pcd, last_pcd_processed,collision_threshold): pcd.translate([-x_step, 0, 0]) break pcd.translate([x_step, 0, 0]) #""" #""" x_accu = 0 while True: bbox = get_axis_aligned_bbox(pcd) collision_threshold_init = collision_threshold+2 #print("Move x_step_big", name, bbox['y_max'], bbox['x_max']) if bbox['x_max'] >= edge_x_max - collision_threshold_init: pcd.translate([-x_accu, 0, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [-x_accu, 0, 0] T_trans1 = T_transTemp @ T_trans1 break if not check_collision_all(pcd, last_pcd_processed,collision_threshold_init): x_accu = 0 while True: bbox = get_axis_aligned_bbox(pcd) collision_threshold_init = collision_threshold+1 if bbox['y_max'] >= edge_y_max - collision_threshold_init: pcd.translate([0, -y_step_big, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, -y_step_big, 0] T_trans1 = T_transTemp @ T_trans1 #print("Move y_max", name, bbox['y_max'], bbox['x_max']) break if check_collision_all(pcd, last_pcd_processed,collision_threshold_init): pcd.translate([0, -y_step_big, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, -y_step_big, 0] T_trans1 = T_transTemp @ T_trans1 #print("Move y_max2", name, bbox['y_max'], bbox['x_max']) break pcd.translate([0, y_step_big, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, y_step_big, 0] T_trans1 = T_transTemp @ T_trans1 #print("Move y_step_big", name, bbox['y_max'], bbox['x_max']) else: n = 1 x_accu += x_step_big pcd.translate([x_step_big, 0, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [x_step_big, 0, 0] T_trans1 = T_transTemp @ T_trans1 #""" else: # T_transTemp = move_to_bottom_left(pcd, edge_x_min, edge_y_min) T_transTemp = move_to_bottom_right(pcd, edge_x_max, edge_y_min) T_trans1 = T_transTemp @ T_trans1 print("last place", name) """ while True: bbox = get_axis_aligned_bbox(pcd) collision_threshold_init = collision_threshold+10 if bbox['x_max'] >= edge_x_max - collision_threshold_init: print("fail to place",name) break if not check_collision_all(pcd, last_pcd_processed,collision_threshold_init): print("last place2",name) break pcd.translate([x_step_big, 0, 0]) while True: bbox = get_axis_aligned_bbox(pcd) collision_threshold_init = collision_threshold+3 if bbox['y_max'] >= edge_y_max - collision_threshold_init: pcd.translate([0, -y_step_big, 0]) print("last place3",name) break if check_collision_all(pcd, last_pcd_processed,collision_threshold_init): #5 pcd.translate([0, -y_step_big, 0]) print("last place4",name,collision_threshold_init,len(last_pcd_processed)) break pcd.translate([0, y_step_big, 0]) print("last place41",y_step_big) while True: bbox = get_axis_aligned_bbox(pcd) if bbox['y_max'] >= edge_y_max - collision_threshold: pcd.translate([0, -y_step, 0]) print("last place5",name) break if check_collision_all(pcd, last_pcd_processed,collision_threshold+1): #5 pcd.translate([0, -y_step, 0]) print("last place6",name) break pcd.translate([0, y_step, 0]) while True: bbox = get_axis_aligned_bbox(pcd) if bbox['x_max'] >= edge_x_max - collision_threshold: pcd.translate([-x_step, 0, 0]) print("last place7",name) break if check_collision_all(pcd, last_pcd_processed,collision_threshold): pcd.translate([-x_step, 0, 0]) print("last place8",name) break pcd.translate([x_step, 0, 0]) #""" """ can_place_last = False x_accu = 0 while True: bbox = get_axis_aligned_bbox(pcd) collision_threshold_init = collision_threshold+2 if bbox['x_max'] >= edge_x_max - collision_threshold_init: if not can_place_last: print("fail to place",name) dict_unplaced[name]=name else: pcd.translate([-x_accu, 0, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [-x_accu, 0, 0] T_trans1 = T_transTemp @ T_trans1 break if not check_collision_all(pcd, last_pcd_processed,collision_threshold_init): can_place_last = True x_accu = 0 while True: bbox = get_axis_aligned_bbox(pcd) collision_threshold_init = collision_threshold+1 if bbox['y_max'] >= edge_y_max - collision_threshold_init: pcd.translate([0, -y_step_big, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, -y_step_big, 0] T_trans1 = T_transTemp @ T_trans1 break if check_collision_all(pcd, last_pcd_processed,collision_threshold_init): pcd.translate([0, -y_step_big, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, -y_step_big, 0] T_trans1 = T_transTemp @ T_trans1 break pcd.translate([0, y_step_big, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, y_step_big, 0] T_trans1 = T_transTemp @ T_trans1 #print("Move2 y_step_big", name) else: n = 1 x_accu += x_step_big pcd.translate([x_step_big, 0, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [x_step_big, 0, 0] T_trans1 = T_transTemp @ T_trans1 #""" #""" can_place_last = False x_accu = 0 while True: bbox = get_axis_aligned_bbox(pcd) collision_threshold_init = collision_threshold+2 if bbox['x_max'] >= edge_x_max - collision_threshold_init: if not can_place_last: print("fail to place",name) dict_unplaced[name]=name else: pcd.translate([-x_accu, 0, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [-x_accu, 0, 0] T_trans1 = T_transTemp @ T_trans1 break if not check_collision_all(pcd, last_pcd_processed,collision_threshold_init): can_place_last = True x_accu = 0 while True: bbox = get_axis_aligned_bbox(pcd) collision_threshold_init = collision_threshold+1 if bbox['y_max'] >= edge_y_max - collision_threshold_init: pcd.translate([0, -y_step_big, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, -y_step_big, 0] T_trans1 = T_transTemp @ T_trans1 break if check_collision_all(pcd, last_pcd_processed,collision_threshold_init): pcd.translate([0, -y_step_big, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, -y_step_big, 0] T_trans1 = T_transTemp @ T_trans1 break pcd.translate([0, y_step_big, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, y_step_big, 0] T_trans1 = T_transTemp @ T_trans1 #print("Move2 y_step_big", name) else: n = 1 x_accu += x_step_big pcd.translate([x_step_big, 0, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [x_step_big, 0, 0] T_trans1 = T_transTemp @ T_trans1 #""" """ can_place_last = False x_accu = 0 place_first = True while True: bbox = get_axis_aligned_bbox(pcd) collision_threshold_init = collision_threshold+2 if bbox['x_min'] <= edge_x_min + collision_threshold_init: if not can_place_last: print("fail to place",name) dict_unplaced[name]=name else: pcd.translate([+x_accu, 0, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [+x_accu, 0, 0] T_trans1 = T_transTemp @ T_trans1 place_first = True print("place_first True") break can_break = False if not check_collision_all(pcd, last_pcd_processed,collision_threshold_init): can_place_last = True x_accu = 0 while True: bbox = get_axis_aligned_bbox(pcd) collision_threshold_init = collision_threshold+1 if bbox['y_max'] >= edge_y_max - collision_threshold_init: pcd.translate([0, -y_step_big, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, -y_step_big, 0] T_trans1 = T_transTemp @ T_trans1 can_break = True break if check_collision_all(pcd, last_pcd_processed,collision_threshold_init): pcd.translate([0, -y_step_big, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, -y_step_big, 0] T_trans1 = T_transTemp @ T_trans1 if place_first: can_break = True break pcd.translate([0, y_step_big, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [0, y_step_big, 0] T_trans1 = T_transTemp @ T_trans1 #print("Move2 y_step_big", name) else: n = 1 if can_break: break x_accu += x_step_big pcd.translate([-x_step_big, 0, 0]) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [-x_step_big, 0, 0] T_trans1 = T_transTemp @ T_trans1 #""" last_pcd_processed.append(pcd) """ print("is_x_top",is_x_top) if not is_x_top: last_pcd_processed.append(pcd) print("last_pcd_processed.append",name) else: print("fail last_pcd_processed.append",name, is_x_top) """ # o3d.io.write_point_cloud(os.path.join(output_dir, name), pcd) dict_total_matrix[obj_name]= T_trans1 @ dict_total_matrix[obj_name] def move_to_top_left(pcd, edge_x_min, edge_y_max): points = np.asarray(pcd.points) min_x = np.min(points[:, 0]) max_y = np.max(points[:, 1]) # 当前最大y值 tx = edge_x_min - min_x # ty = -max_y - 0.001 ty = edge_y_max - max_y T_transTemp = np.eye(4) T_transTemp[:3, 3] = [tx, ty, 0] pcd.translate((tx, ty, 0), relative=True) return T_transTemp def move_to_bottom_left(pcd, edge_x_min, edge_y_min): points = np.asarray(pcd.points) min_x = np.min(points[:, 0]) min_y = np.min(points[:, 1]) tx = edge_x_min - min_x ty = edge_y_min - min_y pcd.translate((tx, ty, 0), relative=True) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [tx, ty, 0] return T_transTemp def move_to_bottom_right(pcd, edge_x_max, edge_y_min): points = np.asarray(pcd.points) max_x = np.min(points[:, 0]) min_y = np.min(points[:, 1]) tx = edge_x_max - max_x ty = edge_y_min - min_y pcd.translate((tx, ty, 0), relative=True) T_transTemp = np.eye(4) T_transTemp[:3, 3] = [tx, ty, 0] return T_transTemp def get_axis_aligned_bbox(pcd): points = np.asarray(pcd.points) return { 'x_min': np.min(points[:,0]), 'x_max': np.max(points[:,0]), 'y_min': np.min(points[:,1]), 'y_max': np.max(points[:,1]), 'z_min': np.min(points[:,2]), 'z_max': np.max(points[:,2]) } def down_obj_data_to_ply(weight_fix_out_obj_dir,weight_fix_out_ply_dir): """""" obj_file_list = [aa for aa in os.listdir(weight_fix_out_obj_dir) if aa.endswith(".obj")] for obj_name in obj_file_list: obj_path = os.path.join(weight_fix_out_obj_dir,obj_name) mesh_obj = read_mesh(obj_path) vertices = np.asarray(mesh_obj.vertices) pcd = o3d.geometry.PointCloud() pcd.points = o3d.utility.Vector3dVector(vertices) voxel_size = 3 # 设置体素的大小,决定下采样的密度 pcd_downsampled = down_sample(pcd, voxel_size) ply_out_path = os.path.join(weight_fix_out_ply_dir,obj_name.replace(".obj",".ply")) o3d.io.write_point_cloud(ply_out_path, pcd_downsampled) print(ply_out_path,"下采样完成。") def compute_centroid_compact(pcd): points = np.asarray(pcd.points) centroid = np.mean(points, axis=0) return centroid def compute_base_point(pcd): points = np.asarray(pcd.points) x_center = np.mean(points[:, 0]) y_center = np.mean(points[:, 1]) min_z = np.min(points[:, 2]) return np.array([x_center, y_center, min_z]) import copy def move_obj_to_compact_bounds(bounds_fix_out_dir,bounds_compact_out_dir,weight_fix_out_obj_dir,base_original_obj_dir,compact_obj_out_dir,dict_mesh_obj,dict_unplaced,placed_remove_dir,dict_bad,bad_dir,full_dir,dict_bounds_fix,dict_compact,dict_origin): """""" # obj_file_list = [aa for aa in os.listdir(weight_fix_out_obj_dir) if aa.endswith(".obj")] obj_file_list = list(dict_mesh_obj.keys()) ply_path_dict = {} # meshes = [] # for ply_file_name in os.listdir(bounds_fix_out_dir): for ply_file_name in dict_bounds_fix: ply_dict_key = ply_file_name.split("=")[0] ply_path_dict[ply_dict_key] = ply_file_name for obj_name in obj_file_list: obj_path = os.path.join(weight_fix_out_obj_dir, obj_name) # mesh_obj = read_mesh(obj_path, False) mesh_obj = dict_mesh_obj[obj_name] # mesh_obj = dict_origin[obj_origin_path] original_obj_pid_dir = base_original_obj_dir obj_origin_path = os.path.join(original_obj_pid_dir, obj_name) obj_origin = dict_origin[obj_origin_path] # obj_origin = copy.deepcopy(dict_origin[obj_origin_path]) ply_name_pid = obj_name.replace(".obj","") # ply_name = ply_path_dict[ply_name_pid] ply_name = ply_path_dict.get(ply_name_pid,None) print(ply_name_pid,ply_name) if ply_name is None: continue print("move_obj_to_compact_bounds",ply_name,len(dict_unplaced)) if not ply_name or ply_name in dict_unplaced: print("unplaced",ply_name) continue ply_fix_path = os.path.join(bounds_fix_out_dir,ply_name) ply_compact_path = os.path.join(bounds_compact_out_dir, ply_name) # pcd_fix = o3d.io.read_point_cloud(ply_fix_path) pcd_fix = dict_bounds_fix[ply_name] vertices = np.asarray(obj_origin.vertices) pcd_origin = o3d.geometry.PointCloud() pcd_origin.points = o3d.utility.Vector3dVector(vertices) # pcd_compact = o3d.io.read_point_cloud(ply_compact_path) pcd_compact = dict_compact[ply_name] centroid_fix = compute_centroid_compact(pcd_fix) centroid_compact = compute_centroid_compact(pcd_compact) centroid_origin = compute_centroid_compact(pcd_origin) displacement = centroid_compact - centroid_fix # displacement = centroid_compact - centroid_origin vertices = np.asarray(mesh_obj.vertices) vertices_translated = vertices + displacement # 将位移应用到每个顶点 mesh_obj.vertices = o3d.utility.Vector3dVector(vertices_translated) # 更新网格顶点 obj_pid = obj_name.split("_P")[0] #compact_obj_pid_out_dir = os.path.join(compact_obj_out_dir,obj_pid) compact_obj_pid_out_dir= compact_obj_out_dir if not os.path.exists(compact_obj_pid_out_dir): os.makedirs(compact_obj_pid_out_dir) obj_path_compact = os.path.join(compact_obj_pid_out_dir,obj_name) mesh_obj.compute_vertex_normals() o3d.io.write_triangle_mesh(obj_path_compact, mesh_obj,write_triangle_uvs=True) print(obj_path_compact, "移动后obj保存完成", displacement) # meshes.append(mesh_obj) #original_obj_pid_dir = os.path.join(base_original_obj_dir,obj_pid) original_obj_pid_dir = base_original_obj_dir for mtl in os.listdir(compact_obj_pid_out_dir): if mtl.endswith(".mtl"): if obj_pid in mtl: mtl_path = os.path.join(compact_obj_pid_out_dir,mtl) os.remove(mtl_path) mtl_name = None tex_name = None for file_name in os.listdir(original_obj_pid_dir): if file_name.endswith(".mtl"): if obj_pid in file_name: mtl_name = file_name if file_name.endswith(".jpg"): if obj_pid in file_name: tex_name = file_name if file_name.endswith(".png"): if obj_pid in file_name: tex_name = file_name for file in os.listdir(original_obj_pid_dir): #print(f"file{file}") if file.endswith(".obj"): continue if obj_pid not in file: continue origin_path = os.path.join(original_obj_pid_dir,file) dis_path = os.path.join(compact_obj_pid_out_dir,file) if os.path.isfile(origin_path): #print(f'origin_path{origin_path}') #print(f'dis_path{dis_path}') shutil.copy(origin_path,dis_path) time.sleep(1) #print("-"*50) base_origin_obj_path = os.path.join(original_obj_pid_dir,obj_name) #print(f"base_origin_obj_path{base_origin_obj_path}") #print(f"obj_path_compact{obj_path_compact}") update_obj_file(base_origin_obj_path, obj_path_compact) placed_remove_obj_path = os.path.join(placed_remove_dir, obj_name) shutil.copy(base_origin_obj_path,placed_remove_obj_path) os.remove(base_origin_obj_path) exist_obj_any = False exist_obj = False delete_mtl = False for file_name in os.listdir(original_obj_pid_dir): if file_name.endswith(".obj"): if obj_pid in file_name: exist_obj = True exist_obj_any = True if not exist_obj_any: delete_mtl = True if not exist_obj: delete_mtl = True if delete_mtl: print("delete_mtl",mtl_name,tex_name) if mtl_name!=None: base_origin_mtl_path = os.path.join(original_obj_pid_dir,mtl_name) placed_remove_mtl_path = os.path.join(placed_remove_dir, mtl_name) shutil.copy(base_origin_mtl_path,placed_remove_mtl_path) os.remove(base_origin_mtl_path) if tex_name!=None: base_origin_tex_path = os.path.join(original_obj_pid_dir,tex_name) placed_remove_tex_path = os.path.join(placed_remove_dir, tex_name) shutil.copy(base_origin_tex_path,placed_remove_tex_path) os.remove(base_origin_tex_path) print(f"排版错误模型数量::{len(dict_bad)}") for obj_name in dict_bad: print("--错误模型名:", obj_name) process_obj_files(original_obj_pid_dir,bad_dir,obj_name) print(f"排版剩余模型数量::{len(dict_unplaced)}") for ply_file_name in dict_unplaced: obj_name = ply_file_name.split("=")[0]+".obj" print("--剩余模型名:", obj_name) process_obj_files(original_obj_pid_dir,full_dir,obj_name) import json def extract_angles(R): # 提取绕X、Y、Z轴的旋转角度(弧度) rx_rad = np.arctan2(R[2, 1], R[2, 2]) # X轴旋转 ry_rad = np.arcsin(-R[2, 0]) # Y轴旋转 rz_rad = np.arctan2(R[1, 0], R[0, 0]) # Z轴旋转 # 将弧度转换为角度(度数) rx_deg = np.degrees(rx_rad) ry_deg = np.degrees(ry_rad) rz_deg = np.degrees(rz_rad) return rx_deg, ry_deg, rz_deg def compute_mesh_center(vertices): """ 计算网格质心 参数: vertices: 顶点坐标数组,形状为(N, 3)的NumPy数组或列表 返回: centroid: 质心坐标的NumPy数组 [x, y, z] """ if len(vertices) == 0: raise ValueError("顶点数组不能为空") n = len(vertices) # 顶点数量 # 初始化坐标累加器 sum_x, sum_y, sum_z = 0.0, 0.0, 0.0 # 遍历所有顶点累加坐标值 for vertex in vertices: sum_x += vertex[0] sum_y += vertex[1] sum_z += vertex[2] # 计算各坐标轴的平均值 centroid = np.array([sum_x / n, sum_y / n, sum_z / n]) return centroid import re def extract_numbers_from_filename(filename): """ 从文件名中提取893333, 338908, 105043和x后面的数字 """ # 提取前两个下划线前的数字 first_part = re.findall(r'^(\d+)_(\d+)', filename) if first_part: num1, num2 = first_part[0] else: num1, num2 = None, None # 提取P后面的数字 p_number = re.findall(r'P(\d+)', filename) num3 = p_number[0] if p_number else None # 提取x后面的数字 x_number = re.findall(r'x(\d+)', filename) num4 = x_number[0] if x_number else None return [num for num in [num1, num2, num3, num4] if num is not None] import requests def move_obj_to_compact_bounds_json(base_original_obj_dir,dict_mesh_obj,dict_unplaced,dict_bad,bad_dir,full_dir,dict_bounds_fix, dict_total_matrix,save_mesh,batch_id, print_start_time,selected_machine,selected_mode,version): """生成3D打印布局的JSON数据并保存为3DPrintLayout.json""" # 创建符合3DPrintLayout规范的JSON数据结构 layout_data = { "summary": { "version": version, "homo_matrix": "Homogeneous Matrix", "precision": 6, "selected_machine": selected_machine, "selected_mode": selected_mode }, "models": [] } send_layout_data={ "data": [], "pre_complate_time": 0.0, "pre_batch_id": batch_id, "type_setting_start_time": print_start_time } print(f"need_upload_result={need_upload_result()}") is_need_upload_result = need_upload_result() obj_file_list = list(dict_mesh_obj.keys()) ply_path_dict = {} original_obj_pid_dir = base_original_obj_dir # 构建PLY文件路径映射 for ply_file_name in dict_bounds_fix: ply_dict_key = ply_file_name.split("=")[0] ply_path_dict[ply_dict_key] = ply_file_name for obj_name in obj_file_list: ply_name_pid = obj_name.replace(".obj", "") ply_name = ply_path_dict.get(ply_name_pid, None) if is_need_upload_result: result = extract_numbers_from_filename(ply_name) if not ply_name or ply_name in dict_unplaced: if is_need_upload_result: print_id = result[2] order_id = result[0] status = 0 pid = result[1] counts = result[3] send_layout_data["data"].append({ "print_id": print_id, "order_id": order_id, "status": status, "pid":pid, "counts":counts}) continue # 跳过未放置的模型 total_matrix = dict_total_matrix[obj_name] flattened = total_matrix.flatten()[:16] matrix_4x4 = [ [round(flattened[i], 6) for i in range(0, 4)], # 第1行 [round(flattened[i], 6) for i in range(4, 8)], # 第2行 [round(flattened[i], 6) for i in range(8, 12)], # 第3行 [round(flattened[i], 6) for i in range(12, 16)] # 第4行 ] layout_data["models"].append({ "file_name": obj_name, "transform": { "homo_matrix": matrix_4x4 } }) if is_need_upload_result: print_id = result[2] order_id = result[0] status = 1 pid = result[1] counts = result[3] send_layout_data["data"].append({ "print_id": print_id, "order_id": order_id, "status": status, "pid":pid, "counts":counts}) # 保存JSON文件 # json_path = os.path.join(base_original_obj_dir, "3DPrintLayout.json") json_path = os.path.join(base_original_obj_dir, f"{batch_id}.json") import re json_str = json.dumps(layout_data, ensure_ascii=False, indent=2) json_str = re.sub( r'\[\s*(-?[\d.]+),\s+(-?[\d.]+),\s+(-?[\d.]+),\s+(-?[\d.]+)\s*\]', r'[\1,\2,\3,\4]', json_str ) with open(json_path, "w", encoding='utf-8') as f: f.write(json_str) print(f"3D打印布局已保存至: {json_path}") print(f"排版错误模型数量::{len(dict_bad)}") for obj_name in dict_bad: print("--错误模型名:", obj_name) process_obj_files(original_obj_pid_dir,bad_dir,obj_name) print(f"排版剩余模型数量::{len(dict_unplaced)}") for ply_file_name in dict_unplaced: obj_name = ply_file_name.split("=")[0]+".obj" print("--剩余模型名:", obj_name) process_obj_files(original_obj_pid_dir,full_dir,obj_name) if save_mesh: cache_type_setting_dir=f"{base_original_obj_dir}/arrange" transform_save_o3d(layout_data, original_obj_pid_dir, cache_type_setting_dir) return send_layout_data def process_obj_files(original_obj_pid_dir,placed_remove_dir,obj_name): """ 处理OBJ文件及其相关资源文件的复制、更新和清理 参数: original_obj_pid_dir: 包含原始OBJ文件的目录 placed_remove_dir: 用于存放移除文件的目录 obj_name: 要处理的OBJ文件名 """ base_origin_obj_path = os.path.join(original_obj_pid_dir,obj_name) # 从obj_name中提取PID(产品ID) obj_pid = obj_name.split("_P")[0] # 查找相关的MTL和纹理文件 mtl_name = None tex_name = None for file_name in os.listdir(original_obj_pid_dir): if file_name.endswith(".mtl") and obj_pid in file_name: mtl_name = file_name if (file_name.endswith(".jpg") or file_name.endswith(".png")) and obj_pid in file_name: tex_name = file_name # 将原始OBJ文件移动到移除目录 placed_remove_obj_path = os.path.join(placed_remove_dir, obj_name) shutil.copy(base_origin_obj_path, placed_remove_obj_path) os.remove(base_origin_obj_path) # 检查目录中是否还有其他OBJ文件 exist_obj_any = False exist_obj = False for file_name in os.listdir(original_obj_pid_dir): if file_name.endswith(".obj"): exist_obj_any = True if obj_pid in file_name: exist_obj = True # 确定是否需要删除MTL和纹理文件 delete_mtl = not exist_obj_any or not exist_obj # 如果确定要删除,移动MTL和纹理文件 if delete_mtl: if mtl_name: base_origin_mtl_path = os.path.join(original_obj_pid_dir, mtl_name) placed_remove_mtl_path = os.path.join(placed_remove_dir, mtl_name) shutil.copy(base_origin_mtl_path, placed_remove_mtl_path) os.remove(base_origin_mtl_path) if tex_name: base_origin_tex_path = os.path.join(original_obj_pid_dir, tex_name) placed_remove_tex_path = os.path.join(placed_remove_dir, tex_name) shutil.copy(base_origin_tex_path, placed_remove_tex_path) os.remove(base_origin_tex_path) def update_obj_file(original_obj_path,compact_obj_path): """""" with open(original_obj_path, "r") as f: lines_original = f.readlines() mtllib_name = None mat_name = None for line in lines_original: if line.startswith("mtllib"): mtllib_name = line.split(" ")[1] elif line.startswith("usemtl"): mat_name = line.split(" ")[1] if mtllib_name and mat_name: break with open(compact_obj_path, "r") as f: lines = f.readlines() new_lines = [] for line2 in lines: if line2.startswith("mtllib"): line2 = f"mtllib {mtllib_name}\n" # 替换为原始 MTL 文件路径 elif line2.startswith("usemtl"): line2 = f"usemtl {mat_name}\n" # 替换为原始贴图路径 new_lines.append(line2) with open(compact_obj_path, "w") as f: f.writelines(new_lines) def pass_for_min_dis(placed_models, dict_unplaced, dict_bounds_fix): pcd_all = [] name_list = [] model_list = [] for model in placed_models: # pcd = o3d.io.read_point_cloud(ply_origin_path) pcd = dict_bounds_fix[model['name']] pcd_all.append(pcd) name_list.append(model['name']) model_list.append(model) for idx, pcd in enumerate(pcd_all): y = model_list[idx]['position'][1] dx = model_list[idx]['dimensions'][0] dy = model_list[idx]['dimensions'][1] # print("pass_for_min_dis", name_list[idx], y, dy) delta_y = 20 # safe_y = y - delta_y safe_y = y - dy - delta_y min_y = 0 if safe_y < min_y: name = name_list[idx] print("fail to place (x=0)", name_list[idx], y, dy) dict_unplaced[name]=name if __name__ == '__main__': out_dir = "/data/datasets_20t/type_setting_test_data/" weight_fix_out_obj_dir = f"{out_dir}/print_weight_fix_data_obj" weight_fix_out_ply_dir = f"{out_dir}/data/datasets_20t/type_ssetting_test_data/print_weight_fix_data_ply" base_original_obj_dir=f"{print_factory_type_dir}/8/" if not os.path.exists(weight_fix_out_ply_dir): os.makedirs(weight_fix_out_ply_dir) bounds_fix_out_dir = f"{out_dir}/print_bounds_fix_data" bounds_compact_out_dir = f"{out_dir}/print_bounds_compact_data" compact_obj_out_dir = f"{out_dir}//print_compact_obj" if not os.path.exists(bounds_fix_out_dir): os.mkdir(bounds_fix_out_dir) if not os.path.exists(bounds_compact_out_dir): os.makedirs(bounds_compact_out_dir) if not os.path.exists(compact_obj_out_dir): os.makedirs(compact_obj_out_dir) move_obj_to_compact_bounds(bounds_fix_out_dir,bounds_compact_out_dir,weight_fix_out_obj_dir,base_original_obj_dir,compact_obj_out_dir)