Kollision von Geraden

  • GM 7

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Kollision von Geraden

    Ich habe mal wieder ein Problem. Im prinziep weiß ich wie ich es Bewerkstelligen soll, aber im Detail scheiterts dann doch.

    Also, ich habe zwei Geraden, geben an Punkten. Also "gerade1 start(x,y)", "gerade1 ende(x,y)", "gerade2 start(x,y)", "gerade2 ende(x,y)".

    Nun will ich checken, ob es da eine Kollision gibt. Ich weiß, das ist nur gleichstellen der funktionen. Nur dann doch nicht so einfach in GML.



    Ich hoffe die frage ist klar. Doch ich komme einfach nich in den Gang.

    In Hoffnung auf gute Ideen
    SDX

    (ja, boxxar: Stoff 7. klasse ^^)
  • Tut mir leid, dass das nichts zum Thema beiträgt (denn ich bin unheimlich schlecht in Mathe), aber:

    Es sind Strecken, keine Geraden. Eine Gerade hat keinen Anfang und kein Ende und dann wäre es so gut wie immer true, außer die Funktionen sind bis auf den Y-Achsenabschnitt identisch (Natürlich nur aus mathematischer Sicht, zeichnerisch lassen sich perfekt parallele Geraden nicht bewerkstelligen)
  • Dennoch kann er den Schnittpunkt mittels Gleichsetzung der beiden ermitteln und dann schauen, ob der Schnittpunkt auf der Strecke liegt (er hat ja 2 Punkte und kann da ein Rechteck drum ziehen und schauen obs da drin ist)

    Das ganze läuft in etwa so ab:

    Gerade f: P1(10, 23) P2(138, 57)
    Gerade g: P1(60, 54) P2(5, 0)

    Zuerst die Funktionsgleichungen ermitteln.

    Steigung:
    m(f) = Delta Y / Delta X = (y1-y2) / (x1-x2) = (-34) / (-128) = 0,266

    Y-Achsenabschnitt:
    y = mx + n | -mx
    n = y - mx | einsetzen
    n = 23 - 0,266*10 = 23 - 2,66 = 21,34

    Funktionsgleichung:
    f(x) = 0,266x + 21,34

    g(x) = 0,982x - 4,91

    Gleichsetzen:

    f(x) = g(x)
    0,266x + 21,34 = 0,982x - 4,91 | -0,266x; +4,91
    26,25 = 0,716x | : 0,716
    x = 36,66

    x in g

    g(36,66) = y = 0,982*36,66 - 4,91 = 31,09

    S(36,66, 31,09)

    Dann noch schauen, ob der wert innerhalb des von den 2 Punkten gebildeten rechteckes ist.

    if(x(s)<max(x1,x2) && x(s)>min(x1,x2) && y(s)<max(y1,y2) && y(s)>min(y1,y2))
    {
    return true;
    }


    So, ich hoffe ich hab keinen Stuss erzählt, aber ich denke so geht es... du musst die Rechenschritte vllt nur etwas zusammenfassen.

    EDIT: Da ich grad massiv Langeweile hatte, hab ich die Formeln mal zusammengefasst (alles eingesetzt) und auf x und y Werte reduziert...
    Kann sein, dass man das kürzen könnte, aber nachdem ich das zusammengebastelt hab, hatte ich dazu keine Lust mehr.
    Nicht erschrecken, sieht schlimmer aus als es ist, sind wirklich nur x und y Werte *g*

    Quellcode

    1. x(s) = ((y1(f)-((y1(f)-y2(f))/(x1(f)-x2(f)))*x1(f))-(y1(g)-((y1(g)-y2(g))/(x1(g)-x2(g)))*x1(g)))/((y1(g)-y2(g))/(x1(g)-x2(g))-(y1(f)-y2(f))/(x1(f)-x2(f)))
    2. y(s) = ((y1(f)-y2(f))/(x1(f)-x2(f)))*(((y1(f)-((y1(f)-y2(f))/(x1(f)-x2(f)))*x1(f))-(y1(g)-((y1(g)-y2(g))/(x1(g)-x2(g)))*x1(g)))/((y1(g)-y2(g))/(x1(g)-x2(g))-(y1(f)-y2(f))/(x1(f)-x2(f)))) + (y1(f)-((y1(f)-y2(f))/(x1(f)-x2(f)))*x1(f))


    Wie ich doch Schlangencode liebe... sowohl mein Mathelehrer als auch mein EDV Lehrer würden mich wohl köpfen *g*
    So far, Schattenphoenix~
    _____________________________________________________________________________
    "Who needs a stairway to heaven...
    If there is an elevator to hell... ?
    "
    - Vergessen
    "Auch ein perfektes Chaos ist etwas vollkommenes."
    - Jean Genet

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von Schattenphoenix ()

  • Die Idee von Schattenphoenix ist im Grunde richtig. Nur ist es problematisch eine Gerade als Funktion von x darzustellen. Denn damit lassen sich keine vertikalen Geraden, also x = c für eine Konstante c, darstellen. Auch bei Geraden, die fast vertikal sind, also einen sehr großen Anstieg haben, kann es zu Problemen wegen numerischer Instabilität kommen. Zur Darstellung von Geraden nutzt man deshalb lieber Vektoren. Genau genommen zwei: Einer gibt einen Punkt auf der Geraden an und der andere die Richtung.

    Die Endpunkte von der ersten Geraden nenne ich mal (x11,y11) und (x12,y12). Die von der Zweiten (x21,y21) und (x22,y22).

    GML-Quellcode

    1. a1x = x11;
    2. a1y = y11;
    3. v1x = x12-x11;
    4. v1y = y12-y11;
    5. a2x = x21;
    6. a2y = y21;
    7. v2x = x22-x21;
    8. v2y = y22-y21;

    sind dann die Vektoren, die die beiden Geraden beschreiben. Zur Berechnung des Schnittpunktes verwendet man das Gleichungssystem

    Quellcode

    1. a1x+r*v1x = a2x+s*v2x
    2. a1y+r*v1y = a2y+s*v2y

    in den Unbekannten r und s. Lösen lässt es sich z.B. durch Multiplizieren der ersten Zeile mit v2y und der zweiten Zeile mit v2x. Subtrahiert man anschließend eine Zeile von der anderen, fällt das s weg. Man erhält

    Quellcode

    1. a1x*v2y+r*v1x*v2y = a2x*v2y+s*v2x*v2y
    2. a1y*v2x+r*v1y*v2x = a2y*v2x+s*v2y*v2x

    und daraus

    Quellcode

    1. (a1x*v2y-a1y*v2x)+r*(v1x*v2y-v1y*v2x) = (a2x*v2y-a2y*v2x)

    also

    GML-Quellcode

    1. r = ((a2x-a1x)*v2y+(a1y-a2y)*v2x)/(v1x*v2y-v1y*v2x);

    Gleichermaßen lässt sich s bestimmen durch

    GML-Quellcode

    1. s = ((a2x-a1x)*v1y+(a1y-a2y)*v1x)/(v1x*v2y-v1y*v2x);

    Wie man an den Gleichungen erkennt, kann nur für v1x*v2y-v1y*v2x != 0 ein Schnittpunkt existieren, ansonsten sind die Geraden parallel. Liegen nun r und s jeweils zwischen 0 und 1, dann liegt der Schnittpunkt der Geraden sogar auf den Strecken, also schneiden sich die Strecken nur dann. Mit

    GML-Quellcode

    1. xs = a1x+r*v1x;
    2. ys = a1y+r*v1y;

    hat man dann den Schnittpunkt berechnet.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Bl@ckSp@rk ()

  • Vielen dank soweit.
    Ich habe es so aufgenommen wie du es beschreiben hast.
    Es funktioniert auch so weit, nur irgendwie wird nur der anfang/ende der einen gerade in die berechnungen eingenommen. Ich habe es jetzt so weit:
    Wäre nett wenn du dir das noch mal angucken könntest (seint beim r zu scheitern)

    GML-Quellcode

    1. var x11,y11,x12,y12,x21,y21,x22,y22,a1x,a1y,v1x,v1y,a2x,a2y,v2x,v2y,r;
    2. x11=argument0;
    3. y11=argument1;
    4. x12=argument2;
    5. y12=argument3;
    6. x21=argument4;
    7. y21=argument5;
    8. x22=argument6;
    9. y22=argument7;
    10. a1x = x11;
    11. a1y = y11;
    12. v1x = x12-x11;
    13. v1y = y12-y11;
    14. a2x = x21;
    15. a2y = y21;
    16. v2x = x22-x21;
    17. v2y = y22-y21;
    18. if (v1x*v2y-v1y*v2x)!=0 {
    19. r = ((a2x-a1x)*v2y+(a1y-a2y)*v2x)/(v1x*v2y-v1y*v2x)
    20. return (r>=0 && r<=1)
    21. }
    22. return 0
    Alles anzeigen


    Also, die länge von Gerade #2 (ich wette du wirst dir jetzt die Haare ausreißen wenn ich so mit den Begriffen durch ein ander komme ;) ) wird nicht mit eingerechnet

    MfG SDX
  • Ja, das ist richtig. Hatte das vor ein paar Minuten auch bemerkt, als ich meinen Beitrag nochmal durchgelesen habe (war doch etwas müde gestern). Da warst du einen Tick zu früh und konntest meinen Edit nicht lesen. Habe oben noch was hinzugefügt. Du musst nämlich auch noch s bestimmen und prüfen ob s zwischen 0 und 1 liegt.

    Wahrscheinlich kannst du auch noch ein bissl Performance rausholen indem du die ganzen Zuweisungen über der if-Abfrage verkürzt. Hatte das in meinem Beitrag nur so beschrieben, damit es leicht nachzuvollziehen ist.