Files
Pier_v1/Code/교각모델링앱/engine/rhino/fingerprint.py
T
ahnyongjooandClaude Sonnet 5.5 964a841de1 chore(rebar): Pier_T_rebar 작업 폴더 초기 구성 및 외부 의존 파일 통합
- Code\rebar_pipeline, review_pipeline, pier-program을 정션에서 실제 폴더로 전환
- Code\rhino_mcp 및 CLAUDE_rhino배경.md 추가, .mcp.json은 PYTHONPATH로 새 위치 사용
- pier-program 내부 .git 제거(이력은 backup\pier-program_20261028.bundle에 보관)
- worktree 가이드 반영(CLAUDE.local.md, HANDOFF.md)
- D:\Rhino-MCP 경로 참조를 새 위치로 치환

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-28 11:20:18 +09:00

53 lines
2.6 KiB
Python

"""Fingerprint a .3dm (run inside Rhino 8 via runner). Globals: MODEL_PATH, OUT_PATH, optional FAST.
Opens MODEL_PATH headless (the active doc is untouched) and writes, per object id (user string `id`,
falling back to the object name): layer path, geometry type, visibility, colour, bbox (0.01 mm),
brep face count / solidity / volume (mm3, 1 decimal), curve length (0.001 mm) and all user strings.
Hidden and locked objects are included.
"""
import json
import Rhino
import Rhino.Geometry as rg
from Rhino.DocObjects import ObjectEnumeratorSettings
FAST = globals().get("FAST", False)
d = Rhino.RhinoDoc.OpenHeadless(MODEL_PATH)
if d is None:
raise RuntimeError(f"cannot open {MODEL_PATH}")
try:
s = ObjectEnumeratorSettings()
s.HiddenObjects = True
s.LockedObjects = True
objs, layers = {}, {}
for o in d.Objects.GetObjectList(s):
a = o.Attributes
oid = a.GetUserString("id") or a.Name or str(o.Id)
lay = d.Layers[a.LayerIndex]
layers[lay.FullPath] = [lay.Color.R, lay.Color.G, lay.Color.B, lay.IsVisible]
g = o.Geometry
bb = g.GetBoundingBox(True)
rec = {"layer": lay.FullPath, "type": type(g).__name__, "hidden": o.IsHidden, "locked": o.IsLocked,
"colour_source": int(a.ColorSource), "colour": [a.ObjectColor.R, a.ObjectColor.G, a.ObjectColor.B],
"bbox": [round(v, 2) for v in (bb.Min.X, bb.Min.Y, bb.Min.Z, bb.Max.X, bb.Max.Y, bb.Max.Z)],
"user": {k: a.GetUserString(k) for k in sorted(a.GetUserStrings().AllKeys)}}
b = g if isinstance(g, rg.Brep) else (rg.Brep.TryConvertBrep(g) if isinstance(g, rg.Extrusion) else None)
if b is not None:
rec["faces"], rec["solid"] = b.Faces.Count, b.IsSolid
if FAST and "-R-" in oid: # rebar pipe: bbox + face count only (volume dominates run time)
rec["volume"] = "skipped"
else:
mp = rg.VolumeMassProperties.Compute(b) if b.IsSolid else None
rec["volume"] = round(mp.Volume, 1) if mp else None
elif isinstance(g, rg.Curve):
rec["length"] = round(g.GetLength(), 3)
if oid in objs:
oid = f"{oid}#dup{sum(k.startswith(oid) for k in objs)}"
objs[oid] = rec
out = {"model": MODEL_PATH, "units": str(d.ModelUnitSystem), "tolerance": d.ModelAbsoluteTolerance,
"count": len(objs), "layers": layers, "objects": objs}
json.dump(out, open(OUT_PATH, "w", encoding="utf-8"), ensure_ascii=False)
print(json.dumps({"count": len(objs), "units": out["units"], "tolerance": out["tolerance"]}))
finally:
d.Dispose()