#! python3 # Ungok footing rebar: (a) bend radius C-1 for B1,B2,B3,B7,B10 (b) z-shift to drawing lines (user approved 2026-10-23) # Source: previous modified model (..._수정_20261023.3dm). Result saved under a NEW name; geometry replaced in place. import sys, os, json, math, collections, traceback sys.path.insert(0, r"C:\Users\User\AppData\Local\PierApp\jobs\c1_work") import c1_core import Rhino from Rhino.Geometry import Transform, Vector3d from c1_core import BASE, plan_curve, make_pipe, required_rc DATE_TXT = "2026-10-23" FOLDER = os.path.join(BASE, "철근 모델랑 운곡교P1_바이브코딩") SRC = os.path.join(FOLDER, "운곡교p1_수정_20261023.3dm") DST = os.path.join(FOLDER, "운곡교p1_수정2_20261023.3dm") OUT = r"C:\Users\User\AppData\Local\PierApp\jobs\c1_work\c1_footing_ungok.json" SHIFT = {"B1": 27.0, "B2": 28.0, "B4": 28.0, "B5": -27.0, "B6": -28.0, "B8": -28.0} # mm, z RFIX = {"B1", "B2", "B3", "B7", "B10"} res = {} def zrange(doc, items): zs = [(o.Geometry.GetBoundingBox(True).Min.Z, o.Geometry.GetBoundingBox(True).Max.Z) for o in items] return [round(min(z[0] for z in zs), 2), round(max(z[1] for z in zs), 2)] if zs else None def stamp(doc, what): doc.Strings.SetString("수정일", DATE_TXT) prev = doc.Strings.GetValue("수정내용") or "" doc.Strings.SetString("수정내용", (prev + " | " if prev else "") + what) try: doc = Rhino.RhinoDoc.OpenHeadless(SRC) tol = doc.ModelAbsoluteTolerance st = Rhino.DocObjects.ObjectEnumeratorSettings() st.HiddenObjects = True st.LockedObjects = True st.NormalObjects = True lay = {l.Index: l.FullPath for l in doc.Layers} res["objects_before"] = doc.Objects.Count footing = [o for o in doc.Objects.GetObjectList(st) if o.Attributes.Name == "P1-FT"] fbot = footing[0].Geometry.GetBoundingBox(True).Min.Z res["footing_bottom_z"] = round(fbot, 3) breps = collections.defaultdict(list) curves = [] for o in doc.Objects.GetObjectList(st): g = o.Geometry L = lay.get(o.Attributes.LayerIndex, "") if isinstance(g, Rhino.Geometry.Brep) and "철근" in L: breps[o.Attributes.Name].append(o) elif isinstance(g, Rhino.Geometry.Curve) and "중심선" in L and o.Attributes.GetUserString("host") == "P1-FT": curves.append(o) by_mark = collections.defaultdict(list) for o in curves: by_mark[o.Attributes.GetUserString("mark")].append(o) res["z_before"] = {m: zrange(doc, v) for m, v in by_mark.items()} stat = collections.Counter() for m, items in by_mark.items(): for o in items: a = o.Attributes dia = a.GetUserString("dia") nb = breps.get(a.Name.replace("-RC-", "-R-"), []) if len(nb) != 1: stat[m + "_no_brep"] += 1 continue cid, bid = o.Id, nb[0].Id did = [] if m in RFIX and isinstance(o.Geometry, Rhino.Geometry.PolyCurve): pc, info = plan_curve(o.Geometry, dia) if info["status"] == "ok": req, d = required_rc(dia) pipes = make_pipe(pc, d, tol) if pipes and len(pipes) == 1 and pipes[0].IsSolid: if doc.Objects.Replace(cid, pc) and doc.Objects.Replace(bid, pipes[0]): did.append("R %.2f" % req) stat[m + "_rfix"] += 1 else: stat[m + "_rfix_replace_failed"] += 1 else: stat[m + "_rfix_pipe_fail"] += 1 elif info["status"] != "unchanged": stat[m + "_rfix_" + info["status"]] += 1 if m in SHIFT: xf = Transform.Translation(Vector3d(0, 0, SHIFT[m])) gc = doc.Objects.FindId(cid).Geometry.Duplicate() gb = doc.Objects.FindId(bid).Geometry.Duplicate() gc.Transform(xf) gb.Transform(xf) if doc.Objects.Replace(cid, gc) and doc.Objects.Replace(bid, gb): did.append("dz %+.0f" % SHIFT[m]) stat[m + "_shift"] += 1 else: stat[m + "_shift_replace_failed"] += 1 if did: for oid in (cid, bid): ro = doc.Objects.FindId(oid) at = ro.Attributes.Duplicate() at.SetUserString("footing_fix", "; ".join(did) + " (" + DATE_TXT + ", user rule: outermost bar centre on drawing line)") doc.Objects.ModifyAttributes(ro, at, True) items_after = collections.defaultdict(list) for o in doc.Objects.GetObjectList(st): if isinstance(o.Geometry, Rhino.Geometry.Curve) and "중심선" in lay.get(o.Attributes.LayerIndex, "") and o.Attributes.GetUserString("host") == "P1-FT": items_after[o.Attributes.GetUserString("mark")].append(o) res["z_after"] = {m: zrange(doc, v) for m, v in items_after.items()} res["stat"] = dict(stat) stamp(doc, "C-1 bend radius (all non-footing + footing B1,B2,B3,B7,B10); footing z shift B1+27 B2+28 B4+28 B5-27 B6-28 B8-28 to drawing lines (top 100 / bottom 150)") res["objects_after"] = doc.Objects.Count res["saved"] = bool(doc.WriteFile(DST, Rhino.FileIO.FileWriteOptions())) res["out"] = DST doc.Dispose() except Exception: res["error"] = traceback.format_exc() res["done"] = True json.dump(res, open(OUT, "w", encoding="utf-8"), ensure_ascii=False, indent=1)