Comment puis-je vérifier si deux segments se croisent?

Réponses:

62

L'équation d'une ligne est:

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

Pour un segment, c'est exactement la même chose, sauf que x est inclus sur un intervalle I.

Si vous avez deux segments, définis comme suit:

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

L'abcisse Xa du point d'intersection potentiel (Xa, Ya) doit être contenue à la fois dans les intervalles I1 et I2, définis comme suit:

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

Et nous pourrions dire que Xa est inclus dans:

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

Maintenant, nous devons vérifier que cet intervalle Ia existe:

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

Donc, nous avons une formule à deux lignes et un intervalle mutuel. Vos formules de ligne sont:

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

Comme nous avons obtenu deux points par segment, nous sommes en mesure de déterminer A1, A2, b1 et 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

Si les segments sont parallèles, alors A1 == A2:

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

Un point (Xa, Ya) sur les deux lignes doit vérifier les deux formules f1 et 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

La dernière chose à faire est de vérifier que Xa est inclus dans 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

En plus de cela, vous pouvez vérifier au démarrage que deux des quatre points fournis ne sont pas égaux pour éviter tous ces tests.

OMG_peanuts
la source
1
Des segments, ce sont des segments, désolé. Pourriez-vous mettre à jour votre réponse en fonction des segments?
aneuryzm
13
Ce n'est pas si compliqué, j'ai écrit un tas d'étapes intermédiaires (non essentielles?) Dans un but de compréhension. Les principaux points à implémenter sont les suivants: Vérifier l'existence d'intervalle mutuel, calculer A1, A2, b1, b2 et Xa, puis vérifier que Xa est inclus dans l'intervalle mutuel. C'est tout :)
OMG_peanuts
2
A1 - A2 ne sera jamais nul car if (A1 == A2) serait retourné avant ce calcul dans ce cas.
inkredibl
3
si A1 == A2 et b1 == b2, les segments sont les uns sur les autres et ont une infinité d'intersections
lynxoïde
5
La formule A1 * x + b1 = y ne gère pas les lignes verticales, donc les segments verticaux doivent être traités séparément avec cette méthode.
dmitri
77

L'utilisateur @ i_4_got pointe vers cette page avec une solution très efficace en Python. Je le reproduis ici pour plus de commodité (car cela m'aurait fait plaisir de l'avoir ici):

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
la source
8
Très simple et élégant, mais il ne gère pas bien la colinéarité, et donc plus de code nécessaire à cette fin.
charles
7
Pour une solution qui gère également la colinéarité, consultez geeksforgeeks.org/check-if-two-given-line-segments-intersect
Zsolt Safrany
J'adore cette solution. Très simple et court! J'ai créé un programme wxPython qui trace une ligne et voit si elle croise une autre ligne. Je n'ai pas pu le placer ici, donc c'est quelque part en dessous de ce commentaire.
user1766438 le
32

Il n'est pas nécessaire de calculer exactement les segments se croisent, mais seulement de comprendre s'ils se croisent. Cela simplifiera la solution.

L'idée est de traiter un segment comme "l'ancre" et de séparer le deuxième segment en 2 points.
Maintenant, vous devrez trouver la position relative de chaque point par rapport au segment "ancré" (OnLeft, OnRight ou Collinear).
Après avoir fait cela pour les deux points, vérifiez que l'un des points est OnLeft et l'autre OnRight (ou peut-être inclure la position colinéaire, si vous souhaitez également inclure des intersections incorrectes ).

Vous devez ensuite répéter le processus avec les rôles d'ancre et de segments séparés.

Une intersection existe si, et seulement si, l'un des points est OnLeft et l'autre est OnRight. Voir ce lien pour une explication plus détaillée avec des images d'exemple pour chaque cas possible.

Implémenter une telle méthode sera beaucoup plus facile que d'implémenter réellement une méthode qui trouve le point d'intersection (étant donné les nombreux cas d'angle que vous devrez également gérer).

Mise à jour

Les fonctions suivantes devraient illustrer l'idée (source: Computational Geometry in C ).
Remarque: cet exemple suppose l'utilisation d'entiers. Si vous utilisez plutôt une représentation en virgule flottante (ce qui pourrait évidemment compliquer les choses), alors vous devriez déterminer une valeur epsilon pour indiquer "l'égalité" (principalement pour l' IsCollinearévaluation).

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

Bien entendu, lors de l'utilisation de ces fonctions, il faut se rappeler de vérifier que chaque segment se trouve "entre" l'autre segment (puisque ce sont des segments finis, et non des lignes infinies).

En outre, en utilisant ces fonctions, vous pouvez comprendre si vous avez un intersection correcte ou incorrecte .

  • Bon : il n'y a pas de points colinéaires. Les segments se croisent "d'un côté à l'autre".
  • Mauvais : un segment "touche" seulement l'autre (au moins un des points est colinéaire au segment ancré).
Liran
la source
+1 À peu près aussi mon idée. Si vous pensez simplement à l'emplacement des points les uns par rapport aux autres, vous pouvez décider si leurs segments doivent se croiser ou non, sans rien calculer.
Jochen Ritzel
et @ THC4k Uhm, ce n'est en fait pas clair. Par exemple, vérifiez l'image que j'ai ajoutée à la question: les 2 points sont "OnLeft" et "OnRight" mais les 2 segments ne se croisent pas.
aneuryzm
@Patrick, en fait non. Selon lequel des segments est "l'ancre", alors les deux points sont soit OnLeft soit OnRight dans ce cas. (Voir ma réponse mise à jour).
Liran
+1 J'ai vu des dizaines de réponses à ce problème, mais c'est de loin la plus claire, la plus simple et la plus efficace que j'ai vue. :)
Miguel
16

Supposons que les deux segments aient des extrémités A, B et C, D. La manière numériquement robuste de déterminer l'intersection est de vérifier le signe des quatre déterminants:

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

Pour l'intersection, chaque déterminant de gauche doit avoir le signe opposé de celui de droite, mais il n'y a pas besoin de relation entre les deux lignes. Vous vérifiez essentiellement chaque point d'un segment par rapport à l'autre segment pour vous assurer qu'ils se trouvent sur les côtés opposés de la ligne définie par l'autre segment.

Voir ici: http://www.cs.cmu.edu/~quake/robust.html

Victor Liu
la source
fonctionne-t-il pour les intersections incorrectes, c'est-à-dire lorsque le point d'intersection se trouve sur un segment de ligne?
Sayam Qazi
@SayamQazi Il semble que l'intersection échoue si vous passez au moins l'extrémité d'un segment de ligne. Car si vous êtes sur le segment: je suppose que ce serait une comparaison 0 vs 1 / -1, donc il ne détecterait aucune intersection.
Warty
1
D'ailleurs, pour expliquer ceci: chaque déterminant calcule le produit croisé des points d'extrémité des vecteurs de deux segments de ligne. Le coin supérieur gauche est CA x CB vs DA x DB en haut à droite, par exemple. Cela teste essentiellement de quel côté se trouve un sommet (horloge). J'essaie toujours de comprendre comment cela fonctionne pour les segments de ligne qui ne s'étendent pas indéfiniment.
Warty
7

Vérifier si les segments de ligne se croisent est très facile avec la bibliothèque Shapely en utilisant la intersectsméthode:

from shapely.geometry import LineString

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

entrez la description de l'image ici

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

entrez la description de l'image ici

Georgy
la source
6

Basé sur les excellentes réponses de Liran et Grumdrig, voici un code Python complet pour vérifier si les segments fermés se croisent. Fonctionne pour les segments colinéaires, les segments parallèles à l'axe Y, les segments dégénérés (le diable est dans les détails). Suppose des coordonnées entières. Les coordonnées à virgule flottante nécessitent une modification du test d'égalité des points.

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
la source
Que signifie exactement "segments fermés"?
Sam le
Le segment @Sam Closed contient ses extrémités. Par exemple, un segment fermé de points de R serait [0, 1] (0 <= x <= 1) par opposition à] 0, 1] (0 <x <= 1)
dmitri
5

Voici une solution utilisant des produits 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)

Voici une visualisation dans Desmos: Intersection de segment de ligne

BenMan95
la source
C'est génial, et j'ai oublié Desmos - c'est parfait pour ce problème! Merci!
ponadto
J'adore votre solution, mais il semble qu'elle échoue si les deux segments de ligne sont alignés
H. Pope
Très agréable. Pour quiconque porte ceci dans une autre langue, assurez-vous d'utiliser float ou int64 car un int32 débordera assez rapidement sur les nombres inférieurs à 1280x720
cet autre gars
4

Vous avez deux segments de ligne. Définissez un segment par les points d'extrémité A et B et le deuxième segment par les points d'extrémité C et D. Il y a une astuce intéressante pour montrer qu'ils doivent se croiser, DANS les limites des segments. (Notez que les lignes elles-mêmes peuvent se croiser au-delà des limites des segments, vous devez donc faire attention. Un bon code surveillera également les lignes parallèles.)

L'astuce consiste à tester que les points A et B doivent être alignés sur les côtés opposés de la ligne CD, ET que les points C et D doivent se trouver sur les côtés opposés de la ligne AB.

Puisque ce sont des devoirs, je ne vous donnerai pas de solution explicite. Mais un test simple pour voir de quel côté d'une ligne tombe un point consiste à utiliser un produit scalaire. Ainsi, pour une ligne CD donnée, calculez le vecteur normal de cette ligne (je l'appellerai N_C.) Maintenant, testez simplement les signes de ces deux résultats:

dot(A-C,N_C)

et

dot(B-C,N_C)

Si ces résultats ont des signes opposés, alors A et B sont des côtés opposés de la ligne CD. Faites maintenant le même test pour l'autre ligne, AB. Il a le vecteur normal N_A. Comparez les signes de

dot(C-A,N_A)

et

dot(D-A,N_A)

Je vous laisse le soin de déterminer comment calculer un vecteur normal. (En 2D, c'est trivial, mais votre code se souciera-t-il de savoir si A et B sont des points distincts? De même, C et D sont-ils distincts?)

Vous devez toujours vous soucier des segments de ligne qui se trouvent le long de la même ligne infinie, ou si un point tombe réellement sur l'autre segment de ligne lui-même. Un bon code répondra à tous les problèmes possibles.


la source
3

Voici le code C pour vérifier si deux points sont sur les côtés opposés du segment de ligne. En utilisant ce code, vous pouvez vérifier si deux segments se croisent également.

// 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
la source
3

Voici un autre code python pour vérifier si les segments fermés se croisent. Il s'agit de la version réécrite du code C ++ dans http://www.cdn.geeksforgeeks.org/check-if-two-given-line-segments-intersect/ . Cette implémentation couvre tous les cas particuliers (par exemple tous les points colinéaires).

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

Voici une fonction de test pour vérifier qu'elle fonctionne.

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
la source
1
closed_segment_intersect()à partir du code de test n'est pas défini.
hhquark
1
@hhquark Merci. J'ai maintenant supprimé ces lignes. J'ai inclus ces lignes lors des tests pour vérifier que mon implémentation est conforme à l'implémentation d'une autre réponse ( stackoverflow.com/a/18524383/7474256 , je pense).
Fabian Ying
1

pour les segments AB et CD, trouvez la pente de CD

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

étendre le CD sur A et B et prendre la distance jusqu'au CD en montant

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

vérifier s'ils sont sur les côtés opposés

return dist1*dist2<0
Anonyme
la source
Êtes-vous sûr des formules? Comme les coordonnées de B ne sont pas utilisées, comment pouvez-vous trouver l'intersection de AB et CD sans considérer les 4 sommets?
mac13k
1
Je pense qu'il devrait y avoir: dist2 = pente * (Dx-Bx) + By-Dy
mac13k
1

Puisque vous ne mentionnez pas que vous souhaitez trouver le point d'intersection de la ligne, le problème devient plus simple à résoudre. Si vous avez besoin du point d'intersection, la réponse OMG_peanuts est une approche plus rapide. Cependant, si vous souhaitez simplement savoir si les lignes se croisent ou non, vous pouvez le faire en utilisant l'équation de ligne (ax + by + c = 0). L'approche est la suivante:

  1. Commençons par deux segments de ligne: le segment 1 et le segment 2.

    segment1 = [[x1,y1], [x2,y2]]
    segment2 = [[x3,y3], [x4,y4]]
    
  2. Vérifiez si les deux segments de ligne sont des lignes de longueur différente de zéro et des segments distincts.

  3. À partir de là, je suppose que les deux segments sont de longueur non nulle et distincts. Pour chaque segment de droite, calculez la pente de la droite puis obtenez l'équation d'une droite sous la forme de ax + by + c = 0. Maintenant, calculez la valeur de f = ax + by + c pour les deux points du autre segment de ligne (répétez ceci également pour l'autre segment de ligne).

    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. Maintenant, il ne reste plus que les différents cas. Si f = 0 pour n'importe quel point, alors les deux lignes se touchent en un point. Si f1_1 et f1_2 sont égaux ou f2_1 et f2_2 sont égaux, alors les lignes ne se coupent pas. Si f1_1 et f1_2 sont inégaux et f2_1 et f2_2 sont inégaux, alors les segments de ligne se croisent. Selon que vous souhaitez considérer les lignes qui se touchent comme "se croisant" ou non, vous pouvez adapter vos conditions.

achyuthan_jr
la source
Ce code ne calcule pas a1et ne fonctionne pas pour les lignes orthogonales.
Björn Lindqvist
1

Nous pouvons également résoudre ce problème en utilisant des vecteurs.

Définissons les segments comme [start, end]. Étant donné deux de ces segments [A, B]et [C, D]que les deux ont une longueur non nulle, nous pouvons choisir l'un des points d'extrémité à utiliser comme point de référence afin d'obtenir trois vecteurs:

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

De là, nous pouvons rechercher une intersection en calculant t et u in p + t*r = u*q. Après avoir joué un peu avec l'équation, nous obtenons:

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]

Ainsi, la fonction est:

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

la source
1

C'est ma façon de vérifier le franchissement de ligne et où se produit l'intersection. Permet d'utiliser x1 à x4 et y1 à y4

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

Ensuite, nous avons besoin de quelques vecteurs pour les représenter

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

Maintenant, nous regardons le déterminant

det = dx1 * dy2 - dx2 * dy1

Si le déterminant est 0,0, les segments de ligne sont parallèles. Cela pourrait signifier qu'ils se chevauchent. S'ils se chevauchent uniquement aux extrémités, il existe une solution d'intersection. Sinon, il y aura des solutions infinies. Avec une infinité de solutions, que dites-vous de votre point d'intersection? C'est donc un cas spécial intéressant. Si vous savez à l'avance que les lignes ne peuvent pas se chevaucher, vous pouvez simplement vérifier si det == 0.0et si c'est le cas, dites simplement qu'elles ne se croisent pas et que c'est terminé. Sinon, continuons sur

dx3 = X3 - X1
dy3 = Y3 - Y1

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

Maintenant, si det, det1 et det2 sont tous nuls, alors vos lignes sont colinéaires et peuvent se chevaucher. Si det est nul mais que det1 ou det2 ne le sont pas, alors ils ne sont pas colinéaires, mais parallèles, il n'y a donc pas d'intersection. Donc, ce qui reste maintenant si det est zéro est un problème 1D au lieu de 2D. Nous devrons vérifier l'une des deux façons, selon que dx1 est égal à zéro ou non (nous pouvons donc éviter la division par zéro). Si dx1 est égal à zéro, faites simplement la même logique avec les valeurs y plutôt que x ci-dessous.

s = X3 / dx1
t = X4 / dx1

Cela calcule deux scalers, de sorte que si nous mettons à l'échelle le vecteur (dx1, dy1) par s, nous obtenons le point (x3, y3), et par t nous obtenons (x4, y4). Donc, si s ou t est compris entre 0,0 et 1,0, le point 3 ou 4 se trouve sur notre première ligne. Négatif signifierait que le point est derrière le début de notre vecteur, tandis que> 1.0 signifie qu'il est plus en avance sur la fin de notre vecteur. 0.0 signifie qu'il est à (x1, y1) et 1.0 signifie qu'il est à (x2, y2). Si s et t sont tous les deux <0,0 ou les deux sont> 1,0, ils ne se croisent pas. Et cela gère le cas particulier des lignes parallèles.

Maintenant, si det != 0.0alors

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

C'est vraiment similaire à ce que nous faisions ci-dessus. Maintenant, si nous réussissons le test ci-dessus, nos segments de ligne se croisent et nous pouvons calculer l'intersection assez facilement comme ceci:

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

Si vous voulez approfondir ce que font les mathématiques, examinez la règle de Cramer.

Jason Hoffoss
la source
1
Typo: "dx2 = X4 - X4" devrait être "dx2 = X4 - X3"
geowar
1

La réponse de Georgy est de loin la plus propre à mettre en œuvre. J'ai dû chasser cela, car l'exemple du brycboe, bien que simple également, avait des problèmes de colinéarité.

Code de 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))
asile
la source
0

si vos données définissent une ligne, il vous suffit de prouver qu'elles ne sont pas parallèles. Pour ce faire, vous pouvez calculer

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

Si ce coefficient est égal pour Line1 et Line2, cela signifie que la ligne est parallèle. Sinon, cela signifie qu'ils se croiseront.

S'ils sont parallèles, vous devez prouver qu'ils ne sont pas identiques. Pour cela, vous calculez

beta = y1 - alpha*x1

Si la version bêta est la même pour Line1 et Line2, cela signifie que votre ligne se coupe car elles sont égales

S'ils sont segment, vous devez toujours calculer alpha et bêta comme décrit ci-dessus pour chaque ligne. Ensuite, vous devez vérifier que (beta1 - beta2) / (alpha1 - alpha2) est supérieur à Min (x1_line1, x2_line1) et inférieur à Max (x1_line1, x2_line1)

PierrOz
la source
0

Calculez le point d'intersection des lignes posées sur vos segments (cela signifie essentiellement résoudre un système d'équations linéaires), puis vérifiez s'il se trouve entre les points de départ et d'arrivée de vos segments.

kosii
la source
0

C'est ce que j'ai pour AS3, je ne sais pas grand-chose sur python mais le concept 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
la source
0

Implémenté en JAVA. Cependant, il semble que cela ne fonctionne pas pour les lignes colinéaires (alias segments de ligne qui existent les uns dans les autres 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;
  }
}

Jusqu'à présent, la sortie est

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
Vagabond
la source
0

J'ai pensé apporter une belle solution 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
la source
0

L'une des solutions ci-dessus fonctionnait si bien que j'ai décidé d'écrire un programme de démonstration complet en utilisant wxPython. Vous devriez pouvoir exécuter ce programme comme ceci: python " votre nom de fichier "

# 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
la source
0

Utilisation d' OMG_Peanuts solution , j'ai traduit en SQL. (Fonction scalaire HANA)

Merci OMG_Peanuts, cela fonctionne très bien. J'utilise de la terre ronde, mais les distances sont petites, donc je pense que ça va.

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
la source
-2

Résolu mais toujours pourquoi pas avec 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

Ce:

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

Production:

True

Et ça:

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

Production:

False
Aime Sharma
la source