Der Hobby-Algorithmus
von Philipp Stephani
Einführung
In der zweidimensionalen Computergrafik stehen wir häufig vor dem Problem, durch eine gegebene Anzahl von Punkten eine glatte Kurve zu legen. Meist werden hierfür Splines verwendet. Dabei handelt es sich um miteinander verbundene Kurvenstücke. Besonders beliebt sind kubische Bézierkurven, da sie durch vier Kontrollpunkte mit einfacher geometrischer Bedeutung definiert sind und mit Hilfe des de-Casteljau-Algorithmus effizient und numerisch stabil berechnet werden können. In Abbildung 1 sehen wir zwei verbundene Bézierkurven, die beispielsweise Teil eines Béziersplines sein könnten. Die Bézierkurve auf der rechten Seite schneidet die beiden Knotenpunkte und
. Die Tangenten an den Schnittpunkten schneiden die zugehörigen Kontrollpunkte
und
. Der Abstand von
und
von
bzw.
gibt grob gesprochen an, wie sehr sich die Kurve an die Tangenten anschmiegt.
Abbildung 1: Winkel und Kontrollpunkte von Bézierkurven
Manchmal wollen wir Béziersplines durch eine Anzahl Knotenpunkte zeichnen, ohne die anderen Kontrollpunkte explizit gegeben zu haben. Vielmehr soll das resultierende Spline die Knotenpunkte so natürlich wie möglich, d. h. mit möglichst geringer Gesamtkrümmung, interpolieren. Dies mathematisch zu quantifizieren, ist ziemlich kompliziert. Ich möchte hier lediglich als Ergebnis den Hobby-Algorithmus vorstellen. Dieser wurde von dem amerikanischen Mathematiker John D. Hobby im Jahre 1985 entwickelt und von Donald E. Knuth für sein Schriftdefinitionssystem METAFONT, welches in TeX und LaTeX benutzt wird, eingesetzt. Verwendung findet der Algorithmus ebenfalls in den auf METAFONT basierenden Vektorgrafiksprachen METAPOST und Asymptote.
Definitionen
Sei mit
. Gegeben seien
Knotenpunkte
, durch die wir ein kubisches Bézierspline mit durch den Hobby-Algorithmus ermittelten Kontrollpunkten legen wollen. Zur notationellen Vereinfachung definieren wir:
Dabei bezeichnen die Transposition des Vektors
(sodass die
Spaltenvektoren im
sind) und
die übliche euklidische Norm.
Grundsätzlich lassen sich zwei Typen von Splines unterscheiden: offene und geschlossene. Geschlossene Splines zeichnen sich gegenüber offenen dadurch aus, dass der letzte Punkt durch ein weiteres Kurvenstück wieder mit dem ersten Punkt
verbunden ist. Geschlossene Splines heißen auch zyklisch. Bezüglich des Hobby-Algorithmus unterscheiden sich offene und geschlossene Splines in einigen wichtigen Details. Das Verhalten an den inneren Knotenpunkten
ist jedoch genau gleich, sodass wir zunächst diese Punkte betrachten und erst später zwischen den beiden Splinetypen differenzieren.
Die inneren Knotenpunkte
Zunächst führen wir für jeden inneren Knotenpunkt die in Abbildung 1 eingezeichneten Winkel ein. ist der Winkel zwischen der Verbindungsstrecke zwischen
und
sowie der Verbindungsstrecke zwischen
und
, d. h. zwischen den Vektoren
und
. Die Winkel
werden dabei so gewählt, dass
gilt.
ist der Winkel zwischen
und der Verbindungsstrecke von
und
. Schließlich ist
der Winkel zwischen der Verbindungsstrecke von
und
und der Verbindungsstrecke von
und
. Zu beachten ist, dass auf diese Weise auch
und
, nicht aber
,
,
und
definiert werden können.
Damit der Spline bei stetig differenzierbar ist, müssen
,
und
auf einer Geraden liegen, und zwar derart, dass
zwischen
und
liegt. Daraus folgt die Bedingung, dass
,
und
sich zum Vollwinkel bzw. Nullwinkel ergänzen. Diese Bedingung werden wir später benötigen.
Durch die Winkel und
ist zwar die Richtung der Kontrollpunkte
und
bezüglich
gegeben, nicht aber ihr Abstand von
. Wir benötigen also pro innerem Knotenpunkt noch zwei weitere Parameter. Diese sollen mit der lokalen Spannungsenergie des Splines an den Kontrollpunkten in Verbindung stehen und werden deshalb Spannungsparameter genannt.
soll hierbei den Spannungsparameter des bei
auslaufenden Kurvensegments bezeichnen,
entsprechend den des einlaufenden Segments. Im Hobby-Algorithmus werden die Spannungsparameter so definiert, dass sich minimale Gesamtspannungsenergie (und damit natürlichstes Aussehen) für
ergibt.
Zunächst betrachten wir lediglich eine einzelne Bézierkurve zwischen den Punkten und
. Wir können das Problem vereinfachen, indem wir ausnutzen, dass bei einer gegebenen affinen Transformation
diejenige Bézierkurve, die durch die mit
transformierten Kontrollpunkte definiert ist, identisch mit der durch
transformierten Bézierkurve ist. Mathematisch formuliert bedeutet dies, dass für die Bézierkurve
mit den Kontrollpunkten
,
,
und
gilt:
Daraus folgern wir, dass wir eine Bézierkurve mit den Knotenpunkten und
betrachten und die ermittelten Kontrollpunkte mit der affinen winkeltreuen Transformation
, die
auf
und
auf
abbildet, transformieren können.
ist eindeutig bestimmt durch
Für die zwei untransformierten Kontrollpunkte und
gilt dann:
Dabei sind der Abstand zwischen
und
sowie
der Abstand zwischen
und
. Hat man
und
erst einmal gefunden, ergeben sich die gesuchten Kontrollpunkte
und
einfach durch Anwendung von
:
Die eigentliche Schwierigkeit am Hobby-Algorithmus ist die Ermittlung von ,
,
und
. Hobby entwickelt in seiner Publikation zunächst eine Methode, um
und
aus den Winkeln zu berechnen. Es gilt:
Entscheidend für die Qualität des Ergebnisses ist die Auswahl der Funktionen und
.
Hobby wählt:
mit
Hierbei sind ,
und
experimentell zu ermittelnde Konstanten; METAFONT und Asymptote wählen:
Damit ist das Problem zumindest für die inneren Knotenpunkte bis auf die Bestimmung der Winkel und
gelöst. Für letzteres führt Hobby eine Krümmungsfunktion k ein:
Diese Funktion ist jedoch nichtlinear in den Variablen und
, was auf ein schwierig zu lösendes nichtlineares Gleichungssystem für
und
hinausliefe. Um dies zu umgehen, wird
nach
entwickelt und nur der lineare Term
benutzt. Man erhält unter Benutzung der linearen Näherungen
und
:
,
,
,
.
Diese Linearisierung führt dazu, dass die Interpolation bei sehr großen Winkeln ,
nicht mehr optimal ist. Derartig große Winkel kommen jedoch in der Praxis relativ selten vor, sodass die linearisierte Krümmungsfunktion für unsere Zwecke eine mehr als ausreichende Näherung darstellt.
Damit die Krümmung an den Knotenpunkten übereinstimmt, muss
gelten. Aus der Stetigkeit der linearisierten Krümmungsfunktion ergibt sich wiederum:
Mit den Abkürzungen
,
,
,
vereinfacht sich die letzte Gleichung zu:
Weiterhin gilt, wie oben erwähnt, aufgrund der stetigen Differenzierbarkeit an den Knotenpunkten:
Dies alles gilt natürlich nur an den inneren Knotenpunkten. Wir haben aus der Stetigkeit der Krümmungsfunktion und aus der stetigen Differenzierbarkeit des Splines ebenfalls
, insgesamt also
Bedingungen erhalten. Für die
Kurvensegmente benötigen wir je zwei zusätzliche Kontrollpunkte. Die Abstände
und
der Kontrollpunkte von den Knotenpunkten lässt sich wie oben gezeigt aus den Winkeln
und
berechnen, somit benötigen wir pro Kontrollpunkt nur eine Gleichung (für den jeweils anliegenden Winkel). Dennoch fehlen immer noch zwei Bedingungen, für die wir die äußeren Knotenpunkte
und
betrachten und erstmals zwischen offenen und geschlossenen Splines unterscheiden müssen.
Offene Splines
Hier müssen wir zwei weitere Gleichungen künstlich einführen, da wir keine periodischen Randbedingungen haben. Analog zu den Spannungsparametern definiert Hobby die Wirbelparameter und
derart, dass sich für
ein natürliches Aussehen ergibt. Die Wirbelparameter beeinflussen das Aussehen des Splines an den Endpunkten. Für
gibt es darüberhinaus einen weiteren Ausgangsspannungsparameter
; analog existiert für
ein Eingangsspannungsparameter
. Man wählt die folgenden Randbedingungen:
,
.
mit
,
.
Damit lassen sich und
aus den anderen Gleichungen eliminieren:
,
.
Für lässt sich
ebenfalls durch
ersetzen:
Weiterhin gilt für :
.
Definiert man nun
,
,
,
,
,
,
,
so gilt:
,
,
.
Dies ist ein ein lineares tridiagonales Gleichungssystem der Form
mit Subdiagonale , Diagonale
, Superdiagonale
und rechtsseitigem Vektor
, welches mit dem Gaußalgorithmus in linearer Zeit gelöst werden kann.
Sind alle und
größer als
, so gilt wegen
,
,
und
an den inneren Knotenpunkten:
.
An den Randpunkten folgt analog, falls zusätzlich und
gelten:
,
.
Somit ist die Systemmatrix diagonaldominant. Das führt dazu, dass in diesem (in der Realität meistens angenommenen) Fall keine Pivotisierung nötig ist.
Geschlossene Splines
Hier haben wir periodische Randbedingungen vorliegen, weshalb es sich anbietet, die Indizes zyklisch zu definieren:
,
,
,
,
,
,
,
,
,
.
Weiterhin definieren wir und
als den Winkel zwischen
und
sowie
als den Winkel zwischen
und
. Damit können wir die Gleichungen Kruemmung und Differenzierbarkeit auch für
und
anwenden. Mit den Definitionen
,
,
,
erhalten wir wieder
Für und
gelten mit obigen Definitionen die Spezialfälle:
,
.
Aufgrund der Periodizität des Problems ist die Gleichung für identisch zu der Gleichung für
. Damit haben wir also für die
Winkel
(ein Winkel pro Knotenpunkt)
Gleichungen gefunden, die nun aber kein einfaches tridiagonales Gleichungssystem mehr, sondern ein zyklisches tridiagonales Gleichungssystem der Form
bilden. Unter Zuhilfenahme der Sherman-Morrison-Formel kann auch dieses System mit linearer Zeitkomplexität gelöst werden.
Quellen
- John D. Hobby: Smooth, Easy to Compute Interpolating Splines, 1985
ftp://db.stanford.edu/pub/cstr/reports/cs/tr/85/1047/ - Martin Kerscher, Joachim Puls, Sigmung Stintzing: Numerik für Physiker, 2007
http://www.mathematik.uni-muenchen.de/~kerscher/vorlesungen/numeriksose08/doc/script.pdf - William H. Press, Saul A. Teukolsky, William T. Vetterling, Brian P. Flannery:
Numerical Recipes in C++, Second Edition, Cambridge University Press
Ihre Meinung
Falls Sie Fragen zu diesem Tutorial haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.