Graphics.MultiplyTransform: Verständnisproblem

  • VB.NET
  • .NET (FX) 3.0–3.5

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von ~blaze~.

    Graphics.MultiplyTransform: Verständnisproblem

    Hallo liebe Community!

    Ich blicke nicht so ganz durch die Methode Graphics.MuliplyTransform durch, trotz MSDN etc.
    Was ich möchte ist, meinen Pfeil, der zuerst nach links zeigt, 90° gegen den Uhrzeigersinn drehen.
    180° habe ich durch reines herumprobieren, ohne es zu verstehen mit: g.MultiplyTransform(New Matrix(-1, 0, 0, 1, 23, 0)) geschafft.
    Allerdings schaffe ich mein genanntes Problem nicht zu beheben, außerdem würde ich mich um eine gute Erklärung bezüglich der Methode freuen.


    Danke im Vorraus.
    Mfg: Gather
    Private Nachrichten bezüglich VB-Fragen werden Ignoriert!


    Hi
    kennst du denn Matrixmultiplikationen?
    Transformationen werden häufig durch homogene Koordinaten abgebildet; die Matrix in diesem Fall stellt eine Abwandlung des ganzen dar. Bei homogenen Koordinaten wird die Matrix auf eine dritte Dimension erweitert und so die Verschiebung (Translation) ermöglicht. Um einen Vektor (x, y) mit der Matrix zu multiplizieren wird er zu (x, y, 1) erweitert, weshalb sich die Translation ergibt.
    Bei einer Matrix-Multiplikation werden die Transformationen miteinander kombiniert und zwar von rechts nach links (die Berechnungen sind ja nicht kommutativ, es macht einen Unterschied, ob du erst rotierst und danach verschiebst oder umgekehrt).

    Was deine Matrix macht, ist, die x-Achse zu spiegeln und um 23 Pixel in x-Richtung zu verschieben.
    Für eine Rotation würde ich dir empfehlen, die RotateTransform-Methode aufzurufen. Diese kombiniert die in Transform angegebene Matrix mit einer Rotationsmatrix.

    Viele Grüße
    ~blaze~
    Danke erstmal, die Erklärung hat mir auf jeden Fall geholfen!
    Grundsätzlich habe ich das ganze jetzt wiefolgt gelöst:

    VB.NET-Quellcode

    1. g.RotateTransform(-90)
    2. g.TranslateTransform(-23, 0) ' Wird benötigt, da sonst der Pfeil nicht mittig ist.


    Jedoch würde mich nun interessieren, wie kann ich beides in MultiplyTransform kombinieren?
    Mfg: Gather
    Private Nachrichten bezüglich VB-Fragen werden Ignoriert!


    Du müsstest erst die Matrix aufstellen, d.h.
    \begin{equation*} \begin{pmatrix} \cos(\phi) & -\sin(\phi) & t_1 \\ \sin(\phi) & \cos(\phi) & t_2 \\ 0 & 0 & 1 \end{pmatrix} \end{equation*}

    Wobei (t1, t2) der Vektor ist, um den du es verschiebst. In der Matrix sind die Dinge etwas anders, dort musst du halt die cos(\phi), usw. eintragen und separat die Verschiebung.

    Viele Grüße
    ~blaze~
    Ich hab Zweifel, ob eine Matrix-Multiplikation ühaupt die richtige Operation ist, um einen Zeiger zu drehen.
    Imo ist .Rotate und .Transate schon genau richtig.

    Klar kann man eine geeignete Matrix auch vorbereiten, und dann auf eine vorhandene draufmultiplizieren - das entspricht dann der Anwendung erst der einen Matrix, dann der anderen.
    .Rotate, .Translate macht ja genau das Gleiche wie MultiplyTransform mit dem Unterschied, dass du dir die Matrix direkt durch einen Winkel bzw. Offset definieren kannst.

    C#-Quellcode

    1. ​ Matrix rotate = new Matrix();
    2. rotate.Rotate(-90);
    3. Matrix translate = new Matrix();
    4. translate.Translate(0, 23);
    5. rotate.Multiply(translate); // Rotationsmatrix wird Translation hinzugefügt

    ​Für dich wäre allerdings sinnvoll Matrix.RotateAt zu benutzen. Das macht im Grunde nur Verschiebung(-x, -y) dann Rotation(degree) und dann wieder Verschiebung(x, y). So bewegst du den Ursprung deines Pfeiles nach (0,0), rotierst dann um -90° und bewegst ihn wieder dahin wo er her kam.
    Es besteht auch kein Grund, 2 Matrixen zu erzeugen, und die dann zu multiplizieren - eine Matrix reicht:

    VB.NET-Quellcode

    1. Matrix rotate = new Matrix();
    2. rotate.Rotate(-90);
    3. rotate.Translate(0, 23, MatrixOrder.Append) // der Rotation wird Translation hinzugefügt
    Und natürlich richtig: Wenn man um einen bestimmten Punkt rotieren will (und das will man eiglich immer), nimmt man gleich .RotateAt()
    Ich denke, es wäre durchaus sehr sinnvoll, sich in die Matrizen einzuarbeiten, wenn man darauf arbeitet. Zusammen mit Homogenen Koordinaten sind die in der Grafikprogrammierung ein quasi unverzichtbares Werkzeug, weil sie eben insbesondere Rotation, Verschiebung und Projektion ermöglichen.
    Wie das funktioniert, wird an der Darstellung der Matrizen klar und der Verwendung der homogenen Koordinaten, aber das lässt sich nun eben nicht einfach in drei Sätzen zusammenfassen.

    Bei meiner Formel ist zu beachten, dass Math.Sin und Math.Cos den Winkel nicht in Grad, sondern als Radiant angeben.

    Hat es denn jetzt eigentlich funktioniert?

    Viele Grüße
    ~blaze~

    ErfinderDesRades schrieb:

    2 Matrixen
    Sorry für den OffTopic-Post, aber die Mehrzahl von Matrix ist Matrizen. :D

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Ich würde da einfach mit der GDI Matrix-Klasse arbeiten, die ist ja ähnlich aufgebaut
    Spoiler anzeigen
    \begin{pmatrix} ScaleX & ShearX \\ ShearY & ScaleY \\ OffsetX & OffsetY \\ \end{pmatrix}

    ​Für eine Rotation sind die ScaleX und ScaleY dann cos(phi), ShearX ist sin(phi) und ShearY ist -sin(phi), wie blaze schon gesagt hat. Vielleicht macht's auch Sinn sich eine eigene Klasse (oder eher Struct) dafür zu schreiben, dann kann man schön die Operatoren überladen und muss Nichts Disposen. Man kann ja eine ConvertToGDIMatrix() Funktion vorsehen, oder einen Conversion Operator. ​Wenn's aber beim Pfeil drehen bleibt, würde ich nur Graphics.RotateAt() verwenden und fertig.
    Es hat schon längst funktioniert, nach deinem ersten Post schon. @~blaze~
    Fasizierend wie sehr die Meinungen bei einem so einfachen Thema auseinander gehen.
    Mfg: Gather
    Private Nachrichten bezüglich VB-Fragen werden Ignoriert!


    Gather schrieb:

    Jedoch würde mich nun interessieren, wie kann ich beides in MultiplyTransform kombinieren?

    Ist dieses Problem ebenfalls gelöst? Anhand deiner Hilfreich-Verteilungen hätte ich gesagt, dass es sich um eine nicht zwangsweise optimale Lösung handelt.

    So verschieden sehe ich die Meinungen übrigens nicht.

    Viele Grüße
    ~blaze~