Como posso verificar se dois segmentos se cruzam?

93

Como posso verificar se 2 segmentos se cruzam?

Tenho os seguintes dados:

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

Preciso escrever um pequeno algoritmo em Python para detectar se as 2 linhas estão se cruzando.


texto alternativo

aneuryzm
fonte

Respostas:

64

A equação de uma linha é:

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

Para um segmento, é exatamente o mesmo, exceto que x está incluído em um intervalo I.

Se você tiver dois segmentos, definidos como segue:

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

O abcisse Xa do ponto potencial de interseção (Xa, Ya) deve estar contido em ambos os intervalos I1 e I2, definidos como segue:

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

E poderíamos dizer que Xa está incluído em:

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

Agora, precisamos verificar se este intervalo Ia existe:

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

Portanto, temos a fórmula de duas linhas e um intervalo mútuo. Suas fórmulas de linha são:

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

Como obtivemos dois pontos por segmento, podemos determinar 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 os segmentos forem paralelos, A1 == A2:

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

Um ponto (Xa, Ya) em ambas as linhas deve verificar ambas as fórmulas 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

A última coisa a fazer é verificar se Xa está incluído em 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

Além disso, você pode verificar na inicialização se dois dos quatro pontos fornecidos não são iguais para evitar todos os testes.

OMG_peanuts
fonte
1
Segmentos, são segmentos, desculpe. Você poderia atualizar sua resposta a determinados segmentos?
aneuryzm
13
Isso não é tão complicado, eu escrevi muitos passos intermediários (não essenciais?) Em um propósito de compreensão. Os principais pontos para implementos são apenas: Verifique a existência de intervalo mútuo, calcule A1, A2, b1, b2 e Xa e verifique se Xa está incluído no intervalo mútuo. Isso é tudo :)
OMG_peanuts
3
A1 - A2 nunca será zero porque se (A1 == A2) teria retornado antes deste cálculo nesse caso.
inkredibl de
3
se A1 == A2 e b1 == b2, os segmentos estão um em cima do outro e têm infinitas interseções
lincóide
6
A fórmula A1 * x + b1 = y não trata de linhas verticais, portanto, segmentos verticais devem ser tratados separadamente com este método.
dmitri
78

O usuário @ i_4_got aponta para esta página com uma solução muito eficiente em Python. Eu reproduzo aqui por conveniência (já que ficaria feliz em tê-lo aqui):

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
fonte
8
Muito simples e elegante, mas não lida bem com colinearidade e, portanto, mais código necessário para esse fim.
Charles
7
Para uma solução que também lida com colinearidade, confira geeksforgeeks.org/check-if-two-given-line-segments-intersect
Zsolt Safrany
Adoro esta solução. Muito simples e curto! Eu fiz um programa wxPython que desenha uma linha e vê se ela se cruza com outra linha. Não consegui colocá-lo aqui, por isso está em algum lugar abaixo deste comentário.
user1766438
33

Você não precisa calcular exatamente onde os segmentos se cruzam, mas apenas entender se eles se cruzam. Isso simplificará a solução.

A ideia é tratar um segmento como a "âncora" e separar o segundo segmento em 2 pontos.
Agora, você terá que encontrar a posição relativa de cada ponto ao segmento "ancorado" (OnLeft, OnRight ou Collinear).
Depois de fazer isso para ambos os pontos, verifique se um dos pontos está OnLeft e o outro está OnRight (ou talvez inclua a posição Collinear, se desejar incluir interseções inadequadas também).

Você deve então repetir o processo com as funções de âncora e segmentos separados.

Existe uma interseção se, e somente se, um dos pontos for OnLeft e o outro for OnRight. Veja este link para uma explicação mais detalhada com imagens de exemplo para cada caso possível.

Implementar tal método será muito mais fácil do que implementar um método que encontre o ponto de interseção (dados os muitos casos de canto que você também terá que lidar).

Atualizar

As funções a seguir devem ilustrar a ideia (fonte: Geometria Computacional em C ).
Observação: Este exemplo pressupõe o uso de inteiros. Se você estiver usando alguma representação de ponto flutuante (o que poderia obviamente complicar as coisas), então você deve determinar algum valor épsilon para indicar "igualdade" (principalmente para a IsCollinearavaliação).

Claro, ao usar essas funções, deve-se lembrar de verificar se cada segmento está "entre" o outro segmento (uma vez que esses são segmentos finitos, e não linhas infinitas).

Além disso, usando essas funções, você pode entender se tem um cruzamento adequado ou impróprio .

  • Própria : Não há pontos colineares. Os segmentos se cruzam "de lado a lado".
  • Impróprio : um segmento apenas "toca" o outro (pelo menos um dos pontos é colinear ao segmento ancorado).
Liran
fonte
1 Quase ideia minha também. Se você apenas pensar em onde os pontos estão em relação uns aos outros, você pode decidir se seus segmentos devem se cruzar ou não, sem calcular nada.
Jochen Ritzel
e @ THC4k Uhm, na verdade não está claro. Por exemplo, verifique a imagem que adicionei à pergunta: os 2 pontos são "OnLeft" e "OnRight", mas os 2 segmentos não estão se cruzando.
aneuryzm,
@Patrick, na verdade não. Dependendo de qual dos segmentos é a "âncora", os dois pontos são OnLeft ou OnRight neste caso. (Veja minha resposta atualizada).
Liran,
1
+1 Já vi dezenas de respostas para esse problema, mas essa é de longe a mais clara, mais simples e mais eficiente que já vi. :)
Miguel de
16

Suponha que os dois segmentos tenham pontos finais A, B e C, D. A maneira numericamente robusta de determinar a interseção é verificar o sinal dos quatro determinantes:

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

Para a interseção, cada determinante da esquerda deve ter o sinal oposto ao da direita, mas não precisa haver nenhuma relação entre as duas linhas. Basicamente, você verifica cada ponto de um segmento em relação ao outro segmento para ter certeza de que estão em lados opostos da linha definida pelo outro segmento.

Veja aqui: http://www.cs.cmu.edu/~quake/robust.html

Victor Liu
fonte
funciona para interseções impróprias, ou seja, quando o ponto de interseção está em um segmento de linha?
Sayam Qazi
@SayamQazi Parece falhar a interseção se você estiver passando pelo ponto final de um segmento de linha, pelo menos. Pois, se você estiver no segmento: Suponho que seria uma comparação 0 vs 1 / -1, portanto, não detectaria nenhuma interseção.
Warty de
1
A propósito, para explicar isso: cada determinante está computando o produto cruzado dos pontos finais dos vetores de dois segmentos de linha. A parte superior esquerda é CA x CB vs parte superior direita DA x DB, por exemplo. Isso testa essencialmente em que lado está o vértice (clockness). Ainda estou tentando descobrir como funciona para segmentos de linha que não se estendem infinitamente.
Warty
8

Verificar se os segmentos de linha se cruzam é ​​muito fácil com a biblioteca Shapely usando o intersectsmétodo:

from shapely.geometry import LineString

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

insira a descrição da imagem aqui

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

insira a descrição da imagem aqui

Georgiano
fonte
6

Com base nas excelentes respostas de Liran e Grumdrig, aqui está um código Python completo para verificar se segmentos fechados se cruzam. Funciona para segmentos colineares, segmentos paralelos ao eixo Y, segmentos degenerados (o diabo está nos detalhes). Assume coordenadas inteiras. As coordenadas de ponto flutuante requerem uma modificação no teste de igualdade de pontos.

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
Dimitri
fonte
O que significa exatamente "segmentos fechados"?
Sam
@Sam O segmento fechado contém seus pontos finais. Por exemplo, um segmento fechado de pontos de R seria [0, 1] (0 <= x <= 1) em oposição a dizer] 0, 1] (0 <x <= 1)
dmitri
6

Aqui está uma solução usando produtos escalares:

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

Aqui está uma visualização no Desmos: Intersecção de segmento de linha

BenMan95
fonte
Isso é incrível, e esqueci o Desmos - é perfeito para esse problema! Obrigado!
Ponadto de
Adorei sua solução, mas parece que ela falha se os dois segmentos de linha estiverem alinhados
H. Pope
Muito agradável. Para qualquer outro portando isso para um idioma diferente, certifique-se de usar float ou int64, pois um int32 irá transbordar rapidamente em números menores que 1280x720
aquele outro cara
4

Você tem dois segmentos de linha. Defina um segmento pelos pontos finais A e B e o segundo segmento pelos pontos finais C e D. Há um bom truque para mostrar que eles devem se cruzar, DENTRO dos limites dos segmentos. (Observe que as próprias linhas podem se cruzar além dos limites dos segmentos, então você deve ter cuidado. Um bom código também observará as linhas paralelas.)

O truque é testar se os pontos A e B devem se alinhar em lados opostos da linha CD, E se os pontos C e D devem estar em lados opostos da linha AB.

Já que isso é dever de casa, não vou dar uma solução explícita. Mas um teste simples para ver em que lado de uma linha um ponto cai é usar um produto escalar. Assim, para uma determinada linha CD, calcule o vetor normal para essa linha (vou chamá-lo de N_C.) Agora, simplesmente teste os sinais desses dois resultados:

dot(A-C,N_C)

e

dot(B-C,N_C)

Se esses resultados tiverem sinais opostos, A e B são lados opostos da linha CD. Agora faça o mesmo teste para a outra linha, AB. Possui vetor normal N_A. Compare os sinais de

dot(C-A,N_A)

e

dot(D-A,N_A)

Vou deixar para você descobrir como calcular um vetor normal. (Em 2-d, isso é trivial, mas seu código se preocupará se A e B são pontos distintos? Da mesma forma, C e D são distintos?)

Você ainda precisa se preocupar com os segmentos de linha que estão ao longo da mesma linha infinita ou se um ponto realmente cai no próprio segmento de linha. Um bom código atenderá a todos os problemas possíveis.


fonte
3

Aqui está o código C para verificar se dois pontos estão nos lados opostos do segmento de linha. Usando este código, você pode verificar se dois segmentos se cruzam também.

// 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
fonte
3

Aqui está outro código Python para verificar se os segmentos fechados se cruzam. É a versão reescrita do código C ++ em http://www.cdn.geeksforgeeks.org/check-if-two-given-line-segments-intersect/ . Esta implementação cobre todos os casos especiais (por exemplo, todos os pontos colineares).

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

Abaixo está uma função de teste para verificar se funciona.

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
fonte
1
closed_segment_intersect()do código de teste não está definido.
hhquark de
1
@hhquark Obrigado. Agora removi essas linhas. Incluí essas linhas durante o teste para verificar se minha implementação está de acordo com a implementação de outra resposta ( stackoverflow.com/a/18524383/7474256 , eu acho).
Fabian Ying
1

para os segmentos AB e CD, encontre a inclinação de CD

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

estenda o CD sobre A e B, e tome a distância até o CD subindo

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

verifique se eles estão em lados opostos

return dist1*dist2<0
Anônimo
fonte
1
Tem certeza sobre as fórmulas? Como as coordenadas de B não são usadas, como você pode encontrar a interseção de AB e CD sem considerar todos os 4 vértices?
mac13k
1
Acho que deveria haver: dist2 = declive * (Dx-Bx) + By-Dy
mac13k
1

Como você não mencionou que deseja encontrar o ponto de interseção da linha, o problema se torna mais simples de resolver. Se você precisa do ponto de interseção, a resposta OMG_peanuts é uma abordagem mais rápida. No entanto, se você deseja apenas descobrir se as linhas se cruzam ou não, você pode fazer isso usando a equação da linha (ax + by + c = 0). A abordagem é a seguinte:

  1. Vamos começar com dois segmentos de linha: segmento 1 e segmento 2.

    segment1 = [[x1,y1], [x2,y2]]
    segment2 = [[x3,y3], [x4,y4]]
    
  2. Verifique se os dois segmentos de linha são linhas de comprimento diferente de zero e segmentos distintos.

  3. Daqui em diante, presumo que os dois segmentos têm comprimento diferente de zero e são distintos. Para cada segmento de linha, calcule a inclinação da linha e, em seguida, obtenha a equação de uma linha na forma de ax + by + c = 0. Agora, calcule o valor de f = ax + by + c para os dois pontos do outro segmento de linha (repita isso para o outro segmento de linha também).

    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. Agora tudo o que resta são os diferentes casos. Se f = 0 para qualquer ponto, as duas linhas se tocam em um ponto. Se f1_1 e f1_2 forem iguais ou f2_1 e f2_2 forem iguais, então as linhas não se cruzam. Se f1_1 e f1_2 forem desiguais e f2_1 e f2_2 forem desiguais, os segmentos de linha se cruzam. Dependendo se você deseja considerar as linhas que se tocam como "intersecção" ou não, você pode adaptar suas condições.

achyuthan_jr
fonte
Este código não calcula a1e não funciona para linhas ortogonais.
Björn Lindqvist
1

Também podemos resolver isso utilizando vetores.

Vamos definir os segmentos como [start, end]. Dados dois desses segmentos [A, B]e [C, D]que ambos têm comprimento diferente de zero, podemos escolher um dos pontos finais a ser usado como ponto de referência para obtermos três vetores:

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

A partir daí, podemos procurar uma interseção calculando t e u em p + t*r = u*q. Depois de brincar um pouco com a equação, obtemos:

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]

Assim, a função é:

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

fonte
1

Esta é a minha maneira de verificar o cruzamento da linha e onde ocorre a interseção. Vamos usar x1 a x4 e y1 a y4

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

Então, precisamos de alguns vetores para representá-los

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

Agora olhamos para o determinante

det = dx1 * dy2 - dx2 * dy1

Se o determinante for 0,0, os segmentos de linha são paralelos. Isso pode significar que eles se sobrepõem. Se eles se sobrepõem apenas nos pontos finais, então há uma solução de interseção. Caso contrário, haverá soluções infinitas. Com infinitas soluções, qual é o seu ponto de intersecção? Portanto, é um caso especial interessante. Se você sabe com antecedência que as linhas não podem se sobrepor, você pode apenas verificar det == 0.0se sim, apenas dizer que elas não se cruzam e pronto. Caso contrário, vamos continuar

dx3 = X3 - X1
dy3 = Y3 - Y1

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

Agora, se det, det1 e det2 são todos zero, então suas linhas são colineares e podem se sobrepor. Se det for zero, mas det1 ou det2 não forem, eles não serão colineares, mas paralelos, portanto, não há interseção. Então, o que resta agora se det for zero é um problema 1D em vez de 2D. Precisaremos verificar uma de duas maneiras, dependendo se dx1 é zero ou não (para que possamos evitar a divisão por zero). Se dx1 for zero, faça a mesma lógica com os valores de y em vez de x abaixo.

s = X3 / dx1
t = X4 / dx1

Isso calcula dois escalonadores, de modo que, se escalarmos o vetor (dx1, dy1) em s, obteremos o ponto (x3, y3), e em t obteremos (x4, y4). Portanto, se s ou t estiver entre 0,0 e 1,0, o ponto 3 ou 4 estará em nossa primeira linha. Negativo significa que o ponto está atrás do início do nosso vetor, enquanto> 1.0 significa que está mais à frente do final do nosso vetor. 0,0 significa que está em (x1, y1) e 1,0 significa que está em (x2, y2). Se s e t forem <0,0 ou ambos forem> 1,0, eles não se cruzam. E isso trata do caso especial das linhas paralelas.

Agora se det != 0.0então

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

Isso é realmente semelhante ao que estávamos fazendo acima. Agora, se passarmos no teste acima, nossos segmentos de linha se cruzam e podemos calcular a interseção facilmente, assim:

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

Se você quiser se aprofundar no que a matemática está fazendo, dê uma olhada na Regra de Cramer.

Jason Hoffoss
fonte
1
Erro de digitação
1

A resposta de Georgy é a mais limpa de implementar, de longe. Tive que perseguir isso, já que o exemplo do brycboe, embora simples também, tinha problemas com colinearidade.

Código para teste:

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

se seus dados definem linha, você só precisa provar que eles não são paralelos. Para fazer isso, você pode calcular

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

Se este coeficiente for igual para Linha1 e Linha2, significa que as linhas são paralelas. Caso contrário, significa que eles se cruzarão.

Se eles forem paralelos, você terá que provar que não são iguais. Para isso, você calcula

beta = y1 - alpha*x1

Se beta é o mesmo para Linha1 e Linha2, significa que sua linha se cruza, pois são iguais

Se eles forem um segmento, você ainda terá que calcular alfa e beta conforme descrito acima para cada linha. Então você tem que verificar se (beta1 - beta2) / (alpha1 - alpha2) é maior que Min (x1_line1, x2_line1) e menor que Max (x1_line1, x2_line1)

PierrOz
fonte
0

Calcule o ponto de interseção das linhas que colocam em seus segmentos (significa basicamente resolver um sistema de equações lineares), depois verifique se está entre os pontos inicial e final de seus segmentos.

Kosii
fonte
0

Isso é o que eu tenho para AS3, não sei muito sobre python, mas o conceito está 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();
    }
Daniel
fonte
0

Implementado em JAVA. No entanto, parece que não funciona para linhas colineares (também conhecidas como segmentos de linha que existem entre si 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;
  }
}

A produção até agora é

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
Andarilho
fonte
0

Pensei em contribuir com uma boa solução 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

}
Matej Ukmar
fonte
0

Uma das soluções acima funcionou tão bem que decidi escrever um programa de demonstração completo usando wxPython. Você deve ser capaz de executar este programa assim: python " seu nome de arquivo "

# 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
fonte
0

Usando a solução OMG_Peanuts , traduzi para SQL. (Função escalar HANA)

Obrigado OMG_Peanuts, funciona muito bem. Estou usando a Terra redonda, mas as distâncias são pequenas, então acho que está tudo bem.

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

Resolvido, mas por que não com 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

Este:

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

Resultado:

True

E isto:

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

Resultado:

False
Amo sharma
fonte