- 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>
95 lines
5.5 KiB
Python
95 lines
5.5 KiB
Python
"""R3 (footing rebar) reading of the Ungok P2 drawings -> params.footing_rebar / rebar_marks(B*) / expected.G3.
|
||
|
||
Drawn facts (D1 front / side view dots, relative to the view centre, z above the footing bottom):
|
||
- layer heights as P1 (F1 rule): 122 / 178 / 227.5 / 277 / 2073 / 2127; B10 rings 350..1950 @200, dots x 5093 / y 3818
|
||
- front (Y-direction bars at X): ends +-5075, series -4875 + 125 i (79) -> B2/B4; -4875 + 250 i (40) -> B1, B3
|
||
- side (X-direction bars at Y): as P1 (+-3800, -3625 + 125 i (59) / + 250 i (30))
|
||
- mid layers: B12 (front) 550/1350: +-1875, 2875, 3875; 950/1750: +-375 .. +-4375 -> 32 drawn (D3 38);
|
||
B11 (side) as P1 -> 28 (D3 28)
|
||
- B9 EREC lines x -4625 .. 4625 @250 (38), y -3500 .. 3500 @250 (29), z 150..2100 -> checker 551 drawn (D3 493)
|
||
Conflicts B9 / B12 count: drawn adopted (P1 rule F2), schedule difference recorded as planned FAIL.
|
||
"""
|
||
import json
|
||
import shutil
|
||
import sys
|
||
import time
|
||
from pathlib import Path
|
||
|
||
HERE = Path(__file__).resolve().parent
|
||
APP = HERE.parent / "교각모델링앱"
|
||
PIER = APP / "data" / "운곡교p2"
|
||
sys.path.insert(0, str(HERE))
|
||
from extract_r2 import schedule # noqa: E402
|
||
|
||
|
||
def series(start, pitch, n):
|
||
return [float(start + pitch * i) for i in range(n)]
|
||
|
||
|
||
def sym(vals):
|
||
return sorted([-v for v in vals] + list(vals))
|
||
|
||
|
||
def main():
|
||
S = schedule()
|
||
P = json.loads((PIER / "params.json").read_text(encoding="utf-8"))
|
||
E = json.loads((PIER / "expected.json").read_text(encoding="utf-8"))
|
||
stamp = time.strftime("%Y%m%d_%H%M%S")
|
||
for f in ("params.json", "expected.json"):
|
||
shutil.copy2(PIER / f, PIER / "backup" / f"{Path(f).stem}_before_R3_{stamp}.json")
|
||
fr = P["footing_rebar"]
|
||
y_bot = sorted([-5075.0, 5075.0] + series(-4875, 125, 79))
|
||
y_250 = sorted([-5075.0, 5075.0] + series(-4875, 250, 40))
|
||
L = fr["layers"]
|
||
L["bottom_Y1"]["pos"], L["bottom_Y3"]["pos"], L["top_Y"]["pos"] = y_bot, y_250, y_250
|
||
mid_y = {"550.0": sym([1875.0, 2875.0, 3875.0]), "950.0": sym([375.0, 1375.0, 2375.0, 3375.0, 4375.0]),
|
||
"1350.0": sym([1875.0, 2875.0, 3875.0]), "1750.0": sym([375.0, 1375.0, 2375.0, 3375.0, 4375.0])}
|
||
L["mid_Y"]["levels"] = mid_y
|
||
fr["a_x"], fr["a_y"] = float(S["B5"]["A"]) * 1000, float(S["B1"]["A"]) * 1000
|
||
fr["a_src"] = "D3 B5 a '10.150' (X bars), B1 a '7.600' (Y bars)"
|
||
fr["b9"].update({"grid_x": series(-4625, 250, 38), "count": 551,
|
||
"src": "D1 정면 EREC x -4625..4625 @250 (chain '450','37@250=9.250'), 측면 -3500..3500 @250; "
|
||
"checker parity as P1 -> 551 drawn; D3 개수 493 (= P1 value) -> CONFLICT, drawn adopted"})
|
||
fr["b10"].update({"size_x": float(S["B10"]["A"]) * 1000, "size_y": float(S["B10"]["B"]) * 1000,
|
||
"src": "D1 정면 '150','9@200=1.800'; dots x=5093 / y=3818; D3 B10 a 10.198 b 7.644"})
|
||
fr["_note"] = "Footing rebar B1-B12 (Ungok P2); z above the footing bottom EL 25.123"
|
||
rows = {}
|
||
for m in ("B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "B10", "B11", "B12"):
|
||
r = S[m]
|
||
rows[m] = [m, r["형식"], r.get("직경", ""), r["개수"], r["A"]] + [r[k] for k in ("B", "C") if k in r] + [r["길이"], r["총길이"]]
|
||
P["rebar_marks"][m] = {"dia": r["_dia"], "shape": r["형식"]}
|
||
fr["schedule"] = rows
|
||
fr["counts_check"] = {"bottom_Y1": len(y_bot), "bottom_X2": len(L["bottom_X2"]["pos"]), "bottom_Y3": len(y_250),
|
||
"bottom_X4": len(L["bottom_X4"]["pos"]), "top_Y": len(y_250), "top_X": len(L["top_X"]["pos"]),
|
||
"mid_X": sum(len(v) for v in L["mid_X"]["levels"].values()),
|
||
"mid_Y": sum(len(v) for v in mid_y.values())}
|
||
sched = {m: [round(float(S[m]["길이"]) * 1000), int(S[m]["개수"])] for m in rows}
|
||
g3 = E["G3"]
|
||
g3.update({
|
||
"schedule": sched,
|
||
"dia": {m: int(S[m]["_dia"][1:]) for m in rows},
|
||
"rows": {"Y_BOT": {"ends": [-5075, 5075], "start": -4875, "pitch": 125, "n": 79},
|
||
"Y_250": {"ends": [-5075, 5075], "start": -4875, "pitch": 250, "n": 40},
|
||
"X_BOT": {"ends": [-3800, 3800], "start": -3625, "pitch": 125, "n": 59},
|
||
"X_250": {"ends": [-3800, 3800], "start": -3625, "pitch": 250, "n": 30}},
|
||
"b10_size": [10198, 7644],
|
||
"b9_grid": {"x": {"start": -4625, "pitch": 250, "n": 38}, "y": {"start": -3500, "pitch": 250, "n": 29}},
|
||
"src": "D3 L·수량 (P2); D1 '100','200','78@125=9.750' / '39@250=9.750' / '100','175','58@125=7.250' / '29@250'; "
|
||
"F1 층 높이(작도점, P1과 같음); '150','9@200=1.800'; '450','37@250=9.250' / '300','28@250=7.000'; "
|
||
"EREC 150~2100; 중간층 작도점 [derived]",
|
||
})
|
||
pf = [x for x in E.get("planned_fail", []) if x["gate"] != "G3"]
|
||
pf += [{"gate": "G3", "item": "B12 bar count vs schedule", "reason": "작도 32본 채택 vs D3 38본 (P1 F2 규칙, P1도 28/34)",
|
||
"approved": "P1 결정(2026-10-07) 준용 — P2 사용자 확인 대기"},
|
||
{"gate": "G3", "item": "B9 bar count vs schedule", "reason": "작도 551본(38×29 엇갈림) 채택 vs D3 493본(P1 값 그대로)",
|
||
"approved": "P1 결정(2026-10-07) 준용 — P2 사용자 확인 대기"}]
|
||
E["planned_fail"] = pf
|
||
(PIER / "params.json").write_text(json.dumps(P, ensure_ascii=False, indent=1), encoding="utf-8")
|
||
(PIER / "expected.json").write_text(json.dumps(E, ensure_ascii=False, indent=1), encoding="utf-8")
|
||
print("counts", fr["counts_check"], "b9", fr["b9"]["count"], "a", fr["a_x"], fr["a_y"], "b10", fr["b10"]["size_x"])
|
||
print("schedule", sched)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|