Files
dxfmakros/tests/testdata/object_data.md
T
2026-07-27 16:54:04 +02:00

21 KiB

JSON-Schema fuer tests/testdata/*.json

Diese Datei leitet aus den Produktions-Routinen in Lisp/ (nicht aus den Test-Hilfsfunktionen in tests/*.lsp) ab, welche Angaben pro Element-Typ noetig sind, um das jeweilige Bauteil programmgesteuert (per JSON) zu erzeugen. Fuer jeden Typ wird die tatsaechlich aufgerufene LISP-Funktion samt Parameterliste referenziert.

Wichtige Unterscheidung, die sich beim Durcharbeiten herauskristallisiert hat:

  • Scriptbar = es existiert eine Produktions-Funktion, die alle noetigen Werte als normale Parameter entgegennimmt (kein getpoint/getstring noetig). Diese Funktionen sind 1:1 aus JSON aufrufbar.
  • Nicht scriptbar = die Produktions-Funktion fragt Punkte/Optionen interaktiv ab (getpoint, getstring, ssget auf bereits gezeichnete Geometrie). Es gibt in Lisp/ keinen parametrischen Einstiegspunkt; ein JSON-Testfall kann diese Faelle nur ueber einen eigens geschriebenen Wrapper (wie es tests/*.lsp tut) nicht-interaktiv nachbilden.

Einheiten durchgaengig: mm fuer Laengen/Koordinaten, Grad fuer Winkel (intern wird oft in Radiant gerechnet, die LISP-API-Grenze ist aber immer Grad). Richtung hz/hz_grad: 0=Ost(+X), 90=Nord(+Y), 180=West(-X), 270=Sued(-Y).


1. Kreisel — Lisp/KreiselInsert.lsp

Scriptbar. Zwei Varianten:

1.1 Insert (freier Punkt + Abstand)

Produktionsfunktion: kreisel-insert-script (pt abstand rotation typ hoehe)

Feld Typ Pflicht Bedeutung Default
x, y real (mm) ja Einfuegepunkt (Welt-XY), zusammen pt -
z real (mm) nein Hoehe; entfaellt hoehe, wird pts Z verwendet *kreisel-default-hoehe* (config kreisel.default_hoehe, 2000.0)
abstand real (mm) nein Abstand zwischen AN-/SP-Kreiselhaelfte (Kreisel-Baulaenge) *kreisel-default-laenge* (config kreisel.default_laenge, 2300.0)
rotation real (Grad) nein freie Rotation des Bauteils, kein Rasterzwang (0/90/180/270 sind nur ueblich, nicht erzwungen) 0.0
typ string nein "STANDARD" oder "PIN" (einzige zwei Optionen aus kreisel-ask-typ) "STANDARD"

Konstanten (Config [kreisel]): durchmesser (800.0mm, fuer Connect-Abstandsberechnung), default_laenge, default_hoehe.

Minimal-JSON (wie kreisel_tests.json):

{ "id": "K1", "function": "insert",
  "x": 500, "y": 500, "z": 2500,
  "abstand": 2000, "rotation": 0.0, "typ": "STANDARD" }

id und expect_*-Felder (expect_block_prefix, expect_hoehe, expect_kreiselart) sind keine Produktionsparameter — reine Test-Erwartungswerte fuer die Ergebnispruefung, nicht von kreisel-insert-script konsumiert.

1.2 Connect (Start-/Endpunkt, Abstand wird berechnet)

Produktionsfunktion: kreisel-connect-script (ptStart ptEnd typ hoehe)

Feld Typ Pflicht Bedeutung
start_x,start_y,start_z real (mm) ja aeusserster Punkt AN-Seite (Antriebsstation)
end_x,end_y,end_z real (mm) ja aeusserster Punkt SP-Seite (Spannstation)
typ string nein "STANDARD"/"PIN"
hoehe real (mm) nein Default: Z von ptStart, sonst *kreisel-default-hoehe*

abstand/rotation werden intern aus der Distanz beider Punkte berechnet (abstand = distanz - *kreisel-durchmesser*; Rotation aus dem Winkel der Verbindungslinie) — bei Connect KEIN Eingabefeld.


2. Gefaellestrecke — Lisp/Gefaellestrecke.lsp

Drei Modi, siehe Kopfkommentar der Datei. Modus 1+2 teilen sich denselben Abschluss (gf-modus12-abschluss) und sind beide scriptbar. Modus 3 (Linienzug) ist in Produktion nicht scriptbar.

Gemeinsame Bau-Funktion (von allen Modi letztlich aufgerufen): gefaellestrecke-einfuegen (L_stau winkel startpunkt as-seite es-seite hz deltaL-total as-winkel es-winkel geruest-einzelmodul geruest-typ)

Wichtig: deltaL (horizontale Laenge) ist der Eingang, nicht die Hoehendifferenz. Bei festem winkel legen Laenge und Hoehendifferenz sich gegenseitig fest (L_stau = (deltaL - aus-dx - ein-dx - sep-x) / cos(rad), sep-x = separator_breite * cos(rad), config gefaelle.separator_breite Default 300.0). Es gibt keinen Parameter fuer eine gewuenschte Ziel-Hoehendifferenz — die ergibt sich aus L_stau/winkel.

2.1 Modus 1 — Manuelle Werteingabe

Eingangsfunktion (nach DCL-Dialog gefaellestrecke.dcl): gf-modus12-abschluss (deltaL winkel hz-winkel as-seite es-seite startpunkt as-winkel es-winkel dialog-bestaetigt geruest-einzelmodul geruest-typ)

Feld Typ Pflicht Bedeutung Default
deltaL / deltaL_mm real (mm) ja horizontale Gesamtlaenge (AS+Staustrecke+Separator+ES) config gefaelle.default_delta_l 5000.0
winkel / winkel_grad real (Grad) nein Gefaelle-Neigungswinkel config gefaelle.default_winkel 3.0
hz_grad real (Grad) nein Fahrtrichtung (0/90/180/270 ueblich, frei waehlbar) 0.0
start_mm [x,y,z] (mm) ja Startpunkt; Z = Einfuegehoehe -
as_seite string nein "links"/"rechts" (AUS-Element-Seite) "links"
es_seite string nein "links"/"rechts" (EIN-Element-Seite) "links"
as_winkel string nein "90"/"30" (AUS-Element-Variante) "90"
es_winkel string nein "90"/"30" (EIN-Element-Variante) "90"
geruest_einzelmodul string "0"/"1" nein Geruest je Einzelmodul (Dialogfeld) "1"
geruest_typ string nein Geruest-Option (*ssg-geruest-optionen*) Default-Index

Minimal-JSON (wie gefaellestrecke_tests.json Modus 1):

{ "test_id": "M1_hz000", "modus": 1, "hz_grad": 0.0,
  "start_mm": [0, 0, 5000],
  "as_seite": "links", "es_seite": "links",
  "as_winkel": "90", "es_winkel": "90" }

deltaL_mm/winkel_grad/z_start_mm stehen in der Testdatei als gemeinsamer Kopf-Eintrag (ein Objekt ohne test_id) statt pro Testfall, weil alle Modus-1-Faelle in gefaellestrecke_tests.json dieselbe Laenge teilen — Produktionsseitig ist deltaL aber pro Aufruf ein normaler, nicht geteilter Parameter.

2.2 Modus 2 — 3D-Linie als Richtungsreferenz

Gleiche Ziel-Funktion (gf-modus12-abschluss), aber deltaL/hz-winkel werden nicht direkt angegeben, sondern aus zwei Linienpunkten berechnet:

deltaX = ende.x - start.x ;  deltaY = ende.y - start.y
deltaL   = hypot(deltaX, deltaY)
hz-winkel = angle(deltaX, deltaY)  [Grad, 0=Ost]

In Produktion werden diese zwei Punkte interaktiv per get-line-start-end-points (Linie in der Zeichnung anklicken) bestimmt — fuer einen JSON-Treiber genuegen aber zwei beliebige Punkte, da die Berechnung rein geometrisch ist.

Feld Typ Pflicht Bedeutung
linie_start_mm [x,y,z] ja erster Linienpunkt (nur X/Y verwendet)
linie_ende_mm [x,y,z] ja zweiter Linienpunkt (nur X/Y verwendet)
start_mm [x,y,z] ja Einfuegepunkt der Kette (unabhaengig von der Linie waehlbar)
winkel, as_seite, es_seite, as_winkel, es_winkel wie Modus 1 nein/ja siehe oben

Geruestoptionen sind in Modus 2 (reine Konsoleneingabe) nicht abfragbar, bleiben auf Default ("0", "Schoenenberger Geruest").

2.3 Modus 3 — Linienzug aus LINE/ARC — nicht scriptbar

Eingangsfunktion: gf-linienzug-modus ()keine Parameter.

Ablauf in Produktion:

  1. (ssget '((0 . "LINE,ARC"))) — der Nutzer muss die Leitlinie (Kette aus bereits in der Zeichnung vorhandenen LINE-/ARC-Entities) vorher zeichnen und dann per Maus auswaehlen. Es gibt keine Funktion, die eine Leitlinie aus Koordinaten/Bogen-Parametern (start_mm/ende_mm/bogen: {winkel_grad, radius_mm, seite}, wie in gefaellestrecke_tests.jsons M3_Bogen zu sehen) direkt als Argument entgegennimmt.
  2. getpoint fuer Startpunkt (Kettenanfang, Z = obere Anschlusshoehe) und Endpunkt-Referenz (Z = untere Anschlusshoehe); deltaH wird aus der Differenz der beiden Z-Werte gebildet.
  3. getstring-Abfragen fuer AS-/ES-Winkel ("90"/"30") und -Seite ("links"/"rechts") — inhaltlich identisch zu Modus 1/2.
  4. Interne Analyse der selektierten Kette (gf-sortiere-objekte, gf-analysiere-kette) leitet Ein-/Ausgangsrichtung sowie Segment-Laengenkorrekturen ab.

Um Modus 3 aus JSON zu treiben, muesste man selbst zuerst die LINE/ARC- Geometrie per entmake erzeugen und dann eine eigene (nicht-interaktive) Nachbildung von gf-linienzug-modus schreiben — genau das tut tests/test_gefaellestrecke.lsp, was hier aber explizit nicht als Parameterquelle verwendet wurde. Die Felder start_mm, ende_mm, bogen in gefaellestrecke_tests.json beschreiben also die gewuenschte Leitlinien-Geometrie, nicht direkte Funktionsparameter einer Produktionsroutine.


3. VarioFoerderer — Lisp/vf_core.lsp + vf_standard.lsp/vf_etage.lsp/vf_linienzug.lsp

Dispatcher c:VarioFoerderer waehlt einen registrierten Anlagetyp ("standard", "etage", "linienzug"). Registry-Vertrag fuer scriptbare Typen:

berechne-fn (deltaL deltaH richtung seite)              -> (best-winkel best-L_GF best-L_VF ergebnis-liste)
einfuege-fn (deltaL deltaH richtung best-winkel L_GF1 L_GF2 L_VF startpunkt seite hz) -> endpunkt

Der Wrapper vf-block-erstellen fasst danach zentral alles zu einem VF_n-Block zusammen (kein JSON-Feld dafuer noetig — laeuft automatisch).

3.1 Standard — scriptbar

  • Winkel-/Laengen-Solver: berechne-standard (deltaL deltaH richtung seite) → wrappt berechne-alle-winkel (deltaL deltaH richtung feste-hz). Kandidatenwinkel (config vario.bogen_winkel, Default): 3 6 9 12 15 18 21 27 33 39 45 51 Grad — nur diese Werte sind moeglich, kein freier Winkel.
  • Bau-Funktion: variofoerderer-einfuegen (deltaL deltaH richtung best-winkel L_GF1 L_GF2 L_VF startpunkt seite hz)
Feld Typ Pflicht Bedeutung
deltaL real (mm) ja horizontale Gesamtlaenge
deltaH real (mm) ja Ziel-Hoehendifferenz (hier IST deltaH ein direkter Eingang, anders als bei Gefaellestrecke!)
richtung string ja "Auf" oder "Ab"
winkel int nein einer der 12 Kandidatenwinkel; ohne Angabe waehlt der Solver automatisch den kleinsten gueltigen Winkel
L_GF1, L_GF2 real (mm) nein Aufteilung der Gefaellestrecke vorne/hinten. Falls nicht vorgegeben: gleichmaessig = beide L_GF/2 (Solver-Ergebnis L_GF gesamt). In Produktion per Dialog waehlbar: 0=gleichmaessig, 1=alles vorne (Rest hinten), 2=alles hinten (Rest vorne), 3=manuell (L_GF1 frei, L_GF2 = Rest)
startpunkt (x,y,z) real (mm) ja Einfuegepunkt
seite string nein "links"/"rechts" (AS/ES-Element-Seite)
hz real (Grad) nein Fahrtrichtung
motorseite string nein "links"/"rechts" — nur Dialog/Anzeige, kein Geometrie-Parameter von variofoerderer-einfuegen selbst

Minimal-JSON (wie foerderer_tests.json):

{ "test_id": "VF_Auf_1000", "richtung": "Auf", "deltaL": 7000, "deltaH": 1000 }

Optionale Erweiterungsfelder aus derselben Datei: seite (Default "links" im Testfall), winkel (erzwingt einen bestimmten Kandidaten statt Auto-Wahl), gf_verteilung ("gleichmaessig"/"vorne"/"hinten", entspricht Verteilungsmodus 0/1/2 oben).

3.2 Etage — scriptbar

  • Solver: berechne-etage (deltaL deltaH richtung seite)berechne-winkel-etage (deltaL deltaH richtung). Gleiche 12 Kandidatenwinkel wie Standard.
  • Bau-Funktion: etage-foerderanlage-einfuegen (deltaL deltaH richtung best-winkel L_GF1 L_GF2 L_VF startpunkt seite hz)identische Signatur wie Standard (Registry-Vertrag), Unterschied liegt im internen Aufbau (30-Grad-AS/ES-Elemente statt 90, AS/ES direkt uebereinander, zusaetzlicher fixer "Gefaellebogen" je nach seite gegenueber dem AS-Element).

Felder: identisch zu 3.1 (deltaL, deltaH, richtung, winkel, L_GF1/L_GF2, startpunkt, seite, hz).

3.3 Linienzug — nicht scriptbar

Eingangsfunktion vf-linienzug-modus ()keine Parameter, rein interaktiver Mehrschritt-Assistent (Kettenaufbau aus GF-Boegen, Vario-Kurven, VF-Einheiten, Horizontal-Stuecken). Jeder Schritt fragt per getpoint/getstring/getint/getreal einzeln ab (Startpunkt, Hoehe, AS/ES-Winkel+Seite, naechstes Element, Linien-Endpunkt via Fahrtrichtung+Laenge, GF-Verteilung, Separator vor/nach, Kettenende ja/nein, ...). Es existiert keine einzelne Produktionsfunktion, die eine ganze Kette aus einer Liste von Segment-Beschreibungen entgegennimmt.

linienzug_tests.json bildet genau diese Prompt-Sequenz als Frage-Antwort-Protokoll ab (typ: point_abs/point_rel/real/ string/int, jeweils mit wert/dL+hz und einem kommentar, der beschreibt, WELCHE Frage/Bedeutung die Antwort hat) — das ist die einzige Moeglichkeit, den interaktiven Ablauf nicht-interaktiv nachzubilden, kein direkter Parametersatz einer Bau-Funktion. Die Reihenfolge und Bedeutung der Prompts (Kurzfassung, siehe vf_linienzug.lsp fuer Details):

  1. Startpunkt (point_abs), Hoehe Z (real)
  2. AS-Element setzen? Ja/Nein, wenn ja: Winkel 90/30, Seite links/rechts
  3. Schleife "naechstes Element": GF-Bogen | Neue Linie (GF) | Neue Linie (Ab/Auf VF) | Horizontal-VF | Kettenende — jeweils eigene Unter-Prompts (Endpunkt point_rel mit dL+hz, Ziel-Hoehe oder Neigungswinkel, Separator vor/nach, GF-Verteilung, Vario-Kurve Winkel/Seite/Variante, ...)
  4. Kettenende: ES-Winkel (90/30) + ES-Seite (links/rechts)

3.4 Vario_Kette_Merge — kein Neubau, sondern Re-Packaging

c:Vario_Kette_Merge: benoetigt nur einen Start-Entity-Pick (entsel), sucht danach selbst alle KS_EIN/KS_AUS-kompatiblen Nachbarblöcke in der ganzen Zeichnung ab (vfl-kette-verfolgen, Toleranzen 2mm/100mm) und fasst sie zu einem neuen VF_n zusammen. Kein JSON-Parametersatz noetig/möglich — reine Nachbearbeitung bereits vorhandener Geometrie.


4. Omniflo — Lisp/OmniModulInsert.lsp

4.1 Boegen/Weichen — Kern scriptbar, Produktions-Befehle NICHT

Kern-Funktion: omni:insert-dxf (sivasnr-str hoehe drehung)

Param Typ Pflicht Bedeutung
sivasnr-str string ja Komponenten-ID; ist gleichzeitig der Dateiname <sivasnr>.dxf unter %DXFM_OMNIFLO% — keine separate Namenstabelle
hoehe string (mm) nein absolute Z-Koordinate des Einfuegepunkts + HOEHE-Attribut; leer/nil -> config omniflo.default_hoehe bzw. hart "2000"
drehung string (Grad) nein feste Rotation; nil -> in den echten c:OMNI_*-Befehlen wird interaktiv per Maus gedreht

Aber: Alle echten c:OMNI_APB_*/c:OMNI_W*_*-Befehle rufen omni:insert-dxf ohne X/Y-Parameter auf — der Einfuegepunkt kommt in _.INSERT immer per pause (Mausklick). Es gibt in Produktion keinen Aufrufpfad, der X/Y programmatisch uebergibt; omni:insert-dxf selbst akzeptiert auch keinen Punkt-Parameter (der Punkt wird IN der Funktion interaktiv abgefragt). Die Felder x/y in omniflo_tests.json haben daher keine direkte Entsprechung in einer Produktions-Parameterliste — sie beschreiben nur, wo das Element im Testlayout stehen soll; ein JSON-Treiber muesste den _.INSERT-Aufruf selbst nachbauen (z.B. wie mubea:build-separator in tests/test_mubea.lsp es fuer Separatoren tut).

Sivasnr-Herkunft: data/json/omniflo_boegen.json (Felder u.a. Sivasnr, ProfilTyp, Radius, KurvenWinkel, Breite, Länge, SivasnrTEF, Antriebsart) und data/json/omniflo_weichen.json (zusaetzlich WeichenTyp, Schaltungstyp, KurvenRichtung, WeichenkörperLänge) — diese Tabellen dienen nur der Dialog-Filterung/Anzeige, nicht der Namensaufloesung selbst (die ist sivasnr == dateiname).

Minimal-JSON, wie es fuer einen scriptbaren Wrapper um omni:insert-dxf sinnvoll waere (entspricht omniflo_tests.json):

{ "id": "821104025", "type": "bogen", "sivasnr": "821104025",
  "x": 219.4, "y": 223.06, "hoehe": 2000, "drehung": 0.0 }

description/row sind reine Dokumentations-/Gruppierungsfelder aus der Testdatei, keine Produktionsparameter.

4.2 Aluprofil-Gerade (AP60/AP110/APG110) — Kern scriptbar

Kern-Funktion: omni:make-gerade (blockname pt pt2 srcAttribs textHeight textGap textEnt)

Param Typ Pflicht Bedeutung
blockname string ja "AP60" / "AP110" / "APG110"
pt, pt2 (x,y,z) ja Start-/Endpunkt der Geraden (absolute Weltkoordinaten); Laenge/Rotation werden aus der Differenz berechnet, keine eigenen Winkel-/Laengenfelder
srcAttribs alist nein aus Vorlagen-DWG gelesen (omni:read-src-attribs blockname); bei nil entsteht ein Block ohne ATTDEFs
textHeight,textGap real nein Konfig omniflo.text_height(100.0)/text_gap(20.0)

Der oeffentliche Befehl omni:insert-block (blockname laengemax) fragt pt/pt2 interaktiv per getpoint ab und prueft laengemax (Config omniflo.laengemax_ap60/ap110/apg110) — omni:make-gerade selbst ist aber mit fest vorgegebenen Punkten aufrufbar, hier waere aus linienzug_tests.json-artigen Daten (profil, x/y, x_ende/y_ende, hoehe) ein Treiber moeglich, wie es die Eintraege vom Typ "gerade" in linienzug_tests.json nahelegen (dort allerdings fuer eine andere Test-Zwecksetzung — Reihen-Layout, nicht direkter Funktionsaufruf).

4.3 TEF/Zubehoer (Stopper, Scanner, Buerstenbremse, Umlenk-/Antriebsstationen)

c:OMNI_STOPPER/c:OMNI_SCANNER/... rufen omni:insert-dxf mit hartcodiertem sivasnr-str (z.B. "827062022") und hoehe=nil, drehung=nil auf — Punkt weiterhin interaktiv. Kein Nutzer-JSON-Feld fuer sivasnr noetig (fest im Code), nur Position/Hoehe/Rotation waeren grundsaetzlich scriptbar (siehe 4.1), aber nicht ueber die vorhandenen c:OMNI_*-Befehle.

4.4 TV_* (Transferwagen-Verbinder) / APBW_* (Boegen fuer Weichen)

Nicht implementiert. Alle c:OMNI_TV_*- und c:OMNI_APBW_*-Befehle sind reine [DUMMY]-Platzhalter ohne echte Bau-Logik — kein Parametersatz vorhanden, unabhaengig davon was eine Testdatei dafuer vorsehen wuerde.

c:OMNI_UPDATE_ATTRIBS ist in Lisp/export.lsp definiert (aktualisiert HOEHE/DREHUNG aller Omniflo-Elemente aus der Zeichnung) — kein Bau-/Einfuege-Befehl und daher kein JSON-Parametersatz.


5. Separator/Scanner — Lisp/SSG_LIB_Commands.lsp

Funktion: ils-insert-sensor (fname)

Param Typ Pflicht Bedeutung
fname string ja Blockdateiname ohne Erweiterung, z.B. "Separator_SP", "Scanner" — aufgeloest ueber ssg-ils-block-datei (2D/3D-Suffix + Fallback)

Nicht scriptbar: die Funktion fragt Einfuegepunkte in einer Schleife per getpoint ab (_.INSERT pfad pt "" "" pause — auch die Rotation kommt per Maus/pause), bis der Nutzer mit ENTER/ESC abbricht. Es gibt keinen Parameter fuer Punkt, Anzahl oder Rotation. Ein JSON-Treiber muss den _.INSERT-Aufruf direkt selbst nachbilden (Blockdatei-Pfad ueber ssg-ils-block-datei bzw. ssg-ils-block-laden, dann _.INSERT pfad pt "" "" rot mit festem rot statt pause) — das ist der Ansatz, den tests/test_mubea.lsps mubea:build-separator verwendet (zur Info, nicht als Quelle fuer diesen Parametersatz genutzt, da bereits aus ils-insert-sensor selbst ableitbar: Blockname + Punkt + Rotation sind die einzigen fachlich noetigen Werte).

Minimal-JSON (wie in mubea.jsons Separator-Eintraegen):

{ "function": "insert", "block": "S-LP", "x": 10310, "y": -14158, "z": 1467, "rotation": 270 }

6. Zusammenfassung: scriptbar vs. nicht scriptbar

Element Produktionsfunktion Scriptbar?
Kreisel Insert kreisel-insert-script ja
Kreisel Connect kreisel-connect-script ja
Gefaellestrecke Modus 1 gf-modus12-abschlussgefaellestrecke-einfuegen ja
Gefaellestrecke Modus 2 gf-modus12-abschluss (deltaL/hz aus 2 Punkten) ja
Gefaellestrecke Modus 3 gf-linienzug-modus nein (erfordert vorgezeichnete LINE/ARC-Auswahl)
VarioFoerderer Standard variofoerderer-einfuegen ja
VarioFoerderer Etage etage-foerderanlage-einfuegen ja
VarioFoerderer Linienzug vf-linienzug-modus nein (mehrstufiger interaktiver Assistent)
Vario_Kette_Merge vfl-kette-verfolgen n/a (Re-Packaging, kein Parametersatz)
Omniflo Bogen/Weiche omni:insert-dxf (Kern) Kern ja, Produktionsbefehle nein (X/Y immer Maus)
Omniflo Aluprofil-Gerade omni:make-gerade (Kern) Kern ja, Befehl omni:insert-block fragt Punkte interaktiv
Omniflo TEF/Zubehoer omni:insert-dxf (fester Sivasnr) Position/Hoehe/Rotation ja, Punkt-Eingabe interaktiv
Omniflo TV_/APBW_ - nein (nicht implementiert, DUMMY)
Separator/Scanner ils-insert-sensor nein (Schleife mit getpoint/pause)