Files
Pier_v1/Code/검토수정/스크립트/c1_okb9_layout.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

56 lines
3.1 KiB
Python

#! python3
# read-only: layout of Okseong B9 (H19 C-ties) in the latest model: plane, position, extent, tail direction, overlaps
import os, json, math, collections, traceback
import Rhino
P = r"D:\★Pier 자료\프로그램\Pier_T\검토파일\검토_옥성교P1\옥성교P1_G5_수정2_20261026.3dm"
OUT = r"C:\Users\User\AppData\Local\PierApp\jobs\c1_work\c1_okb9_layout.json"
res = {}
try:
doc = Rhino.RhinoDoc.OpenHeadless(P)
st = Rhino.DocObjects.ObjectEnumeratorSettings()
st.HiddenObjects = True; st.LockedObjects = True; st.NormalObjects = True
lay = {l.Index: l.FullPath for l in doc.Layers}
fb = [o for o in doc.Objects.GetObjectList(st) if o.Attributes.Name == "P1-FT"][0].Geometry.GetBoundingBox(True)
bars = []
for o in doc.Objects.GetObjectList(st):
g = o.Geometry
if not (isinstance(g, Rhino.Geometry.PolyCurve) and "중심선" in lay.get(o.Attributes.LayerIndex, "")):
continue
if o.Attributes.GetUserString("mark") != "B9":
continue
s0, sN = g.SegmentCurve(0), g.SegmentCurve(g.SegmentCount - 1)
pts = [g.SegmentCurve(i).PointAtStart for i in range(g.SegmentCount)] + [sN.PointAtEnd]
xs = [p.X for p in pts]; ys = [p.Y for p in pts]
planeX = (max(xs) - min(xs)) < 1.0 # all points share x -> bar lies in the YZ plane
planeY = (max(ys) - min(ys)) < 1.0
if planeX:
c, lo, hi = xs[0], min(ys), max(ys)
tail_dir = "tails toward %s" % ("+Y" if s0.PointAtEnd.Y > s0.PointAtStart.Y else "-Y")
plane = "YZ(x=const)"
elif planeY:
c, lo, hi = ys[0], min(xs), max(xs)
tail_dir = "tails toward %s" % ("+X" if s0.PointAtEnd.X > s0.PointAtStart.X else "-X")
plane = "XZ(y=const)"
else:
plane, c, lo, hi, tail_dir = "other", None, None, None, ""
bars.append({"name": o.Attributes.Name, "plane": plane, "c": c, "lo": lo, "hi": hi, "tail": tail_dir,
"zmin": g.GetBoundingBox(True).Min.Z - fb.Min.Z, "zmax": g.GetBoundingBox(True).Max.Z - fb.Min.Z})
cnt = collections.Counter((b["plane"]) for b in bars)
lines = collections.defaultdict(list)
for b in bars:
lines[(b["plane"], round(b["c"], 1) if b["c"] is not None else None)].append((round(b["lo"], 1), round(b["hi"], 1), b["tail"]))
summary = []
for (pl, c), iv in sorted(lines.items(), key=lambda x: (x[0][0], x[0][1] if x[0][1] is not None else 0)):
iv.sort()
overlaps = sum(1 for a, b2 in zip(iv, iv[1:]) if b2[0] < a[1])
summary.append({"plane": pl, "const": c, "n": len(iv), "first": iv[:3], "overlapping_neighbours": overlaps})
res = {"n": len(bars), "planes": dict(cnt), "footing_half": [round(fb.Max.X, 1), round(fb.Max.Y, 1)], "lines": summary[:60],
"n_lines": len(summary), "tail_dirs": dict(collections.Counter(b["tail"] for b in bars)),
"z": [round(min(b["zmin"] for b in bars), 1), round(max(b["zmax"] for b in bars), 1)]}
doc.Dispose()
except Exception:
res["error"] = traceback.format_exc()
res["done"] = True
json.dump(res, open(OUT, "w", encoding="utf-8"), ensure_ascii=False, indent=1)