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:
ahnyongjooandClaude Sonnet 5.5 committed 2026-10-28 11:20:18 +09:00
commit 964a841de1
3978 files changed
+58013356

No files matched your search

@@ -0,0 +1,190 @@
# -*- coding: utf-8 -*-
"""운곡교 P1 재료표 도면(DXF) 대조본 작성.
도면 재료표(3.dxf)와 같은 칸 구성(열 위치·글자 높이·레이어)에 마크마다 두 줄(도면 / 모델)을 놓고,
다른 칸을 색으로 칠하고 오른쪽에 비고 열(비고 · 비고 3 KDS)을 붙인다.
입력: 추출데이터\재료표_대조결과.json (make_bom_compare.py 가 만든다), 3.dxf (스타일·레이어 상속)
사용: python -I make_bom_dxf.py <pylib경로> <대조결과.json> <출력.dxf>
"""
import sys, json, math
sys.path.insert(0, sys.argv[1])
import ezdxf
from ezdxf.enums import TextEntityAlignment
from ezdxf.lldxf import const
SRC = r"D:\★Pier 자료\심수석님 검토 파일\철근 모델랑 운곡교P1_바이브코딩\3.dxf"
data = json.load(open(sys.argv[2], encoding="utf-8"))
OUT = sys.argv[3]
doc = ezdxf.readfile(SRC)
msp = doc.modelspace()
for e in list(msp): # 원본 도면 내용은 지우고 스타일·레이어·단위만 상속
msp.delete_entity(e)
if "KR_TBL" not in doc.styles:
doc.styles.add("KR_TBL", font="malgun.ttf")
LAYERS = {
"대조_다름(주황)": (30, (248, 203, 173)),
"대조_반올림(파랑)": (140, (221, 235, 247)),
"대조_빈칸미추출(노랑)": (50, (255, 242, 204)),
"대조_일치(초록)": (3, (226, 240, 217)),
"대조_비고": (7, None),
"대조_비고3_KDS(자홍)": (6, None),
"대조_표선": (7, None),
"대조_글자": (7, None),
}
for n, (c, _) in LAYERS.items():
if n not in doc.layers:
doc.layers.add(n, color=c)
TH = 150 # 표 글자 높이 (원본과 동일)
SUB = 360 # 한 줄 높이 (원본 행 간격)
XB = [1752, 2652, 3552, 4452, 5352, 6852, 8352, 9852, 11352, 12852, 14352, 15852, 17352, 18852, 20352, 21552, 22752, 23952, 25152]
KEYS = ["num", "shape", "dia", "n", "A", "B", "C", "D", "E", "R", "X1", "X2", "J", "L", "tot", "unit", "w", "wh"]
HEAD = ["번 호", "형 식", "직 경", "개 수", "A", "B", "C", "D", "E", "R", "X1(º)", "X2(º)", "J", "길 이", "총길이", "단위중량", "총중량", "총중량(할증)"]
UNITS = {"L": "(M)", "tot": "(M)", "unit": "(KG/M)", "w": "(TON)", "wh": "(TON)"}
XK = XB[0] - 1500 # '구분'(도면/모델) 열
XV0, XV1 = XB[-1], XB[-1] + 1600 # 판정 열
XN0, XN1 = XV1, XV1 + 16000 # 비고
XK3_0, XK3_1 = XN1, XN1 + 12000 # 비고 3
XLEFT, XRIGHT = XK, XK3_1
MCOL = 6 # ACI 자홍
def col_x(k):
i = KEYS.index(k)
return XB[i], XB[i + 1]
def txt(x, y, s, h=TH, layer="대조_글자", color=None):
if s is None or s == "":
return
t = msp.add_text(s, height=h, dxfattribs={"layer": layer, "style": "KR_TBL"})
t.set_placement((x, y), align=TextEntityAlignment.MIDDLE_CENTER)
if color is not None:
t.dxf.color = color
def mtxt(x0, ytop, width, s, h=110, layer="대조_비고", color=None):
if not s:
return
m = msp.add_mtext(s, dxfattribs={"layer": layer, "style": "KR_TBL", "char_height": h})
m.dxf.insert = (x0, ytop, 0)
m.dxf.width = width
m.dxf.attachment_point = 1 # 좌상단
if color is not None:
m.dxf.color = color
def line(x0, y0, x1, y1, layer="대조_표선", color=None):
ln = msp.add_line((x0, y0), (x1, y1), dxfattribs={"layer": layer})
if color is not None:
ln.dxf.color = color
def fill(x0, y0, x1, y1, lname):
rgb = LAYERS[lname][1]
h = msp.add_hatch(dxfattribs={"layer": lname})
h.set_solid_fill(color=LAYERS[lname][0])
h.rgb = rgb
h.paths.add_polyline_path([(x0, y0), (x1, y0), (x1, y1), (x0, y1)], is_closed=True)
def est_lines(s, width, h=110):
cw = h * 0.8
per = max(8, int((width - 200) / cw))
n = 0
for part in (s or "").split("\n"):
n += max(1, math.ceil(len(part) / per))
return n
STAT_LAYER = {"diff": "대조_다름(주황)", "round": "대조_반올림(파랑)", "drawing_blank": "대조_빈칸미추출(노랑)", "model_blank": "대조_빈칸미추출(노랑)"}
VERD_LAYER = {"차이": "대조_다름(주황)", "일치(반올림)": "대조_반올림(파랑)", "도면 빈칸/모델 미추출": "대조_빈칸미추출(노랑)", "일치": "대조_일치(초록)"}
# ------------------------------------------------------------------ 범례
y = 0.0
txt((XLEFT + XRIGHT) / 2 - 8000, y + 1900, "운 곡 교 P1 (완도방향) 철 근 재 료 표 — 도면(3.dxf) ↔ 모델(운곡교p1.3dm) 대조", h=300)
txt((XLEFT + XRIGHT) / 2 - 8000, y + 1450, "각 마크마다 위 줄 = 도면 재료표 값, 아래 줄 = 모델에서 뽑은 값. 다른 칸은 색으로 표시하고 오른쪽 비고 열에 내용을 적음 (검토 미확정, 2026-10-16).", h=130)
lx = XLEFT
for name, label in (("대조_다름(주황)", "주황 = 도면과 다름"), ("대조_반올림(파랑)", "파랑 = 반올림 범위(≤1 mm/본)"),
("대조_빈칸미추출(노랑)", "노랑 = 도면 빈칸 / 모델 미추출"), ("대조_일치(초록)", "초록 = 일치 (판정 열)")):
fill(lx, y + 700, lx + 500, y + 1100, name)
txt(lx + 600 + len(label) * 55, y + 900, label, h=130)
lx += 700 + len(label) * 115
txt(lx + 1800, y + 900, "자홍 글자 = KDS 24 14 21 기준 상이(비고 3)", h=130, color=MCOL)
def build_table(title, rows, ytop):
"""rows: JSON 행 리스트. 반환: 표 아래 y"""
y = ytop
txt((XB[0] + XB[-1]) / 2, y + 400, title, h=220)
# 헤더 2줄
hy0 = y
for i, hd in enumerate(HEAD):
x0, x1 = XB[i], XB[i + 1]
txt((x0 + x1) / 2, y - SUB / 2, hd)
if KEYS[i] in UNITS:
txt((x0 + x1) / 2, y - SUB * 1.5, UNITS[KEYS[i]])
txt((XK + XB[0]) / 2, y - SUB, "구분")
txt((XV0 + XV1) / 2, y - SUB, "판정")
txt((XN0 + XN1) / 2, y - SUB, "비 고 (칸별 차이 · 도면 내부/도면↔모델 코드)")
txt((XK3_0 + XK3_1) / 2, y - SUB, "비고 3 (KDS 24 14 21 기준 상이)", color=MCOL)
y -= SUB * 2
line(XLEFT, hy0, XRIGHT, hy0, layer="대조_표선")
line(XLEFT, y, XRIGHT, y)
body_top = y
for r in rows:
auto = " / ".join(r.get("auto", []))
note = r.get("note", "")
ntext = auto + ("\\P" if auto and note else "") + note
need1 = est_lines((auto + "\n" + note).strip("\n"), XN1 - XN0)
need3 = est_lines(r.get("kds", ""), XK3_1 - XK3_0)
H = max(2 * SUB, max(need1, need3) * 150 + 80)
half = H / 2.0
yt, ym, yb = y, y - half, y - H
# 칸 색 (도면·모델 두 줄 모두 같은 열에 칠함)
for k, st in r["res"].items():
if k in ("shape", "dia") and st == "same":
continue
lname = STAT_LAYER.get(st)
if lname and k in KEYS:
x0, x1 = col_x(k)
fill(x0, yb, x1, yt, lname)
if r.get("kind") == "bar":
vl = VERD_LAYER.get(r["verdict"])
if vl:
fill(XV0, yb, XV1, yt, vl)
# 글자
for i, k in enumerate(KEYS):
x0, x1 = XB[i], XB[i + 1]
cx = (x0 + x1) / 2
dtxt = r["d"].get(k, "")
mtxt_ = r["m"].get(k, "")
if r["kind"] == "bar" and k in ("shape", "dia"):
pass
if r["kind"] != "bar" and k == "num":
lab = r.get("label", "")
if r["kind"] == "sum":
txt((XB[7] + XB[8]) / 2, y - half / 2, "소 계")
txt((XB[7] + XB[8]) / 2, ym - half / 2, "소 계")
else:
short = lab.replace("총 계", "총 계")
txt((XB[0] + XB[11]) / 2, y - half / 2, short, h=130)
txt((XB[0] + XB[11]) / 2, ym - half / 2, short + " (모델)" if "겹이음" not in short else "(모델 미산출)", h=130)
continue
txt(cx, y - half / 2, dtxt)
txt(cx, ym - half / 2, mtxt_ if (mtxt_ != "" or dtxt == "") else "-")
txt((XK + XB[0]) / 2, y - half / 2, "도면")
txt((XK + XB[0]) / 2, ym - half / 2, "모델")
if r.get("kind") == "bar":
txt((XV0 + XV1) / 2, (yt + yb) / 2, {"차이": "차이", "일치(반올림)": "반올림", "도면 빈칸/모델 미추출": "빈칸/미추출", "일치": "일치"}.get(r["verdict"], r["verdict"]), h=120)
mtxt(XN0 + 100, yt - 50, XN1 - XN0 - 200, ntext)
mtxt(XK3_0 + 100, yt - 50, XK3_1 - XK3_0 - 200, r.get("kds", ""), layer="대조_비고3_KDS(자홍)", color=MCOL)
# 선
line(XLEFT, yb, XRIGHT, yb)
line(XLEFT, ym, XB[-1], ym, color=8)
y = yb
# 세로선
for x in [XK] + XB + [XV1, XN1, XK3_1]:
line(x, hy0, x, y)
line(XLEFT, y, XRIGHT, y, layer="대조_표선")
return y
y1 = build_table("철 근 재 료 표 (SD400)", data["SD400"], -1000.0)
y2 = build_table("철 근 재 료 표 (SD500)", data["SD500"], y1 - 2500.0)
doc.header["$EXTMIN"] = (XLEFT, y2, 0)
doc.header["$EXTMAX"] = (XRIGHT, 2500, 0)
doc.saveas(OUT)
print("saved", OUT, "y", y1, y2)