Merge origin/master: Sensor-Zuordnung + Connections zusammenfuehren
Konflikt in lang/de_DE.json und lang/en_GB.json aufgeloest: beide Seiten haben nur Schluessel ergaenzt (con-*/cmd-connection-* hier, sens-* aus origin). Beide Saetze uebernommen, Einrueckung von origin (2 Leerzeichen) beibehalten, tro-edit-fb mit UID-Anzeige uebernommen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -993,7 +993,7 @@
|
||||
aktuell-frame nach-aus-pt
|
||||
gf-nummer last-ent
|
||||
L-gf-str delta-l-gf laengen-liste first-l l-item
|
||||
bL90 bL60 bL30 bR90 bR60 bR30 n-bogen-gf
|
||||
bL90 bL60 bL30 bR90 bR60 bR30
|
||||
ein-hz-as rad-h-as rad-v-as xu-entry
|
||||
sep-endpunkt rad-h-es rad-v-es xu-exit sep-frame
|
||||
es-aus-frame
|
||||
@@ -1312,8 +1312,6 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
(setq n-bogen-gf (+ bL90 bL60 bL30 bR90 bR60 bR30))
|
||||
|
||||
;; delta-l-gf bereits vor der Zusammenfassung berechnet
|
||||
|
||||
;; Block mit allen Attributen erstellen. Geruest fuer Einzelmodul/
|
||||
@@ -1327,7 +1325,9 @@
|
||||
delta-l-gf
|
||||
L-gf-str
|
||||
grade
|
||||
(1+ n-bogen-gf)
|
||||
;; n-separator/n-scanner = 0: interne Ketten-Separatoren zaehlen nicht;
|
||||
;; die echte Anzahl setzt der Export aus platzierten Symbolen.
|
||||
0
|
||||
0
|
||||
bL90 bL60 bL30
|
||||
bR90 bR60 bR30
|
||||
@@ -1386,7 +1386,7 @@
|
||||
;; L-first-seg: Laenge der ersten geraden Staustrecke in mm.
|
||||
;; Beschriftung: Mitte der ersten Geraden, 400mm senkrecht rechts versetzt.
|
||||
(defun gf-make-label (gf-nummer hoehe-von hoehe-bis deltaH deltaL
|
||||
L-gf-str winkel n-separator nach-aus-pt entry-hz L-first-seg /
|
||||
L-gf-str winkel nach-aus-pt entry-hz L-first-seg /
|
||||
label-txt label-pt chz-l shz-l halb basis-winkel)
|
||||
(setq chz-l (cos (* entry-hz (/ pi 180.0))))
|
||||
(setq shz-l (sin (* entry-hz (/ pi 180.0))))
|
||||
@@ -1401,8 +1401,7 @@
|
||||
" " delta-sym "H=" (itoa (fix (abs deltaH))) "mm"
|
||||
" " delta-sym "L=" (itoa (fix deltaL)) "mm"
|
||||
" L=[" L-gf-str "]m"
|
||||
" W=" (rtos (float winkel) 2 2) grad-zeichen
|
||||
" Sep=" (itoa n-separator)))
|
||||
" W=" (rtos (float winkel) 2 2) grad-zeichen))
|
||||
;; Basiswinkel: Text immer lesbar auf 0 Grad (X-Achse, links->rechts) oder
|
||||
;; 90 Grad (Y-Achse) einrasten - unabhaengig von der tatsaechlichen
|
||||
;; Fahrtrichtung (nie 180/270, damit der Text nie auf dem Kopf steht).
|
||||
@@ -1439,7 +1438,7 @@
|
||||
(if (null geruest-typ) (setq geruest-typ (ssg-geruest-idx-to-typ (ssg-geruest-typ-to-idx nil))))
|
||||
;; Beschriftung: Mitte der ersten Geraden, 400mm senkrecht versetzt
|
||||
(gf-make-label gf-nummer hoehe-von hoehe-bis deltaH deltaL
|
||||
L-gf-str winkel n-separator nach-aus-pt entry-hz L-first-seg)
|
||||
L-gf-str winkel nach-aus-pt entry-hz L-first-seg)
|
||||
;; TYP: mit Bogen -> "Streckengruppe"; ohne Bogen (einsegmentig) ->
|
||||
;; "Gefaellestrecke" (reduzierter Attributsatz, siehe ssg-strecke-attrib-defs).
|
||||
(setq typ-str
|
||||
@@ -1518,6 +1517,12 @@
|
||||
(cons "GF_Bogen_R_90" (itoa bogen-R90))
|
||||
(cons "GF_Bogen_R_60" (itoa bogen-R60))
|
||||
(cons "GF_Bogen_R_30" (itoa bogen-R30))
|
||||
;; ANZAHL_SEPARATOR/ANZAHL_SCANNER werden beim Bau mit 0 vorbelegt
|
||||
;; (n-separator/n-scanner werden von den Aufrufern als 0 uebergeben):
|
||||
;; der intern gezeichnete Ketten-Separator Staustrecke_Separator_SP zaehlt
|
||||
;; NICHT als Separator. Die tatsaechliche Anzahl ermittelt der Export aus
|
||||
;; den platzierten Separator_SP/S-LP-/Scanner-Symbolen und schreibt sie
|
||||
;; hier hinein (cs-zuordnung-lauf in count_sep_scan.lsp).
|
||||
(cons "ANZAHL_SEPARATOR" (itoa n-separator))
|
||||
(cons "ANZAHL_SCANNER" (itoa n-scanner))
|
||||
(cons "GERUEST_EINZELMODUL" geruest-einzelmodul)
|
||||
@@ -1637,7 +1642,9 @@
|
||||
(float deltaL-total)
|
||||
L-gf-str
|
||||
winkel
|
||||
1 0
|
||||
;; n-separator/n-scanner = 0: der interne Ketten-Separator zaehlt nicht;
|
||||
;; die echte Anzahl setzt der Export aus platzierten Symbolen (s.o.).
|
||||
0 0
|
||||
0 0 0 0 0 0
|
||||
startpunkt last-ent nach-aus-pt (float hz) (float L_stau)
|
||||
es-seite geruest-einzelmodul geruest-typ))
|
||||
|
||||
+436
-226
@@ -1,63 +1,90 @@
|
||||
;;; ============================================================
|
||||
;;; count_sep_scan.lsp - Eigenstaendiges Zaehl-Werkzeug
|
||||
;;; count_sep_scan.lsp - Separator-/Scanner-Zuordnung
|
||||
;;; ------------------------------------------------------------
|
||||
;;; Zaehlt die manuell platzierten Bloecke "Scanner" und
|
||||
;;; "Separator_SP" je ILS-Block (Kreisel / VarioFoerderer /
|
||||
;;; Gefaellestrecke) und schreibt die Anzahlen in die Attribute
|
||||
;;; des jeweiligen ILS-Blocks. Anschliessend QSAVE.
|
||||
;;; "Separator_SP" (Muster siehe cfg/export.cfg [blockpattern]
|
||||
;;; pattern_scanner/pattern_separator) je Carrier (Kreisel/Eckrad,
|
||||
;;; 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):
|
||||
;;; - Scanner: der Einfuegepunkt (X/Y) muss in der Bounding-Box
|
||||
;;; des ILS-Blocks liegen. Die 3D-Geometrie des Scanners kann
|
||||
;;; weit vom Einfuegepunkt entfernt sein, daher zaehlt hier der
|
||||
;;; Einfuegepunkt (dort klickt der Benutzer auf den Block).
|
||||
;;; - Separator: der geometrische Mittelpunkt (Zentrum der eigenen
|
||||
;;; Bounding-Box, unabhaengig vom $INSBASE) muss in der
|
||||
;;; Bounding-Box des ILS-Blocks liegen.
|
||||
;;; - Liegt der Punkt in mehreren Boxen (Ueberlappung), wird
|
||||
;;; der ILS-Block mit dem naechstgelegenen Box-Zentrum gewaehlt.
|
||||
;;; - Ein optionaler Toleranzrand (*senstol*) vergroessert die
|
||||
;;; Box, damit Sensoren knapp am Rand noch erfasst werden.
|
||||
;;; WICHTIG: Gezaehlt werden ausschliesslich die eigenstaendig
|
||||
;;; platzierten Sensor-Symbole. Der intern in der GF/VF-Kette
|
||||
;;; gezeichnete 300-mm-Block Staustrecke_Separator_SP ist nur ein
|
||||
;;; Ketten-/Uebergabestueck (kein eigenstaendiger Separator) und wird
|
||||
;;; NICHT mitgezaehlt - wer einen Separator gezaehlt haben will, setzt
|
||||
;;; ein Separator_SP/S-LP-Symbol.
|
||||
;;;
|
||||
;;; Zusaetzlich:
|
||||
;;; - Bei zugeordneten Sensoren wird die Bezeichnung des ILS-Blocks
|
||||
;;; (Attribut "Bezeichnung", Fallback Blockname) in das Sensor-
|
||||
;;; Attribut *zuordnung-tag* geschrieben.
|
||||
;;; - Nicht zugeordnete Sensoren werden mit einem Kreis auf dem
|
||||
;;; Layer *mark-layer* markiert (zentriert auf den Sensor).
|
||||
;;; - Der Befehl ist wiederholbar: alte Markierungskreise werden
|
||||
;;; zu Beginn entfernt.
|
||||
;;; Zuordnung eines Sensors zu einem Carrier (Z wird ignoriert):
|
||||
;;; 0. Traegt der Sensor bereits ein ZUORDNUNG-Attribut, wird das
|
||||
;;; 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
|
||||
;;; Einfuegepunkt (dort klickt der Benutzer auf den Block).
|
||||
;;; 2. Separator: der geometrische Mittelpunkt (Zentrum der eigenen
|
||||
;;; Bounding-Box, unabhaengig vom $INSBASE) muss in der
|
||||
;;; Bounding-Box des Carriers liegen.
|
||||
;;; 3. Liegt der Punkt in mehreren Boxen (Ueberlappung), wird der
|
||||
;;; Carrier mit dem naechstgelegenen Box-Zentrum gewaehlt.
|
||||
;;; 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.
|
||||
;;; 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).
|
||||
;;;
|
||||
;;; Aufruf: ZAEHLE_SEP_SCAN
|
||||
;;; Laden: per APPLOAD oder (load "count_sep_scan")
|
||||
;;; cs-zuordnung-lauf ist die wiederverwendbare Engine (siehe unten):
|
||||
;;; sie wird sowohl vom interaktiven Befehl ZAEHLE_SEP_SCAN als auch
|
||||
;;; automatisch vor jedem CSV-/Sivas-Export aufgerufen (Lisp/export.lsp,
|
||||
;;; csv:run-export) - dort OHNE QSAVE und ohne die ausfuehrliche
|
||||
;;; Detailzeile je Carrier (verbose=nil), damit die Konsolenausgabe
|
||||
;;; beim normalen Export kompakt bleibt.
|
||||
;;;
|
||||
;;; Aufruf (interaktiv): ZAEHLE_SEP_SCAN
|
||||
;;; Laden: per APPLOAD oder (ssg-ensure "count_sep_scan")
|
||||
;;; ============================================================
|
||||
|
||||
(vl-load-com)
|
||||
|
||||
;;; ------------------------------------------------------------
|
||||
;;; KONFIGURATION (bei Bedarf anpassen)
|
||||
;;; KONFIGURATION
|
||||
;;; ------------------------------------------------------------
|
||||
|
||||
;; Toleranzrand um die ILS-Block-Box in Zeichnungseinheiten (mm).
|
||||
;; 0.0 = exakte Box. Groesserer Wert = Sensoren knapp ausserhalb
|
||||
;; werden noch dem ILS-Block zugerechnet.
|
||||
;; Toleranzrand um die Carrier-Box in Zeichnungseinheiten (mm), aus
|
||||
;; cfg/export.cfg [Sensorzuordnung] senstol_mm (Default 0.0 = exakte
|
||||
;; 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))
|
||||
|
||||
;; Blockname-Muster (wcmatch, Grossschreibung) fuer die manuell
|
||||
;; platzierten Sensoren.
|
||||
(setq *scanner-pattern* "SCANNER,SCANNER_*")
|
||||
(setq *separator-pattern* "SEPARATOR_SP,SEPARATOR_SP_*")
|
||||
;; Attribut-Tag im Scanner-/Separator-Block, in das die ID des
|
||||
;; zugeordneten Carriers geschrieben wird.
|
||||
(setq *zuordnung-tag* "ZUORDNUNG")
|
||||
|
||||
;; Blockname-Muster fuer die INTERN im ILS-Block (in der Kette)
|
||||
;; gezeichneten Separatoren. Diese bilden die Basis fuer
|
||||
;; ANZAHL_SEPARATOR und werden bei jedem Lauf frisch gezaehlt.
|
||||
(setq *intern-separator-pattern* "STAUSTRECKE_SEPARATOR_SP*")
|
||||
|
||||
;; Attribut-Tag im Scanner-/Separator-Block, in das die Bezeichnung
|
||||
;; des zugeordneten ILS-Blocks geschrieben wird (Gross/Klein egal).
|
||||
(setq *zuordnung-tag* "zuordnung")
|
||||
|
||||
;; Markierung nicht zugeordneter Sensoren: Kreis auf eigenem Layer.
|
||||
;; Markierung von Sensoren ohne jeglichen Carrier: Kreis auf eigenem Layer.
|
||||
(setq *mark-layer* "S_SENSOR_UNZUGEORDNET")
|
||||
(setq *mark-color* 2) ;; 2 = Gelb
|
||||
;; Kreisradius = Faktor * halbe XY-Diagonale der Sensor-Box,
|
||||
@@ -65,19 +92,32 @@
|
||||
(if (null *mark-radius-factor*) (setq *mark-radius-factor* 1.5))
|
||||
(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
|
||||
;;; Alle ILS-Bloecke (Kreisel / VF / GF) verwenden einheitlich
|
||||
;;; ANZAHL_SCANNER und ANZAHL_SEPARATOR.
|
||||
;;; Rueckgabe: (scanner-tag separator-tag) oder nil
|
||||
;;; Carrier-/Sensor-Erkennung ueber die gemeinsamen Muster aus
|
||||
;;; cfg/export.cfg [blockpattern] (export:pattern, siehe export.lsp) -
|
||||
;;; dieselben Muster wie csv:collect-export-blocks/export_csv.py.
|
||||
;;; ------------------------------------------------------------
|
||||
(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))
|
||||
(if (or (wcmatch up "KREISEL_*")
|
||||
(wcmatch up "VF_*")
|
||||
(wcmatch up "GF_*"))
|
||||
(list "ANZAHL_SCANNER" "ANZAHL_SEPARATOR")
|
||||
nil
|
||||
(or (wcmatch up (export:pattern "pattern_kreisel" "KR_*,KREISEL_*,ECKRAD_*"))
|
||||
(wcmatch up (export:pattern "pattern_variofoerderer" "VF_*"))
|
||||
(wcmatch up (export:pattern "pattern_gefaellestrecke" "GF_*"))
|
||||
)
|
||||
)
|
||||
|
||||
@@ -88,26 +128,12 @@
|
||||
(defun cs-sensor-kind (nm / up)
|
||||
(setq up (strcase nm))
|
||||
(cond
|
||||
((wcmatch up *scanner-pattern*) 'scanner)
|
||||
((wcmatch up *separator-pattern*) 'separator)
|
||||
((wcmatch up (strcase (export:pattern "pattern_scanner" "Scanner*"))) 'scanner)
|
||||
((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)
|
||||
)
|
||||
)
|
||||
|
||||
;;; ------------------------------------------------------------
|
||||
;;; Bounding-Box eines INSERT holen (WCS, achsparallel).
|
||||
;;; Erzwingt vorher ein vla-update (Regen des Objekts), da
|
||||
@@ -116,6 +142,15 @@
|
||||
;;; Rueckgabe: (minx miny maxx maxy) oder nil bei Fehler.
|
||||
;;; *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)
|
||||
(setq *cs-last-error* nil)
|
||||
(setq obj (vlax-ename->vla-object ent))
|
||||
@@ -157,8 +192,8 @@
|
||||
)
|
||||
|
||||
;;; ------------------------------------------------------------
|
||||
;;; Liegt Punkt pt (X/Y) in ILS-Block-Record rec (mit Toleranz)?
|
||||
;;; rec = (ename tagScan tagSep minx miny maxx maxy cx cy)
|
||||
;;; Liegt Punkt pt (X/Y) in Carrier-Record rec (mit Toleranz)?
|
||||
;;; rec = (ename tagScan tagSep minx miny maxx maxy cx cy id)
|
||||
;;; ------------------------------------------------------------
|
||||
(defun cs-in-box (pt rec / x y)
|
||||
(setq x (car pt) y (cadr pt))
|
||||
@@ -246,13 +281,13 @@
|
||||
)
|
||||
|
||||
;;; ------------------------------------------------------------
|
||||
;;; Sensor-Punkt einem ILS-Block zuordnen.
|
||||
;;; Rueckgabe: ILS-Block-Record oder nil (keine Zuordnung).
|
||||
;;; Sensor-Punkt einem Carrier per BBox zuordnen (Schritt 1-3 oben).
|
||||
;;; Rueckgabe: Carrier-Record oder nil (kein BBox-Treffer).
|
||||
;;; Bei mehreren Treffern: naechstes Box-Zentrum (X/Y).
|
||||
;;; grid = Vorsortierung aus cs-grid-build (statt aller Carrier
|
||||
;;; 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)
|
||||
(foreach rec (cs-grid-candidates grid pt)
|
||||
(if (cs-in-box pt rec) (setq matches (cons rec matches))))
|
||||
@@ -270,6 +305,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.
|
||||
;;; ------------------------------------------------------------
|
||||
@@ -309,35 +399,6 @@
|
||||
ok
|
||||
)
|
||||
|
||||
;;; ------------------------------------------------------------
|
||||
;;; Zaehlt rekursiv, wie oft ein Block (Muster pat) in der
|
||||
;;; Definition des Blocks bname verwendet wird - inklusive
|
||||
;;; verschachtelter Unterbloecke. Damit wird die interne Anzahl
|
||||
;;; der Kette-Separatoren aus der Geometrie ermittelt.
|
||||
;;; ------------------------------------------------------------
|
||||
(defun cs-count-nested (bname pat / e ed nm n stop)
|
||||
(setq n 0 stop nil)
|
||||
(setq e (tblobjname "BLOCK" bname))
|
||||
(if e
|
||||
(progn
|
||||
(setq e (entnext e))
|
||||
(while (and e (not stop))
|
||||
(setq ed (entget e))
|
||||
(cond
|
||||
((= (cdr (assoc 0 ed)) "ENDBLK") (setq stop t))
|
||||
((= (cdr (assoc 0 ed)) "INSERT")
|
||||
(setq nm (cdr (assoc 2 ed)))
|
||||
(if (wcmatch (strcase nm) pat)
|
||||
(setq n (1+ n))
|
||||
(setq n (+ n (cs-count-nested nm pat)))))
|
||||
)
|
||||
(if (not stop) (setq e (entnext e)))
|
||||
)
|
||||
)
|
||||
)
|
||||
n
|
||||
)
|
||||
|
||||
;;; ------------------------------------------------------------
|
||||
;;; Attributwert (String) an einem INSERT lesen. "" wenn nicht
|
||||
;;; vorhanden. Tag ohne Gross/Klein-Unterscheidung.
|
||||
@@ -363,8 +424,9 @@
|
||||
)
|
||||
|
||||
;;; ------------------------------------------------------------
|
||||
;;; Bezeichnung eines ILS-Blocks ermitteln: Attribut "Bezeichnung",
|
||||
;;; Fallback auf den Blocknamen.
|
||||
;;; Bezeichnung eines Carriers ermitteln: Attribut "Bezeichnung",
|
||||
;;; Fallback auf den Blocknamen. Nur fuer Konsolen-/Fehlermeldungen -
|
||||
;;; die eigentliche Verknuepfung (ZUORDNUNG) laeuft ueber die ID.
|
||||
;;; ------------------------------------------------------------
|
||||
(defun cs-carrier-label (ent nm / bez)
|
||||
(setq bez (cs-get-att-str ent "Bezeichnung"))
|
||||
@@ -395,7 +457,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
|
||||
;;; (Faktor), mindestens *mark-radius-min*.
|
||||
;;; ------------------------------------------------------------
|
||||
@@ -421,64 +483,166 @@
|
||||
(cons 40 r)))
|
||||
)
|
||||
|
||||
;;; ============================================================
|
||||
;;; HAUPTBEFEHL
|
||||
;;; ============================================================
|
||||
(defun c:ZAEHLE_SEP_SCAN ( / ss i ent ed nm tags bb cx cy label
|
||||
carriers grid scanlist seplist kind pt
|
||||
scanCounts sepCounts
|
||||
rec en nm2 ns nsep internSep newS newP
|
||||
s sent spt
|
||||
n-scan-unassigned n-sep-unassigned
|
||||
n-zuordnung-fehlt mss
|
||||
okS okP)
|
||||
(setq carriers nil scanlist nil seplist nil n-zuordnung-fehlt 0)
|
||||
|
||||
;; Alte Markierungskreise entfernen (Idempotenz)
|
||||
(setq mss (ssget "_X" (list (cons 0 "CIRCLE") (cons 8 *mark-layer*))))
|
||||
(if mss (command "_.ERASE" mss ""))
|
||||
|
||||
;; Vor der Extents-Berechnung einmal regenerieren, damit
|
||||
;; vla-getboundingbox verlaessliche Werte liefert.
|
||||
(vl-catch-all-apply '(lambda () (command "_.REGEN")))
|
||||
|
||||
;; --- 1. Alle INSERTs sammeln und klassifizieren ---
|
||||
;;; ------------------------------------------------------------
|
||||
;;; Schnelltest: Ist ein vollstaendiger cs-zuordnung-lauf ueberhaupt
|
||||
;;; noetig? Der eigentliche Lauf ist teuer (vla-getboundingbox + Regen
|
||||
;;; je Carrier UND je Sensor). Diese Vorpruefung kommt ohne jede
|
||||
;;; Bounding-Box aus - sie liest nur Attribute (entget).
|
||||
;;;
|
||||
;;; Rueckgabe T (Lauf noetig), wenn EINE der Bedingungen zutrifft:
|
||||
;;; a) Ein Scanner-/Separator-Symbol hat ein leeres ZUORDNUNG-Attribut
|
||||
;;; (noch nicht zugeordnet) oder ein ZUORDNUNG, das auf keinen
|
||||
;;; (mehr) existierenden Carrier zeigt.
|
||||
;;; b) An einem Carrier passt ANZAHL_SCANNER nicht zur Anzahl der ihm
|
||||
;;; per ZUORDNUNG zugeschriebenen Scanner-Symbole.
|
||||
;;; c) An einem Carrier passt ANZAHL_SEPARATOR nicht zur Anzahl der ihm
|
||||
;;; per ZUORDNUNG zugeschriebenen Separator-Symbole (nur platzierte
|
||||
;;; Symbole zaehlen - dieselbe Regel wie newP im eigentlichen Lauf;
|
||||
;;; der interne Staustrecke_Separator_SP zaehlt nicht mit).
|
||||
;;; Sonst nil - die gespeicherten Attribute sind konsistent, der teure
|
||||
;;; Lauf wird uebersprungen.
|
||||
;;;
|
||||
;;; Die Zuordnung Symbol->Carrier wird hier billig ueber das bereits
|
||||
;;; gesetzte ZUORDNUNG-Attribut rekonstruiert (Carrier-ID), OHNE die
|
||||
;;; teure Boundingbox-/Distanz-Rechnung des eigentlichen Laufs. Dadurch
|
||||
;;; erkennt der Test - anders als eine reine Gesamtsummen-Pruefung - auch
|
||||
;;; das Verschieben eines Sensors von einem Carrier zu einem anderen
|
||||
;;; (die Per-Carrier-Zahl kippt, ZUORDNUNG zeigt aber noch auf den alten).
|
||||
;;; ------------------------------------------------------------
|
||||
(defun cs-zuordnung-noetig-p ( / ss i ent ed nm sk zuord id
|
||||
carriers carrier-ids sensors s
|
||||
sepByCarrier scanByCarrier
|
||||
noetig expScan expSep rec)
|
||||
(setq noetig nil carriers nil carrier-ids nil sensors nil
|
||||
sepByCarrier nil scanByCarrier nil)
|
||||
(setq ss (ssget "_X" '((0 . "INSERT"))))
|
||||
(if (null ss)
|
||||
(progn (princ "\n>>> Keine Bloecke in der Zeichnung gefunden.") (princ))
|
||||
nil ;; keine Bloecke -> nichts zu tun
|
||||
(progn
|
||||
;; Pass 1: Carrier (ename . id) und Sensor-Symbole (kind . ZUORDNUNG)
|
||||
;; sammeln - die ssget-Reihenfolge ist beliebig, daher erst sammeln,
|
||||
;; dann auswerten.
|
||||
(setq i 0)
|
||||
(while (< i (sslength ss))
|
||||
(setq ent (ssname ss i) ed (entget ent) nm (cdr (assoc 2 ed)))
|
||||
(cond
|
||||
((cs-carrier-p nm)
|
||||
(setq id (cs-get-att-str ent "ID"))
|
||||
(setq carriers (cons (cons ent id) carriers))
|
||||
(setq carrier-ids (cons id carrier-ids)))
|
||||
(t
|
||||
(setq sk (cs-sensor-kind nm))
|
||||
(if sk
|
||||
(setq sensors
|
||||
(cons (cons sk (cs-get-att-str ent *zuordnung-tag*)) sensors))))
|
||||
)
|
||||
(setq i (1+ i))
|
||||
)
|
||||
;; Pass 2: Symbole ueber ZUORDNUNG je Carrier-ID zaehlen. Leeres
|
||||
;; ZUORDNUNG oder ZUORDNUNG auf einen nicht (mehr) existierenden
|
||||
;; Carrier -> Lauf noetig.
|
||||
(foreach s sensors
|
||||
(setq sk (car s) zuord (cdr s))
|
||||
(cond
|
||||
((or (null zuord) (= zuord "")) (setq noetig T))
|
||||
((not (member zuord carrier-ids)) (setq noetig T))
|
||||
((eq sk 'scanner) (setq scanByCarrier (cs-bump scanByCarrier zuord)))
|
||||
(t (setq sepByCarrier (cs-bump sepByCarrier zuord)))
|
||||
)
|
||||
)
|
||||
;; Pass 3: je Carrier Soll (= zugeschriebene Symbole) gegen die
|
||||
;; gespeicherten Attribute pruefen.
|
||||
(if (not noetig)
|
||||
(foreach rec carriers
|
||||
(setq id (cdr rec)) ;; rec = (ename . carrier-id)
|
||||
(setq expScan (cond ((assoc id scanByCarrier) (cdr (assoc id scanByCarrier))) (t 0)))
|
||||
(setq expSep (cond ((assoc id sepByCarrier) (cdr (assoc id sepByCarrier))) (t 0)))
|
||||
(if (or (/= (atoi (cs-get-att-str (car rec) "ANZAHL_SCANNER")) expScan)
|
||||
(/= (atoi (cs-get-att-str (car rec) "ANZAHL_SEPARATOR")) expSep))
|
||||
(setq noetig T))
|
||||
)
|
||||
)
|
||||
noetig
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;;; ============================================================
|
||||
;;; 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 cs-zuordnung-lauf (label verbose /
|
||||
mss ss i ent ed nm bb cx cy lbl carrier-id
|
||||
carriers grid scanlist seplist sk pt
|
||||
scanCounts sepCounts n-scan-unassigned n-sep-unassigned
|
||||
n-strittig n-zuordnung-fehlt
|
||||
s sent spt res mode rec best-d second-rec second-d
|
||||
scanner-id contested handle
|
||||
en nm2 ns nsep newS newP okS okP eintrag)
|
||||
(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 - 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*))))
|
||||
(if mss (command "_.ERASE" mss ""))
|
||||
(vl-catch-all-apply '(lambda () (command "_.REGEN")))
|
||||
|
||||
(princ (ssg-textf "sens-start" (list label)))
|
||||
|
||||
(setq ss (ssget "_X" '((0 . "INSERT"))))
|
||||
(if (null ss)
|
||||
(princ (ssg-textf "sens-no-inserts" (list label)))
|
||||
(progn
|
||||
(setq i 0)
|
||||
(while (< i (sslength ss))
|
||||
(setq ent (ssname ss i))
|
||||
(setq ed (entget ent))
|
||||
(setq nm (cdr (assoc 2 ed)))
|
||||
(setq tags (cs-carrier-tags nm))
|
||||
(cond
|
||||
;; --- ILS-Block ---
|
||||
(tags
|
||||
((cs-carrier-p nm)
|
||||
(setq bb (cs-bbox ent))
|
||||
(if bb
|
||||
(progn
|
||||
(setq cx (/ (+ (nth 0 bb) (nth 2 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
|
||||
(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)
|
||||
cx cy label)
|
||||
cx cy carrier-id lbl)
|
||||
carriers)))
|
||||
(princ (strcat "\n! Bounding-Box fehlgeschlagen fuer ILS-Block '" nm "'"
|
||||
(if *cs-last-error*
|
||||
(strcat " (" *cs-last-error* ")") "")))
|
||||
(princ (ssg-textf "sens-bbox-fehler" (list nm)))
|
||||
)
|
||||
)
|
||||
;; --- Sensor (Entity + Referenzpunkt merken) ---
|
||||
(t
|
||||
(setq kind (cs-sensor-kind nm))
|
||||
(if kind
|
||||
(setq sk (cs-sensor-kind nm))
|
||||
(if sk
|
||||
(progn
|
||||
(setq pt (cs-sensor-point ent ed kind))
|
||||
(if (eq kind 'scanner)
|
||||
(setq pt (cs-sensor-point ent ed sk))
|
||||
(if (eq sk 'scanner)
|
||||
(setq scanlist (cons (list ent pt) scanlist))
|
||||
(setq seplist (cons (list ent pt) seplist)))))
|
||||
)
|
||||
@@ -486,99 +650,145 @@
|
||||
(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 scanCounts nil sepCounts nil
|
||||
n-scan-unassigned 0 n-sep-unassigned 0)
|
||||
(setq scanCounts nil sepCounts nil)
|
||||
|
||||
;; --- Scanner zuordnen (inkl. Distanz-Fallback + Strittig-Erkennung) ---
|
||||
(foreach s scanlist
|
||||
(setq sent (car s) spt (cadr s))
|
||||
(setq rec (cs-assign spt grid))
|
||||
(if rec
|
||||
(progn
|
||||
(setq scanCounts (cs-bump scanCounts (car rec)))
|
||||
(if (not (cs-set-att sent *zuordnung-tag* (nth 9 rec)))
|
||||
(setq n-zuordnung-fehlt (1+ n-zuordnung-fehlt))))
|
||||
(progn
|
||||
(setq n-scan-unassigned (1+ n-scan-unassigned))
|
||||
(cs-set-att sent *zuordnung-tag* "")
|
||||
(cs-mark-unassigned sent))))
|
||||
|
||||
(foreach s seplist
|
||||
(setq sent (car s) spt (cadr s))
|
||||
(setq rec (cs-assign spt grid))
|
||||
(if rec
|
||||
(progn
|
||||
(setq sepCounts (cs-bump sepCounts (car rec)))
|
||||
(if (not (cs-set-att sent *zuordnung-tag* (nth 9 rec)))
|
||||
(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 ---
|
||||
(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
|
||||
(setq en (car rec))
|
||||
(setq nm2 (cdr (assoc 2 (entget en))))
|
||||
(setq ns (cond ((assoc en scanCounts) (cdr (assoc en scanCounts))) (t 0)))
|
||||
(setq nsep (cond ((assoc en sepCounts) (cdr (assoc en sepCounts))) (t 0)))
|
||||
;; interne Kette-Separatoren frisch aus der Blockdefinition zaehlen
|
||||
(setq internSep (cs-count-nested nm2 *intern-separator-pattern*))
|
||||
;; Scanner = nur neu zugeordnete
|
||||
;; Separator = interne Kette-Separatoren + neu zugeordnete
|
||||
(setq newS ns)
|
||||
(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 okP (cs-set-att en (nth 2 rec) (itoa newP)))
|
||||
(if (and okS okP)
|
||||
(princ (strcat "\n -> geschrieben: "
|
||||
"ANZAHL_SCANNER=" (itoa newS)
|
||||
", ANZAHL_SEPARATOR=" (itoa newP)))
|
||||
(princ (strcat "\n -> FEHLER beim Schreiben: "
|
||||
(if okS "" "ANZAHL_SCANNER fehlt ")
|
||||
(if okP "" "ANZAHL_SEPARATOR fehlt"))))
|
||||
(setq res (cs-resolve-sensor sent spt carriers grid))
|
||||
(setq mode (nth 0 res) rec (nth 1 res)
|
||||
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)))
|
||||
(if (member mode '(bbox distance))
|
||||
(if (not (cs-set-att sent *zuordnung-tag* (nth 9 rec)))
|
||||
(setq n-zuordnung-fehlt (1+ n-zuordnung-fehlt))))
|
||||
(if (eq mode 'distance)
|
||||
(progn
|
||||
(setq scanner-id (cs-get-att-str sent "ID"))
|
||||
(setq contested (and second-rec
|
||||
(<= (- 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*))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(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.")))
|
||||
(setq *cs-scanner-ergaenzt* (reverse *cs-scanner-ergaenzt*))
|
||||
|
||||
;; --- 4. Zeichnung speichern ---
|
||||
(princ "\n--------------------------------------------")
|
||||
(princ "\n Speichere Zeichnung (QSAVE) ...")
|
||||
(command "_.QSAVE")
|
||||
(princ "\n>>> Fertig.")
|
||||
(princ)
|
||||
;; --- 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
|
||||
(setq sent (car s) spt (cadr s))
|
||||
(setq res (cs-resolve-sensor sent spt carriers grid))
|
||||
(setq mode (nth 0 res) rec (nth 1 res))
|
||||
(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)))
|
||||
(if (member mode '(bbox distance))
|
||||
(if (not (cs-set-att sent *zuordnung-tag* (nth 9 rec)))
|
||||
(setq n-zuordnung-fehlt (1+ n-zuordnung-fehlt))))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; --- ANZAHL_SCANNER/ANZAHL_SEPARATOR je Carrier schreiben ---
|
||||
(foreach rec carriers
|
||||
(setq en (car rec))
|
||||
(setq nm2 (cdr (assoc 2 (entget en))))
|
||||
(setq ns (cond ((assoc en scanCounts) (cdr (assoc en scanCounts))) (t 0)))
|
||||
(setq nsep (cond ((assoc en sepCounts) (cdr (assoc en sepCounts))) (t 0)))
|
||||
(setq newS ns)
|
||||
;; ANZAHL_SEPARATOR = nur die tatsaechlich platzierten Separator-
|
||||
;; Symbole (Separator_SP/S-LP), die diesem Carrier zugeordnet sind.
|
||||
;; Der intern in der GF/VF-Kette gezeichnete 300-mm-Block
|
||||
;; Staustrecke_Separator_SP ist nur ein Kettenglied (Foerder-/
|
||||
;; Uebergabestueck), KEIN eigenstaendiger Separator - er wird bewusst
|
||||
;; NICHT mitgezaehlt (Entscheidung: nur platzierte Symbole zaehlen).
|
||||
(setq newP nsep)
|
||||
(setq okS (cs-set-att en (nth 1 rec) (itoa newS)))
|
||||
(setq okP (cs-set-att en (nth 2 rec) (itoa newP)))
|
||||
(if verbose
|
||||
(princ (ssg-textf "sens-carrier-zeile"
|
||||
(list nm2 (nth 9 rec) (itoa newS) (itoa newP)))))
|
||||
(if (not (and okS okP))
|
||||
(princ (ssg-textf "sens-carrier-fehler" (list nm2))))
|
||||
)
|
||||
|
||||
;; --- Zusammenfassung ---
|
||||
(princ (ssg-textf "sens-summary"
|
||||
(list label (itoa (length carriers))
|
||||
(itoa (length scanlist)) (itoa n-scan-unassigned)
|
||||
(itoa (length seplist)) (itoa n-sep-unassigned))))
|
||||
|
||||
(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)
|
||||
)
|
||||
|
||||
;;; ============================================================
|
||||
;;; 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)
|
||||
|
||||
+36
-1
@@ -463,7 +463,7 @@
|
||||
;; csv:get-k-kos-strings) werden immer geschrieben, unabhaengig von
|
||||
;; 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
|
||||
insert-quat insert-kos k-list)
|
||||
insert-quat insert-kos k-list warnung-json warnung-eintrag)
|
||||
(setq ed (entget ename))
|
||||
(setq blk-name (cdr (assoc 2 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
|
||||
" {\"block_name\":\"" (csv:json-escape blk-name) "\""
|
||||
",\"layer\":\"" (csv:json-escape layer) "\""
|
||||
@@ -521,6 +532,7 @@
|
||||
",\"k3\":\"" (csv:k-kos k-list "K3") "\""
|
||||
",\"k4\":\"" (csv:k-kos k-list "K4") "\""
|
||||
bbox-json
|
||||
warnung-json
|
||||
"}"
|
||||
)
|
||||
)
|
||||
@@ -615,6 +627,29 @@
|
||||
;; Vor dem Export HOEHE/DREHUNG aller Omniflo-Elemente aktualisieren
|
||||
(princ (ssg-textf "exp-update-hoehe-drehung" (list label)))
|
||||
(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).
|
||||
;;
|
||||
;; Der Lauf ist teuer (Boundingbox+Regen je Carrier und Sensor),
|
||||
;; darum vorher der billige Schnelltest cs-zuordnung-noetig-p (nur
|
||||
;; Attribute lesen, keine Boundingboxen): nur bei leeren ZUORDNUNG-
|
||||
;; Eintraegen oder abweichenden Summen wird tatsaechlich neu gerechnet.
|
||||
(ssg-ensure "count_sep_scan")
|
||||
(if (atoms-family 1 '("cs-zuordnung-lauf"))
|
||||
(if (cs-zuordnung-noetig-p)
|
||||
(cs-zuordnung-lauf label nil)
|
||||
(princ (ssg-textf "sens-skip" (list label)))
|
||||
)
|
||||
)
|
||||
(princ (ssg-textf "exp-collect-blocks" (list label)))
|
||||
|
||||
(setq ss (csv:collect-export-blocks))
|
||||
|
||||
@@ -157,3 +157,24 @@ bb_minimum_height_mm=1
|
||||
# Linie durch beide Stationsmitten) - genau diese Linie trennt links/rechts.
|
||||
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
|
||||
|
||||
|
||||
+699
-686
File diff suppressed because it is too large
Load Diff
+699
-686
File diff suppressed because it is too large
Load Diff
@@ -27,6 +27,13 @@ Warnungen = Spalte fuer Auffaelligkeiten. Aktuell: eine Strecke sollte genau
|
||||
zwei Kreisel (Anfang + Ende) beruehren - beruehrt ihre (in x/y gepruefte)
|
||||
Bounding-Box mehr, steht hier ein Hinweis und es wird zusaetzlich eine
|
||||
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:
|
||||
python export_csv.py <export_raw.json> <data_dir> <output.csv>
|
||||
@@ -84,6 +91,15 @@ EXPORTCSV vorhanden (nicht EXPORTSIVAS) - siehe csv:run-export. Insertpoint/
|
||||
K1-K4 stehen zwar in export_raw.json fuer jeden Export zur Verfuegung (siehe
|
||||
csv:block-to-json), werden aber ebenfalls nur von diesem Skript (EXPORTCSV)
|
||||
als CSV-Spalten ausgegeben.
|
||||
|
||||
Reihenfolge/Elementnummer: die Zeilen werden am Ende aufsteigend nach
|
||||
TeileId sortiert (numerische IDs) und die Elementnummer (erste Spalte)
|
||||
danach neu von 1 an vergeben (siehe teileid_sort_key in process_blocks) -
|
||||
wurde kein Element geloescht, stimmen Elementnummer und TeileId dadurch
|
||||
ueberein, geloeschte Elemente hinterlassen Luecken in der TeileId-Folge.
|
||||
Zeilen ohne numerische TeileId (Omniflo-Sum-Zeile, SEP-/SCN-Fallback-IDs
|
||||
ohne ID-Attribut) behalten stabil ihre bisherige Reihenfolge und stehen
|
||||
danach.
|
||||
"""
|
||||
|
||||
import json
|
||||
@@ -756,6 +772,13 @@ def process_blocks(blocks, lookup, dbg=None):
|
||||
"bezeichnung": f"Scanner :{scanner_count}",
|
||||
"planquadrat": planquadrat_column(block, planquadrat_cfg),
|
||||
"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),
|
||||
})
|
||||
continue
|
||||
@@ -816,6 +839,22 @@ def process_blocks(blocks, lookup, dbg=None):
|
||||
elem_nr = build_kreisel_weiche_items(items, planquadrat_cfg, elem_nr, dbg=dbg)
|
||||
build_strecke_schleus_items(items, planquadrat_cfg, elem_nr, dbg=dbg)
|
||||
|
||||
# Nach dem Sammelheimen aller Zeilen: sortiert nach TeileId ausgeben, damit
|
||||
# Elementnummer (erste Spalte) und TeileId nach Moeglichkeit uebereinstimmen
|
||||
# (siehe format_csv_line/Elementnummer-Neuvergabe unten). Numerische IDs
|
||||
# zuerst aufsteigend; nicht-numerische IDs (z.B. "autogenerated_of_json"
|
||||
# der Omniflo-Sum-Zeile oder SEP-/SCN-Fallback-IDs ohne ID-Attribut)
|
||||
# behalten stabil ihre bisherige Reihenfolge und stehen danach. Wurde kein
|
||||
# Element geloescht, ergibt sich dadurch Elementnummer == TeileId.
|
||||
def teileid_sort_key(indexed_item):
|
||||
index, item = indexed_item
|
||||
tid = str(item.get("teileid", "")).strip()
|
||||
return (0, int(tid)) if tid.isdigit() else (1, index)
|
||||
|
||||
items = [item for _, item in sorted(enumerate(items), key=teileid_sort_key)]
|
||||
for i, item in enumerate(items, start=1):
|
||||
item["nr"] = i
|
||||
|
||||
return items
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -135,7 +135,7 @@
|
||||
[Verbindung bearbeiten]^C^C(ssg-ensure "Connection_Edit") CONNECTION_EDIT
|
||||
[<-Bearbeiten (Auto)]^C^C(ssg-ensure "SSG_LIB_Commands") SSG_BLOCKEDIT
|
||||
[->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
|
||||
[->Konfiguration]
|
||||
[Umschalten 2D und 3D]^C^C(ssg-ensure "SSG_LIB_Commands") SSG_DIM_SWITCH
|
||||
|
||||
Reference in New Issue
Block a user