86 lines
3.2 KiB
Python
86 lines
3.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Inventory the main-line (본선) DXF drawings: header, layers, entity counts,
|
|
extents, 3D flag and text samples. Read-only on the source RAG folder."""
|
|
import collections
|
|
import glob
|
|
import json
|
|
import os
|
|
import sys
|
|
|
|
import ezdxf
|
|
from ezdxf import bbox, recover
|
|
|
|
RAG_DIR = sys.argv[1]
|
|
OUT_JSON = sys.argv[2]
|
|
# 본선 scope (approved 2026-10-21): 02 평면·종단, 03 본선굴착, 04 본선기타
|
|
SUBDIRS = ["02_평면 및 종단면도", "03_본선터널굴착", "04_본선터널기타"]
|
|
|
|
|
|
def inventory(path):
|
|
rec = {"file": os.path.basename(path), "ok": False}
|
|
rec["recovered"] = False
|
|
try:
|
|
doc = ezdxf.readfile(path)
|
|
except Exception as exc: # strict load failed: retry in recover mode and record it
|
|
strict_error = f"{type(exc).__name__}: {exc}"
|
|
try:
|
|
doc, _auditor = recover.readfile(path)
|
|
rec["recovered"] = True
|
|
rec["strict_error"] = strict_error
|
|
except Exception as exc2:
|
|
rec["error"] = f"{strict_error} | recover: {type(exc2).__name__}: {exc2}"
|
|
return rec
|
|
hdr = doc.header
|
|
rec["dxfversion"] = doc.dxfversion
|
|
rec["insunits"] = hdr.get("$INSUNITS")
|
|
rec["codepage"] = hdr.get("$DWGCODEPAGE")
|
|
rec["layers"] = len(doc.layers)
|
|
msp = doc.modelspace()
|
|
counts = collections.Counter(e.dxftype() for e in msp)
|
|
rec["entity_counts"] = dict(counts.most_common())
|
|
rec["blocks"] = len([b for b in doc.blocks if not b.name.startswith("*")])
|
|
z_vals = []
|
|
texts = []
|
|
for e in msp:
|
|
t = e.dxftype()
|
|
if t == "LINE":
|
|
z_vals += [e.dxf.start.z, e.dxf.end.z]
|
|
elif t in ("TEXT", "MTEXT"):
|
|
s = e.dxf.text if t == "TEXT" else e.plain_text()
|
|
if s and len(texts) < 40:
|
|
texts.append(s.strip()[:80])
|
|
elif t in ("POINT", "INSERT", "CIRCLE", "ARC"):
|
|
z_vals.append(e.dxf.location.z if t == "POINT" else e.dxf.insert.z if t == "INSERT" else e.dxf.center.z)
|
|
rec["z_min"] = round(min(z_vals), 3) if z_vals else None
|
|
rec["z_max"] = round(max(z_vals), 3) if z_vals else None
|
|
rec["has_3d_geometry"] = bool(z_vals) and (max(z_vals) - min(z_vals)) > 1e-6
|
|
try:
|
|
ext = bbox.extents(msp)
|
|
rec["extents_min"] = [round(v, 2) for v in ext.extmin]
|
|
rec["extents_max"] = [round(v, 2) for v in ext.extmax]
|
|
except Exception as exc:
|
|
rec["extents_error"] = str(exc)
|
|
rec["text_sample"] = texts
|
|
rec["ok"] = True
|
|
return rec
|
|
|
|
|
|
def main():
|
|
paths = []
|
|
for sub in SUBDIRS:
|
|
paths += sorted(glob.glob(os.path.join(RAG_DIR, sub, "*.dxf")))
|
|
results = [inventory(p) for p in paths]
|
|
os.makedirs(os.path.dirname(OUT_JSON), exist_ok=True)
|
|
with open(OUT_JSON, "w", encoding="utf-8") as fh:
|
|
json.dump(results, fh, ensure_ascii=False, indent=2)
|
|
ok = sum(r["ok"] for r in results)
|
|
print(f"files={len(results)} ok={ok} failed={len(results) - ok}")
|
|
for r in results:
|
|
status = "OK " if r["ok"] else "ERR"
|
|
detail = r.get("error") or f"ents={sum(r['entity_counts'].values())} 3D={r['has_3d_geometry']} units={r['insunits']} cp={r['codepage']} recovered={r['recovered']}"
|
|
print(f"{status} {r['file'][:60]:60s} {detail}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|