<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://wiki-de.moshellshocker.dns64.de/index.php?action=history&amp;feed=atom&amp;title=Garland-Heckbert-Algorithmus</id>
	<title>Garland-Heckbert-Algorithmus - Versionsgeschichte</title>
	<link rel="self" type="application/atom+xml" href="https://wiki-de.moshellshocker.dns64.de/index.php?action=history&amp;feed=atom&amp;title=Garland-Heckbert-Algorithmus"/>
	<link rel="alternate" type="text/html" href="https://wiki-de.moshellshocker.dns64.de/index.php?title=Garland-Heckbert-Algorithmus&amp;action=history"/>
	<updated>2026-05-31T12:54:50Z</updated>
	<subtitle>Versionsgeschichte dieser Seite in Wikipedia (Deutsch) – Lokale Kopie</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://wiki-de.moshellshocker.dns64.de/index.php?title=Garland-Heckbert-Algorithmus&amp;diff=2345905&amp;oldid=prev</id>
		<title>imported&gt;Wikibrechtus am 24. Juni 2023 um 16:09 Uhr</title>
		<link rel="alternate" type="text/html" href="https://wiki-de.moshellshocker.dns64.de/index.php?title=Garland-Heckbert-Algorithmus&amp;diff=2345905&amp;oldid=prev"/>
		<updated>2023-06-24T16:09:39Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Neue Seite&lt;/b&gt;&lt;/p&gt;&lt;div&gt;Der &amp;#039;&amp;#039;&amp;#039;Garland-Heckbert-Algorithmus&amp;#039;&amp;#039;&amp;#039; ist ein Verfahren der [[Computergrafik]], mit dem der Detailgrad eines als [[Dreiecksnetz]] modellierten 3D-Körpers kontrolliert reduziert werden kann, ohne dabei das grundsätzliche Aussehen des Körpers zu verändern. Dies geschieht [[inkrementell]], wobei immer eine Kante des Dreiecksnetzes gelöscht und die beiden [[adjazent]]en Knoten zu einem einzelnen Knoten zusammengefasst werden. Es wird immer diejenige Kante gelöscht, deren Entfernen die geringste optische Veränderung des Körpers bewirkt.&lt;br /&gt;
&lt;br /&gt;
Der [[Algorithmus]] wurde 1997 in einer Veröffentlichung von [[Michael Garland]] und [[Paul Heckbert]] vorgestellt&amp;lt;ref&amp;gt;M. Garland and P. Heckbert. Surface Simplification Using Quadric Error Metrics. In Proceedings of SIGGRAPH 97. ([http://mgarland.org/papers/quadrics.pdf PDF])&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Algorithmus ==&lt;br /&gt;
[[Datei:Edge contraction.svg|miniatur|280px|rechts|Kantenkontraktion]]&lt;br /&gt;
In einem Dreiecksnetz wird das Löschen einer Kante und Zusammenfassen der übrig gebliebenen Knoten als [[Kantenkontraktion]] oder -kollaps bezeichnet. Der Algorithmus gibt Auskunft darüber, welche Kante gelöscht werden muss, und an welcher Stelle der neu entstandene Knoten platziert wird.&lt;br /&gt;
&lt;br /&gt;
Dazu wird eine [[Quadrik|Fehlerquadrik]] verwendet, die jedem Knoten und jeder Kante zugeordnet wird. Diese gibt Auskunft darüber, wie groß der entstehende optische Fehler wäre, wenn die entsprechende Kante kontrahiert werden würde. Gleichzeitig kann mit ihr berechnet werden, wo der neu entstehende Knoten platziert werden muss, damit genau dieser Fehler (und kein größerer) entsteht.&lt;br /&gt;
&lt;br /&gt;
=== Pseudocode ===&lt;br /&gt;
Berechne zunächst für jeden Knoten b&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt; die zugehörige initiale Fehlerquadrik Q&amp;lt;sub&amp;gt;b&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;&amp;lt;/sub&amp;gt;. Siehe dazu weiter unten.&lt;br /&gt;
&lt;br /&gt;
Danach iteriere solange, bis der gewünschte Detailgrad erreicht ist:&lt;br /&gt;
#Jede Kante erhält als Quadrik Q&amp;lt;sub&amp;gt;E&amp;lt;sub&amp;gt;j&amp;lt;/sub&amp;gt;&amp;lt;/sub&amp;gt; die Summe der Quadriken ihrer beiden Endpunkte.&lt;br /&gt;
#Berechne anhand der Quadrik für jede Kante, an welcher Stelle der zusammengezogene Knoten erstellt werden müsste, um minimalen Fehler beim Kollabieren der Kante zu verursachen.&lt;br /&gt;
#Ordne alle Kanten anhand ihrer Fehler. Kollabiere die Kante mit dem kleinsten Fehler.&lt;br /&gt;
#Ordne dem neuen Knoten als Quadrik die Summer der Quadriken der beiden Endpunkte der Kante zu.&lt;br /&gt;
#Update die Quadriken aller Kanten, die durch den Kollaps der Kante verändert wurden.&lt;br /&gt;
&lt;br /&gt;
=== Detaillierte Beschreibung ===&lt;br /&gt;
&lt;br /&gt;
==== Initiale Fehlerquadriken ====&lt;br /&gt;
&lt;br /&gt;
Den Fehler, der beim Zusammenfassen zweier Knoten v&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; und v&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; zu einem neuen v&amp;lt;sub&amp;gt;neu&amp;lt;/sub&amp;gt; entsteht, definiert man als: Quadrat der Summe der Abstände, die v&amp;lt;sub&amp;gt;neu&amp;lt;/sub&amp;gt; zu allen [[Fläche (Mathematik)|Flächen]] hat, die durch irgendeins der Dreiecke definiert werden, welche an v&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; oder v&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; grenzen.&lt;br /&gt;
&lt;br /&gt;
Um zunächst den Abstand eines Punktes v&amp;lt;sub&amp;gt;neu&amp;lt;/sub&amp;gt; zu einer Fläche F zu berechnen, kann folgende Formel verwendet werden:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;dist(v_\text{neu}, F) = n^T \cdot (v_\text{neu}-b)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dabei ist b ein beliebiger Punkt in der Fläche (z.&amp;amp;nbsp;B. einer der Eckpunkte des Dreiecks, das in der Fläche liegt), und n&amp;lt;sup&amp;gt;T&amp;lt;/sup&amp;gt; ist der Normalenvektor der Fläche (zum Zeilenvektor [[Transponierte Matrix|transponiert]]).&lt;br /&gt;
&lt;br /&gt;
Bildet man nun wie vorgesehen das Quadrat dieses Abstands, erhält man:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
dist(v_\text{neu}, F)^2 &amp;amp;= (n^T \cdot (v_\text{neu}-b))^2\\&lt;br /&gt;
&amp;amp;= (n^T \cdot (v_\text{neu}-b)) \cdot (n^T \cdot (v_\text{neu}-b))\\&lt;br /&gt;
&amp;amp;= (n^Tv_\text{neu} - n^Tb) \cdot (n^Tv_\text{neu} - n^Tb)\\&lt;br /&gt;
&amp;amp;= (n^Tv_\text{neu})^2 - n^Tv_\text{neu} \cdot n^Tb - n^Tb \cdot n^Tv_\text{neu} + (n^Tb)^2\\&lt;br /&gt;
&amp;amp;= {v_\text{neu}}^Tn\cdot n^Tv_\text{neu} - b^Tn\cdot n^Tv_\text{neu} - {v_\text{neu}}^Tn\cdot n^Tb + b^Tn\cdot n^Tb&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verwendet man [[homogene Koordinaten]], so ist diese Rechnung gleichbedeutend mit:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
dist(v_\text{neu}, F)^2 = ( v_{\text{neu}_x} v_{\text{neu}_y} v_{\text{neu}_z} 1) \cdot&lt;br /&gt;
\begin{pmatrix} nn^T &amp;amp; -nn^Tb \\ -b^Tnn^T &amp;amp; b^Tnn^Tb\end{pmatrix} \cdot&lt;br /&gt;
\begin{pmatrix} v_{\text{neu}_x} \\ v_{\text{neu}_y} \\ v_{\text{neu}_z} \\ 1 \end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Matrix &amp;lt;math&amp;gt; Q_F = \begin{pmatrix} nn^T &amp;amp; -nn^Tb \\ -b^Tnn^T &amp;amp; b^Tnn^Tb\end{pmatrix} &amp;lt;/math&amp;gt; wird als Fehlerquadrik der Fläche F bezeichnet.&lt;br /&gt;
&lt;br /&gt;
Betrachtet man nun einen Knoten b des Dreiecksnetzes, so kann ihm als Fehlerquadrik Q&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt; die Summe der Quadriken seiner angrenzenden Dreiecksflächen F&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt; zugewiesen werden.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; Q_b = \sum_i Q_{F_i} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Quadrik Q&amp;lt;sub&amp;gt;b&amp;lt;/sub&amp;gt; wird zur Initialisierung des Algorithmus für jeden Knoten des Dreiecksnetzes berechnet.&lt;br /&gt;
&lt;br /&gt;
==== Iterationsschritt ====&lt;br /&gt;
&lt;br /&gt;
===== Berechnung der zu kontrahierenden Kante =====&lt;br /&gt;
&lt;br /&gt;
Jede Kante e&amp;lt;sub&amp;gt;j&amp;lt;/sub&amp;gt; des Dreiecksnetzes erhält als Quadrik Q&amp;lt;sub&amp;gt;e&amp;lt;sub&amp;gt;j&amp;lt;/sub&amp;gt;&amp;lt;/sub&amp;gt; die Summe der Quadriken ihrer Endpunkte b&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; und b&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; Q_{e_j} = Q_{b_1} + Q_{b_2} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Falls der Kante e&amp;lt;sub&amp;gt;j&amp;lt;/sub&amp;gt; vorher noch keine Quadrik zugeordnet war (nur im ersten Iterationsschritt), oder falls sich die Quadrik im Vergleich zum letzten Iterationsschritt verändert hat (weil einer der Endpunkte durch Kantenkontraktion verschoben wurde), muss nun berechnet werden:&lt;br /&gt;
* Welcher Punkt v&amp;lt;sub&amp;gt;neu&amp;lt;/sub&amp;gt; beim Kontrahieren von e&amp;lt;sub&amp;gt;j&amp;lt;/sub&amp;gt; einen möglichst kleinen Fehler verursachen würde&lt;br /&gt;
* Wie groß der verursachte Fehler wäre.&lt;br /&gt;
Um den optimalen Punkt v&amp;lt;sub&amp;gt;neu&amp;lt;/sub&amp;gt; zu bestimmen, muss also der [[Extremwert|Minimalwert]] der Fehlerfunktion gefunden werden, d.&amp;amp;nbsp;h. alle [[Partielle Ableitung|partiellen Ableitungen]] von &amp;lt;math&amp;gt;( {v_\text{neu}}^T \quad 1) \cdot Q_{e_j} \cdot \begin{pmatrix} v_\text{neu} \\ 1 \end{pmatrix}&amp;lt;/math&amp;gt; müssen gleich 0 sein.&lt;br /&gt;
&lt;br /&gt;
Berechnet man diese Ableitungen, erhält man folgendes zu lösende Gleichungssystem:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{pmatrix} &amp;amp; nn^T   &amp;amp; &amp;amp; -nn^Tb \\ 0 &amp;amp; 0 &amp;amp; 0 &amp;amp; 1\end{pmatrix} \cdot&lt;br /&gt;
\begin{pmatrix} v_{\text{neu}_x} \\ v_{\text{neu}_y} \\ v_{\text{neu}_z} \\ 1 \end{pmatrix} =&lt;br /&gt;
\begin{pmatrix}0 \\ 0 \\ 0 \\ 1 \end{pmatrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dabei können sich mehrere Fälle ergeben:&lt;br /&gt;
* Die Matrix &amp;lt;math&amp;gt; \begin{pmatrix} &amp;amp; nn^T   &amp;amp; &amp;amp; -nn^Tb \\ 0 &amp;amp; 0 &amp;amp; 0 &amp;amp; 1\end{pmatrix} &amp;lt;/math&amp;gt; ist [[Inverse Matrix|invertierbar]]: Der Punkt v&amp;lt;sub&amp;gt;neu&amp;lt;/sub&amp;gt; kann einfach durch das Gleichungssystem berechnet werden.&lt;br /&gt;
* Die Matrix &amp;lt;math&amp;gt; \begin{pmatrix} &amp;amp; nn^T   &amp;amp; &amp;amp; -nn^Tb \\ 0 &amp;amp; 0 &amp;amp; 0 &amp;amp; 1\end{pmatrix} &amp;lt;/math&amp;gt; ist nicht invertierbar: Der optimale Wert für v&amp;lt;sub&amp;gt;neu&amp;lt;/sub&amp;gt; kann auf der Verbindungsstrecke der beiden Kantenendpunkte b&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; und b&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; gefunden werden. Man beschreibt dann v&amp;lt;sub&amp;gt;neu&amp;lt;/sub&amp;gt; als [[Linearkombination]] der beiden Endpunkte: &amp;lt;math&amp;gt; {v_\text{neu}}^*(\lambda) = (1-\lambda)\cdot b_1 + \lambda \cdot b_2 &amp;lt;/math&amp;gt; und sucht stattdessen das Minimum von &amp;lt;math&amp;gt;dist(v_\text{neu}, F)^2 = ( ({v_\text{neu}}^*)^T \quad 1) \cdot Q_{e_j} \cdot \begin{pmatrix} {v_\text{neu}}^* \\ 1 \end{pmatrix}&amp;lt;/math&amp;gt; bezüglich λ. Dies geschieht durch einfache Ableitung der Funktion nach λ und setzen dieser Ableitung = 0.&lt;br /&gt;
* Sollte auch die zweite Methode kein Ergebnis liefern, so wird einfach der Mittelpunkt zwischen b&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; und b&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; verwendet, oder b&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; oder b&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; selbst.&lt;br /&gt;
&lt;br /&gt;
Nachdem nun v&amp;lt;sub&amp;gt;neu&amp;lt;/sub&amp;gt; bekannt ist, wird der entstandene Fehler &amp;lt;math&amp;gt;( {v_\text{neu}}^T \quad 1) \cdot Q_{e_j} \cdot \begin{pmatrix} v_\text{neu} \\ 1 \end{pmatrix}&amp;lt;/math&amp;gt; berechnet. Dieser Fehler wird in eine [[Prioritätswarteschlange]] eingetragen, wobei der niedrigste Fehler das Top-Element der Warteschlange ist.&lt;br /&gt;
&lt;br /&gt;
===== Kontrahieren der Kante =====&lt;br /&gt;
&lt;br /&gt;
Aus der Warteschlange wird das Top-Element entfernt. Dieses Element entspricht derjenigen Kante, deren Kontraktion den geringsten Fehler verursacht. Die Kante wird nun kontrahiert, und dem dabei neu entstehenden Punkt v&amp;lt;sub&amp;gt;neu&amp;lt;/sub&amp;gt; wird die Fehlerquadrik der dabei zerstörten Kante zugewiesen. Dies bewirkt, dass der Fehler in den folgenden Iterationsschritten nicht nur von dem jeweils aktuellen Dreiecksnetz abhängt, sondern auch die vorherigen Veränderungen mit einbezogen werden.&lt;br /&gt;
&lt;br /&gt;
== Referenzen ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Algorithmus (Computergrafik)]]&lt;br /&gt;
[[Kategorie:Geometrische Modellierung]]&lt;/div&gt;</summary>
		<author><name>imported&gt;Wikibrechtus</name></author>
	</entry>
</feed>