Solidworks导出GLB格式完善
通过Solidworks——>STL——>GLB,相较于C#库实现更快,其中,用到了pythoncom、trimesh库
话不多说,直接上代码
点击查看代码
import win32com.client
import pythoncom
import trimesh
import os
import time
from pathlib import Path
import gc
class SolidWorksAPI:
"""SolidWorks API封装类,负责与SolidWorks应用程序交互"""
def __init__(self, visible=True):
self.visible = visible
self.app = None
def __enter__(self):
self.connect()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.disconnect()
def connect(self):
"""连接到SolidWorks应用程序"""
try:
self.app = win32com.client.Dispatch("SldWorks.Application")
self.app.Visible = self.visible
return True
except Exception as e:
print(f"连接SolidWorks失败: {e}")
return False
def disconnect(self):
"""断开与SolidWorks的连接并释放资源"""
if self.app:
try:
self.app.ExitApp()
except:
pass
self.app = None
gc.collect()
def export_to_stl(self, file_path, output_dir=None):
"""导出SolidWorks文件为STL格式"""
if not self.app:
print("未连接到SolidWorks应用程序")
return None
try:
doc_type = 1 if file_path.lower().endswith('.sldprt') else 2
# 打开文档
errors = win32com.client.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_I4, 0)
warnings = win32com.client.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_I4, 0)
sw_model = self.app.OpenDoc6(file_path, doc_type, 0, "", errors, warnings)
if errors.value != 0 or not sw_model:
print(f"无法打开文件: {file_path}")
return None
# 准备输出路径
file_name = os.path.basename(file_path)
if output_dir is None:
output_dir = os.path.dirname(file_path)
stl_path = os.path.join(output_dir, f"{file_name}.stl")
# 导出STL
save_options = 2 # 覆盖现有文件
sw_model.SaveAs3(stl_path, 0, save_options)
# 验证STL文件
if not self._validate_stl(stl_path):
return None
print(f"成功导出STL: {stl_path}")
return stl_path
except Exception as e:
print(f"导出STL时出错: {e}")
return None
finally:
# 确保关闭文档
if self.app and sw_model:
self.app.CloseDoc(os.path.basename(file_path))
gc.collect()
def _validate_stl(self, stl_path):
"""验证STL文件有效性"""
if not os.path.exists(stl_path):
print("STL文件未生成")
return False
file_size = os.path.getsize(stl_path)
if file_size < 1024:
print("生成的STL文件异常小")
return False
return True
class FileConverter:
"""文件转换工具类,负责STL到GLB的转换"""
@staticmethod
def stl_to_glb(stl_path, glb_path=None, simplify_ratio=0.5):
"""将STL文件转换为GLB文件"""
if not stl_path or not os.path.exists(stl_path):
print(f"STL文件不存在: {stl_path}")
return None
try:
print(f"正在将STL转换为GLB: {stl_path}")
# 加载STL文件
mesh = trimesh.load_mesh(stl_path)
# 处理多网格场景
if isinstance(mesh, trimesh.Scene):
print("检测到多网格场景,正在合并...")
mesh = mesh.dump().sum()
# 获取原始网格信息
original_faces = len(mesh.faces)
# 简化网格以提高性能(可选)
if simplify_ratio < 1.0:
target_faces = int(original_faces * simplify_ratio)
if target_faces > 1000: # 确保简化后的网格不会过小
print(f"正在简化网格: {original_faces} 面 -> {target_faces} 面")
# mesh = mesh.simplify_vertex_clustering(ratio=simplify_ratio)
mesh = mesh.simplify_quadric_decimation(percent=simplify_ratio, aggression=10)
else:
print(f"目标面数太少 ({target_faces}),取消简化")
# 准备输出路径
if glb_path is None:
glb_path = os.path.splitext(stl_path)[0] + ".glb"
# 导出为GLB
mesh.export(glb_path, file_type='glb')
# 打印转换结果
glb_size = os.path.getsize(glb_path)
print(f"成功创建GLB: {glb_path} ({glb_size / 1024:.2f} KB)")
print(f"网格信息: {len(mesh.vertices)} 顶点, {len(mesh.faces)} 面")
return glb_path
except Exception as e:
print(f"STL转GLB时出错: {e}")
return None
class BatchProcessor:
"""批量处理工具类,负责处理目录中的所有文件"""
def __init__(self, input_dir, output_dir=None, simplify_ratio=0.5):
self.input_dir = input_dir
self.output_dir = output_dir or os.path.join(input_dir, "generated_glb")
self.simplify_ratio = simplify_ratio
def process(self):
"""处理目录中的所有SolidWorks文件"""
# 创建输出目录
os.makedirs(self.output_dir, exist_ok=True)
# 获取所有SolidWorks文件
solidworks_files = self._get_solidworks_files()
total_files = len(solidworks_files)
if total_files == 0:
print("未找到SolidWorks文件")
return 0, []
print(f"\n找到 {total_files} 个SolidWorks文件")
success_count = 0
# 使用上下文管理器确保资源释放
with SolidWorksAPI(visible=True) as sw_api:
for i, file_path in enumerate(solidworks_files, 1):
print(f"\n[{i}/{total_files}] 处理文件: {file_path}")
# 导出为STL
stl_path = sw_api.export_to_stl(file_path, self.output_dir)
if not stl_path:
continue
# 转换为GLB
glb_path = FileConverter.stl_to_glb(stl_path, None, self.simplify_ratio)
if glb_path:
print(f"✓ 成功转换: {os.path.basename(file_path)}")
success_count += 1
# 删除临时STL文件
try:
os.remove(stl_path)
print(f"已删除临时STL文件: {stl_path}")
except Exception as e:
print(f"删除STL文件时出错: {e}")
return success_count, solidworks_files
def _get_solidworks_files(self):
"""获取目录中所有SolidWorks文件"""
solidworks_files = []
for ext in ['.sldprt', '.sldasm']:
solidworks_files.extend(
[str(f) for f in Path(self.input_dir).rglob(f'*{ext}') if not f.name.startswith('~$')]
)
return solidworks_files
def main():
"""主函数"""
start_time = time.time()
# 设置输入和输出目录
input_dir = r"D:\projects\Data\"
output_dir = r"D:\projects\CSharpAndSolidWorks-master\data\glb"
# 检查输入目录是否存在
if not os.path.exists(input_dir):
print(f"输入目录不存在: {input_dir}")
return
# 设置网格简化比例
simplify_ratio = 0.7
print(f"\n开始转换SolidWorks文件到GLB")
print(f"输入目录: {input_dir}")
print(f"输出目录: {output_dir}")
print(f"网格简化比例: {simplify_ratio:.0%}")
# 初始化COM库
pythoncom.CoInitialize()
try:
# 创建并运行批量处理器
processor = BatchProcessor(input_dir, output_dir, simplify_ratio)
success_count, solidworks_files = processor.process()
print(f"\n处理完成! 共尝试 {len(solidworks_files)} 个文件")
print(f"成功转换 {success_count} 个文件")
print(f"总耗时: {time.time() - start_time:.2f} 秒")
finally:
# 释放COM库
pythoncom.CoUninitialize()
if __name__ == "__main__":
main()
这里我尝试导出了一些装配体和零件,效率如下
当然,代码中存在着一些地方需要完善,
1、当频繁打开文件时,solidworks内存占用会增大
2、简化mesh代码需要根据需求自行调试
3、代码效率收到solidworks打开装配体效率影响