Eine Linie um einen bestimmten Winkel rotieren

    • VB.NET

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

      Eine Linie um einen bestimmten Winkel rotieren

      Hier ein kleines Script von mir um eine gedachte Linie zwischen Point1 und Point2 um einen bestimmten Winkel zu rotieren. Point1 ist die Achse und Point2 ist der Punkt, der bewegt werden soll. Die Funktion "RotatePoint" gibt die Koordinaten von Point2 zurück.





      VB.NET-Quellcode

      1. Public Function RotatePoint(ByVal Point1 As Point, ByVal Point2 As Point, ByVal Rotation As Integer) As Point
      2. 'Point1 = Axis/Achse
      3. Dim LineLenght As Integer = CInt(Math.Sqrt((Point1.X - Point2.X) * (Point1.X - Point2.X) + (Point1.Y - Point2.Y) * (Point1.Y - Point2.Y)))
      4. 'Calculate hypotenuse/Hypotenuse ausrechnen
      5. Point2.X = CInt(Math.Sin(Rotation * (Math.PI / 180)) * LineLenght + Point1.X)
      6. Point2.Y = CInt(Math.Cos(Rotation * (Math.PI / 180)) * LineLenght + Point1.Y)
      7. Return Point2
      8. End Function




      Gruß, Jan

      Edit by ~blaze~:
      *Thema aus Hauptforum verschoben, vb-Tags eingefügt*

      Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „J-F“ ()

      Herzlich willkommen im Forum. :thumbup:
      1. nutze den [VB]-Tag direkt über dem Edit-Feld der Posts.
      2. Gib Deinem Programm Option Strict On
      Beseitige die Fehler. Wenn dann Dein Problem immer noch auftritt, melde Dich wieder.
      Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
      Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
      Ein guter .NET-Snippetkonverter (der ist verfügbar).
      Programmierfragen über PN / Konversation werden ignoriert!

      RodFromGermany schrieb:


      2. Gib Deinem Programm Option Strict On
      Beseitige die Fehler. Wenn dann Dein Problem immer noch auftritt, melde Dich wieder.


      Würdest du den (jedenfalls neuen) nutzern etwas mehr aufmerksamkeit schenken, würdest du nun wissen, dass J-F kein problem hat.


      #Edit
      @J-F: Anstatt

      VB.NET-Quellcode

      1. LengthX = LengthX * LengthX

      das hier:

      VB.NET-Quellcode

      1. LengthX = LengthX ^ 2


      (^ 2 = hoch 2)
      Hi
      es ist sogar günstiger, x * x statt x^2 zu rechnen. a ^ b basiert auf einem komplexeren Algorithmus, als a * a, wenn b = 2. Der komplexe Algorithmus wird dann für alle b ausgeführt, anstatt ihn auf a * a zu reduzieren, weil in den meisten angenommenen Fällen eine Abfrage auf 2 die Performanz abschwächen würde. Also brav x * x rechnen.

      Hab' das Thema mal in den Sourcecode-Austausch verschoben, aber korrigiere bitte noch auf Option Strict On und (a-b) ^2 = (b-a)^2. D.h. die if-Abfrage ist überflüssig. Die Methoden würde ich außerdem statisch machen, da keine Referenz auf Me nötig ist.

      Gruß
      ~blaze~

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „~blaze~“ ()

      die System.Drawing.Drawing2D.Matrix - Klasse stellt alle geometrischen Transformationen bereit, dies im 2D-Raum gibt:
      Rotation, Translation, Vergrößerung (X/Y), Scherung.

      Kann angewendet werden auf Point-Arrays, aber auch auf GraphicsPathes (bei OwnerDrawing sehr interessant).
      Option Strict On!

      vb.net ist eine typisierte Sprache, d.h., es gibt Klassen, und es ist programmiert, was eine Klasse kann und was nicht.
      Und die Klassen unterscheiden sich, und man kann nicht einen String an eine Integer-Variable zuweisen, weil das Quatsch ist.
      Man kann natürlich sehr viel umwandeln - "parsen".
      Bei Strict Off überlässt du die Umwandlungen dem Compiler, mit dem Effekt, dass du die Klassen nie kennenlernst, weil dir ja garnet bewußt wird, was du da zusammenrührst, wennde schreibst:

      VB.NET-Quellcode

      1. dim i As Integer = "5"

      Andauernd stoße ich auf grauenhafte Code-Snippets, und wenn ich frage: "Wasn das fürn Datentyp?" kann man mir oft gar keine Antwort geben, weil ühaupt kein Plan, was "Datentyp" eiglich bedeutet.
      Kann angewendet werden auf Point-Arrays, aber auch auf GraphicsPathes (bei OwnerDrawing sehr interessant).

      Und auf ein Graphics Objekt(auch sehr interessant :P)

      @TE: Option Strict ON hilft dir dabei sauber zu programmieren und Fehler zu vermeiden(diese Fehler sind oft dann nicht nachvollziehbar und völlig unnötig). Mit Option Strict OFF sollte man gar nicht programmieren, mich nervt es immernoch, dass es das überhaupt gibt, dies ist nur bei VB.Net vorhanden...

      @ErfinderDesRades: nächstes mal langsamer schreiben :P
      Ich wollte auch mal ne total überflüssige Signatur:
      ---Leer---

      J-F schrieb:

      aber ich würde gerne wissen, was genau das jetzt bring.
      @BeefyX: (zur Info)
      Ich hab Deinen (J-F) Quellcode bei mir eingefügt und werde sofort mit einer Reihe von Option Strict On Fehlern bombardiert, da ich grundsätzulich so arbeite, d.h., mein Studio ist so konfiguriert, dass anne neuen Projekte automatisch Option Strict On haben. Es liegt nun in meinem Ermessen, ob ich die Fehler selbst beseitige oder den TE bitte, dies zu tun. Mein Ermessen richtet sich einfach an der Anzahl der gemeldeten Fehler, und die waren mir einfach zu viel.
      Nun können wir über Algorithmen und Probleme reden. :D
      Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
      Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
      Ein guter .NET-Snippetkonverter (der ist verfügbar).
      Programmierfragen über PN / Konversation werden ignoriert!
      Inzwischen hast Du ja auch fast den ganzen Quellcode rausgenommen.
      Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
      Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
      Ein guter .NET-Snippetkonverter (der ist verfügbar).
      Programmierfragen über PN / Konversation werden ignoriert!
      Vielleicht wurde es schon erwähnt:
      Die Klasse System.Drawing2D.Matrix hat eine Funktion namens RotateAt(Single,PointF).
      Eine Matrix kann man einigen Graphics-Objekten "zuweisen". (GraphicsPath,Graphics, etc.)

      Beispiel:

      VB.NET-Quellcode

      1. '@Onpaint
      2. Dim [Matrix] As New Drawing2D.Matrix
      3. Matrix.RotateAt(90.0!, New PointF(20.0!, 20.0!))
      4. e.Graphics.Transform = [Matrix]
      5. e.Graphics.DrawLine(..)



      Liebe Grüße
      /nicht getestet
      Ja, wurde schon erwähnt, in post#5

      Nur grade von der Transformation von Graphics-Objekten rate ich dringend ab (grad weil das nun schon zweimal angesprochen wurde):
      1. Es ist enorm schwierig, auf einem verzerrten Graphics-Objekt auch nur bisserl kompliziertere Zeichnungen akkurat auszuführen.
      2. Die Koordination von Maus und Control ist im Eimer. Durch die Verzerrung der Darstellung verliert die Maus-Position ihren Bezug zur Oberfläche des Controls, und du bist vollkommen verloren, wenn du auswerten willst, worauf die Maus grade zeigt.
      3. Gelegentlich gibt es mehrere Stellen im Code, wo auf dasselbe Control gezeichnet wird. Verstellst du in der ersten dieser Methoden die Graphics, so versaust du dir die akkurate Zeichnung der zweiten Methode. Naja - kommt selten vor.
      Abgesehen vom 1. kann man die restlichen Punkte umgehen. Die Matrix ist in den meisten Fällen bekannt, also kann man auch eine Transformation auf den Cursor anwenden. Punkt 3 kann man durch Zwischenspeichern der alten Matrix und einer Multiplikation mit dieser erzwingen. Was meinst du bei Punkt 1?

      Gruß
      ~blaze~
      Zu 1: angenommen eine analog-Uhr sei zu zeichnen. Da lege ich eine Zeiger-Figur des Stunden-Zeigers an, und für die anneren Zeiger strecke ich den und machn dünner.
      Dann rotiere ich das Teil in die richtige Ausrichtung und schiebe es auf den Mittelpunkt des Controls.
      Diese Operationen führe ich übrigens nicht eine nach der anneren aus, sondern speicher Streckung, verdünnerung, Rotation, Verschiebung - alles in der jeweiligen Matrix - das ist super-performant :).

      Zum zeichnen wende ich die jeweilige Matrix auf einen Klon der ursprünglichen Zeiger-Figur an, und dann mit Graphics.DrawPath(zeigerKlon) das Teil aufs Control malen.

      Bei einer globalen Matrix-Transformation (also Matrix aufs Graphics-Objekt angewandt) hätte ich jetzt kein Plan, wie sowas auf die Reihe kriegen.


      zu 2 - dass du erst die Graphics transformierst, und dann konsequenterweise jeden Abruf der Mausposition ebenfalls transformieren musst, das ist doch viel komplexer, als die Zeichnung unter Zuhilfenahme der Matrix zu erstellen, aber in ein unverzerrtes Graphics zu zeichnen.
      Aber im Grunde genommen ists geschwätzt: Sobald du mehrere Objekte positionieren mußt, muss auf jedes einzelne eine spezifische Matrix angewandt werden und globale Transformation scheidet aus.
      Stimmt schon. Das Problem hatte ich bei einem kleinen Programm mal. Habe ich dann zwar irgendwie gelöst, aber ich glaub', dass das ziemlich unperformant wurde dann... Eigentlich müsste man bei einer Zeichenoperation nur überprüfen, ob die gesetzte Matrix der Identitätsmatrix entspricht und anschließend - wenn nicht - entsprechende Transformationen an Punkten, Breiten, usw. durchführen. Ich selber bin generell eher nicht der Fan von Matrizen, da einfach alle Multiplikationen ausgeführt werden, also auch unnötige. Das lässt sich im Normalfall schön wegoptimieren. Naja, wenn du auf jeden Fall eine Line von A nach B zeichnen willst, nimmst im naiven Modell den normalisierten Normalenvektor auf den Verbindungsvektor und gehst dem Pen entsprechend die angegebene Punktzahl den Normalenvektor entlang. In einem performanteren Ansatz sollte das aber dann ähnlich ablaufen. Im Prinzip zeichnet man halt nur ein Viereck.

      Gruß
      ~blaze~