Come posso verificare se due segmenti si intersecano?


Risposte:


64

L'equazione di una retta è:

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

Per un segmento, è esattamente lo stesso, tranne che x è incluso in un intervallo I.

Se hai due segmenti, definiti come segue:

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

L'abcisse Xa del potenziale punto di intersezione (Xa, Ya) deve essere contenuta sia nell'intervallo I1 che I2, definiti come segue:

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

E potremmo dire che Xa è incluso in:

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

Ora, dobbiamo verificare che questo intervallo Ia esista:

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

Quindi, abbiamo una formula a due righe e un intervallo reciproco. Le tue formule di linea sono:

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

Poiché abbiamo ottenuto due punti per segmento, siamo in grado di determinare A1, A2, b1 e b2:

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

Se i segmenti sono paralleli, allora A1 == A2:

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

Un punto (Xa, Ya) su entrambe le linee deve verificare entrambe le formule f1 e f2:

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

L'ultima cosa da fare è controllare che Xa sia incluso in Ia:

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

Oltre a questo, puoi verificare all'avvio che due dei quattro punti forniti non siano uguali per evitare tutti quei test.


1
Segmenti, sono segmenti, mi dispiace. Potresti aggiornare la tua risposta dati segmenti?
aneuryzm

13
Non è così complicato, ho scritto molti passaggi intermedi (non essenziali?) In uno scopo di comprensione. I punti principali degli attrezzi sono solo: controllare l'esistenza dell'intervallo reciproco, calcolare A1, A2, b1, b2 e Xa, quindi verificare che Xa sia incluso nell'intervallo reciproco. Questo è tutto :)
OMG_peanuts

3
A1 - A2 non sarà mai zero perché se (A1 == A2) sarebbe tornato prima di questo calcolo in quel caso.
inkredibl

3
se A1 == A2 e b1 == b2, i segmenti sono uno sopra l'altro e hanno infinite intersezioni
lynxoid

6
La formula A1 * x + b1 = y non gestisce le linee verticali, quindi i segmenti verticali dovrebbero essere gestiti separatamente con questo metodo.
dmitri

78

L'utente @ i_4_got punta a questa pagina con una soluzione molto efficiente in Python. Lo riproduco qui per comodità (dato che mi avrebbe reso felice averlo qui):

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)

8
Molto semplice ed elegante, ma non gestisce bene la colinearità, e quindi è necessario più codice a tale scopo.
charles

7
Per una soluzione che gestisce anche la collinearità, dai un'occhiata a geeksforgeeks.org/check-if-two-given-line-segments-intersect
Zsolt Safrany

Amo questa soluzione. Molto semplice e breve! Ho creato un programma wxPython che disegna una linea e vede se si interseca con un'altra linea. Non sono riuscito a posizionarlo qui, quindi è da qualche parte sotto questo commento.
user1766438

33

Non è necessario calcolare esattamente dove si intersecano i segmenti, ma solo capire se si intersecano affatto. Ciò semplificherà la soluzione.

L'idea è di trattare un segmento come "ancora" e separare il secondo segmento in 2 punti.
Ora dovrai trovare la posizione relativa di ogni punto rispetto al segmento "ancorato" (OnLeft, OnRight o Collinear).
Dopo averlo fatto per entrambi i punti, controlla che uno dei punti sia OnLeft e l'altro OnRight (o forse includi la posizione Collineare, se desideri includere anche incroci impropri ).

È quindi necessario ripetere il processo con i ruoli di ancoraggio e segmenti separati.

Esiste un'intersezione se, e solo se, uno dei punti è OnLeft e l'altro è OnRight. Vedi questo collegamento per una spiegazione più dettagliata con immagini di esempio per ogni possibile caso.

L'implementazione di tale metodo sarà molto più semplice che implementare effettivamente un metodo che trovi il punto di intersezione (dati i molti casi d'angolo che dovrai gestire anche tu).

Aggiornare

Le seguenti funzioni dovrebbero illustrare l'idea (fonte: Geometria computazionale in C ).
Nota: questo esempio presuppone l'utilizzo di numeri interi. Se invece stai usando una rappresentazione in virgola mobile (cosa che ovviamente potrebbe complicare le cose), dovresti determinare un valore epsilon per indicare "uguaglianza" (principalmente per la IsCollinearvalutazione).

Ovviamente, quando si usano queste funzioni, bisogna ricordarsi di controllare che ogni segmento si trovi "tra" l'altro segmento (poiché questi sono segmenti finiti e non linee infinite).

Inoltre, utilizzando queste funzioni puoi capire se hai un incrocio corretto o improprio .

  • Corretto : non ci sono punti collineari. I segmenti si incrociano "da un lato all'altro".
  • Non corretto : un segmento "tocca" solo l'altro (almeno uno dei punti è allineato al segmento ancorato).

+1 Praticamente anche una mia idea. Se pensi solo a dove sono i punti in relazione tra loro, puoi decidere se i loro segmenti devono intersecarsi o meno, senza calcolare nulla.
Jochen Ritzel

e @ THC4k Uhm, in realtà non è chiaro. Per esempio, controlla l'immagine che ho aggiunto alla domanda: i 2 punti sono "OnLeft" e "OnRight" ma i 2 segmenti non si intersecano.
aneuryzm

@ Patrick, in realtà no. A seconda di quale dei segmenti è l '"ancoraggio", entrambi i punti in questo caso sono OnLeft o OnRight. (Vedi la mia risposta aggiornata).
Liran

1
+1 Ho visto dozzine di risposte a questo problema, ma questa è di gran lunga la più chiara, la più semplice e la più efficiente che abbia mai visto. :)
Miguel

16

Supponiamo che i due segmenti abbiano i punti finali A, B e C, D. Il modo numericamente robusto per determinare l'intersezione è controllare il segno dei quattro determinanti:

| 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 |

Per l'intersezione, ogni determinante a sinistra deve avere il segno opposto di quello a destra, ma non è necessario che vi sia alcuna relazione tra le due linee. Fondamentalmente stai controllando ogni punto di un segmento rispetto all'altro segmento per assicurarti che si trovino sui lati opposti della linea definita dall'altro segmento.

Vedi qui: http://www.cs.cmu.edu/~quake/robust.html


funziona per le intersezioni improprie cioè quando il punto di intersezione si trova su un segmento di linea?
Sayam Qazi

@SayamQazi Sembra che l'intersezione fallisca se si supera il punto finale di un segmento di linea, almeno. Perché se sei sul segmento: presumo che sarebbe un confronto 0 vs 1 / -1, quindi non rileverebbe alcuna intersezione.
Warty

1
A proposito, per spiegare questo: ogni determinante sta calcolando il prodotto incrociato dei punti finali dei vettori di due segmenti di linea. Ad esempio, in alto a sinistra è CA x CB rispetto a DA x DB in alto a destra. Questo essenzialmente verifica su quale lato si trova un vertice (clockness). Sto ancora cercando di capire come funziona per segmenti di linea che non si estendono all'infinito.
Warty

8

Controllare se i segmenti di linea si intersecano è molto semplice con la libreria Shapely usando il intersectsmetodo:

from shapely.geometry import LineString

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

inserisci qui la descrizione dell'immagine

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

inserisci qui la descrizione dell'immagine


6

Sulla base delle eccellenti risposte di Liran e Grumdrig, ecco un codice Python completo per verificare se i segmenti chiusi si intersecano. Funziona per segmenti collineari, segmenti paralleli all'asse Y, segmenti degeneri (il diavolo è nei dettagli). Assume coordinate intere. Le coordinate in virgola mobile richiedono una modifica al test di uguaglianza dei punti.

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

Cosa significa esattamente "segmenti chiusi"?
Sam

Il segmento @Sam Closed contiene i suoi endpoint. Ad esempio, un segmento chiuso di punti da R sarebbe [0, 1] (0 <= x <= 1) invece di dire] 0, 1] (0 <x <= 1)
dmitri

6

Ecco una soluzione che utilizza prodotti dot:

# 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)

Ecco una visualizzazione in Desmos: Line Segment Intersection


È fantastico e mi sono dimenticato di Desmos: è perfetto per questo problema! Grazie!
ponadto

Ama il tuo soluzione, ma sembra come se fallisce se i due segmenti di linea sono in linea
H. Papa

Molto bella. Per chiunque altro lo trasferisca in una lingua diversa, assicurati di usare float o int64 poiché un int32 trabocca abbastanza rapidamente su numeri inferiori a 1280x720
quell'altro ragazzo

4

Hai due segmenti di linea. Definisci un segmento per i punti finali A e B e il secondo segmento per i punti finali C e D. C'è un bel trucco per mostrare che devono intersecarsi, ALL'INTERNO dei limiti dei segmenti. (Nota che le linee stesse possono intersecarsi oltre i limiti dei segmenti, quindi devi stare attento. Un buon codice controllerà anche le linee parallele.)

Il trucco sta nel verificare che i punti A e B devono essere allineati sui lati opposti della linea CD E che i punti C e D devono trovarsi sui lati opposti della linea AB.

Poiché si tratta di compiti a casa, non ti darò una soluzione esplicita. Ma un semplice test per vedere su quale lato di una linea cade un punto, è usare un prodotto a punti. Quindi, per una data linea CD, calcola il vettore normale di quella linea (lo chiamerò N_C.) Ora, prova semplicemente i segni di questi due risultati:

dot(A-C,N_C)

e

dot(B-C,N_C)

Se questi risultati hanno segni opposti, allora A e B sono lati opposti della linea CD. Ora fai lo stesso test per l'altra linea, AB. Ha il vettore normale N_A. Confronta i segni di

dot(C-A,N_A)

e

dot(D-A,N_A)

Lascio a te il compito di capire come calcolare un vettore normale. (In 2-d, questo è banale, ma il tuo codice si preoccuperà se A e B sono punti distinti? Allo stesso modo, C e D sono distinti?)

È ancora necessario preoccuparsi dei segmenti di linea che si trovano lungo la stessa linea infinita o se un punto cade effettivamente sull'altro segmento di linea stesso. Un buon codice soddisferà ogni possibile problema.


3

Ecco il codice C per verificare se due punti si trovano sui lati opposti del segmento di linea. Usando questo codice puoi controllare se anche due segmenti si intersecano.

// 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));

}


3

Ecco un altro codice Python per verificare se i segmenti chiusi si intersecano. È la versione riscritta del codice C ++ in http://www.cdn.geeksforgeeks.org/check-if-two-given-line-segments-intersect/ . Questa implementazione copre tutti i casi speciali (es. Tutti i punti colineari).

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

Di seguito è una funzione di test per verificare che funzioni.

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))

1
closed_segment_intersect()dal codice di prova non è definito.
hhquark

1
@hhquark Grazie. Ora ho rimosso queste righe. Ho incluso queste righe durante il test per verificare che la mia implementazione concordi con l'implementazione di un'altra risposta ( stackoverflow.com/a/18524383/7474256 , credo).
Fabian Ying

1

per i segmenti AB e CD, trova la pendenza di CD

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

estendi CD su A e B e prendi la distanza dal CD che va verso l'alto

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

controlla se sono su lati opposti

return dist1*dist2<0

1
Sei sicuro delle formule? Poiché le coordinate di B non vengono utilizzate, come puoi trovare l'intersezione di AB e CD senza considerare tutti e 4 i vertici?
mac13k

1
Penso che dovrebbe essere: dist2 = slope * (Dx-Bx) + By-Dy
mac13k

1

Poiché non dici che vuoi trovare il punto di intersezione della retta, il problema diventa più semplice da risolvere. Se hai bisogno del punto di intersezione, la risposta di OMG_peanuts è un approccio più veloce. Tuttavia, se vuoi solo scoprire se le linee si intersecano o meno, puoi farlo usando l'equazione della linea (ax + by + c = 0). L'approccio è il seguente:

  1. Cominciamo con due segmenti di linea: segmento 1 e segmento 2.

    segment1 = [[x1,y1], [x2,y2]]
    segment2 = [[x3,y3], [x4,y4]]
    
  2. Verificare se i due segmenti di linea sono una linea di lunghezza diversa da zero e segmenti distinti.

  3. Da qui in poi, presumo che i due segmenti siano di lunghezza diversa da zero e distinti. Per ogni segmento di linea, calcola la pendenza della linea e quindi ottieni l'equazione di una linea sotto forma di ax + by + c = 0. Ora, calcola il valore di f = ax + by + c per i due punti del altro segmento di linea (ripeti l'operazione anche per l'altro segmento di linea).

    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. Ora tutto ciò che resta sono i diversi casi. Se f = 0 per qualsiasi punto, le due linee si toccano in un punto. Se f1_1 e f1_2 sono uguali o f2_1 e f2_2 sono uguali, le linee non si intersecano. Se f1_1 e f1_2 sono disuguali e f2_1 e f2_2 sono disuguali, i segmenti di linea si intersecano. A seconda che tu voglia considerare le linee che si toccano come "intersecanti" o meno, puoi adattare le tue condizioni.


Questo codice non calcola a1e non funziona per le linee ortogonali.
Björn Lindqvist

1

Possiamo anche risolvere questo problema utilizzando i vettori.

Definiamo i segmenti come [start, end]. Dati due di questi segmenti [A, B]e [C, D]che entrambi hanno lunghezza diversa da zero, possiamo scegliere uno degli estremi da utilizzare come punto di riferimento in modo da ottenere tre vettori:

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]]

Da lì, possiamo cercare un'intersezione calcolando teu in p + t*r = u*q. Dopo aver giocato un po 'con l'equazione, otteniamo:

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]

Pertanto, la funzione è:

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

1

Questo è il mio modo di verificare l'attraversamento della linea e il punto in cui si verifica l'intersezione. Usiamo da x1 a x4 e da y1 a y4

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

Quindi abbiamo bisogno di alcuni vettori per rappresentarli

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

Ora guardiamo il determinante

det = dx1 * dy2 - dx2 * dy1

Se il determinante è 0,0, i segmenti di linea sono paralleli. Ciò potrebbe significare che si sovrappongono. Se si sovrappongono solo agli endpoint, esiste una soluzione di intersezione. Altrimenti ci saranno infinite soluzioni. Con infinite soluzioni, qual è il tuo punto di intersezione? Quindi è un caso speciale interessante. Se sai in anticipo che le linee non possono sovrapporsi, puoi semplicemente controllare se det == 0.0e se è così, dì semplicemente che non si intersecano e va fatto. Altrimenti, continuiamo

dx3 = X3 - X1
dy3 = Y3 - Y1

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

Ora, se det, det1 e det2 sono tutti zero, le tue linee sono co-lineari e potrebbero sovrapporsi. Se det è zero ma det1 o det2 non lo sono, allora non sono co-lineari, ma paralleli, quindi non c'è intersezione. Quindi quello che resta ora se det è zero è un problema 1D invece che 2D. Dovremo controllare uno dei due modi, a seconda che dx1 sia zero o meno (quindi possiamo evitare la divisione per zero). Se dx1 è zero, esegui la stessa logica con i valori y anziché x sotto.

s = X3 / dx1
t = X4 / dx1

Questo calcola due scaler, in modo tale che se scaliamo il vettore (dx1, dy1) per s otteniamo il punto (x3, y3) e per t otteniamo (x4, y4). Quindi, se s o t è compreso tra 0,0 e 1,0, il punto 3 o 4 si trova sulla nostra prima riga. Negativo significherebbe che il punto è dietro l'inizio del nostro vettore, mentre> 1.0 significa che è più avanti rispetto alla fine del nostro vettore. 0.0 significa che è a (x1, y1) e 1.0 significa che è a (x2, y2). Se sia s che t sono <0,0 o entrambi sono> 1,0, allora non si intersecano. E questo gestisce il caso speciale delle linee parallele.

Ora, se det != 0.0allora

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

Questo è simile a quello che stavamo facendo in realtà sopra. Ora, se superiamo il test sopra, i nostri segmenti di linea si intersecano e possiamo calcolare l'intersezione abbastanza facilmente in questo modo:

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

Se vuoi approfondire ciò che sta facendo la matematica, guarda nella regola di Cramer.


1
Errore di battitura: "dx2 = X4 - X4" dovrebbe essere "dx2 = X4 - X3"
geowar

1

La risposta di Georgy è di gran lunga la più pulita da attuare. Ho dovuto inseguire questo, dal momento che l'esempio di Brycboe, sebbene semplice, aveva problemi di colinearità.

Codice per il test:

#!/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))

0

se i tuoi dati definiscono la linea devi solo provare che non sono paralleli. Per fare questo puoi calcolare

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

Se questo coefficiente è uguale sia per Line1 che per Line2, significa che la linea è parallela. In caso contrario, significa che si intersecheranno.

Se sono paralleli, devi dimostrare che non sono la stessa cosa. Per questo, calcoli

beta = y1 - alpha*x1

Se beta è lo stesso per Line1 e Line2, significa che la linea si interseca in quanto sono uguali

Se sono segmenti, devi ancora calcolare alfa e beta come descritto sopra per ogni riga. Quindi devi controllare che (beta1 - beta2) / (alpha1 - alpha2) sia maggiore di Min (x1_line1, x2_line1) e minore di Max (x1_line1, x2_line1)


0

Calcola il punto di intersezione delle linee che si trovano sui tuoi segmenti (significa fondamentalmente risolvere un sistema di equazioni lineari), quindi controlla se si trova tra il punto iniziale e quello finale dei tuoi segmenti.


0

Questo è quello che ho per AS3, non so molto di Python ma il concetto è lì

    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();
    }

0

Implementato in JAVA. Tuttavia sembra che non funzioni per linee co-lineari (ovvero segmenti di linea che esistono l'uno nell'altro 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;
  }
}

L'output finora è

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

0

Ho pensato di contribuire con una bella soluzione Swift:

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

}

0

Una delle soluzioni sopra ha funzionato così bene che ho deciso di scrivere un programma dimostrativo completo utilizzando wxPython. Dovresti essere in grado di eseguire questo programma in questo modo: python " nome del tuo file "

# 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()

0

Utilizzando la soluzione OMG_Peanuts , ho tradotto in SQL. (Funzione scalare HANA)

Grazie OMG_Peanuts, funziona benissimo. Sto usando la terra rotonda, ma le distanze sono piccole, quindi immagino che vada bene.

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;

-2

Risolto ma ancora perché no con 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

Questo:

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

Produzione:

True

E questo:

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

Produzione:

False
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.