Endpunkt einer gezeichneten Linie als Koordinate ermitteln

  • VB.NET

Es gibt 19 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Endpunkt einer gezeichneten Linie als Koordinate ermitteln

    Moin, moin,

    bei meinem aktuellen Projekt brauche ich mal Hilfe.

    Ich habe eine PictureBox 250x 250 Pixel

    Darin zeichne ich mittels DrawLine zwei einzelne Linien.

    '/Mitte meiner PictureBox wird als Drehachse definiert
    X.TranslateTransform(125,125)'/Erzeuge ein Fadenkreuz
    X.DrawLine(Stift_X,0,-125,0,125)
    X.DrawLine(Stift_X,-125,0,125,0)

    Über TranslateTransform lege ich die Mitte der PictureBox als
    Bezugspunkt fest, da ich später meine Linie um diesen Punkt drehen
    möchte.

    Über zwei Textboxen frage ich zwei Werte ab. Der erste Wert ist eine
    Winkelangabe (KdW), der zweite Wert eine Geschwindigkeitsangabe aus der
    dann über einen Maßstab "Länge_Kurslinie" ermittel wird.

    Diese Linie wird an der Vertikalachse erzeugt (= Länge) und um den Winkel gedreht.

    '// Zeichne Kurslinie
    X.RotateTransform(KdW)
    X.DrawLine(Stift_FdW,0,-CInt(Länge_Kurslinie),0,0)

    Das Funktioniert soweit gut.

    Vor dem Drehen habe ich ja meine Koordinaten für den Anfangs- und Endpunkt meiner Linie (damit zeichne ich ja).


    Nun möchte ich in einem zweiten Schritt eine zweite Linie zeichnen, die ihren Anfang dort hat, wo die erste Linie endet.

    Durch das Drehen ist nun aber die Koordinate des Endpunktes nicht mehr dort, wo sie war.

    Nun meine Frage:

    Kann, bzw. wie kann ich die Koordinate des Endpunktes meiner Linie programmtechnisch ermitteln (Mausklick scheidet aus)?
    Bzw. gibt es eine Funktion, die mir den Anfangs- und Endpunkt einer Linie als Koordinate zurück liefert?
    Einen mathematischen Lösungsvorschlag habe ich bereits bekommen. :D
    Viele Grüße
    Stefan

    sailor4rent.de
    Bin gerade über dieses Thema gestolpert.
    Wow - so einfach geht das in VB? Und ich hab in Excel mit Drehmatrizen gerechnet und eine eigene Z/Y/Z'-Konvention entwickelt... 8|

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Higlav“ () aus folgendem Grund: Der gramatik zuliebe XD

    Artentus schrieb:

    So kannst du das berechnen:
    X2 = X1 - Cos(a) * r
    Y2 = Y1 - Sin(a) * r

    r ist die Länge der Linie
    a ist der Winkel
    x1,y1 sind die Koordinaten der Startpunktes
    x2,y2 sind die Koordinaten des Endpunktes
    Vielen Dank!!
    Tja, hätte ich in der Schule mal besser in Mathe aufgepasst.
    Stattdessen habe ich Deutsch gepauckt und das stimmt heute alles nicht mehr :wacko: :D .
    Viele Grüße
    Stefan

    sailor4rent.de

    Artentus schrieb:

    So kannst du das berechnen:
    X2 = X1 - Cos(a) * r
    Y2 = Y1 - Sin(a) * r

    r ist die Länge der Linie
    a ist der Winkel
    x1,y1 sind die Koordinaten der Startpunktes
    x2,y2 sind die Koordinaten des Endpunktes

    @artentus

    Hi,

    irgendwie komme ich auch mit der richten Matheformel nicht weiter.
    Zunächst habe ich eine Linie gezeichnet und gedreht um dann mittels Formel die Koordinate zu berechnen und dann erst mal einen Punkt zu malen.
    Da kam ich aber immer nur in die Nähe des gewünschten Punktes.
    Also habe ich mir mal so zusammengereimt, dass zwei unterschiedliche Methoden (einmal rechnen und ein zweites Mal eine beliebige Linie erzeugen und rotieren) nicht zuverlässig ist.

    Dann habe ich versucht, die Koordinaten für die erste Linie unter Berücksichtigung des Winkels zu berechnen und zu zeichnen.
    Da kam aber immer eine Linie in einem Winkel raus, der nicht stimmte. Bei 90° Eingabe kam ein Winkel um ca. 30° raus.
    Hier mal mein fehlerhafter Code. Fällt jemandem auf, was ich falsch mache?

    VB.NET-Quellcode

    1. '/Definitionen bevor alles berechnet wird
    2. FdW = TB_FdW.Text
    3. Dim X As Graphics = PB1.CreateGraphics()
    4. X.Clear(Me.BackColor)
    5. '//Hier werden die Daten für die grafische Darstellung des eigenen Kurses
    6. 'berechnet und gezeichnet
    7. Dim Länge_Kurslinie As Double = FdW * MalFaktor '/z.B. 3,5 kn * 20 = 35 Px
    8. Dim KdW As Integer = Me.TB_KdW.Text '/Gradzahl des eigenen Kurses
    9. If FdW < 0 Or FdW > 25 Then
    10. MsgBox("Die Angaben erscheinen unrealistisch. Bitte ändern.", MsgBoxStyle.Information)
    11. TB_FdW.Focus()
    12. TB_FdW.SelectAll()
    13. Else
    14. '/Mitte meiner PictureBox wird als Drehachse definiert
    15. X.TranslateTransform(125, 125)
    16. '/Erzeuge ein Fadenkreuz
    17. X.DrawLine(Stift_X, 0, -125, 0, 125)
    18. X.DrawLine(Stift_X, -125, 0, 125, 0)
    19. Dim DiaHalbe As Double = DiamaterCenter / 2
    20. '/Setze einen roten Punkt in die Fadenkreuzmitte
    21. X.FillEllipse(Pinsel_X, 0 - CInt(DiaHalbe), 0 - CInt(DiaHalbe), CInt(DiamaterCenter), CInt(DiamaterCenter))
    22. '/x1_Kdw und y1_Kdw = Koordinaten Startpunkt Linie KdW
    23. '/x2_Kdw und y2_Kdw = Koordinaten Endpunkt Linie KdW
    24. Dim x1_KdW As Double
    25. Dim y1_KdW As Double
    26. Dim x2_KdW As Double
    27. Dim y2_KdW As Double
    28. x1_KdW = 0
    29. y1_KdW = 0
    30. x2_KdW = x1_KdW - Cos(KdW) * Länge_Kurslinie
    31. y2_KdW = y1_KdW - Sin(KdW) * Länge_Kurslinie
    32. '// Zeichne Kurslinie
    33. X.RotateTransform(KdW)
    34. 'X.DrawLine(Stift_FdW, 0, -CInt(Länge_Kurslinie), 0, 0)
    35. X.DrawLine(Stift_FdW, CInt(x1_KdW), CInt(y1_KdW), CInt(x2_KdW), CInt(y2_KdW))
    36. Me.TB_StromRichtung.Focus()
    37. End If
    Viele Grüße
    Stefan

    sailor4rent.de

    Giftzwockel schrieb:

    VB.NET-Quellcode

    1. X.RotateTransform(KdW)
    mit sowas wirste nicht glücklich.
    Das Verstellen des gesamten Bezugssystems bewirkt, dass Kein Punkt mehr da ist, wo man ihn eiglich erwartet.
    Normale Menschen können keine Berechnungen mehr anstellen auf Basis von sonem verdrehten System.

    Bleib lieber "ehrlich", und rechne aus, von wo nach wo du eine Linie zeichnen willst, und dann ist deine Frage nach dem Endpunkt auch augenblicklich gegenstandslos, denn du hast sie ja selbst da hingezeichnet.

    Übrigens kannst du dabei durchaus Matrix-Operationen anwenden, aber wende sie nicht auf das Bezugssystem an, sondern wende sie auf die Punkte an, zwischen denen du deine Linien ziehst.
    Für Matrix-Operationen nutze die System.Drawing.Drawing2D.Matrix-Klasse, die kann dir ein Point-Array transformieren.

    Giftzwockel schrieb:

    VB.NET-Quellcode

    1. Dim KdW As Integer = Me.TB_KdW.Text '/Gradzahl des eigenen Kurses
    1. Das heißt nicht "Gradzahl" sondern Winkel (oder sagst Du meine Zentimeterzahl ist 183 und meine Kilogrammzahl ist 82?).
    2. Gib Deinem Programm Option Strict On, damit Du vorgewarnt bist, wenn da mal einer statt "45" Rouladen mit Klößen eingibt.
    3. Konvertiere den String der Text ordentlich in einen Winkel im Bogenmaß (@Artentus:):

    VB.NET-Quellcode

    1. Dim Winkel As Double
    2. If Not Double.TryParse(TextBox1.Text, Winkel) Then
    3. MessageBox.Show("Rouladen sind alle")
    4. Return
    5. End If
    6. Winkel *= Math.PI / 180
    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!
    Hallo noch mal,

    es liegt wohl an meinen fehlenden mathemathischen Kenntnissen, aber ich komme trotz eurer Hilfe momentan nicht weiter.
    Natürlich habe ich erst mal Option Srict on festgelegt und dann meine Fehler koorigiert.

    Danach bin ich die Sache noch mal neu angegangen und habe einen relativ schlanken Code gebastelt.

    VB.NET-Quellcode

    1. Dim X As Graphics = PB1.CreateGraphics 'Legt fest, dass in PB1 "gemalt wird"
    2. Dim Länge_Kurslinie As Double = CDbl(TB_FdW.Text) * ZeichenFaktor 'Bestimmt Länge der Kurslinie
    3. Dim KdW As Double = CDbl(Me.TB_KdW.Text) 'Übernimmt Wert (Winkel) für den MgK
    4. '/Mitte meiner PictureBox wird als Drehachse definiert
    5. X.TranslateTransform(125, 125)
    6. 'Definition und Berechnung der neuen Koordinaten
    7. Dim x1_KdW As Double = 0
    8. Dim y1_KdW As Double = 0
    9. Dim x2_KdW As Double = x1_KdW - Cos(KdW) * Länge_Kurslinie / 180 * PI * 100
    10. Dim y2_KdW As Double = y1_KdW - Sin(KdW) * Länge_Kurslinie / 180 * PI * 100
    11. '/Kontrollausgabe
    12. Me.Label2.Text = Länge_Kurslinie & " Pixel Kurslinie"
    13. Me.Label3.Text = KdW & " ° MgK"
    14. Me.Label4.Text = CInt(x2_KdW) & " Pixel"
    15. Me.Label5.Text = CInt(y2_KdW) & " Pixel"
    16. 'Zeichnen
    17. X.DrawLine(Stift_FdW, CInt(x1_KdW), CInt(y1_KdW), CInt(x2_KdW), CInt(y2_KdW))


    Was ich dabei als Ergebnis erhalte ist zwar eine Linie, die im Zentrum meines Koordinatensystems beginnt, aber alles andere stimmt nicht.
    Wenn ich einen Winkel von 90° eingabe muss ja meine Linie lediglich andere Koordinaten für x2_KdW und y2_KdW bekommen wobei y2_KdW ein Wert von 125 sein muss weil sonst keine 90° Drehung erfolgt.
    Die Länge meiner Linie darf sich nicht in Abhängigkeit des Winkels ändern, den diese Linie entspricht dem Vektor Geschwindigkeit.
    Aktuell habe ich immer eine Linie in korrekter Länge aber im falschen Winkel (ca. 60° weniger als angegeben) :cursing: .
    Ich bin mir sicher, dass eure Lösung stimmt, sehe ich den Wald vor lauter Bäumen nicht mehr??
    Viele Grüße
    Stefan

    sailor4rent.de
    hast du post#6 iwie übersehen?

    Auf einem verdrehten Bezugssystem können nur noch Ausserirdische geometrisch korrekte Berechnungen anstellen (naja, Gauss und Euler hättens vlt. noch drauf gehabt, und ein paar Inder springen glaub noch rum, denen ichs auch zutrauen täte).

    Transformiere deine Punkte, aber nicht das Bezugssystem.

    Giftzwockel schrieb:

    VB.NET-Quellcode

    1. Dim x2_KdW As Double = x1_KdW - Cos(KdW) * Länge_Kurslinie / 180 * PI * 100
    2. Dim y2_KdW As Double = y1_KdW - Sin(KdW) * Länge_Kurslinie / 180 * PI * 100
    Was macht denn der Faktor 100 am Ende beider Zeilen :?:
    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:

    Giftzwockel schrieb:

    VB.NET-Quellcode

    1. Dim x2_KdW As Double = x1_KdW - Cos(KdW) * Länge_Kurslinie / 180 * PI * 100
    2. Dim y2_KdW As Double = y1_KdW - Sin(KdW) * Länge_Kurslinie / 180 * PI * 100
    Was macht denn der Faktor 100 am Ende beider Zeilen :?:
    Die 100 ist ein Faktor zum skalieren. Ohne diesen bekomme ich eine Minilinie.
    Viele Grüße
    Stefan

    sailor4rent.de

    Giftzwockel schrieb:

    ist ein Faktor zum skalieren
    Das ist allerdings nicht korrekt.
    Meinst Du eventuell dies (Klammern um den gesamten Ausdruck):

    VB.NET-Quellcode

    1. Dim x2_KdW As Double = (x1_KdW - Cos(KdW) * Länge_Kurslinie / 180 * PI) * 100
    2. Dim y2_KdW As Double = (y1_KdW - Sin(KdW) * Länge_Kurslinie / 180 * PI) * 100
    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!
    Habe mir den Thread nicht durchgelesen - aber was soll "/ 180 * PI" bewirken? Sieht für mich aus als würdest du versuchen zwischen Bogenmaß und Gradmaß umzurechnen. Wenn das der Fall ist, dann passiert das an der falschen Stelle und würde auch erklären, warum du eine "MiniLinie" als Ergebnis zu sehen bekommst. So müsste es richtig sein:

    VB.NET-Quellcode

    1. winkelBogenmaß = KdW / 180 * PI 'Wenn KdW im Gradmaß angegeben ist - also z.B. 45°
    2. Dim x2_KdW As Double = x1_KdW - Cos(winkelBogenmaß) * Länge_Kurslinie
    3. Dim y2_KdW As Double = y1_KdW - Sin(winkelBogenmaß) * Länge_Kurslinie

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

    @FreakJNS: Völlig korrekt, das ist mir glatt entfallen.
    @Giftzwockel: Ich präzisiere meinen letzten Post:
    Meinst Du vielleicht dies (andere Klammersetzung):

    VB.NET-Quellcode

    1. Dim x2_KdW As Double = (x1_KdW - Cos(KdW * Länge_Kurslinie / 180 * PI)) * 100
    2. Dim y2_KdW As Double = (y1_KdW - Sin(KdW * Länge_Kurslinie / 180 * PI)) * 100
    Teste sdas ganze mit Winkeln, die Du auf einem Blatt Papier hinmalen kannst: 30°, 45°, 60°, 90°.
    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
    Wenn ich das richtig verstanden habe, hatte er den Faktor (100) nur eingeführt um die MiniLinie zu vergrößern. Die Linienlänge ist aber gegeben und wurde im fehlerhaften Code wegen falscher Klammersetzung um "/180*PI" verkürzt (=> also ca. 60 mal kürzer als Länge_Kurslinie angibt). Weiterhin war der Winkel total falsch, weil er im Gradmaß übergeben wurde, sin/cos aber Bogenmaß benötigen. Da ging also wirklich alles schief^^

    (glaube deshalb, dass deine vorgeschlagene Klammersetzung merkwürdig erscheinen sollte, schließlich würde sich der berechnete Punkt so vom Ursprung entfernen. Gewollt war glaubich nur, dass der neue Punkt eine vorgegebene Entfernung und Winkel zum Ursprungspunkt hat)

    Außerdem hat sich bei dir glaubich noch ein Fehler eingeschlichen: Jetzt ziehst du die Länge der Linie (das ist doch Länge_Kurslinie??) mit in die Winkelberechnung xDD

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

    FreakJNS schrieb:

    Außerdem hat sich bei dir glaubich noch ein Fehler eingeschlichen
    Ja, sieht so aus. Danke.
    Ich habe das so verstanden, dass der Faktor 100 die gesamte Darstellung skaliert, und dann müsste es so aussehen. 3. Versuch:
    @Giftzwockel: Ich präzisiere meinen letzten Post zum 2. Mal:

    VB.NET-Quellcode

    1. Dim x2_KdW As Double = (x1_KdW - Cos(KdW / 180 * PI) * Länge_Kurslinie) * 100
    2. Dim y2_KdW As Double = (y1_KdW - Sin(KdW / 180 * PI) * Länge_Kurslinie) * 100
    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!

    FreakJNS schrieb:

    @RodFromGermany
    Wenn ich das richtig verstanden habe, hatte er den Faktor (100) nur eingeführt um die MiniLinie zu vergrößern. Die Linienlänge ist aber gegeben und wurde im fehlerhaften Code wegen falscher Klammersetzung um "/180*PI" verkürzt (=> also ca. 60 mal kürzer als Länge_Kurslinie angibt). Weiterhin war der Winkel total falsch, weil er im Gradmaß übergeben wurde, sin/cos aber Bogenmaß benötigen. Da ging also wirklich alles schief^^

    (glaube deshalb, dass deine vorgeschlagene Klammersetzung merkwürdig erscheinen sollte, schließlich würde sich der berechnete Punkt so vom Ursprung entfernen. Gewollt war glaubich nur, dass der neue Punkt eine vorgegebene Entfernung und Winkel zum Ursprungspunkt hat)

    Außerdem hat sich bei dir glaubich noch ein Fehler eingeschlichen: Jetzt ziehst du die Länge der Linie (das ist doch Länge_Kurslinie??) mit in die Winkelberechnung xDD
    Da war wirklich vieles falsch.
    Das mit der falschen Klammersetzung ist mir bis jetzt nicht aufgefallen, hätte mich aber stutzig mache sollen, denn die Werte sind ja - wie du feststellst - vorgegeben.
    Inzwischen habe ich das mit falscher Klammer :D so bereinigt, dass mein Programm funktioniert.
    Ich werde aber mal gaaaaanz vorsichtig an der falschen Klammer arbeiten.
    Danke euch allen.
    Viele Grüße
    Stefan

    sailor4rent.de

    Giftzwockel schrieb:

    Ich werde aber mal gaaaaanz vorsichtig an der falschen Klammer arbeiten.
    Bei solch "elementaren" geometrischen Aufgaben empfiehlt es sich, ein paar Tests auf Millimeterpapier zu malen und dann die gemalten und die gerechneten Ergebnisse zu vergleichen.
    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!