Dispogruppe-Header korrigiert, Container-Referenzen und --type 2D/3D fuer set_attributs.py
Sivasnr-Werte mit 0_BGxxxxxx-Mustern werden jetzt ueber die neue [container]-Config-Sektion in kommaseparierte Listen aufgeloest. set_attributs.py kann nun explizit zwischen data/omniflo/2D und /3D als Quellverzeichnis waehlen.
This commit is contained in:
+2
-2
@@ -4,7 +4,7 @@
|
|||||||
export_sivas.py - Erzeugt Sivas-Export-CSV mit gruppierten Zeilen und Summierungszeilen.
|
export_sivas.py - Erzeugt Sivas-Export-CSV mit gruppierten Zeilen und Summierungszeilen.
|
||||||
|
|
||||||
Neues CSV-Format:
|
Neues CSV-Format:
|
||||||
Nr;TeileArt;SivasNummer;Dispgruppe;Anzahl;Laenge[mm];Hoehe[m];details
|
Nr;TeileArt;SivasNummer;Dispogruppe;Anzahl;Laenge[mm];Hoehe[m];details
|
||||||
|
|
||||||
- Omniflo Bogen/Weiche: gruppiert nach SivasNummer, Anzahl summiert
|
- Omniflo Bogen/Weiche: gruppiert nach SivasNummer, Anzahl summiert
|
||||||
- Omniflo Gerade: gruppiert nach ARTINR-Attribut, Laenge[mm] summiert
|
- Omniflo Gerade: gruppiert nach ARTINR-Attribut, Laenge[mm] summiert
|
||||||
@@ -492,7 +492,7 @@ def main():
|
|||||||
|
|
||||||
items, _ = process_blocks(blocks, lookup)
|
items, _ = process_blocks(blocks, lookup)
|
||||||
|
|
||||||
header = "Nr;TeileArt;SivasNummer;Dispgruppe;Anzahl;Laenge[mm];Hoehe[m];details"
|
header = "Nr;TeileArt;SivasNummer;Dispogruppe;Anzahl;Laenge[mm];Hoehe[m];details"
|
||||||
with open(output_csv, "w", encoding="utf-8") as f:
|
with open(output_csv, "w", encoding="utf-8") as f:
|
||||||
f.write(header + "\n")
|
f.write(header + "\n")
|
||||||
for item in items:
|
for item in items:
|
||||||
|
|||||||
+59
-8
@@ -39,13 +39,14 @@ Umgebungsvariablen:
|
|||||||
DXFM_RESULTS - Pfad zum results/-Verzeichnis
|
DXFM_RESULTS - Pfad zum results/-Verzeichnis
|
||||||
|
|
||||||
Aufruf:
|
Aufruf:
|
||||||
python lib/set_attributs.py [--number SIVASNR] [--dry-run]
|
python lib/set_attributs.py [--number SIVASNR] [--dry-run] [--type 2D|3D]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import configparser
|
import configparser
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import ezdxf
|
import ezdxf
|
||||||
@@ -64,6 +65,7 @@ def load_config(cfg_path):
|
|||||||
"bogen": [("BESCHR", "ProfilTyp"), ("ARTINR", "Sivasnr"), ...],
|
"bogen": [("BESCHR", "ProfilTyp"), ("ARTINR", "Sivasnr"), ...],
|
||||||
"weiche": [("BESCHR", "ProfilTyp"), ...],
|
"weiche": [("BESCHR", "ProfilTyp"), ...],
|
||||||
"layer": {"bogen": "OF Boegen A-2", "weiche_90": "Weiche 90 Grad A-2", ...},
|
"layer": {"bogen": "OF Boegen A-2", "weiche_90": "Weiche 90 Grad A-2", ...},
|
||||||
|
"container": {"0_BG071090": "0_B10071, 0_B10090, 0_B10090", ...},
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
@@ -81,6 +83,13 @@ def load_config(cfg_path):
|
|||||||
val = val[1:-1]
|
val = val[1:-1]
|
||||||
layer_map[key] = val
|
layer_map[key] = val
|
||||||
result["layer"] = layer_map
|
result["layer"] = layer_map
|
||||||
|
elif section == "container":
|
||||||
|
# Container-Sektion: 0_BGxxxxxx -> bereinigte, kommaseparierte Liste
|
||||||
|
container_map = {}
|
||||||
|
for key, val in config.items(section):
|
||||||
|
parts = [p.strip() for p in val.split(",") if p.strip()]
|
||||||
|
container_map[key] = ", ".join(parts)
|
||||||
|
result["container"] = container_map
|
||||||
else:
|
else:
|
||||||
attrs = []
|
attrs = []
|
||||||
for tag, source in config.items(section):
|
for tag, source in config.items(section):
|
||||||
@@ -131,12 +140,33 @@ def get_layer_for_entry(typ, json_entry, layer_map):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
def resolve_value(source, json_entry, sivasnr):
|
CONTAINER_PATTERN = re.compile(r"0_BG\d+")
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_container_refs(text, container_map):
|
||||||
|
"""
|
||||||
|
Ersetzt jedes Vorkommen von 0_BGxxxxxx in text durch die zugehoerige
|
||||||
|
kommaseparierte Liste aus [container]. Kommt das Muster mehrfach vor,
|
||||||
|
wird jedes Vorkommen einzeln ersetzt. Unbekannte 0_BG-Werte bleiben
|
||||||
|
unveraendert stehen.
|
||||||
|
"""
|
||||||
|
if not container_map or "0_BG" not in text:
|
||||||
|
return text
|
||||||
|
return CONTAINER_PATTERN.sub(
|
||||||
|
lambda m: container_map.get(m.group(0), m.group(0)), text
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_value(source, json_entry, sivasnr, container_map=None):
|
||||||
"""
|
"""
|
||||||
Loest einen Quell-Ausdruck aus der Config auf:
|
Loest einen Quell-Ausdruck aus der Config auf:
|
||||||
- "fester Text" -> fester Text
|
- "fester Text" -> fester Text
|
||||||
- {sivasnr} -> SivasNr-Wert
|
- {sivasnr} -> SivasNr-Wert
|
||||||
- Feldname -> Wert aus json_entry
|
- Feldname -> Wert aus json_entry
|
||||||
|
|
||||||
|
Wird das Feld "Sivasnr" aufgeloest und enthaelt der Wert ein oder
|
||||||
|
mehrere 0_BGxxxxxx-Muster, werden diese anhand von [container] durch
|
||||||
|
die dort hinterlegte kommaseparierte Liste ersetzt.
|
||||||
"""
|
"""
|
||||||
source = source.strip()
|
source = source.strip()
|
||||||
|
|
||||||
@@ -152,7 +182,10 @@ def resolve_value(source, json_entry, sivasnr):
|
|||||||
val = json_entry.get(source)
|
val = json_entry.get(source)
|
||||||
if val is None:
|
if val is None:
|
||||||
return ""
|
return ""
|
||||||
return str(val)
|
val = str(val)
|
||||||
|
if source == "Sivasnr":
|
||||||
|
val = resolve_container_refs(val, container_map)
|
||||||
|
return val
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
@@ -225,7 +258,7 @@ def wrap_entities_in_block(doc, block_name):
|
|||||||
|
|
||||||
|
|
||||||
def add_attdefs_to_dxf(dxf_path, output_path, attr_defs, json_entry, sivasnr,
|
def add_attdefs_to_dxf(dxf_path, output_path, attr_defs, json_entry, sivasnr,
|
||||||
layer_value=""):
|
layer_value="", container_map=None):
|
||||||
"""
|
"""
|
||||||
Oeffnet eine DXF-Datei, fuegt ATTDEF-Entities in den Modelspace ein
|
Oeffnet eine DXF-Datei, fuegt ATTDEF-Entities in den Modelspace ein
|
||||||
und speichert das Ergebnis.
|
und speichert das Ergebnis.
|
||||||
@@ -233,6 +266,7 @@ def add_attdefs_to_dxf(dxf_path, output_path, attr_defs, json_entry, sivasnr,
|
|||||||
attr_defs: Liste von (TAG, source_expression) aus der Config
|
attr_defs: Liste von (TAG, source_expression) aus der Config
|
||||||
json_entry: Dict mit den JSON-Daten fuer dieses Element
|
json_entry: Dict mit den JSON-Daten fuer dieses Element
|
||||||
layer_value: Layer-Name aus [layer]-Sektion (wird als LAYER-ATTDEF gesetzt)
|
layer_value: Layer-Name aus [layer]-Sektion (wird als LAYER-ATTDEF gesetzt)
|
||||||
|
container_map: Dict aus [container]-Sektion fuer 0_BG-Aufloesung in Sivasnr
|
||||||
"""
|
"""
|
||||||
doc = ezdxf.readfile(dxf_path)
|
doc = ezdxf.readfile(dxf_path)
|
||||||
msp = doc.modelspace()
|
msp = doc.modelspace()
|
||||||
@@ -265,7 +299,7 @@ def add_attdefs_to_dxf(dxf_path, output_path, attr_defs, json_entry, sivasnr,
|
|||||||
y_pos = y_start
|
y_pos = y_start
|
||||||
count = 0
|
count = 0
|
||||||
for tag, source in all_defs:
|
for tag, source in all_defs:
|
||||||
default_value = resolve_value(source, json_entry, sivasnr)
|
default_value = resolve_value(source, json_entry, sivasnr, container_map)
|
||||||
prompt = tag
|
prompt = tag
|
||||||
|
|
||||||
msp.add_attdef(
|
msp.add_attdef(
|
||||||
@@ -296,6 +330,7 @@ def process_all(data_dir, cfg_path, results_dir, single_nr=None, dry_run=False):
|
|||||||
# Config laden
|
# Config laden
|
||||||
attr_config = load_config(cfg_path)
|
attr_config = load_config(cfg_path)
|
||||||
layer_map = attr_config.pop("layer", {})
|
layer_map = attr_config.pop("layer", {})
|
||||||
|
container_map = attr_config.pop("container", {})
|
||||||
print(f"[set_attributs] Config geladen: {list(attr_config.keys())}")
|
print(f"[set_attributs] Config geladen: {list(attr_config.keys())}")
|
||||||
if layer_map:
|
if layer_map:
|
||||||
print(f" [layer] {len(layer_map)} Zuordnungen: "
|
print(f" [layer] {len(layer_map)} Zuordnungen: "
|
||||||
@@ -319,7 +354,18 @@ def process_all(data_dir, cfg_path, results_dir, single_nr=None, dry_run=False):
|
|||||||
out_dir = os.path.join(results_dir, "omniflo")
|
out_dir = os.path.join(results_dir, "omniflo")
|
||||||
os.makedirs(out_dir, exist_ok=True)
|
os.makedirs(out_dir, exist_ok=True)
|
||||||
|
|
||||||
omniflo_dir = os.environ.get("DXFM_OMNIFLO") or os.path.join(data_dir, "omniflo")
|
dxfm_dim = os.environ.get("DXFM_DIM")
|
||||||
|
if dxfm_dim:
|
||||||
|
omniflo_dir = os.path.join(data_dir, "omniflo", dxfm_dim)
|
||||||
|
else:
|
||||||
|
omniflo_dir = os.environ.get("DXFM_OMNIFLO") or os.path.join(data_dir, "omniflo")
|
||||||
|
if not os.path.isdir(omniflo_dir) or not any(
|
||||||
|
f.lower().endswith(".dxf") for f in os.listdir(omniflo_dir)
|
||||||
|
):
|
||||||
|
print(f"[set_attributs] FEHLER: Im Quellverzeichnis '{omniflo_dir}' "
|
||||||
|
f"wurden keine DXF-Dateien gefunden. eventuell DXFM_DIM=2D in Umgebung setzen")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
processed = 0
|
processed = 0
|
||||||
skipped = 0
|
skipped = 0
|
||||||
errors = 0
|
errors = 0
|
||||||
@@ -348,7 +394,7 @@ def process_all(data_dir, cfg_path, results_dir, single_nr=None, dry_run=False):
|
|||||||
output_path = os.path.join(out_dir, dxf_name)
|
output_path = os.path.join(out_dir, dxf_name)
|
||||||
|
|
||||||
if dry_run:
|
if dry_run:
|
||||||
values = {tag: resolve_value(src, entry, sivasnr)
|
values = {tag: resolve_value(src, entry, sivasnr, container_map)
|
||||||
for tag, src in attr_defs}
|
for tag, src in attr_defs}
|
||||||
if layer_value:
|
if layer_value:
|
||||||
values["LAYER"] = layer_value
|
values["LAYER"] = layer_value
|
||||||
@@ -359,7 +405,8 @@ def process_all(data_dir, cfg_path, results_dir, single_nr=None, dry_run=False):
|
|||||||
try:
|
try:
|
||||||
count = add_attdefs_to_dxf(dxf_path, output_path, attr_defs,
|
count = add_attdefs_to_dxf(dxf_path, output_path, attr_defs,
|
||||||
entry, sivasnr,
|
entry, sivasnr,
|
||||||
layer_value=layer_value)
|
layer_value=layer_value,
|
||||||
|
container_map=container_map)
|
||||||
processed += 1
|
processed += 1
|
||||||
print(f" OK: {sivasnr} ({typ}) -> {count} Attribute -> {output_path}")
|
print(f" OK: {sivasnr} ({typ}) -> {count} Attribute -> {output_path}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -379,9 +426,13 @@ def main():
|
|||||||
help="Nur diese SivasNr verarbeiten")
|
help="Nur diese SivasNr verarbeiten")
|
||||||
parser.add_argument("--dry-run", "-d", action="store_true",
|
parser.add_argument("--dry-run", "-d", action="store_true",
|
||||||
help="Nur anzeigen, nicht schreiben")
|
help="Nur anzeigen, nicht schreiben")
|
||||||
|
parser.add_argument("--type", "-t", choices=["2D", "3D"], default="2D",
|
||||||
|
help="Ueberschreibt DXFM_DIM und damit das "
|
||||||
|
"Quellverzeichnis data/omniflo/<type> (Default: 2D)")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
# Umgebungsvariablen
|
# Umgebungsvariablen
|
||||||
|
os.environ["DXFM_DIM"] = args.type
|
||||||
data_dir = os.environ.get("DXFM_DATA")
|
data_dir = os.environ.get("DXFM_DATA")
|
||||||
cfg_dir = os.environ.get("DXFM_CFG")
|
cfg_dir = os.environ.get("DXFM_CFG")
|
||||||
results_dir = os.environ.get("DXFM_RESULTS")
|
results_dir = os.environ.get("DXFM_RESULTS")
|
||||||
|
|||||||
Reference in New Issue
Block a user