2D Vektor verlängern

  • Allgemein

Es gibt 23 Antworten in diesem Thema. Der letzte Beitrag () ist von Artentus.

    2D Vektor verlängern

    Hallo,

    ich stehe vor folgendem Problem:
    eine Halbgerade [AB[ ist definiert durch A(XA|YA) und B(XB|YB).
    Sie läuft also von A aus durch B.
    Nun möchte ich die Lage von einem weiterem Punkt C berechnen, welcher auf [AB[ liegt und zwar "hinter" B, sodass [AB] < [AC].
    Leider habe ich zusätzlich nur die Länge der Stecke [BC] gegeben, nennen wir sie n.
    Zur besseren Vorstellung hier eine Grafik:

    Ich dachte mir dass sich dieses Problem bestimmt mit Vektorrechnung lösen lässt, leider scheitere ich dabei.
    Wie berechne ich also C aus den oben gegebenen Prämissen?

    //Edit: Die trigonometrische Lösung

    VB.NET-Quellcode

    1. Private Function projectPoint(A As Point, B As Point, n As Single) As Point
    2. Dim at As Single = Math.Atan2(B.Y - A.Y, B.X - A.X)
    3. Return New Point(B.X + Math.Cos(at) * n, B.Y + Math.Sin(at) * n)
    4. End Function


    Vielen Dank,
    SᴛᴀʀGᴀᴛᴇ01

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

    Schau dir mal an, wie ich es in meiner MathUtils-Lib (OpenSource, du kannst dir also den entsprechenden Quelltext ansehen) gemacht habe. Besonderes Augenmerk solltest du dabei auf die Funktion MathHelper.GetPointOnCircle legen. in Kombination mit MathHelper.GetAngle solltest du genau das Ergebnis erzielen können, das du haben willst.
    AB normalisieren also Einheitsvektorbilden:
    AB / |AB|

    das multiplizierst mit |BC| und schon hast den richtungsvektor BC.
    Für den Punkt C addierst dann nur noch den Ortsvektor B und den Richtungsvektor BC
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Danke euch beiden!
    @Artentus
    Exzellente Bibliothek, ich war mal so frei und hab mir meine eigene Funktion mit Deinem Code gebastelt:

    VB.NET-Quellcode

    1. Public Function ProjectPoint(ByVal A As PointF, ByVal B As PointF, ByVal n As Single) As PointF
    2. Dim grad As Single = (A.Y - B.Y) / (A.X - B.X)
    3. Dim at As Single = Math.Atan(grad)
    4. If grad < 0 Then at = Math.PI + at
    5. If (A.Y > B.Y) OrElse (A.Y = B.Y AndAlso A.X > B.X) Then at += Math.PI
    6. Return New PointF(B.X + Math.Cos(at) * n, B.X + Math.Sin(at) * n)
    7. End Function

    Wäre das okay für Dich wenn ich die Funktion so unabhängig von deiner Bibliothek nutze?

    @jvbsl
    Danke für Deine Lösung, allerdings weiß ich in Trigonometrie noch deutlich besser Bescheid als in Vektorenrechnung (*räusper* Schüler *räusper*), deshalb werde ich wohl Artentus Lösung nehmen. Ich will nur keinen Krams anfangen, den ich nicht verstehe, sondern den Krams von Anfang an mal lernen.
    SᴛᴀʀGᴀᴛᴇ01
    Dim grad As Single = (A.Y - B.Y) / (A.X - B.X)
    Dim at As Single = Math.Atan(grad)

    uaaah

    Math.Atan2 wäre da wohl die bessere Lösung ;)
    Wenns schon über Geometrie sein muss^^
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    @StarGate01: Über welche mathematischen Grundlagen verfügst Du denn?
    Hier steckt alles drin, was Du brauchst:

    Quellcode

    1. y = a + b * x
    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
    Die generische Geradengleichung... aber was damit tun? ?(

    Übrigens hat der Code oben von mir einen Fehler, so spuckt er bei z.B. ((5|5),(10|5),2) (12|10) statt den erwarteten (12|5) aus.
    Also: Zurück auf Los, ich bin für alles offen, auch Vektoren (ich versuch sie zu verstehen).

    //EDIT
    Ich hab den Fehler gefunden:

    VB.NET-Quellcode

    1. Return New PointF(B.X + Math.Cos(at) * n, B.X + Math.Sin(at) * n)
    2. wird zu
    3. Return New PointF(B.X + Math.Cos(at) * n, B.Y + Math.Sin(at) * n)


    @Artentus
    Keine Ahnung ob der Fehler bei deiner Bibliothek auch so existiert, ich gehe zwar nicht davon aus, aber nachschauen kostet nichts :)
    SᴛᴀʀGᴀᴛᴇ01

    StarGate01 schrieb:

    VB.NET-Quellcode

    1. Dim grad As Single = (A.Y - B.Y) / (A.X - B.X)
    Ich halte es für fahrlässig, einen Winkel im Bogenmaß mit einer Variable namens "grad" zu bezeichnen. :S
    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!
    @Artentus
    @RodFromGermany
    @jvbsl

    Nur dank eurer Hilfe konnte ich diese 2D Schattensimulation erstellen:
    dl.dropboxusercontent.com/u/41406531/dynshad2d.html
    Ihr benötigt einen aktuellen und schnellen Browser
    Bewegt die Maus mal zwischen den Polygonen rum :)
    Interessanterweise läuft es im IE10 an flüssigsten (lol)

    Aber was eigentlich viel wichtiger ist: Wieder was gelernt.
    SᴛᴀʀGᴀᴛᴇ01
    if ((A.Y > B.Y) || (A.Y == B.Y && A.X > B.X)) { at += Math.PI; }

    atan2 hätte das für dich übernommen. Außerdem wenn A.X == B.X dann dividierst du bereits durch 0. Eine Prüfung zuvor wäre angebracht, bzw. direkt atan2 zu verwenden
    Math.atan2(A.Y - B.Y,A.X - B.X)
    sollte einwandfrei funktionieren...

    Edit:btw. mit Vektorrechnung könnte es schneller gehen ;)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    @jvbsl
    Ich hab das gerade mal ausprobiert und ich glaube ich mach irgendwas falsch.
    Das ist der alte Code:

    VB.NET-Quellcode

    1. Dim p1 = New Point2D(300, 300)
    2. Dim p2 = New Point2D(PointToClient(Cursor.Position))
    3. Dim p3 = MathHelper.GetPointOnCircle(p1, MathHelper.GetAngle(p1, p2), 200)
    4. e.Graphics.DrawLine(Pens.Red, New PointF(CSng(p1.X), CSng(p1.Y)), New PointF(CSng(p3.X), CSng(p3.Y)))

    Die Linie hängt hier immer schön am Mauszeiger.

    Wenn ich das jetzt durch das ersetze

    VB.NET-Quellcode

    1. Dim p1 = New Point2D(300, 300)
    2. Dim p2 = New Point2D(PointToClient(Cursor.Position))
    3. Dim p3 = MathHelper.GetPointOnCircle(p1, Math.Atan2(p2.X - p1.X, p2.Y - p1.Y), 200)
    4. e.Graphics.DrawLine(Pens.Red, New PointF(CSng(p1.X), CSng(p1.Y)), New PointF(CSng(p3.X), CSng(p3.Y)))

    Dann scheint es so, als ob sich die Linie in die entgegengesetzte Richtung zur Maus verschieben würde.

    Kannst du dir das erklären?
    Verstehe ich das richtig?

    Bei der Vektoren-Lösung des Problems müsste man doch einen Punkt als Ortverktor bzw. Stützvektor verwenden. Nun berechnet man mithilfe des zweiten Punktes den Richtungsvektor.

    Punkt A(1,1) PunktB(3,4)
    g:x = OA + r * AB
    OA = (1,1)
    AB = (2,3)

    => g:x = (1,1) + r * (2,3)
    (Ich weiß das man Vektoren nomalerweise untereinander schreibt ;) )

    8-) faxe1008 8-)