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,198 @@
|
||||
"""Ramp-A P1 coping rebar (G4: C1~C16, S1~S4) -> centreline polylines for the generic builder rebar_polylines.py.
|
||||
|
||||
Inputs: drawn values read from D2 / D3 (판독서 v0.1.06 §13, values typed below with their source) and the user
|
||||
decisions T1-T6 (2026-10-14). Output: 판독/g4_bars.json {"bars": [...], "summary": {...}} used by add_g4.py.
|
||||
Model axes: X along the coping, Y across, Z = EL x 1000; pier centre at the origin.
|
||||
"""
|
||||
import json
|
||||
import math
|
||||
from pathlib import Path
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
APP = HERE.parents[1] / "Code" / "교각모델링앱"
|
||||
P = json.loads((APP / "data" / "Ramp-A교P1" / "params.json").read_text(encoding="utf-8"))
|
||||
CP = P["coping"]
|
||||
TL, TR = CP["z_top_left"], CP["z_top_right"] # 59952 / 60267
|
||||
ZB, ZT = CP["z_bottom"], CP["z_tip"] # 57452 / 58952
|
||||
SCX, SCZ = abs(CP["soffit"]["centre_x"]), CP["soffit"]["centre_z"]
|
||||
bars = []
|
||||
|
||||
|
||||
def rb(dia): # min bend radius of the centreline (as the other builders)
|
||||
return ((2 * dia if dia <= 16 else 3.5 * dia) + dia) / 2
|
||||
|
||||
|
||||
def add(mark, occ, pts, dia, L, src, r=None):
|
||||
bars.append({"mark": mark, "occ": occ, "pts": [[round(v, 2) for v in p] for p in pts],
|
||||
"r": rb(dia) if r is None else r, "design_length": round(L, 1), "src": src})
|
||||
|
||||
|
||||
def top(x):
|
||||
return TL if x <= 0 else TR
|
||||
|
||||
|
||||
def arc_z(x, R):
|
||||
"""z of the soffit-parallel arc of radius R (centre (+-SCX, SCZ)) at x; flat zone at the column handled by caller."""
|
||||
d = SCX - abs(x)
|
||||
return SCZ + math.sqrt(R * R - d * d)
|
||||
|
||||
|
||||
def face_y(z):
|
||||
"""Half width of the coping side at z (2,200 above the tip level, taper to 2,000 at the column top)."""
|
||||
return 1100.0 if z >= ZT else 1000.0 + 100.0 * (z - ZB) / (ZT - ZB)
|
||||
|
||||
|
||||
# ---- top bars C1/C4 (1단), C2/C5 (2단), C3 (3단): D2 정면 작도 end points, 단면 A-A/B-B rows
|
||||
ROW17 = [-1000 + 125 * k for k in range(17)]
|
||||
ROW9 = [-1000 + 250 * k for k in range(9)]
|
||||
TOPS = { # mark: (z, [left leg end], x_left, x_right, [right leg end], L, dia)
|
||||
1: (59852.0, (-3672.0, 59030.4), -3425.6, 3492.1, (3679.3, 59031.7), 8617, 29),
|
||||
2: (59752.0, (-3485.6, 59652.0), -3455.6, 3515.0, (3537.8, 59652.0), 7177, 29),
|
||||
3: (59652.0, (-3515.6, 59552.0), -3485.6, 3537.8, (3560.6, 59552.0), 7230, 25),
|
||||
}
|
||||
for layer, (z, le, xl, xr, re_, L, dia) in TOPS.items():
|
||||
ys = ROW9 if layer == 3 else ROW17
|
||||
for k, y in enumerate(ys):
|
||||
mark = {1: ("C1", "C4"), 2: ("C2", "C5"), 3: ("C3", "C3")}[layer][k % 2]
|
||||
add(mark, f"y{y:+.0f}", [(le[0], y, le[1]), (xl, y, z), (xr, y, z), (re_[0], y, re_[1])], dia, L,
|
||||
f"D2 정면 {layer}단 작도선, 단면 A-A/B-B {'@250' if layer == 3 else '@125 교번'}")
|
||||
|
||||
# ---- C6 soffit bars: leg 400 along the end face, R 5,100 arc, bottom 1,914 at EL 57.552 (D2 ARC 478/479); T1: 9 @250;
|
||||
# the bars near the faces keep inside the side taper (y <= face - 100.2) [T1 추론]
|
||||
for k in range(9):
|
||||
y0 = -1000 + 250 * k
|
||||
pts = [(-3557.1, y0, 59413.5)]
|
||||
a0, a1 = math.radians(79.1), math.radians(43.8)
|
||||
for i in range(21):
|
||||
t = a0 + (a1 - a0) * i / 20
|
||||
pts.append((-SCX + 5100 * math.cos(t), y0, SCZ + 5100 * math.sin(t)))
|
||||
for i in range(21):
|
||||
t = math.radians(180 - 43.8) + (math.radians(180 - 79.1) - math.radians(180 - 43.8)) * i / 20
|
||||
pts.append((SCX + 5100 * math.cos(t), y0, SCZ + 5100 * math.sin(t)))
|
||||
pts.append((3590.3, y0, 59421.7))
|
||||
pts = [(x, math.copysign(min(abs(y), face_y(z) - 100.2), y) if y else 0.0, z) for x, y, z in pts]
|
||||
add("C6", f"y{y0:+.0f}", pts, 25, 9003, "D2 정면 ARC 478/479 R5,100, 하면 1,914 EL 57.552; @250 9본 (T1 [추론])", r=0)
|
||||
|
||||
# ---- stirrups at x = -3375 ... 3375 @125 (D2 정면 55 작도선): outer C7 / C9 / C11, inner pair C8 / C10 / C12
|
||||
XS = [-3375 + 125 * i for i in range(55)]
|
||||
|
||||
|
||||
def bottom(x):
|
||||
"""Stirrup bottom (centreline): 77.5 above the soffit, i.e. on R 5,077.5, flat 57,529.5 over the column."""
|
||||
return ZB + 77.5 if abs(x) < 1000 else arc_z(x, 5077.5)
|
||||
|
||||
|
||||
Z_C1 = TL - 996.7 # inner outer-leg vertical bottom (단면 A-A/B-B)
|
||||
for x in XS:
|
||||
zt, zb = top(x) - 77.5, bottom(x)
|
||||
b = zt - zb
|
||||
outer, inner = ("C7", "C8") if x < -875 else (("C9", "C10") if x <= 875 else ("C11", "C12"))
|
||||
add(outer, f"x{x:+.0f}", [(x, -62.5, zt), (x, 750, zt), (x, 750, zb), (x, -875, zb), (x, -875, zt), (x, -62.5, zt)],
|
||||
19, 2 * 1673 + 2 * b + 2 * 450, f"D2 정면 x {x}; 단면 B-B y -875~750; b {b:.1f}")
|
||||
yb = face_y(zb) - 100.2
|
||||
for s in (1, -1):
|
||||
xi = x + 20 # beside the outer stirrup (T6 [추론])
|
||||
p = [(xi, s * 687.5, zt), (xi, s * 1000, zt), (xi, s * 1000, Z_C1), (xi, s * yb, zb), (xi, s * 375, zb),
|
||||
(xi, s * 375, zt), (xi, s * 687.5, zt)]
|
||||
c2 = math.hypot(1000 - yb, Z_C1 - zb)
|
||||
add(inner, f"x{x:+.0f}{'R' if s > 0 else 'L'}", p, 19, 673 + b + (yb - 375) + c2 + (zt - Z_C1) + 2 * 450,
|
||||
f"단면 A-A/B-B 안쪽 모따기 스터럽, x {x}+20 [T6 추론]; c1 {zt - Z_C1:.0f} (T4)")
|
||||
|
||||
# ---- side loops C14 (4 levels) / C13 (6 levels): D2 정면 수평선 ends; 3 concentric loops per level (T2)
|
||||
LEVELS = [ # z, x_left, x_right (D2 정면)
|
||||
(59827.0, -3433.1, 3497.9), (59577.0, -3508.1, 3554.9), (59327.0, -3583.1, 3611.9), (59077.0, -3658.1, 3669.0),
|
||||
(58827.0, -2927.0, 2927.1), (58577.0, -2343.2, 2343.2), (58327.0, -1903.0, 1903.1), (58077.0, -1544.6, 1544.7),
|
||||
(57827.0, -1241.9, 1242.0), (57577.0, -981.2, 981.3)]
|
||||
for i, (z, xl, xr) in enumerate(LEVELS):
|
||||
mark = "C14" if i < 4 else "C13"
|
||||
yo = min(977.5, face_y(z) - 122.7) # outer dots follow the taper (단면 B-B -968.9 ...)
|
||||
for k, (yn, yp) in enumerate(((-yo, yo), (-852.5, 727.5), (-397.5, 397.5))):
|
||||
a, b_ = xl + 25 * k, xr - 25 * k
|
||||
p = [(0, yp, z), (b_, yp, z), (b_, yn, z), (a, yn, z), (a, yp, z), (0, yp, z)]
|
||||
L = 2 * (b_ - a + 48) + 2 * (yp - yn) + 2 * 350 + (290 if mark == "C14" else 0)
|
||||
add(mark, f"z{z:.0f}-{k}", p, 19, L, f"D2 정면 수평선 EL {z / 1000:.3f}; 동심 고리 {k} (T2 [추론])")
|
||||
|
||||
# ---- C16: raised right top, x 100~3,400 at EL 60.167, legs 350, y @125 (17)
|
||||
for y in ROW17:
|
||||
add("C16", f"y{y:+.0f}", [(100, y, 60167 - 350), (100, y, 60167), (3400, y, 60167), (3400, y, 60167 - 350)], 19,
|
||||
4000, "D2 정면 C16 EL 60.167, x 100~3,400, 다리 350")
|
||||
# ---- C15: transverse U on top, midway between stirrups, |x| <= 3,187.5 except 62.5 (T3 [추론]) -> 51
|
||||
for x in [-3312.5 + 125 * i for i in range(54)]:
|
||||
if abs(x) > 3187.5 or x == 62.5:
|
||||
continue
|
||||
z = top(x) - 77.5 - 19
|
||||
add("C15", f"x{x:+.1f}", [(x, -1000, z - 350), (x, -1000, z), (x, 1000, z), (x, 1000, z - 350)], 19, 2700,
|
||||
"상면 횡방향 U형, 스터럽 사이 중간 위치 (T3 [추론])")
|
||||
|
||||
# ---- seat bars per bearing (T5): local axes u (along, rotated), v (across); pedestal top = seat_z + h1
|
||||
for bng in P["bearing_seats"]["bearings"]:
|
||||
no, (cx, cy), rot = bng["no"], bng["centre"], math.radians(bng["rotation_deg"])
|
||||
u = (math.sin(rot), math.cos(rot))
|
||||
v = (math.cos(rot), -math.sin(rot))
|
||||
zp = bng["seat_z"] + bng["h1"]
|
||||
g = lambda su, sv, z: (cx + su * u[0] + sv * v[0], cy + su * u[1] + sv * v[1], z)
|
||||
# S1: straight a 1,300 along u, legs 700, 11 positions along v (50|100|8@125|100|50 = 1,300)
|
||||
for j, sv in enumerate([-600] + [-500 + 125 * k for k in range(9)] + [600]):
|
||||
z = zp - 50
|
||||
add("S1", f"B{no}-{j:02d}", [g(-650, sv, z - 700), g(-650, sv, z), g(650, sv, z), g(650, sv, z - 700)], 16, 2700,
|
||||
f"교좌면 보강 E-E, 받침 {no} [T5 추론]")
|
||||
# S2: straight a 1,200 along v, legs 700, 12 positions along u (9@125 + 2 edge [추론])
|
||||
for j, su in enumerate([-625] + [-562.5 + 125 * k for k in range(10)] + [625]):
|
||||
z = zp - 50 - 16
|
||||
add("S2", f"B{no}-{j:02d}", [g(su, -600, z - 700), g(su, -600, z), g(su, 600, z), g(su, 600, z - 700)], 16, 2600,
|
||||
f"교좌면 보강 E-E, 받침 {no} [T5 추론]")
|
||||
# S3 (along u) / S4 (along v): 2 layers x 11, 10@125 = 1,250, straight 1,250, 345 / 445 below the pedestal top
|
||||
for layer, dz in enumerate((345, 445)):
|
||||
for j, s_ in enumerate([-625 + 125 * k for k in range(11)]):
|
||||
add("S3", f"B{no}-{layer}{j:02d}", [g(-625, s_, zp - dz), g(625, s_, zp - dz)], 25, 1250,
|
||||
f"교좌면 보강 F-F, 받침 {no}, {layer + 1}층 [T5 추론]", r=0)
|
||||
add("S4", f"B{no}-{layer}{j:02d}", [g(s_, -625, zp - dz - 25), g(s_, 625, zp - dz - 25)], 25, 1250,
|
||||
f"교좌면 보강 F-F, 받침 {no}, {layer + 1}층 [T5 추론]", r=0)
|
||||
|
||||
# ---- plan-corner clipping [추론, 울산 R500 모서리 단축과 같은 방식]: the end face is convex in plan (corner 3,650 at the
|
||||
# tip level vs 3,800 at y = 0), so points nearer than cover 40 (+ bar radius) to it are pulled inwards in x
|
||||
PE = CP["plan_end"]
|
||||
RP = (PE["half_width"] ** 2 + (PE["tip_x"] - PE["corner_x"]) ** 2) / (2 * (PE["tip_x"] - PE["corner_x"]))
|
||||
|
||||
|
||||
def face_x(y, z, sx):
|
||||
xa = PE["tip_x"] - (RP - math.sqrt(RP * RP - min(abs(y), PE["half_width"]) ** 2))
|
||||
zt = TL if sx < 0 else TR
|
||||
return xa + (z - ZT) / (zt - ZT) * (CP["top_half"] - xa)
|
||||
|
||||
|
||||
DIA = {"C1": 29, "C2": 29, "C3": 25, "C4": 29, "C5": 29, "C6": 25, "C13": 19, "C14": 19}
|
||||
clipped = {}
|
||||
for b in bars:
|
||||
m = b["mark"]
|
||||
if m not in DIA:
|
||||
continue
|
||||
r = DIA[m] / 2
|
||||
pts = b["pts"]
|
||||
if m in ("C13", "C14"): # keep the loop rectangular: one limit per short side
|
||||
ymax = max(abs(p[1]) for p in pts)
|
||||
for sx in (-1, 1):
|
||||
lim = min(face_x(ymax + r, p[2], sx) for p in pts) - (r + 40)
|
||||
if any(p[0] * sx > lim for p in pts):
|
||||
clipped[m] = clipped.get(m, 0) + 1
|
||||
for p in pts:
|
||||
if p[0] * sx > 0 and abs(p[0]) > 1:
|
||||
p[0] = round(sx * min(abs(p[0]), lim), 2)
|
||||
continue
|
||||
hit = False
|
||||
for p in pts:
|
||||
sx = 1 if p[0] > 0 else -1
|
||||
lim = face_x(abs(p[1]) + r, p[2], sx) - (r + 40)
|
||||
if abs(p[0]) > lim:
|
||||
p[0] = round(sx * lim, 2)
|
||||
hit = True
|
||||
clipped[m] = clipped.get(m, 0) + hit
|
||||
if hit:
|
||||
b["src"] += "; 평면 모서리 단축 [추론]"
|
||||
|
||||
count = {}
|
||||
for b in bars:
|
||||
count[b["mark"]] = count.get(b["mark"], 0) + 1
|
||||
out = {"bars": bars, "summary": {"bars": len(bars), "per_mark": count, "corner_clipped": clipped}}
|
||||
(HERE / "판독" / "g4_bars.json").write_text(json.dumps(out, ensure_ascii=False), encoding="utf-8")
|
||||
print(json.dumps(out["summary"], ensure_ascii=False))
|
||||
Reference in new issue
Block a user