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,177 @@
|
||||
"""Stage 4: column rebar P1-P6 (centreline + pipe solid) from params.json `column_rebar`.
|
||||
|
||||
Run inside Rhino 8 after build_rhino.py:
|
||||
exec(open(<this file>, encoding="utf-8").read(), {"__rhino_doc__": doc, "PARAMS_PATH": <params.json>})
|
||||
Rules: 설계서 v0.1.04 §5 (HITL H1-H3 approved 2026-10-07). Units mm, Z = EL x 1000.
|
||||
Each centreline carries `design_length` (schedule-style original length: straight + arc lengths
|
||||
before hook fillets) and the actual curve length is measured separately (box rule: 원길이 vs 곡선길이).
|
||||
"""
|
||||
import json
|
||||
import math
|
||||
|
||||
import Rhino
|
||||
import Rhino.Geometry as rg
|
||||
from Rhino.DocObjects import ObjectAttributes
|
||||
from System.Drawing import Color
|
||||
|
||||
P = json.load(open(PARAMS_PATH, encoding="utf-8"))
|
||||
doc = __rhino_doc__
|
||||
TOL = 0.01
|
||||
DIA = {"S32": 32.0, "H19": 19.0, "H16": 16.0}
|
||||
MARK_DIA = {"P1": "S32", "P2": "S32", "P3": "H19", "P4": "H19", "P5": "H19", "P6": "H16"}
|
||||
COLORS = {"P1": (200, 40, 40), "P2": (230, 120, 40), "P3": (40, 120, 200), "P4": (40, 170, 170),
|
||||
"P5": (90, 90, 220), "P6": (140, 60, 160)}
|
||||
|
||||
|
||||
def layer(path, color):
|
||||
idx = doc.Layers.FindByFullPath(path, -1)
|
||||
if idx >= 0:
|
||||
return idx
|
||||
parent = -1
|
||||
parts = path.split("::")
|
||||
for i in range(1, len(parts) + 1):
|
||||
sub = "::".join(parts[:i])
|
||||
idx = doc.Layers.FindByFullPath(sub, -1)
|
||||
if idx < 0:
|
||||
lay = Rhino.DocObjects.Layer()
|
||||
lay.Name, lay.Color = parts[i - 1], Color.FromArgb(*color)
|
||||
if parent >= 0:
|
||||
lay.ParentLayerId = doc.Layers[parent].Id
|
||||
idx = doc.Layers.Add(lay)
|
||||
parent = idx
|
||||
return parent
|
||||
|
||||
|
||||
def min_bend_radius(dia_name):
|
||||
d = DIA[dia_name]
|
||||
inner = 2 * d if d <= 16 else 3.5 * d # box project rule (REBAR_BENDS_20260914)
|
||||
return (inner + d) / 2
|
||||
|
||||
|
||||
def add_bar(curve, mark, occ, design_len, hosts, src, coupler=0.0):
|
||||
d = DIA[MARK_DIA[mark]]
|
||||
# fitRail=False: fitRail=True fails on line-arc-line rails and crashed a headless Rhino (2026-10-07)
|
||||
pipes = rg.Brep.CreatePipe(curve, d / 2, False, rg.PipeCapMode.Flat, False, TOL, math.radians(1))
|
||||
if not pipes or not pipes[0].IsSolid:
|
||||
raise RuntimeError(f"{mark} {occ}: pipe failed")
|
||||
common = dict(mark=mark, dia=MARK_DIA[mark], shape=P["column_rebar"]["schedule"][mark]["shape"],
|
||||
occurrence=occ, host="P1-CL", anchor_hosts=hosts, design_length=f"{design_len:.3f}",
|
||||
coupler_length=f"{coupler:.3f}",
|
||||
src=src)
|
||||
for geo, lay, prefix in ((curve, layer("P1::철근::중심선", (60, 60, 60)), "P1-RC"),
|
||||
(pipes[0], layer(f"P1::철근::기둥::{mark}", COLORS[mark]), "P1-R")):
|
||||
attr = ObjectAttributes()
|
||||
attr.LayerIndex = lay
|
||||
oid = f"{prefix}-{mark}-{occ}"
|
||||
attr.Name = oid
|
||||
attr.SetUserString("id", oid)
|
||||
for k, v in common.items():
|
||||
attr.SetUserString(k, v)
|
||||
if isinstance(geo, rg.Brep):
|
||||
doc.Objects.AddBrep(geo, attr)
|
||||
else:
|
||||
doc.Objects.AddCurve(geo, attr)
|
||||
|
||||
|
||||
def pt(r, deg, z):
|
||||
t = math.radians(deg)
|
||||
return rg.Point3d(r * math.cos(t), r * math.sin(t), z)
|
||||
|
||||
|
||||
def arc_xy(r, a0, a1, z):
|
||||
"""Horizontal arc at height z from angle a0 to a1 (deg, counter-clockwise)."""
|
||||
am = (a0 + a1) / 2
|
||||
return rg.ArcCurve(rg.Arc(pt(r, a0, z), pt(r, am, z), pt(r, a1, z)))
|
||||
|
||||
|
||||
def hooked_half_ring(r, a0, z, hook, bend_r):
|
||||
"""Semicircle a0 -> a0+180 with inward 135-degree hooks at both ends (P3, shape VI)."""
|
||||
arc = arc_xy(r, a0, a0 + 180, z)
|
||||
pieces = []
|
||||
for at_start in (True, False):
|
||||
p = arc.PointAtStart if at_start else arc.PointAtEnd
|
||||
t = arc.TangentAtStart if at_start else arc.TangentAtEnd
|
||||
if at_start:
|
||||
t = -t # travel direction away from the arc
|
||||
n = rg.Vector3d(-p.X, -p.Y, 0)
|
||||
n.Unitize()
|
||||
d = t * math.cos(math.radians(135)) + n * math.sin(math.radians(135)) # back + inward
|
||||
d.Unitize()
|
||||
pieces.append(rg.LineCurve(p, p + d * hook))
|
||||
joined = rg.Curve.JoinCurves([pieces[0], arc, pieces[1]], TOL)[0]
|
||||
fil = rg.Curve.CreateFilletCornersCurve(joined, bend_r, TOL, math.radians(1))
|
||||
return fil or joined
|
||||
|
||||
|
||||
def main():
|
||||
for o in list(doc.Objects):
|
||||
if (o.Attributes.GetUserString("id") or "").startswith(("P1-R-", "P1-RC-")):
|
||||
doc.Objects.Delete(o, True)
|
||||
cr = P["column_rebar"]
|
||||
mb, hp, tie = cr["main_bars"], cr["hoops"], cr["ties"]
|
||||
sch = cr["schedule"]
|
||||
count = 0
|
||||
# Main bars P1 (outer, hooked) / P2 (inner, straight)
|
||||
p1, p2 = mb["p1"], mb["p2"]
|
||||
for i in range(mb["divisions"]):
|
||||
th = mb["start_deg"] * 0 + i * mb["pitch_deg"] # start angle 0 (CAD 0.001 deg)
|
||||
ro, ri = mb["r_outer"], mb["r_inner"]
|
||||
z_leg, R = p1["hook_leg_z"], p1["bend_r"]
|
||||
top = p1["straight_from"] + p1["straight_len"]
|
||||
leg = rg.LineCurve(pt(ro + R + p1["hook_leg"], th, z_leg), pt(ro + R, th, z_leg))
|
||||
bend = rg.ArcCurve(rg.Arc(pt(ro + R, th, z_leg),
|
||||
pt(ro + R - R * math.sin(math.radians(45)), th,
|
||||
z_leg + R - R * math.cos(math.radians(45))),
|
||||
pt(ro, th, z_leg + R)))
|
||||
vert = rg.LineCurve(pt(ro, th, z_leg + R), pt(ro, th, top))
|
||||
c1 = rg.Curve.JoinCurves([leg, bend, vert], TOL)[0]
|
||||
add_bar(c1, "P1", f"{i + 1:02d}", p1["straight_len"] + math.pi / 2 * R + p1["hook_leg"],
|
||||
"P1-FT,P1-CP", f"angle {th:.4f} deg; D1 단면 C-C / 정면도; D3 P1")
|
||||
c2 = rg.LineCurve(pt(ri, th, p2["z0"]), pt(ri, th, p2["z0"] + p2["length"]))
|
||||
add_bar(c2, "P2", f"{i + 1:02d}", p2["length"], "P1-FT,P1-CP",
|
||||
f"angle {th:.4f} deg; D1 단면 C-C / 정면도; D3 P2")
|
||||
count += 2
|
||||
# Hoops: P4 (V: 2 half arcs + 2 coupler gaps), P5 (IX: ring + 1 gap), P3 (VI: 2 hooked halves)
|
||||
r = hp["radius"]
|
||||
n3 = 0
|
||||
for k, (z, mark) in enumerate(zip(hp["levels"], hp["marks"])):
|
||||
s = sch[mark]
|
||||
a = float(s["A"]) * 1000 if float(s["A"]) < 100 else float(s["A"])
|
||||
if mark in ("P4", "P5"):
|
||||
gap = float(s["B"])
|
||||
gap_deg = math.degrees(gap / r)
|
||||
arcs = ([(90 + gap_deg / 2, 270 - gap_deg / 2), (270 + gap_deg / 2, 450 - gap_deg / 2)]
|
||||
if mark == "P4" else [(90 + gap_deg / 2, 450 - gap_deg / 2)])
|
||||
curves = [arc_xy(r, a0, a1, z) for a0, a1 in arcs]
|
||||
for j, c in enumerate(curves):
|
||||
add_bar(c, mark, f"L{k + 1:02d}{'ab'[j] if len(curves) > 1 else ''}", a, "",
|
||||
f"EL {z / 1000:.3f}; coupler gap {gap:.0f} at {'90/270' if mark == 'P4' else '90'} deg",
|
||||
coupler=gap) # one coupler (b) per piece: P4 2 pieces/2 gaps, P5 1/1
|
||||
else:
|
||||
n3 += 1
|
||||
a0 = 90 if n3 % 2 else 0 # joins staggered by 90 deg
|
||||
hook = float(s["B"])
|
||||
for j, start in enumerate((a0, a0 + 180)):
|
||||
c = hooked_half_ring(r, start, z, hook, min_bend_radius("H19"))
|
||||
add_bar(c, mark, f"L{k + 1:02d}{'ab'[j]}", a + 2 * hook,
|
||||
"P1-CP" if z > 40411 else "", f"EL {z / 1000:.3f}; joins at {a0}/{a0 + 180} deg")
|
||||
count += 1
|
||||
# Cross ties P6 (III): straight 1836 on diameters, 150 hooks down at r=918, sitting on hoop
|
||||
half = tie["straight"] / 2
|
||||
zoff = DIA["H19"] / 2 + DIA["H16"] / 2
|
||||
for k, z in enumerate(tie["levels"]):
|
||||
for ang in tie["angles_deg"]:
|
||||
zt = z + zoff
|
||||
pts = [pt(half, ang + 180, zt - tie["hook"]), pt(half, ang + 180, zt), pt(half, ang, zt),
|
||||
pt(half, ang, zt - tie["hook"])]
|
||||
pl = rg.PolylineCurve(pts)
|
||||
c = rg.Curve.CreateFilletCornersCurve(pl, min_bend_radius("H16"), TOL, math.radians(1)) or pl
|
||||
add_bar(c, "P6", f"L{k + 1}-{ang:03d}", tie["straight"] + 2 * tie["hook"],
|
||||
"P1-FT" if z < 28408 else ("P1-CP" if z > 40411 else ""),
|
||||
f"EL {z / 1000:.3f} (+{zoff} on hoop); angle {ang} deg")
|
||||
count += 1
|
||||
doc.Views.Redraw()
|
||||
print(json.dumps({"bars": count}))
|
||||
|
||||
|
||||
main()
|
||||
Reference in new issue
Block a user