"""Read column rebar (marks P1-P6) and append `column_rebar` to params.json. Sources (read only): 판독/3_survey.json (D3 rebar schedule rows), D1 DXF (section C-C bar dots and tie lines, front-view hoop/tie levels via dimension chain texts). Existing params.json keys unchanged. Items marked `hitl` are interpretations pending user approval (설계서 v0.1.03). """ import json import math from collections import defaultdict from pathlib import Path import ezdxf HERE = Path(__file__).resolve().parent SCHED_COLS = {"mark": 2100, "shape": 3000, "dia": 3951, "n": 4800, "A": 5846, "B": 7449, "C": 9000, "R": 13449, "L": 19541} SECTION_CC = (23572.5, 26567.1) # D1 단면 C-C concrete ARC 1C77F centre def schedule(): texts = json.loads((HERE / "판독" / "3_survey.json").read_text(encoding="utf-8"))["texts"] rows = defaultdict(dict) for t in texts: if t["x"] > 21000 or t["y"] < 15000: continue # SD400 table occupies x<21000; SD500 table (P1, P2) is handled below col = min(SCHED_COLS, key=lambda c: abs(SCHED_COLS[c] - t["x"])) if abs(SCHED_COLS[col] - t["x"]) < 260: rows[round(t["y"])][col] = t["text"] out = {r["mark"]: r for r in rows.values() if r.get("mark") in ("P3", "P4", "P5", "P6")} # SD500 table: P1/P2 rows (same column pitch, offset by the table origin) off = None for t in texts: if t["text"] == "P1" and t["x"] > 21000 and t["y"] > 15000: off = t["x"] - SCHED_COLS["mark"] rows = defaultdict(dict) for t in texts: if t["x"] > 21000 and t["y"] > 15000: col = min(SCHED_COLS, key=lambda c: abs(SCHED_COLS[c] + off - t["x"])) if abs(SCHED_COLS[col] + off - t["x"]) < 260: rows[round(t["y"])][col] = t["text"] out.update({r["mark"]: r for r in rows.values() if r.get("mark") in ("P1", "P2")}) return out def section_bars(): msp = ezdxf.readfile(sorted((HERE / "입력DXF").glob("*.dxf"))[0]).modelspace() cx, cy = SECTION_CC dots = [] for e in msp.query("LWPOLYLINE"): if e.dxf.layer != "CS-RBAR-MAJR": continue pts = [(p[0], p[1]) for p in e.get_points()] mx, my = sum(p[0] for p in pts) / len(pts), sum(p[1] for p in pts) / len(pts) r = math.hypot(mx - cx, my - cy) if 700 < r < 900: dots.append((math.degrees(math.atan2(my - cy, mx - cx)) % 360, r)) outer = sorted(a for a, r in dots if r > 850) inner = sorted(a for a, r in dots if r < 850) steps = [b - a for a, b in zip(outer, outer[1:])] return dict(count_outer=len(outer), count_inner=len(inner), start_deg=round(outer[0], 3), pitch_deg_mean=round(sum(steps) / len(steps), 4), r_outer_cad=round(sum(r for a, r in dots if r > 850) / len(outer), 1), r_inner_cad=round(sum(r for a, r in dots if r < 850) / len(inner), 1)) def main(): s = schedule() sec = section_bars() footing_bottom = 26208 hoop_levels = [footing_bottom + 150 + 1030 + 120 * i for i in range(9)] # P4: 8@120 hoop_levels += [hoop_levels[-1] + 120 * (i + 1) for i in range(22)] # P5: 22@120 hoop_levels += [hoop_levels[-1] + 300 * (i + 1) for i in range(36)] # P3: 36@300 tie_levels = [footing_bottom + 150 + 1030 + 1800 * k for k in range(9)] # P6: 8@1.800 rebar = dict( _note="Column rebar P1-P6. Z = EL x 1000. Angles from +X counter-clockwise (plan).", schedule={m: s[m] for m in sorted(s)}, main_bars=dict( divisions=46, start_deg=sec["start_deg"], pitch_deg=360 / 46, section_cad=sec, r_outer_dim=875, r_outer=870.5, r_inner=825.5, # HITL H2 2026-10-07: section CAD radii p1=dict(role="outer, hooked into footing (XIV)", hook_leg_z=footing_bottom + 300, bend_r=340, hook_leg=500, hook_dir="outward (radial +)", straight_from=footing_bottom + 300 + 340, straight_len=16213), p2=dict(role="inner, straight (XVI)", z0=footing_bottom + 300, length=16553), src={"radii": "D1 단면 C-C dim '125'/'875' (outer); D1 정면도 lines 1C4DB x=875, 1C4DA x=830 " "(inner); section CAD dots 870.5/825.5", "bottom": "D1 정면도 1C4D7 bottom y -> EL 26.508 (= footing bottom + 300); 1C4DB starts 26.848 " "(= 26.508 + R340); P1 bend b=534 = pi/2 x 340", "top": "schedule: P1 26.848+16.213 = 43.061, P2 26.508+16.553 = 43.061 (drawn lines stop at " "43.011 / 40.411 -> schedule adopted; HITL H1 2026-10-07)"}), hoops=dict(radius=897, levels=hoop_levels, marks=["P4"] * 9 + ["P5"] * 22 + ["P3"] * 36, src={"levels": "D1 정면도 dim chain '150','1.030','8@120=960','22@120=2.640','36@300=10.800' " "(user: @120 adopted over label @100); drawn hoop dots y match", "radius": "D3 R 897 (2*pi*897 = 5636 = L of P4/P5); section ARC r=898; front dots 902 (HITL H2: R897)"}), ties=dict(levels=tie_levels, angles_deg=[0, 45, 90, 135], straight=1836, hook=150, src={"levels": "D1 정면도 dim chain '150','1.030','8@1.800=14.400'", "angles": "D1 단면 C-C tie lines along 0/45/90/135 deg, ends at +-897/898"}), ) params_path = HERE / "params.json" params = json.loads(params_path.read_text(encoding="utf-8")) params["column_rebar"] = rebar params_path.write_text(json.dumps(params, ensure_ascii=False, indent=2), encoding="utf-8") print(json.dumps(dict(schedule=rebar["schedule"], section=sec, hoops=len(hoop_levels), hoop_top=hoop_levels[-1], ties=len(tie_levels) * 4, tie_top=tie_levels[-1]), ensure_ascii=False, indent=1)) if __name__ == "__main__": main()