95 lines
3.1 KiB
Python
95 lines
3.1 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
STEP → 每 solid 一个 STL + manifest.json(需 cadquery:pip install cadquery)
|
||
用法: python3 step_parse_mvp.py <step_path> <out_dir>
|
||
stdout 打印一行 JSON: {"ok":true} 或 {"ok":false,"error":"..."}
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import json
|
||
import os
|
||
import sys
|
||
|
||
|
||
def main() -> None:
|
||
if len(sys.argv) < 3:
|
||
err = {"ok": False, "error": "usage: step_parse_mvp.py <step_path> <out_dir>"}
|
||
print(json.dumps(err), flush=True)
|
||
sys.exit(2)
|
||
|
||
step_path = sys.argv[1]
|
||
out_dir = sys.argv[2]
|
||
|
||
try:
|
||
import cadquery as cq # type: ignore
|
||
except ImportError as e:
|
||
# pip3 与 python3 可能不是同一解释器,须用「当前解释器」安装:见 sys.executable
|
||
exe = sys.executable
|
||
pip_cmd = (
|
||
f'"{exe}" -m pip install --break-system-packages '
|
||
f"-i https://pypi.tuna.tsinghua.edu.cn/simple cadquery"
|
||
)
|
||
detail = f"{type(e).__name__}: {e}"
|
||
err = {
|
||
"ok": False,
|
||
"error": (
|
||
f"无法 import cadquery({detail})。当前 Python: {exe}。"
|
||
f"请用**同一解释器**安装(勿单独用 pip3,除非确认与 python3 一致): {pip_cmd}"
|
||
),
|
||
}
|
||
print(json.dumps(err, ensure_ascii=False), flush=True)
|
||
sys.exit(1)
|
||
|
||
if not os.path.isfile(step_path):
|
||
err = {"ok": False, "error": f"文件不存在: {step_path}"}
|
||
print(json.dumps(err), flush=True)
|
||
sys.exit(1)
|
||
|
||
os.makedirs(out_dir, exist_ok=True)
|
||
|
||
try:
|
||
wp = cq.importers.importStep(step_path)
|
||
except Exception as e:
|
||
err = {"ok": False, "error": f"importStep: {e}"}
|
||
print(json.dumps(err), flush=True)
|
||
sys.exit(1)
|
||
|
||
solids: list = []
|
||
try:
|
||
solids = list(wp.solids().vals())
|
||
except Exception:
|
||
try:
|
||
solids = [wp.val()]
|
||
except Exception as e:
|
||
err = {"ok": False, "error": f"无法取得实体: {e}"}
|
||
print(json.dumps(err), flush=True)
|
||
sys.exit(1)
|
||
|
||
if not solids:
|
||
err = {"ok": False, "error": "STEP 中未解析出任何 Solid"}
|
||
print(json.dumps(err), flush=True)
|
||
sys.exit(1)
|
||
|
||
parts: list[dict] = []
|
||
for i, solid in enumerate(solids):
|
||
name = f"part_{i:04d}"
|
||
stl_name = f"{name}.stl"
|
||
stl_path = os.path.join(out_dir, stl_name)
|
||
cq.exporters.export(solid, stl_path)
|
||
parts.append({"id": name, "name": name, "stlRelative": stl_name})
|
||
|
||
manifest = {"ok": True, "parts": parts, "sourceStep": os.path.abspath(step_path)}
|
||
man_path = os.path.join(out_dir, "manifest.json")
|
||
with open(man_path, "w", encoding="utf-8") as f:
|
||
json.dump(manifest, f, indent=2, ensure_ascii=False)
|
||
|
||
result_line = json.dumps({"ok": True, "parts": parts, "manifestPath": man_path})
|
||
# Node 端若 stdout 含 OCP 杂讯,仍可从该文件读取结果
|
||
with open(os.path.join(out_dir, "_parse_result.json"), "w", encoding="utf-8") as f:
|
||
f.write(result_line)
|
||
print(result_line, flush=True)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|