- 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>
58 lines
2.5 KiB
Python
58 lines
2.5 KiB
Python
"""Ulsan P1 rebar schedule (배근도(3) 철근재료표 SD400 / SD500) -> 판독/schedule.json.
|
|
|
|
The header row's column x positions (A, B, C, D, E, R, X1..X4, J, length, total) are taken from the drawing;
|
|
the first four columns (번호, 형식, 직경, 개수) are fixed left columns. Each data row (first cell = mark) is
|
|
mapped to the nearest header column. Ditto marks are resolved within a table. Values in m are kept as text.
|
|
"""
|
|
import json
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
HERE = Path(__file__).resolve().parent
|
|
T = json.loads((HERE.parent / "교각모델링앱" / "data" / "산외교울산P2" / "drawings" / "texts.json").read_text(encoding="utf-8"))
|
|
MARK = re.compile(r"^[A-Z]{1,2}\d{1,2}$")
|
|
|
|
|
|
def table(x0, x1, y_top, y_bot):
|
|
cells = [t for t in T if x0 <= t["x"] <= x1 and y_bot <= t["y"] <= y_top]
|
|
head = [t for t in cells if t["text"] in ("A", "B", "C", "D", "E", "R", "J")]
|
|
hy = max(round(t["y"]) for t in head) if head else None
|
|
cols = {t["text"]: t["x"] for t in head if abs(t["y"] - hy) < 100}
|
|
rows = {}
|
|
for t in cells:
|
|
rows.setdefault(round(t["y"] / 60), []).append(t)
|
|
out = []
|
|
for k in sorted(rows, reverse=True):
|
|
r = sorted(rows[k], key=lambda t: t["x"])
|
|
if not MARK.match(r[0]["text"]):
|
|
continue
|
|
rec = {"mark": r[0]["text"], "y": r[0]["y"]}
|
|
rest = r[1:]
|
|
for name, t in zip(("shape", "dia", "n"), rest[:3]):
|
|
rec[name] = t["text"]
|
|
for t in rest[3:]:
|
|
name = min(cols, key=lambda c: abs(cols[c] - t["x"]))
|
|
if abs(cols[name] - t["x"]) < 450 and name not in rec:
|
|
rec[name] = t["text"]
|
|
else:
|
|
rec.setdefault("_right", []).append((round(t["x"]), t["text"]))
|
|
out.append(rec)
|
|
return out, cols
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import math
|
|
# locate the two tables by their titles
|
|
sd = {t["text"]: t for t in T if t["text"] in ("(SD400)", "(SD500)") and t["h"] < 300}
|
|
res = {}
|
|
for key, t in sd.items():
|
|
other = [o for o in sd.values() if o is not t and o["y"] < t["y"]]
|
|
y_bot = max(o["y"] for o in other) + 500 if other else t["y"] - 15000
|
|
recs, cols = table(t["x"] - 500, t["x"] + 22000, t["y"], y_bot)
|
|
res[key] = {"columns": cols, "rows": recs}
|
|
print(key, "columns", sorted(cols), "rows", len(recs))
|
|
for r in recs:
|
|
print(" ", {k: v for k, v in r.items() if k != "y"})
|
|
(HERE / "판독" / "schedule.json").write_text(json.dumps(res, ensure_ascii=False, indent=1), encoding="utf-8")
|