Extracted per-sheet pattern groups (입출구부 50 m / 온도미고려), note-5 scope, fck 27 MPa, SD400, aggregate 25 mm, rebar label counts and printed radii. Model keeps R1 = 6,982 mm; lining sheets print 6.892 m -> [CONFLICT DETECTED] for user check. Sheet-to-station and pattern-name mapping left [미확정]. Viewer shows the lining spec on click. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A5Cun3RHQKna9qxE6ybZ4A
99 lines
3.9 KiB
Python
99 lines
3.9 KiB
Python
#!/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 <RAG_04_DIR> <OUT_JSON>
|
|
"""
|
|
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()
|