[Frage] Bearbeiten von Listen mittels Programmschleife im Visual Scripting

Schlagworte:
  • VisualScritping
  • Liste
  • Schleife
  • Loop

Beim Arbeiten mit Längen/Koordinaten wäre es für mich hilfreich, wenn man diese gezielt weiterverarbeiten kann. In meinem aktuellen Vorhaben ist folgendes umzusetzen.

Gegeben ist eine variable Liste mit Fließkommazahlen (values) und ein variabler Abstand (x). Die Liste soll so angepasst werde, dass zwischen den Werten der Mindestabstand X eingehalten wird. Die Werte sollen nur gegebenenfalls vergrößert aber nie verkleinert werden. X ist immer positiv.
Hier ein Beispiel:

Liste [0, 1.2, 2.0, 2.5, 4.3, 5.1, 7.6, 7.9, 9.0]

Abstand 0.8
Ergebnis [0, 1.2, 2.0, 2.8, 4.3, 5.1, 7.6, 8.4, 9.2]

Abstand 1.2
Ergebnis [0, 1.2, 2.4, 3.6, 4.8, 6.0, 7.6, 8.8, 10.0]

Was Python-Programmierung betrifft bin ich noch Anfänger, aber ich denke das lässt sich gut mit einer Schleife lösen:

x = 0.8
values = [0, 1.2, 2.0, 2.5, 4.3, 5.1, 7.6, 7.9, 9.0]

values.sort()
loop_count = 0

for item in values:
    if loop_count == 0:
        loop_count += 1
    elif values[loop_count] - values[loop_count - 1] < x:
        values[loop_count] = values[loop_count - 1] + x
        loop_count += 1
    else:
        loop_count += 1

Für den Fall, dass die Liste negative Werte enthält und oder nicht aufsteigend sortiert ist, wird zuerst eine Sortierung durchgeführt.
Der erste/kleinste Wert soll nie verändert werden, daher überspringt das if den ersten loop.

Ist es möglich eine solche Auswertung in Visual Scripting vorzunehmen?

Mit den einfachen Math Operators-Nodes scheint das nicht zu funktionieren.
Aber es gibt das Node ExecPythonScript.
Laut Beschreibung kann man hiermit ein Python-Script ausführen. Leider finde ich keine Infos darüber, wie man das richtig einsetzt. Man kann Parameter übergeben und laut Eigenschaftenfeld eine Funktion definieren. Gibt es dazu irgendwo eine Anleitung?

Gruß Felix
Allplan 2024-0-1

Anhänge (2)

Typ: text/plain
983-mal heruntergeladen
Größe: 346,00 B
Typ: image/png
55-mal heruntergeladen
Größe: 12,15 KiB

Hilfreichste Antwort anzeigen Hilfreichste Antwort verbergen

habe gerade versucht mit VS dein Problem zu lösen, aber im ersten Blick scheint es mir schwieriger als gedacht. Da momentan VS hat keine richtige Schleife. Genauer gesagt im Fall:

x = 0.8
Ausgang [0, 1.2, 2.0, 2.5, 4.3, 5.1, 7.6, 7.9, 9.0]
Ergebnis [0, 1.2, 2.0, 2.8, 4.3, 5.1, 7.6, 8.4, 9.2]

Diese 9.2 kriege ich nicht hin, da sie auch von 8.4 sogar 7.6 aus der Ergebnisliste abhängig ist. Wenn die Abstände zwischen der Ausgangsliste noch kleiner wären, dann hängt es noch von mehreren vorherigen Ergebnissen ab.

Als Alternativ kann man mit dem Node "ExecPythonScript" versuchen. Eine mögliche Lösung sieht so aus:

def function_to_execute(x):
  result = []
  interval = x[0]
  valuelist = x[1:]
  result.append(valuelist[0])
  i = 1
  while i < len(valuelist):
    c = result[i-1] + interval
    if c > valuelist[i]:
        result.append(c)
    else:
        result.append(valuelist[i])
    i += 1
  return result

Die Code hier sind ganz normal Python-Code. Nur muss man beachten, mit List zu bearbeiten. Ein Problem hat das Node noch, dass es nur ein Parameter akzeptieren kann. Daher muss man als Workaround zuerst das X und das Ausgangslist zusammen kombinieren und dann im Node zu splitten.

Das UI von dem Node ist momentan auch nicht perfekt, wenn man sehr lange Code dort eintippt.

Product Owner API, Allplan GmbH

Anhänge (1)

Typ: image/png
77-mal heruntergeladen
Größe: 403,58 KiB

habe gerade versucht mit VS dein Problem zu lösen, aber im ersten Blick scheint es mir schwieriger als gedacht. Da momentan VS hat keine richtige Schleife. Genauer gesagt im Fall:

x = 0.8
Ausgang [0, 1.2, 2.0, 2.5, 4.3, 5.1, 7.6, 7.9, 9.0]
Ergebnis [0, 1.2, 2.0, 2.8, 4.3, 5.1, 7.6, 8.4, 9.2]

Diese 9.2 kriege ich nicht hin, da sie auch von 8.4 sogar 7.6 aus der Ergebnisliste abhängig ist. Wenn die Abstände zwischen der Ausgangsliste noch kleiner wären, dann hängt es noch von mehreren vorherigen Ergebnissen ab.

Als Alternativ kann man mit dem Node "ExecPythonScript" versuchen. Eine mögliche Lösung sieht so aus:

def function_to_execute(x):
  result = []
  interval = x[0]
  valuelist = x[1:]
  result.append(valuelist[0])
  i = 1
  while i < len(valuelist):
    c = result[i-1] + interval
    if c > valuelist[i]:
        result.append(c)
    else:
        result.append(valuelist[i])
    i += 1
  return result

Die Code hier sind ganz normal Python-Code. Nur muss man beachten, mit List zu bearbeiten. Ein Problem hat das Node noch, dass es nur ein Parameter akzeptieren kann. Daher muss man als Workaround zuerst das X und das Ausgangslist zusammen kombinieren und dann im Node zu splitten.

Das UI von dem Node ist momentan auch nicht perfekt, wenn man sehr lange Code dort eintippt.

Product Owner API, Allplan GmbH

Anhänge (1)

Typ: image/png
77-mal heruntergeladen
Größe: 403,58 KiB

Der Python-Ansatz von f_hoeser war schon mal richtig(er) als der von Xinling!

Bei letzterem werden einmal die Werte der neuen Result-Liste (Zeile 8 ) benutzt, um den gewünschten
Min-Wert des nächsten Eintrag zu berechnen, dann wird aber dieser Sollwert mit der Original-Liste verglichen(Zeile 9)! Das ist genau falsch! Der Vergleich muss auch mit dem Wert der neuen Result-Liste passieren! Dadurch stellt sich die Frage nach der Sinnhaftigkeit von 2 Listen (result und valuelist) in der ganzen Funktion!

Bei der Anforderungsbeschreibung von f_hoeser fehlt die Beschreibung für den Fall, dass der korrigierte Wert
(mit dem Mindestabstand) den folgenden Eintrag/ die folgenden Einträge der Ausgangsliste übersteigt!
Werden diese Einträge dann ignoriert, oder wie bei einem Schneepflug vor diesem hergeschoben.

Letzteren Fall deckt der Code von f_hoeser bereits ab!
Wenn die überrollten Werte ignoriert werden sollen, müßte man den Code für diesen Fall anpassen.

Danke für die ausführlichen Antworten.

Die Anzahl der Werte bleibt gleich. Es gibt für jeden Eingabewert exakt einen Ausgabewert. Etweder der Wert bleibt gleich oder er wird größer. Also wie ein Schneepflug vor sich hergeschoben.

Den Code von Xinling habe ich noch nicht ausprobiert.

Wenn nur ein Parameter übergeben werden kann, also Werteliste + Abstand X, dann würde ich vielleicht den Abstand X hinten an die Werte anhängen und im Script als erstes die Pop-Methode (values.pop()) verwenden um den Wert X aus der Liste zu entfernen. X kann dann gleich mit dem return von pop belegt werden (x = values.pop()).

Ich habe das noch nicht ausprobiert ist nur ein schneller Gedanke.

Gruß Felix
Allplan 2024-0-1

Im PyCharm scheint es zu funktionieren...

Gruß Felix
Allplan 2024-0-1

Anhänge (1)

Typ: image/png
60-mal heruntergeladen
Größe: 114,22 KiB

..ich würde den Wert vorne als eine Liste mit einem Element anfügen! Und als zweites Element in der Liste die Werte-Liste selbst.
(Man kann ja Listen beliebig tief verschachteln.)
Das würde es erlauben, den Mindest-Abstand sogar für jedes Item unterschiedlich zu gestalten, indem man in der
ersten Liste (mit den Abständen) n-1 Abstände eingibt.
Intern müsste man nur über die Abstandsliste simultan zur Werteliste iterieren, und am Ende der Abstandsliste einfach
den letzten Wert weiterbenutzen...

Den "Input-Datenstrom" muss man ja auch wieder mit Nodes erzeugen. Insofern richtet es sich danach,
was mit den verfügbaren Nodes einfacher zu bewerkstelligen ist....