Files
Pier_v1/Code/검토수정/스크립트/c1_core.py
T
ahnyongjooandClaude Sonnet 5.5 964a841de1 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>
2026-10-28 11:20:18 +09:00

103 lines
3.6 KiB
Python

#! python3
# shared logic for C-1 (bend radius -> KDS 24 14 21 Table 4.5-1). Pure geometry, no document edits.
import math
import Rhino
from Rhino.Geometry import Arc, Line, Point3d, Vector3d, PolyCurve, PolylineCurve, ArcCurve, Curve, Brep, PipeCapMode
from Rhino.Geometry.Intersect import Intersection
BASE = r"D:\★Pier 자료\프로그램\Pier_T\검토파일"
NOMINAL = {13: 12.7, 16: 15.9, 19: 19.1, 22: 22.2, 25: 25.4, 29: 28.6, 32: 31.8, 35: 34.9}
def required_rc(dia):
"""Minimum centreline bend radius: inner diameter >= 3.5db (D19+) / 2db (<=D16), db nominal, tube d = integer dia."""
d = int("".join(ch for ch in dia if ch.isdigit()))
nom = NOMINAL[d]
inner_r = 1.75 * nom if d >= 19 else 1.0 * nom
return math.ceil((inner_r + d / 2.0) * 100.0) / 100.0, d
def _is_straight(c):
if isinstance(c, PolylineCurve):
return True
return c.IsLinear(1e-6)
def plan_curve(poly, dia):
"""Return (new_polycurve or None, info). info['short'] = number of short arcs, info['status'] ok|complex|unchanged."""
req, d = required_rc(dia)
n = poly.SegmentCount
segs = [poly.SegmentCurve(i).DuplicateCurve() for i in range(n)]
short = []
for i, s in enumerate(segs):
ok, arc = s.TryGetArc()
if ok and not s.IsLinear() and arc.Radius < req - 1e-6 and math.degrees(arc.Angle) < 179.0:
short.append(i)
info = {"short": len(short), "req": req, "status": "unchanged"}
if not short:
return None, info
# each short arc needs straight neighbours (or curve ends) and tangent continuity
for i in short:
for j in (i - 1, i + 1):
if 0 <= j < n and not _is_straight(segs[j]):
info["status"] = "complex"
return None, info
if 0 <= j < n and j in short:
info["status"] = "complex"
return None, info
new = list(segs)
for i in short:
ok, arc = segs[i].TryGetArc()
p0, p1 = arc.StartPoint, arc.EndPoint
t0 = segs[i].TangentAtStart
t1 = segs[i].TangentAtEnd
t0.Unitize()
t1.Unitize()
ok2, a, b = Intersection.LineLine(Line(p0, p0 + t0 * 1e5), Line(p1 - t1 * 1e5, p1))
if not ok2:
info["status"] = "complex"
return None, info
corner = Line(p0, p0 + t0 * 1e5).PointAt(a)
theta = math.acos(max(-1.0, min(1.0, t0 * t1)))
tl = req * math.tan(theta / 2.0)
ns = corner - t0 * tl
ne = corner + t1 * tl
mid_arc = Arc(ns, t0, ne)
if not mid_arc.IsValid:
info["status"] = "complex"
return None, info
new[i] = ArcCurve(mid_arc)
if i - 1 >= 0:
pc = new[i - 1].DuplicateCurve()
new[i - 1] = _retarget(pc, end=ns)
if i + 1 < n:
nc = new[i + 1].DuplicateCurve()
new[i + 1] = _retarget(nc, start=ne)
pc = PolyCurve()
for s in new:
if s is None:
info["status"] = "complex"
return None, info
pc.Append(s)
info["status"] = "ok"
return pc, info
def _retarget(c, start=None, end=None):
if isinstance(c, PolylineCurve):
pts = [c.Point(i) for i in range(c.PointCount)]
if start is not None:
pts[0] = start
if end is not None:
pts[-1] = end
return PolylineCurve(pts)
a = start if start is not None else c.PointAtStart
b = end if end is not None else c.PointAtEnd
return Rhino.Geometry.LineCurve(a, b)
def make_pipe(curve, d, tol):
r = d / 2.0
res = Brep.CreatePipe(curve, r, False, PipeCapMode.Flat, True, tol, Rhino.RhinoMath.ToRadians(1.0))
return res