#!/usr/bin/env python3 """Extract structured lining-reinforcement data from the concrete-lining structure drawings 04-004..009 (read-only on RAG). Per sheet: pattern groups and their detail kind (입출구부 50 m / 온도미고려), note-5 scope sentence, concrete and rebar grade, rebar sizes present, radius and lap dimensions as printed, EL datum texts. Output: data/lining_spec.json (+ printed summary). Usage: extract_lining_spec.py """ import glob import json import os import re import sys import ezdxf from ezdxf import recover RAG_04, OUT = sys.argv[1], sys.argv[2] BAR_RE = re.compile(r"^0?H(\d{2})$") PAT_RE = re.compile(r"\(([^()]*?)\s*패턴\)") GROUP_RE = re.compile(r"주철근 조립도\(([^()]*?)\s*패턴\)") def load(path): try: return ezdxf.readfile(path) except Exception: doc, _ = recover.readfile(path) return doc def texts_of(doc): out = [] for e in doc.modelspace(): if e.dxftype() == "TEXT": s = e.dxf.text elif e.dxftype() == "MTEXT": s = e.plain_text() else: continue if s and s.strip(): out.append((e.dxf.layer, round(e.dxf.insert.x, 1), round(e.dxf.insert.y, 1), s.strip())) return out def sheet_no(name): return int(re.search(r"C0060304-(\d{3})", name).group(1)) def main(): files = sorted(glob.glob(os.path.join(RAG_04, "C0060304-00[4-9]*.dxf"))) sheets = [] for f in files: doc = load(f) tx = texts_of(doc) rec = {"sheet": sheet_no(f), "file": os.path.basename(f)} # pattern groups: detail kind from the text itself groups = [] for layer, x, y, s in tx: if layer != "CS-TABL-TEX1": continue if "패턴" in s: kind = "입출구부 50m" if "입출구부" in s else ("온도미고려" if "온도미고려" in s else "기타") m = PAT_RE.search(s) groups.append({"group": m.group(1) if m else None, "kind": kind, "raw": s}) rec["pattern_details"] = groups # scope note 5 (full line, joined with the continuation line) note5 = [s for _, _, _, s in tx if s.startswith("5. 본 콘크리트 라이닝 구조도")] cont = [s for _, _, _, s in tx if s.startswith("설계조건과 상이할 경우")] rec["note5"] = (note5[0] + " " + (cont[0] if cont else "")).strip() if note5 else None rec["concrete"] = sorted({s for _, _, _, s in tx if "fck" in s}) rec["rebar_grade"] = sorted({s for _, _, _, s in tx if "fy=" in s}) rec["aggregate"] = sorted({s for _, _, _, s in tx if "최대치수" in s}) bars = {} for layer, x, y, s in tx: m = BAR_RE.match(s) if m: bars[f"H{m.group(1)}"] = bars.get(f"H{m.group(1)}", 0) + 1 rec["rebar_sizes_label_count"] = dict(sorted(bars.items())) rec["radius_dims"] = sorted({s for layer, _, _, s in tx if layer == "CS-DIMT" and re.match(r"R\d?'?=", s)}) rec["lap_dims"] = sorted({s for layer, _, _, s in tx if layer == "CS-DIMT" and "mm" in s and "이음장" not in s and "600" in s}) rec["el_texts"] = sorted({s for _, _, _, s in tx if s.startswith("EL")}) rec["entrance_exit_50m"] = any("입출구부 50m" in s for _, _, _, s in tx) sheets.append(rec) with open(OUT, "w", encoding="utf-8") as fh: json.dump({"source": "C0060304-004..009 (콘크리트라이닝구조도)", "sheets": sheets}, fh, ensure_ascii=False, indent=1) for r in sheets: print("==", r["sheet"], "| groups:", [(g["group"], g["kind"]) for g in r["pattern_details"]]) print(" note5:", (r["note5"] or "")[:140]) print(" concrete:", r["concrete"], "| rebar:", r["rebar_grade"], "| agg:", r["aggregate"]) print(" bars:", r["rebar_sizes_label_count"], "| R:", r["radius_dims"], "| EL:", r["el_texts"]) if __name__ == "__main__": main()