Laden...

Drehen und Skalieren eines Rechtecks

Erstellt von Gimmick vor 6 Jahren Letzter Beitrag vor 6 Jahren 3.571 Views
G
Gimmick Themenstarter:in
154 Beiträge seit 2015
vor 6 Jahren
Drehen und Skalieren eines Rechtecks

Moin,

ich habe hier ein paar Schwierigkeiten beim Drehen eines Rechteckes.

Und zwar möchte ich eine rechteckige Auswahl im Bildbetrachter zeichnen und benötige dafür die vier Punkte des Rechteckes. Das Rechteck soll drehbar, gedreht an jeder Ecke anfassbar und darüber änderbar sein.

Ich habe jetzt Schwierigkeiten das ganze optisch und geometrisch stabil hinzubekommen.

Was ich versucht habe:

1.
Ich betrachte jeden Punkt einzeln und nur mit den eigentlichen Koordinaten im Bild. Beim Drehen wird immer um den Mittelpunkt des Rechtecks gedreht, beim Verschieben eines Punktes berechne ich die Position der beiden verbundenen Punkte über Vektorprojektion selbst.

Ergebnis: Ein frei drehbares immer änderbares Rechteck, dass aber leider nach einigem hin-und-her-Drehen ein wenig aus der Form geht, es bleibt also nicht garantiert rechtwinklig.

2.
Ich habe eine Klasse "Rechteck" erstellt, welche die Eigenschaften des Rechtecks (Höhe, Breite, Drehwinkel) enthält.
Beim Ändern der Rechteckmaße transformiere ich die Mauskoordinaten in die Rechteckkoordinaten und verschiebe die entsprechende Ecke zur Maus. Das Ergebnis transfomiere ich in Position und Rotation wieder in das Bild.

Ergebnis: Die Winkel bleiben immer rechtwinklig und das Rechteck lässt sich frei bewegen, drehen und in der Größe ändern - aber:
Ziehe ich an einer Ecke des Rechtecks ändert sich auch der Mittelpunkt. Das heisst der Rotationpunkt ändert sich beim Ändern der Größe, wodurch sich alle Punkte in ihrer Position ändern.
Ich muss nach jeder Änderung den Mittelpunkt des sichtbaren Rechtecks in Rechteckkoordinaten transfomieren und dort dann das Rechteck passend verschieben und dann wieder ins Bild zurück transformieren. Das sieht man leider in Form von "Gezuppel".

Gibt es da bessere und stabilere Lösungen für?

P
1.090 Beiträge seit 2011
vor 6 Jahren

Hi Gimmick,

es wäre nett wenn du die Technologie Angibst mit der du Zeichnest Windows Forms oder WPF. (Ich denke mal bei WPF wäre das eine Lösung : Scale, Move and rotate controls in your GUI - WPF

Auch wäre es nett wenn du Ausschnitte des Quellcodes mit angeben würdest. Damit man sehen kann wie du die Berechnungen machst.

Grundlegend kann ich mir jetzt nicht vorstellen, das die Berechnungen so aufwändig sind.

Bei 2 hab ich auch nicht ganz Verstanden wie so du jedes mal wie so du jedes mal den mittel Punkt neu berechnest. Den Brauchst du eigentlich nur für die Rotation, aber die Berechnung ist jetzt auch nicht wirklich komplex, der liegt ja genau in der Mitte von 2 gegenüberliegenden Ecken (Punkten).

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

C
2.121 Beiträge seit 2010
vor 6 Jahren

bei 1. sind es sicher Rundungsfehler, die die Punkte langsam aus der Form laufen lassen. Da ist 2. schon besser, damit hast du für jeden Drehwinkel stabile Ausgangsdaten.

Rechnest du übrigens schon mit float oder double? Sonst gibts sowieso Fehler.

Den Mittelpunkt nach-berechnen halte ich für keine gute Idee. Beim verziehen einer Ecke bleibt der gegenüberliegende Punkt doch eigentlich konstant. Lass den da stehen wo er gerade steht, verschiebe den Ziehpunkt dahin wo er hin soll und berechne anhand der beiden Punkte die beiden anderen neu. Dann dürfte es schon ruhiger werden.

Vorausgesetzt ich verstehe das Problem richtig.

G
Gimmick Themenstarter:in
154 Beiträge seit 2015
vor 6 Jahren

Hi Gimmick,

es wäre nett wenn du die Technologie Angibst mit der du Zeichnest[...]

Das Zeichnen, im Sinne der Darstellung, wird über einen Bildbetrachter quasi direkt als Grafik erledigt. Das Ganze an sich ist eine Forms-Anwendung.

Bei 2 hab ich auch nicht ganz Verstanden wie so du jedes mal wie so du jedes mal den mittel Punkt neu berechnest. Den Brauchst du eigentlich nur für die Rotation, aber die Berechnung ist jetzt auch nicht wirklich komplex, der liegt ja genau in der Mitte von 2 gegenüberliegenden Ecken (Punkten).

Genauer zur zweiten Methode:
Dem Rechteck gebe ich 5 Punkte: Die Ecken A,B,C,D und den Rotationspunkt R. Dazu noch den "Offset" für die Positionierung im Bild und den Winkel.

Wenn das Rechteck immer um seinen Mittelpunkt gedreht werden soll passiert folgendes:
Die Matrix M transformiert jeden Punkt [A,B,C,D] für den Offset O und den Winkel W um Punkt R.
Jetzt ziehe ich an einer Ecke. -> Die Mauskoordinaten werden über die selbe, aber invertierte Matrix in Rechteckkoordinaten transformiert, die entsprechende Ecke wird zur transformierten Mausposition bewegt.
Um den Punkt korrekt in das Bild zu transfomieren darf sich R nicht ändern, denn alle vier Punkte wurden ja über die Rotation in Bezug auf R gebildet.

Jetzt möchte ich das Rechteck wieder drehen. Und zwar um den neuen Mittelpunkt R2 mit Matrix M2.
Das Rechteck, transfomiert mit M2, entspricht aber nicht dem Rechteck, was man im Bild sieht.

Damit das Rechteck transfomiert mit M2 dem Rechteck im Bild entspricht muss das Rechteck im Bild invertiert-transfomiert dem Rechteck im Rechteck-Raum entsprechen.

Dann ändere ich aber mein original Rechteck, was ja eigentlich nicht Sinn der Sache ist, da es so nicht mehr garantiert rechtwinklig bleibt.

Und Punkt B transfomiert mit M zu B' ist halt dummer Weise nicht gleich B transfomiert mit M2 zu B'. :<

Rechnest du übrigens schon mit float oder double? Sonst gibts sowieso Fehler.

Jop.

Vorausgesetzt ich verstehe das Problem richtig.

Die Frage ist dann:
Wie drehe ich das "verzogene" Rechteck wieder um seinen neuen Mittelpunkt?
Ich bräuchte entweder ein neues original Rechteck, das mit bekannter Matrix M das bekannte Bild ergibt, oder eine neue Matrix M, die mir aus dem bekannten Rechteck das gezeigte Bild errechnet.

Ich habe aber noch eine dritte, Idee mittlerweile 😄:

Es wird mit einem ungedrehten Rechteck bekannter Koordinaten gestartet.
Statt den Ecken kann man jetzt die Kanten ziehen ^^.
Beim Rechteck A,B,C,D (links oben, rechts oben....) werden z.B. beim Anfassen der Kante AB aus den Punkten CA und DC zwei Geraden von Bildrand zu Bildrand nach Bresenham oder ähnlichem berechnet.
Das Bewegen der Maus verschiebt dann die Punkte nur auf Pixeln dieser Geraden.

Bei Rotation wird aus AC und BD der Mittelpunkt bestimmt und der umschließende Kreis berechnet. Die Pixel befinden sich sortiert in einer Liste und für jeden Punkt A,B,C,D wird der aktuelle Index in dieser Liste bestimmt. Beim Drehen wird dann der Index erhöht oder verringert.

Habe mal ein Bild angehängt.
Meinungen? 😄

P
1.090 Beiträge seit 2011
vor 6 Jahren

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

G
Gimmick Themenstarter:in
154 Beiträge seit 2015
vor 6 Jahren

So ähnlich habe ich das auch gemacht, das löst aber auch nicht das Problem des wechselndes Rotationspunktes.
In seinem Beispiel dreht er das Rechteck immer um den selben Punkt, das klappt bei mir auch 😄

P
1.090 Beiträge seit 2011
vor 6 Jahren

Lies dir mal die ToTos durch "when you stop dragging, reset the _rectPos to the center of the rectangle"

Das kannst du ganz einfach beim MouseUp Event machen.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

G
Gimmick Themenstarter:in
154 Beiträge seit 2015
vor 6 Jahren

Hatte die Transformation des Offsets vor dem Umrücken vergessen 😐

Das mit den Linien funktioniert btw auch 😄

Hinweis von Abt vor 6 Jahren

Bitte keine Full Quotes