# 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)