Wie kann ich überprüfen, ob sich zwei Segmente schneiden?

90

Wie kann ich überprüfen, ob sich 2 Segmente schneiden?

Ich habe folgende Daten:

Segment1 [ {x1,y1}, {x2,y2} ]
Segment2 [ {x1,y1}, {x2,y2} ] 

Ich muss einen kleinen Algorithmus in Python schreiben, um festzustellen, ob sich die beiden Linien schneiden.


Alt-Text

aneuryzm
quelle

Antworten:

62

Die Gleichung einer Linie lautet:

f(x) = A*x + b = y

Für ein Segment ist es genau das gleiche, außer dass x in einem Intervall I enthalten ist.

Wenn Sie zwei Segmente haben, definieren Sie diese wie folgt:

Segment1 = {(X1, Y1), (X2, Y2)}
Segment2 = {(X3, Y3), (X4, Y4)}

Die Abcisse Xa des potentiellen Schnittpunkts (Xa, Ya) muss in beiden Intervallen I1 und I2 enthalten sein, die wie folgt definiert sind:

I1 = [min(X1,X2), max(X1,X2)]
I2 = [min(X3,X4), max(X3,X4)]

Und wir könnten sagen, dass Xa enthalten ist in:

Ia = [max( min(X1,X2), min(X3,X4) ),
      min( max(X1,X2), max(X3,X4) )]

Nun müssen wir überprüfen, ob dieses Intervall Ia existiert:

if (max(X1,X2) < min(X3,X4)):
    return False  # There is no mutual abcisses

Wir haben also eine zweizeilige Formel und ein gegenseitiges Intervall. Ihre Zeilenformeln sind:

f1(x) = A1*x + b1 = y
f2(x) = A2*x + b2 = y

Da wir zwei Punkte pro Segment erhalten haben, können wir A1, A2, b1 und b2 bestimmen:

A1 = (Y1-Y2)/(X1-X2)  # Pay attention to not dividing by zero
A2 = (Y3-Y4)/(X3-X4)  # Pay attention to not dividing by zero
b1 = Y1-A1*X1 = Y2-A1*X2
b2 = Y3-A2*X3 = Y4-A2*X4

Wenn die Segmente parallel sind, ist A1 == A2:

if (A1 == A2):
    return False  # Parallel segments

Ein Punkt (Xa, Ya), der auf beiden Linien steht, muss beide Formeln f1 und f2 überprüfen:

Ya = A1 * Xa + b1
Ya = A2 * Xa + b2
A1 * Xa + b1 = A2 * Xa + b2
Xa = (b2 - b1) / (A1 - A2)   # Once again, pay attention to not dividing by zero

Als letztes müssen Sie überprüfen, ob Xa in Ia enthalten ist:

if ( (Xa < max( min(X1,X2), min(X3,X4) )) or
     (Xa > min( max(X1,X2), max(X3,X4) )) ):
    return False  # intersection is out of bound
else:
    return True

Darüber hinaus können Sie beim Start überprüfen, ob zwei der vier angegebenen Punkte nicht gleich sind, um all diese Tests zu vermeiden.

OMG_peanuts
quelle
1
Segmente, sie sind Segmente, sorry. Könnten Sie Ihre Antwort in bestimmten Segmenten aktualisieren?
aneuryzm
13
Das ist nicht so kompliziert, ich habe viele (unwesentliche?) Zwischenschritte zu einem Verständniszweck geschrieben. Die wichtigsten Punkte für Geräte sind: Überprüfen Sie das Vorhandensein eines gegenseitigen Intervalls, berechnen Sie A1, A2, b1, b2 und Xa und überprüfen Sie dann, ob Xa im gegenseitigen Intervall enthalten ist. Das ist alles :)
OMG_peanuts
2
A1 - A2 wird niemals Null sein, denn wenn (A1 == A2) in diesem Fall vor dieser Berechnung zurückgekehrt wäre.
Inkredibl
3
wenn A1 == A2 und b1 == b2, sind die Segmente übereinander und haben unendlich viele Schnittpunkte
lynxoid
5
Die Formel A1 * x + b1 = y behandelt keine vertikalen Linien, daher sollten vertikale Segmente mit dieser Methode separat behandelt werden.
Dmitri
77

User @ i_4_got verweist auf diese Seite mit einer sehr effizienten Lösung in Python. Ich reproduziere es hier der Einfachheit halber (da es mich glücklich gemacht hätte, es hier zu haben):

def ccw(A,B,C):
    return (C.y-A.y) * (B.x-A.x) > (B.y-A.y) * (C.x-A.x)

# Return true if line segments AB and CD intersect
def intersect(A,B,C,D):
    return ccw(A,C,D) != ccw(B,C,D) and ccw(A,B,C) != ccw(A,B,D)
Grumdrig
quelle
8
Sehr einfach und elegant, aber es geht nicht gut mit Kolinearität um und daher wird mehr Code für diesen Zweck benötigt.
Charles
7
Eine Lösung für Kollinearität finden Sie unter geeksforgeeks.org/check-if-two-given-line-segments-intersect
Zsolt Safrany,
Ich liebe diese Lösung. Sehr einfach und kurz! Ich habe ein wxPython-Programm erstellt, das eine Linie zeichnet und prüft, ob sie sich mit einer anderen Linie schneidet. Ich konnte es hier nicht platzieren, also ist es irgendwo unter diesem Kommentar.
user1766438
32

Sie müssen nicht genau berechnen, wo sich die Segmente schneiden, sondern nur verstehen, ob sie sich überhaupt schneiden. Dies vereinfacht die Lösung.

Die Idee ist, ein Segment als "Anker" zu behandeln und das zweite Segment in 2 Punkte zu trennen.
Jetzt müssen Sie die relative Position jedes Punkts zum "verankerten" Segment (OnLeft, OnRight oder Collinear) ermitteln.
Überprüfen Sie anschließend für beide Punkte, ob einer der Punkte OnLeft und der andere OnRight ist (oder schließen Sie die kollineare Position ein, wenn Sie auch falsche Schnittpunkte einbeziehen möchten ).

Sie müssen den Vorgang dann mit den Rollen Anker und getrennte Segmente wiederholen.

Ein Schnittpunkt liegt nur dann vor, wenn einer der Punkte OnLeft und der andere OnRight ist. Unter diesem Link finden Sie eine detailliertere Erklärung mit Beispielbildern für jeden möglichen Fall.

Das Implementieren einer solchen Methode ist viel einfacher als das tatsächliche Implementieren einer Methode, die den Schnittpunkt findet (angesichts der vielen Eckfälle, die Sie ebenfalls behandeln müssen).

Aktualisieren

Die folgenden Funktionen sollen die Idee veranschaulichen (Quelle: Computational Geometry in C ).
Anmerkung: In diesem Beispiel wird die Verwendung von Ganzzahlen angenommen. Wenn Sie stattdessen eine Gleitkommadarstellung verwenden (was die Sache offensichtlich komplizieren könnte), sollten Sie einen Epsilon-Wert bestimmen, um "Gleichheit" anzuzeigen (hauptsächlich für die IsCollinearAuswertung).

// points "a" and "b" forms the anchored segment.
// point "c" is the evaluated point
bool IsOnLeft(Point a, Point b, Point c)
{
     return Area2(a, b, c) > 0;
}

bool IsOnRight(Point a, Point b, Point c)
{
     return Area2(a, b, c) < 0;
}

bool IsCollinear(Point a, Point b, Point c)
{
     return Area2(a, b, c) == 0;
}

// calculates the triangle's size (formed by the "anchor" segment and additional point)
int Area2(Point a, Point b, Point c)
{
     return (b.X - a.X) * (c.Y - a.Y) -
            (c.X - a.X) * (b.Y - a.Y);
}

Wenn Sie diese Funktionen verwenden, müssen Sie natürlich daran denken, zu überprüfen, ob jedes Segment "zwischen" dem anderen Segment liegt (da es sich um endliche Segmente und nicht um unendliche Linien handelt).

Mit diesen Funktionen können Sie auch nachvollziehen, ob Sie eine richtige oder eine falsche Kreuzung haben.

  • Richtig : Es gibt keine kollinearen Punkte. Die Segmente kreuzen sich "von Seite zu Seite".
  • Unsachgemäß : Ein Segment "berührt" nur das andere (mindestens einer der Punkte ist kollinear zum verankerten Segment).
Liran
quelle
+1 So ziemlich auch meine Idee. Wenn Sie nur darüber nachdenken, wo die Punkte in Beziehung zueinander stehen, können Sie entscheiden, ob sich ihre Segmente schneiden müssen oder nicht, ohne etwas zu berechnen.
Jochen Ritzel
und @ THC4k Ähm, es ist eigentlich nicht klar. Überprüfen Sie beispielsweise das Bild, das ich der Frage hinzugefügt habe: Die beiden Punkte sind "OnLeft" und "OnRight", aber die beiden Segmente überschneiden sich nicht.
aneuryzm
@ Patrick, eigentlich nein. Je nachdem, welches der Segmente der "Anker" ist, sind in diesem Fall beide Punkte entweder OnLeft oder OnRight. (Siehe meine aktualisierte Antwort).
Liran
+1 Ich habe Dutzende von Antworten auf dieses Problem gesehen, aber dies ist bei weitem die klarste, einfachste und effizienteste, die ich je gesehen habe. :)
Miguel
16

Angenommen, die beiden Segmente haben die Endpunkte A, B und C, D. Die numerisch robuste Methode zur Bestimmung des Schnittpunkts besteht darin, das Vorzeichen der vier Determinanten zu überprüfen:

| Ax-Cx  Bx-Cx |    | Ax-Dx  Bx-Dx |
| Ay-Cy  By-Cy |    | Ay-Dy  By-Dy |

| Cx-Ax  Dx-Ax |    | Cx-Bx  Dx-Bx |
| Cy-Ay  Dy-Ay |    | Cy-By  Dy-By |

Für die Schnittmenge muss jede Determinante auf der linken Seite das entgegengesetzte Vorzeichen der auf der rechten Seite haben, es muss jedoch keine Beziehung zwischen den beiden Linien bestehen. Sie überprüfen im Grunde jeden Punkt eines Segments mit dem anderen Segment, um sicherzustellen, dass sie auf gegenüberliegenden Seiten der vom anderen Segment definierten Linie liegen.

Siehe hier: http://www.cs.cmu.edu/~quake/robust.html

Victor Liu
quelle
funktioniert es für falsche Schnittpunkte, dh wenn der Schnittpunkt auf einem Liniensegment liegt?
Sayam Qazi
@SayamQazi Es scheint, als würde die Kreuzung fehlschlagen, wenn Sie zumindest den Endpunkt eines Liniensegments passieren. Wenn Sie sich auf dem Segment befinden: Ich gehe davon aus, dass es sich um einen Vergleich zwischen 0 und 1 / -1 handelt, sodass kein Schnittpunkt erkannt wird.
Warty
1
Übrigens, um dies zu erklären: Jede Determinante berechnet das Kreuzprodukt der Vektorendpunkte zweier Liniensegmente. Oben links ist beispielsweise CA x CB gegenüber oben rechts DA x DB. Dies testet im Wesentlichen, auf welcher Seite sich ein Scheitelpunkt befindet (Uhrzeit). Ich versuche immer noch herauszufinden, wie es für Liniensegmente funktioniert, die sich nicht unendlich erstrecken.
Warty
7

Mit der Shapely- Bibliothek können Sie mithilfe der folgenden intersectsMethode sehr einfach überprüfen, ob sich Liniensegmente schneiden :

from shapely.geometry import LineString

line = LineString([(0, 0), (1, 1)])
other = LineString([(0, 1), (1, 0)])
print(line.intersects(other))
# True

Geben Sie hier die Bildbeschreibung ein

line = LineString([(0, 0), (1, 1)])
other = LineString([(0, 1), (1, 2)])
print(line.intersects(other))
# False

Geben Sie hier die Bildbeschreibung ein

Georgy
quelle
6

Basierend auf den hervorragenden Antworten von Liran und Grumdrig finden Sie hier einen vollständigen Python-Code, mit dem überprüft werden kann, ob sich geschlossene Segmente überschneiden. Funktioniert für kollineare Segmente, Segmente parallel zur Achse Y, entartete Segmente (der Teufel steckt im Detail). Nimmt ganzzahlige Koordinaten an. Gleitkommakoordinaten erfordern eine Änderung des Punktgleichheitstests.

def side(a,b,c):
    """ Returns a position of the point c relative to the line going through a and b
        Points a, b are expected to be different
    """
    d = (c[1]-a[1])*(b[0]-a[0]) - (b[1]-a[1])*(c[0]-a[0])
    return 1 if d > 0 else (-1 if d < 0 else 0)

def is_point_in_closed_segment(a, b, c):
    """ Returns True if c is inside closed segment, False otherwise.
        a, b, c are expected to be collinear
    """
    if a[0] < b[0]:
        return a[0] <= c[0] and c[0] <= b[0]
    if b[0] < a[0]:
        return b[0] <= c[0] and c[0] <= a[0]

    if a[1] < b[1]:
        return a[1] <= c[1] and c[1] <= b[1]
    if b[1] < a[1]:
        return b[1] <= c[1] and c[1] <= a[1]

    return a[0] == c[0] and a[1] == c[1]

#
def closed_segment_intersect(a,b,c,d):
    """ Verifies if closed segments a, b, c, d do intersect.
    """
    if a == b:
        return a == c or a == d
    if c == d:
        return c == a or c == b

    s1 = side(a,b,c)
    s2 = side(a,b,d)

    # All points are collinear
    if s1 == 0 and s2 == 0:
        return \
            is_point_in_closed_segment(a, b, c) or is_point_in_closed_segment(a, b, d) or \
            is_point_in_closed_segment(c, d, a) or is_point_in_closed_segment(c, d, b)

    # No touching and on the same side
    if s1 and s1 == s2:
        return False

    s1 = side(c,d,a)
    s2 = side(c,d,b)

    # No touching and on the same side
    if s1 and s1 == s2:
        return False

    return True
dmitri
quelle
Was genau bedeutet "geschlossene Segmente"?
Sam
Das geschlossene @ Sam-Segment enthält seine Endpunkte. ZB wäre ein geschlossenes Punktsegment von R [0, 1] (0 <= x <= 1) im Gegensatz zu sagen] 0, 1] (0 <x <= 1)
dmitri
5

Hier ist eine Lösung mit Punktprodukten:

# assumes line segments are stored in the format [(x0,y0),(x1,y1)]
def intersects(s0,s1):
    dx0 = s0[1][0]-s0[0][0]
    dx1 = s1[1][0]-s1[0][0]
    dy0 = s0[1][1]-s0[0][1]
    dy1 = s1[1][1]-s1[0][1]
    p0 = dy1*(s1[1][0]-s0[0][0]) - dx1*(s1[1][1]-s0[0][1])
    p1 = dy1*(s1[1][0]-s0[1][0]) - dx1*(s1[1][1]-s0[1][1])
    p2 = dy0*(s0[1][0]-s1[0][0]) - dx0*(s0[1][1]-s1[0][1])
    p3 = dy0*(s0[1][0]-s1[1][0]) - dx0*(s0[1][1]-s1[1][1])
    return (p0*p1<=0) & (p2*p3<=0)

Hier ist eine Visualisierung in Desmos: Liniensegmentschnitt

BenMan95
quelle
Das ist großartig und ich habe Desmos vergessen - es ist perfekt für dieses Problem! Vielen Dank!
ponadto
Ich liebe deine Lösung, aber es scheint, als würde sie fehlschlagen, wenn die beiden Liniensegmente in einer Linie liegen
H. Pope
Sehr schön. Wenn Sie dies in eine andere Sprache portieren, stellen Sie sicher, dass float oder int64 verwendet wird, da int32 bei Zahlen unter 1280 x 720 ziemlich schnell überläuft
dieser andere Typ
4

Sie haben zwei Liniensegmente. Definieren Sie ein Segment anhand der Endpunkte A und B und das zweite Segment anhand der Endpunkte C und D. Es gibt einen guten Trick, um zu zeigen, dass sie sich innerhalb der Grenzen der Segmente schneiden müssen. (Beachten Sie, dass sich die Linien selbst möglicherweise über die Grenzen der Segmente hinaus schneiden. Sie müssen also vorsichtig sein. Guter Code sucht auch nach parallelen Linien.)

Der Trick besteht darin, zu testen, dass die Punkte A und B auf gegenüberliegenden Seiten der Linie CD liegen müssen und dass die Punkte C und D auf gegenüberliegenden Seiten der Linie AB liegen müssen.

Da dies Hausaufgaben sind, werde ich Ihnen keine explizite Lösung geben. Ein einfacher Test, um festzustellen, auf welche Seite einer Linie ein Punkt fällt, ist die Verwendung eines Punktprodukts. Berechnen Sie für eine bestimmte Zeilen-CD den Normalenvektor für diese Zeile (ich nenne sie N_C). Testen Sie nun einfach die Vorzeichen dieser beiden Ergebnisse:

dot(A-C,N_C)

und

dot(B-C,N_C)

Wenn diese Ergebnisse entgegengesetzte Vorzeichen haben, sind A und B gegenüberliegende Seiten der Linie CD. Führen Sie nun den gleichen Test für die andere Leitung AB durch. Es hat den normalen Vektor N_A. Vergleichen Sie die Zeichen von

dot(C-A,N_A)

und

dot(D-A,N_A)

Ich überlasse es Ihnen, herauszufinden, wie man einen normalen Vektor berechnet. (In 2D ist das trivial, aber macht sich Ihr Code Sorgen darüber, ob A und B unterschiedliche Punkte sind? Sind auch C und D unterschiedliche Punkte?)

Sie müssen sich immer noch Gedanken über Liniensegmente machen, die entlang derselben unendlichen Linie liegen oder wenn ein Punkt tatsächlich auf das andere Liniensegment selbst fällt. Guter Code wird jedem möglichen Problem gerecht.


quelle
3

Hier ist C-Code, um zu überprüfen, ob sich zwei Punkte auf den gegenüberliegenden Seiten des Liniensegments befinden. Mit diesem Code können Sie überprüfen, ob sich auch zwei Segmente schneiden.

// true if points p1, p2 lie on the opposite sides of segment s1--s2
bool oppositeSide (Point2f s1, Point2f s2, Point2f p1, Point2f p2) {

//calculate normal to the segment
Point2f vec = s1-s2;
Point2f normal(vec.y, -vec.x); // no need to normalize

// vectors to the points
Point2f v1 = p1-s1;
Point2f v2 = p2-s1;

// compare signs of the projections of v1, v2 onto the normal
float proj1 = v1.dot(normal);
float proj2 = v2.dot(normal);
if (proj1==0 || proj2==0)
        cout<<"collinear points"<<endl;

return(SIGN(proj1) != SIGN(proj2));

}}

Vlad
quelle
3

Hier ist ein weiterer Python-Code, mit dem überprüft werden kann, ob sich geschlossene Segmente schneiden. Es ist die umgeschriebene Version des C ++ - Codes in http://www.cdn.geeksforgeeks.org/check-if-two-given-line-segments-intersect/ . Diese Implementierung deckt alle Sonderfälle ab (z. B. alle Punkte kolinear).

def on_segment(p, q, r):
    '''Given three colinear points p, q, r, the function checks if 
    point q lies on line segment "pr"
    '''
    if (q[0] <= max(p[0], r[0]) and q[0] >= min(p[0], r[0]) and
        q[1] <= max(p[1], r[1]) and q[1] >= min(p[1], r[1])):
        return True
    return False

def orientation(p, q, r):
    '''Find orientation of ordered triplet (p, q, r).
    The function returns following values
    0 --> p, q and r are colinear
    1 --> Clockwise
    2 --> Counterclockwise
    '''

    val = ((q[1] - p[1]) * (r[0] - q[0]) - 
            (q[0] - p[0]) * (r[1] - q[1]))
    if val == 0:
        return 0  # colinear
    elif val > 0:
        return 1   # clockwise
    else:
        return 2  # counter-clockwise

def do_intersect(p1, q1, p2, q2):
    '''Main function to check whether the closed line segments p1 - q1 and p2 
       - q2 intersect'''
    o1 = orientation(p1, q1, p2)
    o2 = orientation(p1, q1, q2)
    o3 = orientation(p2, q2, p1)
    o4 = orientation(p2, q2, q1)

    # General case
    if (o1 != o2 and o3 != o4):
        return True

    # Special Cases
    # p1, q1 and p2 are colinear and p2 lies on segment p1q1
    if (o1 == 0 and on_segment(p1, p2, q1)):
        return True

    # p1, q1 and p2 are colinear and q2 lies on segment p1q1
    if (o2 == 0 and on_segment(p1, q2, q1)):
        return True

    # p2, q2 and p1 are colinear and p1 lies on segment p2q2
    if (o3 == 0 and on_segment(p2, p1, q2)):
        return True

    # p2, q2 and q1 are colinear and q1 lies on segment p2q2
    if (o4 == 0 and on_segment(p2, q1, q2)):
        return True

    return False # Doesn't fall in any of the above cases

Unten finden Sie eine Testfunktion, um zu überprüfen, ob sie funktioniert.

import matplotlib.pyplot as plt

def test_intersect_func():
    p1 = (1, 1)
    q1 = (10, 1)
    p2 = (1, 2)
    q2 = (10, 2)
    fig, ax = plt.subplots()
    ax.plot([p1[0], q1[0]], [p1[1], q1[1]], 'x-')
    ax.plot([p2[0], q2[0]], [p2[1], q2[1]], 'x-')
    print(do_intersect(p1, q1, p2, q2))

    p1 = (10, 0)
    q1 = (0, 10)
    p2 = (0, 0)
    q2 = (10, 10)
    fig, ax = plt.subplots()
    ax.plot([p1[0], q1[0]], [p1[1], q1[1]], 'x-')
    ax.plot([p2[0], q2[0]], [p2[1], q2[1]], 'x-')
    print(do_intersect(p1, q1, p2, q2))

    p1 = (-5, -5)
    q1 = (0, 0)
    p2 = (1, 1)
    q2 = (10, 10)
    fig, ax = plt.subplots()
    ax.plot([p1[0], q1[0]], [p1[1], q1[1]], 'x-')
    ax.plot([p2[0], q2[0]], [p2[1], q2[1]], 'x-')
    print(do_intersect(p1, q1, p2, q2))

    p1 = (0, 0)
    q1 = (1, 1)
    p2 = (1, 1)
    q2 = (10, 10)
    fig, ax = plt.subplots()
    ax.plot([p1[0], q1[0]], [p1[1], q1[1]], 'x-')
    ax.plot([p2[0], q2[0]], [p2[1], q2[1]], 'x-')
    print(do_intersect(p1, q1, p2, q2))
Fabian Ying
quelle
1
closed_segment_intersect()aus dem Testcode ist nicht definiert.
Hhquark
1
@hhquark Danke. Ich habe diese Zeilen jetzt entfernt. Ich habe diese Zeilen beim Testen eingefügt , um zu überprüfen, ob meine Implementierung mit der Implementierung aus einer anderen Antwort übereinstimmt ( stackoverflow.com/a/18524383/7474256 , glaube ich).
Fabian Ying
1

Bestimmen Sie für die Segmente AB und CD die Steigung von CD

slope=(Dy-Cy)/(Dx-Cx)

Ziehen Sie die CD über A und B und nehmen Sie den Abstand zur CD, der gerade nach oben geht

dist1=slope*(Cx-Ax)+Ay-Cy
dist2=slope*(Dx-Ax)+Ay-Dy

Überprüfen Sie, ob sie sich auf gegenüberliegenden Seiten befinden

return dist1*dist2<0
Anonym
quelle
Sind Sie sicher über die Formeln? Da die Koordinaten von B nicht verwendet werden, wie können Sie den Schnittpunkt von AB und CD finden, ohne alle 4 Eckpunkte zu berücksichtigen?
Mac13k
1
Ich denke, es sollte geben: dist2 = Steigung * (Dx-Bx) + By-Dy
mac13k
1

Da Sie nicht erwähnen, dass Sie den Schnittpunkt der Linie finden möchten, ist das Problem einfacher zu lösen. Wenn Sie den Schnittpunkt benötigen, ist die Antwort von OMG_peanuts ein schnellerer Ansatz. Wenn Sie jedoch nur herausfinden möchten, ob sich die Linien schneiden oder nicht, können Sie dies mithilfe der Liniengleichung (ax + by + c = 0) tun. Der Ansatz ist wie folgt:

  1. Beginnen wir mit zwei Liniensegmenten: Segment 1 und Segment 2.

    segment1 = [[x1,y1], [x2,y2]]
    segment2 = [[x3,y3], [x4,y4]]
    
  2. Überprüfen Sie, ob die beiden Liniensegmente Linien ungleich Null und unterschiedliche Segmente sind.

  3. Ab diesem Zeitpunkt gehe ich davon aus, dass die beiden Segmente ungleich Null sind und sich unterscheiden. Berechnen Sie für jedes Liniensegment die Steigung der Linie und erhalten Sie dann die Gleichung einer Linie in Form von ax + by + c = 0. Berechnen Sie nun den Wert von f = ax + by + c für die beiden Punkte der anderes Liniensegment (wiederholen Sie dies auch für das andere Liniensegment).

    a2 = (y3-y4)/(x3-x4);
    b1 = -1;
    b2 = -1;
    c1 = y1 - a1*x1;
    c2 = y3 - a2*x3;
    // using the sign function from numpy
    f1_1 = sign(a1*x3 + b1*y3 + c1);
    f1_2 = sign(a1*x4 + b1*y4 + c1);
    f2_1 = sign(a2*x1 + b2*y1 + c2);
    f2_2 = sign(a2*x2 + b2*y2 + c2);
    
  4. Jetzt bleiben nur noch die verschiedenen Fälle. Wenn für einen Punkt f = 0 ist, berühren sich die beiden Linien an einem Punkt. Wenn f1_1 und f1_2 gleich sind oder f2_1 und f2_2 gleich sind, schneiden sich die Linien nicht. Wenn f1_1 und f1_2 ungleich sind und f2_1 und f2_2 ungleich sind, schneiden sich die Liniensegmente. Je nachdem, ob Sie die Linien, die sich berühren, als "schneidend" betrachten möchten oder nicht, können Sie Ihre Bedingungen anpassen.

achyuthan_jr
quelle
Dieser Code wird nicht berechnet a1und funktioniert nicht für orthogonale Linien.
Björn Lindqvist
1

Wir können dies auch unter Verwendung von Vektoren lösen.

Definieren wir die Segmente als [start, end]. Bei zwei solchen Segmenten [A, B]und einer [C, D]Länge ungleich Null können wir einen der Endpunkte auswählen, der als Referenzpunkt verwendet werden soll, sodass wir drei Vektoren erhalten:

x = 0
y = 1
p = A-C = [C[x]-A[x], C[y]-A[y]]
q = B-A = [B[x]-A[x], B[y]-A[y]]
r = D-C = [D[x]-C[x], D[y]-C[y]]

Von dort aus können wir nach einem Schnittpunkt suchen, indem wir t und u in berechnen p + t*r = u*q. Nachdem wir ein wenig mit der Gleichung herumgespielt haben, erhalten wir:

t = (q[y]*p[x] - q[x]*p[y])/(q[x]*r[y] - q[y]*r[x])
u = (p[x] + t*r[x])/q[x]

Die Funktion lautet also:

def intersects(a, b):
    p = [b[0][0]-a[0][0], b[0][1]-a[0][1]]
    q = [a[1][0]-a[0][0], a[1][1]-a[0][1]]
    r = [b[1][0]-b[0][0], b[1][1]-b[0][1]]

    t = (q[1]*p[0] - q[0]*p[1])/(q[0]*r[1] - q[1]*r[0]) \
        if (q[0]*r[1] - q[1]*r[0]) != 0 \
        else (q[1]*p[0] - q[0]*p[1])
    u = (p[0] + t*r[0])/q[0] \
        if q[0] != 0 \
        else (p[1] + t*r[1])/q[1]

    return t >= 0 and t <= 1 and u >= 0 and u <= 1

quelle
1

Auf diese Weise überprüfe ich, ob eine Linie gekreuzt wurde und wo die Kreuzung auftritt. Verwenden wir x1 bis x4 und y1 bis y4

Segment1 = {(X1, Y1), (X2, Y2)}
Segment2 = {(X3, Y3), (X4, Y4)}

Dann brauchen wir einige Vektoren, um sie darzustellen

dx1 = X2 - X1
dx2 = X4 - X4
dy1 = Y2 - Y1
dy2 = Y4 - Y3

Nun betrachten wir die Determinante

det = dx1 * dy2 - dx2 * dy1

Wenn die Determinante 0,0 ist, sind die Liniensegmente parallel. Dies könnte bedeuten, dass sie sich überlappen. Wenn sie sich nur an Endpunkten überlappen, gibt es eine Schnittlösung. Andernfalls gibt es unendlich viele Lösungen. Was sagen Sie bei unendlich vielen Lösungen zu Ihrem Schnittpunkt? Es ist also ein interessanter Sonderfall. Wenn Sie im Voraus wissen, dass sich die Linien nicht überlappen können, können Sie einfach überprüfen, ob det == 0.0und wenn ja, einfach sagen, dass sie sich nicht schneiden und fertig sind. Ansonsten fahren wir fort

dx3 = X3 - X1
dy3 = Y3 - Y1

det1 = dx1 * dy3 - dx3 * dy1
det2 = dx2 * dy3 - dx3 * dy2

Wenn det, det1 und det2 alle Null sind, sind Ihre Linien kolinear und können sich überlappen. Wenn det Null ist, aber entweder det1 oder det2 nicht, dann sind sie nicht kolinear, sondern parallel, sodass es keinen Schnittpunkt gibt. Was jetzt übrig bleibt, wenn det Null ist, ist ein 1D-Problem anstelle von 2D. Wir müssen eine von zwei Möglichkeiten prüfen, je nachdem, ob dx1 Null ist oder nicht (damit wir die Division durch Null vermeiden können). Wenn dx1 Null ist, machen Sie einfach die gleiche Logik mit y-Werten und nicht mit x darunter.

s = X3 / dx1
t = X4 / dx1

Dies berechnet zwei Skalierer, so dass wir, wenn wir den Vektor (dx1, dy1) mit s skalieren, den Punkt (x3, y3) und mit t (x4, y4) erhalten. Wenn also entweder s oder t zwischen 0,0 und 1,0 liegt, liegt Punkt 3 oder 4 auf unserer ersten Linie. Negativ würde bedeuten, dass der Punkt hinter dem Anfang unseres Vektors liegt, während> 1,0 bedeutet, dass er weiter vor dem Ende unseres Vektors liegt. 0.0 bedeutet, dass es bei (x1, y1) ist und 1.0 bedeutet, dass es bei (x2, y2) ist. Wenn sowohl s als auch t <0,0 oder beide> 1,0 sind, schneiden sie sich nicht. Und das behandelt den Sonderfall der parallelen Linien.

Nun, wenn det != 0.0dann

s = det1 / det
t = det2 / det
if (s < 0.0 || s > 1.0 || t < 0.0 || t > 1.0)
    return false  // no intersect

Dies ähnelt dem, was wir oben wirklich gemacht haben. Wenn wir nun den obigen Test bestehen, schneiden sich unsere Liniensegmente und wir können den Schnitt ganz einfach so berechnen:

Ix = X1 + t * dx1
Iy = Y1 + t * dy1

Wenn Sie tiefer in die Mathematik eintauchen möchten, schauen Sie sich Cramers Regel an.

Jason Hoffoss
quelle
1
Tippfehler: "dx2 = X4 - X4" sollte "dx2 = X4 - X3" sein
Geowar
1

Die Antwort von Georgy ist bei weitem die sauberste. Musste dies verfolgen, da das Brycboe-Beispiel, obwohl es auch einfach ist, Probleme mit der Kolinearität hatte.

Code zum Testen:

#!/usr/bin/python
#
# Notes on intersection:
#
# https://bryceboe.com/2006/10/23/line-segment-intersection-algorithm/
#
# /programming/3838329/how-can-i-check-if-two-segments-intersect

from shapely.geometry import LineString

class Point:
    def __init__(self,x,y):
        self.x = x
        self.y = y

def ccw(A,B,C):
    return (C.y-A.y)*(B.x-A.x) > (B.y-A.y)*(C.x-A.x)

def intersect(A,B,C,D):
    return ccw(A,C,D) != ccw(B,C,D) and ccw(A,B,C) != ccw(A,B,D)


def ShapelyIntersect(A,B,C,D):
    return LineString([(A.x,A.y),(B.x,B.y)]).intersects(LineString([(C.x,C.y),(D.x,D.y)]))


a = Point(0,0)
b = Point(0,1)
c = Point(1,1)
d = Point(1,0)

'''
Test points:

b(0,1)   c(1,1)




a(0,0)   d(1,0)
'''

# F
print(intersect(a,b,c,d))

# T
print(intersect(a,c,b,d))
print(intersect(b,d,a,c))
print(intersect(d,b,a,c))

# F
print(intersect(a,d,b,c))

# same end point cases:
print("same end points")
# F - not intersected
print(intersect(a,b,a,d))
# T - This shows as intersected
print(intersect(b,a,a,d))
# F - this does not
print(intersect(b,a,d,a))
# F - this does not
print(intersect(a,b,d,a))

print("same end points, using shapely")
# T
print(ShapelyIntersect(a,b,a,d))
# T
print(ShapelyIntersect(b,a,a,d))
# T
print(ShapelyIntersect(b,a,d,a))
# T
print(ShapelyIntersect(a,b,d,a))
Asylumax
quelle
0

Wenn Ihre Daten eine Linie definieren, müssen Sie nur beweisen, dass sie nicht parallel sind. Dazu können Sie berechnen

alpha = float(y2 - y1) / (x2 - x1).

Wenn dieser Koeffizient für Linie1 und Linie2 gleich ist, bedeutet dies, dass die Linie parallel ist. Wenn nicht, bedeutet dies, dass sie sich schneiden.

Wenn sie parallel sind, müssen Sie beweisen, dass sie nicht gleich sind. Dafür rechnen Sie

beta = y1 - alpha*x1

Wenn Beta für Linie1 und Linie2 gleich ist, bedeutet dies, dass Sie die Linie schneiden, da sie gleich sind

Wenn es sich um Segmente handelt, müssen Sie für jede Zeile noch Alpha und Beta wie oben beschrieben berechnen. Dann müssen Sie überprüfen, ob (beta1 - beta2) / (alpha1 - alpha2) größer als Min (x1_line1, x2_line1) und kleiner als Max (x1_line1, x2_line1) ist.

PierrOz
quelle
0

Berechnen Sie den Schnittpunkt der Linien, die auf Ihren Segmenten liegen (dies bedeutet im Grunde, ein lineares Gleichungssystem zu lösen), und prüfen Sie dann, ob er zwischen dem Start- und dem Endpunkt Ihrer Segmente liegt.

kosii
quelle
0

Dies ist, was ich für AS3 habe, weiß nicht viel über Python, aber das Konzept ist da

    public function getIntersectingPointF($A:Point, $B:Point, $C:Point, $D:Point):Number {
        var A:Point = $A.clone();
        var B:Point = $B.clone();
        var C:Point = $C.clone();
        var D:Point = $D.clone();
        var f_ab:Number = (D.x - C.x) * (A.y - C.y) - (D.y - C.y) * (A.x - C.x);

        // are lines parallel
        if (f_ab == 0) { return Infinity };

        var f_cd:Number = (B.x - A.x) * (A.y - C.y) - (B.y - A.y) * (A.x - C.x);
        var f_d:Number = (D.y - C.y) * (B.x - A.x) - (D.x - C.x) * (B.y - A.y);
        var f1:Number = f_ab/f_d
        var f2:Number = f_cd / f_d
        if (f1 == Infinity || f1 <= 0 || f1 >= 1) { return Infinity };
        if (f2 == Infinity || f2 <= 0 || f2 >= 1) { return Infinity };
        return f1;
    }

    public function getIntersectingPoint($A:Point, $B:Point, $C:Point, $D:Point):Point
    {
        var f:Number = getIntersectingPointF($A, $B, $C, $D);
        if (f == Infinity || f <= 0 || f >= 1) { return null };

        var retPoint:Point = Point.interpolate($A, $B, 1 - f);
        return retPoint.clone();
    }
Daniel
quelle
0

In JAVA implementiert. Es scheint jedoch, dass es nicht für kolineare Linien funktioniert (auch bekannt als Liniensegmente, die ineinander existieren L1 (0,0) (10,10) L2 (1,1) (2,2)

public class TestCode
{

  public class Point
  {
    public double x = 0;
    public double y = 0;
    public Point(){}
  }

  public class Line
  {
    public Point p1, p2;
    public Line( double x1, double y1, double x2, double y2) 
    {
      p1 = new Point();
      p2 = new Point();
      p1.x = x1;
      p1.y = y1;
      p2.x = x2;
      p2.y = y2;
    }
  }

  //line segments
  private static Line s1;
  private static Line s2;

  public TestCode()
  {
    s1 = new Line(0,0,0,10);
    s2 = new Line(-1,0,0,10);
  }

  public TestCode(double x1, double y1, 
    double x2, double y2,
    double x3, double y3,
    double x4, double y4)
  {
    s1 = new Line(x1,y1, x2,y2);
    s2 = new Line(x3,y3, x4,y4);
  }

  public static void main(String args[])
  {
     TestCode code  = null;
////////////////////////////
     code = new TestCode(0,0,0,10,
                         0,1,0,5);
     if( intersect(code) )
     { System.out.println( "OK COLINEAR: INTERSECTS" ); }
     else
     { System.out.println( "ERROR COLINEAR: DO NOT INTERSECT" ); }
////////////////////////////
     code = new TestCode(0,0,0,10,
                         0,1,0,10);
     if( intersect(code) )
     { System.out.println( "OK COLINEAR: INTERSECTS" ); }
     else
     { System.out.println( "ERROR COLINEAR: DO NOT INTERSECT" ); }
////////////////////////////
     code = new TestCode(0,0,10,0,
                         5,0,15,0);
     if( intersect(code) )
     { System.out.println( "OK COLINEAR: INTERSECTS" ); }
     else
     { System.out.println( "ERROR COLINEAR: DO NOT INTERSECT" ); }
////////////////////////////
     code = new TestCode(0,0,10,0,
                         0,0,15,0);
     if( intersect(code) )
     { System.out.println( "OK COLINEAR: INTERSECTS" ); }
     else
     { System.out.println( "ERROR COLINEAR: DO NOT INTERSECT" ); }

////////////////////////////
     code = new TestCode(0,0,10,10,
                         1,1,5,5);
     if( intersect(code) )
     { System.out.println( "OK COLINEAR: INTERSECTS" ); }
     else
     { System.out.println( "ERROR COLINEAR: DO NOT INTERSECT" ); }
////////////////////////////
     code = new TestCode(0,0,0,10,
                         -1,-1,0,10);
     if( intersect(code) )
     { System.out.println( "OK SLOPE END: INTERSECTS" ); }
     else
     { System.out.println( "ERROR SLOPE END: DO NOT INTERSECT" ); }
////////////////////////////
     code = new TestCode(-10,-10,10,10,
                         -10,10,10,-10);
     if( intersect(code) )
     { System.out.println( "OK SLOPE Intersect(0,0): INTERSECTS" ); }
     else
     { System.out.println( "ERROR SLOPE Intersect(0,0): DO NOT INTERSECT" ); }
////////////////////////////
     code = new TestCode(-10,-10,10,10,
                         -3,-2,50,-2);
     if( intersect(code) )
     { System.out.println( "OK SLOPE Line2 VERTIAL: INTERSECTS" ); }
     else
     { System.out.println( "ERROR SLOPE Line2 VERTICAL: DO NOT INTERSECT" ); }
////////////////////////////
     code = new TestCode(-10,-10,10,10,
                         50,-2,-3,-2);
     if( intersect(code) )
     { System.out.println( "OK SLOPE Line2 (reversed) VERTIAL: INTERSECTS" ); }
     else
     { System.out.println( "ERROR SLOPE Line2 (reversed) VERTICAL: DO NOT INTERSECT" ); }
////////////////////////////
     code = new TestCode(0,0,0,10,
                         1,0,1,10);
     if( intersect(code) )
     { System.out.println( "ERROR PARALLEL VERTICAL: INTERSECTS" ); }
     else
     { System.out.println( "OK PARALLEL VERTICAL: DO NOT INTERSECT" ); }
////////////////////////////
     code = new TestCode(0,2,10,2,
                         0,10,10,10);
     if( intersect(code) )
     { System.out.println( "ERROR PARALLEL HORIZONTAL: INTERSECTS" ); }
     else
     { System.out.println( "OK PARALLEL HORIZONTAL: DO NOT INTERSECT" ); }
////////////////////////////
     code = new TestCode(0,10,5,13.75,
                         0,18.75,10,15);
     if( intersect(code) )
     { System.out.println( "ERROR PARALLEL SLOPE=.75: INTERSECTS" ); }
     else
     { System.out.println( "OK PARALLEL SLOPE=.75: DO NOT INTERSECT" ); }
////////////////////////////
     code = new TestCode(0,0,1,1,
                         2,-1,2,10);
     if( intersect(code) )
     { System.out.println( "ERROR SEPERATE SEGMENTS: INTERSECTS" ); }
     else
     { System.out.println( "OK SEPERATE SEGMENTS: DO NOT INTERSECT" ); }
////////////////////////////
     code = new TestCode(0,0,1,1,
                         -1,-10,-5,10);
     if( intersect(code) )
     { System.out.println( "ERROR SEPERATE SEGMENTS 2: INTERSECTS" ); }
     else
     { System.out.println( "OK SEPERATE SEGMENTS 2: DO NOT INTERSECT" ); }
  }

  public static boolean intersect( TestCode code )
  {
    return intersect( code.s1, code.s2);
  }

  public static boolean intersect( Line line1, Line line2 )
  {
    double i1min = Math.min(line1.p1.x, line1.p2.x);
    double i1max = Math.max(line1.p1.x, line1.p2.x);
    double i2min = Math.min(line2.p1.x, line2.p2.x);
    double i2max = Math.max(line2.p1.x, line2.p2.x);

    double iamax = Math.max(i1min, i2min);
    double iamin = Math.min(i1max, i2max);

    if( Math.max(line1.p1.x, line1.p2.x) < Math.min(line2.p1.x, line2.p2.x) )
      return false;

    double m1 = (line1.p2.y - line1.p1.y) / (line1.p2.x - line1.p1.x );
    double m2 = (line2.p2.y - line2.p1.y) / (line2.p2.x - line2.p1.x );

    if( m1 == m2 )
        return false;

    //b1 = line1[0][1] - m1 * line1[0][0]
    //b2 = line2[0][1] - m2 * line2[0][0]
    double b1 = line1.p1.y - m1 * line1.p1.x;
    double b2 = line2.p1.y - m2 * line2.p1.x;
    double x1 = (b2 - b1) / (m1 - m2);
    if( (x1 < Math.max(i1min, i2min)) || (x1 > Math.min(i1max, i2max)) )
        return false;
    return true;
  }
}

Die bisherige Ausgabe ist

ERROR COLINEAR: DO NOT INTERSECT
ERROR COLINEAR: DO NOT INTERSECT
ERROR COLINEAR: DO NOT INTERSECT
ERROR COLINEAR: DO NOT INTERSECT
ERROR COLINEAR: DO NOT INTERSECT
OK SLOPE END: INTERSECTS
OK SLOPE Intersect(0,0): INTERSECTS
OK SLOPE Line2 VERTIAL: INTERSECTS
OK SLOPE Line2 (reversed) VERTIAL: INTERSECTS
OK PARALLEL VERTICAL: DO NOT INTERSECT
OK PARALLEL HORIZONTAL: DO NOT INTERSECT
OK PARALLEL SLOPE=.75: DO NOT INTERSECT
OK SEPERATE SEGMENTS: DO NOT INTERSECT
OK SEPERATE SEGMENTS 2: DO NOT INTERSECT
Wanderer
quelle
0

Ich dachte, ich würde eine schöne Swift-Lösung beitragen:

struct Pt {
    var x: Double
    var y: Double
}

struct LineSegment {
    var p1: Pt
    var p2: Pt
}

func doLineSegmentsIntersect(ls1: LineSegment, ls2: LineSegment) -> Bool {

    if (ls1.p2.x-ls1.p1.x == 0) { //handle vertical segment1
        if (ls2.p2.x-ls2.p1.x == 0) {
            //both lines are vertical and parallel
            return false
        }

        let x = ls1.p1.x

        let slope2 = (ls2.p2.y-ls2.p1.y)/(ls2.p2.x-ls2.p1.x)
        let c2 = ls2.p1.y-slope2*ls2.p1.x

        let y = x*slope2+c2 // y intersection point

        return (y > ls1.p1.y && x < ls1.p2.y) || (y > ls1.p2.y && y < ls1.p1.y) // check if y is between y1,y2 in segment1
    }

    if (ls2.p2.x-ls2.p1.x == 0) { //handle vertical segment2

        let x = ls2.p1.x

        let slope1 = (ls1.p2.y-ls1.p1.y)/(ls1.p2.x-ls1.p1.x)
        let c1 = ls1.p1.y-slope1*ls1.p1.x

        let y = x*slope1+c1 // y intersection point

        return (y > ls2.p1.y && x < ls2.p2.y) || (y > ls2.p2.y && y < ls2.p1.y) // validate that y is between y1,y2 in segment2

    }

    let slope1 = (ls1.p2.y-ls1.p1.y)/(ls1.p2.x-ls1.p1.x)
    let slope2 = (ls2.p2.y-ls2.p1.y)/(ls2.p2.x-ls2.p1.x)

    if (slope1 == slope2) { //segments are parallel
        return false
    }

    let c1 = ls1.p1.y-slope1*ls1.p1.x
    let c2 = ls2.p1.y-slope2*ls2.p1.x

    let x = (c2-c1)/(slope1-slope2)

    return (((x > ls1.p1.x && x < ls1.p2.x) || (x > ls1.p2.x && x < ls1.p1.x)) &&
        ((x > ls2.p1.x && x < ls2.p2.x) || (x > ls2.p2.x && x < ls2.p1.x)))
    //validate that x is between x1,x2 in both segments

}
Matej Ukmar
quelle
0

Eine der oben genannten Lösungen hat so gut funktioniert, dass ich beschlossen habe, ein vollständiges Demonstrationsprogramm mit wxPython zu schreiben. Sie sollten dieses Programm folgendermaßen ausführen können: Python " Ihr Dateiname "

# Click on the window to draw a line.
# The program will tell you if this and the other line intersect.

import wx

class Point:
    def __init__(self, newX, newY):
        self.x = newX
        self.y = newY

app = wx.App()
frame = wx.Frame(None, wx.ID_ANY, "Main")
p1 = Point(90,200)
p2 = Point(150,80)
mp = Point(0,0) # mouse point
highestX = 0


def ccw(A,B,C):
    return (C.y-A.y) * (B.x-A.x) > (B.y-A.y) * (C.x-A.x)

# Return true if line segments AB and CD intersect
def intersect(A,B,C,D):
    return ccw(A,C,D) != ccw(B,C,D) and ccw(A,B,C) != ccw(A,B,D)

def is_intersection(p1, p2, p3, p4):
    return intersect(p1, p2, p3, p4)

def drawIntersection(pc):
    mp2 = Point(highestX, mp.y)
    if is_intersection(p1, p2, mp, mp2):
        pc.DrawText("intersection", 10, 10)
    else:
        pc.DrawText("no intersection", 10, 10)

def do_paint(evt):
    pc = wx.PaintDC(frame)
    pc.DrawLine(p1.x, p1.y, p2.x, p2.y)
    pc.DrawLine(mp.x, mp.y, highestX, mp.y)
    drawIntersection(pc)

def do_left_mouse(evt):
    global mp, highestX
    point = evt.GetPosition()
    mp = Point(point[0], point[1])
    highestX = frame.Size[0]
    frame.Refresh()

frame.Bind(wx.EVT_PAINT, do_paint)
frame.Bind(wx.EVT_LEFT_DOWN, do_left_mouse)
frame.Show()
app.MainLoop()
user1766438
quelle
0

Mit der OMG_Peanuts- Lösung habe ich in SQL übersetzt. (HANA-Skalarfunktion)

Danke OMG_Peanuts, es funktioniert großartig. Ich benutze runde Erde, aber die Entfernungen sind gering, also denke ich, dass es in Ordnung ist.

FUNCTION GA_INTERSECT" ( IN LAT_A1 DOUBLE,
         IN LONG_A1 DOUBLE,
         IN LAT_A2 DOUBLE,
         IN LONG_A2 DOUBLE,
         IN LAT_B1 DOUBLE,
         IN LONG_B1 DOUBLE,
         IN LAT_B2 DOUBLE,
         IN LONG_B2 DOUBLE) 
    
RETURNS RET_DOESINTERSECT DOUBLE
    LANGUAGE SQLSCRIPT
    SQL SECURITY INVOKER AS
BEGIN

    DECLARE MA DOUBLE;
    DECLARE MB DOUBLE;
    DECLARE BA DOUBLE;
    DECLARE BB DOUBLE;
    DECLARE XA DOUBLE;
    DECLARE MAX_MIN_X DOUBLE;
    DECLARE MIN_MAX_X DOUBLE;
    DECLARE DOESINTERSECT INTEGER;
    
    SELECT 1 INTO DOESINTERSECT FROM DUMMY;
    
    IF LAT_A2-LAT_A1 != 0 AND LAT_B2-LAT_B1 != 0 THEN
        SELECT (LONG_A2 - LONG_A1)/(LAT_A2 - LAT_A1) INTO MA FROM DUMMY; 
        SELECT (LONG_B2 - LONG_B1)/(LAT_B2 - LAT_B1) INTO MB FROM DUMMY;
        IF MA = MB THEN
            SELECT 0 INTO DOESINTERSECT FROM DUMMY;
        END IF;
    END IF;
    
    SELECT LONG_A1-MA*LAT_A1 INTO BA FROM DUMMY;
    SELECT LONG_B1-MB*LAT_B1 INTO BB FROM DUMMY;
    SELECT (BB - BA) / (MA - MB) INTO XA FROM DUMMY;
    
    -- Max of Mins
    IF LAT_A1 < LAT_A2 THEN         -- MIN(LAT_A1, LAT_A2) = LAT_A1
        IF LAT_B1 < LAT_B2 THEN        -- MIN(LAT_B1, LAT_B2) = LAT_B1
            IF LAT_A1 > LAT_B1 THEN       -- MAX(LAT_A1, LAT_B1) = LAT_A1
                SELECT LAT_A1 INTO MAX_MIN_X FROM DUMMY;
            ELSE                          -- MAX(LAT_A1, LAT_B1) = LAT_B1
                SELECT LAT_B1 INTO MAX_MIN_X FROM DUMMY;
            END IF;
        ELSEIF LAT_B2 < LAT_B1 THEN   -- MIN(LAT_B1, LAT_B2) = LAT_B2
            IF LAT_A1 > LAT_B2 THEN       -- MAX(LAT_A1, LAT_B2) = LAT_A1
                SELECT LAT_A1 INTO MAX_MIN_X FROM DUMMY;
            ELSE                          -- MAX(LAT_A1, LAT_B2) = LAT_B2
                SELECT LAT_B2 INTO MAX_MIN_X FROM DUMMY;
            END IF;
        END IF;
    ELSEIF LAT_A2 < LAT_A1 THEN     -- MIN(LAT_A1, LAT_A2) = LAT_A2
        IF LAT_B1 < LAT_B2 THEN        -- MIN(LAT_B1, LAT_B2) = LAT_B1
            IF LAT_A2 > LAT_B1 THEN       -- MAX(LAT_A2, LAT_B1) = LAT_A2
                SELECT LAT_A2 INTO MAX_MIN_X FROM DUMMY;
            ELSE                          -- MAX(LAT_A2, LAT_B1) = LAT_B1
                SELECT LAT_B1 INTO MAX_MIN_X FROM DUMMY;
            END IF;
        ELSEIF LAT_B2 < LAT_B1 THEN   -- MIN(LAT_B1, LAT_B2) = LAT_B2
            IF LAT_A2 > LAT_B2 THEN       -- MAX(LAT_A2, LAT_B2) = LAT_A2
                SELECT LAT_A2 INTO MAX_MIN_X FROM DUMMY;
            ELSE                          -- MAX(LAT_A2, LAT_B2) = LAT_B2
                SELECT LAT_B2 INTO MAX_MIN_X FROM DUMMY;
            END IF;
        END IF;
    END IF;
    
    -- Min of Max
    IF LAT_A1 > LAT_A2 THEN         -- MAX(LAT_A1, LAT_A2) = LAT_A1
        IF LAT_B1 > LAT_B2 THEN        -- MAX(LAT_B1, LAT_B2) = LAT_B1
            IF LAT_A1 < LAT_B1 THEN       -- MIN(LAT_A1, LAT_B1) = LAT_A1
                SELECT LAT_A1 INTO MIN_MAX_X FROM DUMMY;
            ELSE                          -- MIN(LAT_A1, LAT_B1) = LAT_B1
                SELECT LAT_B1 INTO MIN_MAX_X FROM DUMMY;
            END IF;
        ELSEIF LAT_B2 > LAT_B1 THEN   -- MAX(LAT_B1, LAT_B2) = LAT_B2
            IF LAT_A1 < LAT_B2 THEN       -- MIN(LAT_A1, LAT_B2) = LAT_A1
                SELECT LAT_A1 INTO MIN_MAX_X FROM DUMMY;
            ELSE                          -- MIN(LAT_A1, LAT_B2) = LAT_B2
                SELECT LAT_B2 INTO MIN_MAX_X FROM DUMMY;
            END IF;
        END IF;
    ELSEIF LAT_A2 > LAT_A1 THEN     -- MAX(LAT_A1, LAT_A2) = LAT_A2
        IF LAT_B1 > LAT_B2 THEN        -- MAX(LAT_B1, LAT_B2) = LAT_B1
            IF LAT_A2 < LAT_B1 THEN       -- MIN(LAT_A2, LAT_B1) = LAT_A2
                SELECT LAT_A2 INTO MIN_MAX_X FROM DUMMY;
            ELSE                          -- MIN(LAT_A2, LAT_B1) = LAT_B1
                SELECT LAT_B1 INTO MIN_MAX_X FROM DUMMY;
            END IF;
        ELSEIF LAT_B2 > LAT_B1 THEN   -- MAX(LAT_B1, LAT_B2) = LAT_B2
            IF LAT_A2 < LAT_B2 THEN       -- MIN(LAT_A2, LAT_B2) = LAT_A2
                SELECT LAT_A2 INTO MIN_MAX_X FROM DUMMY;
            ELSE                          -- MIN(LAT_A2, LAT_B2) = LAT_B2
                SELECT LAT_B2 INTO MIN_MAX_X FROM DUMMY;
            END IF;
        END IF;
    END IF;
        
    
    IF XA < MAX_MIN_X OR
       XA > MIN_MAX_X THEN  
       SELECT 0 INTO DOESINTERSECT FROM DUMMY;
    END IF;
    
    RET_DOESINTERSECT := :DOESINTERSECT;
END;
NY Reno
quelle
-2

Gelöst aber trotzdem warum nicht mit Python ... :)

def islineintersect(line1, line2):
    i1 = [min(line1[0][0], line1[1][0]), max(line1[0][0], line1[1][0])]
    i2 = [min(line2[0][0], line2[1][0]), max(line2[0][0], line2[1][0])]
    ia = [max(i1[0], i2[0]), min(i1[1], i2[1])]
    if max(line1[0][0], line1[1][0]) < min(line2[0][0], line2[1][0]):
        return False
    m1 = (line1[1][1] - line1[0][1]) * 1. / (line1[1][0] - line1[0][0]) * 1.
    m2 = (line2[1][1] - line2[0][1]) * 1. / (line2[1][0] - line2[0][0]) * 1.
    if m1 == m2:
        return False
    b1 = line1[0][1] - m1 * line1[0][0]
    b2 = line2[0][1] - m2 * line2[0][0]
    x1 = (b2 - b1) / (m1 - m2)
    if (x1 < max(i1[0], i2[0])) or (x1 > min(i1[1], i2[1])):
        return False
    return True

Dies:

print islineintersect([(15, 20), (100, 200)], [(210, 5), (23, 119)])

Ausgabe:

True

Und das:

print islineintersect([(15, 20), (100, 200)], [(-1, -5), (-5, -5)])

Ausgabe:

False
Liebe Sharma
quelle