Grundlagen der Computergeometrie Γbung 3 1 Affinkombination von Punkten Gegeben sei ein Affiner Raum ππ = (π«π«, π±π±). Wir haben in der letzten Γbung gelernt, dass man a) zwei Punkte subtrahieren kann. Das Ergebnis ist ein Vektor. b) einen Punkt und einen Vektor addieren kann. Das Ergebnis ist eine Verschiebung des Punktes. Beide MΓΆglichkeiten kann man aus den Axiomen fΓΌr den Affinen Raum herleiten. Weitere Operationen mit Punkten sind nicht mΓΆglich. Insbesondere kann man Punkte nicht addieren. In der Vorlesung haben Sie aber eine Operation hergeleitet, die einer Addition von Punkten sehr Γ€hnlich sieht, nΓ€mlich die Affinkombination von Punkten. Dabei wird ein Punkt ππ β π«π« als gewichtete Summe der ππ Punkte ππ1 , β¦ , ππππ β π«π« dargestellt. Die Gewichte sind die reellen Zahlen πΌπΌ1 , β¦ , πΌπΌππ β β. ππ = πΌπΌ1 β ππ1 + β¦ + πΌπΌππ β ππππ FΓΌr die Gewichte gilt dabei immer, dass ihre Summe gleich 1 ist. πΌπΌ1 + β¦ + πΌπΌππ = 1 FΓΌr den Fall, dass ππ eine Affinkombination von nur zwei Punkten ist, gilt folgender Zusammenhang bei den Gewichten. πΌπΌ1 + πΌπΌ2 = 1 πΌπΌ1 = 1 β πΌπΌ2 Den Punkt ππ kann man dann wie folgt darstellen. ππ = (1 β πΌπΌ2 ) β ππ1 + πΌπΌ2 β ππ2 Diese Gleichung kann man so umstellen, dass ππ als Verschiebung des Punktes ππ1 um das πΌπΌ2 -fache des Vektors ππ2 β ππ1 dargestellt wird. ππ = 1 β ππ1 β πΌπΌ2 β ππ1 + πΌπΌ2 β ππ2 Aufgabe ππ = ππ1 + πΌπΌ2 β (ππ2 β ππ1 ) Gegeben seien die drei Punkte π΄π΄, π΅π΅, ππ β π«π«. Beschreiben Sie einen Algorithmus, der bestimmt, ob der οΏ½οΏ½οΏ½οΏ½ liegt. (3 Punkte) Punkt ππ auf der Strecke π΄π΄π΄π΄ LΓΆsung Der folgende Algorithmus basiert darauf, dass wir den Punkt ππ zunΓ€chst als Affinkombination der Punkte π΄π΄ und π΅π΅ darstellen. ππ = πΌπΌ β π΄π΄ + π½π½ β π΅π΅ Die Summe der Gewichte ist 1. Wir kΓΆnnen damit eines der Gewichte, nΓ€mlich πΌπΌ, eliminieren und den Punkt ππ als Verschiebung des Punktes π΄π΄ um das π½π½-fache des Vektors π΅π΅ β π΄π΄ darstellen. ππ = (1 β π½π½) β π΄π΄ + π½π½ β π΅π΅ ππ = 1 β π΄π΄ β π½π½ β π΄π΄ + π½π½ β π΅π΅ ππ = π΄π΄ + π½π½ β (π΅π΅ β π΄π΄) Im Hinblick auf die Aufgabenstellung gilt folgendes: β’ β’ β’ β’ Wenn π½π½ = 0 ist, dann ist ππ = π΄π΄. Wenn π½π½ = 1 ist, dann ist ππ = π΅π΅. Wenn 0 < π½π½ < 1 ist, dann liegt ππ genau zwischen π΄π΄ und π΅π΅. Wenn π½π½ < 0 oder π½π½ > 1 ist, dann liegt der Punkt nicht auf der Strecke οΏ½οΏ½οΏ½οΏ½ π΄π΄π΄π΄. Wir mΓΌssen also den Wert von π½π½ berechnen und prΓΌfen, ob dieser im Intervall [0,1] liegt. Dazu betrachten wir zunΓ€chst die Gleichung fΓΌr ππ. πππ₯π₯ π΄π΄π₯π₯ π΅π΅π₯π₯ β π΄π΄π₯π₯ οΏ½ππ οΏ½ = οΏ½π΄π΄ οΏ½ + π½π½ β οΏ½π΅π΅ β π΄π΄ οΏ½ π¦π¦ π¦π¦ π¦π¦ π¦π¦ Faktisch haben wir hier ein Gleichungssystem mit zwei Gleichungen und einer Unbekannten. Dieses gilt es zu lΓΆsen. Wie stellen die Gleichungen auf π½π½ um. π½π½1 = π½π½2 = πππ₯π₯ β π΄π΄π₯π₯ οΏ½π΅π΅ β π΄π΄ π₯π₯ π₯π₯ πππ¦π¦ β π΄π΄π¦π¦ οΏ½π΅π΅ β π΄π΄ π¦π¦ π¦π¦ Wenn π½π½1 β π½π½2 ist, dann haben wir den Fall, dass der Punkt ππ nicht auf der Geraden liegt, die durch π΄π΄ und π΅π΅ geht. Wenn aber π½π½ = π½π½1 = π½π½2 ist, dann liegt ππ auf dieser Geraden. Wenn π½π½ auΓerdem im Intervall [0,1] liegt, dann liegt ππ auch auf der Strecke οΏ½οΏ½οΏ½οΏ½ π΄π΄π΄π΄. 2 Baryzentrische Koordinaten Gegeben sei ein Affiner Raum ππ = (π«π«, π±π±). Die Dimension von ππ sei ππ. Gegeben seien weiterhin ππ + 1 Punkte ππ0 β¦ ππππ β π«π« und ππ + 1 Gewichte πΌπΌ0 β¦ πΌπΌππ β β mit πΌπΌ0 + β¦ + πΌπΌππ = 1. Der Punkt ππ β π«π« sei die folgende Affinkombination. ππ = πΌπΌ0 ππ0 + β¦ + πΌπΌππ ππππ Das Besondere dabei ist, dass der Punkt ππ im Bezug auf die Punkte ππ0 β¦ ππππ eindeutig durch die Gewichte πΌπΌ0 β¦ πΌπΌππ festgelegt ist. Letztere nennt man die baryzentrischen Koordinaten von ππ. Wichtig ist, dass die Summe der baryzentrischen Koordinaten gleich 1 ist und dass die Anzahl der Bezugspunkte genau um eins grΓΆΓer ist als die Dimension des Affinen Raums. DarΓΌber hinaus mΓΌssen die Bezugspunkte paarweise verschieden sein. Die Menge der ππ + 1 Bezugspunkte nennt man einen ππ-Simplex. Da wir in der Ebene drei Bezugspunkte benΓΆtigen, beziehen sich die baryzentrischen Koordinaten eines Punktes in der Ebene immer auf ein bestimmtes Dreieck (2-Simplex) ππ0 ππ1 ππ2 . Entsprechend beziehen sich die baryzentrischen Koordinaten eines Punktes im Raum immer auf einen bestimmten Tetraeder (3-Simplex) ππ0 ππ1 ππ2 ππ3 . Auch Vektoren kann man mittels baryzentrischer Koordinaten darstellen. Seien π½π½0 β¦ π½π½ππ β β die baryzentrischen Koordinaten eines Vektors π£π£ β π±π± bezogen auf einen bestimmten ππ-Simplex. Dann ist die Summe der Koordinaten π½π½0 + β¦ + π½π½ππ gleich 0. Aufgabe 1 4 3 3 a) Gegeben seien die Punkte π΄π΄ = οΏ½ οΏ½, π΅π΅ = οΏ½ οΏ½, πΆπΆ = οΏ½ οΏ½ und ππ = οΏ½ οΏ½. Berechnen Sie die 2 1 7 3 baryzentrischen Koordinaten von ππ bezΓΌglich des Dreiecks π΄π΄π΄π΄π΄π΄. (3 Punkte) b) Nennen Sie einen Nachteil baryzentrischer Koordinaten gegenΓΌber kartesischen Koordinaten, insbesondere im Hinblick auf eine effiziente Implementierung. (1 Punkt) c) Implementieren Sie die Methode Triangle2.GetBarycentricCoordinates(). Starten Sie anschlieΓend das Programm und evaluieren Sie, ob Ihre Implementierung korrekt ist. LΓΆsung a) FΓΌr die Berechnung der baryzentrischen Koordinaten kann man die Cramersche Regel anwenden. πππ₯π₯ det οΏ½πππ¦π¦ 1 πππ΄π΄ = π΄π΄π₯π₯ det οΏ½π΄π΄π¦π¦ 1 π΄π΄π₯π₯ det οΏ½π΄π΄π¦π¦ 1 πππ΅π΅ = π΄π΄π₯π₯ det οΏ½π΄π΄π¦π¦ 1 π΄π΄π₯π₯ det οΏ½π΄π΄π¦π¦ 1 πππΆπΆ = π΄π΄π₯π₯ det οΏ½π΄π΄π¦π¦ 1 π΅π΅π₯π₯ π΅π΅π¦π¦ 1 π΅π΅π₯π₯ π΅π΅π¦π¦ 1 π΅π΅π₯π₯ πΆπΆπ₯π₯ 3 π΅π΅π¦π¦ πΆπΆπ¦π¦ οΏ½ det οΏ½3 1 1 1 = π΅π΅π₯π₯ πΆπΆπ₯π₯ 1 π΅π΅π¦π¦ πΆπΆπ¦π¦ οΏ½ det οΏ½2 1 1 1 πππ₯π₯ πππ¦π¦ 1 π΅π΅π₯π₯ π΅π΅π¦π¦ 1 πΆπΆπ₯π₯ 1 πΆπΆπ¦π¦ οΏ½ det οΏ½2 1 1 = πΆπΆπ₯π₯ 1 πΆπΆπ¦π¦ οΏ½ det οΏ½2 1 1 πππ₯π₯ 1 πππ¦π¦ οΏ½ det οΏ½2 1 1 = πΆπΆπ₯π₯ 1 πΆπΆπ¦π¦ οΏ½ det οΏ½2 1 1 Es gilt offensichtlich πππ΄π΄ + πππ΅π΅ + πππΆπΆ = 1. 4 1 1 4 1 1 4 1 1 4 1 1 3 3 1 4 1 1 3 7οΏ½ 1 = 4 3 17 7οΏ½ 1 3 7οΏ½ 1 = 8 3 17 7οΏ½ 1 3 3οΏ½ 1 = 1 β ππ β ππ = 5 π΄π΄ π΅π΅ 3 17 7οΏ½ 1 b) Die baryzentrischen Koordinaten eines Punktes oder Vektors im ππ-dimensionalen Raum bestehen aus ππ + 1 reellen Zahlen. Die kartesischen Koordinaten bestehen dagegen nur aus ππ reellen Zahlen. Letztere sind also theoretisch speichereffizienter. Andererseits reicht es aus, immer nur ππ baryzentrische Koordinaten zu speichern. Da die Summe aller Koordinaten stets 1 ist, kann die nicht gespeicherte Koordinate immer aus den gespeicherten ππ Koordinaten hergeleitet werden. c) FΓΌr die Evaluierung sollte der Mauszeiger nacheinander auf die Punkte π΄π΄, π΅π΅ und πΆπΆ geschoben werden. Die baryzentrischen Koordinaten des Punktes π΄π΄ sollten πππ΄π΄ = 1, πππ΅π΅ = 0 und πππΆπΆ = 0, die des Punktes π΅π΅ sollten πππ΄π΄ = 0, πππ΅π΅ = 1 und πππΆπΆ = 0 und die des Punktes πΆπΆ sollten πππ΄π΄ = 0, πππ΅π΅ = 0 und πππΆπΆ = 1 sein. Weiterhin sollten die baryzentrischen Koordinaten von Punkten innerhalb des Dreiecks alle grΓΆΓer als 0 sein. Nur bei Punkten auΓerhalb des Dreiecks sollten einzelne Koordinaten negativ sein. Bei Punkten auf dem Rand des Dreiecks, die keine Eckpunkte sind, ist stets eine Koordinate gleich 0. AuΓerdem sollte die Summe der baryzentrischen Koordinaten in allen FΓ€llen stets gleich 1 sein. public struct Triangle2 { // ... /// <summary> /// Berechnet die baryzentrischen Koordinaten eines /// Punktes bezogen auf dieses Dreieck. /// </summary> /// <param name="P"> /// Der Punkt, dessen baryzentrische Koordinaten berechnet /// werden sollen. /// </param> /// <returns> /// Ein 3-Tupel mit den baryzentrischen Koordinaten von /// <paramref name="P"/> bezogen auf dieses Dreieck. /// </returns> public Tuple3 GetBarycentricCoordinates(Point2 P) { // Anwendung der Cramerschen Regel. // Determinante fΓΌr die Nenner. double detN = A.X * (B.Y - C.Y) + B.X * (C.Y - A.Y) + C.X * (A.Y - B.Y); // Determinanten fΓΌr die ZΓ€hler. double detA = P.X * (B.Y - C.Y) + B.X * (C.Y - P.Y) + C.X * (P.Y - B.Y); double detB = A.X * (P.Y - C.Y) + P.X * (C.Y - A.Y) + C.X * (A.Y - P.Y); // Baryzentrische Koordinaten. double l1 = detA / detN; double l2 = detB / detN; double l3 = 1.0 β l1 β l2; } } // Tupel erzeugen und zurΓΌckgeben. return new Tuple3(l1, l2, l3); 3 Punkttest fΓΌr ebene Dreiecke Der Punkttest gehΓΆrt zu den wichtigsten Problemstellungen in der Computergeometrie. Dabei geht es um die Frage, ob ein gegebener Punkt ππ auf einer Strecke, Kurve, FlΓ€che oder in einem Dreieck, Viereck, FΓΌnfeck liegt oder zu einer wie auch immer beschaffenen Menge von Punkten gehΓΆrt. FΓΌr ein ebenes Dreieck π΄π΄π΄π΄π΄π΄ gibt es mehrere MΓΆglichkeiten fΓΌr den Punkttest. Eine Variante basiert auf den Eigenschaften baryzentrischer Koordinaten. Dazu werden die baryzentrischen Koordinaten des Punktes ππ bezΓΌglich des Dreiecks π΄π΄π΄π΄π΄π΄ berechnet und geprΓΌft, ob alle Koordinaten grΓΆΓer gleich 0 sind liegen. Wenn dem so ist, dann liegt der Punkt im Dreieck. οΏ½οΏ½οΏ½οΏ½οΏ½β, ππππ οΏ½οΏ½οΏ½οΏ½οΏ½β und β ππππ οΏ½οΏ½οΏ½οΏ½οΏ½β , ππππ οΏ½οΏ½οΏ½οΏ½οΏ½β. οΏ½οΏ½οΏ½οΏ½οΏ½β , β ππππ οΏ½οΏ½οΏ½οΏ½οΏ½β, ππππ In einer anderen Variante berechnet man die Summe der Winkel β ππππ Nur wenn diese Summe gleich 360Β° ist, liegt der Punkt ππ im Dreieck. Aufgabe a) Finden Sie heraus, welche der beiden genannten Varianten des Punkttests fΓΌr ebene Dreiecke effizienter ist. Gehen Sie dabei von den folgenden Annahmen aus. (3 Punkte) β’ Der Vergleich zweier reeller Zahlen benΓΆtigt einen Rechentakt. β’ Die Addition (bzw. Subtraktion) zweier reeller Zahlen benΓΆtigt ebenfalls einen Rechentakt. β’ Die Multiplikation (bzw. Division) zweier reeller Zahlen benΓΆtigt fΓΌnf Rechentakte. β’ Alle sonstigen Funktionen (Quadratwurzel, Sinus, usw.) benΓΆtigen jeweils 20 Rechentakte. b) Gegeben sei ein ebenes, ΓΌberschneidungsfreies Viereck π΄π΄π΄π΄π΄π΄π΄π΄. Beschreiben Sie kurz einen Algorithmus, der prΓΌft, ob ein Punkt ππ in diesem Viereck liegt. (1 Punkt) c) Implementieren Sie die Methode Triangle2.Contains(). LΓΆsung a) In der ersten Variante mΓΌssen β unter Anwendung der Cramerschen Regel β die baryzentrischen Koordinaten wie folgt berechnet werden: πππ₯π₯ det οΏ½πππ¦π¦ 1 πππ΄π΄ = π΄π΄π₯π₯ det οΏ½π΄π΄π¦π¦ 1 π΄π΄π₯π₯ det οΏ½π΄π΄π¦π¦ 1 πππ΅π΅ = π΄π΄π₯π₯ det οΏ½π΄π΄π¦π¦ 1 π΅π΅π₯π₯ π΅π΅π¦π¦ 1 π΅π΅π₯π₯ π΅π΅π¦π¦ 1 πππ₯π₯ πππ¦π¦ 1 π΅π΅π₯π₯ π΅π΅π¦π¦ 1 πΆπΆπ₯π₯ πΆπΆπ¦π¦ οΏ½ 1 πΆπΆπ₯π₯ πΆπΆπ¦π¦ οΏ½ 1 πΆπΆπ₯π₯ πΆπΆπ¦π¦ οΏ½ 1 πΆπΆπ₯π₯ πΆπΆπ¦π¦ οΏ½ 1 πππΆπΆ = 1 β πππ΄π΄ β πππ΅π΅ Es sind also zunΓ€chst drei verschiedene Determinanten von 3 Γ 3-Matrizen zu berechnen, deren letzte Zeile nur aus Einsen besteht. Beispielhaft sei das im Folgenden fΓΌr die Determinante ausgefΓΌhrt, die jeweils im Nenner steht. π΄π΄π₯π₯ det οΏ½π΄π΄π¦π¦ 1 π΅π΅π₯π₯ π΅π΅π¦π¦ 1 πΆπΆπ₯π₯ πΆπΆπ¦π¦ οΏ½ = π΄π΄π₯π₯ β οΏ½π΅π΅π¦π¦ β πΆπΆπ¦π¦ οΏ½ + π΅π΅π₯π₯ β οΏ½πΆπΆπ¦π¦ β π΄π΄π¦π¦ οΏ½ + πΆπΆπ₯π₯ β οΏ½π΄π΄π¦π¦ β π΅π΅π¦π¦ οΏ½ 1 Hier haben wir 3 Multiplikationen und 5 Additionen. Wir benΓΆtigen also pro Determinante 20 Rechentakte. Bei drei Determinanten macht das zusammen 60 Rechentakte. FΓΌr die Berechnung der ersten zwei baryzentrischen Koordinaten sind auΓerdem noch zwei Divisionen nΓΆtig. Diese schlagen mit weiteren 2 β 5 = 10 Rechentakten zu Buche, macht zusammen 70 Rechentakte. Die Berechnung der dritten baryzentrischen Koordinate erfordert zwei Additionen, folglich zwei weitere Rechentakte. Macht zusammen 72 Rechentakte. FΓΌr alle drei Koordinaten muss zum Schluss geprΓΌft werden, ob sie jeweils grΓΆΓer als 0 sind. Das sind zusΓ€tzlich 3 Vergleiche bzw. 3 Rechentakte. FΓΌr die erste Variante des Punkttests sind also insgesamt 75 Rechentakte nΓΆtig. οΏ½οΏ½οΏ½οΏ½οΏ½β, ππππ οΏ½οΏ½οΏ½οΏ½οΏ½β berechnen. Das sind οΏ½οΏ½οΏ½οΏ½οΏ½β und ππππ Bei der zweiten Variante mΓΌssen wir zunΓ€chst die Vektoren ππππ insgesamt 6 Additionen bzw. 6 Rechentakte. AnschlieΓend berechnen wir die LΓ€ngen der drei Vektoren. FΓΌr jede LΓ€nge sind 2 Multiplikationen, eine Addition und eine Wurzel, also 31 Rechentakte nΓΆtig. Die Berechnung aller drei LΓ€ngen erfordert also 93 Rechentakte. Danach οΏ½ , ππππ οΏ½ . Pro Vektor sind das 2 οΏ½ und ππππ berechnen wir die Normierungen der Vektoren. Diese seien ππππ Multiplikationen bzw. 10 Rechentakte. Die Normierung aller Vektoren erfordert also 30 Rechentakte. Zusammengefasst benΓΆtigen wir bisher schon 129 Rechentakte fΓΌr die Berechnung und Normalisierung dreier Vektoren. Im nΓ€chsten Schritt mΓΌssen die drei Winkel berechnet werden. FΓΌr jeden Winkel ist der Arkuskosinus aus dem Skalarprodukt zweier normierter Vektoren zu berechnen. οΏ½ , ππππ οΏ½ βͺοΏ½ πΎπΎ = acosοΏ½β©ππππ Das sind zwei Multiplikationen (10 Rechentakte), eine Addition (1 Rechentakt) und ein Arkuskosinus (20 Rechentakte) pro Winkel, zusammen also 31 Rechentakte pro Winkel und insgesamt 93 Rechentakte fΓΌr drei Winkel. In der Zwischensumme liegen wir jetzt bei 222 Rechentakten. Die Berechnung der Summe der Winkel erfordert zwei weitere Rechentakte und der Vergleich der Summe mit dem Vollwinkel einen weiteren Rechentakt. Wir benΓΆtigen fΓΌr die zweite Variante also insgesamt 225 Rechentakte. Zusammenfassend ist die erste Variante deutlich effizienter. b) Die einfachste MΓΆglichkeit ist die Zerlegung des Vierecks in zwei Dreiecke. Wenn der Punkt in einem der beiden Dreieck liegt (oder auf dem Rand der gemeinsamen Seite beider Dreiecke), dann liegt er auch im Viereck. Wir reduzieren also den Punkttest fΓΌr ein Viereck auf zwei Punkttests fΓΌr Dreiecke. c) public struct Triangle2 { // ... /// <summary> /// PrΓΌft, ob dieses Dreieck einen bestimmten Punkt enthΓ€lt. /// </summary> /// <param name="P">Der Punkt.</param> /// <returns> /// <see langword="true"/>, falls der Punkt <paramref name="P"/> /// in diesem Dreieck liegt, sonst <see langword="false"/>. /// </returns> public bool Contains(Point2 P) { // baryzentrische Koordinaten berechnen. Tuple3 Bary = GetBarycentricCoordinates(P); // if if if } } Koordinaten mΓΌssen alle grΓΆΓer gleich 0 sein. (Bary.A1 < 0) return false; (Bary.A2 < 0) return false; (Bary.A3 < 0) return false; // Punkt liegt im Dreieck. return true; // ...
Β© Copyright 2025