- 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>
61 lines
3.0 KiB
Python
61 lines
3.0 KiB
Python
import sys, json, math, collections
|
|
sys.path.insert(0, 'pylib')
|
|
import rhino3dm
|
|
M = r"D:\★Pier 자료\심수석님 검토 파일\Ramp-A교P1\ramp-A G5.3dm"
|
|
m3 = rhino3dm.File3dm.Read(M)
|
|
def V(p): return (p.X, p.Y, p.Z)
|
|
def sub(a, b): return (a[0]-b[0], a[1]-b[1], a[2]-b[2])
|
|
def dot(a, b): return a[0]*b[0]+a[1]*b[1]+a[2]*b[2]
|
|
def nrm(a): return math.sqrt(dot(a, a))
|
|
def addv(a, b, t): return (a[0]+b[0]*t, a[1]+b[1]*t, a[2]+b[2]*t)
|
|
def isect(p1, d1, p2, d2):
|
|
w = sub(p1, p2); a = dot(d1, d1); b = dot(d1, d2); c = dot(d2, d2); d = dot(d1, w); e = dot(d2, w)
|
|
den = a*c - b*b
|
|
if abs(den) < 1e-9: return None
|
|
return addv(p1, d1, (b*e - c*d)/den)
|
|
def segs_of(g):
|
|
if isinstance(g, rhino3dm.PolyCurve): return [g.SegmentCurve(i) for i in range(g.SegmentCount)]
|
|
return [g]
|
|
def is_line(s): return type(s).__name__ in ("LineCurve", "PolylineCurve")
|
|
def is_arc(s): return type(s).__name__ == "ArcCurve"
|
|
def cseq(g):
|
|
lines = [(V(s.PointAtStart), V(s.PointAtEnd)) for s in segs_of(g) if is_line(s)]
|
|
if len(lines) < 2: return [nrm(sub(l[1], l[0])) for l in lines]
|
|
pts = []
|
|
for i in range(len(lines)-1):
|
|
p1, q1 = lines[i]; p2, q2 = lines[i+1]
|
|
p = isect(p1, sub(q1, p1), p2, sub(q2, p2))
|
|
pts.append(p if p else q1)
|
|
seq = [lines[0][0]] + pts + [lines[-1][1]]
|
|
return [nrm(sub(seq[i+1], seq[i])) for i in range(len(seq)-1)]
|
|
def desc(g):
|
|
out = []
|
|
for s in segs_of(g):
|
|
if is_line(s): out.append("L%.0f" % nrm(sub(V(s.PointAtEnd), V(s.PointAtStart))))
|
|
elif is_arc(s): out.append("A r%.1f a%.1f" % (s.Arc.Radius, s.Arc.AngleDegrees))
|
|
else: out.append(type(s).__name__)
|
|
return " ".join(out)
|
|
bars = collections.defaultdict(list)
|
|
for o in m3.Objects:
|
|
g = o.Geometry
|
|
if isinstance(g, rhino3dm.Brep) or not hasattr(g, "PointAtStart"):
|
|
continue
|
|
us = dict(o.Attributes.GetUserStrings())
|
|
if us.get("mark"):
|
|
bars[us["mark"]].append((us, g))
|
|
out = {}
|
|
lines = []
|
|
for mk, items in sorted(bars.items()):
|
|
seqs = [[round(x) for x in cseq(g)] for us, g in items]
|
|
dl = [float(us["design_length"]) + float(us.get("coupler_length") or 0) for us, g in items]
|
|
allv = sorted(set(v for s in seqs for v in s))
|
|
items.sort(key=lambda b: float(b[0]["design_length"]))
|
|
out[mk] = {"n": len(items), "dl": dl, "seqs": seqs, "values": allv, "shape": items[0][0]["shape"], "dia": items[0][0]["dia"], "host": items[0][0].get("host")}
|
|
lines.append("%s n=%d %s %s dl %.0f..%.0f | min: %s | max: %s" % (mk, len(items), items[0][0]["shape"], items[0][0]["dia"], min(dl), max(dl), desc(items[0][1]), desc(items[-1][1])))
|
|
c = collections.Counter(tuple(s) for s in seqs)
|
|
for s, k in sorted(c.items())[:3] + (sorted(c.items())[-2:] if len(c) > 3 else []):
|
|
lines.append(" %d x %s" % (k, s))
|
|
json.dump(out, open("ra_model_dims.json", "w", encoding="utf-8"), ensure_ascii=False)
|
|
open("ra_model_out.txt", "w", encoding="utf-8").write("\n".join(lines))
|
|
print("ok", len(out))
|