Files
dxfmakros/lib/split_block_library.py
T

146 lines
4.6 KiB
Python

"""
Teilt ils_library.dxf in einzelne DXF-Dateien pro Block auf.
Jede Ausgabedatei enthaelt den Block + alle seine Unterblock-Abhaengigkeiten.
Aufruf: python split_block_library.py
"""
import os
import sys
import ezdxf
from ezdxf.document import Drawing
# Pfade
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
PROJECT_ROOT = os.path.dirname(SCRIPT_DIR)
LIB_PATH = os.path.join(PROJECT_ROOT, "data", "block_libraries", "ils_library.dxf")
OUT_DIR = os.path.join(PROJECT_ROOT, "data", "ils")
# Nur diese Bloecke exportieren (alle fuer den Vario-Foerderer relevanten)
EXPORT_PREFIXES = (
"Vario_",
"Staustrecke_",
"_3D_AS_",
"_3D_ES_",
)
# Abhaengigkeiten: KS_EIN und KS_AUS muessen immer mitgeliefert werden
ALWAYS_INCLUDE = {"KS_EIN", "KS_AUS"}
def collect_dependencies(src_doc: Drawing, blockname: str, visited: set) -> set:
"""Gibt alle Unterblock-Namen zurueck, die 'blockname' direkt oder transitiv benoetigt."""
if blockname in visited:
return visited
visited.add(blockname)
if blockname not in src_doc.blocks:
return visited
blk = src_doc.blocks[blockname]
for entity in blk:
if entity.dxftype() == "INSERT":
ref = entity.dxf.name
collect_dependencies(src_doc, ref, visited)
return visited
def copy_block(src_doc: Drawing, dst_doc: Drawing, blockname: str):
"""Kopiert einen Block und seine Abhaengigkeiten von src nach dst."""
deps = collect_dependencies(src_doc, blockname, set())
for name in deps:
if name not in src_doc.blocks:
continue
if name in dst_doc.blocks:
continue
src_blk = src_doc.blocks[name]
# Neuen Block im Zieldokument anlegen
dst_blk = dst_doc.blocks.new(
name=name,
base_point=src_blk.block.dxf.base_point if hasattr(src_blk.block.dxf, "base_point") else (0, 0, 0),
)
# Alle Entities kopieren (ausser BLOCK/ENDBLK - die werden automatisch erstellt)
for entity in src_blk:
try:
dst_blk.add_entity(entity.copy())
except Exception:
pass
def export_block(src_doc: Drawing, blockname: str, out_dir: str):
"""Exportiert einen einzelnen Block als eigene DXF-Datei."""
safe_name = blockname.replace("/", "_").replace("\\", "_")
out_path = os.path.join(out_dir, safe_name + ".dxf")
dst_doc = ezdxf.new(dxfversion="R2010")
dst_doc.units = src_doc.units
# Layer aus Quelldatei uebernehmen (nur die benutzten)
for layer in src_doc.layers:
if layer.dxf.name not in dst_doc.layers:
try:
dst_doc.layers.new(
name=layer.dxf.name,
dxfattribs={"color": layer.dxf.get("color", 7)},
)
except Exception:
pass
# Block + Abhaengigkeiten kopieren
copy_block(src_doc, dst_doc, blockname)
dst_doc.saveas(out_path)
return out_path
def main():
print(f"Lese Bibliothek: {LIB_PATH}")
if not os.path.exists(LIB_PATH):
print(f"FEHLER: Datei nicht gefunden: {LIB_PATH}")
sys.exit(1)
src_doc = ezdxf.readfile(LIB_PATH)
print(f" Geladen. Bloecke gesamt: {len(list(src_doc.blocks))}")
os.makedirs(OUT_DIR, exist_ok=True)
# Relevante Bloecke filtern
to_export = []
for blk in src_doc.blocks:
name = blk.name
if name.startswith("*"):
continue
if any(name.startswith(p) for p in EXPORT_PREFIXES) or name in ALWAYS_INCLUDE:
to_export.append(name)
print(f" Zu exportierende Bloecke: {len(to_export)}")
ok = 0
fail = 0
for name in sorted(to_export):
try:
out = export_block(src_doc, name, OUT_DIR)
# KS_EIN/KS_AUS pruefen
check_doc = ezdxf.readfile(out)
has_ks_ein = "KS_EIN" in check_doc.blocks
has_ks_aus = "KS_AUS" in check_doc.blocks
ks_status = ""
if name not in ALWAYS_INCLUDE:
blk = check_doc.blocks[name]
inserts = [e.dxf.name for e in blk if e.dxftype() == "INSERT"]
has_ks_ein_ref = "KS_EIN" in inserts
has_ks_aus_ref = "KS_AUS" in inserts
ks_status = f" KS_EIN={'ja' if has_ks_ein_ref else 'NEIN'} KS_AUS={'ja' if has_ks_aus_ref else 'NEIN'}"
print(f" OK {name}{ks_status}")
ok += 1
except Exception as e:
print(f" FEHLER {name}: {e}")
fail += 1
print(f"\nErgebnis: {ok} exportiert, {fail} Fehler")
print(f"Ausgabeverzeichnis: {OUT_DIR}")
if __name__ == "__main__":
main()