Aufbau der Planquadrate nur durch Boundingboxen. Ansonsten werden die Bereiche der Lage nicht korrekt erzeugt
This commit is contained in:
@@ -107,7 +107,7 @@ Detaillierte Dokumentation aller Funktionen und Befehle: siehe `Lisp/README.md`.
|
||||
| `SSG_LIB_Commands.lsp` | ILS_BTMT_Beladung, ILS_BTMT_Entladung, ILS_SCANNER_INSERT, ILS_SEPARATOR_INSERT, ILS_EINGANG_INSERT, ILS_AUSGANG_INSERT, ILS_ETF_*, ILS_GK*_*, SSG_BLOCKEDIT, SSG_DIM_SWITCH, SSG_SPRACHE | BTMT Be-/Entladung (`ils-insert-station`: wiederholtes Einfuegen von `BTMT-Beladung` bzw. `SC_Entladung`, Drehung interaktiv, Layer aus `LAYER`-Attribut, Dimension via `ssg-ils-block-laden`) + Sensoren (`ils-insert-sensor`) + Eingang-/Ausgang-Symbol (frei platzierbar wie BTMT Be-/Entladung, ueber `ils-insert-station` mit den Rohnamen `Eingang`/`Ausgang`, Bloecke `Eingang_<DIM>.dwg`/`Ausgang_<DIM>.dwg` in data/ils) + Dummy-Befehle fuer Menue + Doppelklick/Kontextmenue-Dispatcher + Konfiguration (2D/3D, Sprache) |
|
||||
| `Tro_Edit.lsp` | TRO_INSERT, TRO_EDIT | TRO-Marker (Block `TRO_SYM_<Typ>`) fuer sps_skel (lib/tro_annotate.py): TRO_INSERT fuegt eine bestehende Blockdefinition an einem gewaehlten Punkt ein und setzt ID/TYPE (bricht ab, wenn der Typ noch keine Blockdefinition in der Zeichnung hat - die entsteht nur ueber tro_annotate.py); TRO_EDIT aendert ID/TYPE eines bestehenden Markers per Dialog. Typliste aus `tro_types.lsp` (von `tro_annotate.py --emit-lisp` nach DXFM_LISP geschrieben). Der Dispatcher SSG_BLOCKEDIT leitet Blocknamen `TRO_*` zu TRO_EDIT. |
|
||||
| `menu-inventory.lsp` | MenuInventory | BricsCAD Diagnostik (Menuegruppen, Plugins, Startdateien) |
|
||||
| `DrawPlanquadrate.lsp` | DRAW_PLANQUADRATE, DELETE_PLANQUADRATE, PLANQUADRATE_TOGGLE | Zeichnet auf Z=0 ein Planquadrat-Linienraster (senkrecht/waagerecht) ueber die aktuellen Zeichnungs-Extents, im Abstand/Zaehlschema der aktiven `[Planquadrate]`-Konfiguration aus `cfg/export.cfg` (dieselbe Quelle wie `lib/export_planquadrat.py` fuer den CSV-Export) - Ursprung (Index 1) aus `x_origin`/`y_origin` bzw. Fallback EXTMIN. Spalten-/Zeilenzahl wird IMMER aufgerundet auf volle Rasterschritte (nicht auf die exakte Extent-Grenze), damit alle senkrechten Linien auf der letzten waagerechten enden und umgekehrt - das Raster bildet immer ein geschlossenes Rechteck. Zaehlung (alphabetisch/numerisch je Achse) als Text am linken/unteren Rand. Das fertige Raster (Linien+Texte) wird per `_.-BLOCK`/`_.INSERT` zu einem einzigen Block `ZZ_PLANQUADRATE` bei (0,0,0) zusammengefasst. Layer aus `cfg/layer.cfg` (`[allgemein]` Key `planquadrate`, Fallback `ZZ_Planquadrate`). DRAW_PLANQUADRATE entfernt vor dem Neuaufbau zuerst einen evtl. vorhandenen Block (`plq-block-entfernen`: INSERTs loeschen + `_-PURGE _B`), DELETE_PLANQUADRATE ruft nur diese Entfernung auf. PLANQUADRATE_TOGGLE ("Planquadrate an/aus", Menue: Konfiguration) prueft per `tblsearch`/`ssget "X"`, ob der Block existiert, und dispatcht auf Zeichnen bzw. Loeschen. Lazy geladen ueber `(ssg-ensure "DrawPlanquadrate")`, nicht in der Core-Ladereihenfolge. |
|
||||
| `DrawPlanquadrate.lsp` | DRAW_PLANQUADRATE, DELETE_PLANQUADRATE, PLANQUADRATE_TOGGLE | Zeichnet auf Z=0 ein Planquadrat-Linienraster (senkrecht/waagerecht), im Abstand/Zaehlschema der aktiven `[Planquadrate]`-Konfiguration aus `cfg/export.cfg` (dieselbe Quelle wie `lib/export_planquadrat.py` fuer den CSV-Export). Bereich kommt NICHT aus den Zeichnungs-Extents, sondern aus derselben Blockmenge wie EXPORTCSV (`csv:collect-export-blocks`, export.lsp; siehe `plq-export-bbox`): Ursprung (Index 1) UND obere Grenze kommen BEIDE aus der tatsaechlichen Bounding-Box jedes Blocks (`csv:get-bbox`, wie `bbox_columns()`/`planquadrat_column()`/`_bbox_min()` in `lib/export_csv.py` bzw. `lib/export_planquadrat.py`), NICHT aus dem reinen Einfuegepunkt - bei einem gedrehten/exzentrisch eingefuegten Block (z.B. ein um 90 Grad gedrehter Kreisel) kann das Bounding-Box-Zentrum weit vom Einfuegepunkt abweichen; Ursprung und Zellzuordnung muessen auf derselben Referenz beruhen, sonst driften sie auseinander (realer Bug, behoben). Reine Hilfsgeometrie (Kreisel-Umfahrungsboegen als eigene Linien, Texte) zaehlt bewusst nicht mit, sonst weicht das Raster vom CSV-Export ab. `x_origin`/`y_origin` ueberschreiben den Ursprung, Fallback auf EXTMIN/EXTMAX falls keine Export-Bloecke vorhanden sind bzw. `csv:get-bbox` fuer einen Block scheitert. Spalten-/Zeilenzahl wird IMMER aufgerundet auf volle Rasterschritte, damit alle senkrechten Linien auf der letzten waagerechten enden und umgekehrt - das Raster bildet immer ein geschlossenes Rechteck. Zaehlung (alphabetisch/numerisch je Achse) als Text am linken/unteren Rand. Das fertige Raster (Linien+Texte) wird per `_.-BLOCK`/`_.INSERT` zu einem einzigen Block `ZZ_PLANQUADRATE` bei (0,0,0) zusammengefasst. Layer aus `cfg/layer.cfg` (`[allgemein]` Key `planquadrate`, Fallback `ZZ_Planquadrate`). DRAW_PLANQUADRATE entfernt vor dem Neuaufbau zuerst einen evtl. vorhandenen Block (`plq-block-entfernen`: INSERTs loeschen + `_-PURGE _B`), DELETE_PLANQUADRATE ruft nur diese Entfernung auf. PLANQUADRATE_TOGGLE ("Planquadrate an/aus", Menue: Konfiguration) prueft per `tblsearch`/`ssget "X"`, ob der Block existiert, und dispatcht auf Zeichnen bzw. Loeschen. Lazy geladen ueber `(ssg-ensure "DrawPlanquadrate")`, nicht in der Core-Ladereihenfolge. Die Planquadrat-SPALTE im CSV-Export (`export_csv.py::planquadrat_column`/`resolve_origins`, `lib/export_planquadrat.py::compute_planquadrat`/`_bbox_min`) rechnet ebenfalls durchgaengig auf Bounding-Box-Basis (nicht nur Einfuegepunkt) und liefert eine SPANNE ("A/1-J/1") statt nur einer Zelle, wenn ein Element mehr als eine Zelle ueberdeckt (Kreisel, lange VF-/GF-Ketten). |
|
||||
|
||||
## DCL-Dialoge
|
||||
|
||||
|
||||
+101
-15
@@ -10,15 +10,33 @@
|
||||
;; je Spalte die zugehoerige Zaehlung (alphabetisch oder numerisch, je nach
|
||||
;; x_description/y_description).
|
||||
;;
|
||||
;; Bereich: die aktuellen Zeichnungs-Extents (EXTMIN/EXTMAX), aber IMMER auf
|
||||
;; ein ganzzahliges Vielfaches der Schrittweite ab dem Ursprung aufgerundet -
|
||||
;; das Raster bildet also stets ein GESCHLOSSENES Rechteck: jede senkrechte
|
||||
;; Linie endet exakt auf der letzten waagerechten und umgekehrt (kein
|
||||
;; "Ueberstand" einzelner Linien ueber die letzte volle Zeile/Spalte hinaus).
|
||||
;; Bereich: aus den EXPORTIERTEN Bloecken (dieselbe Blockmenge, die
|
||||
;; csv:collect-export-blocks in export.lsp fuer EXPORTCSV sammelt - siehe
|
||||
;; plq-export-bbox), NICHT die Zeichnungs-Extents (EXTMIN/EXTMAX). Ursprung
|
||||
;; (Index 1) UND obere Grenze kommen BEIDE aus der tatsaechlichen Bounding-Box
|
||||
;; jedes Blocks (csv:get-bbox, dieselbe wie bbox_columns()/
|
||||
;; planquadrat_column()/_bbox_min() in lib/export_csv.py bzw.
|
||||
;; lib/export_planquadrat.py), NICHT aus dem reinen Einfuegepunkt: bei einem
|
||||
;; gedrehten oder exzentrisch eingefuegten Block (z.B. ein um 90 Grad
|
||||
;; gedrehter Kreisel, dessen Insertpunkt an einem Rand statt der Mitte liegt)
|
||||
;; kann das Bounding-Box-Zentrum weit vom Einfuegepunkt abweichen - Ursprung
|
||||
;; und Zellzuordnung MUESSEN auf derselben Referenz beruhen, sonst driften sie
|
||||
;; auseinander (realer Bug: ein Kreisel landete dadurch in der CSV-Spalte
|
||||
;; "F/3-G/13" statt der laut Zeichnung korrekten Spalte A). Reine
|
||||
;; Hilfsgeometrie (Kreisel-Umfahrungsboegen als eigene Linien, Texte, das
|
||||
;; Planquadrat-Raster selbst) zaehlt zu EXTMIN/EXTMAX, gehoert aber zu keinem
|
||||
;; Export-Block - das BricsCAD-Raster muss daher auf derselben Blockmenge wie
|
||||
;; der CSV-Export rechnen, sonst landet ein Bauteil im CSV in einer anderen
|
||||
;; Spalte/Zeile als im Raster in der Zeichnung.
|
||||
;; Der Bereich wird IMMER auf ein ganzzahliges Vielfaches der Schrittweite ab
|
||||
;; dem Ursprung aufgerundet - das Raster bildet also stets ein GESCHLOSSENES
|
||||
;; Rechteck: jede senkrechte Linie endet exakt auf der letzten waagerechten
|
||||
;; und umgekehrt (kein "Ueberstand" einzelner Linien ueber die letzte volle
|
||||
;; Zeile/Spalte hinaus).
|
||||
;; x_origin/y_origin aus [Planquadrate] legen die Koordinate von Index 1 fest
|
||||
;; (wie im CSV-Export); sind sie leer, faellt der Ursprung auf EXTMIN zurueck
|
||||
;; (= kleinstes X/Y der Zeichnung, analog zur Auto-Ermittlung in
|
||||
;; export_planquadrat.resolve_origins).
|
||||
;; (wie im CSV-Export) und ueberschreiben den automatisch ermittelten
|
||||
;; Ursprung. Fallback auf EXTMIN/EXTMAX, falls keine exportfaehigen Bloecke in
|
||||
;; der Zeichnung stehen.
|
||||
;;
|
||||
;; Das fertige Raster (Linien + Beschriftungstexte) wird zu EINEM Block
|
||||
;; (*plq-blockname*) zusammengefasst und bei (0,0,0) eingefuegt - dadurch
|
||||
@@ -108,6 +126,60 @@
|
||||
(if pos (vl-string-trim " \t" (substr s 1 pos)) (vl-string-trim " \t" s))
|
||||
)
|
||||
|
||||
;; Ursprung + Ausdehnung aus den EXPORTIERTEN Bloecken ermitteln - dieselbe
|
||||
;; Blockmenge, die csv:collect-export-blocks (export.lsp) fuer EXPORTCSV
|
||||
;; sammelt. Der reine EXTMIN/EXTMAX der Zeichnung (alle Entities, auch
|
||||
;; Hilfsgeometrie wie Kreisel-Umfahrungsboegen) weicht davon ab und fuehrte zu
|
||||
;; einem im BricsCAD-Raster verschobenen Planquadrat gegenueber der CSV-Spalte
|
||||
;; - siehe cfg/export.cfg [Planquadrate] und den Hinweis oben in der
|
||||
;; Moduldoku. Sowohl Ursprung als auch obere Grenze kommen aus der
|
||||
;; tatsaechlichen Bounding-Box (csv:get-bbox, dieselbe wie
|
||||
;; bbox_columns()/planquadrat_column()/_bbox_min() in lib/export_csv.py bzw.
|
||||
;; lib/export_planquadrat.py), NICHT aus dem reinen Einfuegepunkt: bei einem
|
||||
;; gedrehten oder exzentrisch eingefuegten Block (z.B. ein um 90 Grad
|
||||
;; gedrehter Kreisel, dessen Insertpunkt an einem Rand statt der Mitte liegt)
|
||||
;; kann das BBox-Zentrum weit vom Einfuegepunkt abweichen - Ursprung und
|
||||
;; Zellzuordnung MUESSEN auf derselben Referenz beruhen, sonst driften sie
|
||||
;; auseinander (genau der Bug, der zur Einfuehrung von plq-export-bbox
|
||||
;; fuehrte). Fallback auf den Einfuegepunkt (Gruppencode 10) nur, wenn
|
||||
;; csv:get-bbox fuer einen Block scheitert (z.B. auf eingefrorenem Layer).
|
||||
;; Rueckgabe: Liste (xmin ymin xmax ymax) oder nil, wenn keine Bloecke.
|
||||
(defun plq-export-bbox ( / ss i ename ed pt bbox xmin ymin xmax ymax)
|
||||
(setq ss (csv:collect-export-blocks))
|
||||
(if ss
|
||||
(progn
|
||||
(setq i 0)
|
||||
(while (setq ename (ssname ss i))
|
||||
(setq ed (entget ename))
|
||||
(setq pt (cdr (assoc 10 ed)))
|
||||
(setq bbox (csv:get-bbox ename))
|
||||
(if bbox
|
||||
(progn
|
||||
(setq xmin (if xmin (min xmin (- (nth 0 bbox) (/ (nth 3 bbox) 2.0)))
|
||||
(- (nth 0 bbox) (/ (nth 3 bbox) 2.0))))
|
||||
(setq ymin (if ymin (min ymin (- (nth 1 bbox) (/ (nth 4 bbox) 2.0)))
|
||||
(- (nth 1 bbox) (/ (nth 4 bbox) 2.0))))
|
||||
(setq xmax (if xmax (max xmax (+ (nth 0 bbox) (/ (nth 3 bbox) 2.0)))
|
||||
(+ (nth 0 bbox) (/ (nth 3 bbox) 2.0))))
|
||||
(setq ymax (if ymax (max ymax (+ (nth 1 bbox) (/ (nth 4 bbox) 2.0)))
|
||||
(+ (nth 1 bbox) (/ (nth 4 bbox) 2.0))))
|
||||
)
|
||||
(if pt
|
||||
(progn
|
||||
(setq xmin (if xmin (min xmin (car pt)) (car pt)))
|
||||
(setq ymin (if ymin (min ymin (cadr pt)) (cadr pt)))
|
||||
(setq xmax (if xmax (max xmax (car pt)) (car pt)))
|
||||
(setq ymax (if ymax (max ymax (cadr pt)) (cadr pt)))
|
||||
)
|
||||
)
|
||||
)
|
||||
(setq i (1+ i))
|
||||
)
|
||||
)
|
||||
)
|
||||
(if xmin (list xmin ymin xmax ymax))
|
||||
)
|
||||
|
||||
;; Zeichnet eine Linie auf dem aktuellen Layer.
|
||||
(defun plq-line (p1 p2)
|
||||
(entmake (list
|
||||
@@ -135,7 +207,7 @@
|
||||
;; DRAW_PLANQUADRATE - Raster zeichnen/neu aufbauen
|
||||
;; ============================================================
|
||||
(defun c:DRAW_PLANQUADRATE ( / section x-step x-alpha y-step y-alpha
|
||||
ext-min ext-max x-origin y-origin
|
||||
ext-min ext-max bbox x-origin y-origin
|
||||
x0 y0 x1 y1 lay hoehe n-x n-y i x y
|
||||
label textabstand lastEnt ss e)
|
||||
(ssg-start "DRAW_PLANQUADRATE" '(("OSMODE")))
|
||||
@@ -156,28 +228,42 @@
|
||||
(princ (ssg-text "plq-ungueltige-schrittweite"))
|
||||
(progn
|
||||
;; Vorhandenes Raster zuerst entfernen (Block + Definition) -
|
||||
;; wiederholte Aufrufe erzeugen so keine Dubletten.
|
||||
;; wiederholte Aufrufe erzeugen so keine Dubletten UND ein alter
|
||||
;; Planquadrat-Block verfaelscht nicht die Bloecke-BBox unten
|
||||
;; (Raster-Linien/-Texte zaehlen ohnehin nicht zu den Export-
|
||||
;; Blockmustern, aber so ist es unabhaengig davon sauber).
|
||||
(plq-block-entfernen)
|
||||
|
||||
;; Referenzbereich: dieselbe Blockmenge wie EXPORTCSV
|
||||
;; (csv:collect-export-blocks, export.lsp) - siehe plq-export-bbox.
|
||||
;; Fallback auf die Zeichnungs-Extents (EXTMIN/EXTMAX), falls keine
|
||||
;; exportfaehigen Bloecke in der Zeichnung stehen.
|
||||
(setq bbox (plq-export-bbox))
|
||||
(setq ext-min (getvar "EXTMIN"))
|
||||
(setq ext-max (getvar "EXTMAX"))
|
||||
|
||||
(setq x-origin (export:cfg "Planquadrate" "x_origin" ""))
|
||||
(setq x-origin (if (and x-origin (/= x-origin "")) (* 1000.0 (atof x-origin)) (car ext-min)))
|
||||
(setq x-origin (if (and x-origin (/= x-origin ""))
|
||||
(* 1000.0 (atof x-origin))
|
||||
(if bbox (nth 0 bbox) (car ext-min))
|
||||
))
|
||||
(setq y-origin (export:cfg "Planquadrate" "y_origin" ""))
|
||||
(setq y-origin (if (and y-origin (/= y-origin "")) (* 1000.0 (atof y-origin)) (cadr ext-min)))
|
||||
(setq y-origin (if (and y-origin (/= y-origin ""))
|
||||
(* 1000.0 (atof y-origin))
|
||||
(if bbox (nth 1 bbox) (cadr ext-min))
|
||||
))
|
||||
|
||||
(setq x0 x-origin)
|
||||
(setq y0 y-origin)
|
||||
|
||||
;; Anzahl Spalten/Zeilen: mind. 1, sonst so viele volle Schritte,
|
||||
;; bis die Zeichnungs-Extents (mind.) abgedeckt sind - AUFGERUNDET,
|
||||
;; bis der Referenzbereich (mind.) abgedeckt ist - AUFGERUNDET,
|
||||
;; damit x1/y1 exakt auf einem Rasterschritt liegen. Damit endet
|
||||
;; JEDE senkrechte Linie exakt auf der letzten waagerechten (bei
|
||||
;; y1) und jede waagerechte exakt auf der letzten senkrechten (bei
|
||||
;; x1) - das Raster bildet immer ein geschlossenes Rechteck.
|
||||
(setq n-x (max 1 (fix (+ 0.999999 (/ (- (car ext-max) x0) x-step)))))
|
||||
(setq n-y (max 1 (fix (+ 0.999999 (/ (- (cadr ext-max) y0) y-step)))))
|
||||
(setq n-x (max 1 (fix (+ 0.999999 (/ (- (if bbox (nth 2 bbox) (car ext-max)) x0) x-step)))))
|
||||
(setq n-y (max 1 (fix (+ 0.999999 (/ (- (if bbox (nth 3 bbox) (cadr ext-max)) y0) y-step)))))
|
||||
|
||||
(setq x1 (+ x0 (* n-x x-step)))
|
||||
(setq y1 (+ y0 (* n-y y-step)))
|
||||
|
||||
+12
-4
@@ -432,20 +432,28 @@ def bbox_columns(block):
|
||||
|
||||
|
||||
def planquadrat_column(block, planquadrat_cfg):
|
||||
"""Berechnet das Planquadrat aus x/y des Blocks (siehe export_planquadrat.py).
|
||||
"""Berechnet das Planquadrat aus der Bounding-Box des Blocks, falls
|
||||
vorhanden (siehe export_planquadrat.py), sonst aus dem Einfuegepunkt.
|
||||
|
||||
planquadrat_cfg = Rueckgabe von resolve_origins() fuer den aktuellen
|
||||
Exportlauf (x_origin_mm/y_origin_mm bereits aufgeloest).
|
||||
Leerer String, wenn keine Planquadrat-Konfiguration geladen werden konnte
|
||||
(fehlende/unvollstaendige [Planquadrate]-Sektion in cfg/export.cfg).
|
||||
|
||||
Ueberdeckt die Bounding-Box des Elements mehr als eine Zelle (z.B. ein
|
||||
Kreisel oder eine lange VarioFoerderer-Kette), liefert compute_planquadrat
|
||||
eine SPANNE "start-ende" (z.B. "A/1-J/1") statt nur der Mittelpunkt-Zelle.
|
||||
"""
|
||||
if planquadrat_cfg is None:
|
||||
return ""
|
||||
x = block.get("x")
|
||||
y = block.get("y")
|
||||
bbox = block.get("bbox") or {}
|
||||
x = bbox.get("cx", block.get("x"))
|
||||
y = bbox.get("cy", block.get("y"))
|
||||
if x is None or y is None:
|
||||
return ""
|
||||
return compute_planquadrat(float(x), float(y), planquadrat_cfg)
|
||||
dx = bbox.get("dx", 0.0)
|
||||
dy = bbox.get("dy", 0.0)
|
||||
return compute_planquadrat(float(x), float(y), planquadrat_cfg, dx_mm=float(dx), dy_mm=float(dy))
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
+68
-12
@@ -54,17 +54,42 @@ def load_planquadrat_config(cfg_path=None):
|
||||
}
|
||||
|
||||
|
||||
def _bbox_min(block, axis):
|
||||
"""Untere Bounding-Box-Kante eines Blocks auf einer Achse ("x"/"y"), oder
|
||||
dessen Einfuegepunkt, falls kein bbox-Feld vorhanden ist (z.B.
|
||||
EXPORTSIVAS, das keine Bounding-Box mitschickt - siehe include-bbox in
|
||||
csv:block-to-json, Lisp/export.lsp).
|
||||
|
||||
MUSS dieselbe Referenz (BBox statt nur Einfuegepunkt) wie
|
||||
compute_planquadrat/planquadrat_column verwenden, sonst driften Ursprung
|
||||
(Index 1) und Zellzuordnung auseinander: ein Element, dessen Bounding-Box-
|
||||
Mitte weit von seinem Einfuegepunkt abweicht (z.B. ein um 90 Grad
|
||||
gedrehter Kreisel, dessen Insertpunkt an einem Rand statt der Mitte
|
||||
liegt), wuerde sonst in eine andere Spalte/Zeile einsortiert als der
|
||||
Ursprung erwarten laesst.
|
||||
"""
|
||||
bbox = block.get("bbox")
|
||||
if bbox:
|
||||
c = bbox.get("c" + axis)
|
||||
d = bbox.get("d" + axis)
|
||||
if c is not None and d is not None:
|
||||
return float(c) - float(d) / 2.0
|
||||
v = block.get(axis)
|
||||
return float(v) if v is not None else None
|
||||
|
||||
|
||||
def resolve_origins(cfg, blocks):
|
||||
"""Loest x_origin_mm/y_origin_mm auf, falls in export.cfg nicht gesetzt.
|
||||
|
||||
cfg = Rueckgabe von load_planquadrat_config() (kann None sein).
|
||||
blocks = alle Bloecke des aktuellen Exportlaufs (Liste von dicts mit
|
||||
"x"/"y", wie im Roh-JSON von export.lsp).
|
||||
blocks = alle Bloecke des aktuellen Exportlaufs (Liste von dicts, wie im
|
||||
Roh-JSON von export.lsp - "x"/"y" und optional "bbox").
|
||||
|
||||
Automatik: das am weitesten links liegende Element (min x) setzt
|
||||
x_origin, das am weitesten unten liegende (min y) setzt y_origin -
|
||||
beide landen damit exakt in Planquadrat-Index 1 auf ihrer Achse.
|
||||
Explizit in export.cfg gesetzte Werte werden nicht ueberschrieben.
|
||||
Automatik: die am weitesten links liegende Bounding-Box-Kante (min x)
|
||||
setzt x_origin, die am weitesten unten liegende (min y) setzt y_origin -
|
||||
beide landen damit exakt in Planquadrat-Index 1 auf ihrer Achse. Fehlt
|
||||
einem Block die Bounding-Box, faellt _bbox_min auf dessen Einfuegepunkt
|
||||
zurueck. Explizit in export.cfg gesetzte Werte werden nicht ueberschrieben.
|
||||
|
||||
Rueckgabe: neues dict (cfg bleibt unveraendert) oder None, wenn cfg None ist.
|
||||
"""
|
||||
@@ -72,10 +97,12 @@ def resolve_origins(cfg, blocks):
|
||||
return None
|
||||
resolved = dict(cfg)
|
||||
if resolved.get("x_origin_mm") is None:
|
||||
xs = [float(b["x"]) for b in blocks if b.get("x") is not None]
|
||||
xs = [_bbox_min(b, "x") for b in blocks]
|
||||
xs = [v for v in xs if v is not None]
|
||||
resolved["x_origin_mm"] = min(xs) if xs else 0.0
|
||||
if resolved.get("y_origin_mm") is None:
|
||||
ys = [float(b["y"]) for b in blocks if b.get("y") is not None]
|
||||
ys = [_bbox_min(b, "y") for b in blocks]
|
||||
ys = [v for v in ys if v is not None]
|
||||
resolved["y_origin_mm"] = min(ys) if ys else 0.0
|
||||
return resolved
|
||||
|
||||
@@ -104,10 +131,39 @@ def _index_for(coord_mm, step_mm, origin_mm=0.0):
|
||||
return int((coord_mm - origin_mm) // step_mm) + 1
|
||||
|
||||
|
||||
def compute_planquadrat(x_mm, y_mm, cfg):
|
||||
"""Berechnet die Planquadrat-Bezeichnung fuer eine x/y-Koordinate (mm)."""
|
||||
x_idx = _index_for(x_mm, cfg["x_step_mm"], cfg.get("x_origin_mm", 0.0))
|
||||
y_idx = _index_for(y_mm, cfg["y_step_mm"], cfg.get("y_origin_mm", 0.0))
|
||||
def _cell_label(x_idx, y_idx, cfg):
|
||||
x_label = _index_to_alpha(x_idx) if cfg["x_alpha"] else str(x_idx)
|
||||
y_label = _index_to_alpha(y_idx) if cfg["y_alpha"] else str(y_idx)
|
||||
return cfg["format"].format(x=x_label, y=y_label)
|
||||
|
||||
|
||||
def compute_planquadrat(x_mm, y_mm, cfg, dx_mm=0.0, dy_mm=0.0):
|
||||
"""Berechnet die Planquadrat-Bezeichnung fuer ein Element.
|
||||
|
||||
x_mm/y_mm = Mittelpunkt (Bounding-Box-Zentrum bzw. Einfuegepunkt, mm).
|
||||
dx_mm/dy_mm = Ausdehnung der Bounding-Box (mm), optional (Default 0).
|
||||
|
||||
Ohne Ausdehnung (dx_mm/dy_mm <= 0, z.B. Sensoren/Weichen ohne eigene BBox)
|
||||
wird wie bisher NUR die Zelle des Mittelpunkts geliefert (z.B. "A/1").
|
||||
|
||||
Mit Ausdehnung > 0 wird die Zelle der unteren/linken UND der oberen/
|
||||
rechten Bounding-Box-Ecke berechnet - deckt das Element mehr als eine
|
||||
Zelle ab (z.B. ein Kreisel ueber A/1 bis J/1, ein VarioFoerderer ueber
|
||||
B/2 bis C/3), wird eine SPANNE "start-ende" geliefert (z.B. "A/1-J/1",
|
||||
"B/2-C/3"); liegen beide Ecken in derselben Zelle, wird weiterhin nur
|
||||
diese eine Zelle geliefert (kein "A/1-A/1").
|
||||
"""
|
||||
if dx_mm and dx_mm > 0 and dy_mm and dy_mm > 0:
|
||||
x_lo_idx = _index_for(x_mm - dx_mm / 2.0, cfg["x_step_mm"], cfg.get("x_origin_mm", 0.0))
|
||||
x_hi_idx = _index_for(x_mm + dx_mm / 2.0, cfg["x_step_mm"], cfg.get("x_origin_mm", 0.0))
|
||||
y_lo_idx = _index_for(y_mm - dy_mm / 2.0, cfg["y_step_mm"], cfg.get("y_origin_mm", 0.0))
|
||||
y_hi_idx = _index_for(y_mm + dy_mm / 2.0, cfg["y_step_mm"], cfg.get("y_origin_mm", 0.0))
|
||||
if x_lo_idx == x_hi_idx and y_lo_idx == y_hi_idx:
|
||||
return _cell_label(x_lo_idx, y_lo_idx, cfg)
|
||||
start = _cell_label(x_lo_idx, y_lo_idx, cfg)
|
||||
ende = _cell_label(x_hi_idx, y_hi_idx, cfg)
|
||||
return f"{start}-{ende}"
|
||||
|
||||
x_idx = _index_for(x_mm, cfg["x_step_mm"], cfg.get("x_origin_mm", 0.0))
|
||||
y_idx = _index_for(y_mm, cfg["y_step_mm"], cfg.get("y_origin_mm", 0.0))
|
||||
return _cell_label(x_idx, y_idx, cfg)
|
||||
|
||||
Reference in New Issue
Block a user