Blatt 7

Disclaimer: Dieser Thread wurde aus dem alten Forum importiert. Daher werden eventuell nicht alle Formatierungen richtig angezeigt. Der ursprüngliche Thread beginnt im zweiten Post dieses Threads.

Blatt 7

Wie ist das zu interpretieren?
Wenn man im Intervall [0, 1] mit numApproximationPoints = 1 abtastet, ist das dann der Wert an Stelle 0.5? Oder sollen dabei die drei Werte an den Stellen 0, 0.5 und 1 zurueckgegeben werden?


Wenn man das Testprogramm öffnet und die Anzahl der ApproximationPoints verringert, hört das ganze bei 2 auf.

Daraus habe ich abgeleitet, dass man bei 2 Points das ganze an t=0 und t=1 auswertet, bei 3 Points an t=0, t=0.5 und t=1, usw…

Eine Kurve an nur einem Punkt abzutasten bringt ja auch nichts, kommt ja nichmal ne Linie raus…


Wie ist das zu verstehen? Warum wird da in linke und rechte Teilkurve aufgeteilt?


Beide, da du teilst rekursiv die funktion aufrufst.


Ziel des Midpoint-Subdivison-Algorithmus ist es, eine Punktemenge zu finden, die eine bestimmte Bezierkurve annähert.

Ein einzelner Subdivision-Schritt bekommt eine Liste mit n Kontrollpunkten als Argument übergeben und gibt zwei Listen mit jeweils n Kontrollpunkten zurück. Die beiden zurückgegebenen Listen werden die “linke” bzw. “rechte” genannt. Sie knüpfen nahtlos aneinander an und ihre Punkte sind grob entlang der gesuchten Bezier-Kurve ausgerichtet.

Auf die linke und rechte Liste kann nun jeweils wieder ein Subdivision-Schritt angewendet werden. Das Ergebnis sind vier Listen, die die Bezierkurve noch besser annähern als die beiden Listen aus dem vorherigen Schritt. Usw…

Hier mal ein einzelner Subdivision-Schritt als Zeichnung:

Die vier schwarzen Punkte sind die Kontrollpunkte der Eingabe-Bezier-Kurve (hier vom Grad 3). Nun wird in insgesamt drei Schritten (grün, blau, rot) Decasteljau mit t=1/2 ausgeführt. Wichtig ist, dass der jeweils nächste Schritt von Decasteljau immer nur auf die im vorherigen Decasteljau-Schritt entstandenen Punktmengen angewendet wird. Wenn man nun von allen eingezeichneten Punktemengen (schwarz, grün, blau, rot. in dieser Reihenfolge) jeweils den ersten und letzten Punkt hernimmt, dann entstehen die lila bzw. orange umrandeten Ausgabe-Listen (linke bzw. rechte).

Man kann gut sehen, dass die beiden Ausgabe-Listen wieder aus jeweils vier Punkten bestehen und damit wieder je eine Bezier-Kurve vom Grad 3 beschreiben.

3 Likes

Sehr gute Erklärung (und sehr schönes Bild), danke :slight_smile:


Was spuckt denn bei euch die bezierText aus? Ich kriege folgendes:

CP 0: (0, 0)
CP 1: (0, 8)
CP 2: (8, 8)
CP 3: (8, 0)

Approximation mit 5 Punkten:
(8, 0)
(8, 0)
(8, 0)
(8, 0)
(8, 0)

Entferne mittleren Kontrollpunkt:
CP 0: (0, 0)
CP 1: (8, 8)
CP 2: (8, 0)

Degree elevation:
CP 0: (0, 0)
CP 1: (8, 8)
CP 2: (8, 0)
CP 3: (8, 0)

könnte mir bitte jemand sagen wie man die curDepth berechnet ?
Danke im voraus


Hoffe ich verstehe deine Frage richtig. Du startest mit curDepth = 0 und schaust in jedem Rekursionsschritt, ob maxDepth bereits erreicht ist.

Sind in Teilaufgabe f eigentlich die in vorherigen Teilaufgaben implementierten Funktionen zu nutzen oder überhaupt zu gebrauchen?


erstmal vielen Dank für die schnelle Antwort.
Ja deCasteljau wird schon gebraucht vermute ich.

Ich habe noch eine kleine Frage bezüglich curDepth:

am Anfang ist sie ja 0, aber später wenn man subdivision im rekursiven Fall aufruft , was für Wert nimmt sie ?
sorry dass ich vorher meine Frage nicht genau erklärt habe.


CurDepth wird im rekursiven Funktionsaufruf immer um 1 erhöht. Wenn du irgendwann mal maxDepth mal diese Funktion aufgerufen hast, dann kehrt sie aus der Rekursion wieder zurück.

Beispiel:

void rec(unsigned int curDepth, unsigned int maxDepth) {
	if (curDepth == maxDepth) {
		// No further recursion
		std::cout << curDepth << "No further recursion" << std::endl;
	}
	else {
		// Do some stuff before recursive call
		std::cout << curDepth << std::endl;

		// Recursion
		rec(curDepth + 1, maxDepth);
		
		// Do some stuff after recursion
 		std::cout << curDepth * 1000 << std::endl;
	}
}

Ruft man diese Funktion mit curDepth = 0 und maxDepth = 3 auf, ist der Output:


Deine Degree Elevation stimmt nicht. Schau mal, ob du floats verwendest. Also 1.0f statt 1. Bei der Approximation habe ich auch andere Ergebnisse.

Bekomme folgendes:


Und ich hab nochmal was anderes :):

CP 0: (0, 0)
CP 1: (0, 8)
CP 2: (8, 8)
CP 3: (8, 0)

Approximation mit 5 Punkten:
(0, 0)
(1.25, 4.5)
(4, 6)
(6.75, 4.5)
(8, 0)

Entferne mittleren Kontrollpunkt:
CP 0: (0, 0)
CP 1: (8, 8)
CP 2: (8, 0)

Degree elevation:
CP 0: (0, 0)
CP 1: (8, 8)
CP 2: (8, 0)

Wobei bei der Approximation mit 5 Punkten der Start- und Endwert eigentlich schon enthalten sein sollten, wie ich meine (also so wie bei mir)…


@qwert du hast wahrscheinlich bei degree elevation die zuweisung vergessen. Da sollten vier Punkte rauskommen.

@BTL beim berechnen von alpha hat noch ein cast gefehlt …
Habe jetzt folgendes:


Rechne mal auf Papier nach. Fuer CP 2 ist alpha = 2/4. Damit ergibt sich fuer CP2: 2/4 * (8, 8) + (1 - 2/4) * (8, 0) = (8, 4).


@kronos: Vielen Dank für die Fernanalyse :).

Hab jetzt folgendes:

Degree elevation:
CP 0: (0, 0)
CP 1: (6, 6)
CP 2: (8, 4)
CP 3: (8, 0)

Zum Coonspatch:

Mit Komponenten sind schon die Komponenten eines Point3D gemeint oder?

Soll man bei der 2b) getApproximationGrid die Punkte zeilenweise oder spaltenweise in den Vektor einfuegen?

Welchen Output bekommt ihr fuer ./coonsText?


  1. ich bekomme für bezierText:
CP 0: (0, 0)
CP 1: (0, 8)
CP 2: (8, 8)
CP 3: (8, 0)
starting approx mit step :0.25

Approximation mit 5 Punkten:
(0, 0)
(1.25, 4.5)
(4, 6)
(6.75, 4.5)
(8, 0)

Entferne mittleren Kontrollpunkt:
CP 0: (0, 0)
CP 1: (8, 8)
CP 2: (8, 0)

Degree elevation:
CP 0: (0, 0)
CP 1: (6, 6)
CP 2: (8, 4)
CP 3: (8, 0)

Unstimmigkeiten mit vorherigen Posts bei der Approximation mit 5 Punkten. Rein optisch sehe ich jedoch bei mir kein Unterschied zur Referenzimplementierung.
Kann das so stimmen?

2.:

Genau, also (x,y,z), ist jedoch imho sehr unglücklich formuliert, habe aber auch erst etwas darüber gegrübelt.

Ich habs einfach zeilenweise gemacht und kriege das gleiche Ergebnis wie die Referenzimplementierung (wieder rein optisch).

Reihenfolge der Komponenten ist (s, t, cp(s,t)).                                                                                                                                    
(0, 0, 0) - (0, 0.25, 0.0625) - (0, 0.5, 0.25) - (0, 0.75, 0.5625) - (0, 1, 1)                                                                                                      
(0.25, 0, 0) - (0.25, 0.25, -0.125) - (0.25, 0.5, -0.125) - (0.25, 0.75, 0) - (0.25, 1, 0.25)                                                                                       
(0.5, 0, 0) - (0.5, 0.25, -0.1875) - (0.5, 0.5, -0.25) - (0.5, 0.75, -0.1875) - (0.5, 1, 0)                                                                                         
(0.75, 0, 0) - (0.75, 0.25, -0.125) - (0.75, 0.5, -0.125) - (0.75, 0.75, 0) - (0.75, 1, 0.25)                                                                                       
(1, 0, 0) - (1, 0.25, 0.0625) - (1, 0.5, 0.25) - (1, 0.75, 0.5625) - (1, 1, 1)         

Danke :slight_smile:

Komme nun auf die gleichen Ergebnisse wie du, Cliff_T.