Es gibt unendlich viele solche Sweep-Funktionen. Hier leite ich eine Sweep-Funktion her, die möglichst lange einen linearen Verlauf hat, aber am Anfang weich beschleunigt und am Ende weich verzögert.
Um eine Sweep-Funktion universal einsetzen zu können, wird sie so definiert, dass der Definitions-Bereich zwischen 0 und 1 in einen Werte-Bereich zwischen 0 und 1 abgebildet wird, sodass also f(0) = 0 und f(1) = 1 ist. Mit folgender Formel kann jederzeit ein beliebiger Zeitabschnitt in einen beliebigen Wegabschnitt transformiert werden, sodass immer dieselbe Sweep-Funktion verwendet werden kann:
(1) | ||||||||||
wobei' |
|
Der grüne Teil der Formel transformiert einen Zeitabschnitt von tmin bis tmax in einen Wertebereich zwischen 0 und 1, wie er von der Sweep-Funktion erwartet wird. Die Sweep-Funktion liefert ihrerseits einen Wert zwischen 0 und 1. Mit dem blauen Teil der Formel wird dieser in einen Wegbereich zwischen xmin und xmax transformiert.
Zur Demonstration einer Sweep-Funktion nehme ich folgende einfache Formel und erstelle damit eine Animation. Die Grafik zur Formel ist rechts abgebildet.
(2) |
Die Animation starte bei tmin = 0 s und ende bei tmax = 3 s. In dieser Zeit soll ein Objekt eine Strecke auf dem Bildschirm von xmin = 50 px bis xmax = 450 px zurücklegen. Mit der Formel (2) sieht der Bewegungsablauf folgendermassen aus:
Für ein Panorama-Plugin, welches ein Panoramabild in einem Fenster langsam hin und her schwenkt, suche ich eine Sweep-Funktion, welche in einem weiten Bereich möglichst linear verläuft, jedoch am Umkehrpunkt, also am Anfang und am Ende der Sweep-Funktion, langsam abbremst.
Die Graphik einer solchen Funktion ähnelt jener der Cosinus-Funktion oben, ist jedoch nur ganz am Anfang und am Ende abgerundet und dazwischen praktisch eine Gerade. Die Steigung der Sweep-Funktion muss bei t = 0 und bei t = 1 horizontal sein, damit ein Umkehren der Bewegung ohne Sprung erfolgt.
Um eine solche Sweep-Funktion zu entwickeln, beginne ich bei der Betrachtung des Geschwindigkeitsverlaufs. Der Geschwindigkeitsverlauf hat folgende Eigenschaften:
Wenn ich eine Funktion y = v(t) gefunden habe, welche diese Eigenschaften erfüllt, kann ich durch Integrieren der Funktion die entsprechende Sweep-Funktion y = f(t) erhalten. Die t-Achse entspricht in der Grafik der x-Achse. Ich verwende ab jetzt die Variable x anstelle von t.
Die Sweep-Funktion ist in beiden Achsen symmetrisch, wobei die Symmetrieachsen durch den Punkt (0,5, 0,5) laufen. Für die Herleitung der Sweepfunktion ist es einfacher, wenn ich zunächst die X- und Y-Achse als Symmetrieachsen verwende und die gefundene Sweepfunktion erst danach in den gewünschten Bereich transformiere.
Ich suche also zunächst eine Geschwindigkeitsfunktion v(x), welche bei x = −1 und x = +1 den Wert y = 0 hat und dazwischen möglichst lange einen konstanten Wert, zum Beispiel y = 1 hat. Eine Geschwindigkeitsfunktion mit dem gewünschten Verhalten erhalte ich über eine umgekehrte Parabel (orange Kurve in der Grafik):
(3) |
welche durch Potenzieren von x mit einer ganzen Zahl n in die gewünschte Form gebracht werden kann (grüne Kurve: n = 2 und blaue Kurve n = 6):
(4) | |
(5) |
Ich könnte noch höhere Potenzen verwenden, um sie oben noch mehr abzuflachen. Ich beschränke mich für dieses Beispiel jedoch auf eine Potenz von 2 und 6.
Die Sweep-Funktion stellt den Weg als Funktion eines Zeitparameters x dar. Ich habe nun aber eine Funktion, welche die Geschwindigkeit als Funktion von x angibt. Um daraus die Weg-Funktion zu berechnen, muss ich die Geschwindigkeitsfunktion integrieren:
(6) | |
(7) |
Mit n = 2 erhalte ich die hellgrüne Kurve in der Grafik rechts. Diese Kurve muss noch mit einem Faktor s1 multipliziert werden, damit sie genau im Bereich -1 bis +1 zu liegen kommt:
(8) |
Den Faktor s1 erhalte ich, wenn ich verlange, dass f1(x = 1) = 1 ist:
(9) | |
Somit erhalte ich die Formel, welche der grünen Kurve entspricht:
(10) |
Analog erhalte ich s2 = 13 / 12 für die Funktion f2(x):
(11) |
Die grüne Kurve hat bereits den gewünschten Verlauf, sie liegt jedoch noch im Bereich -1 bis +1 in beiden Achsen. Mit ein paar Transformationen kann sie in den Bereich 0 bis 1 skaliert und verschoben werden:
Schritt 1 und 2 kann ich zusammenfassen zu 2 · (x − 0,5) = (2·x − 1)
Somit erhalte ich die Formeln für die gewünschten Sweep-Funktionen:
(12) | |
(13) |
In der Grafik rechts ist die Sweep-Funktion f1(x) grün und die Funktion f2(x) blau dargestellt. Zum Vergleich ist hellrot nochmals die Cosinus-Funktion eingezeichnet.
Wie man sieht sind die Sweep-Funktionen in einem weiten Bereich annähernd linear, wogegen die Cosinus-Funktion auf dem ganzen Weg gekrümmt ist. Je höher die Potenz n, desto breiter ist der lineare Bereich.
Die allgemeine Formel für ein beliebiges n > 0 ist:
(14) |
|
In der folgenden Animation können die verschiedenen Sweep-Funktionen verglichen werden:
Zum Abschluss noch das JavaScript der Sweep-Funktionen:
function f1( x ) { var xx = 2 * x - 1; return 0.5 + (5/8) * (xx - (Math.pow( xx, 5 ) / 5)); } function f2( x ) { var xx = 2 * x - 1; return 0.5 + (13/24) * (xx - (Math.pow( xx, 13 ) / 13)); }