- 新增XCAF转换器,直接从STP到GLB保留完整装配层级 - 修复HTTP API与CLI参数不一致问题 - 修复静默吞没错误的问题,遵循快速失败原则 - 清理旧文件,整理测试文件到tests目录 - 添加URL下载支持,可直接转换远程STP文件 - 更新文档,准确描述XCAF装配保留功能 技术改进: - 使用STEPCAFControl_Reader读取带装配信息的STEP文件 - 通过RWGltf_CafWriter直接导出GLB,无需STL中间格式 - 支持CPU多线程并行三角化 - HTTP API和CLI使用完全一致的转换参数 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
121 lines
4.5 KiB
Python
121 lines
4.5 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
STP到GLB转换器类
|
||
使用XCAF直接保留装配结构,无需STL中间步骤
|
||
"""
|
||
|
||
import os
|
||
from typing import Callable, Optional, List, Dict, Literal
|
||
from utils.network_helper import is_url, download_file, cleanup_downloaded_file
|
||
|
||
# 导入XCAF转换器
|
||
try:
|
||
from .converter_xcaf import XCAFConverter, check_xcaf_availability
|
||
XCAF_AVAILABLE = True
|
||
except ImportError:
|
||
XCAF_AVAILABLE = False
|
||
XCAFConverter = None
|
||
|
||
|
||
class StpToGlbConverter:
|
||
"""STP到GLB转换器"""
|
||
|
||
def __init__(self):
|
||
"""初始化转换器,使用XCAF管线"""
|
||
self.progress_callback: Optional[Callable[[int, str], None]] = None
|
||
self.downloaded_file_path: Optional[str] = None # 记录下载的临时文件路径
|
||
|
||
# 检查XCAF可用性
|
||
if not XCAF_AVAILABLE:
|
||
raise RuntimeError("XCAF模块不可用,请检查pythonocc安装")
|
||
|
||
self.xcaf_converter = XCAFConverter()
|
||
if not self.xcaf_converter.is_available():
|
||
status = self.xcaf_converter.get_availability_status()
|
||
raise RuntimeError(f"XCAF转换器不可用: {status['message']}")
|
||
|
||
def set_progress_callback(self, callback: Callable[[int, str], None]) -> None:
|
||
"""设置进度回调函数"""
|
||
self.progress_callback = callback
|
||
if self.xcaf_converter:
|
||
self.xcaf_converter.set_progress_callback(callback)
|
||
|
||
def _update_progress(self, progress: int, message: str) -> None:
|
||
"""更新进度"""
|
||
if self.progress_callback:
|
||
self.progress_callback(progress, message)
|
||
|
||
def _prepare_input_file(self, stp_path: str) -> str:
|
||
"""
|
||
准备输入文件(下载URL或验证本地文件)
|
||
|
||
Args:
|
||
stp_path: STP文件路径或URL
|
||
|
||
Returns:
|
||
str: 本地文件路径
|
||
"""
|
||
if is_url(stp_path):
|
||
self._update_progress(1, f"检测到URL输入: {stp_path}")
|
||
# 下载文件到临时位置
|
||
self.downloaded_file_path = download_file(stp_path, self.progress_callback)
|
||
self._update_progress(95, f"文件下载完成: {self.downloaded_file_path}")
|
||
return self.downloaded_file_path
|
||
else:
|
||
# 本地文件验证
|
||
self._update_progress(5, "检查本地输入文件...")
|
||
if not os.path.isfile(stp_path):
|
||
raise FileNotFoundError(f"找不到文件:{stp_path}")
|
||
return stp_path
|
||
|
||
def _cleanup_downloaded_file(self) -> None:
|
||
"""清理下载的临时文件"""
|
||
if self.downloaded_file_path:
|
||
cleanup_downloaded_file(self.downloaded_file_path)
|
||
self.downloaded_file_path = None
|
||
|
||
def convert(self, stp_path: str, glb_path: str,
|
||
linear_deflection: float = 0.01, angular_deflection: float = 0.1,
|
||
embed_textures: bool = True, y_up: bool = True, **kwargs) -> None:
|
||
"""
|
||
STP到GLB转换,直接保留装配结构
|
||
|
||
Args:
|
||
stp_path: 输入STEP文件路径或URL(支持HTTP/HTTPS)
|
||
glb_path: 输出GLB文件路径
|
||
linear_deflection: 线性偏差(控制网格精度)
|
||
angular_deflection: 角度偏差(控制网格精度)
|
||
embed_textures: 是否嵌入纹理
|
||
y_up: 是否使用Y向上坐标系
|
||
**kwargs: 忽略的其他参数(用于兼容性)
|
||
"""
|
||
try:
|
||
# 准备输入文件(可能需要下载)
|
||
local_stp_path = self._prepare_input_file(stp_path)
|
||
|
||
# 使用XCAF转换,保留装配结构
|
||
self.xcaf_converter.convert_with_xcaf(
|
||
local_stp_path, glb_path,
|
||
embed_textures=embed_textures,
|
||
y_up=y_up,
|
||
linear_deflection=linear_deflection,
|
||
angular_deflection=angular_deflection
|
||
)
|
||
finally:
|
||
# 清理下载的文件
|
||
self._cleanup_downloaded_file()
|
||
|
||
def get_info(self) -> dict:
|
||
"""获取转换器信息"""
|
||
status = self.xcaf_converter.get_availability_status() if self.xcaf_converter else {}
|
||
return {
|
||
"converter": "XCAF",
|
||
"capabilities": {
|
||
"assembly_hierarchy": True,
|
||
"component_names": True,
|
||
"colors": True,
|
||
"materials": True,
|
||
"instances": True
|
||
},
|
||
"status": status
|
||
} |