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,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)
|
||||
Reference in new issue
Block a user