- 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>
73 lines
3.3 KiB
Python
73 lines
3.3 KiB
Python
# execute_rhino_code (IronPython 2.7) - 검토: 파이프 Brep -> 중심선 복원, 치수/각도/길이/피복
|
|
# 마크별로 나눠 실행 (타임아웃 방지). 컴프리헨션/lambda 금지 (exec 스코프 문제).
|
|
import scriptcontext as sc, Rhino, math, System
|
|
from Rhino.Geometry import Point3d, Vector3d, Line
|
|
d = sc.doc
|
|
cop = d.Objects.FindId(System.Guid("d7b51436-d411-4ed6-be00-5af9d2058029")).Geometry
|
|
LAYER = "P1_두부_주철근_1CYCLE::C8_H25"; r = 12.7
|
|
circ = 2*math.pi*r
|
|
out = []
|
|
o = None
|
|
for ob in d.Objects.FindByLayer(d.Layers[d.Layers.FindByFullPath(LAYER, -1)]):
|
|
o = ob
|
|
xf = o.Geometry.Xform
|
|
for leaf in o.InstanceDefinition.GetObjects():
|
|
g = leaf.Geometry.Duplicate(); g.Transform(xf)
|
|
Ltot = 0.0; segs = []
|
|
for f in g.Faces:
|
|
du = f.Domain(0); dv = f.Domain(1)
|
|
c1 = f.IsoCurve(1, du.Mid); c0 = f.IsoCurve(0, dv.Mid)
|
|
if c1.IsClosed and abs(c1.GetLength() - circ) < 2:
|
|
ra = f.IsoCurve(0, dv.ParameterAt(0.0)); rb = f.IsoCurve(0, dv.ParameterAt(0.5))
|
|
elif c0.IsClosed and abs(c0.GetLength() - circ) < 2:
|
|
ra = f.IsoCurve(1, du.ParameterAt(0.0)); rb = f.IsoCurve(1, du.ParameterAt(0.5))
|
|
else:
|
|
continue # 캡 면
|
|
Ltot += (ra.GetLength() + rb.GetLength())/2.0 # 중심선 전개길이
|
|
if ra.IsLinear(0.01):
|
|
segs.append(((ra.PointAtStart + rb.PointAtStart)/2.0, (ra.PointAtEnd + rb.PointAtEnd)/2.0))
|
|
# 체인 정렬
|
|
chain = [segs.pop(0)]
|
|
while len(segs) > 0:
|
|
best = None; i = 0
|
|
while i < len(segs):
|
|
a = segs[i][0]; b = segs[i][1]
|
|
for cand in [(a, False, True), (b, True, True), (b, False, False), (a, True, False)]:
|
|
if cand[2]: ref = chain[-1][1]
|
|
else: ref = chain[0][0]
|
|
dd = cand[0].DistanceTo(ref)
|
|
if best is None or dd < best[0]: best = (dd, i, cand[1], cand[2])
|
|
i += 1
|
|
s_ = segs.pop(best[1])
|
|
if best[2]: s_ = (s_[1], s_[0])
|
|
if best[3]: chain.append(s_)
|
|
else: chain.insert(0, s_)
|
|
# 가상 교점 -> 재료표식 치수/각도
|
|
pts = [chain[0][0]]; k = 0
|
|
while k < len(chain) - 1:
|
|
l1 = Line(chain[k][0], chain[k][1]); l2 = Line(chain[k+1][0], chain[k+1][1])
|
|
ok, ta, tb = Rhino.Geometry.Intersect.Intersection.LineLine(l1, l2, 0.001, False)
|
|
pts.append((l1.PointAt(ta) + l2.PointAt(tb))/2.0); k += 1
|
|
pts.append(chain[-1][1])
|
|
dims = []; angs = []; k = 0
|
|
while k < len(pts) - 1:
|
|
dims.append(round(pts[k].DistanceTo(pts[k+1]), 1)); k += 1
|
|
k = 1
|
|
while k < len(pts) - 1:
|
|
angs.append(round(math.degrees(Vector3d.VectorAngle(pts[k-1] - pts[k], pts[k+1] - pts[k])), 1)); k += 1
|
|
# 피복: 표면 격자 샘플 -> ClosestPoint (메시 정점 사용 금지)
|
|
lm = 1e9
|
|
for f in g.Faces:
|
|
du = f.Domain(0); dv = f.Domain(1); i = 0
|
|
while i <= 60:
|
|
j = 0
|
|
while j <= 24:
|
|
p = f.PointAt(du.ParameterAt(i/60.0), dv.ParameterAt(j/24.0))
|
|
dd = p.DistanceTo(cop.ClosestPoint(p))
|
|
if dd < lm: lm = dd
|
|
j += 1
|
|
i += 1
|
|
out.append("dims=%s sum=%.1f ang=%s Ldev=%.1f centerCover=%.2f" % (str(dims), sum(dims), str(angs), Ltot, lm + r))
|
|
result = "\n".join(out)
|
|
print(result)
|