Sensor-Zuordnung: Separator/Scanner je Kreisel/Strecke zaehlen vor Export

count_sep_scan.lsp neu als wiederverwendbare Engine (cs-zuordnung-lauf),
die automatisch vor jedem CSV-/Sivas-Export laeuft (export.lsp,
csv:run-export). Zaehlt Separator_SP/Scanner je Carrier (Kreisel/Eckrad,
VF_*, GF_*) ueber die gemeinsamen cfg/export.cfg-Muster und schreibt
ANZAHL_SEPARATOR/ANZAHL_SCANNER, so dass die Summe zur Szene passt.

Scanner ausserhalb jeder Carrier-Boundingbox ohne ZUORDNUNG werden per
Abstand dem naechsten Kreisel/Strecke zugeschlagen (ZUORDNUNG = Carrier-ID).
Ist der Abstand zum zweitnaechsten Kandidaten fast gleich (<= strittig_diff_mm,
neu in cfg/export.cfg [Sensorzuordnung]), gilt die Zuordnung als strittig:
Konsolenausgabe der ergaenzten Scanner + JSON-"warnung"-Feld mit den IDs der
strittigen Kandidaten (csv:block-to-json), das export_csv.py in der Spalte
"Warnungen" ausgibt.

Menue: ZAEHLE_SEP_SCAN-Vorlauf vor EXPORTSIVAS entfernt (laeuft jetzt
automatisch im Export); interaktiver Befehl bleibt erhalten.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-21 15:37:50 +02:00
parent 966bfa866d
commit edfba75801
7 changed files with 429 additions and 190 deletions
+316 -163
View File
@@ -1,63 +1,91 @@
;;; ============================================================ ;;; ============================================================
;;; count_sep_scan.lsp - Eigenstaendiges Zaehl-Werkzeug ;;; count_sep_scan.lsp - Separator-/Scanner-Zuordnung
;;; ------------------------------------------------------------ ;;; ------------------------------------------------------------
;;; Zaehlt die manuell platzierten Bloecke "Scanner" und ;;; Zaehlt die manuell platzierten Bloecke "Scanner" und
;;; "Separator_SP" je ILS-Block (Kreisel / VarioFoerderer / ;;; "Separator_SP" (Muster siehe cfg/export.cfg [blockpattern]
;;; Gefaellestrecke) und schreibt die Anzahlen in die Attribute ;;; pattern_scanner/pattern_separator) je Carrier (Kreisel/Eckrad,
;;; des jeweiligen ILS-Blocks. Anschliessend QSAVE. ;;; VarioFoerderer-Streckengruppe VF_*, Gefaellestrecke GF_* -
;;; Muster pattern_kreisel/pattern_variofoerderer/
;;; pattern_gefaellestrecke) und schreibt die Anzahlen in die
;;; Attribute ANZAHL_SCANNER/ANZAHL_SEPARATOR des jeweiligen
;;; Carrier-Blocks.
;;; ;;;
;;; Zuordnung eines Sensors zu einem ILS-Block (Z wird ignoriert): ;;; Zuordnung eines Sensors zu einem Carrier (Z wird ignoriert):
;;; - Scanner: der Einfuegepunkt (X/Y) muss in der Bounding-Box ;;; 0. Traegt der Sensor bereits ein ZUORDNUNG-Attribut, wird das
;;; des ILS-Blocks liegen. Die 3D-Geometrie des Scanners kann ;;; respektiert (nicht ueberschrieben) - er zaehlt mit, wenn die
;;; dort stehende ID zu einem bekannten Carrier passt.
;;; 1. Scanner: der Einfuegepunkt (X/Y) muss in der Bounding-Box
;;; des Carriers liegen. Die 3D-Geometrie des Scanners kann
;;; weit vom Einfuegepunkt entfernt sein, daher zaehlt hier der ;;; weit vom Einfuegepunkt entfernt sein, daher zaehlt hier der
;;; Einfuegepunkt (dort klickt der Benutzer auf den Block). ;;; Einfuegepunkt (dort klickt der Benutzer auf den Block).
;;; - Separator: der geometrische Mittelpunkt (Zentrum der eigenen ;;; 2. Separator: der geometrische Mittelpunkt (Zentrum der eigenen
;;; Bounding-Box, unabhaengig vom $INSBASE) muss in der ;;; Bounding-Box, unabhaengig vom $INSBASE) muss in der
;;; Bounding-Box des ILS-Blocks liegen. ;;; Bounding-Box des Carriers liegen.
;;; - Liegt der Punkt in mehreren Boxen (Ueberlappung), wird ;;; 3. Liegt der Punkt in mehreren Boxen (Ueberlappung), wird der
;;; der ILS-Block mit dem naechstgelegenen Box-Zentrum gewaehlt. ;;; Carrier mit dem naechstgelegenen Box-Zentrum gewaehlt.
;;; - Ein optionaler Toleranzrand (*senstol*) vergroessert die ;;; 4. Liegt der Punkt in KEINER Carrier-Box (Scanner koennen
;;; durchaus ausserhalb der Kreisel-BBox montiert sein), wird der
;;; raeumlich naechstgelegene Carrier ueber alle Kreisel/Strecken
;;; hinweg gewaehlt (cs-nearest-two). Ist der Abstand zum
;;; zweitnaechsten Carrier fast gleich gross (Differenz <=
;;; cs-strittig-diff-mm, siehe cfg/export.cfg [Sensorzuordnung]
;;; strittig_diff_mm), gilt die Zuordnung als "strittig": sie
;;; wird trotzdem geschrieben, aber zusaetzlich in
;;; *cs-scanner-ergaenzt* (Report-Liste) und
;;; *cs-scanner-warnung-by-handle* (Key = Entity-Handle, Wert =
;;; Warnungstext) vermerkt. csv:block-to-json (export.lsp) liest
;;; *cs-scanner-warnung-by-handle* aus und haengt den Text als
;;; "warnung"-Feld an den JSON-Block des betroffenen Scanners an
;;; - export_csv.py gibt ihn in der CSV-Spalte "Warnungen" aus.
;;; *cs-scanner-ergaenzt* sammelt ALLE per Abstand (nicht per
;;; BBox) zugeordneten Scanner, nicht nur die strittigen -
;;; cs-zuordnung-lauf gibt diese Liste auf der Konsole aus.
;;; 5. Ein optionaler Toleranzrand (cs-senstol, siehe
;;; cfg/export.cfg [Sensorzuordnung] senstol_mm) vergroessert die
;;; Box, damit Sensoren knapp am Rand noch erfasst werden. ;;; Box, damit Sensoren knapp am Rand noch erfasst werden.
;;; 6. Bei zugeordneten Sensoren wird die ID des Carriers (Attribut
;;; "ID") in das Sensor-Attribut ZUORDNUNG geschrieben.
;;; 7. Sensoren, zu denen ueberhaupt kein Carrier existiert (leere
;;; Zeichnung), werden mit einem Kreis auf dem Layer *mark-layer*
;;; markiert (zentriert auf den Sensor).
;;; ;;;
;;; Zusaetzlich: ;;; cs-zuordnung-lauf ist die wiederverwendbare Engine (siehe unten):
;;; - Bei zugeordneten Sensoren wird die Bezeichnung des ILS-Blocks ;;; sie wird sowohl vom interaktiven Befehl ZAEHLE_SEP_SCAN als auch
;;; (Attribut "Bezeichnung", Fallback Blockname) in das Sensor- ;;; automatisch vor jedem CSV-/Sivas-Export aufgerufen (Lisp/export.lsp,
;;; Attribut *zuordnung-tag* geschrieben. ;;; csv:run-export) - dort OHNE QSAVE und ohne die ausfuehrliche
;;; - Nicht zugeordnete Sensoren werden mit einem Kreis auf dem ;;; Detailzeile je Carrier (verbose=nil), damit die Konsolenausgabe
;;; Layer *mark-layer* markiert (zentriert auf den Sensor). ;;; beim normalen Export kompakt bleibt.
;;; - Der Befehl ist wiederholbar: alte Markierungskreise werden
;;; zu Beginn entfernt.
;;; ;;;
;;; Aufruf: ZAEHLE_SEP_SCAN ;;; Aufruf (interaktiv): ZAEHLE_SEP_SCAN
;;; Laden: per APPLOAD oder (load "count_sep_scan") ;;; Laden: per APPLOAD oder (ssg-ensure "count_sep_scan")
;;; ============================================================ ;;; ============================================================
(vl-load-com) (vl-load-com)
;;; ------------------------------------------------------------ ;;; ------------------------------------------------------------
;;; KONFIGURATION (bei Bedarf anpassen) ;;; KONFIGURATION
;;; ------------------------------------------------------------ ;;; ------------------------------------------------------------
;; Toleranzrand um die ILS-Block-Box in Zeichnungseinheiten (mm). ;; Toleranzrand um die Carrier-Box in Zeichnungseinheiten (mm), aus
;; 0.0 = exakte Box. Groesserer Wert = Sensoren knapp ausserhalb ;; cfg/export.cfg [Sensorzuordnung] senstol_mm (Default 0.0 = exakte
;; werden noch dem ILS-Block zugerechnet. ;; Box). Wird von cs-zuordnung-lauf bei jedem Lauf frisch gelesen und
;; hier nur mit einem Startwert vorbelegt, damit cs-in-box/cs-grid-add
;; auch ausserhalb eines Laufs referenzierbar bleiben.
(if (null *senstol*) (setq *senstol* 0.0)) (if (null *senstol*) (setq *senstol* 0.0))
;; Blockname-Muster (wcmatch, Grossschreibung) fuer die manuell ;; Attribut-Tag im Scanner-/Separator-Block, in das die ID des
;; platzierten Sensoren. ;; zugeordneten Carriers geschrieben wird.
(setq *scanner-pattern* "SCANNER,SCANNER_*") (setq *zuordnung-tag* "ZUORDNUNG")
(setq *separator-pattern* "SEPARATOR_SP,SEPARATOR_SP_*")
;; Blockname-Muster fuer die INTERN im ILS-Block (in der Kette) ;; Blockname-Muster fuer die INTERN im Carrier-Block (in der Kette)
;; gezeichneten Separatoren. Diese bilden die Basis fuer ;; gezeichneten Separatoren. Diese bilden einen Teil von
;; ANZAHL_SEPARATOR und werden bei jedem Lauf frisch gezaehlt. ;; ANZAHL_SEPARATOR und werden bei jedem Lauf frisch aus der
;; Blockdefinition gezaehlt (siehe cs-count-nested) - rein LISP-
;; intern, daher (anders als pattern_separator/pattern_scanner) nicht
;; in cfg/export.cfg.
(setq *intern-separator-pattern* "STAUSTRECKE_SEPARATOR_SP*") (setq *intern-separator-pattern* "STAUSTRECKE_SEPARATOR_SP*")
;; Attribut-Tag im Scanner-/Separator-Block, in das die Bezeichnung ;; Markierung von Sensoren ohne jeglichen Carrier: Kreis auf eigenem Layer.
;; des zugeordneten ILS-Blocks geschrieben wird (Gross/Klein egal).
(setq *zuordnung-tag* "zuordnung")
;; Markierung nicht zugeordneter Sensoren: Kreis auf eigenem Layer.
(setq *mark-layer* "S_SENSOR_UNZUGEORDNET") (setq *mark-layer* "S_SENSOR_UNZUGEORDNET")
(setq *mark-color* 2) ;; 2 = Gelb (setq *mark-color* 2) ;; 2 = Gelb
;; Kreisradius = Faktor * halbe XY-Diagonale der Sensor-Box, ;; Kreisradius = Faktor * halbe XY-Diagonale der Sensor-Box,
@@ -65,19 +93,32 @@
(if (null *mark-radius-factor*) (setq *mark-radius-factor* 1.5)) (if (null *mark-radius-factor*) (setq *mark-radius-factor* 1.5))
(if (null *mark-radius-min*) (setq *mark-radius-min* 500.0)) (if (null *mark-radius-min*) (setq *mark-radius-min* 500.0))
;; --- Toleranzrand (mm) aus cfg/export.cfg [Sensorzuordnung] senstol_mm ---
(defun cs-senstol ()
(atof (export:cfg "Sensorzuordnung" "senstol_mm" "0"))
)
;; --- "Strittig"-Schwelle (mm) aus cfg/export.cfg [Sensorzuordnung] ---
;; Differenz zwischen dem Abstand zum naechsten und zweitnaechsten
;; Carrier, unterhalb derer eine Distanz-Zuordnung als unsicher gilt.
(defun cs-strittig-diff-mm ()
(atof (export:cfg "Sensorzuordnung" "strittig_diff_mm" "500"))
)
;;; ------------------------------------------------------------ ;;; ------------------------------------------------------------
;;; ILS-Block-Erkennung und zugehoerige Attribut-Tags ;;; Carrier-/Sensor-Erkennung ueber die gemeinsamen Muster aus
;;; Alle ILS-Bloecke (Kreisel / VF / GF) verwenden einheitlich ;;; cfg/export.cfg [blockpattern] (export:pattern, siehe export.lsp) -
;;; ANZAHL_SCANNER und ANZAHL_SEPARATOR. ;;; dieselben Muster wie csv:collect-export-blocks/export_csv.py.
;;; Rueckgabe: (scanner-tag separator-tag) oder nil
;;; ------------------------------------------------------------ ;;; ------------------------------------------------------------
(defun cs-carrier-tags (nm / up)
;; --- Ist nm ein Kreisel/Eckrad-, VarioFoerderer- oder Gefaellestrecke-
;; Compound-Block? Alle drei fuehren einheitlich die Attribute
;; ANZAHL_SCANNER/ANZAHL_SEPARATOR. ---
(defun cs-carrier-p (nm / up)
(setq up (strcase nm)) (setq up (strcase nm))
(if (or (wcmatch up "KREISEL_*") (or (wcmatch up (export:pattern "pattern_kreisel" "KR_*,KREISEL_*,ECKRAD_*"))
(wcmatch up "VF_*") (wcmatch up (export:pattern "pattern_variofoerderer" "VF_*"))
(wcmatch up "GF_*")) (wcmatch up (export:pattern "pattern_gefaellestrecke" "GF_*"))
(list "ANZAHL_SCANNER" "ANZAHL_SEPARATOR")
nil
) )
) )
@@ -88,22 +129,8 @@
(defun cs-sensor-kind (nm / up) (defun cs-sensor-kind (nm / up)
(setq up (strcase nm)) (setq up (strcase nm))
(cond (cond
((wcmatch up *scanner-pattern*) 'scanner) ((wcmatch up (strcase (export:pattern "pattern_scanner" "Scanner*"))) 'scanner)
((wcmatch up *separator-pattern*) 'separator) ((wcmatch up (strcase (export:pattern "pattern_separator" "Separator_SP*,S-LP*"))) 'separator)
(t nil)
)
)
;;; ------------------------------------------------------------
;;; Punkt-Rueckgabe von vla-getboundingbox in eine Liste wandeln.
;;; BricsCAD liefert ein Safearray, AutoCAD ein Variant mit
;;; Safearray - beide Faelle werden hier abgedeckt.
;;; ------------------------------------------------------------
(defun cs-pt->list (v)
(cond
((= (type v) 'variant) (vlax-safearray->list (vlax-variant-value v)))
((= (type v) 'safearray) (vlax-safearray->list v))
((listp v) v)
(t nil) (t nil)
) )
) )
@@ -116,6 +143,15 @@
;;; Rueckgabe: (minx miny maxx maxy) oder nil bei Fehler. ;;; Rueckgabe: (minx miny maxx maxy) oder nil bei Fehler.
;;; *cs-last-error* enthaelt bei Fehler den echten COM-Fehlertext. ;;; *cs-last-error* enthaelt bei Fehler den echten COM-Fehlertext.
;;; ------------------------------------------------------------ ;;; ------------------------------------------------------------
(defun cs-pt->list (v)
(cond
((= (type v) 'variant) (vlax-safearray->list (vlax-variant-value v)))
((= (type v) 'safearray) (vlax-safearray->list v))
((listp v) v)
(t nil)
)
)
(defun cs-bbox (ent / obj res) (defun cs-bbox (ent / obj res)
(setq *cs-last-error* nil) (setq *cs-last-error* nil)
(setq obj (vlax-ename->vla-object ent)) (setq obj (vlax-ename->vla-object ent))
@@ -157,8 +193,8 @@
) )
;;; ------------------------------------------------------------ ;;; ------------------------------------------------------------
;;; Liegt Punkt pt (X/Y) in ILS-Block-Record rec (mit Toleranz)? ;;; Liegt Punkt pt (X/Y) in Carrier-Record rec (mit Toleranz)?
;;; rec = (ename tagScan tagSep minx miny maxx maxy cx cy) ;;; rec = (ename tagScan tagSep minx miny maxx maxy cx cy id)
;;; ------------------------------------------------------------ ;;; ------------------------------------------------------------
(defun cs-in-box (pt rec / x y) (defun cs-in-box (pt rec / x y)
(setq x (car pt) y (cadr pt)) (setq x (car pt) y (cadr pt))
@@ -246,13 +282,13 @@
) )
;;; ------------------------------------------------------------ ;;; ------------------------------------------------------------
;;; Sensor-Punkt einem ILS-Block zuordnen. ;;; Sensor-Punkt einem Carrier per BBox zuordnen (Schritt 1-3 oben).
;;; Rueckgabe: ILS-Block-Record oder nil (keine Zuordnung). ;;; Rueckgabe: Carrier-Record oder nil (kein BBox-Treffer).
;;; Bei mehreren Treffern: naechstes Box-Zentrum (X/Y). ;;; Bei mehreren Treffern: naechstes Box-Zentrum (X/Y).
;;; grid = Vorsortierung aus cs-grid-build (statt aller Carrier ;;; grid = Vorsortierung aus cs-grid-build (statt aller Carrier
;;; wird nur die Kandidatenliste der eigenen Zelle geprueft). ;;; wird nur die Kandidatenliste der eigenen Zelle geprueft).
;;; ------------------------------------------------------------ ;;; ------------------------------------------------------------
(defun cs-assign (pt grid / matches best bestd d) (defun cs-assign (pt grid / matches best bestd d rec)
(setq matches nil) (setq matches nil)
(foreach rec (cs-grid-candidates grid pt) (foreach rec (cs-grid-candidates grid pt)
(if (cs-in-box pt rec) (setq matches (cons rec matches)))) (if (cs-in-box pt rec) (setq matches (cons rec matches))))
@@ -270,6 +306,61 @@
) )
) )
;;; ------------------------------------------------------------
;;; Die beiden dem Punkt pt (X/Y) naechstgelegenen Carrier, sortiert
;;; nach Abstand zum Box-Mittelpunkt (gleicher Massstab wie der
;;; Ueberlappungs-Tiebreak in cs-assign). carriers darf nicht leer
;;; sein - siehe cs-resolve-sensor.
;;; Rueckgabe: (best-rec best-dist second-rec-oder-nil second-dist-oder-nil)
;;; ------------------------------------------------------------
(defun cs-nearest-two (pt carriers / paare sortiert rec)
(setq paare nil)
(foreach rec carriers
(setq paare (cons (cons (distance (list (car pt) (cadr pt))
(list (nth 7 rec) (nth 8 rec)))
rec)
paare))
)
(setq sortiert (vl-sort paare (function (lambda (a b) (< (car a) (car b))))))
(list
(cdr (nth 0 sortiert))
(car (nth 0 sortiert))
(if (cdr sortiert) (cdr (nth 1 sortiert)) nil)
(if (cdr sortiert) (car (nth 1 sortiert)) nil)
)
)
;;; --- Carrier-Record mit gegebener ID aus carriers heraussuchen ---
(defun cs-find-carrier-by-id (carriers id / found rec)
(setq found nil)
(foreach rec carriers
(if (and (not found) (= (nth 9 rec) id)) (setq found rec))
)
found
)
;;; ------------------------------------------------------------
;;; Ordnet einen Sensor-Punkt (Scanner oder Separator) einem Carrier
;;; zu (Reihenfolge siehe Datei-Kopfkommentar Schritte 0/1-3/4).
;;; Rueckgabe: (modus rec best-d second-rec second-d)
;;; modus = 'manual | 'bbox | 'distance | 'none (keine Carrier vorhanden)
;;; best-d/second-rec/second-d sind nur bei modus='distance gesetzt.
;;; ------------------------------------------------------------
(defun cs-resolve-sensor (sent spt carriers grid / existing rec nearest)
(setq existing (cs-get-att-str sent *zuordnung-tag*))
(cond
((and existing (/= existing ""))
(list 'manual (cs-find-carrier-by-id carriers existing) nil nil nil))
((setq rec (cs-assign spt grid))
(list 'bbox rec nil nil nil))
((null carriers)
(list 'none nil nil nil nil))
(t
(setq nearest (cs-nearest-two spt carriers))
(list 'distance (nth 0 nearest) (nth 1 nearest) (nth 2 nearest) (nth 3 nearest)))
)
)
;;; ------------------------------------------------------------ ;;; ------------------------------------------------------------
;;; Zaehler in einer Assoc-Liste (Schluessel = ename) erhoehen. ;;; Zaehler in einer Assoc-Liste (Schluessel = ename) erhoehen.
;;; ------------------------------------------------------------ ;;; ------------------------------------------------------------
@@ -363,8 +454,9 @@
) )
;;; ------------------------------------------------------------ ;;; ------------------------------------------------------------
;;; Bezeichnung eines ILS-Blocks ermitteln: Attribut "Bezeichnung", ;;; Bezeichnung eines Carriers ermitteln: Attribut "Bezeichnung",
;;; Fallback auf den Blocknamen. ;;; Fallback auf den Blocknamen. Nur fuer Konsolen-/Fehlermeldungen -
;;; die eigentliche Verknuepfung (ZUORDNUNG) laeuft ueber die ID.
;;; ------------------------------------------------------------ ;;; ------------------------------------------------------------
(defun cs-carrier-label (ent nm / bez) (defun cs-carrier-label (ent nm / bez)
(setq bez (cs-get-att-str ent "Bezeichnung")) (setq bez (cs-get-att-str ent "Bezeichnung"))
@@ -395,7 +487,7 @@
) )
;;; ------------------------------------------------------------ ;;; ------------------------------------------------------------
;;; Nicht zugeordneten Sensor mit einem Kreis markieren, zentriert ;;; Sensor ohne jeglichen Carrier mit einem Kreis markieren, zentriert
;;; auf die Sensor-Geometrie. Radius aus der XY-Box des Sensors ;;; auf die Sensor-Geometrie. Radius aus der XY-Box des Sensors
;;; (Faktor), mindestens *mark-radius-min*. ;;; (Faktor), mindestens *mark-radius-min*.
;;; ------------------------------------------------------------ ;;; ------------------------------------------------------------
@@ -422,63 +514,81 @@
) )
;;; ============================================================ ;;; ============================================================
;;; HAUPTBEFEHL ;;; ENGINE - wird sowohl von ZAEHLE_SEP_SCAN als auch automatisch
;;; vor jedem CSV-/Sivas-Export aufgerufen (siehe export.lsp,
;;; csv:run-export).
;;;
;;; label = Anzeigepraefix fuer die Konsolenausgabe (z.B. "EXPORTCSV").
;;; verbose = T -> zusaetzlich je Carrier eine Detailzeile ausgeben
;;; (nur fuer den interaktiven Befehl sinnvoll - der
;;; automatische Aufruf aus csv:run-export laesst dies aus,
;;; damit die Export-Konsole kompakt bleibt).
;;;
;;; Setzt als Nebenwirkung:
;;; *cs-scanner-ergaenzt* - Liste (scanner-id carrier-id
;;; distanz-mm strittig-p
;;; zweiter-carrier-id zweite-distanz-mm)
;;; je per Abstand (nicht per BBox)
;;; zugeordnetem Scanner.
;;; *cs-scanner-warnung-by-handle* - Assoc-Liste (handle . warnungstext)
;;; fuer strittige Scanner-Zuordnungen,
;;; von csv:block-to-json ausgelesen.
;;; ============================================================ ;;; ============================================================
(defun c:ZAEHLE_SEP_SCAN ( / ss i ent ed nm tags bb cx cy label (defun cs-zuordnung-lauf (label verbose /
carriers grid scanlist seplist kind pt mss ss i ent ed nm bb cx cy lbl carrier-id
scanCounts sepCounts carriers grid scanlist seplist sk pt
rec en nm2 ns nsep internSep newS newP scanCounts sepCounts n-scan-unassigned n-sep-unassigned
s sent spt n-strittig n-zuordnung-fehlt
n-scan-unassigned n-sep-unassigned s sent spt res mode rec best-d second-rec second-d
n-zuordnung-fehlt mss scanner-id contested handle
okS okP) en nm2 ns nsep internSep newS newP okS okP eintrag)
(setq carriers nil scanlist nil seplist nil n-zuordnung-fehlt 0) (setq carriers nil scanlist nil seplist nil
n-zuordnung-fehlt 0 n-scan-unassigned 0 n-sep-unassigned 0 n-strittig 0)
(setq *cs-scanner-ergaenzt* nil)
(setq *cs-scanner-warnung-by-handle* nil)
(setq *senstol* (cs-senstol))
;; Alte Markierungskreise entfernen (Idempotenz) ;; Alte Markierungskreise entfernen (Idempotenz - Sensoren, die in
;; einem frueheren Lauf unzuordenbar waren, koennen inzwischen einen
;; Carrier bekommen haben oder umgekehrt).
(setq mss (ssget "_X" (list (cons 0 "CIRCLE") (cons 8 *mark-layer*)))) (setq mss (ssget "_X" (list (cons 0 "CIRCLE") (cons 8 *mark-layer*))))
(if mss (command "_.ERASE" mss "")) (if mss (command "_.ERASE" mss ""))
;; Vor der Extents-Berechnung einmal regenerieren, damit
;; vla-getboundingbox verlaessliche Werte liefert.
(vl-catch-all-apply '(lambda () (command "_.REGEN"))) (vl-catch-all-apply '(lambda () (command "_.REGEN")))
;; --- 1. Alle INSERTs sammeln und klassifizieren --- (princ (ssg-textf "sens-start" (list label)))
(setq ss (ssget "_X" '((0 . "INSERT")))) (setq ss (ssget "_X" '((0 . "INSERT"))))
(if (null ss) (if (null ss)
(progn (princ "\n>>> Keine Bloecke in der Zeichnung gefunden.") (princ)) (princ (ssg-textf "sens-no-inserts" (list label)))
(progn (progn
(setq i 0) (setq i 0)
(while (< i (sslength ss)) (while (< i (sslength ss))
(setq ent (ssname ss i)) (setq ent (ssname ss i))
(setq ed (entget ent)) (setq ed (entget ent))
(setq nm (cdr (assoc 2 ed))) (setq nm (cdr (assoc 2 ed)))
(setq tags (cs-carrier-tags nm))
(cond (cond
;; --- ILS-Block --- ((cs-carrier-p nm)
(tags
(setq bb (cs-bbox ent)) (setq bb (cs-bbox ent))
(if bb (if bb
(progn (progn
(setq cx (/ (+ (nth 0 bb) (nth 2 bb)) 2.0)) (setq cx (/ (+ (nth 0 bb) (nth 2 bb)) 2.0))
(setq cy (/ (+ (nth 1 bb) (nth 3 bb)) 2.0)) (setq cy (/ (+ (nth 1 bb) (nth 3 bb)) 2.0))
(setq label (cs-carrier-label ent nm)) (setq lbl (cs-carrier-label ent nm))
(setq carrier-id (cs-get-att-str ent "ID"))
(setq carriers (setq carriers
(cons (list ent (car tags) (cadr tags) (cons (list ent "ANZAHL_SCANNER" "ANZAHL_SEPARATOR"
(nth 0 bb) (nth 1 bb) (nth 2 bb) (nth 3 bb) (nth 0 bb) (nth 1 bb) (nth 2 bb) (nth 3 bb)
cx cy label) cx cy carrier-id lbl)
carriers))) carriers)))
(princ (strcat "\n! Bounding-Box fehlgeschlagen fuer ILS-Block '" nm "'" (princ (ssg-textf "sens-bbox-fehler" (list nm)))
(if *cs-last-error*
(strcat " (" *cs-last-error* ")") "")))
) )
) )
;; --- Sensor (Entity + Referenzpunkt merken) ---
(t (t
(setq kind (cs-sensor-kind nm)) (setq sk (cs-sensor-kind nm))
(if kind (if sk
(progn (progn
(setq pt (cs-sensor-point ent ed kind)) (setq pt (cs-sensor-point ent ed sk))
(if (eq kind 'scanner) (if (eq sk 'scanner)
(setq scanlist (cons (list ent pt) scanlist)) (setq scanlist (cons (list ent pt) scanlist))
(setq seplist (cons (list ent pt) seplist))))) (setq seplist (cons (list ent pt) seplist)))))
) )
@@ -486,46 +596,77 @@
(setq i (1+ i)) (setq i (1+ i))
) )
;; --- 2. Sensoren zuordnen: zuordnung schreiben bzw. markieren ---
;; Vorsortierung: Carrier einmalig in ein raeumliches Grid einsortieren,
;; damit cs-assign je Sensor nur die Kandidaten der eigenen Zelle statt
;; aller Carrier prueft (siehe cs-grid-build).
(setq grid (cs-grid-build carriers)) (setq grid (cs-grid-build carriers))
(setq scanCounts nil sepCounts nil (setq scanCounts nil sepCounts nil)
n-scan-unassigned 0 n-sep-unassigned 0)
;; --- Scanner zuordnen (inkl. Distanz-Fallback + Strittig-Erkennung) ---
(foreach s scanlist (foreach s scanlist
(setq sent (car s) spt (cadr s)) (setq sent (car s) spt (cadr s))
(setq rec (cs-assign spt grid)) (setq res (cs-resolve-sensor sent spt carriers grid))
(if rec (setq mode (nth 0 res) rec (nth 1 res)
(progn best-d (nth 2 res) second-rec (nth 3 res) second-d (nth 4 res))
(cond
((eq mode 'none)
(setq n-scan-unassigned (1+ n-scan-unassigned))
(cs-mark-unassigned sent))
((null rec) nil) ;; manuell zugeordnet, ID unbekannt -> unangetastet
(t
(setq scanCounts (cs-bump scanCounts (car rec))) (setq scanCounts (cs-bump scanCounts (car rec)))
(if (member mode '(bbox distance))
(if (not (cs-set-att sent *zuordnung-tag* (nth 9 rec))) (if (not (cs-set-att sent *zuordnung-tag* (nth 9 rec)))
(setq n-zuordnung-fehlt (1+ n-zuordnung-fehlt)))) (setq n-zuordnung-fehlt (1+ n-zuordnung-fehlt))))
(if (eq mode 'distance)
(progn (progn
(setq n-scan-unassigned (1+ n-scan-unassigned)) (setq scanner-id (cs-get-att-str sent "ID"))
(cs-set-att sent *zuordnung-tag* "") (setq contested (and second-rec
(cs-mark-unassigned sent)))) (<= (- second-d best-d) (cs-strittig-diff-mm))))
(setq *cs-scanner-ergaenzt*
(cons (list scanner-id (nth 9 rec) (fix (+ best-d 0.5))
contested
(if contested (nth 9 second-rec) nil)
(if contested (fix (+ second-d 0.5)) nil))
*cs-scanner-ergaenzt*))
(if contested
(progn
(setq n-strittig (1+ n-strittig))
(setq handle (cdr (assoc 5 (entget sent))))
(setq *cs-scanner-warnung-by-handle*
(cons (cons handle
(strcat "Distanz-Zuordnung unsicher: "
(nth 9 rec) " (" (itoa (fix (+ best-d 0.5))) "mm) vs. "
(nth 9 second-rec) " (" (itoa (fix (+ second-d 0.5))) "mm)"))
*cs-scanner-warnung-by-handle*))
)
)
)
)
)
)
)
(setq *cs-scanner-ergaenzt* (reverse *cs-scanner-ergaenzt*))
;; --- Separatoren zuordnen (gleiche Logik, ohne Strittig-Report -
;; der Distanz-Fallback stellt hier nur sicher, dass die
;; ANZAHL_SEPARATOR-Summe auch bei Sonderfaellen stimmt). ---
(foreach s seplist (foreach s seplist
(setq sent (car s) spt (cadr s)) (setq sent (car s) spt (cadr s))
(setq rec (cs-assign spt grid)) (setq res (cs-resolve-sensor sent spt carriers grid))
(if rec (setq mode (nth 0 res) rec (nth 1 res))
(progn (cond
((eq mode 'none)
(setq n-sep-unassigned (1+ n-sep-unassigned))
(cs-mark-unassigned sent))
((null rec) nil)
(t
(setq sepCounts (cs-bump sepCounts (car rec))) (setq sepCounts (cs-bump sepCounts (car rec)))
(if (member mode '(bbox distance))
(if (not (cs-set-att sent *zuordnung-tag* (nth 9 rec))) (if (not (cs-set-att sent *zuordnung-tag* (nth 9 rec)))
(setq n-zuordnung-fehlt (1+ n-zuordnung-fehlt)))) (setq n-zuordnung-fehlt (1+ n-zuordnung-fehlt))))
(progn )
(setq n-sep-unassigned (1+ n-sep-unassigned)) )
(cs-set-att sent *zuordnung-tag* "") )
(cs-mark-unassigned sent))))
;; --- 3. ANZAHL-Attribute setzen und Bericht ausgeben --- ;; --- ANZAHL_SCANNER/ANZAHL_SEPARATOR je Carrier schreiben ---
(princ "\n============================================")
(princ "\n Sensor-Zaehlung je ILS-Block")
(princ "\n============================================")
(if (null carriers)
(princ "\n (Keine ILS-Bloecke KREISEL_/VF_/GF_ gefunden)")
(foreach rec carriers (foreach rec carriers
(setq en (car rec)) (setq en (car rec))
(setq nm2 (cdr (assoc 2 (entget en)))) (setq nm2 (cdr (assoc 2 (entget en))))
@@ -533,52 +674,64 @@
(setq nsep (cond ((assoc en sepCounts) (cdr (assoc en sepCounts))) (t 0))) (setq nsep (cond ((assoc en sepCounts) (cdr (assoc en sepCounts))) (t 0)))
;; interne Kette-Separatoren frisch aus der Blockdefinition zaehlen ;; interne Kette-Separatoren frisch aus der Blockdefinition zaehlen
(setq internSep (cs-count-nested nm2 *intern-separator-pattern*)) (setq internSep (cs-count-nested nm2 *intern-separator-pattern*))
;; Scanner = nur neu zugeordnete
;; Separator = interne Kette-Separatoren + neu zugeordnete
(setq newS ns) (setq newS ns)
(setq newP (+ internSep nsep)) (setq newP (+ internSep nsep))
;; gefundene Anzahlen melden (mit Bezeichnung/Label)
(princ (strcat "\n " nm2 " [" (nth 9 rec) "]"
": Scanner(neu)=" (itoa ns)
", Separator intern=" (itoa internSep)
" + manuell=" (itoa nsep)))
;; Werte schreiben und Ergebnis bestaetigen
(setq okS (cs-set-att en (nth 1 rec) (itoa newS))) (setq okS (cs-set-att en (nth 1 rec) (itoa newS)))
(setq okP (cs-set-att en (nth 2 rec) (itoa newP))) (setq okP (cs-set-att en (nth 2 rec) (itoa newP)))
(if (and okS okP) (if verbose
(princ (strcat "\n -> geschrieben: " (princ (ssg-textf "sens-carrier-zeile"
"ANZAHL_SCANNER=" (itoa newS) (list nm2 (nth 9 rec) (itoa ns) (itoa internSep) (itoa nsep)
", ANZAHL_SEPARATOR=" (itoa newP))) (itoa newS) (itoa newP)))))
(princ (strcat "\n -> FEHLER beim Schreiben: " (if (not (and okS okP))
(if okS "" "ANZAHL_SCANNER fehlt ") (princ (ssg-textf "sens-carrier-fehler" (list nm2))))
(if okP "" "ANZAHL_SEPARATOR fehlt"))))
) )
)
(princ (strcat "\n--------------------------------------------"
"\n ILS-Bloecke gesamt: " (itoa (length carriers))
"\n Scanner gesamt: " (itoa (length scanlist))
" (nicht zugeordnet: " (itoa n-scan-unassigned) ")"
"\n Separator gesamt: " (itoa (length seplist))
" (nicht zugeordnet: " (itoa n-sep-unassigned) ")"))
(if (> (+ n-scan-unassigned n-sep-unassigned) 0)
(princ (strcat "\n " (itoa (+ n-scan-unassigned n-sep-unassigned))
" nicht zugeordnete(r) Sensor(en) mit Kreis markiert"
" (Layer '" *mark-layer* "').")))
(if (> n-zuordnung-fehlt 0)
(princ (strcat "\n WARNUNG: " (itoa n-zuordnung-fehlt)
" zugeordnete(r) Sensor(en) ohne Attribut '"
*zuordnung-tag* "' - Bezeichnung nicht schreibbar.")))
;; --- 4. Zeichnung speichern --- ;; --- Zusammenfassung ---
(princ "\n--------------------------------------------") (princ (ssg-textf "sens-summary"
(princ "\n Speichere Zeichnung (QSAVE) ...") (list label (itoa (length carriers))
(command "_.QSAVE") (itoa (length scanlist)) (itoa n-scan-unassigned)
(princ "\n>>> Fertig.") (itoa (length seplist)) (itoa n-sep-unassigned))))
(princ)
(if *cs-scanner-ergaenzt*
(progn
(princ (ssg-textf "sens-ergaenzt-header"
(list label (itoa (length *cs-scanner-ergaenzt*)))))
(foreach eintrag *cs-scanner-ergaenzt*
(princ (ssg-textf "sens-ergaenzt-zeile"
(list (nth 0 eintrag) (nth 1 eintrag) (itoa (nth 2 eintrag)))))
(if (nth 3 eintrag)
(princ (ssg-textf "sens-strittig-suffix"
(list (nth 4 eintrag) (itoa (nth 5 eintrag))))))
)
)
)
(if (> n-strittig 0)
(princ (ssg-textf "sens-strittig-summary" (list label (itoa n-strittig)))))
(if (> (+ n-scan-unassigned n-sep-unassigned) 0)
(princ (ssg-textf "sens-unassigned-marked"
(list label (itoa (+ n-scan-unassigned n-sep-unassigned)) *mark-layer*))))
(if (> n-zuordnung-fehlt 0)
(princ (ssg-textf "sens-zuordnung-fehlt" (list label (itoa n-zuordnung-fehlt)))))
) )
) )
(princ) (princ)
) )
;;; ============================================================
;;; BEFEHL: ZAEHLE_SEP_SCAN - interaktiver Aufruf mit vollem Bericht
;;; (verbose) und abschliessendem QSAVE. Der automatische Aufruf vor
;;; jedem CSV-/Sivas-Export (csv:run-export in export.lsp) nutzt
;;; dieselbe Engine (cs-zuordnung-lauf) direkt, ohne QSAVE.
;;; ============================================================
(defun c:ZAEHLE_SEP_SCAN ()
(cs-zuordnung-lauf "ZAEHLE_SEP_SCAN" T)
(princ "\n--------------------------------------------")
(princ "\n Speichere Zeichnung (QSAVE) ...")
(command "_.QSAVE")
(princ "\n>>> Fertig.")
(princ)
)
(princ "\n>>> count_sep_scan.lsp geladen. Befehl: ZAEHLE_SEP_SCAN") (princ "\n>>> count_sep_scan.lsp geladen. Befehl: ZAEHLE_SEP_SCAN")
(princ) (princ)
+28 -1
View File
@@ -463,7 +463,7 @@
;; csv:get-k-kos-strings) werden immer geschrieben, unabhaengig von ;; csv:get-k-kos-strings) werden immer geschrieben, unabhaengig von
;; include-bbox -- Kodierung ueber csv:kos-encode (siehe dort). ;; include-bbox -- Kodierung ueber csv:kos-encode (siehe dort).
(defun csv:block-to-json (ename include-bbox / ed blk-name layer pt rotation handle attribs bbox bbox-json (defun csv:block-to-json (ename include-bbox / ed blk-name layer pt rotation handle attribs bbox bbox-json
insert-quat insert-kos k-list) insert-quat insert-kos k-list warnung-json warnung-eintrag)
(setq ed (entget ename)) (setq ed (entget ename))
(setq blk-name (cdr (assoc 2 ed))) (setq blk-name (cdr (assoc 2 ed)))
(setq layer (cdr (assoc 8 ed))) (setq layer (cdr (assoc 8 ed)))
@@ -506,6 +506,17 @@
) )
) )
) )
;; Warnung fuer strittige Scanner-Zuordnungen anhaengen (siehe
;; cs-zuordnung-lauf in count_sep_scan.lsp, das *cs-scanner-warnung-
;; by-handle* vor csv:collect-export-blocks befuellt). Referenziert
;; die Variable direkt statt ueber atoms-family: ein in AutoLISP noch
;; nie gesetztes globales Symbol wertet beim Lesen zu nil aus (kein
;; Fehler), genau wie *export-test-override* in diesem Modul.
(setq warnung-json "")
(setq warnung-eintrag (assoc handle *cs-scanner-warnung-by-handle*))
(if warnung-eintrag
(setq warnung-json (strcat ",\"warnung\":\"" (csv:json-escape (cdr warnung-eintrag)) "\""))
)
(strcat (strcat
" {\"block_name\":\"" (csv:json-escape blk-name) "\"" " {\"block_name\":\"" (csv:json-escape blk-name) "\""
",\"layer\":\"" (csv:json-escape layer) "\"" ",\"layer\":\"" (csv:json-escape layer) "\""
@@ -521,6 +532,7 @@
",\"k3\":\"" (csv:k-kos k-list "K3") "\"" ",\"k3\":\"" (csv:k-kos k-list "K3") "\""
",\"k4\":\"" (csv:k-kos k-list "K4") "\"" ",\"k4\":\"" (csv:k-kos k-list "K4") "\""
bbox-json bbox-json
warnung-json
"}" "}"
) )
) )
@@ -615,6 +627,21 @@
;; Vor dem Export HOEHE/DREHUNG aller Omniflo-Elemente aktualisieren ;; Vor dem Export HOEHE/DREHUNG aller Omniflo-Elemente aktualisieren
(princ (ssg-textf "exp-update-hoehe-drehung" (list label))) (princ (ssg-textf "exp-update-hoehe-drehung" (list label)))
(omni:update-all-attribs) (omni:update-all-attribs)
;; Vor dem Export: Separator-/Scanner-Zuordnung pruefen und
;; ANZAHL_SEPARATOR/ANZAHL_SCANNER an Kreisel/Streckengruppe/
;; Gefaellestrecke aktualisieren (siehe count_sep_scan.lsp,
;; cs-zuordnung-lauf). Scanner ausserhalb jeder Carrier-Boundingbox
;; werden dabei per Abstand zugeordnet (ZUORDNUNG-Attribut = Carrier-
;; ID) und - bei mehrdeutigem Abstand - als "strittig" markiert;
;; *cs-scanner-warnung-by-handle* wird von csv:block-to-json unten
;; ausgelesen und haengt den Warnungstext an den betroffenen Scanner-
;; Block im JSON an. verbose=nil haelt die Export-Konsole kompakt
;; (die ausfuehrliche Detailzeile je Carrier gibt es nur beim
;; interaktiven Befehl ZAEHLE_SEP_SCAN).
(ssg-ensure "count_sep_scan")
(if (atoms-family 1 '("cs-zuordnung-lauf"))
(cs-zuordnung-lauf label nil)
)
(princ (ssg-textf "exp-collect-blocks" (list label))) (princ (ssg-textf "exp-collect-blocks" (list label)))
(setq ss (csv:collect-export-blocks)) (setq ss (csv:collect-export-blocks))
+21
View File
@@ -157,3 +157,24 @@ bb_minimum_height_mm=1
# Linie durch beide Stationsmitten) - genau diese Linie trennt links/rechts. # Linie durch beide Stationsmitten) - genau diese Linie trennt links/rechts.
durchmesser_mm=800 durchmesser_mm=800
[Sensorzuordnung]
# Zuordnung von manuell platzierten Separator_SP/Scanner-Bloecken zu einem
# Kreisel/Eckrad, einer VarioFoerderer-Streckengruppe (VF_*) oder einer
# Gefaellestrecke (GF_*) - siehe Lisp/count_sep_scan.lsp (cs-zuordnung-lauf).
# Laeuft automatisch vor jedem CSV-/Sivas-Export (Lisp/export.lsp,
# csv:run-export) und schreibt ANZAHL_SEPARATOR/ANZAHL_SCANNER am
# Kreisel/VF/GF sowie ZUORDNUNG (= ID des zugeordneten Elements) am Sensor.
# Toleranzrand (mm) um die Carrier-Boundingbox: Sensoren knapp ausserhalb
# gelten noch als "innerhalb". 0 = exakte Box.
senstol_mm=0
# Scanner (und Separatoren) ausserhalb JEDER Carrier-Boundingbox ohne
# vorhandenes ZUORDNUNG-Attribut werden per Abstand dem naechstgelegenen
# Kreisel/VF/GF zugeschlagen. Liegt der Abstand zum zweitnaechsten
# Kandidaten hoechstens strittig_diff_mm ueber dem des naechsten, gilt die
# Zuordnung als unsicher ("strittig"): sie wird trotzdem geschrieben, aber
# als Warnung im CSV-Export (Spalte "Warnungen") und in der BricsCAD-Konsole
# ausgegeben. Wert in mm.
strittig_diff_mm=500
+12
View File
@@ -512,6 +512,18 @@
"exp-csv-missing": "\n[%1] FEHLER: Python meldete Erfolg, aber die CSV fehlt: %2. Log: %3", "exp-csv-missing": "\n[%1] FEHLER: Python meldete Erfolg, aber die CSV fehlt: %2. Log: %3",
"exp-omni-no-inserts": "\n[OMNI_UPDATE] Keine INSERT-Bloecke in der Zeichnung.", "exp-omni-no-inserts": "\n[OMNI_UPDATE] Keine INSERT-Bloecke in der Zeichnung.",
"exp-omni-updated": "\n[OMNI_UPDATE] %1 Elemente aktualisiert (HOEHE, DREHUNG).", "exp-omni-updated": "\n[OMNI_UPDATE] %1 Elemente aktualisiert (HOEHE, DREHUNG).",
"sens-start": "\n[%1] Pruefe Separator-/Scanner-Zuordnung (ANZAHL_SEPARATOR/ANZAHL_SCANNER)...",
"sens-no-inserts": "\n[%1] Keine Bloecke in der Zeichnung gefunden - Sensor-Zuordnung uebersprungen.",
"sens-bbox-fehler": "\n ! Bounding-Box fehlgeschlagen fuer ILS-Block '%1'",
"sens-carrier-zeile": "\n %1 [%2]: Scanner(neu)=%3, Separator intern=%4 + manuell=%5 -> ANZAHL_SCANNER=%6, ANZAHL_SEPARATOR=%7",
"sens-carrier-fehler": "\n FEHLER beim Schreiben der Anzahl-Attribute an %1",
"sens-summary": "\n[%1] %2 Kreisel/Streckengruppen/Gefaellestrecken aktualisiert, %3 Scanner gesamt (%4 nicht zuordenbar), %5 Separator gesamt (%6 nicht zuordenbar).",
"sens-ergaenzt-header": "\n[%1] %2 Scanner ausserhalb jeder Kreisel-/Strecken-Boundingbox per Abstand automatisch zugeordnet:",
"sens-ergaenzt-zeile": "\n Scanner %1 -> %2 (%3mm)",
"sens-strittig-suffix": " STRITTIG: auch nah an %1 (%2mm)",
"sens-strittig-summary": "\n[%1] WARNUNG: %2 der obigen Zuordnungen sind strittig (Abstand zu zwei Kandidaten fast gleich) - siehe Spalte 'Warnungen' im CSV-Export.",
"sens-unassigned-marked": "\n[%1] %2 Sensor(en) ohne jeglichen Kreisel/Strecke markiert (Layer '%3').",
"sens-zuordnung-fehlt": "\n[%1] WARNUNG: %2 zugeordnete(r) Sensor(en) ohne Attribut 'ZUORDNUNG' - Wert nicht schreibbar.",
"id-new-assigned": "\n[ID] Neue ID zugewiesen: %1", "id-new-assigned": "\n[ID] Neue ID zugewiesen: %1",
"id-invalid-block": "\n[ID] FEHLER: Kein gueltiger INSERT-Block!", "id-invalid-block": "\n[ID] FEHLER: Kein gueltiger INSERT-Block!",
"id-check-no-blocks": "\n[IDSCHECK] Keine relevanten Bloecke gefunden.", "id-check-no-blocks": "\n[IDSCHECK] Keine relevanten Bloecke gefunden.",
+12
View File
@@ -512,6 +512,18 @@
"exp-csv-missing": "\n[%1] ERROR: Python reported success but the CSV is missing: %2. Log: %3", "exp-csv-missing": "\n[%1] ERROR: Python reported success but the CSV is missing: %2. Log: %3",
"exp-omni-no-inserts": "\n[OMNI_UPDATE] No INSERT blocks in the drawing.", "exp-omni-no-inserts": "\n[OMNI_UPDATE] No INSERT blocks in the drawing.",
"exp-omni-updated": "\n[OMNI_UPDATE] %1 elements updated (HEIGHT, ROTATION).", "exp-omni-updated": "\n[OMNI_UPDATE] %1 elements updated (HEIGHT, ROTATION).",
"sens-start": "\n[%1] Checking separator/scanner assignment (ANZAHL_SEPARATOR/ANZAHL_SCANNER)...",
"sens-no-inserts": "\n[%1] No blocks found in the drawing - sensor assignment skipped.",
"sens-bbox-fehler": "\n ! Bounding box failed for ILS block '%1'",
"sens-carrier-zeile": "\n %1 [%2]: Scanner(new)=%3, Separator internal=%4 + manual=%5 -> ANZAHL_SCANNER=%6, ANZAHL_SEPARATOR=%7",
"sens-carrier-fehler": "\n ERROR writing the count attributes on %1",
"sens-summary": "\n[%1] %2 Kreisel/Streckengruppen/Gefaellestrecken updated, %3 scanners total (%4 unassignable), %5 separators total (%6 unassignable).",
"sens-ergaenzt-header": "\n[%1] %2 scanners outside every Kreisel/track bounding box auto-assigned by distance:",
"sens-ergaenzt-zeile": "\n Scanner %1 -> %2 (%3mm)",
"sens-strittig-suffix": " CONTESTED: also close to %1 (%2mm)",
"sens-strittig-summary": "\n[%1] WARNING: %2 of the above assignments are contested (distance to two candidates nearly equal) - see column 'Warnungen' in the CSV export.",
"sens-unassigned-marked": "\n[%1] %2 sensor(s) without any Kreisel/track marked (layer '%3').",
"sens-zuordnung-fehlt": "\n[%1] WARNING: %2 assigned sensor(s) without a 'ZUORDNUNG' attribute - value not writable.",
"id-new-assigned": "\n[ID] New ID assigned: %1", "id-new-assigned": "\n[ID] New ID assigned: %1",
"id-invalid-block": "\n[ID] ERROR: Not a valid INSERT block!", "id-invalid-block": "\n[ID] ERROR: Not a valid INSERT block!",
"id-check-no-blocks": "\n[IDSCHECK] No relevant blocks found.", "id-check-no-blocks": "\n[IDSCHECK] No relevant blocks found.",
+14
View File
@@ -27,6 +27,13 @@ Warnungen = Spalte fuer Auffaelligkeiten. Aktuell: eine Strecke sollte genau
zwei Kreisel (Anfang + Ende) beruehren - beruehrt ihre (in x/y gepruefte) zwei Kreisel (Anfang + Ende) beruehren - beruehrt ihre (in x/y gepruefte)
Bounding-Box mehr, steht hier ein Hinweis und es wird zusaetzlich eine Bounding-Box mehr, steht hier ein Hinweis und es wird zusaetzlich eine
Konsolen-WARNUNG ausgegeben (mit exakten 3D-BBoxen sollte das nicht auftreten). Konsolen-WARNUNG ausgegeben (mit exakten 3D-BBoxen sollte das nicht auftreten).
Scanner-Zeilen bekommen dieselbe Spalte fuer strittige Distanz-Zuordnungen:
liegt ein Scanner ausserhalb jeder Kreisel-/Streckengruppen-/Gefaellestrecke-
Boundingbox und ist der Abstand zum naechsten und zweitnaechsten Carrier fast
gleich gross, schreibt Lisp/count_sep_scan.lsp (cs-zuordnung-lauf, vor dem
Export automatisch aufgerufen) einen Warnungstext mit den IDs beider
Kandidaten in das "warnung"-Feld des Scanner-Blocks im Roh-JSON (siehe
csv:block-to-json in export.lsp) - hier unveraendert uebernommen.
Aufruf: Aufruf:
python export_csv.py <export_raw.json> <data_dir> <output.csv> python export_csv.py <export_raw.json> <data_dir> <output.csv>
@@ -765,6 +772,13 @@ def process_blocks(blocks, lookup, dbg=None):
"bezeichnung": f"Scanner :{scanner_count}", "bezeichnung": f"Scanner :{scanner_count}",
"planquadrat": planquadrat_column(block, planquadrat_cfg), "planquadrat": planquadrat_column(block, planquadrat_cfg),
"merkmale": build_sensor_merkmale(block), "merkmale": build_sensor_merkmale(block),
# "warnung" kommt von cs-zuordnung-lauf (Lisp/count_sep_scan.lsp),
# das vor dem Export strittige Distanz-Zuordnungen (Scanner
# ausserhalb jeder Kreisel-/Strecken-Boundingbox, Abstand zu zwei
# Kandidaten fast gleich) in *cs-scanner-warnung-by-handle*
# sammelt - csv:block-to-json (export.lsp) haengt den Text als
# "warnung"-Feld an den betroffenen Scanner-Block im JSON an.
"warnung": block.get("warnung", ""),
**bbox_columns(block), **bbox_columns(block),
}) })
continue continue
+1 -1
View File
@@ -131,7 +131,7 @@
[Marker bearbeiten]^C^C(ssg-ensure "Tro_Edit") TRO_EDIT [Marker bearbeiten]^C^C(ssg-ensure "Tro_Edit") TRO_EDIT
[<-Bearbeiten (Auto)]^C^C(ssg-ensure "SSG_LIB_Commands") SSG_BLOCKEDIT [<-Bearbeiten (Auto)]^C^C(ssg-ensure "SSG_LIB_Commands") SSG_BLOCKEDIT
[->Export] [->Export]
[Export Sivas]^C^C(ssg-ensure "count_sep_scan") ZAEHLE_SEP_SCAN (ssg-ensure "export") EXPORTSIVAS [Export Sivas]^C^C(ssg-ensure "export") EXPORTSIVAS
[<-Export CSV]^C^C(ssg-ensure "export") EXPORTCSV [<-Export CSV]^C^C(ssg-ensure "export") EXPORTCSV
[->Konfiguration] [->Konfiguration]
[Umschalten 2D und 3D]^C^C(ssg-ensure "SSG_LIB_Commands") SSG_DIM_SWITCH [Umschalten 2D und 3D]^C^C(ssg-ensure "SSG_LIB_Commands") SSG_DIM_SWITCH