175 lines
5.8 KiB
Python
175 lines
5.8 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.
|
|
|
|
Strategie: Entities des Hauptblocks gehen in den Modelspace der
|
|
Ausgabedatei (NICHT als named block mit gleichem Name). Dadurch
|
|
erzeugt vla-InsertBlock in BricsCAD keinen Namenskonflikt /
|
|
Selbstreferenz-Fehler mehr. Abhaengigkeiten (KS_EIN, KS_AUS, ...)
|
|
werden weiterhin als Blockdefinitionen in die Blocktabelle kopiert.
|
|
"""
|
|
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
|
|
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
|
|
|
|
# Nur Abhaengigkeiten (nicht den Hauptblock selbst) als named blocks kopieren
|
|
deps = collect_dependencies(src_doc, blockname, set())
|
|
deps.discard(blockname)
|
|
for dep in deps:
|
|
if dep not in src_doc.blocks or dep in dst_doc.blocks:
|
|
continue
|
|
src_blk = src_doc.blocks[dep]
|
|
dst_blk = dst_doc.blocks.new(
|
|
name=dep,
|
|
base_point=src_blk.block.dxf.base_point if hasattr(src_blk.block.dxf, "base_point") else (0, 0, 0),
|
|
)
|
|
for entity in src_blk:
|
|
try:
|
|
dst_blk.add_entity(entity.copy())
|
|
except Exception:
|
|
pass
|
|
|
|
# Hauptblock-Entities direkt in den Modelspace schreiben (sichtbar + kein Namenskonflikt)
|
|
msp = dst_doc.modelspace()
|
|
for entity in src_doc.blocks[blockname]:
|
|
try:
|
|
msp.add_entity(entity.copy())
|
|
except Exception:
|
|
pass
|
|
|
|
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:
|
|
# Hauptblock liegt jetzt im Modelspace, nicht mehr als named block
|
|
msp_inserts = [e.dxf.name for e in check_doc.modelspace() if e.dxftype() == "INSERT"]
|
|
has_ks_ein_ref = "KS_EIN" in msp_inserts
|
|
has_ks_aus_ref = "KS_AUS" in msp_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()
|