TellmeStpToGlb/core/converter.py
root 5102bd57e8 feat: 服务化改造STP到GLB转换器
- 🚀 新增FastAPI Web服务支持
-  实现异步任务处理和并发转换
- 📊 添加实时进度追踪(0-100%)
- 🏗️ 重构为模块化架构:core/api/services/utils
- 🔧 完整的任务管理系统和状态追踪
- 📖 自动生成API文档(Swagger/ReDoc)
- 🔄 保持CLI模式100%向后兼容
- 🛡️ 增强错误处理和文件验证
- 📝 更新完整文档(README/CLAUDE.md)

技术栈: FastAPI + uvicorn + pydantic + asyncio
API端点: /health, /api/v1/convert, /api/v1/status, /api/v1/tasks

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-02 09:44:43 +08:00

98 lines
3.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
STP到GLB转换器类
封装原有转换逻辑,支持进度回调
"""
import os
import trimesh
from typing import Callable, Optional
from OCC.Extend.DataExchange import read_step_file, write_stl_file
class StpToGlbConverter:
"""STP到GLB转换器"""
def __init__(self):
self.progress_callback: Optional[Callable[[int, str], None]] = None
def set_progress_callback(self, callback: Callable[[int, str], None]) -> None:
"""设置进度回调函数"""
self.progress_callback = callback
def _update_progress(self, progress: int, message: str) -> None:
"""更新进度"""
if self.progress_callback:
self.progress_callback(progress, message)
def stp_to_stl(self, stp_path: str, stl_path: str) -> None:
"""pythonocc 读 STP 写二进制 STL"""
self._update_progress(5, "检查输入文件...")
if not os.path.isfile(stp_path):
raise FileNotFoundError(f"找不到文件:{stp_path}")
self._update_progress(20, "读取STP文件...")
shape = read_step_file(stp_path)
if shape is None:
raise ValueError(f"无法读取STP文件{stp_path}")
self._update_progress(40, "转换为STL格式...")
write_stl_file(shape, stl_path, mode="binary", linear_deflection=0.01, angular_deflection=0.1)
self._update_progress(60, "STL文件生成完成")
def stl_to_glb(self, stl_path: str, glb_path: str, auto_scale: bool = True, auto_center: bool = True) -> None:
"""使用 trimesh 转换 STL 到 GLB并优化用于Blender"""
self._update_progress(65, "检查STL文件...")
if not os.path.isfile(stl_path):
raise FileNotFoundError(f"找不到STL文件{stl_path}")
self._update_progress(70, "加载STL网格...")
mesh = trimesh.load(stl_path)
if mesh.is_empty:
raise ValueError(f"STL文件为空或无效{stl_path}")
if len(mesh.vertices) == 0 or len(mesh.faces) == 0:
raise ValueError("网格数据无效")
self._update_progress(80, "优化网格...")
# 自动缩放和居中
if auto_scale or auto_center:
bounds = mesh.bounds
max_dimension = max(bounds[1] - bounds[0])
if auto_scale and max_dimension > 1000:
scale_factor = 50.0 / max_dimension
mesh.apply_scale(scale_factor)
if auto_center:
mesh.apply_translation(-mesh.centroid)
self._update_progress(90, "导出GLB文件...")
try:
mesh.export(glb_path)
if os.path.getsize(glb_path) == 0:
raise ValueError("生成的GLB文件为空")
except Exception as e:
raise ValueError(f"GLB导出失败{e}")
self._update_progress(100, "转换完成")
def convert(self, stp_path: str, glb_path: str, auto_scale: bool = True, auto_center: bool = True) -> None:
"""完整的STP到GLB转换流程"""
stl_tmp = os.path.splitext(glb_path)[0] + ".tmp.stl"
try:
self._update_progress(0, "开始转换...")
self.stp_to_stl(stp_path, stl_tmp)
self.stl_to_glb(stl_tmp, glb_path, auto_scale, auto_center)
finally:
# 清理临时文件
if os.path.isfile(stl_tmp):
os.remove(stl_tmp)