#!/usr/bin/env python3 """ STEP → 每 solid 一个 STL + manifest.json(需 cadquery:pip install cadquery) 用法: python3 step_parse_mvp.py 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 "} 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()