sepliste: Bauteil-IDs eintragen, AS/ES ueber dauerhaften Marker sichtbar machen
Stufe 1 (LISP-Export-Pfad): export_raw.json enthaelt jetzt fuer jeden sepliste-Eintrag (AS/SEP/ES) einer VF_n/GF_n-Kette die ID des realen Bauteils, das ihn vertritt. - csv:sep-proxies-erzeugen (Separatoren) und die neuen AS/ES-Marker teilen sich csv:nested-welt-records/csv:block-einfuegen-welt zur Platzierung. - csv:sepliste-paare ordnet sepliste-Eintraege ihrem Bauteil exklusiv nach Abstand zu (kuerzester zuerst, dann verbraucht) statt "jeder Eintrag nimmt sich das naechste" - ein einzelner fehlerhafter Koordinatenwert (bekannter Bug: gespiegeltes x bei lfdnr=2) verschiebt dadurch keine andere Zuordnung mehr. - Neu: ZZ_ASES_MARKER - ein kleines Rechteck an jedem AS/ES-Kettenende, das nach dem Export STEHEN BLEIBT (anders als die temporaeren Separator-Kopien). Macht das sonst unsichtbare, in der Wrapper- Blockdefinition verpackte Kettenende in BricsCAD sichtbar/anklickbar und traegt seine ID unsichtbar am Attribut ID - dadurch behaelt ein AS/ES seine TeileId ueber Exportlaeufe hinweg. Wird bei jedem Export neu aufgebaut (Lage folgt der Kette), Wiederfund ueber ZUORDNUNG+TYP+ LFDNR, verwaiste Marker werden entfernt. In BricsCAD verifiziert (5 HundM05-Ketten, zwei Exportlaeufe: gleiche Marker-IDs, korrekte sepliste-"id"-Felder). Dabei einen realen Bug gefunden und behoben: die Blockdefinition des Markers uebernahm ueber einen ungefilterten entnext-Walk versehentlich auch die Attribute des zuletzt eingefuegten Blocks (VF_5 verlor dadurch alle Attribute inkl. ID) - jetzt auf LWPOLYLINE/ATTDEF gefiltert. 9 neue zeichnungsfreie Unit-Tests (csv:sepliste-paare/*, csv:asmark- finden/*, csv:proxy-typ/*), 4 neue de/en-Textschluessel (Paritaet geprueft). bin\run_tests.bat --lisp: 257/257 bestanden. Noch nicht enthalten (Stufe 2, Python): map_separator_kette_items nutzt das neue "id"-Feld noch nicht, build_strecke_schleus_items synthetisiert AS/ES-Zeilen weiterhin selbst statt die exportierten zu lesen. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
9671fe4e04
commit
618ff3d86c
+103
-9
@@ -12,9 +12,12 @@ BricsCAD (LISP) Python
|
||||
───────────────── ──────
|
||||
c:EXPORTCSV
|
||||
-> csv:run-export
|
||||
-> Proxies fuer verpackte
|
||||
-> Kopien fuer verpackte
|
||||
Separatoren einfuegen
|
||||
-> AS/ES-Marker aufbauen
|
||||
-> IDs vergeben (ssg-id-check-all)
|
||||
-> IDs in die sepliste
|
||||
eintragen
|
||||
-> Separator-/Scanner-Zuordnung
|
||||
(count_sep_scan.lsp)
|
||||
-> REGENALL
|
||||
@@ -48,15 +51,32 @@ Bounding-Boxen braucht).
|
||||
durchlaeuft danach ID-Vergabe und Export ganz normal ueber den freien-
|
||||
Separator-Pfad (Blockname-Muster `Separator_SP*` trifft zu) und bekommt
|
||||
dadurch eine echte `vla-getboundingbox`-Box, die das verpackte Original nie
|
||||
haben koennte. Rueckgabe: Liste `(proxy-ename . wrapper-ename)`.
|
||||
haben koennte. Rueckgabe: Liste von Records
|
||||
`(proxy-ename wrapper-ename typ (x y z))`.
|
||||
1b. **`csv:asmark-aktualisieren`** — die AS-/ES-Enden derselben Kette
|
||||
(`AS_Element*`/`ES_Element*`, Muster `pattern_schleuselement`) bekommen
|
||||
KEINE temporaere Kopie, sondern einen DAUERHAFTEN Marker — siehe eigener
|
||||
Abschnitt "Der AS/ES-Marker" unten. Beide Wege teilen sich die
|
||||
Platzierungsrechnung (`csv:nested-welt-records` liefert die Weltlage jedes
|
||||
verpackten Fundes, `csv:block-einfuegen-welt` setzt ein Objekt dorthin).
|
||||
2. **`ssg-id-check-all`** — vergibt fehlende IDs (inkl. der frisch erzeugten
|
||||
Proxies) und korrigiert Duplikate. Muss NACH den Proxies laufen, sonst
|
||||
wuerden diese Kopien numerisch nie erfasst.
|
||||
wuerden diese Kopien numerisch nie erfasst. `ssg-id-collect-blocks`
|
||||
(`ssg_id.lsp`) erfasst dafuer auch `AS_Element*`/`ES_Element*`.
|
||||
3. **`csv:sep-proxies-zuordnung-setzen`** — jetzt steht die ID jedes Wrappers
|
||||
fest: die Proxy-Kopie bekommt `ZUORDNUNG = Wrapper-ID` fest zugewiesen
|
||||
(nicht geraten) und wird zusaetzlich in `*cs-sep-fix-by-handle*` vermerkt,
|
||||
damit `count_sep_scan.lsp` diesen Wert spaeter nicht per Geometrie
|
||||
ueberschreibt.
|
||||
ueberschreibt. Nur fuer die Separator-Kopien — AS/ES sind keine Sensoren.
|
||||
3b. **`csv:asmark-ids-setzen` + `csv:sepliste-ids-setzen`** — ebenfalls erst
|
||||
jetzt moeglich: jedes Bauteil wird seinem `sepliste`-Eintrag zugeordnet und
|
||||
seine ID unter `*csv-sepliste-id-by-handle*` (Key = Wrapper-Handle)
|
||||
abgelegt; `csv:block-to-json` schreibt sie als Feld `id` in den Eintrag.
|
||||
AS/ES laufen ueber die Marker (die ihre ID schon kennen, die Zuordnung
|
||||
steht im Marker-Attribut `LFDNR`), SEP ueber die temporaeren Kopien und
|
||||
`csv:sepliste-paare` — siehe eigener Abschnitt unten. `csv:asmark-ids-setzen`
|
||||
traegt zusaetzlich die `ZUORDNUNG` (Wrapper-ID) am Marker nach; ohne sie
|
||||
faende der naechste Export den Marker nicht wieder.
|
||||
4. **`omni:update-all-attribs`** — Hoehe/Drehung aller Omniflo-Elemente vor
|
||||
dem Export aktualisieren.
|
||||
5. **`count_sep_scan.lsp::cs-zuordnung-lauf`** (nur bei Bedarf, siehe
|
||||
@@ -88,7 +108,7 @@ Pro INSERT wird ein JSON-Objekt geschrieben:
|
||||
| `bbox` | `csv:get-bbox` (`vla-getboundingbox`) | NUR wenn `include-bbox=T` und der Aufruf gelingt; fehlt sonst komplett im JSON |
|
||||
| `warnung` | `*cs-scanner-warnung-by-handle*` | strittige Scanner-Zuordnung aus `cs-zuordnung-lauf` |
|
||||
| `zuordnung_fix` | `*cs-sep-fix-by-handle*` | nur bei Proxy-Kopien: die feststehende Wrapper-ID |
|
||||
| `sepliste` | `ssg-sepliste-xdata-lesen` | nur bei VF_n/GF_n, siehe eigener Abschnitt |
|
||||
| `sepliste` | `ssg-sepliste-xdata-lesen` + `*csv-sepliste-id-by-handle*` | nur bei VF_n/GF_n, siehe eigener Abschnitt |
|
||||
|
||||
**K1-K4 je Blocktyp:** normale ILS-Bloecke fuehren echte K1-K4-Sub-Bloecke.
|
||||
Omniflo-Geraden (`AP110*`) haben keine echten K-Bloecke — K1/K2 werden aus
|
||||
@@ -132,6 +152,80 @@ Separatoren als Eintraege mit Vorgaenger-/Nachfolger-Wissen. Python fuehrt
|
||||
beides zusammen (siehe `map_separator_kette_items` unten) statt sie doppelt
|
||||
zu zaehlen.
|
||||
|
||||
### Das Feld `id` je sepliste-Eintrag
|
||||
|
||||
Seit `csv:sepliste-ids-setzen` traegt JEDER Eintrag zusaetzlich die `id` des
|
||||
realen Bauteils, das ihn in der Zeichnung vertritt:
|
||||
|
||||
```json
|
||||
{"typ": "AS", "lfdnr": 1, "x": 5070.1, "y": 1199.2, "id": "0031"}
|
||||
```
|
||||
|
||||
Das ist dieselbe ID, die die zugehoerige temporaere Kopie in ihrer eigenen
|
||||
JSON-Zeile traegt — die Verbindung "Kettenglied <-> reales Teil" steht damit
|
||||
schon im Export und muss in Python nicht mehr ueber Koordinaten-Naehe geraten
|
||||
werden (`map_separator_kette_items`, siehe unten; solange Python das Feld noch
|
||||
nicht liest, aendert sich dort nichts). Das Feld fehlt, wenn keine Kopie
|
||||
erzeugt werden konnte oder deren ID-Attribut leer blieb — Altbestand und
|
||||
Fehlerfaelle verhalten sich damit wie bisher.
|
||||
|
||||
### Der AS/ES-Marker (`ZZ_ASES_MARKER`)
|
||||
|
||||
Die beiden Kettenenden stecken als `AS_Element_*`/`ES_Element_*` verpackt in
|
||||
der Wrapper-Blockdefinition: in der Zeichnung sind sie weder anklickbar noch
|
||||
einzeln erkennbar, und `(ssget "X" ...)` findet sie nicht. `csv:asmark-*`
|
||||
(`Lisp/export.lsp`) setzt darum an jedes Ende ein kleines Rechteck, das nach
|
||||
dem Export in der Zeichnung STEHEN BLEIBT:
|
||||
|
||||
- **Sichtbarmachung** — Kantenlaenge aus `cfg/export.cfg` `[Marker]`
|
||||
`ases_groesse_mm` (Default 200 mm), mittig auf dem Einfuegepunkt des
|
||||
Schleuselements, in dessen Drehung (auch bei geneigter Kette). Layer aus
|
||||
`cfg/layer.cfg` `[allgemein]` `ases_marker` — abschaltbar wie jede andere
|
||||
Hilfsgeometrie. Die Blockdefinition wird bei Bedarf zur Laufzeit erzeugt
|
||||
(`csv:asmark-blockdef-sicherstellen`, Rechteck + ATTDEFs + `_.-BLOCK`), es
|
||||
gibt keine DWG dafuer.
|
||||
- **ID-Traeger** — die Attribute (alle unsichtbar) sind
|
||||
`ID`, `ZUORDNUNG` (Wrapper-ID), `TYP` (`AS`/`ES`), `LFDNR` (sepliste-Eintrag),
|
||||
`ELEMENT` (Blockname des echten Elements, haelt die Variante 30/90,
|
||||
links/rechts, 2D/3D fest) und `ARTINR`. `ssg-id-check-all` fuellt die `ID`,
|
||||
und weil der Marker liegen bleibt, **behaelt ein AS/ES seine TeileId ueber
|
||||
Exportlaeufe hinweg** — im Unterschied zu den Separator-Kopien, die jeder
|
||||
Lauf neu erzeugt und neu nummeriert.
|
||||
|
||||
Der Marker ist abgeleitete Geometrie: jeder Export baut ihn neu auf (die Lage
|
||||
folgt damit automatisch einer umgebauten Kette) und uebernimmt vom bisherigen
|
||||
Marker nur dessen `ID`. Wiedergefunden wird er ueber (`ZUORDNUNG`, `TYP`,
|
||||
`LFDNR`) — bewusst nicht ueber die Position, damit eine verschobene Kette ihre
|
||||
TeileIds behaelt. Was am Ende keinem Kettenende mehr entspricht (Kette
|
||||
geloescht, Eintrag entfallen), wird geloescht; Karteileichen entstehen nicht.
|
||||
Ein frisch gebauter Wrapper hat beim Setzen der Marker noch keine ID — seine
|
||||
Marker bekommen die `ZUORDNUNG` nach der ID-Vergabe nachgetragen und sind ab
|
||||
dem naechsten Export wiederfindbar.
|
||||
|
||||
Im Export ist der Marker eine eigene Zeile (`pattern_ases_marker` in
|
||||
`cfg/export.cfg`) und liefert die `id` des AS-/ES-Eintrags in der `sepliste`.
|
||||
|
||||
**Zuordnung Eintrag -> Kopie (`csv:sepliste-paare`).** Verglichen wird nur
|
||||
innerhalb desselben Typmarkers (`AS`/`ES`/`SEP`) und EXKLUSIV: alle Paare
|
||||
eines Typs werden nach Abstand sortiert, das kuerzeste zuerst genommen, danach
|
||||
sind Eintrag UND Kopie verbraucht. Zwei Gruende gegen das naheliegende "je
|
||||
Eintrag die naechste Kopie":
|
||||
|
||||
- waehlen zwei Eintraege dieselbe Kopie, bleibt eine Kopie ohne Eintrag und
|
||||
ein Eintrag ohne ID (genau dieses Muster verursacht in Python die
|
||||
Separatoren ohne `Nachbarn`/`TrackIds`);
|
||||
- EIN fehlerhafter Koordinatenwert in der sepliste (bekannter Fall: gespiegeltes
|
||||
`x` bei `lfdnr=2`) verschiebt so keine anderen Zuordnungen mehr — alle
|
||||
uebrigen Eintraege finden ihre Kopie ueber den kurzen Abstand zuerst, der
|
||||
fehlerhafte bekommt den Rest zugeteilt. Liegt dieser Rest weiter als
|
||||
`csv:sepliste-abstand-warnung-mm` (500 mm) entfernt, meldet der Export das
|
||||
(`exp-sepliste-abstand`), ohne die Zuordnung zu verwerfen.
|
||||
|
||||
Die Sortierung ist eine strikte Totalordnung (Abstand, dann `lfdnr`, dann
|
||||
Index) — `vl-sort` wirft Elemente weg, die unter der Vergleichsfunktion gleich
|
||||
sind, zwei Paare mit identischem Abstand wuerden sonst zu einem verschmelzen.
|
||||
Getestet in `tests/test_unit.lsp` (`csv:sepliste-paare/*`, zeichnungsfrei).
|
||||
|
||||
## Phase 2 (Python): `lib/export_csv.py::process_blocks`
|
||||
|
||||
Aufruf: `python export_csv.py <export_raw.json> <data_dir> <output.csv>`.
|
||||
@@ -215,10 +309,10 @@ relevanten Felder):
|
||||
"k2": "AAAAQwAATkAAAAAA...",
|
||||
"bbox": {"min": [10800.0, 4850.0, 0.0], "max": [13000.0, 5150.0, 300.0]},
|
||||
"sepliste": [
|
||||
["AS", 1, 10800.0, 5000.0],
|
||||
["SEP", 2, 11600.0, 5000.0],
|
||||
["SEP", 3, 12300.0, 5000.0],
|
||||
["ES", 4, 13000.0, 5000.0]
|
||||
{"typ": "AS", "lfdnr": 1, "x": 10800.0, "y": 5000.0, "id": "0025"},
|
||||
{"typ": "SEP", "lfdnr": 2, "x": 11600.0, "y": 5000.0, "id": "0022"},
|
||||
{"typ": "SEP", "lfdnr": 3, "x": 12300.0, "y": 5000.0, "id": "0023"},
|
||||
{"typ": "ES", "lfdnr": 4, "x": 13000.0, "y": 5000.0, "id": "0026"}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user