You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

310 lines
9.9 KiB

import open3d as o3d
import numpy as np
import re
from config import *
from compute_print_net_out import mesh_transform_by_matrix
from compute_print_net_out import down_sample
from compute_print_net_out import voxel_size
from compute_print_net_out import read_mesh
import shutil
# -------------------------- 开始:运行 ----------------------------------
def is_run_local_data():
if curr_run_mode == run_mode.formal:
return False
return True
def need_upload_result():
if curr_run_mode == run_mode.test:
return False
return True
def is_use_debug_oss():
if curr_run_mode == run_mode.test:
return True
return False
# -------------------------- 结束:运行 ----------------------------------
# -------------------------- 开始:模型 ----------------------------------
def mesh_tranform_to_pcd(mesh, transform_matrix):
vertices = np.asarray(mesh.vertices)
transformed_vertices = mesh_transform_by_matrix(vertices, transform_matrix)
mesh.vertices = o3d.utility.Vector3dVector(transformed_vertices)
return mesh_to_pcd(mesh)
def mesh_to_pcd(mesh, is_down_sample=True):
vertices = np.asarray(mesh.vertices)
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(vertices)
if is_down_sample:
pcd_downsampled = down_sample(pcd, voxel_size, False)
return pcd_downsampled
else:
return pcd
import os
def transform_save_bpy(layout_data, original_obj_pid_dir):
# 清除场景
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)
## 尺寸调整,环境设置
bpy.ops.object.delete(use_global=False, confirm=False)
bpy.context.scene.unit_settings.length_unit = 'CENTIMETERS'
bpy.context.scene.unit_settings.scale_length = 0.001
bpy.context.scene.unit_settings.mass_unit = 'GRAMS'
meshes = []
need_offset = True
for model in layout_data["models"]:
transform = model.get('transform', {})
homo_matrix = transform["homo_matrix"]
reconstructed_matrix = np.array(homo_matrix, dtype=np.float64)
obj_name = model.get('file_name', '')
obj_path = os.path.join(original_obj_pid_dir, obj_name)
mtl_name_temp = obj_name
separator = "_P"
index = mtl_name_temp.find(separator)
if index != -1:
old_mtl_name = mtl_name_temp[:index]
else:
old_mtl_name = mtl_name_temp # 或者你希望的其他处理逻辑,比如直接使用原字符串或报错
old_mtl_name = f"{old_mtl_name}.mtl"
old_mtl_path = os.path.join(original_obj_pid_dir, old_mtl_name)
bpy.ops.wm.obj_import(filepath=obj_path)
imported_object = bpy.context.object
if imported_object is None or imported_object.type != 'MESH':
print(f"警告: 未能成功导入网格对象 {obj_name}。跳过。")
continue
mesh_data = imported_object.data
mesh_data.calc_loop_triangles()
original_vertices = np.empty(len(mesh_data.vertices) * 3, dtype=np.float64)
mesh_data.vertices.foreach_get('co', original_vertices)
original_vertices = original_vertices.reshape(-1, 3)
transformed_vertices = mesh_transform_by_matrix(original_vertices, reconstructed_matrix)
if need_offset:
offset = np.array([-small_machine_size[0], -small_machine_size[1], 0])
transformed_vertices += offset
print(f"已对模型 {obj_name} 应用偏移: {offset}")
flattened_verts = transformed_vertices.reshape(-1)
mesh_data.vertices.foreach_set('co', flattened_verts)
mesh_data.update()
meshes.append(imported_object)
# 导出前确保选中当前对象
bpy.ops.object.select_all(action='DESELECT')
imported_object.select_set(True)
bpy.context.view_layer.objects.active = imported_object
bpy.ops.wm.obj_export(
filepath=obj_path,
export_selected_objects=True,
export_materials=True,
path_mode='AUTO'
)
os.remove(old_mtl_path)
def transform_save_o3d(layout_data, original_obj_pid_dir):
meshes = []
# 小打印机需要偏移[-small_machine_size[0], -small_machine_size[1], 0]
need_offset = True
for model in layout_data["models"]:
transform = model.get('transform', {})
homo_matrix = transform["homo_matrix"] # 获取存储的列表
reconstructed_matrix = np.array(homo_matrix, dtype=np.float64)
obj_name = model.get('file_name', '')
obj_path = os.path.join(original_obj_pid_dir, obj_name)
# 加载网格
try:
mesh = read_mesh(obj_path, enable_post_processing=True)
if not mesh.has_vertices():
print(f"警告: 网格无有效顶点 - {obj_path}")
continue
except Exception as e:
print(f"加载模型失败: {obj_path} - {e}")
continue
original_vertices = np.asarray(mesh.vertices)
transformed_vertices = mesh_transform_by_matrix(original_vertices, reconstructed_matrix)
# 如果 need_offset 为 True,应用额外的偏移
if need_offset:
offset = np.array([-small_machine_size[0], -small_machine_size[1], 0])
transformed_vertices += offset
print(f"已对模型 {obj_name} 应用偏移: {offset}")
mesh.vertices = o3d.utility.Vector3dVector(transformed_vertices)
meshes.append(mesh)
obj_path_arrange = os.path.join(original_obj_pid_dir, "arrange")
if not os.path.exists(obj_path_arrange):
os.mkdir(obj_path_arrange)
obj_path_arrange_obj = os.path.join(obj_path_arrange, obj_name)
print("obj_path_arrange_obj", obj_path_arrange_obj)
mesh.compute_vertex_normals()
o3d.io.write_triangle_mesh(obj_path_arrange_obj, mesh,write_triangle_uvs=True)
def is_multi_obj(obj_name):
pattern = r'_x(\d+)'
match = re.search(pattern, obj_name)
if match:
number = match.group(1)
if int(number) > 1 :
return True
return False
def is_same_obj(obj_name1, obj_name2):
pre_name1 = obj_name1.split("_x")[0]
pre_name2 = obj_name2.split("_x")[0]
# print(f"pre_name1={pre_name1}, pre_name2={pre_name2}")
if (pre_name1==pre_name2):
return True
return False
def get_blank_path(is_small_machine=False):
if is_small_machine:
return os.path.join(print_factory_type_dir, "print_setting/blank/blank_small.obj")
else:
return os.path.join(print_factory_type_dir, "print_setting/blank/blank_big.obj")
def copy_obj_2x(base_obj_dir):
obj_list = [aa for aa in os.listdir(base_obj_dir) if aa.endswith(".obj")]
for obj_name in obj_list:
if "_F" in obj_name:
continue
obj_count = obj_name.split("x")[-1].replace(".obj","")
if not obj_count.isnumeric():
match = re.search(r"x(\d+)", obj_name)
if match:
obj_count = match.group(1)
else:
print("未找到 x 后的数字")
obj_count_num = int(obj_count)
if obj_count_num!=1:
for i in range(obj_count_num-1):
origin_path = os.path.join(base_obj_dir,obj_name)
dis_path = os.path.join(base_obj_dir,obj_name.replace(".obj",f"_F{i+1}.obj"))
if not os.path.exists(dis_path):
shutil.copy(origin_path,dis_path)
print(dis_path,"复制成功")
# -------------------------- 结束:模型 ----------------------------------
# -------------------------- 开始:碰撞检测和越界 --------------------------
extend_dist_border_x_min = 6
extend_dist_border_x_max = 6
extend_dist_border_z_max = 3
extend_dist_border_y_min = 6
extend_dist_border_y_max = 6
extend_dist_model_x = 4
extend_dist_model_y = 2
extend_dist_model_z = 2
extend_dist_box = 1
extend_dist_min_collision = 3
def is_cross_border_c(x, y, z, mx, my, mz, max_x, max_y, max_z):
if (x - mx < extend_dist_border_x_min or
y - my < extend_dist_border_y_min or
z + mz > max_z - extend_dist_border_z_max or
y > max_y - extend_dist_border_y_max):
return True
return False
# -------------------------- 结束:碰撞检测和越界 --------------------------
# -------------------------- 开始:JSON --------------------------
import json
from dataclasses import dataclass
@dataclass
class JSONModelInfo:
obj_name: str
order_id: str
pid: str
print_order_id: str
model_height: str
def read_from_json(json_path):
if not os.path.exists(json_path):
print(f"错误: JSON文件不存在 - {json_path}")
return []
try:
with open(json_path, 'r') as f:
json_data = json.load(f)
except Exception as e:
print(f"读取JSON文件失败: {e}")
return []
return json_data
def read_models_from_json(json_path):
json_data = read_from_json(json_path)
list_model_info = []
# 处理每个模型
for model in json_data.get('models', []):
obj_name = model.get('file_name', '')
parts = obj_name.split('_')
order_id = parts[0]
pid = parts[1]
model_height = parts[3]
model_info = JSONModelInfo(
obj_name=obj_name,
order_id=order_id,
pid=pid,
model_height=model_height
)
list_model_info.append(model_info)
return list_model_info, json_data
def get_summary(json_data):
return json_data.get('summary')
def get_selected_machine(json_data):
return get_summary(json_data)['selected_machine']
def is_small_machine(json_data):
selected_machine = get_selected_machine(json_data)
is_small_machine = True if selected_machine=="小机型" else False
return is_small_machine
# -------------------------- 结束:JSON --------------------------