Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Beim Kreis Winkel herausfinden


mg4all - Fr 07.08.09 21:44
Titel: Beim Kreis Winkel herausfinden
Hallo Leute !

Ich habe seit langer Zeit mal wieder ein kleines Problem.

Ich habe einen Kreis gezeichnet (ganz normal) und wenn ich jetzt auf den Strich klicke möchte ich den entsprechenden Winkel angezeigt bekommen (ausgehend von rechts = 0). Kann mir jemand weiterhelfen ?

MG4all


Delete - Fr 07.08.09 23:01

Was für ein Winkel soll das sein? Was sollen die beiden Schenkel des Winkels sein?


mg4all - Fr 07.08.09 23:41

Einfach alle Winkel die der Kreis hergibt !


Delete - Sa 08.08.09 00:30

Könnest du bitte mal etwas deutlicher werden? Oder wenn das nicht geht mal eine Grafik anhängen?


Hidden - Sa 08.08.09 00:40

Hi :)

Um einen Winkel angeben zu können, benötigt man drei Punkte. Wenn ich dich richtig verstanden habe(schwerlich, du drückst dich nicht sehr ausführlich aus), ist der erste Punkt wohl in Bezug auf den Einheitskreis [http://de.wikipedia.org/wiki/Einheitskreis] der Punkt (1/0), bzw. auf den allgemeinen Kreis dann (Xm+r/Ym). Der zweite Punkt wäre der Mittelpunkt (Xm/Ym). Und als dritten Punkt dann einfach die Koordinaten des Mausklicks nehmen.

Haben wir also unsere drei Punkte, so können wir eine Steigung berechnen. Diese Wandeln wir dann mit dem Arcustangens in einen Winkel um.

Im beschriebenen Fall ist die Steigung des Winkelschenkels P1-P2 wohl null, daher berechnen wir einfach die Steigung der Strecke Mittelpunkt - Mausklick.

Die Steigung berechnet sich als

Quelltext
1:
m := dy/dx = (Maus.Y - Ym) / (Maus.X - Xm)                    


Da du den Kreis "ganz normal" gezeichnet hast, gehe ich mal davon aus, dass du wie es sich gehört eine Paintbox verwendest - und kein Image oder gar das Canvas des Formulars ;)

Dann nimmst du dir beispielsweise die Methode

Delphi-Quelltext
1:
2:
3:
4:
5:
procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin

end;


und hast mit den Parametern X, Y die Koordinaten der Maus. Mit ArcTan(m) = w erhältst du aus den Koordinaten wie oben beschrieben den Winkel. Jetzt musst du aber noch einige Sonderfälle beachten, das überlasse ich mal dir. So musst du dir noch überlegen was du machst, wenn die Steigung entweder Unendlich oder negatives Unendlich ist(Xm = Maus.X). Außerdem lässt sich von der Steigung nicht eindeutig auf den Winkel schließen, da um 180° vergrößerte Winkel wieder der selben Steigung entsprechen. Da negatives dY und negatives dX die selbe Steigung geben wie die positiven Werte, kannst du so nur den Bereich von -90° bis +90° erfassen. Du kannst allerdings vorher prüfen, ob einer der Werte negativ ist und entsprechend 180° dazuaddieren, damit hast du dann alle Winkel.

Insgesamt entspricht das dann der Funktion ArcTan2 - für die Eingeweihten. Für den Anfang solltest du es aber erst einmal selbst umsetzen, da du es dann besser verstehst.

mfG,


NetSpider - Sa 08.08.09 01:41

Ich hab hier mal versucht was zusammen zu stoepseln - und ja ich weiss - es zeichnet direkt auf das Form-Canvas Object, aber vielleicht ist es ein kleine Hilfe und Denkanstoss. Es wird der Winkel von der vertikalen kreishalbierenden (zwischen 4. und 1. Quadrant) und der Linie berechnet die im OnMouseDown-Event gezeichnet wird.

Funktionsweise:

Es werden die Diagonalen von zwei Seiten des entstehenden Dreiecks ausgerechnet (Gegenkathete und Hypotenuse). Diese werden dann mit Hilfe von einigen Formeln (z.B. http://de.wikipedia.org/wiki/Trigonometrie) ins Gradmass umgerechnet.

Ich weiss jetzt im Moment nicht wie man diesen Schoenheitsfehler bereinigen kann, dass er maximal auf 180 Grad geht, aber es ist auch schon spaet :-)

Gruss


jfheins - Sa 08.08.09 12:41

user profile iconNetSpider hat folgendes geschrieben Zum zitierten Posting springen:

Ich weiss jetzt im Moment nicht wie man diesen Schoenheitsfehler bereinigen kann, dass er maximal auf 180 Grad geht, aber es ist auch schon spaet :-)

In der Math-Unit sollte es eine Funktion arctan2 geben, die genau für diesen Zweck (kart. Koordinaten => Polarkoordinaten) geschrieben wurde ;)


Hidden - Sa 08.08.09 13:04

Hi :)

user profile iconHidden hat folgendes geschrieben Zum zitierten Posting springen:
Insgesamt entspricht das dann der Funktion ArcTan2 - für die Eingeweihten. Für den Anfang solltest du es aber erst einmal selbst umsetzen, da du es dann besser verstehst.
:zwinker:

Mit welcher Version von Delphi hast du das denn erstellt, mein Turbo Delphi 2006 sagt dazu: [Pascal Error] Project1.dpr(11): E2003 Undeclared identifier: 'MainFormOnTaskbar'

Vielleicht bringt dich ja der Anhang auf eine Idee, warum man eine Paintbox verwenden sollte. Ist eigentlich ganz unkompliziert: Man erzeugt die zu Zeichnenden Sachen als Bitmaps rein im Speicher(Formvariable deklarieren, im Formcreate erzeugen, Größe setzen.) und zeichnet in der OnPaint-Methode der Paintbox alles mti Stretchdraw() drauf. Näheres über die Suche :)

Kleiner Tipp: Bei den um 180° verschobenen Winkeln ist die Mauß links vom Mittelpunkt, bei den Originalwinkeln rechts. @user profile iconNetSpider: Bei dir ist der Nullwinkel übrigens oben, user profile iconmg4all hat schon von der mathematisch korrekten Variante mit 0° <-> Rechts geschrieben ;)

mfG,


jaenicke - Sa 08.08.09 13:06

user profile iconHidden hat folgendes geschrieben Zum zitierten Posting springen:
Mit welcher Version von Delphi hast du das denn erstellt, mein Turbo Delphi 2006 sagt dazu: [Pascal Error] Project1.dpr(11): E2003 Undeclared identifier: 'MainFormOnTaskbar'
Das gibt es ab Delphi 2007, was es macht sagt ja der Name schon (das passt in den Rahmen der Korrekturen um das bis D2006 versteckte Application-Fenster für die Taskleiste, wodurch die Taskbarvorschau ab Vista z.B. nicht ging bei Delphiprogrammen). :mrgreen:


NetSpider - Sa 08.08.09 14:16

Ich weiss dass der Canvas von TForm fluechtig ist, aber das ganze sollte eben nur ein Denkanstoss sein. Ausserdem bin ich mir nicht sicher ob ich alles richtig gemacht hab bei den Formeln. Beim letzten Teil hab ich einfach ausprobiert.

Das Programm ist in Delphi 2007 erstellt worden.


mg4all - Mo 10.08.09 04:14

Hi !

Danke für das kleine Programm. So ungefähr habe ich mir das vorgestellt aber ich komme mit deinen Koordinaten A1, B1, D1 usw. leider nicht klar. Kannst du mir das noch ein bisschen besser erläutern. Desweiteren sollte mein Winkel rechts bei 0 losgehen und dann gegen den Uhrzeigersinn immer größer werden.

Danke schon mal im voraus !!!


jfheins - Mo 10.08.09 12:48

Seien Xm und Ym die Koordinaten des Kreismittelpunkts.
Weiter seien X und Y die Koordinaten des Punktes

Dann berechnest du:


Delphi-Quelltext
1:
2:
deltaX := X - Xm;
deltaY := -(Y - Ym);


das tust du nun in deine (ggf. selbst programmierte) arctan2 Funktion rein:


Delphi-Quelltext
1:
phi := arctan2(deltaY, deltaX);                    


Und du hast den Winkel. Bei dieser Lösung ist der Winkel nach rechts =0 und wird nach unten negativ.
Falls du den Winkel statt von -Pi ... +Pi (bzw. -180° .. +180°) lieber von 0..2Pi (0..360°) haben möchtest, füge noch folgendes ein:

Delphi-Quelltext
1:
2:
if phi < 0 then
  phi := phi + 2*Pi;


Das Ergebnis kannst du jetzt ins Gradmaß umrechnen, wenn du willst:


Delphi-Quelltext
1:
phi_deg := RadToDeg(phi);                    


Hoffe geholfen zu haben :)


mg4all - Mo 10.08.09 22:07

Hi

Vielen Dank für die viele Hilfe. Habe es jetzt so gemacht wie Hidden es geschrieben hat.