export_csv: sepliste-Koordinaten (x/y) entfernen, nur noch typ/lfdnr/id
Validiert (Nutzer-Befund): die sepliste-XDATA-Koordinaten sind der rohe Gruppencode-10-Punkt des jeweiligen Bau-Primitivs und teils gespiegelt/um mehrere 100mm verschoben (z.B. Separator 0037: x=-5070.1 statt 5070.1, ausserhalb der VF_1-Boundingbox). Die eigene Export-Zeile jedes Bauteils (x/y aus der echten Proxy-Kopie) ist dagegen verlaesslich und liegt korrekt in der Boundingbox. sepliste dient nur noch der ID-Zuordnung/Reihenfolge, nicht mehr als Koordinatenquelle. Der Python-Faellback in map_sepliste_kette_items (nur fuer SEP-Eintraege ohne aufloesbares "id"-Feld, Altbestand) matchte bisher per naechstem sepliste-Punkt - jetzt erster unverbrauchter Kandidat je Zuordnung, da keine Koordinate mehr vorliegt. lib/dump_vf_kette_inhalt.py zeigt Position/Typ jetzt ueber die ID-Verknuepfung zur eigenen Bauteil-Zeile statt ueber die entfernten sepliste-Felder. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
42309c77d2
commit
4f1a0e0b5b
+15
-2
@@ -786,6 +786,21 @@
|
||||
;; Eintrag (Key = Handle dieses Wrappers). Fehlt sie (Kopie nicht
|
||||
;; erzeugbar, Block ohne ID-ATTDEF, Altbestand), bleibt das Feld weg -
|
||||
;; der Python-Teil faellt dann auf seine Koordinaten-Zuordnung zurueck.
|
||||
;;
|
||||
;; KEIN x/y mehr im JSON: die sepliste-XDATA-Koordinaten sind der
|
||||
;; rohe Gruppencode-10-Punkt des jeweiligen Einfuege-Primitivs
|
||||
;; (siehe gf-insert-hz-with-ks-Kommentar, ssg_ks_insert.lsp) und
|
||||
;; koennen gespiegelt/verschoben sein (Nutzer-Befund 2026-09-25:
|
||||
;; Sepliste-x/y von SEP-Eintraegen wich um bis zu mehrere 100mm bzw.
|
||||
;; vorzeichenverkehrt von der tatsaechlichen, aus der echten
|
||||
;; Proxy-Kopie berechneten Position ab - siehe die "x"/"y"-Felder
|
||||
;; der eigenen Bauteil-Zeile, die verlaesslich sind). x/y wurden nie
|
||||
;; fuer die ID-Zuordnung gebraucht (die laeuft VORHER, LISP-seitig,
|
||||
;; ueber csv:sepliste-paare/csv:sepliste-ids-setzen mit einer
|
||||
;; eigenen, unabhaengigen XDATA-Lesung) - nur der Python-Naehe-
|
||||
;; Fallback (map_sepliste_kette_items in export_csv.py, fuer
|
||||
;; SEP-Eintraege ohne "id", Altbestand ohne ID-ATTDEF) konsumierte
|
||||
;; sie und degradiert jetzt auf 0.0/0.0 (siehe dort).
|
||||
(setq sepliste-ids (cdr (assoc handle *csv-sepliste-id-by-handle*)))
|
||||
(setq sepliste-teile "" sepliste-first t)
|
||||
(foreach e sepliste
|
||||
@@ -794,8 +809,6 @@
|
||||
(strcat sepliste-teile (if sepliste-first "" ",")
|
||||
"{\"typ\":\"" (nth 0 e) "\""
|
||||
",\"lfdnr\":" (itoa (nth 1 e))
|
||||
",\"x\":" (rtos (nth 2 e) 2 2)
|
||||
",\"y\":" (rtos (nth 3 e) 2 2)
|
||||
(if sep-id (strcat ",\"id\":\"" (csv:json-escape sep-id) "\"") "")
|
||||
"}"))
|
||||
(setq sepliste-first nil)
|
||||
|
||||
@@ -105,15 +105,37 @@ def wrapper_aus_export_raw(export_raw):
|
||||
return wrapper
|
||||
|
||||
|
||||
def sepliste_zusammenfassung(wrapper_block):
|
||||
def bauteile_nach_id(export_raw):
|
||||
"""Lookup ID-Attribut -> Bauteil-Record. Die sepliste selbst traegt seit
|
||||
2026-09-25 kein x/y mehr (die dortigen Koordinaten waren der rohe,
|
||||
teils gespiegelte/verschobene Gruppencode-10-Punkt des Bau-Primitivs,
|
||||
siehe export.lsp-Kommentar bei sepliste-teile) - die verlaessliche
|
||||
Position steht an der eigenen Export-Zeile des Bauteils (x/y/z dort
|
||||
kommen aus der echten Proxy-Kopie)."""
|
||||
out = {}
|
||||
for b in export_raw:
|
||||
bid = b.get("attribs", {}).get("ID")
|
||||
if bid:
|
||||
out[bid] = b
|
||||
return out
|
||||
|
||||
|
||||
def sepliste_zusammenfassung(wrapper_block, bauteile):
|
||||
sepliste = wrapper_block.get("sepliste", [])
|
||||
if not sepliste:
|
||||
return " (keine sepliste-XDATA am Wrapper - Altbestand oder Fehler)"
|
||||
zeilen = []
|
||||
for s in sepliste:
|
||||
teil = bauteile.get(s.get("id"))
|
||||
if teil:
|
||||
pos = f"x={teil['x']:10.2f} y={teil['y']:10.2f}"
|
||||
typ = teil.get("strecke_typ")
|
||||
if typ:
|
||||
pos += f" strecke_typ={typ}"
|
||||
else:
|
||||
pos = "(kein Bauteil mit dieser ID gefunden)"
|
||||
zeilen.append(
|
||||
f" lfdnr={s['lfdnr']:2d} typ={s['typ']:3s} id={s.get('id','?'):6s} "
|
||||
f"x={s['x']:10.2f} y={s['y']:10.2f}"
|
||||
f" lfdnr={s['lfdnr']:2d} typ={s['typ']:3s} id={s.get('id','?'):6s} {pos}"
|
||||
)
|
||||
return "\n".join(zeilen)
|
||||
|
||||
@@ -128,9 +150,11 @@ def main():
|
||||
|
||||
export_raw = None
|
||||
wrapper_liste = []
|
||||
bauteile = {}
|
||||
if len(sys.argv) == 3:
|
||||
export_raw = lade_json(sys.argv[2])
|
||||
wrapper_liste = wrapper_aus_export_raw(export_raw)
|
||||
bauteile = bauteile_nach_id(export_raw)
|
||||
if len(wrapper_liste) != len(ketten):
|
||||
print(
|
||||
f"[WARNUNG] {len(ketten)} Ketten in der Spec, aber "
|
||||
@@ -150,7 +174,7 @@ def main():
|
||||
print(kette_zusammenfassung(kette))
|
||||
if i < len(wrapper_liste):
|
||||
print("--- sepliste (tatsaechlich exportierte Separator-Reihenfolge) ---")
|
||||
print(sepliste_zusammenfassung(wrapper_liste[i]))
|
||||
print(sepliste_zusammenfassung(wrapper_liste[i], bauteile))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
+19
-12
@@ -21,7 +21,6 @@ von export_raw.json bis zur fertigen CSV-Zeile) siehe doc/csv-export.md.
|
||||
"""
|
||||
|
||||
import json
|
||||
import math
|
||||
import sys
|
||||
import os
|
||||
|
||||
@@ -567,19 +566,29 @@ def map_sepliste_kette_items(items, sep_kette, dbg=None):
|
||||
|
||||
Fallback (kein "id"-Feld - Altbestand-Export ohne Marker/Kopie-ID, oder
|
||||
deren Zuweisung ist in Lisp fehlgeschlagen): NUR fuer SEP-Eintraege
|
||||
weiterhin per naechstem INSERT-Punkt gegen die per Zuordnung
|
||||
vorgefilterten Separator-Items. AS/ES ohne "id" bleiben unaufgeloest -
|
||||
fuer sie existiert seit dem Wegfall der Kreisel<->Strecke-Kollisions-
|
||||
erzeugung (frueher compute_strecke_kreisel_schleus/
|
||||
build_strecke_schleus_items) ohnehin kein Item mehr, das sie vertreten
|
||||
koennte.
|
||||
weiterhin gegen die per Zuordnung vorgefilterten Separator-Items, je
|
||||
Strecke der erste noch nicht verbrauchte Kandidat (Baureihenfolge in
|
||||
items). AS/ES ohne "id" bleiben unaufgeloest - fuer sie existiert seit
|
||||
dem Wegfall der Kreisel<->Strecke-Kollisionserzeugung (frueher
|
||||
compute_strecke_kreisel_schleus/build_strecke_schleus_items) ohnehin
|
||||
kein Item mehr, das sie vertreten koennte.
|
||||
|
||||
Der Fallback matchte frueher per naechstem sepliste-Koordinatenpunkt
|
||||
(x/y) - die sepliste-XDATA traegt seit 2026-09-25 kein x/y mehr, weil
|
||||
diese Koordinaten der rohe, teils gespiegelte/verschobene Gruppencode-10-
|
||||
Punkt des jeweiligen Bau-Primitivs waren (siehe export.lsp-Kommentar bei
|
||||
sepliste-teile) und keine verlaessliche Zuordnungsgrundlage. Der
|
||||
ID-Abgleich oben deckt praktisch jeden aktuellen Export ab; dieser
|
||||
Fallback ist reine Altbestands-Kompatibilitaet.
|
||||
|
||||
Rueckgabe: sep_kette_by_key (neues dict).
|
||||
"""
|
||||
sep_kette_by_key = {}
|
||||
by_teileid = {it.get("teileid", ""): it for it in items if it.get("teileid", "")}
|
||||
|
||||
# Kandidatenpool nur noch fuer den Koordinaten-Fallback (SEP ohne "id").
|
||||
# Kandidatenpool nur noch fuer den Fallback (SEP ohne "id"); verbrauchte
|
||||
# Kandidaten werden entfernt, damit zwei Sepliste-Eintraege nicht auf
|
||||
# dasselbe Item fallen.
|
||||
sep_items_by_zuordnung = {}
|
||||
for it in items:
|
||||
if it.get("teileart", "") != "ILS 2.0 Separator":
|
||||
@@ -620,13 +629,11 @@ def map_sepliste_kette_items(items, sep_kette, dbg=None):
|
||||
dbg(f" {key}: kein Separator-Item mit Zuordnung "
|
||||
f"{eintrag['strecke_id']!r} gefunden - uebersprungen")
|
||||
continue
|
||||
sx, sy = eintrag.get("x", 0.0), eintrag.get("y", 0.0)
|
||||
best = min(kandidaten,
|
||||
key=lambda it: math.hypot(it.get("_x", 0.0) - sx, it.get("_y", 0.0) - sy))
|
||||
best = kandidaten.pop(0)
|
||||
sep_kette_by_key[key] = best
|
||||
per_fallback += 1
|
||||
if dbg:
|
||||
dbg(f" {key} (x={sx:.0f},y={sy:.0f}) -> Naehe-Fallback auf "
|
||||
dbg(f" {key} -> Fallback (erster unverbrauchter Kandidat) auf "
|
||||
f"Separator-Item TeileId {best.get('teileid', '')!r}")
|
||||
|
||||
if dbg:
|
||||
|
||||
@@ -1153,7 +1153,8 @@ def _asel_collision_boxes(item, half_tol, box_dims):
|
||||
# "sepliste" (item["sepliste"], von csv:block-to-json aus SSG_VF_SEP/
|
||||
# SSG_GF_SEP-XDATA gelesen) ist die beim Bau in Baureihenfolge gesammelte
|
||||
# Liste der Separator-/AS-/ES-Sub-Bloecke EINER VF_n/GF_n-Kette:
|
||||
# [{"typ": "AS"|"SEP"|"ES", "lfdnr": int, "x": float, "y": float}, ...].
|
||||
# [{"typ": "AS"|"SEP"|"ES", "lfdnr": int, "id": str}, ...] (kein x/y - siehe
|
||||
# compute_sep_kette-Docstring).
|
||||
# Ersetzt das bisherige Raten der Ketten-internen Reihenfolge (die Linie
|
||||
# selbst wird nicht exportiert) durch die tatsaechliche Bau-Reihenfolge.
|
||||
|
||||
@@ -1168,7 +1169,7 @@ def compute_sep_kette(items, dbg=None):
|
||||
naechste Eintrag in der Sepliste (die bereits in Baureihenfolge vorliegt)
|
||||
- kein Rateverfahren noetig.
|
||||
|
||||
Rueckgabe: dict {key: {"typ", "x", "y", "id", "strecke_id", "vorgaenger",
|
||||
Rueckgabe: dict {key: {"typ", "id", "strecke_id", "vorgaenger",
|
||||
"nachfolger"}} - vorgaenger/nachfolger sind wieder solche keys, oder None
|
||||
am jeweiligen Kettenende (Verkettung mit dem Kreisel-Umlauf uebernimmt
|
||||
compute_kreisel_umlauf). "id" ist die TeileId des Bauteils, das diesen
|
||||
@@ -1176,6 +1177,12 @@ def compute_sep_kette(items, dbg=None):
|
||||
ZZ_ASES_MARKER, SEP ueber die beim Export ausgepackte temporaere
|
||||
Separator_SP-Kopie - siehe csv:sepliste-ids-setzen, Lisp/export.lsp) -
|
||||
leerer String, wenn (noch) keine ID zugewiesen wurde (Altbestand).
|
||||
|
||||
Kein x/y mehr: die sepliste-XDATA traegt seit 2026-09-25 keine
|
||||
Koordinaten mehr (der rohe Gruppencode-10-Punkt des jeweiligen
|
||||
Bau-Primitivs war teils gespiegelt/verschoben und keine verlaessliche
|
||||
Positionsquelle - siehe export.lsp-Kommentar bei sepliste-teile). Die
|
||||
verlaessliche Position steht an der eigenen Export-Zeile des Bauteils.
|
||||
"""
|
||||
result = {}
|
||||
for item in items:
|
||||
@@ -1190,8 +1197,6 @@ def compute_sep_kette(items, dbg=None):
|
||||
key = keys[i]
|
||||
result[key] = {
|
||||
"typ": entry.get("typ", ""),
|
||||
"x": entry.get("x", 0.0),
|
||||
"y": entry.get("y", 0.0),
|
||||
"id": str(entry.get("id", "")).strip(),
|
||||
"strecke_id": sid,
|
||||
"vorgaenger": keys[i - 1] if i > 0 else None,
|
||||
|
||||
Reference in New Issue
Block a user