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,135 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# 05_realign_base_pieces.py (대호지교 P1, 2026-10-06 검증)
|
||||
# 목적: 수직전단철근 박스(C12/C14/C16/C18 등)에서 바닥(⊔) 조각이 뚜껑(⊓) 평면에서 s 방향으로
|
||||
# 어긋난 것을 되돌린다. 피복(헌치 경사면에 수직인 거리)은 유지하려고 경사 접선 방향으로 움직이고,
|
||||
# 바닥 상단을 뚜껑 윗변 중심에서 다시 자른다(겹침 510 유지).
|
||||
# 실행: rhino_mcp execute_rhino_code (IronPython 2.7). MARK 하나씩 실행 (소켓 타임아웃 방지).
|
||||
# 주의: lambda/리스트컴프리헨션 금지(exec 스코프), f-string 금지. 결과는 JSON 파일로 쓰고 따로 읽는다.
|
||||
# 구조 가정: 마크 idef -> 스테이션 idef -> 박스 idef(리프 Brep: 뚜껑, 바닥, [연장 조각...])
|
||||
import Rhino, json, io, os, math
|
||||
import scriptcontext as sc
|
||||
doc = sc.doc
|
||||
|
||||
MARK = "C12" # C12 / C14 / C16 / C18 ...
|
||||
OX, OY = 480714926.0, 153833329.5 # 코핑 로컬 원점 (코핑 bbox 중심)
|
||||
ANG = math.atan2(4255.0, 12284.0) # 코핑 축 각도 (두 기둥 중심 연결선)
|
||||
# 헌치 경사 dz/ds (그 스테이션에서 콘크리트 밑면의 기울기): 끝단 헌치 ±0.375, 안쪽 헌치 ±1/3
|
||||
SLOPES = {"C12": -0.375, "C18": 0.375, "C14": 1.0 / 3.0, "C16": -1.0 / 3.0}
|
||||
RBAR = 11.1 # 철근 반지름 (H22)
|
||||
TOL = 0.5 # 이보다 작은 어긋남은 건너뜀
|
||||
|
||||
ca = math.cos(ANG)
|
||||
sa = math.sin(ANG)
|
||||
k = SLOPES[MARK]
|
||||
folder = os.path.dirname(doc.Path)
|
||||
out = os.path.join(folder, "fix_result_" + MARK + ".json")
|
||||
|
||||
inst = None
|
||||
for o in doc.Objects:
|
||||
g = o.Geometry
|
||||
if isinstance(g, Rhino.Geometry.InstanceReferenceGeometry):
|
||||
if doc.Layers[o.Attributes.LayerIndex].FullPath.endswith(MARK + "_H22"):
|
||||
inst = g
|
||||
mxf = inst.Xform
|
||||
midf = doc.InstanceDefinitions.FindId(inst.ParentIdefId)
|
||||
|
||||
# 박스 idef 이름 -> 대표 인스턴스 월드 변환
|
||||
boxT = {}
|
||||
for ob in midf.GetObjects():
|
||||
og = ob.Geometry
|
||||
if not isinstance(og, Rhino.Geometry.InstanceReferenceGeometry):
|
||||
continue
|
||||
sidf = doc.InstanceDefinitions.FindId(og.ParentIdefId)
|
||||
sxf = mxf * og.Xform
|
||||
for b in sidf.GetObjects():
|
||||
bg = b.Geometry
|
||||
if isinstance(bg, Rhino.Geometry.InstanceReferenceGeometry):
|
||||
bn = doc.InstanceDefinitions.FindId(bg.ParentIdefId).Name
|
||||
if bn not in boxT:
|
||||
boxT[bn] = sxf * bg.Xform
|
||||
|
||||
report = []
|
||||
names = list(boxT.keys())
|
||||
names.sort()
|
||||
for bn in names:
|
||||
T = boxT[bn]
|
||||
ok, inv = T.TryGetInverse()
|
||||
bidf = doc.InstanceDefinitions.Find(bn)
|
||||
objs = bidf.GetObjects()
|
||||
geoms = []
|
||||
attrs = []
|
||||
info = [] # [s, area, bbox minZ, bbox maxZ] (월드)
|
||||
for ob in objs:
|
||||
bg = ob.Geometry
|
||||
amp = Rhino.Geometry.AreaMassProperties.Compute(bg)
|
||||
c = amp.Centroid
|
||||
c.Transform(T)
|
||||
s = (c.X - OX) * ca + (c.Y - OY) * sa
|
||||
w = bg.Duplicate()
|
||||
w.Transform(T)
|
||||
bbox = w.GetBoundingBox(True)
|
||||
info.append([s, bg.GetArea(), bbox.Min.Z, bbox.Max.Z])
|
||||
geoms.append(bg.Duplicate())
|
||||
attrs.append(ob.Attributes.Duplicate()) # ColorFromParent 보존
|
||||
# 면적 큰 2개 = 뚜껑/바닥 (연장 조각은 작다). 뚜껑 = bbox 최저 z가 더 높은 쪽
|
||||
i1 = -1
|
||||
i2 = -1
|
||||
for i in range(len(info)):
|
||||
if i1 < 0 or info[i][1] > info[i1][1]:
|
||||
i2 = i1
|
||||
i1 = i
|
||||
elif i2 < 0 or info[i][1] > info[i2][1]:
|
||||
i2 = i
|
||||
if info[i1][2] > info[i2][2]:
|
||||
lid = i1
|
||||
base = i2
|
||||
else:
|
||||
lid = i2
|
||||
base = i1
|
||||
dev = info[base][0] - info[lid][0]
|
||||
row = {"box": bn, "n": len(info), "dev_before": round(dev, 3)}
|
||||
if abs(dev) <= TOL:
|
||||
row["action"] = "skip"
|
||||
report.append(row)
|
||||
continue
|
||||
bkname = bn + "_bk1006b" # 백업 idef
|
||||
if doc.InstanceDefinitions.Find(bkname) is None:
|
||||
bl = []
|
||||
al = []
|
||||
for ob in objs:
|
||||
bl.append(ob.Geometry.Duplicate())
|
||||
al.append(ob.Attributes.Duplicate())
|
||||
doc.InstanceDefinitions.Add(bkname, "backup before s-realign", Rhino.Geometry.Point3d.Origin, bl, al)
|
||||
ds = -dev
|
||||
dz = k * ds # 경사 접선 방향 이동 -> 수직 피복 유지
|
||||
v = Rhino.Geometry.Vector3d(ca * ds, sa * ds, dz)
|
||||
v.Transform(inv) # 월드 이동벡터 -> idef 로컬
|
||||
ztop = info[lid][3] - RBAR # 뚜껑 윗변 중심 z (월드)
|
||||
pl = Rhino.Geometry.Plane(Rhino.Geometry.Point3d(0.0, 0.0, ztop), Rhino.Geometry.Vector3d.ZAxis)
|
||||
pl.Transform(inv)
|
||||
newgeoms = []
|
||||
for i in range(len(geoms)):
|
||||
if abs(info[i][0] - info[lid][0]) > TOL: # 뚜껑 평면에서 벗어난 조각만 이동
|
||||
m = geoms[i]
|
||||
m.Translate(v)
|
||||
chk = m.Duplicate()
|
||||
chk.Transform(T)
|
||||
if chk.GetBoundingBox(True).Max.Z > ztop + 0.05:
|
||||
tr = m.Trim(pl, 0.01) # +Z 쪽 제거
|
||||
if tr is not None and len(tr) > 0:
|
||||
m = tr[0]
|
||||
newgeoms.append(m)
|
||||
else:
|
||||
newgeoms.append(geoms[i])
|
||||
doc.InstanceDefinitions.ModifyGeometry(bidf.Index, newgeoms, attrs) # 3-인자: 속성 보존
|
||||
row["action"] = "fixed"
|
||||
row["dz"] = round(dz, 3)
|
||||
report.append(row)
|
||||
doc.Views.Redraw()
|
||||
txt = json.dumps(report)
|
||||
f = io.open(out, "w", encoding="utf-8")
|
||||
try:
|
||||
f.write(txt)
|
||||
except TypeError:
|
||||
f.write(txt.decode("utf-8"))
|
||||
f.close()
|
||||
Reference in new issue
Block a user