Drehung eines Rechtecks um einen bestimmten Winkel

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

    Drehung eines Rechtecks um einen bestimmten Winkel

    Guten Abend,

    ich habe mittels folgendem Rechenweg die neuen Koordinaten eines Punktes berechnet, um von einem Ausgangspunkt um einen bestimmten Winkel ein Rechteck zu drehen. Die Länge des Rechtecks muss dafür natürlich erhalten bleiben.

    Hypotenuse c bekannt, da es die Länge des Rechtecks ist.
    1. sin((PI / 180) * (90 - beta)) * c = Seite a
    2. sqrt(-(a * a) + (c * c)) = Seite b
    3. ((a * a) / c) = p (Teil der Hypotenuse)
    4. c - p = q (Teil der Hypotenuse)
    5. sqrt(p * q) = h (Höhe, also im rechten Winkel von der Hypotenuse hoch zum Punkt mit dem eigentlichen rechten Winkel)

    Im zweiten Schritt wird ein weiteres Dreieck berechnet, damit das Rechteck trotz Drehung in seiner Form erhalten bleibt (Berechnung der Punkte Links-oben und Links-unten).

    Hypotenuse b bekannt, da es die "Dicke" des Rechtecks ist.
    1. b / sin((PI / 180) * (90 - alpha)) = Seite c
    2. sqrt(-(b * b) + (c * c)) = Seite a
    3. ((a * a) / c) = p (Teil der Hypotenuse)
    4. c - p = q (Teil der Hypotenuse)
    5. sqrt(p * q) = h (Höhe, also im rechten Winkel von der Hypotenuse hoch zum Punkt mit dem eigentlichen rechten Winkel)

    Ich glaube, dass der Rechenweg soweit richtig sein müsste. Damit lässt sich die neue Koordinate der um einen Winkel x gedrehten Seite berechen.
    Außerdem erhalte ich durch die zweite Dreiecksberechnung die beiden anderen Punkte des Rechtecks. Siehe hierfür Anhang 3.

    Nun erhalte ich aber ein zwar gedrehtes Rechteck, aber mit teils ganz leicht krummen Seiten. Besonders die beiden kurzen Seiten und dann gerade bei dem ganz rechten Rechteck gibt es augenscheinlich kleinste Abweichungen, die man bei genauerer Betrachtung aber erkennen kann.

    Wie kommt das zustande? Richtig gerechnet müsste ich haben. Oder liegt das an der Darstellung, also bspw. am Monitor?
    Bilder
    • Schiefes Rechteck.png

      8,42 kB, 508×249, 24 mal angesehen
    • Schiefes Rechteck.png

      16,52 kB, 508×249, 21 mal angesehen
    • Unbenannt.png

      81,89 kB, 1.407×279, 22 mal angesehen
    • Schiefes Rechteck.png

      18,68 kB, 508×249, 22 mal angesehen

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „rwCapt“ ()

    das kann ja nur ein Darstellungsfehler sein.
    Du zeichnest das Rechteck ja nicht mit einer Zeichenmethode, die KreisSegmente darstellt, oder Bzier-Kurven oder sowas, oder?

    edit: jo, stimmt auch wieder.
    Nur sollte man ein Graphics nicht drehen, sondern lieber nur die Zeichnung, die man darauf darstellen will.
    Weil zB Mausklicks einem Figur-Element zuordnen, was in ein verdrehten Graphics gezeichnet wurde, ist - naja, ich jdfs. weiss nicht, wie das gehen soll.
    Also besser nicht mit ssowas anfangen.

    Mein Königsweg ist: in einem System.Drawing.Drawing2d.GraphicsPath eine Zeichenfigur anlegen.
    Diesen mit der System.Drawing.Drawing2d.Matrix drehen, verschieben, whatever.
    Dann mit Graphics.DrawPath "zu Papier" bringen.

    Im Tut- Bereich habich auch ein Tut zu "OwnerDrawing".
    Das ist ein weites Feld, aber wer was lernen will, kann da ssicherlich so allerlei rausziehen.

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

    @ErfinderDesRades
    Es gibt immer mehrere Möglichkeiten und warum nicht die Graphics drehen? Nimm ein Blatt Papier, nimm einen Pin und tacker das Blatt Papier zb im Mittelpunkt (Rotatiospunkt) fest. Dreh das Blatt Papier um diesen Punkt um zb 45 Grad. Zeichne ein Rechteck mit senk- und waagerechten Linien wobei dessen Mittelpunkt = der Rotationspunkt ist. Dreh das Blatt Papier um 45 Grad zurück. Was einfacheres gibt es nicht.
    Mfg -Franky-
    Hi.

    Es ist die bessere Alternative, vorgegebene Methoden zu nutzen.

    Um beide Vorredner (-tipper) zusammenzubringen.

    Das Blatt Papier ist die Zeichnung auf einer Pinnwand, und der Pinn hat bei @ErfinderDesRades in

    Quellcode

    1. System.Drawing.Drawing2d.Matrix
    eine Rotationsfunktion (und mehr).

    Falls später auch WPF-Technik (3D) ausprobiert wird, ist dann ist die gleiche Vorgehensweise (mittels Matrix-Operationen) anzuwenden.

    Gebt mir einen Hebel, der lang genug, und einen Angelpunkt, der stark genug ist, dann kann ich die Welt mit einer Hand bewegen. -Archimedes


    Habe da mal was zum Verständnis gepostet, kannst ja mal den Beitrag überfliegen.
    Drehung und Projektion einer Ebene.

    Viel Spaß mit Matrix und sein Neo... uups falscher Franchise. :)

    c.u Joshi aus Lost in Translation oder HH

    -Franky- schrieb:

    @ErfinderDesRades
    Es gibt immer mehrere Möglichkeiten und warum nicht die Graphics drehen? Nimm ein Blatt Papier, nimm einen Pin und tacker das Blatt Papier zb im Mittelpunkt (Rotatiospunkt) fest. Dreh das Blatt Papier um diesen Punkt um zb 45 Grad. Zeichne ein Rechteck mit senk- und waagerechten Linien wobei dessen Mittelpunkt = der Rotationspunkt ist. Dreh das Blatt Papier um 45 Grad zurück. Was einfacheres gibt es nicht.
    Und nun versuche zu ermitteln, ob die Maus sich überm Rechteck befindet.
    Das Problem dabei ist: Du weist zwar, wo die Maus ist, aber wo das Rechteck ist, weisst du nicht.

    Hingegen wenn du einen GraphicsPath genau da hinmalst, wo er auch hinsoll, dann kannstes mit gp.IsVisible(MousePosition) abhandeln.

    ErfinderDesRades schrieb:

    Weil zB Mausklicks einem Figur-Element zuordnen, was in ein verdrehten Graphics gezeichnet wurde, ist - naja, ich jdfs. weiss nicht, wie das gehen soll.
    Also besser nicht mit ssowas anfangen.

    Das ist erstaunlich leicht. Wenn man ein Graphics Objekt transformiert, passiert das mit einer Matrix. Um diese Graphics wieder in den ursprünglichen Zustand zu bekommen, muss man es mit der Inversen dieser Matrix transformieren. Jetzt malst du bspw. ein Rechteck und überprüfst mit .Contains() ob der Mauszeiger sich darin befindet. Das gleiche funktioniert auch unter einer Transformation, wenn man den Punkt (Mauszeiger) einfach mit der Inversen transformiert.

    Also jeder Hittest funktioniert auch unter Tranfsormationen. Man muss nur vorher den zu testenden Punkt mit der Inversen transformieren.

    C#-Quellcode

    1. bool HitTestTransformed(Point p, Matrix transform)
    2. {
    3. using (Matrix inverse = transform.Clone())
    4. {
    5. inverse.Invert();
    6. var transformedPoint = new Point[] { p };
    7. inverse.TransformPoints(transformedPoint);
    8. return DoHitTest(transformedPoint[0]);
    9. }
    10. }

    ErfinderDesRades schrieb:

    Und nun versuche zu ermitteln, ob die Maus sich überm Rechteck befindet.
    Da hab ich ja Glück das der TE gar nicht danach gefragt hat. :) Ansonsten gehe ich konform mit den anderen Postings. Um ein wenig bei @Joshi zu bleiben: Blaue oder Rote Pille? ;)

    Ansonsten, ja ich weis, ist VB6, also ein alter Hut. :P

    Visual Basic-Quellcode

    1. Private Function Rotation(ByVal Degrees As Single, _
    2. ByRef xyPoint() As PointF, _
    3. ByRef xyCenter As PointF) As PointF()
    4. 'Operation eM11 eM12 eM21 eM22
    5. 'Rotation Cosine Sine Negative sine Cosine
    6. 'X = (x * Cos) + (y * Sin) + eDx,
    7. 'Y = (x * -Sin) + (y * Cos) + eDy,
    8. Dim Radians As Single
    9. Dim CosRadians As Single
    10. Dim SinRadians As Single
    11. Dim lngItem As Long
    12. Dim lngCount As Long
    13. Dim tPointF() As PointF
    14. lngCount = UBound(xyPoint)
    15. ReDim tPointF(lngCount)
    16. Radians = CSng(Degrees * (Atn(1) * 4) / 180)
    17. CosRadians = CSng(Cos(Radians))
    18. SinRadians = CSng(Sin(Radians))
    19. For lngItem = 0 To lngCount
    20. tPointF(lngItem).X = CSng((xyPoint(lngItem).X * CosRadians) + _
    21. (xyPoint(lngItem).Y * SinRadians) + xyCenter.X)
    22. tPointF(lngItem).Y = CSng((xyPoint(lngItem).X * -SinRadians) + _
    23. (xyPoint(lngItem).Y * CosRadians) + xyCenter.Y)
    24. Next
    25. Rotation = tPointF
    26. End Function
    Mfg -Franky-

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „-Franky-“ ()

    @Gonger96 also "ganz einfach" sich beim Malen die Matrix merken, und bei jedem HitTest deren Inverse erzeugen, und den Mauspunkt damit transformieren?
    Also einfacher wäre doch gewesen, man hätte die Zeichnung gleich beim Zeichnen transformiert, dann könnte man den Hittest da ausführen, wo die Zeichnung ist.

    Und noch eine Schippe draufgelegt:
    Male nu ein Rechteck nach rechts gedreht, und ein zweites nach links gedreht. willst du jetzt für jedes Rechteck die Matrix merken, wie du es gedreht hast, und dann den Mauspunkt da in der Gegend herum-schleudern?
    @ErfinderDesRades
    Sinn macht das hauptsächlich, wenn man nur eine Transformation hat. Ich hab mal irgendwann eine Multiline Textbox programmiert, die rein auf GDI+ basierte. Die konnte man in alle Himmelsrichtungen drehen, skalieren etc. Die komplette Maus-Interaktionslogik habe ich nur einmal für den "untransformierten" Zustand geschrieben. Eine Scrollbar auf 45° mit der Maus hin- und herzuziehen ist zwar Quatsch, hat aber hervorragend funktionert.
    Hallo @rwCapt, es gibt zwei Möglichkeiten, eine Grafik zu drehen und dann darzustellen:
    1. du malst mit .NET-eigenen Funktionen eine Figur, zum Beispiel ein Rechteck, und drehst das mithilfe der vorhandenen Funktionen. Um die Darstellung kümmert sich die Funktion. Da brauchst du nichts machen. Ich weiß gerade dar nicht, ob auch 3D-Drehung und -projektion möglich ist.
    2. du machst dir – um zu lernen – eine Liste mit Vektoren (einfach ne Klasse mit 3 Doubles (x, y, z)). In diese Liste fügst du alle Vektoren hinzu, die du brauchst. Wenn du einen 3D-Quader erzeugen willst, einfach 3 For-Schleifen von x1 zu x2, von y1 zu y2 und von z1 zu z2. Diese Vektoren kannst du mit den Drehmatrizen drehen. Wenn du bei der Mathematik Hilfe brauchst, sag gern bescheid. Damit das Ganze korrekt aussieht – auch in 3D – musst du die Projektionsformel verwenden. Dann alle fertig berechneten Punkte zeichnen.
    Du kannst also 1) oder 2) machen, aber bitte nicht einfach irgendwie (mit Hypotenusenformeln und etwas ich nenne es mal "Ausgedachtem") die Drehung berechnen. Es kommt immer zu Rundungs- und Darstellungsfehlern und die Drehung (und auch die aufeinander zu laufenden Linien in der Tiefe) sieht nicht akkurat aus.

    Das hier hab ich vor ein paar Monaten gebaut.




    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Bartosz“ ()

    Leute, vielen Dank für die Antworten.
    Ich wollte zwecks Übung erst mal das ganze möglichst ohne vorhandene Funktionen machen. Ich saß die letzten Tage vor dem Laptop und hab mir quasi fingernägelzerkauend (sprichwörtlich) durch den Kopf gehen lassen, wie ich denn dieses verdammte Objekt drehen kann (der rote Balken da ist nur ein Teil). Dabei habe ich eine Sache ganz aus den Augen verloren: Die Drehmatrix. Verschiebe sämtliche Koordinaten in den Urspruch (oder aber deinen "Origin-Point", um den du drehen möchtest und führe die Drehberechnung mittels Drehmatrix aus.

    @Bartosz Daran, dass es an Rundungsfehlern liegt, hatte ich bislang nicht wirklich gedacht. Aber das ist gut möglich.