Winkelberechnung im Koordinatensystem für Kreisdrehung



  • Hallo zusammen,

    Ich habe ein Programm geschrieben mit dem ich Drahtgittermodelle auf dem Bildschirm rotieren lassen kann. Mein Programm funktioniert soweit, jedoch bin ich nicht sonderlich fit in der Trigonometrie und hoffe das jemand hier einen Tipp für mich hat.

    http://supernicky.dyndns.info/bild.html

    Folgendes wird gemacht:

    Mein Fenster ist unsichtbar in 4 Felder eingeteilt (Feld1 bis Feld4).
    Nun habe ich einen Punkt (rot) der zufällig irgendwo auf dem Bildschirm
    in einem der vier Felder landet.

    Ich berechne nun in welchem Winkel er zum Mittelpunkt (blau) steht und wie
    gross der Radius ist.
    Anschließend addiere ich zum Winkel den Steigerungswert (Bsp. 0.5) und setze
    den Punkt an die neue Stelle. Das ganze in einer Schleife erzeugt eine reibungs-
    lose Drehung die exakt wieder den Ursprungspunkt erreicht.

    Nun das Problem:

    Je nachdem in welchem Feld der Punkt landet, habe ich vier unterschiedliche
    Berechnungen zur Bestimmung des Winkels durchzuführen.

    Das liegt daran das der Sinus in Feld1 und Feld3 auf der Y-Achse und
    in Feld2 und Feld4 auf der X-Achse liegt. Cosinus entsprechend andersrum.

    Auch werden auf die unterschiedlichen Felder noch unterschiedliche
    Winkelgrade dazu addiert.
    Feld1 + 0
    Feld2 + 90
    Feld3 + 180
    Feld4 + 270
    damit ich am Ende den richtigen Winkel habe.

    Dort wo der Pfeil jeweils hinzeigt, diesen Winkel brauche ich dafür.

    Gibt es vielleicht einen kürzeren Weg dafür?

    Nicky

    PS: Das Programm ist mit MASM erstellt und verwendet 95% FPU Befehle.
    Falls der Code gewüscht wird, kann
    ich ihn noch nachtragen.





  • Hallo dot,

    das Problem ist das ich die FPU nicht mit Matrizen füttern kann und die Winkel
    sind ja nicht bekannt.

    Hätte ja sein können...

    Gruß, Nicky



  • Das Problem versteh ich nicht. Natürlich weiß die FPU nicht, was eine Matrix ist. Das hindert aber niemanden daran, die FPU zu verwenden um mit Matritzen zu rechnen. 😉
    Die Rechnung steht doch schon ausgeschrieben auf der verlinkten Seite: "So the coordinates (x',y') of the point (x,y) after rotation are:"...

    Und so wie ich das oben verstanden hab, willst du einfach einen beliebigen Punkt um einen bestimmten Winkel weiterdrehen!? Und genau das macht die entsprechende Matrix. Oder was meinst du mit "die Winkel sind nicht bekannt"?



  • Mir geht es eigentlich nur darum ganz einfach herauszufinden wie groß der Winkel
    Alpha zum Mittelpunkt ist.

    Wenn ich den Winkel und den Radius habe, ist das "Drehen" ganz einfach.

    Diese vier Prüfungen, in welchem Feld sich der Punkt befindet, die möchte ich mir sparen. Somit könnte ich ich später mittels SSE mein Punktearray
    berechnen lassen, was ich so nicht kann.

    Eine Art Allzweckformel für die vier Felder...

    Gruß, Nicky



  • Du brauchst den momentanen Winkel und Radius aber eben gar nicht zu wissen, um einen Punkt um x° weiterzudrehen, genau ja das schöne dran... 😉



  • Du brauchst den momentanen Winkel aber eben gar nicht wissen, um einen Punkt um x° weiterzudrehen, genau ja das schöne dran...

    😕

    kannst du das etwas genauer ausschreiben?

    Da mein Fenster 600x600 Pixel groß ist habe ich die Mitte auf x=300 und y=300
    gelegt.

    Nun hab ich einen Punkt bei den Koordinaten x=200 und Y=200. Das währe auf meinem
    Bild das Feld2. Wie muss ich das der FPU sagen?

    Nicky



  • Was genau willst du der FPU sagen? Du hast also irgendeinen Punkt, was genau willst du jetzt damit machen? Sag einfach mal was du erreichen willst und nicht wie du denkst, dass du es erreichen willst...



  • B = blauer Punkt, A = Beliebiger Punkt, alpha := winkel gegen x-Achse:
    vektoriell: C = B-A
    alpha = arccos(C.x/sqrt(C.x2+C.y2))



  • C = A-B



  • dot schrieb:

    Was genau willst du der FPU sagen? Du hast also irgendeinen Punkt, was genau willst du jetzt damit machen? Sag einfach mal was du erreichen willst und nicht wie du denkst, dass du es erreichen willst...

    Das er mir den Punkt an x=200 und y=200 einen Grad weiter bewegt...



  • Was für eine API verwendest du denn? GDI, GDI+, DirecX, OGL?
    Wenn du den Drehwinkel und den Drehpunkt kennst, wird die Rotation eines Bildes durch Kombination von Translations- und Rotationsmatrix bewerkstelligt.
    (GDI: SetWorldTranform() + BitBlt())



  • masm schrieb:

    Was für eine API verwendest du denn? GDI, GDI+, DirecX, OGL?
    Wenn du den Drehwinkel und den Drehpunkt kennst, wird die Rotation eines Bildes durch Kombination von Translations- und Rotationsmatrix bewerkstelligt.
    (GDI: SetWorldTranform() + BitBlt())

    Hallo masm,

    1993 hatten wir auf unserer Dorfschule noch keine Matrizen 😞

    Ich zeichne nur mit der Windows GDI32. Alle Berechnungen erfolgen nur mit FPU
    wegen der Winkelfunktionen (keine Hilfe von Windows).

    Um bei meinem Beispiel zu bleiben:

    Mittelpunkt ist bei x=300 und y=300

    Wenn der Punkt bei x=350 und y=250 liegt sollte das Ergebnis 45° sein.
    Wenn der Punkt bei x=250 und y=250 liegt sollte das Ergebnis 135° sein.
    Wenn der Punkt bei x=250 und y=350 liegt sollte das Ergebnis 225° sein.
    Wenn der Punkt bei x=350 und y=350 liegt sollte das Ergebnis 315° sein.

    http://supernicky.dyndns.info/bild2.html

    Das Programm wie es jetzt läuft:
    http://supernicky.dyndns.info/3d_programm_3.zip

    Nicky



  • supernicky schrieb:

    Das er mir den Punkt an x=200 und y=200 einen Grad weiter bewegt...

    Dann mach es so wie von mir verlinked:

    \begin{align} x_{neu} &= x_{alt} \cdot \cos(1°) - y_{alt} \cdot \sin(1°) \\ y_{neu} &= x_{alt} \cdot \sin(1°) + y_{alt} \cdot \cos(1°) \end{align}

    Wobei du den Rotationsmittelpunkt zuerst von x und y abziehen, dann rotieren und dann wieder draufaddieren musst...



  • dot schrieb:

    supernicky schrieb:

    Das er mir den Punkt an x=200 und y=200 einen Grad weiter bewegt...

    Dann mach es so wie von mir verlinked:

    \begin{align} x_{neu} &= x_{alt} \cdot \cos(1°) - y_{alt} \cdot \sin(1°) \\ y_{neu} &= x_{alt} \cdot \sin(1°) + y_{alt} \cdot \cos(1°) \end{align}

    Wobei du den Rotationsmittelpunkt zuerst von x und y abziehen, dann rotieren und dann wieder draufaddieren musst...

    Hallo dot,

    die Formel scheint zu passen.. lediglich in der oberen Formel erhalte ich einen
    Wert der typisch für Y und in der unteren für X währe.

    Ich schreibe es mal um und gucke was passiert...

    Gruß, Nicky

    PS: Wenn soviel mit cos und sin gerechnet wird, brauch ich MMX/SSE wohl garnicht
    erst einsetzen.. Dort habe ich keinen Befehl wie FSIN oder FCOS gefunden.



  • Entschuldigung, aber den Code muss du dir doch irgendwoher kopiert haben? Das was der Code jetzt tut, steht doch im Wiederspruch zu deiner Frage.



  • sin(1°) und cos(1°) sind Konstanten, die du vorberechnen kannst...



  • masm schrieb:

    Entschuldigung, aber den Code muss du dir doch irgendwoher kopiert haben? Das was der Code jetzt tut, steht doch im Wiederspruch zu deiner Frage.

    Hallo masm,

    das stimmt wohl.. eigentlich habe ich nur die Formel zum bestimmen des Winkels gesucht....

    Falls ich die Formel von dot zum laufen bekomme, entfällt das ganze aber.
    Noch läuft es leider nicht..

    Gruß, Nicky



  • Mein Freund Olly hat mit im Übrigen verraten, das du dich nicht an die WinABI hältst - dies ist der Grund warum es nicht richtig funktioniert (win7, x64). EBX, ESI und EDI müssen in callbacks vor Veränderung geschützt werden: sehr einfach geht das mit der USES-Direktive:

    WndProc proc uses ebx edi esi hWnd:HWND,...



  • Gibt es eigentlich einen bestimmten Gund, wieso du das unbedingt mit Assembler machen willst?



  • masm schrieb:

    Mein Freund Olly hat mit im Übrigen verraten, das du dich nicht an die WinABI hältst - dies ist der Grund warum es nicht richtig funktioniert (win7, x64). EBX, ESI und EDI müssen in callbacks vor Veränderung geschützt werden: sehr einfach geht das mit der USES-Direktive:

    WndProc proc uses ebx edi esi hWnd:HWND,...

    Alle FPU Anweisungen liegen in einer Prozedur (PROC). Vor dem Aufruf sichere
    ich alle Register mit pushad und danach hole ich alle mit popad zurück...

    Das Programm von mir funktioniert tadellos... es ist nur nicht gerade optimal 😉

    Gruß, Nicky


Anmelden zum Antworten