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>
This commit is contained in:
commit
964a841de1
3978 files changed
+58013356
No files matched your search
@@ -0,0 +1,115 @@
|
||||
"""G3 gate checker, footing rebar as centreline polylines (Okseong P1, 2026-10-14): mats B1~B8, mid layers B11 / B12,
|
||||
perimeter loops B10, vertical ties B9.
|
||||
|
||||
Globals: __rhino_doc__, EXPECTED_PATH, RESULT_PATH. Expected values (section G3) come from the schedule (L, N), the
|
||||
front / side dimension chains (bar positions), the leg lengths b of the schedule, the drawn mat / loop levels and
|
||||
the B9 grid rule with the user decisions F1-F4; generator params are not read.
|
||||
Checks (C9): counts, original length vs L, per mat: positions vs chain, straight level, span, leg length and
|
||||
direction; mid layers; B10 levels / size; B9 grid / height; containment in the footing; min cover (record).
|
||||
"""
|
||||
import json
|
||||
import math
|
||||
import os
|
||||
import sys
|
||||
|
||||
import Rhino.Geometry as rg
|
||||
|
||||
sys.path.insert(0, os.path.dirname(__file__))
|
||||
from _common import all_objects, chain, load_expected, write_result # noqa: E402
|
||||
|
||||
doc = __rhino_doc__
|
||||
X = load_expected(EXPECTED_PATH)
|
||||
PID, G = X["pier_id"], X["G3"]
|
||||
SCHED = {m: tuple(v) for m, v in G["schedule"].items()}
|
||||
results = []
|
||||
|
||||
|
||||
def check(item, exp, act, tol=1.0):
|
||||
results.append(dict(check="C9", item=item, expected=round(exp, 3), actual=round(act, 3),
|
||||
diff=round(act - exp, 3), tol=tol, result="PASS" if abs(act - exp) <= tol else "FAIL"))
|
||||
|
||||
|
||||
def flag(item, ok, detail=""):
|
||||
results.append(dict(check="C9", item=item, detail=detail, result="PASS" if ok else "FAIL"))
|
||||
|
||||
|
||||
def info(item, detail):
|
||||
results.append(dict(check="C9", item=item, detail=detail, result="INFO"))
|
||||
|
||||
|
||||
def bb(o):
|
||||
return o.Geometry.GetBoundingBox(True)
|
||||
|
||||
|
||||
def worst(a, b):
|
||||
return max(abs(x - y) for x, y in zip(a, b)) if len(a) == len(b) and a else 1e9
|
||||
|
||||
|
||||
def main():
|
||||
cl = {m: [] for m in SCHED}
|
||||
pp = {m: [] for m in SCHED}
|
||||
for o in all_objects(doc):
|
||||
oid = o.Attributes.GetUserString("id") or ""
|
||||
m = o.Attributes.GetUserString("mark")
|
||||
if m in SCHED and oid.startswith(f"{PID}-RC-"):
|
||||
cl[m].append(o)
|
||||
elif m in SCHED and oid.startswith(f"{PID}-R-"):
|
||||
pp[m].append(o)
|
||||
for m, (L, n) in SCHED.items():
|
||||
check(f"{m} bar count vs schedule", n, len(cl[m]), tol=0)
|
||||
flag(f"{m} pipes closed & paired", len(pp[m]) == len(cl[m]) and all(o.Geometry.IsSolid for o in pp[m]), f"{len(pp[m])}/{len(cl[m])}")
|
||||
if cl[m]:
|
||||
check(f"{m} original length vs L (worst)", 0, max(abs(float(o.Attributes.GetUserString("design_length")) - L) for o in cl[m]))
|
||||
half = G["half_a"]
|
||||
for name, mt in G["mats"].items():
|
||||
objs = [o for m in mt["marks"] for o in cl[m]]
|
||||
axis = mt["axis"]
|
||||
pos = sorted(round((bb(o).Min.X + bb(o).Max.X) / 2 if axis == "Y" else (bb(o).Min.Y + bb(o).Max.Y) / 2, 1) for o in objs)
|
||||
want = chain(mt["chain"])
|
||||
check(f"{name} positions vs chain ({len(pos)}/{len(want)}, worst)", 0, worst(pos, want))
|
||||
leg = mt["leg"]
|
||||
straight = [bb(o).Min.Z if leg > 0 else bb(o).Max.Z for o in objs]
|
||||
check(f"{name} straight part level {mt['z']} (worst)", 0, max(abs(z - mt["z"]) for z in straight) if straight else 1e9)
|
||||
span = [(bb(o).Max.Y - bb(o).Min.Y) if axis == "Y" else (bb(o).Max.X - bb(o).Min.X) for o in objs]
|
||||
check(f"{name} span 2 x {half} (worst)", 0, max(abs(s - 2 * half) for s in span) if span else 1e9)
|
||||
legs = [(bb(o).Max.Z - bb(o).Min.Z) for o in objs]
|
||||
check(f"{name} leg {abs(leg)} {'up' if leg > 0 else 'down'} (worst)", 0, max(abs(h - abs(leg)) for h in legs) if legs else 1e9)
|
||||
a, b = mt["marks"]
|
||||
ia = sorted(round((bb(o).Min.X + bb(o).Max.X) / 2 if axis == "Y" else (bb(o).Min.Y + bb(o).Max.Y) / 2, 1) for o in cl[a])
|
||||
flag(f"{name} {a}/{b} alternate from the edge (F3)", ia == want[0::2], f"{a} {len(ia)}")
|
||||
for m, md in G["mid"].items():
|
||||
got = sorted((round(bb(o).Max.Z, 1), round((bb(o).Min.X + bb(o).Max.X) / 2 if md["axis"] == "Y" else (bb(o).Min.Y + bb(o).Max.Y) / 2, 1)) for o in cl[m])
|
||||
want = sorted((md["z_hi"] if round(p) % 1000 == 0 else md["z_lo"], round(p, 1)) for p in chain(md["chain"]))
|
||||
flag(f"{m} levels / positions ({len(want)})", len(got) == len(want) and all(abs(g[0] - w[0]) <= 1 and abs(g[1] - w[1]) <= 1 for g, w in zip(got, want)),
|
||||
f"{got[:3]} vs {want[:3]}")
|
||||
b10 = G["b10"]
|
||||
zs = sorted(round(bb(o).Min.Z, 1) for o in cl["B10"])
|
||||
check("B10 levels (worst)", 0, worst(zs, sorted(b10["levels"])))
|
||||
check("B10 loop size X (worst)", 0, max(abs(bb(o).Max.X - bb(o).Min.X - b10["size"]) for o in cl["B10"]) if cl["B10"] else 1e9)
|
||||
b9 = G["b9"]
|
||||
cols = sorted({round((bb(o).Min.X + bb(o).Max.X) / 2, 1) for o in cl["B9"]})
|
||||
flag(f"B9 columns {b9['n_cols']} @{b9['pitch_x']}", len(cols) == b9["n_cols"] and all(abs(b - a - b9["pitch_x"]) < 1 for a, b in zip(cols, cols[1:])), f"{len(cols)}")
|
||||
check("B9 height top-bottom (worst)", b9["height"], max((bb(o).Max.Z - bb(o).Min.Z for o in cl["B9"]), key=lambda h: abs(h - b9["height"])) if cl["B9"] else 0)
|
||||
flag("B9 hooks the top and bottom Y bars", all(bb(o).Max.Z > G["mats"]["y_top"]["z"] and bb(o).Min.Z < G["mats"]["y_bottom"]["z"] for o in cl["B9"]))
|
||||
# containment and cover
|
||||
ft = [o.Geometry for o in all_objects(doc) if (o.Attributes.GetUserString("id") or "") == f"{PID}-FT"][0]
|
||||
cover = {}
|
||||
for m in SCHED:
|
||||
bad, cov = 0, 1e9
|
||||
r = G["dia"][m] / 2
|
||||
for o in cl[m]:
|
||||
cu = o.Geometry
|
||||
for t in cu.DivideByCount(max(6, int(cu.GetLength() / 300)), True):
|
||||
p = cu.PointAt(t)
|
||||
for q in (p, p + rg.Vector3d(r, 0, 0), p - rg.Vector3d(r, 0, 0), p + rg.Vector3d(0, r, 0),
|
||||
p - rg.Vector3d(0, r, 0), p + rg.Vector3d(0, 0, r), p - rg.Vector3d(0, 0, r)):
|
||||
if not ft.IsPointInside(q, 0.01, False):
|
||||
bad += 1
|
||||
cov = min(cov, p.DistanceTo(ft.ClosestPoint(p)) - r)
|
||||
cover[m] = round(cov, 1)
|
||||
check(f"{m} sample points outside the footing", 0, bad, tol=0)
|
||||
info("min cover to the footing surface per mark (record)", json.dumps(cover))
|
||||
write_result(RESULT_PATH, results, dict(cover=cover))
|
||||
|
||||
|
||||
main()
|
||||
Reference in new issue
Block a user