Ich möchte, dass eine Funktion ein Objekt animiert, das sich im Laufe der Zeit von Punkt A nach Punkt B bewegt, so dass es zu einem festgelegten Zeitpunkt B erreicht, seine Position jedoch zu jeder Zeit zufällig kontinuierlich gestört wird, aber niemals rückwärts geht. Die Objekte bewegen sich entlang gerader Linien, daher benötige ich nur eine Dimension.
Mathematisch bedeutet das, dass ich nach einem stetigen f (x), x ∈ [0,1] suche, so dass:
- f (0) = 0
- f (1) = 1
- x <y → f (x) ≤ f (y)
- An "den meisten" Punkten hat f (x + d) - f (x) keine offensichtliche Beziehung zu d. (Die Funktion nimmt nicht gleichmäßig zu oder ist auf andere Weise vorhersehbar. Ich denke, das entspricht auch der Aussage, dass kein Grad der Ableitung eine Konstante ist.)
Idealerweise möchte ich tatsächlich eine Möglichkeit haben, eine Familie dieser Funktionen zu haben, die einen Samenzustand liefert. Ich würde für meine derzeitige Verwendung mindestens 4 Bit Seed (16 mögliche Funktionen) benötigen, aber da dies nicht viel ist, können Sie noch mehr bereitstellen.
Um verschiedene Probleme mit Akkumulationsfehlern zu vermeiden, würde ich es vorziehen, wenn die Funktion keinen internen Status erfordert. Das heißt, ich möchte, dass es eine echte Funktion ist, keine programmierende "Funktion".
f'(x)>0
, sodass die normalisierte Integration des Absolutwerts einer Rauschfunktion alle Ihre Anforderungen erfüllt. Leider kenne ich keine einfache Möglichkeit, das zu berechnen, aber vielleicht tut es jemand anderes. :)Antworten:
Für diesen Beitrag ist y = f (t), wobei t der Parameter ist, den Sie variieren (Zeit / Fortschritt) und y die Entfernung zum Ziel ist. Ich werde also in Bezug auf Punkte auf 2D-Plots sprechen, bei denen die horizontale Achse Zeit / Fortschritt und die vertikale Achse Entfernung ist.
Ich denke, Sie können eine kubische Bezier-Kurve mit dem ersten Punkt bei (0, 1) und dem vierten (letzten) Punkt bei (1, 0) erstellen. Die beiden Mittelpunkte können zufällig (x = Rand, y = Rand) innerhalb dieses 1-mal-1-Rechtecks platziert werden. Ich kann dies nicht analytisch überprüfen, aber wenn ich nur mit einem Applet herumspiele (ja, mach weiter und lache), scheint es, dass die Bezier-Kurve mit einer solchen Einschränkung niemals abnehmen wird.
Dies ist Ihre Elementarfunktion b (p1, p2), die einen nicht abnehmenden Pfad von Punkt p1 zu Punkt p2 bereitstellt.
Jetzt können Sie ab (p (1) = (0, 1), p (n) = (1, 0)) erzeugen und eine Anzahl von p (i) entlang dieser Kurve so auswählen, dass 1
Im Wesentlichen generieren Sie einen "allgemeinen" Pfad, teilen ihn dann in Segmente auf und generieren jedes Segment neu.
Da Sie eine mathematische Funktion wünschen: Angenommen, die obige Prozedur ist in eine Funktion y = f (t, s) gepackt, die Ihnen den Abstand bei t für die Funktion des Samens s gibt. Du wirst brauchen:
Jeder Samen muss also eines der folgenden liefern:
Ich kann mir vorstellen, dass Sie beides erreichen können, indem Sie einfach eine Reihe von Zahlen als Startwerte angeben. Alternativ können Sie beispielsweise eine Zahl s als Startwert angeben und dann den integrierten Zufallszahlengenerator mit rand (s), rand (s + 1), rand (s + 2) usw. aufrufen (oder mit initialisieren) s und rufen Sie dann rand.NextNumber weiter auf.
Beachten Sie, dass Sie, obwohl die gesamte Funktion f (t, s) aus vielen Segmenten besteht, nur ein Segment für jedes t auswerten. Sie werden müssen wiederholt die Grenzen der Segmente mit dieser Methode berechnen, weil Sie sie sortieren müssen sicherstellen , dass keine zwei Segmente überlappen. Sie können diese zusätzliche Arbeit wahrscheinlich optimieren und loswerden und nur die Endpunkte eines Segments für jeden Anruf finden, aber es ist mir momentan nicht klar.
Bezier-Kurven sind ebenfalls nicht erforderlich, ein sich entsprechend verhaltender Spline reicht aus.
Ich habe eine Matlab-Beispielimplementierung erstellt.
Die Bezier-Funktion (vektorisiert):
Die oben beschriebene zusammengesetzte Bezier-Funktion (absichtlich unentdeckt gelassen, um zu verdeutlichen, wie viel Auswertung für jeden Aufruf erforderlich ist):
Das Skript, das die Funktion für einen zufälligen Startwert darstellt (beachten Sie, dass dies der einzige Ort ist, an dem eine zufällige Funktion aufgerufen wird. Die Zufallsvariablen werden von diesem einen zufälligen Array an alle anderen Codes weitergegeben):
Hier ist eine Beispielausgabe:
Es scheint die meisten Ihrer Kriterien zu erfüllen. Jedoch:
quelle
Ich denke, anstatt eine Reihe transformierter Cosinus zu mischen (wie es die Punktprodukte im Perlin-Rauschen geben), könnten Sie mehrere monotone Funktionen mischen, die bei f (0) = 0 beginnen, wie f (x) = x oder 2x, oder x ^ 2 usw. Da Ihre Domain auf 0 => 1 beschränkt ist, können Sie auch Triggerfunktionen einblenden, die wie cos (90 * x + 270) zur Rechnung innerhalb dieser Domain passen. Um Ihre Methoden so zu normalisieren, dass sie bei 1 enden, können Sie einfach die gewichtete Summe dieser monotonen Methoden beginnend bei f (0) = 0 durch f (1) teilen. So etwas sollte auch ziemlich einfach zu invertieren sein (was ich von dem Punkt über zustandslose reale Funktionen im Vergleich zu Programmierfunktionen möchte).
Hoffe das hilft.
quelle
Man kann dieses grobe Bild analysieren. Sie können eine Funktion erhalten, die Ihre Animation im laufenden Betrieb ausführt, indem Sie eine einheitliche Rand-Funktion verwenden. Ich weiß, dass dies nicht die exakte mathematische Formel ist, aber es gibt tatsächlich keine mathematische Formel für eine Zufallsfunktion, und selbst wenn es eine gäbe, würden Sie viel codieren, um dies zu erreichen. Da Sie keine Bedingungen für die Laufruhe angegeben haben, ist das Geschwindigkeitsprofil $ C ^ 0 $ kontinuierlich (da Sie sich jedoch nicht mit Robotern befassen, müssen Sie sich keine Gedanken über diskontinuierliche Beschleunigungsprofile machen).
quelle
Die übliche Art, eine zunehmende Folge von N Zufallszahlen aus [0,1] zu erzeugen, besteht darin, N Zufallszahlen in einem beliebigen Bereich zu erzeugen, sie dann alle durch ihre Gesamtsumme zu dividieren und sie dann einzeln zu summieren, um die zu erhalten Reihenfolge.
Dies kann durch Generieren dieser Werte für X und Y auf 2D erweitert werden. Sie können N erhöhen, um die gewünschte Granularität zu erhalten.
In der ähnlichen Antwort von @ teodron haben Sie Effizienzprobleme mit großen Zeitskalen angeführt. Ohne das eigentliche Problem zu kennen, kann ich nicht sagen, ob dieses Anliegen berechtigt ist. Eine andere Möglichkeit wäre, für kleines N zu generieren und das Ergebnis einfach zu glätten. Je nach Anwendung kann dies tatsächlich zu besseren Ergebnissen führen.
N = 100, keine Glättung
N = 15 mit Glättung
quelle
Ich schlage diese Implementierung vor, die von der Summe der Oktaven inspiriert ist, die im fraktalen Rauschen zu finden sind, wobei hier und da ein bisschen billiger Arsch schlurft. Ich glaube, es ist ziemlich schnell und kann eingestellt werden, indem weniger Oktaven als in den Parametern gespeichert werden, mit einem Genauigkeitsverlust von ungefähr
1/2^octave
.Sie können es als stückweise Implementierung betrachten, die nur O-Zeit (log (Teile)) benötigt . Das Parameterarray wird sowohl für die Pivot-Position zum Teilen und Erobern als auch für die zurückgelegte Strecke beim Erreichen des Pivots verwendet.
Dies könnte durch Vorberechnung der Gleitkommadivisionen beschleunigt werden, wobei dreimal so viele Informationen gespeichert werden.
Dies ist ein kurzes Beispiel:
Das Beispiel wurde mit dem folgenden Code erhalten:
quelle
Laut denken und Kalkül zugeben ist nicht meine Stärke ... ist das vielleicht nicht möglich? Um ein offensichtliches Muster zu vermeiden, muss der Durchschnitt der Rauschfunktion über jede Änderung von x nahe Null sein, und um Monotonie zu gewährleisten, muss die Rauschamplitude über diese Änderung von x kleiner sein als die Änderung von x, wie es jede größere Amplitude könnte führen zu einem niedrigeren Wert bei x 'relativ zu x. Dies würde jedoch bedeuten, dass eine solche Funktion beim Reduzieren von dx gegen 0 auch dA (wobei A die Amplitude ist) gegen Null reduzieren muss, was bedeutet, dass Sie keinen Beitrag von einer kompatiblen Rauschfunktion erhalten.
Ich kann mir vorstellen, dass es möglich ist, eine Funktion zu formulieren, die den Rauschbeitrag allmählich verringert, wenn sich x 1 nähert, aber Ihnen eine gekrümmte Funktion gibt, die sich verlangsamt, wenn sich x 1 nähert, was meiner Meinung nach nicht das ist, was Sie wollen.
quelle
g(x) = 1 - f(1 - x)
, die stattdessen beschleunigt, wenn x von 0 abweicht.