logging in plant2dxf.py, svg2dxf.py und dxf2lib.py implementiert
SVG2DXF: Inkscape-Option hinzugefügt, die mit einem SVG Parser arbeitet
This commit is contained in:
+77
-30
@@ -13,12 +13,21 @@ import configparser
|
||||
import ezdxf
|
||||
from pathlib import Path
|
||||
import math
|
||||
from utils import check_environment_var, setup_logger
|
||||
|
||||
# --------------------------------------------------------- CFG-Leser für shapes.cfg
|
||||
def get_shape_cfg(teileart, cfg_path):
|
||||
def get_shape_cfg(teileart, cfg_path, logger=None):
|
||||
parser = configparser.ConfigParser()
|
||||
with open(cfg_path, encoding='utf-8') as f:
|
||||
parser.read_file(f)
|
||||
try:
|
||||
with open(cfg_path, encoding='utf-8') as f:
|
||||
parser.read_file(f)
|
||||
except Exception as e:
|
||||
msg = f"Fehler beim Lesen der Config-Datei {cfg_path}: {e}"
|
||||
if logger:
|
||||
logger.error(msg)
|
||||
else:
|
||||
print(msg)
|
||||
return []
|
||||
section = teileart
|
||||
if section not in parser:
|
||||
return []
|
||||
@@ -53,14 +62,6 @@ ATTR_TAG = "TeileId" # Attributtag im Block
|
||||
RADIUS = 400 # Radius der Kreiselkreise (mm)
|
||||
|
||||
# --------------------------------------------------------- Hilfsfunktionen
|
||||
def check_environment_var(env_str: str) -> Path:
|
||||
"""Liefert Path aus Umgebungsvariable oder beendet mit Fehlermeldung."""
|
||||
out_path = os.environ.get(env_str)
|
||||
if out_path:
|
||||
return Path(out_path)
|
||||
print(f"Umgebungsvariable {env_str} ist nicht gesetzt oder leer.")
|
||||
sys.exit(1)
|
||||
|
||||
def extract_coords(planquadrat: str) -> tuple[float, float]:
|
||||
"""Extrahiert X/Y Koordinaten aus PlanquadratString."""
|
||||
m = re.search(r"X:(\d+[\.,]?\d*)\s+Y:(\d+[\.,]?\d*)", planquadrat)
|
||||
@@ -87,8 +88,9 @@ def import_block(block_name: str, from_doc, to_doc) -> None:
|
||||
for ent in src:
|
||||
tgt.add_entity(ent.copy())
|
||||
|
||||
def berechne_hoehe(csv_path):
|
||||
y_werte = []
|
||||
def berechne_hoehe(csv_path, logger=None):
|
||||
y_werte = []
|
||||
try:
|
||||
with csv_path.open(newline="", encoding="utf-8") as fh:
|
||||
reader = csv.DictReader(fh, delimiter=';')
|
||||
for row in reader:
|
||||
@@ -96,11 +98,23 @@ def berechne_hoehe(csv_path):
|
||||
try:
|
||||
_, y = extract_coords(planquadrat)
|
||||
y_werte.append(y)
|
||||
except Exception:
|
||||
continue
|
||||
if not y_werte:
|
||||
raise ValueError("Keine Y-Koordinaten in der CSV gefunden!")
|
||||
return max(y_werte)
|
||||
except Exception as e:
|
||||
if logger:
|
||||
logger.warning(f"Fehler beim Extrahieren der Koordinate aus '{planquadrat}': {e}")
|
||||
except Exception as e:
|
||||
if logger:
|
||||
logger.error(f"Fehler beim Lesen der CSV-Datei {csv_path}: {e}")
|
||||
else:
|
||||
print(f"Fehler beim Lesen der CSV-Datei {csv_path}: {e}")
|
||||
return 0
|
||||
if not y_werte:
|
||||
msg = "Keine Y-Koordinaten in der CSV gefunden!"
|
||||
if logger:
|
||||
logger.error(msg)
|
||||
else:
|
||||
print(msg)
|
||||
raise ValueError(msg)
|
||||
return max(y_werte)
|
||||
|
||||
def transform_coords(x: float, y: float, height: float) -> tuple[float, float]:
|
||||
"""Transformiert Bildschirmkoordinaten (0,0 oben links) ins DXF-KoSy (0,0 unten links)."""
|
||||
@@ -276,7 +290,7 @@ def normalize_func_name(name):
|
||||
|
||||
# --------------------------------------------------------- Hauptfunktion
|
||||
def main(csv_path: Path, lib_path: Path, cfg_path: Path,
|
||||
output_path: Path, verbose=False):
|
||||
output_path: Path, verbose=False, logger=None):
|
||||
|
||||
# Bibliothek nur laden, wenn Datei existiert
|
||||
lib_doc = None
|
||||
@@ -284,12 +298,21 @@ def main(csv_path: Path, lib_path: Path, cfg_path: Path,
|
||||
try:
|
||||
lib_doc = ezdxf.readfile(lib_path)
|
||||
if verbose:
|
||||
print(f"[INFO] Bibliothek geladen: {lib_path}")
|
||||
logger.info(f"[INFO] Bibliothek geladen: {lib_path}") if logger else print(f"[INFO] Bibliothek geladen: {lib_path}")
|
||||
except Exception as e:
|
||||
sys.exit(f"Fehler beim Lesen der Bibliothek '{lib_path}': {e}")
|
||||
msg = f"Fehler beim Lesen der Bibliothek '{lib_path}': {e}"
|
||||
if logger:
|
||||
logger.error(msg)
|
||||
else:
|
||||
print(msg)
|
||||
sys.exit(1)
|
||||
else:
|
||||
print(f"[INFO] Keine Bibliothek gefunden unter {lib_path}.")
|
||||
exit(1)
|
||||
msg = f"[INFO] Keine Bibliothek gefunden unter {lib_path}."
|
||||
if logger:
|
||||
logger.warning(msg)
|
||||
else:
|
||||
print(msg)
|
||||
sys.exit(1)
|
||||
|
||||
# Neue Zielzeichnung (DXF R2018)
|
||||
doc = ezdxf.new(dxfversion="R2018")
|
||||
@@ -297,7 +320,15 @@ def main(csv_path: Path, lib_path: Path, cfg_path: Path,
|
||||
|
||||
# CSV einlesen
|
||||
# Höhe bestimmen für Koordinaten-Transformation
|
||||
height = berechne_hoehe(csv_path)
|
||||
try:
|
||||
height = berechne_hoehe(csv_path, logger=logger)
|
||||
except Exception as e:
|
||||
msg = f"Fehler bei der Höhenberechnung: {e}"
|
||||
if logger:
|
||||
logger.error(msg)
|
||||
else:
|
||||
print(msg)
|
||||
sys.exit(1)
|
||||
|
||||
# Verarbeitung der Blöcke
|
||||
with csv_path.open(newline="", encoding="utf-8") as fh:
|
||||
@@ -312,22 +343,33 @@ def main(csv_path: Path, lib_path: Path, cfg_path: Path,
|
||||
x_screen, y_screen = extract_coords(planquadrat)
|
||||
x, y = transform_coords(x_screen, y_screen, height)
|
||||
except Exception as e:
|
||||
print(f"[WARN] {teileid}: {e}")
|
||||
msg = f"[WARN] {teileid}: {e}"
|
||||
if logger:
|
||||
logger.warning(msg)
|
||||
else:
|
||||
print(msg)
|
||||
continue
|
||||
|
||||
# Funktions-Dispatch: handle_<teileart> (mit _ statt Leerzeichen und Punkten, alles klein)
|
||||
func_name = f'handle_{normalize_func_name(teileart)}'
|
||||
handler = globals().get(func_name)
|
||||
symbols = get_shape_cfg(teileart, cfg_path)
|
||||
symbols = get_shape_cfg(teileart, cfg_path, logger=logger)
|
||||
if handler:
|
||||
handler(msp, teileid, merkmale, x, y, doc, lib_doc, verbose, symbols)
|
||||
else:
|
||||
print(f"[WARN] Keine Routine für TeileArt '{teileart}'. Überspringe '{teileid}'.")
|
||||
continue
|
||||
msg = f"[WARN] Keine Routine für TeileArt '{teileart}'. Überspringe '{teileid}'."
|
||||
if logger:
|
||||
logger.warning(msg)
|
||||
else:
|
||||
print(msg)
|
||||
continue
|
||||
|
||||
# DXF speichern
|
||||
doc.saveas(output_path)
|
||||
print(f"[DONE] DXF gespeichert unter: {output_path}")
|
||||
if logger:
|
||||
logger.info(f"[DONE] DXF gespeichert unter: {output_path}")
|
||||
else:
|
||||
print(f"[DONE] DXF gespeichert unter: {output_path}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(
|
||||
@@ -340,10 +382,14 @@ if __name__ == "__main__":
|
||||
args = parser.parse_args()
|
||||
|
||||
# Verzeichnisse aus Umgebungsvariablen
|
||||
log_dir = check_environment_var("PROJECT_LOG")
|
||||
data_dir = check_environment_var("PROJECT_DATA")
|
||||
work_dir = check_environment_var("PROJECT_WORK")
|
||||
config_dir = check_environment_var("PROJECT_CFG")
|
||||
|
||||
logger = setup_logger(log_dir, name='plant2dxf')
|
||||
logger.info("=== plant2dxf Verarbeitung gestartet ===")
|
||||
|
||||
# CSV‑Pfad: nur Dateiname → im WORK‑Ordner suchen
|
||||
if os.sep not in args.file and "/" not in args.file:
|
||||
csv_path = work_dir / args.file
|
||||
@@ -354,4 +400,5 @@ if __name__ == "__main__":
|
||||
lib_path = Path(args.lib) if args.lib else data_dir / "blocks.dxf"
|
||||
output_path = Path(args.output) if args.output else (work_dir / f"{csv_path.stem}.dxf")
|
||||
|
||||
main(csv_path, lib_path, cfg_path, output_path, verbose=args.verbose)
|
||||
main(csv_path, lib_path, cfg_path, output_path, verbose=args.verbose, logger=logger)
|
||||
logger.info("=== plant2dxf Verarbeitung abgeschlossen ===")
|
||||
|
||||
Reference in New Issue
Block a user