- 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>
56 lines
3.1 KiB
Python
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)
|