Bézier-Kurve mit bleibig vielen Punkten...
Übersicht

n-HalbleiterBetreff: Bézier-Kurve mit bleibig vielen Punkten... |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
... allerdings als fortlaufende Spline.
![]() Damit dieses System verstehbar ist, sollte ein wenig Grundverständnis für Bézier-Kurven vorhanden sein. Wenn jemand nicht weiß, was los ist, gibt es den Wikipediaartikel zu Bézierkurven, ich möchte euch allerdings zusätzlich noch einen Artikel auf Gamedev.net (auf Englisch, lesenswert) ans Herz legen. Der Dreh- und Angelpunkt des Lösungsansatzes beruht auf der Verallgemeinerung von binomischen Formeln mit dem Exponent n: Zitat: n
Sigma ( (n über i) * a^(n-i) * b^(i) ) = (a+b)^n i=0 Es wird, denke ich, schon aufgefallen sein, dass bei den Bézier-Kurven genau solche binomischen Formeln eine Rolle spielen. Jedoch: Bei den Splines wird jedes Polynom noch mit der Koordinate ( x bzw. y) des Puntes i multipliziert, damit die Punkte ins Gewicht fallen. Wenn man dies berücksichtigt, lässt sich daraus eine in BB umsetzbare Konstruktion finden: Code: [AUSKLAPPEN] Local C,AXY#,a#=t,b#=1-t
For C=0 To amount AXY=AXY+(P(C,F)*BinomialCoE(amount,C)*ToThePowerOf(a,amount-C)*ToThePowerOf(b,C)) Next Die Funktion "BinomialCoE" errechnet den Binomialkoeffizienten " "amount" über C ", "ToThePowerOf" ist eine Funktion, die eine Potenz berechnet (z.B. b^C (zweiter Aufruf)). Die For-Next-Schleife in Kombination der Addition des Wertes zu AXY umschreibt den Summenoperator. Ein letztes Wort noch zur Technik, bevor es an den Code geht: Es gibt nur eine Funktion XY, welche sowohl die X- als auch die Y-Koordinate berechnen kann; Definiert, welche Koordinate berechnet werden soll, wird durch F (0 bedeutet X-Koordinate, 1 Y-Koordinate). Der Code, ein Beispiel ist direkt dabei: Code: [AUSKLAPPEN] Graphics 1024,768,32,2
SeedRnd MilliSecs() SetBuffer BackBuffer() Global timer=CreateTimer(60),PosField=CreateBank() ;PosField ist die Bank, in der die Koordinaten aller Punkte gespeichert werden Local C#,a#=1,C2 Global amount=Rand(2,8);Amount: Anzahl der Punkte (-1) For C2=0 To amount;Genug Punkte erstellen (an sich amount+1) NewPos(Rand(50,700),Rand(50,700)) Next ClsColor 100,100,100 Repeat ;Pfad malen Color 200,200,0 For C=0 To 1 Step 0.005 Plot XY(C,0),XY(C,1) Next ;Punkt an der aktuellen Position malen Color 0,0,255 Rect XY(a,0)-1,XY(a,1)-1,2,2,1 ;Die Punkte markieren For C2=0 To amount If C2=0 Or C2=amount Color 0,200,200 Else Color 0,200,0 EndIf Rect P(C2,0)-1,P(C2,1)-1,2,2,1 Color 255,255,255 Text P(C2,0),P(C2,1),C2+": "+P(C2,0)+","+P(C2,1),1 Next Text 10,10,a a=a+0.005 If a>=1 Then a=0 Text 10,30,amount+1 Flip 0 WaitTimer timer Cls Until KeyHit(1) End ;Gibt die Komponente F der Spline zum Zeitpunkt t zurück Function XY#(t#,F) Local C,AXY#,a#=t,b#=1-t For C=0 To amount AXY=AXY+(P(C,F)*BinomialCoE(amount,C)*ToThePowerOf(a,amount-C)*ToThePowerOf(b,C)) Next Return AXY End Function ;Fügt einen neuen Punkt zu Punktliste hinzu Function NewPos(X#,Y#) Local size=BankSize(PosField) ResizeBank(PosField,size+8) PokeFloat(PosField,size,X) PokeFloat(PosField,size+4,Y) End Function ;Gibt vom Punkt C die Komponente F (0:x, 1:y) zurück Function P#(C,F=0) Return PeekFloat(PosField,(C Shl 3)+(F Shl 2)) End Function ;Mathematische Funktionen, die benötigt werden ;Potenz a^x Function ToThePowerOf#(Basis#,Exponent) Local Ergebnis#=1 Local Faktor#=Basis# If Exponent<0 Then Exponent=-Exponent:Faktor=1/Faktor While Exponent If (Exponent And 1) Then Ergebnis=Ergebnis*Faktor Exponent=Exponent Shr 1 Faktor=Faktor*Faktor Wend Return Ergebnis End Function ;Fakultät von x Function Factorial(x) ;Spezialfallberücksichtigung If x<0 Return 0 ElseIf x=0 Return 1 EndIf Local C,ret=1 For C=2 To x ret=ret*C Next Return ret End Function ;Binomialkoeffizient ("n über k") Function BinomialCoE(n,k) Return Factorial(n)/(Factorial(k)*Factorial(n-k)) End Function Falls sich Fragen ergeben, fragt. P.S.: Der Code ist realtimefähig. Allerdings gibt es, wie auch sonst, irgendwann eine Marke an Aufrufen, die bei Überschreiten in unschönen FPS-Zahlen resultieren. ![]() EDIT: Der Code wurde ein wenig verändert; man sieht jetzt an den Stellen, an denen die Punkte sind, kleine Rechtecke unterschiedlicher Färbung (abhängig davon, ob sie Start- und Endpunkte oder Kontrollpunkte sind). EDIT2: Ich habe (dazu vielen Dank an mpmxyz) die Potenzfunktion verbessert. ![]() ![]() |
||
mfg, Calvin
Maschine: Intel Core2 Duo E6750, 4GB DDR2-Ram, ATI Radeon HD4850, Win 7 x64 und Ubuntu 12.04 64-Bit Ploing! Blog "Die Seele einer jeden Ordnung ist ein großer Papierkorb." - Kurt Tucholsky (09.01.1890 - 21.12.1935) |
- Zuletzt bearbeitet von n-Halbleiter am Mo, Jul 13, 2009 11:48, insgesamt 2-mal bearbeitet
![]() |
Nova |
![]() Antworten mit Zitat ![]() |
---|---|---|
Und was ist das ganze jetzt? Ich sehe da nur eine weiche Kurve, wie bei Sinus und Cosinus.
Wikipedia ist da viel zu kompliziert für eine Erklärung. Was bringt diese Kurve? Und wieso ist die so gepunktet? Und warum läuft auf der Kurve so ein blauer Punkt rum der jede Sekunde eine Stelle weiter rückt? |
||
AMD Athlon II 4x3,1GHz, 8GB Ram DDR3, ATI Radeon HD 6870, Win 7 64bit |
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Eine bezierkurve ist eine mathematische Beschreibung einer fast beliebigen kurve die durch einige Fixpunkte läuft. Sehr sinnige sache, denn so kann man mit wenigen bytes an Info sehr komplexe Muster speichern. | ||
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3 Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64 B3D BMax MaxGUI Stolzer Gewinner des BAC#48, #52 & #92 |
n-Halbleiter |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Es ist eine weiche Kurve. Das ist ja auch der Sinn von Splines, nämlich, Strecken zu interpolieren. Die Wikipedia-Erklärung ist in der Tat viel zu kompliziert, um schnell heruaszufinden, was los ist, weshalb ich noch den Artikel auf Gamedev.net dazugeschrieben habe. Wenn du keine Lust hast, dir den Artikel durchzulesen, oder ihn nicht verstehst, kann ich noch zum Tutoral dazu schreiben/raussuchen.
Diese Kurve wäre zum Beispiel für einen fliegenden Kundschafter in einem Strategiespiel nützlich, wenn er in einem Flug eine bestimmte endliche Anzahl Punkte abfahren soll. Es ist zwar auch anders möglich, aber mir gefällt diese Methode, und ich wollte sie als Möglichkeit offerieren. ![]() Die gepunktete Kurve ist eine Annäherung an die Spline. Die Nähe kannst du in der Zeile "For C=0 To 1 Step 0.005" verändern, dazu musst du eben den Step verändern. Doch Vorsicht: eine höhere Genauigkeit heißt auch längere Rechenzeit. Der blaue Punkt ist quasi der aktuelle Stand nach dem Zähler. Das habe ich lediglich aus Jux eingefügt. Es ist übrigens nicht jede Sekunde eine Erhöhung zu vermerken, sondern jeden Frame um 0,005 (in der Zeile "a=a+0.005" zu finden, hier ist es ebenfalls möglich, den Wert zu verändern). |
||
mfg, Calvin
Maschine: Intel Core2 Duo E6750, 4GB DDR2-Ram, ATI Radeon HD4850, Win 7 x64 und Ubuntu 12.04 64-Bit Ploing! Blog "Die Seele einer jeden Ordnung ist ein großer Papierkorb." - Kurt Tucholsky (09.01.1890 - 21.12.1935) |
![]() |
Nova |
![]() Antworten mit Zitat ![]() |
---|---|---|
Okay. Dann hätte ich nur einen Verbesserungsvorschlag: Die Fixpunkte, auf denen die Linie verläuft, anscheinend drei, sollten markiert werden.
Wenn du den Link zu dem Tutorial schreiben könntest wäre das sehr nett! ![]() |
||
AMD Athlon II 4x3,1GHz, 8GB Ram DDR3, ATI Radeon HD 6870, Win 7 64bit |
n-Halbleiter |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Nova hat Folgendes geschrieben: Die Fixpunkte, auf denen die Linie verläuft, anscheinend drei, sollten markiert werden.
Änderung: Die (beliebig vielen, die maximale Anzahl an Punkten ist theoretisch unbegrenzt) Punkte werden nun farbig markiert (siehe Einstiegspost). Achtung: Die Kurve verläuft nicht auf ihnen, sondern nähert sich ihnen, bedingt durch die Anzahl sonstiger Punkte & der Entfernung zu ebenjenen, nur an. Es ist allerdings möglich, eine "Kollision" zu erzugen, jedoch sind solche Situationen nicht die Regel, sondern nur durch wirkliche Linien zu erreichen, da eine Abweichung von einer Einheit schon eine Krümmung besagt. Das musste mal gesagt werden. ![]() |
||
mfg, Calvin
Maschine: Intel Core2 Duo E6750, 4GB DDR2-Ram, ATI Radeon HD4850, Win 7 x64 und Ubuntu 12.04 64-Bit Ploing! Blog "Die Seele einer jeden Ordnung ist ein großer Papierkorb." - Kurt Tucholsky (09.01.1890 - 21.12.1935) |
![]() |
mpmxyz |
![]() Antworten mit Zitat ![]() |
---|---|---|
Moin!
Zitat: Code: [AUSKLAPPEN]
Function ToThePowerOf#... Hattest du Langeweile oder warum hast du eine neue, noch optimierbare Potenzfunktion geschieben? So viel ich weiß, hat BB schon eine. ![]() Ist die etwa schneller als diese? Aber ich finde den Code interessant. Es ist nur so, dass Splines, die durch die Punkte gehen, lieber mag. ![]() mfG mpmxyz |
||
Moin Moin!
Projekte: DBPC CodeCruncher Mandelbrot-Renderer |
n-Halbleiter |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
mpmxyz hat Folgendes geschrieben: Hattest du Langeweile oder warum hast du eine neue, noch optimierbare Potenzfunktion geschieben?
So viel ich weiß, hat BB schon eine. ![]() Ist die etwa schneller als diese? Ich habe schon einen Test angestellt, meine Funktion ist schneller, allerdings versagt sie bei negativen Exponenten. Aber für diesen Test reicht es. ![]() mpmxyz hat Folgendes geschrieben: Aber ich finde den Code interessant.
Es ist nur so, dass Splines, die durch die Punkte gehen, lieber mag. ![]() Es gibt für beide Typen ihre Anwendungsmöglichkeiten. ^^ |
||
mfg, Calvin
Maschine: Intel Core2 Duo E6750, 4GB DDR2-Ram, ATI Radeon HD4850, Win 7 x64 und Ubuntu 12.04 64-Bit Ploing! Blog "Die Seele einer jeden Ordnung ist ein großer Papierkorb." - Kurt Tucholsky (09.01.1890 - 21.12.1935) |
![]() |
mpmxyz |
![]() Antworten mit Zitat ![]() |
---|---|---|
Das mit der Geschwindigkeit ist seltsam...
Aber ich vermute mal, dass das daran liegt, dass in der Standardfunktion der Exponent eine Float ist. Aber du hast dich wirklich bemüht. Ich habe eine eigene Funktion in Informatik kennengelernt: Code: [AUSKLAPPEN] Function Potenz#(Basis#,Exponent)
Local Ergebnis#=1 Local Faktor#=Basis# If Exponent<0 Then Exponent=-Exponent:Faktor=1/Faktor While Exponent If (Exponent And 1) Then Ergebnis=Ergebnis*Faktor Exponent=Exponent Shr 1 Faktor=Faktor*Faktor Wend Return Ergebnis End Function Besonders bei goßen Linien kann das die Geschwindigkeit erhöhen. mfG mpmxyz |
||
Moin Moin!
Projekte: DBPC CodeCruncher Mandelbrot-Renderer |
- Zuletzt bearbeitet von mpmxyz am Mo, Jul 13, 2009 11:47, insgesamt einmal bearbeitet
n-Halbleiter |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
DAS war der Code, an den ich mich nicht mehr erinnern konnte. ![]() Also, danke, ich habe ihn eingebaut. ![]() |
||
mfg, Calvin
Maschine: Intel Core2 Duo E6750, 4GB DDR2-Ram, ATI Radeon HD4850, Win 7 x64 und Ubuntu 12.04 64-Bit Ploing! Blog "Die Seele einer jeden Ordnung ist ein großer Papierkorb." - Kurt Tucholsky (09.01.1890 - 21.12.1935) |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group