Grundlagen der Computergeometrie

Transcription

Grundlagen der Computergeometrie
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;
// ...