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,83 @@
|
||||
"""Ramp-A교 P3-2 수정 전·후 이미지 (Rhino 캡처 + 도면 형상 기준선 + 치수). 입력: 결과/캡처/p32_ramp3|4(.png, _capture.json)."""
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
ROOT = Path(r"D:\★Pier 자료\프로그램\Pier_T")
|
||||
CAP = ROOT / "Code" / "검토수정" / "결과" / "캡처"
|
||||
OUT = ROOT / "검토파일" / "수정후_캡처"
|
||||
OUT.mkdir(parents=True, exist_ok=True)
|
||||
FONT = r"C:\Windows\Fonts\malgun.ttf"
|
||||
FONTB = r"C:\Windows\Fonts\malgunbd.ttf"
|
||||
|
||||
|
||||
def F(s, b=False):
|
||||
return ImageFont.truetype(FONTB if b else FONT, s)
|
||||
|
||||
|
||||
def compose(key, title, sub, color, lines, legend, outname, before):
|
||||
cj = json.loads((CAP / ("%s_capture.json" % key)).read_text(encoding="utf-8"))
|
||||
img = Image.open(CAP / ("%s.png" % key)).convert("RGB")
|
||||
T1, T2, C1, C2 = cj["T1"], cj["T2"], cj["C1"], cj["C2"]
|
||||
pad = 60
|
||||
box = (max(0, int(T1[0] - 330)), int(T1[1] - 110), min(1500, int(T2[0] + 160)), int(C1[1] + 150))
|
||||
crop = img.crop(box)
|
||||
ox, oy = box[0], box[1]
|
||||
d = ImageDraw.Draw(crop)
|
||||
P = lambda p: (p[0] - ox, p[1] - oy)
|
||||
if before: # drawing shape (plain U) as dashed magenta guide
|
||||
mag = (200, 0, 200)
|
||||
for a, b in ((T1, C1), (C1, C2), (C2, T2)):
|
||||
x0, y0 = P(a); x1, y1 = P(b)
|
||||
n = max(1, int(((x1 - x0) ** 2 + (y1 - y0) ** 2) ** 0.5 // 22))
|
||||
for i in range(n):
|
||||
if i % 2 == 0:
|
||||
d.line([(x0 + (x1 - x0) * i / n, y0 + (y1 - y0) * i / n), (x0 + (x1 - x0) * (i + 1) / n, y0 + (y1 - y0) * (i + 1) / n)], fill=mag, width=4)
|
||||
d.text((P(C1)[0] + 20, P(C1)[1] + 36), "자홍 점선 = 도면 형상(바닥 수평 + 다리 수직 ㄷ자)", font=F(26, True), fill=mag)
|
||||
else:
|
||||
# dimension lines
|
||||
x0, y0 = P(C1); x1, y1 = P(C2)
|
||||
yd = y0 + 70
|
||||
d.line([(x0, yd), (x1, yd)], fill=(0, 110, 0), width=3)
|
||||
for x in (x0, x1):
|
||||
d.line([(x, yd - 14), (x, yd + 14)], fill=(0, 110, 0), width=3)
|
||||
txt = lines[0]
|
||||
w = d.textlength(txt, font=F(28, True))
|
||||
d.rectangle([(x0 + x1) / 2 - w / 2 - 8, yd - 20, (x0 + x1) / 2 + w / 2 + 8, yd + 20], fill=(255, 255, 255))
|
||||
d.text(((x0 + x1) / 2 - w / 2, yd - 18), txt, font=F(28, True), fill=(0, 110, 0))
|
||||
tx, ty = P(T1)
|
||||
xd = tx - 70
|
||||
d.line([(xd, ty), (xd, P(C1)[1])], fill=(0, 110, 0), width=3)
|
||||
for y in (ty, P(C1)[1]):
|
||||
d.line([(xd - 14, y), (xd + 14, y)], fill=(0, 110, 0), width=3)
|
||||
w2 = d.textlength(lines[1], font=F(28, True))
|
||||
lx = tx + 26 # label inside the U (left margin of the capture is too small)
|
||||
d.rectangle([lx - 8, (ty + P(C1)[1]) / 2 - 20, lx + w2 + 8, (ty + P(C1)[1]) / 2 + 20], fill=(255, 255, 255))
|
||||
d.text((lx, (ty + P(C1)[1]) / 2 - 18), lines[1], font=F(28, True), fill=(0, 110, 0))
|
||||
d.text((P(C1)[0] + 16, P(C1)[1] + 12), lines[2], font=F(26, True), fill=(0, 110, 0))
|
||||
W = crop.width
|
||||
banner = Image.new("RGB", (W, 112), color)
|
||||
bd = ImageDraw.Draw(banner)
|
||||
bd.text((14, 8), title, font=F(40, True), fill=(255, 255, 255))
|
||||
bd.text((14, 64), sub, font=F(26), fill=(255, 255, 255))
|
||||
foot = Image.new("RGB", (W, 80), (246, 246, 246))
|
||||
fd = ImageDraw.Draw(foot)
|
||||
for i, t in enumerate(legend):
|
||||
fd.text((14, 6 + i * 34), t, font=F(24), fill=(20, 20, 20))
|
||||
out = Image.new("RGB", (W, banner.height + crop.height + foot.height), (255, 255, 255))
|
||||
out.paste(banner, (0, 0)); out.paste(crop, (0, banner.height)); out.paste(foot, (0, banner.height + crop.height))
|
||||
p = OUT / outname
|
||||
out.save(p)
|
||||
return p
|
||||
|
||||
|
||||
p1 = compose("p32_ramp3", "Ramp-A교 · P3-2 (H16) — 수정 전 모델", "도면은 바닥 수평 + 다리 수직 ㄷ자 (다리 200 은 P1-2 에 용접), 모델은 깔때기 형상",
|
||||
(170, 40, 30), None,
|
||||
["다리 위쪽 184 만 수직, 그 아래 459 는 약 13.4° 안쪽으로 기울고 모서리가 R135 두 호(13.44° + 76.56°)로 이어짐",
|
||||
"바닥 직선이 다리 위쪽 간격보다 좁음 (깔때기). 중심선 길이 3,276.3 (재료표 L 3,342)"], "RampA_P3-2_수정전.png", True)
|
||||
p2 = compose("p32_ramp4", "Ramp-A교 · P3-2 (H16) — 수정 후 모델", "바닥 수평 + 다리 수직 ㄷ자, 모서리 R24 (KDS H16 최소 23.9)",
|
||||
(30, 120, 60), ["바닥 폭 2,050", "다리 높이 646", "모서리 R24"],
|
||||
["바닥 폭 2,050 + 다리 2×646 = 3,342 (재료표 L 직선 치수 합). 다리 200 용접 구간은 다리 안에 포함",
|
||||
"중심선 길이 3,321.4. 모서리 R 은 도면에 값이 없어 KDS 최소(H16)를 적용"], "RampA_P3-2_수정후.png", False)
|
||||
print(p1.name, p2.name)
|
||||
Reference in new issue
Block a user